… | |
… | |
250 | "spell_cause_rabies", /* 204 */ |
250 | "spell_cause_rabies", /* 204 */ |
251 | "spell_glyph", /* 205 */ |
251 | "spell_glyph", /* 205 */ |
252 | NULL |
252 | NULL |
253 | }; |
253 | }; |
254 | |
254 | |
255 | extern int arch_init; |
255 | extern bool loading_arch; |
256 | |
256 | |
257 | /* This function checks the object after it has been loaded (when we |
257 | /* This function checks the object after it has been loaded (when we |
258 | * get the 'end' in the input stream). This function can be used to |
258 | * get the 'end' in the input stream). This function can be used to |
259 | * deal with legacy objects where fields may have changed. It can also be used |
259 | * deal with legacy objects where fields may have changed. It can also be used |
260 | * to check for objects to make sure there are no common errors. |
260 | * to check for objects to make sure there are no common errors. |
… | |
… | |
289 | /* only do these when program is first run - a bit |
289 | /* only do these when program is first run - a bit |
290 | * excessive to do this at every run - most of this is |
290 | * excessive to do this at every run - most of this is |
291 | * really just to catch any errors - program will still run, but |
291 | * really just to catch any errors - program will still run, but |
292 | * not in the ideal fashion. |
292 | * not in the ideal fashion. |
293 | */ |
293 | */ |
294 | if ((op->type == WEAPON || op->type == BOW) && arch_init) |
294 | if ((op->type == WEAPON || op->type == BOW) && loading_arch) |
295 | { |
295 | { |
296 | if (!op->skill) |
296 | if (!op->skill) |
297 | LOG (llevError, "Weapon %s lacks a skill.\n", op->debug_desc ()); |
297 | LOG (llevError, "Weapon %s lacks a skill.\n", op->debug_desc ()); |
298 | else if ((!strcmp (op->skill, "one handed weapons") && op->body_info[1] != -1) || |
298 | else if ((!strcmp (op->skill, "one handed weapons") && op->body_info[1] != -1) || |
299 | (!strcmp (op->skill, "two handed weapons") && op->body_info[1] != -2)) |
299 | (!strcmp (op->skill, "two handed weapons") && op->body_info[1] != -2)) |
… | |
… | |
340 | } |
340 | } |
341 | |
341 | |
342 | /* Old spellcasting object - need to load in the appropiate object */ |
342 | /* Old spellcasting object - need to load in the appropiate object */ |
343 | if ((op->type == ROD || op->type == WAND || op->type == SCROLL || op->type == HORN || op->type == FIREWALL || |
343 | if ((op->type == ROD || op->type == WAND || op->type == SCROLL || op->type == HORN || op->type == FIREWALL || |
344 | /* POTIONS and ALTARS don't always cast spells, but if they do, update them */ |
344 | /* POTIONS and ALTARS don't always cast spells, but if they do, update them */ |
345 | ((op->type == POTION || op->type == ALTAR) && op->stats.sp)) && !op->inv && !arch_init) |
345 | ((op->type == POTION || op->type == ALTAR) && op->stats.sp)) && !op->inv && !loading_arch) |
346 | { |
346 | { |
347 | /* Fireall is bizarre in that spell type was stored in dam. Rest are 'normal' |
347 | /* Fireall is bizarre in that spell type was stored in dam. Rest are 'normal' |
348 | * in that spell was stored in sp. |
348 | * in that spell was stored in sp. |
349 | */ |
349 | */ |
350 | object *tmp = get_archetype (spell_mapping[op->type == FIREWALL ? op->stats.dam : op->stats.sp]); |
350 | object *tmp = get_archetype (spell_mapping[op->type == FIREWALL ? op->stats.dam : op->stats.sp]); |
351 | insert_ob_in_ob (tmp, op); |
351 | insert_ob_in_ob (tmp, op); |
352 | op->randomitems = NULL; /* So another spell isn't created for this object */ |
352 | op->randomitems = NULL; /* So another spell isn't created for this object */ |
353 | } |
353 | } |
354 | |
354 | |
355 | /* spellbooks & runes use slaying. But not to arch name, but to spell name */ |
355 | /* spellbooks & runes use slaying. But not to arch name, but to spell name */ |
356 | if ((op->type == SPELLBOOK || op->type == RUNE) && op->slaying && !op->inv && !arch_init) |
356 | if ((op->type == SPELLBOOK || op->type == RUNE) && op->slaying && !op->inv && !loading_arch) |
357 | { |
357 | { |
358 | object *tmp = get_archetype_by_object_name (op->slaying); |
358 | object *tmp = get_archetype_by_object_name (op->slaying); |
359 | insert_ob_in_ob (tmp, op); |
359 | insert_ob_in_ob (tmp, op); |
360 | op->randomitems = NULL; /* So another spell isn't created for this object */ |
360 | op->randomitems = NULL; /* So another spell isn't created for this object */ |
361 | /* without this, value is all screwed up */ |
361 | /* without this, value is all screwed up */ |
… | |
… | |
409 | |
409 | |
410 | static void |
410 | static void |
411 | set_move (MoveType &mt, const char *str) |
411 | set_move (MoveType &mt, const char *str) |
412 | { |
412 | { |
413 | static const struct flagstr { |
413 | static const struct flagstr { |
414 | char *name; |
414 | const char *name; |
415 | MoveType flags; |
415 | MoveType flags; |
416 | } move_flags[] = { |
416 | } move_flags[] = { |
417 | { "walk" , MOVE_WALK }, |
417 | { "walk" , MOVE_WALK }, |
418 | { "flying" , MOVE_FLY_LOW | MOVE_FLY_HIGH }, |
418 | { "flying" , MOVE_FLY_LOW | MOVE_FLY_HIGH }, |
419 | { "fly_low" , MOVE_FLY_LOW }, |
419 | { "fly_low" , MOVE_FLY_LOW }, |
420 | { "fly_high", MOVE_FLY_HIGH }, |
420 | { "fly_high", MOVE_FLY_HIGH }, |
421 | { "swim" , MOVE_SWIM }, |
421 | { "swim" , MOVE_SWIM }, |
422 | { "boat" , MOVE_BOAT }, |
422 | { "boat" , MOVE_BOAT }, |
|
|
423 | { "ship" , MOVE_SHIP }, |
423 | { "all" , MOVE_ALL }, |
424 | { "all" , MOVE_ALL }, |
424 | }; |
425 | }; |
425 | |
426 | |
426 | if (!str) |
427 | if (!str) |
427 | { |
428 | { |
… | |
… | |
473 | CLEAR_FLAG (op, flag) \ |
474 | CLEAR_FLAG (op, flag) \ |
474 | |
475 | |
475 | bool |
476 | bool |
476 | object::parse_kv (object_thawer &f) |
477 | object::parse_kv (object_thawer &f) |
477 | { |
478 | { |
478 | assert (f.kw == KW_object || f.kw == KW_arch); |
|
|
479 | |
|
|
480 | if (f.kw == KW_object) |
|
|
481 | f.get (name); // preset name from object name |
|
|
482 | |
|
|
483 | f.next (); |
|
|
484 | |
|
|
485 | object *op_inv = inv; |
479 | object *op_inv = inv; |
486 | |
480 | |
487 | for (;;) |
481 | for (;;) |
488 | { |
482 | { |
489 | switch (f.kw) |
483 | switch (f.kw) |
… | |
… | |
551 | } |
545 | } |
552 | } |
546 | } |
553 | continue; |
547 | continue; |
554 | |
548 | |
555 | case KW_other_arch: |
549 | case KW_other_arch: |
|
|
550 | other_arch = |
|
|
551 | loading_arch |
|
|
552 | ? archetype::get (f.get_str ()) |
556 | other_arch = archetype::find (f.get_str ()); |
553 | : archetype::find (f.get_str ()); |
|
|
554 | |
|
|
555 | if (!other_arch) |
|
|
556 | LOG (llevError, "%s uses unknown other_arch '%s'.\n", debug_desc (), f.get_str ()); |
557 | break; |
557 | break; |
558 | |
558 | |
559 | case KW_animation: |
559 | case KW_animation: |
560 | { |
560 | { |
561 | CLEAR_FLAG (this, FLAG_ANIMATE); |
561 | CLEAR_FLAG (this, FLAG_ANIMATE); |
… | |
… | |
833 | case KW_no_steal: GET_FLAG (this, FLAG_NO_STEAL); break; |
833 | case KW_no_steal: GET_FLAG (this, FLAG_NO_STEAL); break; |
834 | case KW_one_hit: GET_FLAG (this, FLAG_ONE_HIT); break; |
834 | case KW_one_hit: GET_FLAG (this, FLAG_ONE_HIT); break; |
835 | case KW_berserk: GET_FLAG (this, FLAG_BERSERK); break; |
835 | case KW_berserk: GET_FLAG (this, FLAG_BERSERK); break; |
836 | case KW_is_buildable: GET_FLAG (this, FLAG_IS_BUILDABLE); break; |
836 | case KW_is_buildable: GET_FLAG (this, FLAG_IS_BUILDABLE); break; |
837 | case KW_destroy_on_death: GET_FLAG (this, FLAG_DESTROY_ON_DEATH); break; |
837 | case KW_destroy_on_death: GET_FLAG (this, FLAG_DESTROY_ON_DEATH); break; |
|
|
838 | case KW_treasure_env: GET_FLAG (this, FLAG_TREASURE_ENV); break; |
|
|
839 | case KW_precious: GET_FLAG (this, FLAG_PRECIOUS); break; |
838 | |
840 | |
839 | case KW_armour: f.get (resist[ATNR_PHYSICAL]); break; |
841 | case KW_armour: f.get (resist[ATNR_PHYSICAL]); break; |
840 | case KW_resist_physical: f.get (resist[ATNR_PHYSICAL]); break; |
842 | case KW_resist_physical: f.get (resist[ATNR_PHYSICAL]); break; |
841 | case KW_resist_magic: f.get (resist[ATNR_MAGIC]); break; |
843 | case KW_resist_magic: f.get (resist[ATNR_MAGIC]); break; |
842 | case KW_resist_fire: f.get (resist[ATNR_FIRE]); break; |
844 | case KW_resist_fire: f.get (resist[ATNR_FIRE]); break; |
… | |
… | |
908 | case KW_connected: |
910 | case KW_connected: |
909 | add_button_link (this, map, f.get_sint32 ()); |
911 | add_button_link (this, map, f.get_sint32 ()); |
910 | break; |
912 | break; |
911 | |
913 | |
912 | case KW_randomitems: |
914 | case KW_randomitems: |
913 | randomitems = find_treasurelist (f.get_str ()); |
915 | if (f.get_str ()) |
|
|
916 | { |
|
|
917 | randomitems = |
|
|
918 | loading_arch |
|
|
919 | ? treasurelist::get (f.get_str ()) |
|
|
920 | : treasurelist::find (f.get_str ()); |
|
|
921 | |
914 | //if (!randomitems) |
922 | if (!randomitems) |
915 | // LOG (llevError, "%s uses unknown randomitems '%s'.\n", debug_desc (), f.get_str ()); |
923 | LOG (llevError, "%s uses unknown randomitems '%s'.\n", debug_desc (), f.get_str ()); |
|
|
924 | } |
916 | break; |
925 | break; |
917 | |
926 | |
918 | case KW_msg: |
927 | case KW_msg: |
919 | f.get_ml (KW_endmsg, msg); |
928 | f.get_ml (KW_endmsg, msg); |
920 | //TODO: allow longer messages |
929 | //TODO: allow longer messages |
… | |
… | |
941 | break; |
950 | break; |
942 | |
951 | |
943 | case KW_end: |
952 | case KW_end: |
944 | check_loaded_object (this); |
953 | check_loaded_object (this); |
945 | |
954 | |
946 | if (!arch_init) |
955 | if (!loading_arch) |
947 | instantiate (); |
956 | instantiate (); |
948 | |
957 | |
949 | f.next (); |
958 | f.next (); |
950 | return true; |
959 | return true; |
951 | |
960 | |
… | |
… | |
977 | arch = archetype::find ("earthwall"); |
986 | arch = archetype::find ("earthwall"); |
978 | } |
987 | } |
979 | |
988 | |
980 | assert (arch); //D maybe use exception handling of sorts? |
989 | assert (arch); //D maybe use exception handling of sorts? |
981 | |
990 | |
|
|
991 | f.next (); |
|
|
992 | |
982 | object *op = object::create (); |
993 | object *op = object::create (); |
983 | |
994 | |
984 | op->map = map; |
995 | op->map = map; |
985 | op->arch = arch; |
|
|
986 | arch->clone.copy_to (op); |
996 | arch->clone.copy_to (op); |
987 | // copy_to activates, this should be fixed properly |
997 | // copy_to activates, this should be fixed properly |
988 | op->deactivate (); |
998 | op->deactivate (); |
989 | |
999 | |
990 | if (!op->parse_kv (f)) |
1000 | if (!op->parse_kv (f)) |
991 | { |
1001 | { |
992 | delete op; |
1002 | op->destroy (true); |
993 | return 0; |
1003 | return 0; |
994 | } |
1004 | } |
995 | |
1005 | |
996 | return op; |
1006 | return op; |
997 | } |
1007 | } |
… | |
… | |
1005 | int |
1015 | int |
1006 | set_variable (object *op, char *buf) |
1016 | set_variable (object *op, char *buf) |
1007 | { |
1017 | { |
1008 | object_thawer f (buf, (AV *)0); |
1018 | object_thawer f (buf, (AV *)0); |
1009 | |
1019 | |
1010 | f.kw = KW_arch; // special hack so that parse_kv skips |
1020 | f.next (); |
1011 | return op->parse_kv (f); |
1021 | return op->parse_kv (f); |
1012 | } |
1022 | } |
1013 | |
1023 | |
1014 | /* This returns a string of the integer movement type */ |
1024 | /* This returns a string of the integer movement type */ |
1015 | #if 0 |
1025 | #if 0 |
… | |
… | |
1096 | KW_monster, |
1106 | KW_monster, |
1097 | KW_friendly, |
1107 | KW_friendly, |
1098 | KW_generator, |
1108 | KW_generator, |
1099 | KW_is_thrown, |
1109 | KW_is_thrown, |
1100 | KW_auto_apply, |
1110 | KW_auto_apply, |
1101 | KW_NULL, // was KW_treasure |
1111 | KW_treasure_env, |
1102 | KW_player_sold, |
1112 | KW_player_sold, |
1103 | /* 20 */ |
1113 | /* 20 */ |
1104 | KW_see_invisible, |
1114 | KW_see_invisible, |
1105 | KW_can_roll, |
1115 | KW_can_roll, |
1106 | KW_overlay_floor, |
1116 | KW_overlay_floor, |
… | |
… | |
1167 | KW_can_use_skill, |
1177 | KW_can_use_skill, |
1168 | KW_been_applied, |
1178 | KW_been_applied, |
1169 | /* 80 */ |
1179 | /* 80 */ |
1170 | KW_has_ready_scroll, |
1180 | KW_has_ready_scroll, |
1171 | KW_can_use_rod, |
1181 | KW_can_use_rod, |
1172 | KW_NULL, |
1182 | KW_precious, |
1173 | KW_can_use_horn, |
1183 | KW_can_use_horn, |
1174 | KW_make_invisible, |
1184 | KW_make_invisible, |
1175 | KW_inv_locked, |
1185 | KW_inv_locked, |
1176 | KW_is_wooded, |
1186 | KW_is_wooded, |
1177 | KW_is_hilly, |
1187 | KW_is_hilly, |
… | |
… | |
1243 | f.put (KW_msg, KW_endmsg, op->msg); |
1253 | f.put (KW_msg, KW_endmsg, op->msg); |
1244 | if (op->lore != tmp->lore) |
1254 | if (op->lore != tmp->lore) |
1245 | f.put (KW_lore, KW_endlore, op->lore); |
1255 | f.put (KW_lore, KW_endlore, op->lore); |
1246 | |
1256 | |
1247 | CMP_OUT (other_arch); |
1257 | CMP_OUT (other_arch); |
1248 | CMP_OUT (face); |
1258 | |
|
|
1259 | if (op->face != tmp->face) f.put (KW_face, op->face ? &faces [op->face] : 0); |
1249 | |
1260 | |
1250 | if (op->animation_id != tmp->animation_id) |
1261 | if (op->animation_id != tmp->animation_id) |
1251 | if (op->animation_id) |
1262 | if (op->animation_id) |
1252 | { |
1263 | { |
1253 | f.put (KW_animation, animations[GET_ANIM_ID (op)].name); |
1264 | f.put (KW_animation, animations[GET_ANIM_ID (op)].name); |
… | |
… | |
1386 | return true; |
1397 | return true; |
1387 | } |
1398 | } |
1388 | |
1399 | |
1389 | ///////////////////////////////////////////////////////////////////////////// |
1400 | ///////////////////////////////////////////////////////////////////////////// |
1390 | |
1401 | |
|
|
1402 | // generic resource file load, |
|
|
1403 | // currently supports: region, treasures, archetypes |
1391 | bool load_resource_file (const char *filename) |
1404 | bool load_resource_file (const char *filename) |
1392 | { |
1405 | { |
1393 | object_thawer f (filename); |
1406 | object_thawer f (filename); |
|
|
1407 | |
|
|
1408 | bool success = false; |
|
|
1409 | bool seen_arch = false; |
1394 | |
1410 | |
1395 | f.next (); |
1411 | f.next (); |
1396 | |
1412 | |
1397 | for (;;) |
1413 | for (;;) |
1398 | { |
1414 | { |
1399 | switch (f.kw) |
1415 | switch (f.kw) |
1400 | { |
1416 | { |
1401 | case KW_region: |
1417 | case KW_region: |
1402 | if (!region::read (f)) |
1418 | if (!region::read (f)) |
1403 | return false; |
1419 | goto finish; |
|
|
1420 | break; |
|
|
1421 | |
|
|
1422 | case KW_treasure: |
|
|
1423 | case KW_treasureone: |
|
|
1424 | if (!treasurelist::read (f)) |
|
|
1425 | goto finish; |
|
|
1426 | break; |
|
|
1427 | |
|
|
1428 | case KW_object: |
|
|
1429 | seen_arch = true; |
|
|
1430 | if (!archetype::read (f)) |
|
|
1431 | goto finish; |
1404 | break; |
1432 | break; |
1405 | |
1433 | |
1406 | case KW_EOF: |
1434 | case KW_EOF: |
1407 | return true; |
1435 | success = true; |
|
|
1436 | goto finish; |
1408 | |
1437 | |
1409 | default: |
1438 | default: |
1410 | if (!f.parse_error ("resource file")) |
1439 | if (!f.parse_error ("resource file")) |
1411 | return false; |
1440 | goto finish; |
1412 | } |
1441 | } |
1413 | |
|
|
1414 | f.next (); |
|
|
1415 | } |
1442 | } |
|
|
1443 | |
|
|
1444 | finish: |
|
|
1445 | if (seen_arch) |
|
|
1446 | init_archetype_pointers (); |
|
|
1447 | |
|
|
1448 | return success; |
1416 | } |
1449 | } |
1417 | |
1450 | |