ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/loader.C
Revision: 1.90
Committed: Sun Jul 1 05:00:17 2007 UTC (16 years, 11 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.89: +11 -12 lines
Log Message:
- upgrade crossfire trt to the GPL version 3 (hopefully correctly).
- add a single file covered by the GNU Affero General Public License
  (which is not yet released, so I used the current draft, which is
  legally a bit wavy, but its likely better than nothing as it expresses
  direct intent by the authors, and we can upgrade as soon as it has been
  released).
  * this should ensure availability of source code for the server at least
    and hopefully also archetypes and maps even when modified versions
    are not being distributed, in accordance of section 13 of the agplv3.

File Contents

# User Rev Content
1 root 1.1 /*
2 root 1.90 * This file is part of Crossfire TRT, the Roguelike Realtime MORPG.
3 pippijn 1.46 *
4 root 1.86 * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team
5     * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team
6     * Copyright (©) 1992,2007 Frank Tore Johansen
7 pippijn 1.46 *
8 root 1.90 * Crossfire TRT is free software: you can redistribute it and/or modify
9     * it under the terms of the GNU General Public License as published by
10     * the Free Software Foundation, either version 3 of the License, or
11     * (at your option) any later version.
12 pippijn 1.46 *
13 root 1.90 * This program is distributed in the hope that it will be useful,
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     * GNU General Public License for more details.
17 pippijn 1.46 *
18 root 1.90 * You should have received a copy of the GNU General Public License
19     * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 root 1.86 *
21     * The authors can be reached via e-mail to <crossfire@schmorp.de>
22 pippijn 1.46 */
23 root 1.1
24     /* Eneq(@csd.uu.se): Added weight-modifiers in environment of objects.
25     sub/add_weight will transcend the environment updating the carrying
26     variable. */
27    
28     #include <global.h>
29     #include <loader.h>
30     #include <sproto.h>
31    
32 root 1.52 /////////////////////////////////////////////////////////////////////////////
33 root 1.51
34 root 1.1 /* This table is only necessary to convert objects that existed before the
35     * spell object conversion to the new object. It was not practical
36     * to go through every mapping looking for every potion, rod, wand, etc
37     * that had a sp set and update to the new value. So this maps the
38     * old spell numbers to the name of the new archs.
39     * If you are adding a new spell, you should not modify this - you
40     * new spell won't have been used, and thus won't have any legacy object.
41     * NULL entries in this table are valid - to denote objects that should
42     * not be updated for whatever reason.
43     */
44     const char *spell_mapping[] = {
45 root 1.12 "spell_magic_bullet", /* 0 */
46     "spell_small_fireball", /* 1 */
47     "spell_medium_fireball", /* 2 */
48     "spell_large_fireball", /* 3 */
49     "spell_burning_hands", /* 4 */
50     "spell_sm_lightning", /* 5 */
51     "spell_large_lightning", /* 6 */
52     "spell_magic_missile", /* 7 */
53     "spell_create_bomb", /* 8 */
54     "spell_summon_golem", /* 9 */
55     "spell_summon_fire_elemental", /* 10 */
56     "spell_summon_earth_elemental", /* 11 */
57     "spell_summon_water_elemental", /* 12 */
58     "spell_summon_air_elemental", /* 13 */
59     "spell_dimension_door", /* 14 */
60     "spell_create_earth_wall", /* 15 */
61     "spell_paralyze", /* 16 */
62     "spell_icestorm", /* 17 */
63     "spell_magic_mapping", /* 18 */
64     "spell_turn_undead", /* 19 */
65     "spell_fear", /* 20 */
66     "spell_poison_cloud", /* 21 */
67     "spell_wonder", /* 22 */
68     "spell_destruction", /* 23 */
69     "spell_perceive_self", /* 24 */
70     "spell_word_of_recall", /* 25 */
71     "spell_invisible", /* 26 */
72     "spell_invisible_to_undead", /* 27 */
73     "spell_probe", /* 28 */
74     "spell_lg_magic_bullet", /* 29 */
75     "spell_improved_invisibility", /* 30 */
76     "spell_holy_word", /* 31 */
77     "spell_minor_healing", /* 32 */
78     "spell_medium_healing", /* 33 */
79     "spell_major_healing", /* 34 */
80     "spell_heal", /* 35 */
81     "spell_create_food", /* 36 */
82     "spell_earth_to_dust", /* 37 */
83     "spell_armour", /* 38 */
84     "spell_strength", /* 39 */
85     "spell_dexterity", /* 40 */
86     "spell_constitution", /* 41 */
87     "spell_charisma", /* 42 */
88     "spell_create_fire_wall", /* 43 */
89     "spell_create_frost_wall", /* 44 */
90     "spell_protection_from_cold", /* 45 */
91     "spell_protection_from_electricity", /* 46 */
92     "spell_protection_from_fire", /* 47 */
93     "spell_protection_from_poison", /* 48 */
94     "spell_protection_from_slow", /* 49 */
95     "spell_protection_from_paralysis", /* 50 */
96     "spell_protection_from_draining", /* 51 */
97     "spell_protection_from_magic", /* 52 */
98     "spell_protection_from_attack", /* 53 */
99     "spell_levitate", /* 54 */
100     "spell_small_speedball", /* 55 */
101     "spell_large_speedball", /* 56 */
102     "spell_hellfire", /* 57 */
103     "spell_dragonbreath", /* 58 */
104     "spell_large_icestorm", /* 59 */
105     "spell_charging", /* 60 */
106     "spell_polymorph", /* 61 */
107     "spell_cancellation", /* 62 */
108     "spell_confusion", /* 63 */
109     "spell_mass_confusion", /* 64 */
110     "spell_summon_pet_monster", /* 65 */
111     "spell_slow", /* 66 */
112     "spell_regenerate_spellpoints", /* 67 */
113     "spell_cure_poison", /* 68 */
114     "spell_protection_from_confusion", /* 69 */
115     "spell_protection_from_cancellation", /* 70 */
116     "spell_protection_from_depletion", /* 71 */
117     "spell_alchemy", /* 72 */
118     "spell_remove_curse", /* 73 */
119     "spell_remove_damnation", /* 74 */
120     "spell_identify", /* 75 */
121     "spell_detect_magic", /* 76 */
122     "spell_detect_monster", /* 77 */
123     "spell_detect_evil", /* 78 */
124     "spell_detect_curse", /* 79 */
125     "spell_heroism", /* 80 */
126     "spell_aggravation", /* 81 */
127     "spell_firebolt", /* 82 */
128     "spell_frostbolt", /* 83 */
129     "spell_shockwave", /* 84 */
130     "spell_color_spray", /* 85 */
131     "spell_haste", /* 86 */
132     "spell_face_of_death", /* 87 */
133     "spell_ball_lightning", /* 88 */
134     "spell_meteor_swarm", /* 89 */
135     "spell_comet", /* 90 */
136     "spell_mystic_fist", /* 91 */
137     "spell_raise_dead", /* 92 */
138     "spell_resurrection", /* 93 */
139     "spell_reincarnation", /* 94 */
140     "spell_immunity_to_cold", /* 95 */
141     "spell_immunity_to_electricity", /* 96 */
142     "spell_immunity_to_fire", /* 97 */
143     "spell_immunity_to_poison", /* 98 */
144     "spell_immunity_to_slow", /* 99 */
145     "spell_immunity_to_paralysis", /* 100 */
146     "spell_immunity_to_draining", /* 101 */
147     "spell_immunity_to_magic", /* 102 */
148     "spell_immunity_to_attack", /* 103 */
149     "spell_invulnerability", /* 104 */
150     "spell_defense", /* 105 */
151     "spell_rune_of_fire", /* 106 */
152     "spell_rune_of_frost", /* 107 */
153     "spell_rune_of_shocking", /* 108 */
154     "spell_rune_of_blasting", /* 109 */
155     "spell_rune_of_death", /* 110 */
156     "spell_marking_rune", /* 111 */
157     "spell_build_director", /* 112 */
158     "spell_create_pool_of_chaos", /* 113 */
159     "spell_build_bullet_wall", /* 114 */
160     "spell_build_lightning_wall", /* 115 */
161     "spell_build_fireball_wall", /* 116 */
162     "spell_magic_rune", /* 117 */
163     "spell_rune_of_magic_drain", /* 118 */
164     "spell_antimagic_rune", /* 119 */
165     "spell_rune_of_transference", /* 120 */
166     "spell_transference", /* 121 */
167     "spell_magic_drain", /* 122 */
168     "spell_counterspell", /* 123 */
169     "spell_disarm", /* 124 */
170     "spell_cure_confusion", /* 125 */
171     "spell_restoration", /* 126 */
172     "was summon evil monster", /* 127 *//* Not implenented as nothing used it */
173     "spell_counterwall", /* 128 */
174     "spell_cause_light_wounds", /* 129 */
175     "spell_cause_medium_wounds", /* 130 */
176     "spell_cause_heavy_wounds", /* 131 */
177     "spell_charm_monsters", /* 132 */
178     "spell_banishment", /* 133 */
179     "spell_create_missile", /* 134 */
180     "spell_show_invisible", /* 135 */
181     "spell_xray", /* 136 */
182     "spell_pacify", /* 137 */
183     "spell_summon_fog", /* 138 */
184     "spell_steambolt", /* 139 */
185     "spell_command_undead", /* 140 */
186     "spell_holy_orb", /* 141 */
187     "spell_summon_avatar", /* 142 */
188     "spell_holy_possession", /* 143 */
189     "spell_bless", /* 144 */
190     "spell_curse", /* 145 */
191     "spell_regeneration", /* 146 */
192     "spell_consecrate", /* 147 */
193     "spell_summon_cult_monsters", /* 148 */
194     "spell_cause_critical_wounds", /* 149 */
195     "spell_holy_wrath", /* 150 */
196     "spell_retributive_strike", /* 151 */
197     "spell_finger_of_death", /* 152 */
198     "spell_insect_plague", /* 153 */
199     "spell_call_holy_servant", /* 154 */
200     "spell_wall_of_thorns", /* 155 */
201     "spell_staff_to_snake", /* 156 */
202     "spell_light", /* 157 */
203     "spell_darkness", /* 158 */
204     "spell_nightfall", /* 159 */
205     "spell_daylight", /* 160 */
206     "spell_sunspear", /* 161 */
207     "spell_faery_fire", /* 162 */
208     "spell_cure_blindness", /* 163 */
209     "spell_dark_vision", /* 164 */
210     "spell_bullet_swarm", /* 165 */
211     "spell_bullet_storm", /* 166 */
212     "spell_cause_many_wounds", /* 167 */
213     "spell_small_snowstorm", /* 168 */
214     "spell_medium_snowstorm", /* 169 */
215     "spell_large_snowstorm", /* 170 */
216     "spell_cure_disease", /* 171 */
217     "spell_cause_red_death", /* 172 */
218     "spell_cause_flu", /* 173 */
219     "spell_cause_black_death", /* 174 */
220     "spell_cause_leprosy", /* 175 */
221     "spell_cause_smallpox", /* 176 */
222     "spell_cause_white_death", /* 177 */
223     "spell_cause_anthrax", /* 178 */
224     "spell_cause_typhoid", /* 179 */
225     "spell_mana_blast", /* 180 */
226     "spell_small_manaball", /* 181 */
227     "spell_medium_manaball", /* 182 */
228     "spell_large_manaball", /* 183 */
229     "spell_manabolt", /* 184 */
230     "spell_dancing_sword", /* 185 */
231     "spell_animate_weapon", /* 186 */
232     "spell_cause_cold", /* 187 */
233     "spell_divine_shock", /* 188 */
234     "spell_windstorm", /* 189 */
235     "spell_sanctuary", /* 190 */
236     "spell_peace", /* 191 */
237     "spell_spiderweb", /* 192 */
238     "spell_conflict", /* 193 */
239     "spell_rage", /* 194 */
240     "spell_forked_lightning", /* 195 */
241     "spell_poison_fog", /* 196 */
242     "spell_flaming_aura", /* 197 */
243     "spell_vitriol", /* 198 */
244     "spell_vitriol_splash", /* 199 */
245     "spell_iron_skin", /* 200 */
246     "spell_wrathful_eye", /* 201 */
247     "spell_town_portal", /* 202 */
248     "spell_missile_swarm", /* 203 */
249     "spell_cause_rabies", /* 204 */
250     "spell_glyph", /* 205 */
251     NULL
252 root 1.1 };
253    
254 root 1.68 extern bool loading_arch;
255 root 1.1
256     /* This function checks the object after it has been loaded (when we
257     * get the 'end' in the input stream). This function can be used to
258     * deal with legacy objects where fields may have changed. It can also be used
259     * to check for objects to make sure there are no common errors.
260     */
261 root 1.78 void
262     object::post_load_check ()
263 root 1.12 {
264 root 1.83 if (type >= NUM_TYPES)
265     {
266     LOG (llevError, "%s: type out of range, resetting to 0.\n", debug_desc ());
267     type = 0;
268     }
269    
270 root 1.78 switch (type)
271     {
272     case BOW:
273     case WAND:
274     case ROD:
275     case HORN:
276 root 1.79 if (slot [body_range].info != -1)
277 root 1.78 {
278 root 1.80 LOG (llevError, "%s: body_range %d != -1\n", debug_desc (), slot [body_range].info);
279 root 1.79 slot [body_range].info = -1;
280 root 1.78 }
281     break;
282    
283     case WEAPON:
284 root 1.79 if (slot [body_combat].info != -1)
285 root 1.78 {
286 root 1.80 LOG (llevError, "%s: body_combat %d != -1\n", debug_desc (), slot [body_combat].info);
287 root 1.79 slot [body_combat].info = -1;
288 root 1.78 }
289     break;
290    
291     case SHIELD:
292 root 1.79 if (slot [body_shield].info != -1)
293 root 1.78 {
294 root 1.80 LOG (llevError, "%s: body_shield %d != -1\n", debug_desc (), slot [body_shield].info);
295 root 1.79 slot [body_shield].info = -1;
296 root 1.78 }
297     break;
298    
299     case PLAYER:
300     if (slot [body_shield].info != 1)
301     {
302 root 1.80 LOG (llevError, "%s: body_shield %d != 1\n", debug_desc (), slot [body_shield].info);
303 root 1.78 slot [body_shield].info = 1;
304     }
305    
306     if (slot [body_combat].info != 1)
307     {
308 root 1.80 LOG (llevError, "%s: body_combat %d != 1\n", debug_desc (), slot [body_combat].info);
309 root 1.78 slot [body_combat].info = 1;
310     }
311 root 1.79
312     if (slot [body_range].info != 1)
313     {
314 root 1.80 LOG (llevError, "%s: body_range %d != 1\n", debug_desc (), slot [body_range].info);
315 root 1.79 slot [body_range].info = 1;
316     }
317 root 1.78 break;
318     }
319    
320 pippijn 1.38 /* We do some specialised handling to handle legacy cases of name_pl.
321 root 1.12 * If the object doesn't have a name_pl, we just use the object name -
322 pippijn 1.38 * this isn't perfect (things won't be properly pluralised), but works to
323 root 1.12 * that degree (5 heart is still quite understandable). But the case we
324     * also have to catch is if this object is not using the normal name for
325     * the object. In that case, we also want to use the loaded name.
326     * Otherwise, what happens is that the the plural name will lose
327     * information (appear as just 'hearts' and not 'goblins heart')
328     */
329 root 1.88 if (arch && name != arch->object::name && name_pl == arch->object::name_pl)
330 root 1.78 name_pl = 0;
331 root 1.1
332 root 1.78 if (!name_pl)
333     name_pl = name;
334 root 1.1
335 root 1.12 /* objects now have a materialname. try to patch it in */
336 root 1.78 if (!(is_weapon () && level > 0))
337 root 1.79 set_materialname (this, map ? map->difficulty : 5, 0);
338 root 1.57
339 root 1.12 /* only do these when program is first run - a bit
340     * excessive to do this at every run - most of this is
341     * really just to catch any errors - program will still run, but
342     * not in the ideal fashion.
343     */
344 root 1.78 if (loading_arch && (type == WEAPON || type == BOW || type == ROD || type == HORN || type == WAND))
345 root 1.12 {
346 root 1.78 if (!skill)
347     LOG (llevError, "Weapon %s lacks a skill.\n", debug_desc ());
348     else if ((!strcmp (skill, "one handed weapons") && slot[body_arm].info != -1) ||
349     (!strcmp (skill, "two handed weapons") && slot[body_arm].info != -2))
350     LOG (llevError, "weapon %s arm usage does not match skill: %d, %s\n", debug_desc (), slot[body_arm].info, &skill);
351 root 1.1 }
352    
353 root 1.12 /* We changed last_heal to gen_sp_armour, which is what it
354     * really does for many objects. Need to catch any in maps
355     * that may have an old value.
356     */
357 root 1.78 if (type == WEAPON
358     || type == ARMOUR || type == HELMET
359     || type == SHIELD || type == RING
360     || type == BOOTS || type == GLOVES
361     || type == AMULET || type == GIRDLE
362     || type == BRACERS || type == CLOAK)
363 root 1.12 {
364 root 1.78 if (last_heal)
365 root 1.12 {
366 root 1.78 LOG (llevDebug, "Object %s still has last_heal set, not gen_sp_armour\n", debug_desc ());
367     gen_sp_armour = last_heal;
368     last_heal = 0;
369 root 1.1 }
370 elmex 1.39
371 root 1.78 int ip = calc_item_power (this, 0);
372 root 1.57
373 root 1.12 /* Legacy objects from before item power was in the game */
374 root 1.78 if (!item_power && ip)
375 root 1.12 {
376     if (ip > 3)
377 root 1.78 LOG (llevDebug, "Object %s had no item power, using %d\n", debug_desc (), ip);
378 root 1.57
379 root 1.78 item_power = ip;
380 root 1.1 }
381 root 1.57
382 root 1.12 /* Check for possibly bogus values. Has to meet both these criteria -
383     * something that has item_power 1 is probably just fine if our calculated
384     * value is 1 or 2 - these values are small enough that hard to be precise.
385     * similarly, it item_power is 0, the first check will always pass,
386     * but not the second one.
387     */
388 root 1.84 #if 0 //TODO
389 root 1.78 if (ip > 2 * item_power && ip > (item_power + 3))
390     LOG (llevDebug, "Object %s seems to have too low item power? %d > %d\n", debug_desc (), ip, item_power);
391 root 1.84 #endif
392 root 1.57 }
393 root 1.1
394 root 1.12 /* Old spellcasting object - need to load in the appropiate object */
395 root 1.78 if ((type == ROD || type == WAND || type == SCROLL || type == HORN || type == FIREWALL ||
396 root 1.12 /* POTIONS and ALTARS don't always cast spells, but if they do, update them */
397 root 1.78 ((type == POTION || type == ALTAR) && stats.sp)) && !inv && !loading_arch)
398 root 1.12 {
399     /* Fireall is bizarre in that spell type was stored in dam. Rest are 'normal'
400     * in that spell was stored in sp.
401     */
402 root 1.78 object *tmp = get_archetype (spell_mapping[type == FIREWALL ? stats.dam : stats.sp]);
403     insert_ob_in_ob (tmp, this);
404     randomitems = NULL; /* So another spell isn't created for this object */
405 root 1.1 }
406 root 1.57
407 root 1.12 /* spellbooks & runes use slaying. But not to arch name, but to spell name */
408 root 1.78 if ((type == SPELLBOOK || type == RUNE) && slaying && !inv && !loading_arch)
409 root 1.12 {
410 root 1.78 object *tmp = get_archetype_by_object_name (slaying);
411     insert_ob_in_ob (tmp, this);
412     randomitems = NULL; /* So another spell isn't created for this object */
413 root 1.12 /* without this, value is all screwed up */
414 root 1.88 value = arch->value * inv->value;
415 root 1.1 }
416    
417 root 1.78 if (QUERY_FLAG (this, FLAG_MONSTER))
418 root 1.12 {
419 root 1.78 if (stats.hp > stats.maxhp)
420 root 1.49 {
421 root 1.78 LOG (llevDebug, "Monster %s has hp set higher than maxhp (%d>%d)\n", debug_desc (), stats.hp, stats.maxhp);
422     stats.maxhp = stats.hp;
423 root 1.49 }
424 root 1.1
425 root 1.12 /* The archs just need to be updated for this */
426 root 1.78 if (move_type == 0)
427     move_type = MOVE_WALK;
428 root 1.1 }
429 root 1.14
430 root 1.78 if ((QUERY_FLAG (this, FLAG_GENERATOR) && QUERY_FLAG (this, FLAG_CONTENT_ON_GEN)) || type == CREATOR || type == CONVERTER)
431 root 1.12 {
432     /* Object will duplicate it's content as part of the
433     * generation process. To do this, we must flag inventory
434     * so it remains unevaluated concerning the randomitems and
435     * the living (a demonlord shouldn't cast from inside generator!)
436     */
437 root 1.78 flag_inv (this, FLAG_IS_A_TEMPLATE);
438 root 1.1 }
439    
440 root 1.12 /* Handle player movers. We use move_type for player movers
441     * because they operate on their own time (move_on
442     * would potentially cause them to be triggered when someone steps
443     * on them). If move_type is set, presume person knows what they
444     * are doing, otherwise, set move_type based on maxhp value.
445     */
446 root 1.78 if (type == PLAYERMOVER)
447 root 1.12 {
448 root 1.78 if (!move_type)
449 root 1.12 {
450 root 1.78 if (stats.maxhp)
451 root 1.12 {
452 root 1.78 move_type = MOVE_ALL;
453     stats.maxhp = 0;
454 root 1.12 }
455     else
456 root 1.78 move_type = MOVE_WALK;
457 root 1.1 }
458     }
459     }
460    
461     static void
462 root 1.63 set_move (MoveType &mt, const char *str)
463 root 1.1 {
464 root 1.63 static const struct flagstr {
465 root 1.67 const char *name;
466 root 1.63 MoveType flags;
467     } move_flags[] = {
468     { "walk" , MOVE_WALK },
469     { "flying" , MOVE_FLY_LOW | MOVE_FLY_HIGH },
470     { "fly_low" , MOVE_FLY_LOW },
471     { "fly_high", MOVE_FLY_HIGH },
472     { "swim" , MOVE_SWIM },
473     { "boat" , MOVE_BOAT },
474 root 1.72 { "ship" , MOVE_SHIP },
475 root 1.63 { "all" , MOVE_ALL },
476     };
477    
478 root 1.1 if (!str)
479     {
480     mt = 0;
481     return;
482     }
483    
484     if (isdigit (*str))
485     {
486     mt = atoi (str);
487     return;
488     }
489    
490     mt = 0;
491    
492 root 1.12 for (str = strtok ((char *) str, " "); str; str = strtok (0, " "))
493 root 1.1 {
494 root 1.63 bool negate = 0;
495    
496     if (*str == '-')
497 root 1.1 {
498 root 1.63 negate = 1;
499     str++;
500     }
501 root 1.1
502 root 1.63 for (const flagstr *f = move_flags; f < move_flags + sizeof (move_flags) / sizeof (move_flags [0]); ++f)
503     {
504     if (!strcmp (f->name, str))
505 root 1.1 {
506 root 1.63 if (negate)
507     mt &= ~f->flags;
508     else
509     mt |= f->flags;
510    
511     goto next;
512 root 1.1 }
513 root 1.63 }
514 root 1.1
515 root 1.63 LOG (llevDebug, "common/loader.C: set_move - unknown move string '%s'\n", str);
516 root 1.1
517 root 1.63 next: ;
518 root 1.1 }
519     }
520    
521 root 1.85 #define GET_FLAG(op,flg) op->flag [flg] = f.get_bool ()
522 root 1.1
523 root 1.59 bool
524     object::parse_kv (object_thawer &f)
525 root 1.1 {
526 root 1.59 object *op_inv = inv;
527 root 1.1
528     for (;;)
529     {
530 root 1.59 switch (f.kw)
531 root 1.1 {
532 root 1.15 case KW_uuid:
533 root 1.59 if (const char *s = f.get_str ())
534 root 1.12 {
535 root 1.15 unsigned int version;
536     unsigned long long seq;
537 root 1.1
538 root 1.15 if (2 == sscanf (s, "<%d.%llx>", &version, &seq) && version == 1)
539 root 1.12 {
540 root 1.59 uuid.seq = seq;
541 root 1.15 break;
542 root 1.12 }
543     }
544 root 1.1
545 root 1.59 uuid = gen_uuid ();
546 root 1.15 break;
547 root 1.1
548 root 1.15 case KW_oid:
549 root 1.59 f.get (this, f.get_sint32 ());
550 root 1.15 break;
551 root 1.1
552 root 1.59 case KW_name: f.get (name); break;
553     case KW_name_pl: f.get (name_pl); break;
554     case KW_title: f.get (title); break;
555     case KW_custom_name: f.get (custom_name); break;
556    
557     case KW_attach: f.get_ornull (attach); break;
558     case KW_skill: f.get_ornull (skill); break;
559     case KW_race: f.get_ornull (race); break;
560     case KW_slaying: f.get_ornull (slaying); break;
561 root 1.1
562 root 1.15 case KW_arch:
563     {
564 root 1.59 object *tmp = object::read (f);
565     tmp->deactivate ();
566 root 1.1
567 root 1.59 {
568     // was: insert_ob_in_ob (tmp, op);
569     // but manually adding it can improve map loading times a lot
570     // also, appending instead of prepending keeps the
571     // save ordering the same between repeated load/saves.
572     CLEAR_FLAG (tmp, FLAG_OBJ_ORIGINAL);
573     CLEAR_FLAG (tmp, FLAG_REMOVED);
574    
575     if (!op_inv)
576     {
577     inv = tmp;
578     tmp->above = 0;
579     }
580     else
581     {
582     while (op_inv->below)
583     op_inv = op_inv->below;
584    
585     op_inv->below = tmp;
586     tmp->above = op_inv;
587     }
588    
589     tmp->below = 0;
590     tmp->env = this;
591     op_inv = tmp;
592     }
593 root 1.15 }
594 root 1.59 continue;
595 root 1.1
596 root 1.15 case KW_other_arch:
597 root 1.68 other_arch =
598     loading_arch
599     ? archetype::get (f.get_str ())
600     : archetype::find (f.get_str ());
601    
602     if (!other_arch)
603     LOG (llevError, "%s uses unknown other_arch '%s'.\n", debug_desc (), f.get_str ());
604 root 1.15 break;
605 root 1.1
606 root 1.15 case KW_animation:
607     {
608 root 1.59 CLEAR_FLAG (this, FLAG_ANIMATE);
609     animation_id = 0;
610 root 1.56
611 root 1.59 const char *str = f.get_str ();
612     if (str && (animation_id = find_animation (str)))
613     SET_FLAG (this, FLAG_ANIMATE);
614 root 1.15 }
615     break;
616    
617 root 1.59 case KW_last_heal: f.get (last_heal); break;
618     case KW_last_sp: f.get (last_sp); break;
619     case KW_last_grace: f.get (last_grace); break;
620     case KW_last_eat: f.get (last_eat); break;
621     case KW_speed_left: f.get (speed_left); break;
622 root 1.15
623     case KW_speed:
624 root 1.59 f.get (speed);
625 root 1.31
626     //TODO: maybe do in check_object
627     // removed check for style maps
628 root 1.59 if (speed < 0)
629     speed_left = speed_left - rndm ();
630 root 1.31
631 root 1.15 break;
632    
633     case KW_slow_move:
634 root 1.59 move_slow |= MOVE_WALK;
635     f.get (move_slow_penalty);
636 root 1.15 break;
637 root 1.1
638 root 1.15 case KW_face:
639 root 1.64 face = face_find (f.get_str ());
640 root 1.15 break;
641    
642 root 1.59 case KW_x: f.get (x); break;
643     case KW_y: f.get (y); break;
644 root 1.18
645 root 1.15 case KW_Str: // uppercase alias
646 root 1.59 case KW_str: f.get (stats.Str); break;
647 root 1.15 case KW_Dex: // uppercase alias
648 root 1.59 case KW_dex: f.get (stats.Dex); break;
649 root 1.15 case KW_Con: // uppercase alias
650 root 1.59 case KW_con: f.get (stats.Con); break;
651 root 1.15 case KW_Wis: // uppercase alias
652 root 1.59 case KW_wis: f.get (stats.Wis); break;
653 root 1.15 case KW_Cha: // uppercase alias
654 root 1.59 case KW_cha: f.get (stats.Cha); break;
655 root 1.15 case KW_Int: // uppercase alias
656 root 1.59 case KW_int: f.get (stats.Int); break;
657 root 1.15 case KW_Pow: // uppercase alias
658 root 1.59 case KW_pow: f.get (stats.Pow); break;
659 root 1.15
660 root 1.59 case KW_hp: f.get (stats.hp); break;
661     case KW_maxhp: f.get (stats.maxhp); break;
662     case KW_sp: f.get (stats.sp); break;
663     case KW_maxsp: f.get (stats.maxsp); break;
664     case KW_grace: f.get (stats.grace); break;
665     case KW_maxgrace: f.get (stats.maxgrace); break;
666    
667     case KW_exp: f.get (stats.exp); break;
668     case KW_perm_exp: f.get (perm_exp); break;
669     case KW_food: f.get (stats.food); break;
670     case KW_dam: f.get (stats.dam); break;
671     case KW_wc: f.get (stats.wc); break;
672     case KW_ac: f.get (stats.ac); break;
673     case KW_nrof: f.get (nrof); break;
674     case KW_level: f.get (level); break;
675     case KW_direction: f.get (direction); break;
676     case KW_type: f.get (type); break;
677     case KW_subtype: f.get (subtype); break;
678     case KW_value: f.get (value); break;
679     case KW_weight: f.get (weight); break;
680     case KW_carrying: f.get (carrying); break;
681     case KW_attacktype: f.get (attacktype); break;
682     case KW_path_attuned: f.get (path_attuned); break;
683     case KW_path_repelled: f.get (path_repelled); break;
684     case KW_path_denied: f.get (path_denied); break;
685     case KW_invisible: f.get (invisible); break;
686     case KW_magic: f.get (magic); break;
687     case KW_state: f.get (state); break;
688     case KW_move_slow_penalty: f.get (move_slow_penalty); break;
689     case KW_material: f.get (materials); break; //TODO: nuke
690     case KW_materialname: f.get (materialname); break;
691 root 1.1
692 root 1.15 /* These are the new values */
693 root 1.59 case KW_move_block: set_move (move_block, f.get_str ()); break;
694     case KW_move_allow: set_move (move_allow, f.get_str ()); break;
695     case KW_move_type: set_move (move_type, f.get_str ()); break;
696     case KW_move_on: set_move (move_on, f.get_str ()); break;
697     case KW_move_off: set_move (move_off, f.get_str ()); break;
698     case KW_move_slow: set_move (move_slow, f.get_str ()); break;
699 root 1.1
700 root 1.15 /* These are all legacy - any new objects should use the move_ .. values */
701     case KW_no_pass:
702     {
703 root 1.59 if (f.get_sint32 ())
704     move_block = MOVE_ALL;
705 root 1.15 else
706 root 1.59 move_block = 0;
707 root 1.15 }
708 root 1.1
709 root 1.15 break;
710 root 1.1
711 root 1.15 /* These are all legacy - any new objects should use the move_ .. values */
712     case KW_walk_on:
713     {
714 root 1.59 if (f.get_sint32 ())
715     move_on |= MOVE_WALK;
716 root 1.15 else
717 root 1.59 move_on &= ~MOVE_WALK;
718 root 1.15 }
719 root 1.1
720 root 1.15 break;
721 root 1.1
722 root 1.15 /* These are all legacy - any new objects should use the move_ .. values */
723     case KW_walk_off:
724     {
725 root 1.59 if (f.get_sint32 ())
726     move_off |= MOVE_WALK;
727 root 1.15 else
728 root 1.59 move_off &= ~MOVE_WALK;
729 root 1.15 }
730     break;
731 root 1.1
732 root 1.15 /* These are all legacy - any new objects should use the move_ .. values */
733     case KW_fly_on:
734     {
735 root 1.59 if (f.get_sint32 ())
736     move_on |= MOVE_FLY_LOW;
737 root 1.15 else
738 root 1.59 move_on &= ~MOVE_FLY_LOW;
739 root 1.15 }
740     break;
741 root 1.1
742 root 1.15 /* These are all legacy - any new objects should use the move_ .. values */
743     case KW_fly_off:
744     {
745 root 1.59 if (f.get_sint32 ())
746     move_off |= MOVE_FLY_LOW;
747 root 1.15 else
748 root 1.59 move_off &= ~MOVE_FLY_LOW;
749 root 1.15 }
750     break;
751 root 1.1
752 root 1.17 //TODO: remove these after converting archetypes
753 root 1.15 case KW_can_use_wand:
754 root 1.59 GET_FLAG (this, FLAG_USE_RANGE);
755 root 1.15 break;
756 root 1.1
757 root 1.15 /* These are all legacy - any new objects should use the move_ .. values */
758     case KW_flying:
759     {
760 root 1.59 if (f.get_sint32 ())
761     move_type |= MOVE_FLY_LOW;
762 root 1.1 else
763 root 1.59 move_type &= ~MOVE_FLY_LOW;
764 root 1.15 }
765     break;
766    
767    
768     case KW_identified:
769 root 1.59 GET_FLAG (this, FLAG_IDENTIFIED);
770 root 1.15 //TODO: move to check_object or so
771 root 1.59 if (QUERY_FLAG (this, FLAG_IDENTIFIED))
772     CLEAR_FLAG (this, FLAG_KNOWN_MAGICAL);
773 root 1.1
774 root 1.15 break;
775 root 1.1
776 root 1.15 case KW_friendly:
777 root 1.85 if (f.get_bool ())
778 root 1.59 if (type != PLAYER)
779     add_friendly_object (this);
780    
781     break;
782    
783     case KW_monster: GET_FLAG (this, FLAG_MONSTER); break;
784     case KW_neutral: GET_FLAG (this, FLAG_NEUTRAL); break;
785     case KW_no_attack: GET_FLAG (this, FLAG_NO_ATTACK); break;
786     case KW_no_damage: GET_FLAG (this, FLAG_NO_DAMAGE); break;
787     case KW_obj_original: GET_FLAG (this, FLAG_OBJ_ORIGINAL); break;
788     case KW_generator: GET_FLAG (this, FLAG_GENERATOR); break;
789     case KW_use_content_on_gen: GET_FLAG (this, FLAG_CONTENT_ON_GEN); break;
790     case KW_is_thrown: GET_FLAG (this, FLAG_IS_THROWN); break;
791     case KW_auto_apply: GET_FLAG (this, FLAG_AUTO_APPLY); break;
792     case KW_see_invisible: GET_FLAG (this, FLAG_SEE_INVISIBLE); break;
793     case KW_can_roll: GET_FLAG (this, FLAG_CAN_ROLL); break;
794     case KW_overlay_floor: GET_FLAG (this, FLAG_OVERLAY_FLOOR); break;
795     case KW_is_turnable: GET_FLAG (this, FLAG_IS_TURNABLE); break;
796     case KW_is_used_up: GET_FLAG (this, FLAG_IS_USED_UP); break;
797     case KW_alive: GET_FLAG (this, FLAG_ALIVE); break;
798     case KW_applied: GET_FLAG (this, FLAG_APPLIED); break;
799     case KW_unpaid: GET_FLAG (this, FLAG_UNPAID); break;
800     case KW_is_animated: GET_FLAG (this, FLAG_ANIMATE); break;
801     case KW_no_pick: GET_FLAG (this, FLAG_NO_PICK); break;
802     case KW_reflecting: GET_FLAG (this, FLAG_REFLECTING); break;
803     case KW_changing: GET_FLAG (this, FLAG_CHANGING); break;
804     case KW_splitting: GET_FLAG (this, FLAG_SPLITTING); break;
805     case KW_hitback: GET_FLAG (this, FLAG_HITBACK); break;
806     case KW_startequip: GET_FLAG (this, FLAG_STARTEQUIP); break;
807     case KW_blocksview: GET_FLAG (this, FLAG_BLOCKSVIEW); break;
808     case KW_undead: GET_FLAG (this, FLAG_UNDEAD); break;
809     case KW_scared: GET_FLAG (this, FLAG_SCARED); break;
810     case KW_unaggressive: GET_FLAG (this, FLAG_UNAGGRESSIVE); break;
811     case KW_reflect_missile: GET_FLAG (this, FLAG_REFL_MISSILE); break;
812     case KW_reflect_spell: GET_FLAG (this, FLAG_REFL_SPELL); break;
813     case KW_no_magic: GET_FLAG (this, FLAG_NO_MAGIC); break;
814     case KW_no_drop: GET_FLAG (this, FLAG_NO_DROP); break;
815     case KW_random_movement: GET_FLAG (this, FLAG_RANDOM_MOVE); break;
816     case KW_no_fix_player: GET_FLAG (this, FLAG_NO_FIX_PLAYER); break;
817     case KW_is_lightable: GET_FLAG (this, FLAG_IS_LIGHTABLE); break;
818     case KW_tear_down: GET_FLAG (this, FLAG_TEAR_DOWN); break;
819     case KW_can_use_shield: GET_FLAG (this, FLAG_USE_SHIELD); break;
820     case KW_can_cast_spell: GET_FLAG (this, FLAG_CAST_SPELL); break;
821     case KW_can_use_scroll: GET_FLAG (this, FLAG_USE_SCROLL); break;
822     case KW_can_use_range: GET_FLAG (this, FLAG_USE_RANGE); break;
823     case KW_can_use_bow: GET_FLAG (this, FLAG_USE_BOW); break;
824     case KW_can_use_armour: GET_FLAG (this, FLAG_USE_ARMOUR); break;
825     case KW_can_use_weapon: GET_FLAG (this, FLAG_USE_WEAPON); break;
826     case KW_can_use_ring: GET_FLAG (this, FLAG_USE_RING); break;
827     case KW_has_ready_bow: GET_FLAG (this, FLAG_READY_BOW); break;
828     case KW_has_ready_range: GET_FLAG (this, FLAG_READY_RANGE); break;
829     case KW_xrays: GET_FLAG (this, FLAG_XRAYS); break;
830     case KW_is_floor: GET_FLAG (this, FLAG_IS_FLOOR); break;
831     case KW_lifesave: GET_FLAG (this, FLAG_LIFESAVE); break;
832     case KW_no_strength: GET_FLAG (this, FLAG_NO_STRENGTH); break;
833     case KW_sleep: GET_FLAG (this, FLAG_SLEEP); break;
834     case KW_stand_still: GET_FLAG (this, FLAG_STAND_STILL); break;
835     case KW_random_move: GET_FLAG (this, FLAG_RANDOM_MOVE); break;
836     case KW_only_attack: GET_FLAG (this, FLAG_ONLY_ATTACK); break;
837     case KW_activate_on_push: GET_FLAG (this, FLAG_ACTIVATE_ON_PUSH); break;
838     case KW_activate_on_release: GET_FLAG (this, FLAG_ACTIVATE_ON_RELEASE); break;
839     case KW_confused: GET_FLAG (this, FLAG_CONFUSED); break;
840     case KW_stealth: GET_FLAG (this, FLAG_STEALTH); break;
841     case KW_cursed: GET_FLAG (this, FLAG_CURSED); break;
842     case KW_damned: GET_FLAG (this, FLAG_DAMNED); break;
843     case KW_see_anywhere: GET_FLAG (this, FLAG_SEE_ANYWHERE); break;
844     case KW_known_magical: GET_FLAG (this, FLAG_KNOWN_MAGICAL); break;
845     case KW_known_cursed: GET_FLAG (this, FLAG_KNOWN_CURSED); break;
846     case KW_can_use_skill: GET_FLAG (this, FLAG_CAN_USE_SKILL); break;
847     case KW_been_applied: GET_FLAG (this, FLAG_BEEN_APPLIED); break;
848     case KW_has_ready_scroll: GET_FLAG (this, FLAG_READY_SCROLL); break;
849     case KW_can_use_rod: GET_FLAG (this, FLAG_USE_ROD); break;
850     case KW_can_use_horn: GET_FLAG (this, FLAG_USE_HORN); break;
851     case KW_unique: GET_FLAG (this, FLAG_UNIQUE); break;
852     case KW_make_invisible: GET_FLAG (this, FLAG_MAKE_INVIS); break;
853     case KW_inv_locked: GET_FLAG (this, FLAG_INV_LOCKED); break;
854     case KW_is_wooded: GET_FLAG (this, FLAG_IS_WOODED); break;
855     case KW_is_hilly: GET_FLAG (this, FLAG_IS_HILLY); break;
856     case KW_is_water: GET_FLAG (this, FLAG_IS_WATER); break;
857     case KW_has_ready_skill: GET_FLAG (this, FLAG_READY_SKILL); break;
858     case KW_has_ready_weapon: GET_FLAG (this, FLAG_READY_WEAPON); break;
859     case KW_no_skill_ident: GET_FLAG (this, FLAG_NO_SKILL_IDENT); break;
860     case KW_is_blind: GET_FLAG (this, FLAG_BLIND); break;
861     case KW_can_see_in_dark: GET_FLAG (this, FLAG_SEE_IN_DARK); break;
862     case KW_is_cauldron: GET_FLAG (this, FLAG_IS_CAULDRON); break;
863     case KW_no_steal: GET_FLAG (this, FLAG_NO_STEAL); break;
864     case KW_one_hit: GET_FLAG (this, FLAG_ONE_HIT); break;
865     case KW_berserk: GET_FLAG (this, FLAG_BERSERK); break;
866     case KW_is_buildable: GET_FLAG (this, FLAG_IS_BUILDABLE); break;
867     case KW_destroy_on_death: GET_FLAG (this, FLAG_DESTROY_ON_DEATH); break;
868 root 1.73 case KW_treasure_env: GET_FLAG (this, FLAG_TREASURE_ENV); break;
869     case KW_precious: GET_FLAG (this, FLAG_PRECIOUS); break;
870 root 1.59
871     case KW_armour: f.get (resist[ATNR_PHYSICAL]); break;
872     case KW_resist_physical: f.get (resist[ATNR_PHYSICAL]); break;
873     case KW_resist_magic: f.get (resist[ATNR_MAGIC]); break;
874     case KW_resist_fire: f.get (resist[ATNR_FIRE]); break;
875     case KW_resist_electricity: f.get (resist[ATNR_ELECTRICITY]); break;
876     case KW_resist_cold: f.get (resist[ATNR_COLD]); break;
877     case KW_resist_confusion: f.get (resist[ATNR_CONFUSION]); break;
878     case KW_resist_acid: f.get (resist[ATNR_ACID]); break;
879     case KW_resist_drain: f.get (resist[ATNR_DRAIN]); break;
880     case KW_resist_weaponmagic: f.get (resist[ATNR_WEAPONMAGIC]); break;
881     case KW_resist_ghosthit: f.get (resist[ATNR_GHOSTHIT]); break;
882     case KW_resist_poison: f.get (resist[ATNR_POISON]); break;
883     case KW_resist_slow: f.get (resist[ATNR_SLOW]); break;
884     case KW_resist_paralyze: f.get (resist[ATNR_PARALYZE]); break;
885     case KW_resist_turn_undead: f.get (resist[ATNR_TURN_UNDEAD]); break;
886     case KW_resist_fear: f.get (resist[ATNR_FEAR]); break;
887     case KW_resist_cancellation: f.get (resist[ATNR_CANCELLATION]); break;
888     case KW_resist_deplete: f.get (resist[ATNR_DEPLETE]); break;
889     case KW_resist_death: f.get (resist[ATNR_DEATH]); break;
890     case KW_resist_chaos: f.get (resist[ATNR_CHAOS]); break;
891     case KW_resist_counterspell: f.get (resist[ATNR_COUNTERSPELL]); break;
892     case KW_resist_godpower: f.get (resist[ATNR_GODPOWER]); break;
893     case KW_resist_holyword: f.get (resist[ATNR_HOLYWORD]); break;
894     case KW_resist_blind: f.get (resist[ATNR_BLIND]); break;
895     case KW_resist_internal: f.get (resist[ATNR_INTERNAL]); break;
896     case KW_resist_life_stealing: f.get (resist[ATNR_LIFE_STEALING]); break;
897     case KW_resist_disease: f.get (resist[ATNR_DISEASE]); break;
898    
899     case KW_luck: f.get (stats.luck); break;
900     case KW_run_away: f.get (run_away); break;
901     case KW_pick_up: f.get (pick_up); break;
902     case KW_item_power: f.get (item_power); break;
903     case KW_gen_sp_armour: f.get (gen_sp_armour); break;
904     case KW_anim_speed: f.get (anim_speed); break;
905     case KW_container: f.get (weight_limit); break;
906     case KW_will_apply: f.get (will_apply); break;
907     case KW_attack_movement: f.get (attack_movement); break;
908     case KW_move_state: f.get (move_status); break;
909     case KW_expmul: f.get (expmul); break;
910     case KW_glow_radius: f.get (glow_radius); break;
911     case KW_weapontype: f.get (weapontype); break;
912     case KW_tooltype: f.get (tooltype); break;
913     case KW_casting_time: f.get (casting_time); break;
914     case KW_elevation: f.get (elevation); break;
915 root 1.65 case KW_smoothlevel: f.get (smoothlevel); smoothlevel = clamp (smoothlevel, 0, 255); break;
916 root 1.59 case KW_client_type: f.get (client_type); break;
917     case KW_duration: f.get (duration); break;
918     case KW_range: f.get (range); break;
919     case KW_range_modifier: f.get (range_modifier); break;
920     case KW_dam_modifier: f.get (dam_modifier); break;
921     case KW_duration_modifier: f.get (duration_modifier); break;
922 root 1.15
923     //TODO: mechanism to ensure that KW_xxx is consecutive needed from include/preprocess
924     //TODO: parse from other include files
925 root 1.78 case KW_body_range: slot[body_range] .info = f.get_sint32 (); break;
926     case KW_body_shield: slot[body_shield] .info = f.get_sint32 (); break;
927     case KW_body_combat: slot[body_combat] .info = f.get_sint32 (); break;
928     case KW_body_arm: slot[body_arm] .info = f.get_sint32 (); break;
929     case KW_body_torso: slot[body_torso] .info = f.get_sint32 (); break;
930     case KW_body_head: slot[body_head] .info = f.get_sint32 (); break;
931     case KW_body_neck: slot[body_neck] .info = f.get_sint32 (); break;
932     case KW_body_skill: slot[body_skill] .info = f.get_sint32 (); break;
933     case KW_body_finger: slot[body_finger] .info = f.get_sint32 (); break;
934     case KW_body_shoulder: slot[body_shoulder].info = f.get_sint32 (); break;
935     case KW_body_foot: slot[body_foot] .info = f.get_sint32 (); break;
936     case KW_body_hand: slot[body_hand] .info = f.get_sint32 (); break;
937     case KW_body_wrist: slot[body_wrist] .info = f.get_sint32 (); break;
938     case KW_body_waist: slot[body_waist] .info = f.get_sint32 (); break;
939 root 1.15 case KW_can_apply:
940     break;
941    
942     case KW_connected:
943 root 1.59 add_button_link (this, map, f.get_sint32 ());
944 root 1.15 break;
945    
946     case KW_randomitems:
947 root 1.68 if (f.get_str ())
948     {
949     randomitems =
950     loading_arch
951     ? treasurelist::get (f.get_str ())
952     : treasurelist::find (f.get_str ());
953    
954     if (!randomitems)
955     LOG (llevError, "%s uses unknown randomitems '%s'.\n", debug_desc (), f.get_str ());
956     }
957 root 1.75 else
958     randomitems = 0;
959 root 1.15 break;
960 root 1.12
961 root 1.15 case KW_msg:
962 root 1.59 f.get_ml (KW_endmsg, msg);
963 root 1.31 //TODO: allow longer messages
964 root 1.59 if (strlen (msg) >= HUGE_BUF)
965 root 1.31 {
966 root 1.59 LOG (llevDebug, "\tError message length >= %d: %d\n>%.80s<\n", HUGE_BUF, strlen (msg), &msg);
967     msg = "ERROR, please report: string too long, winged.\n";
968 root 1.31 }
969 root 1.15 break;
970 root 1.1
971 root 1.15 case KW_lore:
972 root 1.59 f.get_ml (KW_endlore, lore);
973 root 1.31 //TODO: allow longer messages
974     /* Just print a warning so we can be reasonably safe
975     * about not overflowing the buffer.
976     */
977 root 1.59 if (strlen (lore) > (HUGE_BUF / 2))
978 pippijn 1.37 LOG (llevDebug, "\tWarning lore length > %d (max allowed=%d): %d\n>%.80s<\n",
979 root 1.59 HUGE_BUF / 2, HUGE_BUF, strlen (lore), &lore);
980 root 1.15 break;
981 root 1.1
982 root 1.15 case KW_editable:
983     case KW_editor_folder:
984     break;
985 root 1.1
986 root 1.15 case KW_end:
987 root 1.68 if (!loading_arch)
988 root 1.59 instantiate ();
989 root 1.1
990 root 1.59 f.next ();
991     return true;
992 root 1.1
993 root 1.15 case KW_ERROR:
994 root 1.59 set_ob_key_value (this, f.kw_str, f.value, true);
995     //fprintf (stderr, "addkv(%s,%s)\n", f.kw_str, f.value);//D
996 root 1.15 break;
997    
998     default:
999 root 1.59 if (!f.parse_error ("object", name))
1000 root 1.52 return false;
1001 root 1.15 break;
1002 root 1.1 }
1003 root 1.59
1004     f.next ();
1005 root 1.1 }
1006     }
1007    
1008 root 1.59 object *
1009 root 1.60 object::read (object_thawer &f, maptile *map)
1010 root 1.12 {
1011 root 1.59 assert (f.kw == KW_arch);
1012    
1013     archetype *arch = archetype::find (f.get_str ());
1014 root 1.61
1015     if (!arch)
1016     {
1017     LOG (llevError, "object refering to nonexistant archetype '%s'.\n", f.get_str ());
1018     arch = archetype::find ("earthwall");
1019     }
1020    
1021 root 1.59 assert (arch); //D maybe use exception handling of sorts?
1022    
1023 root 1.71 f.next ();
1024    
1025 root 1.59 object *op = object::create ();
1026 root 1.31
1027 root 1.60 op->map = map;
1028 root 1.88 arch->copy_to (op);
1029 root 1.59 // copy_to activates, this should be fixed properly
1030     op->deactivate ();
1031    
1032     if (!op->parse_kv (f))
1033     {
1034 root 1.68 op->destroy (true);
1035 root 1.59 return 0;
1036     }
1037    
1038 root 1.78 op->post_load_check ();
1039 root 1.59 return op;
1040 root 1.1 }
1041    
1042     /* This takes a buffer, scans it for variables, and sets those variables
1043     * as appropriate in op.
1044     *
1045     * This function appears to be used in only 2 places - in crossedit to
1046     * override values and in c_wiz to mutate values.
1047     */
1048 pippijn 1.8 int
1049 root 1.12 set_variable (object *op, char *buf)
1050 pippijn 1.8 {
1051 root 1.59 object_thawer f (buf, (AV *)0);
1052 root 1.1
1053 root 1.71 f.next ();
1054 root 1.59 return op->parse_kv (f);
1055 root 1.1 }
1056    
1057     /* This returns a string of the integer movement type */
1058 pippijn 1.8 #if 0
1059     // unused function
1060 root 1.12 static char *
1061     get_string_move_type (MoveType mt)
1062 root 1.1 {
1063 root 1.12 static char retbuf[MAX_BUF], retbuf_all[MAX_BUF];
1064     int i, all_count = 0, count;
1065 root 1.1
1066 root 1.12 strcpy (retbuf, "");
1067     strcpy (retbuf_all, " all");
1068 root 1.1
1069 root 1.12 /* Quick check, and probably fairly common */
1070     if (mt == MOVE_ALL)
1071     return retbuf_all + 1;
1072     if (mt == 0)
1073     {
1074     strcpy (retbuf, "0");
1075     return retbuf;
1076 root 1.1 }
1077    
1078 root 1.12 /* We basically slide the bits down. Why look at MOVE_ALL?
1079     * because we may want to return a string like 'all -swim',
1080     * and if we just looked at mt, we couldn't get that.
1081     */
1082     for (i = MOVE_ALL, count = 0; i != 0; i >>= 1, count++)
1083     {
1084     if (mt & (1 << count))
1085     {
1086     strcat (retbuf, " ");
1087     strcat (retbuf, move_name[count]);
1088     }
1089     else
1090     {
1091     strcat (retbuf_all, " -");
1092     strcat (retbuf_all, move_name[count]);
1093     all_count++;
1094 root 1.1 }
1095     }
1096 root 1.12 /* Basically, if there is a single negation, return it, eg
1097     * 'all -swim'. But more than that, just return the
1098     * enumerated values. It doesn't make sense to return
1099     * 'all -walk -fly_low' - it is shorter to return 'fly_high swim'
1100     */
1101     if (all_count <= 1)
1102     return retbuf_all + 1;
1103     else
1104     return retbuf + 1;
1105 root 1.1 }
1106 pippijn 1.8 #endif
1107    
1108 root 1.1 // compare *op against *tmp and output differences
1109 root 1.59 static void
1110     write_diff (object_freezer &f, object *op, object *tmp)
1111 root 1.1 {
1112 root 1.19 static const keyword resist_save[NROFATTACKS] = {
1113     # define def(uc, lc, name, plus, change) KW_resist_ ## lc,
1114     # include "attackinc.h"
1115     # undef def
1116     };
1117    
1118     /* This is a list of keywords that correspond to the FLAG_.. values.
1119     * This is a simple 1:1 mapping - if FLAG_FRIENDLY is 15, then
1120     * the 15'th element of this array should match that name.
1121     * If an entry is NULL, that is a flag not to loaded/saved.
1122     */
1123     static const keyword flag_names [NUM_FLAGS] = {
1124     KW_alive,
1125     KW_NULL,
1126     KW_NULL,
1127 root 1.82 KW_NULL,
1128     KW_NULL,
1129 root 1.19 KW_applied,
1130     KW_unpaid,
1131     KW_can_use_shield,
1132     KW_no_pick,
1133     KW_NULL, // walk_on
1134     KW_NULL, // no_pass
1135     /* 10 */
1136     KW_is_animated,
1137     KW_NULL, // slow_move
1138     KW_NULL, // flying
1139     KW_monster,
1140     KW_friendly,
1141     KW_generator,
1142     KW_is_thrown,
1143     KW_auto_apply,
1144 root 1.73 KW_treasure_env,
1145 root 1.19 KW_player_sold,
1146     /* 20 */
1147     KW_see_invisible,
1148     KW_can_roll,
1149     KW_overlay_floor,
1150     KW_is_turnable,
1151     KW_NULL, // walk_off
1152     KW_NULL, // fly_on
1153     KW_NULL, // fly_off
1154     KW_is_used_up,
1155     KW_identified,
1156     KW_reflecting,
1157     /* 30 */
1158     KW_changing,
1159     KW_splitting,
1160     KW_hitback,
1161     KW_startequip,
1162     KW_blocksview,
1163     KW_undead,
1164     KW_scared,
1165     KW_unaggressive,
1166     KW_reflect_missile,
1167     KW_reflect_spell,
1168     /* 40 */
1169     KW_no_magic,
1170     KW_no_fix_player,
1171     KW_is_lightable,
1172     KW_tear_down,
1173     KW_run_away,
1174     KW_NULL, // pass_thru
1175     KW_NULL, // an_pass_thru
1176     KW_pick_up,
1177     KW_unique,
1178     KW_no_drop,
1179     /* 50 */
1180     KW_NULL, // wizcast
1181     KW_can_cast_spell,
1182     KW_can_use_scroll,
1183     KW_can_use_range,
1184     KW_can_use_bow,
1185     KW_can_use_armour,
1186     KW_can_use_weapon,
1187     KW_can_use_ring,
1188     KW_has_ready_range,
1189     KW_has_ready_bow,
1190     /* 60 */
1191     KW_xrays,
1192     KW_NULL,
1193     KW_is_floor,
1194     KW_lifesave,
1195     KW_no_strength,
1196     KW_sleep,
1197     KW_stand_still,
1198     KW_random_move,
1199     KW_only_attack,
1200     KW_confused,
1201     /* 70 */
1202     KW_stealth,
1203     KW_NULL,
1204     KW_NULL,
1205     KW_cursed,
1206     KW_damned,
1207     KW_see_anywhere,
1208     KW_known_magical,
1209     KW_known_cursed,
1210     KW_can_use_skill,
1211     KW_been_applied,
1212     /* 80 */
1213     KW_has_ready_scroll,
1214     KW_can_use_rod,
1215 root 1.73 KW_precious,
1216 root 1.19 KW_can_use_horn,
1217     KW_make_invisible,
1218     KW_inv_locked,
1219     KW_is_wooded,
1220     KW_is_hilly,
1221     KW_has_ready_skill,
1222     KW_has_ready_weapon,
1223     /* 90 */
1224     KW_no_skill_ident,
1225     KW_is_blind,
1226     KW_can_see_in_dark,
1227     KW_is_cauldron,
1228     KW_NULL,
1229     KW_no_steal,
1230     KW_one_hit,
1231     KW_NULL,
1232     KW_berserk,
1233     KW_neutral,
1234     /* 100 */
1235     KW_no_attack,
1236     KW_no_damage,
1237 root 1.43 KW_obj_original,
1238 root 1.19 KW_NULL,
1239     KW_activate_on_push,
1240     KW_activate_on_release,
1241     KW_is_water,
1242     KW_use_content_on_gen,
1243     KW_NULL,
1244     KW_is_buildable,
1245     /* 110 */
1246 root 1.41 KW_destroy_on_death,
1247 root 1.44 KW_NULL,
1248 root 1.19 };
1249    
1250 root 1.1 int i;
1251    
1252     /* This saves the key/value lists. We do it first so that any
1253     * keys that match field names will be overwritten by the loader.
1254     */
1255 root 1.44 for (key_value *my_field = op->key_values; my_field; my_field = my_field->next)
1256 root 1.1 {
1257     /* Find the field in the opposing member. */
1258     key_value *arch_field = get_ob_key_link (tmp, my_field->key);
1259    
1260     /* If there's no partnering field, or it's got a different value, save our field. */
1261 root 1.19 if (!arch_field || my_field->value != arch_field->value)
1262 root 1.1 f.put (my_field->key, my_field->value);
1263     }
1264    
1265     /* We don't need to worry about the arch's extra fields - they
1266 root 1.22 * will get taken care of the copy_to method.
1267 root 1.1 */
1268    
1269 root 1.15 {
1270     char uids[64];
1271     snprintf (uids, sizeof (uids), "<1.%llx>", (unsigned long long)op->uuid.seq);
1272     f.put (KW_uuid, (const char *)uids);
1273     }
1274    
1275 root 1.12 #define CMP_OUT(v) if (op->v != tmp->v) f.put (KW_ ## v, op->v)
1276     #define CMP_OUT2(k,v) if (op->v != tmp->v) f.put (KW_ ## k, op->v)
1277 root 1.1
1278     CMP_OUT (name);
1279     CMP_OUT (name_pl);
1280     CMP_OUT (custom_name);
1281     CMP_OUT (title);
1282     CMP_OUT (race);
1283     CMP_OUT (slaying);
1284    
1285 root 1.12 if (op->msg != tmp->msg)
1286     f.put (KW_msg, KW_endmsg, op->msg);
1287     if (op->lore != tmp->lore)
1288     f.put (KW_lore, KW_endlore, op->lore);
1289 root 1.89
1290     CMP_OUT (other_arch);
1291 root 1.66
1292     if (op->face != tmp->face) f.put (KW_face, op->face ? &faces [op->face] : 0);
1293 root 1.1
1294     if (op->animation_id != tmp->animation_id)
1295     if (op->animation_id)
1296     {
1297     f.put (KW_animation, animations[GET_ANIM_ID (op)].name);
1298 root 1.12
1299 root 1.1 if (!QUERY_FLAG (op, FLAG_ANIMATE))
1300 root 1.12 f.put (KW_is_animated, (sint32) 0);
1301 root 1.1 }
1302     else
1303 root 1.12 f.put (KW_animation, (const char *) 0);
1304 root 1.1
1305 root 1.12 CMP_OUT2 (str, stats.Str);
1306     CMP_OUT2 (dex, stats.Dex);
1307     CMP_OUT2 (con, stats.Con);
1308     CMP_OUT2 (wis, stats.Wis);
1309     CMP_OUT2 (pow, stats.Pow);
1310     CMP_OUT2 (cha, stats.Cha);
1311     CMP_OUT2 (int, stats.Int);
1312    
1313     CMP_OUT2 (hp, stats.hp);
1314     CMP_OUT2 (maxhp, stats.maxhp);
1315     CMP_OUT2 (sp, stats.sp);
1316     CMP_OUT2 (maxsp, stats.maxsp);
1317     CMP_OUT2 (grace, stats.grace);
1318 root 1.1 CMP_OUT2 (maxgrace, stats.maxgrace);
1319 root 1.12 CMP_OUT2 (exp, stats.exp);
1320 root 1.1
1321     CMP_OUT (perm_exp);
1322     CMP_OUT (expmul);
1323    
1324 root 1.12 CMP_OUT2 (food, stats.food);
1325     CMP_OUT2 (dam, stats.dam);
1326     CMP_OUT2 (luck, stats.luck);
1327     CMP_OUT2 (wc, stats.wc);
1328     CMP_OUT2 (ac, stats.ac);
1329 root 1.1
1330     CMP_OUT (x);
1331     CMP_OUT (y);
1332     CMP_OUT (speed);
1333     CMP_OUT (speed_left);
1334     CMP_OUT2 (move_state, move_status);
1335     CMP_OUT (attack_movement);
1336     CMP_OUT (nrof);
1337     CMP_OUT (level);
1338     CMP_OUT (direction);
1339     CMP_OUT (type);
1340     CMP_OUT (subtype);
1341     CMP_OUT (attacktype);
1342    
1343     for (i = 0; i < NROFATTACKS; i++)
1344 root 1.12 if (op->resist[i] != tmp->resist[i])
1345     f.put (resist_save[i], op->resist[i]);
1346 root 1.1
1347     CMP_OUT (path_attuned);
1348     CMP_OUT (path_repelled);
1349     CMP_OUT (path_denied);
1350 root 1.54 CMP_OUT2 (material, materials);//TODO: nuke
1351 root 1.1 CMP_OUT (materialname);
1352     CMP_OUT (value);
1353     CMP_OUT (carrying);
1354     CMP_OUT (weight);
1355     CMP_OUT (invisible);
1356     CMP_OUT (state);
1357     CMP_OUT (magic);
1358     CMP_OUT (last_heal);
1359     CMP_OUT (last_sp);
1360     CMP_OUT (last_grace);
1361     CMP_OUT (last_eat);
1362     CMP_OUT (glow_radius);
1363    
1364     if (QUERY_FLAG (op, FLAG_IS_LINKED) && (i = get_button_value (op)))
1365     f.put (KW_connected, i);
1366    
1367     CMP_OUT (randomitems);
1368     CMP_OUT2 (container, weight_limit);
1369    
1370     CMP_OUT (run_away);
1371     CMP_OUT (pick_up);
1372     CMP_OUT (will_apply);
1373     CMP_OUT (smoothlevel);
1374     CMP_OUT (weapontype);
1375     CMP_OUT (tooltype);
1376     CMP_OUT (elevation);
1377     CMP_OUT (client_type);
1378     CMP_OUT (item_power);
1379     CMP_OUT (duration);
1380     CMP_OUT (range);
1381     CMP_OUT (range_modifier);
1382     CMP_OUT (duration_modifier);
1383     CMP_OUT (dam_modifier);
1384     CMP_OUT (gen_sp_armour);
1385    
1386     CMP_OUT (move_type);
1387     CMP_OUT (move_block);
1388     CMP_OUT (move_allow);
1389     CMP_OUT (move_on);
1390     CMP_OUT (move_off);
1391     CMP_OUT (move_slow);
1392     CMP_OUT (move_slow_penalty);
1393    
1394 root 1.27 if (op->flag != tmp->flag)
1395 root 1.1 for (i = 0; i <= NUM_FLAGS; i++)
1396 root 1.27 if (flag_names [i] && op->flag [i] != tmp->flag [i])
1397     f.put (flag_names [i], op->flag [i] ? "1" : "0");
1398 root 1.1
1399 root 1.77 // save body locations
1400 root 1.1 for (i = 0; i < NUM_BODY_LOCATIONS; i++)
1401 root 1.76 if (op->slot[i].info != tmp->slot[i].info)
1402     f.put (body_locations[i].save_name, op->slot[i].info);
1403 root 1.1 }
1404    
1405     /*
1406     * Dumps all variables in an object to a file.
1407     * If bit 0 of flag is set, unpaid objects will be saved. As of now,
1408     * the only place this is not set is when saving the player.
1409     */
1410 root 1.59 bool
1411     object::write (object_freezer &f)
1412 root 1.1 {
1413     /* Even if the object does have an owner, it would seem that we should
1414     * still save it.
1415     */
1416 root 1.59 if (owner)
1417     return true;
1418 root 1.1
1419 root 1.59 archetype *at = arch ? (archetype *)arch : empty_archetype;
1420 root 1.1
1421 root 1.87 f.put (KW_arch, at->archname);
1422 root 1.88 write_diff (f, this, at);
1423 root 1.1
1424 root 1.59 for (object *tmp = inv; tmp; tmp = tmp->below)
1425     tmp->write (f);
1426 root 1.1
1427 root 1.59 f.put (this);
1428     f.put (KW_end);
1429 root 1.1
1430 root 1.59 return true;
1431 root 1.1 }
1432 root 1.15
1433 root 1.58 /////////////////////////////////////////////////////////////////////////////
1434    
1435 root 1.69 // generic resource file load,
1436 root 1.70 // currently supports: region, treasures, archetypes
1437 root 1.58 bool load_resource_file (const char *filename)
1438     {
1439     object_thawer f (filename);
1440    
1441 root 1.70 bool success = false;
1442     bool seen_arch = false;
1443    
1444 root 1.59 f.next ();
1445 root 1.58
1446     for (;;)
1447     {
1448     switch (f.kw)
1449     {
1450     case KW_region:
1451 root 1.59 if (!region::read (f))
1452 root 1.70 goto finish;
1453 root 1.58 break;
1454    
1455 root 1.69 case KW_treasure:
1456     case KW_treasureone:
1457     if (!treasurelist::read (f))
1458 root 1.70 goto finish;
1459     break;
1460    
1461     case KW_object:
1462     seen_arch = true;
1463     if (!archetype::read (f))
1464     goto finish;
1465 root 1.69 break;
1466    
1467 root 1.58 case KW_EOF:
1468 root 1.70 success = true;
1469     goto finish;
1470 root 1.58
1471     default:
1472     if (!f.parse_error ("resource file"))
1473 root 1.70 goto finish;
1474 root 1.74
1475     f.next ();
1476     break;
1477 root 1.58 }
1478     }
1479 root 1.70
1480     finish:
1481     if (seen_arch)
1482     init_archetype_pointers ();
1483    
1484     return success;
1485 root 1.58 }
1486