ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/loader.C
Revision: 1.65
Committed: Wed Mar 14 04:12:27 2007 UTC (17 years, 2 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.64: +1 -1 lines
Log Message:
- rewrote more face handling code
- automatically send smooth faces, as the client will need them anyways
  and it makes little sense to wait for the client to axk for it. of course,
  gcfclient suffers from weird ordering problems again.
- UP_OBJ_FACE was often abused in situations where other things changed,
  updated lots of spaces, probably more to be done.
- update_smooth became so small that inlining it actually clarified
  the code. similar for update_space, which is not inlined for other reasons.
- faces were not initialised properly
- add versioncheck for face data
- rewrite invisibility handling a bit: god finger etc. now makes you blink,
  blinking routine has changed to be less annoying and more useful while
  still indicating invisibleness.

File Contents

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