ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/object.C
Revision: 1.219
Committed: Wed Apr 23 21:09:10 2008 UTC (16 years, 1 month ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.218: +6 -0 lines
Log Message:
catch a potential bug

File Contents

# User Rev Content
1 elmex 1.1 /*
2 root 1.199 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 pippijn 1.116 *
4 root 1.208 * Copyright (©) 2005,2006,2007,2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 root 1.157 * Copyright (©) 2001,2007 Mark Wedel & Crossfire Development Team
6     * Copyright (©) 1992,2007 Frank Tore Johansen
7 pippijn 1.116 *
8 root 1.199 * Deliantra is free software: you can redistribute it and/or modify
9 root 1.163 * 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.116 *
13 root 1.163 * 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.116 *
18 root 1.163 * 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.157 *
21 root 1.199 * The authors can be reached via e-mail to <support@deliantra.net>
22 pippijn 1.116 */
23 elmex 1.1
24     #include <global.h>
25 root 1.28 #include <stdio.h>
26     #include <sys/types.h>
27     #include <sys/uio.h>
28 elmex 1.1 #include <object.h>
29 root 1.146 #include <sproto.h>
30 elmex 1.1 #include <loader.h>
31 root 1.28
32 root 1.68 #include <bitset>
33    
34 root 1.202 UUID UUID::cur;
35 root 1.204 static uint64_t seq_next_save;
36     static const uint64 UUID_GAP = 1<<19;
37 elmex 1.1
38 root 1.108 objectvec objects;
39     activevec actives;
40 elmex 1.1
41 root 1.203 short freearr_x[SIZEOFFREE] = {
42     0,
43     0, 1, 1, 1, 0, -1, -1, -1,
44     0, 1, 2, 2, 2, 2, 2, 1, 0, -1, -2, -2, -2, -2, -2, -1,
45     0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, -1, -2, -3, -3, -3, -3, -3, -3, -3, -2, -1
46 root 1.24 };
47 root 1.203 short freearr_y[SIZEOFFREE] = {
48     0,
49     -1, -1, 0, 1, 1, 1, 0, -1,
50     -2, -2, -2, -1, 0, 1, 2, 2, 2, 2, 2, 1, 0, -1, -2, -2,
51     -3, -3, -3, -3, -2, -1, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, -1, -2, -3, -3, -3
52 root 1.24 };
53 root 1.203 int maxfree[SIZEOFFREE] = {
54     0,
55     9, 10, 13, 14, 17, 18, 21, 22,
56     25, 26, 27, 30, 31, 32, 33, 36, 37, 39, 39, 42, 43, 44, 45, 48,
57     49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49
58 root 1.24 };
59     int freedir[SIZEOFFREE] = {
60 root 1.203 0,
61     1, 2, 3, 4, 5, 6, 7, 8,
62     1, 2, 2, 2, 3, 4, 4, 4, 5, 6, 6, 6, 7, 8, 8, 8,
63     1, 2, 2, 2, 2, 2, 3, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 7, 8, 8, 8, 8, 8
64 root 1.24 };
65 elmex 1.1
66 root 1.39 static void
67 root 1.203 write_uuid (uval64 skip, bool sync)
68 root 1.39 {
69 root 1.203 CALL_BEGIN (2);
70     CALL_ARG_SV (newSVval64 (skip));
71     CALL_ARG_SV (boolSV (sync));
72     CALL_CALL ("cf::write_uuid", G_DISCARD);
73     CALL_END;
74 root 1.39 }
75    
76     static void
77     read_uuid (void)
78     {
79     char filename[MAX_BUF];
80    
81     sprintf (filename, "%s/uuid", settings.localdir);
82    
83 root 1.204 seq_next_save = 0;
84    
85 root 1.39 FILE *fp;
86    
87     if (!(fp = fopen (filename, "r")))
88     {
89     if (errno == ENOENT)
90     {
91     LOG (llevInfo, "RESET uid to 1\n");
92 root 1.202 UUID::cur.seq = 0;
93 root 1.204 write_uuid (UUID_GAP, true);
94 root 1.39 return;
95     }
96    
97     LOG (llevError, "FATAL: cannot open %s for reading!\n", filename);
98     _exit (1);
99     }
100    
101 root 1.203 UUID::BUF buf;
102     buf[0] = 0;
103     fgets (buf, sizeof (buf), fp);
104    
105     if (!UUID::cur.parse (buf))
106 root 1.39 {
107 root 1.203 LOG (llevError, "FATAL: error reading uid from %s (%s)!\n", filename, buf);
108 root 1.39 _exit (1);
109     }
110    
111 root 1.203 LOG (llevDebug, "read UUID: %s\n", UUID::cur.c_str ());
112    
113 root 1.204 write_uuid (UUID_GAP, true);
114 root 1.39 fclose (fp);
115     }
116    
117     UUID
118 root 1.202 UUID::gen ()
119 root 1.39 {
120     UUID uid;
121    
122 root 1.202 uid.seq = ++cur.seq;
123 root 1.39
124 root 1.204 if (expect_false (cur.seq >= seq_next_save))
125     {
126     seq_next_save = UUID::cur.seq + (UUID_GAP >> 1);
127     write_uuid (UUID_GAP, false);
128     }
129    
130 root 1.39
131     return uid;
132     }
133    
134     void
135 root 1.202 UUID::init ()
136 root 1.39 {
137     read_uuid ();
138     }
139    
140 elmex 1.1 /* Returns TRUE if every key_values in wants has a partner with the same value in has. */
141 root 1.205 static bool
142 root 1.24 compare_ob_value_lists_one (const object *wants, const object *has)
143     {
144     key_value *wants_field;
145    
146     /* n-squared behaviour (see get_ob_key_link()), but I'm hoping both
147     * objects with lists are rare, and lists stay short. If not, use a
148     * different structure or at least keep the lists sorted...
149     */
150    
151     /* For each field in wants, */
152 root 1.86 for (wants_field = wants->key_values; wants_field; wants_field = wants_field->next)
153 root 1.24 {
154     key_value *has_field;
155    
156     /* Look for a field in has with the same key. */
157     has_field = get_ob_key_link (has, wants_field->key);
158    
159 root 1.205 if (!has_field)
160     return 0; /* No field with that name. */
161 root 1.24
162     /* Found the matching field. */
163     if (has_field->value != wants_field->value)
164 root 1.205 return 0; /* Values don't match, so this half of the comparison is false. */
165 root 1.24
166     /* If we get here, we found a match. Now for the next field in wants. */
167 elmex 1.1 }
168 root 1.24
169     /* If we get here, every field in wants has a matching field in has. */
170 root 1.205 return 1;
171 elmex 1.1 }
172    
173     /* Returns TRUE if ob1 has the same key_values as ob2. */
174 root 1.205 static bool
175 root 1.24 compare_ob_value_lists (const object *ob1, const object *ob2)
176     {
177     /* However, there may be fields in has which aren't partnered in wants,
178     * so we need to run the comparison *twice*. :(
179     */
180     return compare_ob_value_lists_one (ob1, ob2) && compare_ob_value_lists_one (ob2, ob1);
181 elmex 1.1 }
182    
183     /* Function examines the 2 objects given to it, and returns true if
184     * they can be merged together.
185     *
186     * Note that this function appears a lot longer than the macro it
187     * replaces - this is mostly for clarity - a decent compiler should hopefully
188     * reduce this to the same efficiency.
189     *
190 root 1.66 * Check nrof variable *before* calling can_merge()
191 elmex 1.1 *
192     * Improvements made with merge: Better checking on potion, and also
193     * check weight
194     */
195 root 1.66 bool object::can_merge_slow (object *ob1, object *ob2)
196 root 1.16 {
197     /* A couple quicksanity checks */
198 root 1.66 if (ob1 == ob2
199     || ob1->type != ob2->type
200     || ob1->speed != ob2->speed
201     || ob1->value != ob2->value
202     || ob1->name != ob2->name)
203 root 1.16 return 0;
204    
205 root 1.205 /* Do not merge objects if nrof would overflow. First part checks
206 root 1.208 * for unsigned overflow (2c), second part checks whether the result
207 root 1.205 * would fit into a 32 bit signed int, which is often used to hold
208     * nrof values.
209 root 1.16 */
210 root 1.205 if (~ob1->nrof < ob2->nrof || ob1->nrof + ob2->nrof > (1UL << 31))
211 root 1.16 return 0;
212    
213     /* If the objects have been identified, set the BEEN_APPLIED flag.
214 root 1.205 * This is to the comparison of the flags below will be OK. We
215 root 1.16 * just can't ignore the been applied or identified flags, as they
216     * are not equal - just if it has been identified, the been_applied
217     * flags lose any meaning.
218     */
219     if (QUERY_FLAG (ob1, FLAG_IDENTIFIED))
220     SET_FLAG (ob1, FLAG_BEEN_APPLIED);
221    
222     if (QUERY_FLAG (ob2, FLAG_IDENTIFIED))
223     SET_FLAG (ob2, FLAG_BEEN_APPLIED);
224 elmex 1.1
225 root 1.208 if (ob1->arch->name != ob2->arch->name
226 root 1.68 || ob1->name != ob2->name
227     || ob1->title != ob2->title
228     || ob1->msg != ob2->msg
229     || ob1->weight != ob2->weight
230     || ob1->attacktype != ob2->attacktype
231     || ob1->magic != ob2->magic
232     || ob1->slaying != ob2->slaying
233     || ob1->skill != ob2->skill
234     || ob1->value != ob2->value
235     || ob1->animation_id != ob2->animation_id
236     || ob1->client_type != ob2->client_type
237     || ob1->materialname != ob2->materialname
238     || ob1->lore != ob2->lore
239     || ob1->subtype != ob2->subtype
240     || ob1->move_type != ob2->move_type
241     || ob1->move_block != ob2->move_block
242     || ob1->move_allow != ob2->move_allow
243     || ob1->move_on != ob2->move_on
244     || ob1->move_off != ob2->move_off
245     || ob1->move_slow != ob2->move_slow
246 root 1.208 || ob1->move_slow_penalty != ob2->move_slow_penalty
247     || memcmp (&ob1->resist, &ob2->resist, sizeof (ob1->resist))
248     || memcmp (&ob1->stats , &ob2->stats , sizeof (ob1->stats)))
249     return 0;
250    
251     if ((ob1->flag ^ ob2->flag)
252     .reset (FLAG_INV_LOCKED)
253     .reset (FLAG_CLIENT_SENT)
254     .reset (FLAG_REMOVED)
255     .any ())
256 root 1.16 return 0;
257    
258 root 1.205 /* This is really a spellbook check - we should in general
259     * not merge objects with real inventories, as splitting them
260     * is hard.
261 root 1.16 */
262     if (ob1->inv || ob2->inv)
263     {
264 root 1.193 if (!(ob1->inv && ob2->inv))
265     return 0; /* inventories differ in length */
266    
267     if (ob1->inv->below || ob2->inv->below)
268     return 0; /* more than one object in inv */
269 root 1.16
270 root 1.66 if (!object::can_merge (ob1->inv, ob2->inv))
271 root 1.205 return 0; /* inventory objects differ */
272 root 1.16
273     /* inventory ok - still need to check rest of this object to see
274     * if it is valid.
275     */
276     }
277 elmex 1.1
278 root 1.16 /* Don't merge objects that are applied. With the new 'body' code,
279     * it is possible for most any character to have more than one of
280     * some items equipped, and we don't want those to merge.
281     */
282     if (QUERY_FLAG (ob1, FLAG_APPLIED) || QUERY_FLAG (ob2, FLAG_APPLIED))
283     return 0;
284 elmex 1.1
285 root 1.16 /* Note sure why the following is the case - either the object has to
286     * be animated or have a very low speed. Is this an attempted monster
287     * check?
288     */
289 elmex 1.97 if (!QUERY_FLAG (ob1, FLAG_ANIMATE) && ob1->has_active_speed ())
290 root 1.16 return 0;
291 elmex 1.1
292 root 1.16 switch (ob1->type)
293     {
294 root 1.29 case SCROLL:
295     if (ob1->level != ob2->level)
296     return 0;
297     break;
298 root 1.16 }
299 elmex 1.1
300 root 1.205 if (ob1->key_values || ob2->key_values)
301 root 1.16 {
302     /* At least one of these has key_values. */
303 root 1.205 if ((!ob1->key_values) != (!ob2->key_values))
304 root 1.208 return 0; /* One has fields, but the other one doesn't. */
305    
306     if (!compare_ob_value_lists (ob1, ob2))
307 root 1.24 return 0;
308 elmex 1.1 }
309 root 1.16
310     if (ob1->self || ob2->self)
311     {
312     ob1->optimise ();
313     ob2->optimise ();
314    
315     if (ob1->self || ob2->self)
316 root 1.192 {
317 root 1.195 int k1 = ob1->self ? HvTOTALKEYS (ob1->self) : 0;
318     int k2 = ob2->self ? HvTOTALKEYS (ob2->self) : 0;
319 root 1.192
320     if (k1 != k2)
321     return 0;
322 root 1.208
323     if (k1 == 0)
324 root 1.192 return 1;
325 root 1.208
326     if (!cfperl_can_merge (ob1, ob2))
327 root 1.192 return 0;
328     }
329 elmex 1.1 }
330    
331 root 1.16 /* Everything passes, must be OK. */
332     return 1;
333 elmex 1.1 }
334 root 1.24
335 root 1.214 // find player who can see this object
336     object *
337     object::visible_to () const
338     {
339     if (!flag [FLAG_REMOVED])
340     {
341     // see if we are in a container of sorts
342     if (env)
343     {
344     // the player inventory itself is always visible
345     if (env->type == PLAYER)
346     return env;
347    
348     // else a player could have our env open
349     object *envest = env->outer_env ();
350    
351     // the player itself is always on a map, so we will find him here
352     // even if our inv is in a player.
353     if (envest->is_on_map ())
354     if (object *pl = envest->ms ().player ())
355     if (pl->container == env)
356     return pl;
357     }
358     else
359     {
360     // maybe there is a player standing on the same mapspace
361     // this will catch the case where "this" is a player
362     if (object *pl = ms ().player ())
363     return pl;
364     }
365     }
366    
367     return 0;
368     }
369    
370 root 1.208 // adjust weight per container type ("of holding")
371 root 1.207 static sint32
372     weight_adjust (object *op, sint32 weight)
373     {
374     return op->type == CONTAINER
375     ? lerp (weight, 0, 100, 0, 100 - op->stats.Str)
376     : weight;
377     }
378    
379 elmex 1.1 /*
380 root 1.208 * adjust_weight(object, weight) adds the specified weight to an object,
381 root 1.207 * and also updates how much the environment(s) is/are carrying.
382 elmex 1.1 */
383 root 1.207 static void
384 root 1.208 adjust_weight (object *op, sint32 weight)
385 root 1.24 {
386 root 1.207 while (op)
387 root 1.24 {
388 root 1.207 weight = weight_adjust (op, weight);
389 root 1.142
390 root 1.212 if (!weight)
391     return;
392    
393 root 1.207 op->carrying += weight;
394 root 1.212
395     if (object *pl = op->visible_to ())
396 root 1.215 if (pl != op) // player is handled lazily
397     esrv_update_item (UPD_WEIGHT, pl, op);
398 root 1.212
399 root 1.207 op = op->env;
400 root 1.24 }
401 root 1.207 }
402 root 1.37
403 root 1.207 /*
404     * this is a recursive function which calculates the weight
405     * an object is carrying. It goes through op and figures out how much
406     * containers are carrying, and sums it up.
407     */
408     void
409     object::update_weight ()
410     {
411     sint32 sum = 0;
412 root 1.37
413 root 1.207 for (object *op = inv; op; op = op->below)
414     {
415     if (op->inv)
416     op->update_weight ();
417 elmex 1.1
418 root 1.207 sum += op->total_weight ();
419     }
420 elmex 1.1
421 root 1.212 sum = weight_adjust (this, sum);
422    
423     if (sum != carrying)
424     {
425     carrying = sum;
426    
427     if (object *pl = visible_to ())
428 root 1.215 if (pl != this) // player is handled lazily
429     esrv_update_item (UPD_WEIGHT, pl, this);
430 root 1.212 }
431 elmex 1.1 }
432    
433     /*
434 root 1.208 * Used by: Server DM commands: dumpbelow, dump. Some error messages.
435 elmex 1.1 */
436 root 1.53 char *
437 root 1.24 dump_object (object *op)
438     {
439 root 1.53 if (!op)
440     return strdup ("[NULLOBJ]");
441 elmex 1.1
442 root 1.53 object_freezer freezer;
443 root 1.133 op->write (freezer);
444 root 1.53 return freezer.as_string ();
445 elmex 1.1 }
446    
447     /*
448     * get_nearest_part(multi-object, object 2) returns the part of the
449     * multi-object 1 which is closest to the second object.
450     * If it's not a multi-object, it is returned.
451     */
452 root 1.24 object *
453     get_nearest_part (object *op, const object *pl)
454     {
455     object *tmp, *closest;
456     int last_dist, i;
457    
458 root 1.208 if (!op->more)
459 elmex 1.1 return op;
460 root 1.208
461     for (last_dist = distance (op, pl), closest = op, tmp = op->more;
462     tmp;
463     tmp = tmp->more)
464 root 1.24 if ((i = distance (tmp, pl)) < last_dist)
465     closest = tmp, last_dist = i;
466 root 1.208
467 elmex 1.1 return closest;
468     }
469    
470     /*
471     * Returns the object which has the count-variable equal to the argument.
472 root 1.208 * VERRRY slow.
473 elmex 1.1 */
474 root 1.24 object *
475     find_object (tag_t i)
476     {
477 root 1.112 for_all_objects (op)
478     if (op->count == i)
479     return op;
480    
481     return 0;
482 elmex 1.1 }
483    
484     /*
485     * Returns the first object which has a name equal to the argument.
486     * Used only by the patch command, but not all that useful.
487     * Enables features like "patch <name-of-other-player> food 999"
488     */
489 root 1.24 object *
490     find_object_name (const char *str)
491     {
492 root 1.35 shstr_cmp str_ (str);
493 elmex 1.1 object *op;
494 root 1.24
495 root 1.108 for_all_objects (op)
496 root 1.35 if (op->name == str_)
497 elmex 1.1 break;
498 root 1.11
499 elmex 1.1 return op;
500     }
501    
502     /*
503     * Sets the owner and sets the skill and exp pointers to owner's current
504     * skill and experience objects.
505 root 1.183 * ACTUALLY NO! investigate! TODO
506 elmex 1.1 */
507 root 1.24 void
508 root 1.30 object::set_owner (object *owner)
509 elmex 1.1 {
510 root 1.183 // allow objects which own objects
511     if (owner)
512     while (owner->owner)
513     owner = owner->owner;
514 elmex 1.1
515 root 1.198 if (flag [FLAG_FREED])
516     {
517     LOG (llevError | logBacktrace, "tried to set owner of %s to %s\n", debug_desc (), owner->debug_desc ());
518     return;
519     }
520    
521 root 1.30 this->owner = owner;
522 elmex 1.1 }
523    
524 root 1.148 int
525     object::slottype () const
526     {
527     if (type == SKILL)
528     {
529     if (IS_COMBAT_SKILL (subtype)) return slot_combat;
530     if (IS_RANGED_SKILL (subtype)) return slot_ranged;
531     }
532     else
533     {
534     if (slot [body_combat].info) return slot_combat;
535     if (slot [body_range ].info) return slot_ranged;
536     }
537    
538     return slot_none;
539     }
540    
541 root 1.147 bool
542     object::change_weapon (object *ob)
543 root 1.144 {
544     if (current_weapon == ob)
545 root 1.147 return true;
546 root 1.146
547 root 1.150 if (chosen_skill)
548     chosen_skill->flag [FLAG_APPLIED] = false;
549    
550 root 1.144 current_weapon = ob;
551 root 1.147 chosen_skill = !ob || ob->type == SKILL ? ob : find_skill_by_name (this, ob->skill);
552 root 1.146
553 root 1.150 if (chosen_skill)
554     chosen_skill->flag [FLAG_APPLIED] = true;
555    
556 root 1.144 update_stats ();
557 root 1.147
558     if (ob)
559     {
560     // now check wether any body locations became invalid, in which case
561     // we cannot apply the weapon at the moment.
562     for (int i = 0; i < NUM_BODY_LOCATIONS; ++i)
563     if (slot[i].used < 0)
564     {
565     current_weapon = chosen_skill = 0;
566     update_stats ();
567    
568     new_draw_info_format (NDI_UNIQUE, 0, this,
569 root 1.156 "You try to balance all your items at once, "
570     "but the %s is just too much for your body. "
571     "[You need to unapply some items first.]", &ob->name);
572 root 1.147 return false;
573     }
574    
575 root 1.148 //new_draw_info_format (NDI_UNIQUE, 0, this, "You switch to your %s.", &ob->name);
576 root 1.147 }
577     else
578 root 1.148 ;//new_draw_info_format (NDI_UNIQUE, 0, this, "You unwield your weapons.");
579 root 1.147
580 root 1.151 if (ob && !ob->flag [FLAG_APPLIED] && ob->type != SPELL)
581     {
582     LOG (llevError | logBacktrace, "%s changed to unapplied weapon %s",
583     &name, ob->debug_desc ());
584     return false;
585     }
586    
587 root 1.147 return true;
588 root 1.144 }
589    
590 elmex 1.1 /* Zero the key_values on op, decrementing the shared-string
591     * refcounts and freeing the links.
592     */
593 root 1.24 static void
594     free_key_values (object *op)
595 root 1.11 {
596 root 1.137 for (key_value *i = op->key_values; i; )
597 root 1.11 {
598     key_value *next = i->next;
599     delete i;
600 root 1.24
601 root 1.11 i = next;
602 elmex 1.1 }
603 root 1.24
604 root 1.11 op->key_values = 0;
605 elmex 1.1 }
606    
607 root 1.137 object &
608     object::operator =(const object &src)
609 root 1.11 {
610 root 1.137 bool is_freed = flag [FLAG_FREED];
611     bool is_removed = flag [FLAG_REMOVED];
612 root 1.59
613 root 1.137 *(object_copy *)this = src;
614 elmex 1.1
615 root 1.137 flag [FLAG_FREED] = is_freed;
616     flag [FLAG_REMOVED] = is_removed;
617 elmex 1.1
618 root 1.11 /* Copy over key_values, if any. */
619 root 1.137 if (src.key_values)
620 root 1.14 {
621 root 1.23 key_value *tail = 0;
622 root 1.137 key_values = 0;
623 elmex 1.1
624 root 1.137 for (key_value *i = src.key_values; i; i = i->next)
625 root 1.11 {
626     key_value *new_link = new key_value;
627 root 1.8
628 root 1.24 new_link->next = 0;
629     new_link->key = i->key;
630 root 1.11 new_link->value = i->value;
631    
632     /* Try and be clever here, too. */
633 root 1.137 if (!key_values)
634 root 1.11 {
635 root 1.137 key_values = new_link;
636 root 1.11 tail = new_link;
637 root 1.8 }
638 root 1.11 else
639     {
640     tail->next = new_link;
641     tail = new_link;
642     }
643 root 1.14 }
644     }
645 root 1.137 }
646    
647     /*
648     * copy_to first frees everything allocated by the dst object,
649     * and then copies the contents of itself into the second
650     * object, allocating what needs to be allocated. Basically, any
651     * data that is malloc'd needs to be re-malloc/copied. Otherwise,
652     * if the first object is freed, the pointers in the new object
653     * will point at garbage.
654     */
655     void
656     object::copy_to (object *dst)
657     {
658     *dst = *this;
659    
660     if (speed < 0)
661 root 1.185 dst->speed_left -= rndm ();
662 root 1.2
663 root 1.87 dst->set_speed (dst->speed);
664 elmex 1.1 }
665    
666 root 1.133 void
667     object::instantiate ()
668     {
669     if (!uuid.seq) // HACK
670 root 1.202 uuid = UUID::gen ();
671 root 1.133
672     speed_left = -0.1f;
673     /* copy the body_info to the body_used - this is only really
674     * need for monsters, but doesn't hurt to do it for everything.
675     * by doing so, when a monster is created, it has good starting
676     * values for the body_used info, so when items are created
677     * for it, they can be properly equipped.
678     */
679 root 1.145 for (int i = NUM_BODY_LOCATIONS; i--; )
680     slot[i].used = slot[i].info;
681 root 1.133
682     attachable::instantiate ();
683     }
684    
685 root 1.65 object *
686     object::clone ()
687     {
688     object *neu = create ();
689     copy_to (neu);
690     return neu;
691     }
692    
693 elmex 1.1 /*
694     * If an object with the IS_TURNABLE() flag needs to be turned due
695     * to the closest player being on the other side, this function can
696     * be called to update the face variable, _and_ how it looks on the map.
697     */
698 root 1.24 void
699     update_turn_face (object *op)
700     {
701 root 1.96 if (!QUERY_FLAG (op, FLAG_IS_TURNABLE) || !op->arch)
702 root 1.24 return;
703 root 1.96
704 root 1.24 SET_ANIMATION (op, op->direction);
705     update_object (op, UP_OBJ_FACE);
706 elmex 1.1 }
707    
708     /*
709     * Updates the speed of an object. If the speed changes from 0 to another
710     * value, or vice versa, then add/remove the object from the active list.
711     * This function needs to be called whenever the speed of an object changes.
712     */
713 root 1.24 void
714 root 1.87 object::set_speed (float speed)
715 root 1.24 {
716 root 1.87 if (flag [FLAG_FREED] && speed)
717 root 1.24 {
718 root 1.87 LOG (llevError, "Object %s is freed but has speed.\n", &name);
719     speed = 0;
720 elmex 1.1 }
721 root 1.31
722 root 1.87 this->speed = speed;
723    
724 elmex 1.97 if (has_active_speed ())
725 root 1.98 activate ();
726 root 1.24 else
727 root 1.98 deactivate ();
728 elmex 1.1 }
729    
730     /*
731 root 1.75 * update_object() updates the the map.
732 elmex 1.1 * It takes into account invisible objects (and represent squares covered
733     * by invisible objects by whatever is below them (unless it's another
734     * invisible object, etc...)
735     * If the object being updated is beneath a player, the look-window
736     * of that player is updated (this might be a suboptimal way of
737     * updating that window, though, since update_object() is called _often_)
738     *
739     * action is a hint of what the caller believes need to be done.
740     * current action are:
741     * UP_OBJ_INSERT: op was inserted
742     * UP_OBJ_REMOVE: op was removed
743     * UP_OBJ_CHANGE: object has somehow changed. In this case, we always update
744     * as that is easier than trying to look at what may have changed.
745     * UP_OBJ_FACE: only the objects face has changed.
746     */
747 root 1.24 void
748     update_object (object *op, int action)
749     {
750     if (op == NULL)
751     {
752     /* this should never happen */
753     LOG (llevDebug, "update_object() called for NULL object.\n");
754     return;
755 elmex 1.1 }
756 root 1.24
757 root 1.75 if (op->env)
758 root 1.24 {
759     /* Animation is currently handled by client, so nothing
760     * to do in this case.
761     */
762     return;
763 elmex 1.1 }
764    
765 root 1.24 /* If the map is saving, don't do anything as everything is
766     * going to get freed anyways.
767     */
768     if (!op->map || op->map->in_memory == MAP_SAVING)
769     return;
770    
771     /* make sure the object is within map boundaries */
772 root 1.83 if (op->x < 0 || op->x >= op->map->width || op->y < 0 || op->y >= op->map->height)
773 root 1.24 {
774     LOG (llevError, "update_object() called for object out of map!\n");
775 elmex 1.1 #ifdef MANY_CORES
776 root 1.24 abort ();
777 elmex 1.1 #endif
778 root 1.24 return;
779 elmex 1.1 }
780    
781 root 1.76 mapspace &m = op->ms ();
782 elmex 1.1
783 root 1.99 if (!(m.flags_ & P_UPTODATE))
784 root 1.75 /* nop */;
785     else if (action == UP_OBJ_INSERT)
786     {
787     // this is likely overkill, TODO: revisit (schmorp)
788     if ((QUERY_FLAG (op, FLAG_BLOCKSVIEW) && !(m.flags_ & P_BLOCKSVIEW))
789     || (QUERY_FLAG (op, FLAG_NO_MAGIC) && !(m.flags_ & P_NO_MAGIC))
790     || (op->type == PLAYER && !(m.flags_ & P_PLAYER))
791     || (op->type == SAFE_GROUND && !(m.flags_ & P_SAFE))
792     || (QUERY_FLAG (op, FLAG_ALIVE) && !(m.flags_ & P_IS_ALIVE))
793     || (QUERY_FLAG (op, FLAG_DAMNED) && !(m.flags_ & P_NO_CLERIC))
794     || (m.move_on | op->move_on ) != m.move_on
795     || (m.move_off | op->move_off ) != m.move_off
796     || (m.move_slow | op->move_slow) != m.move_slow
797     /* This isn't perfect, but I don't expect a lot of objects to
798     * to have move_allow right now.
799     */
800     || ((m.move_block | op->move_block) & ~op->move_allow) != m.move_block
801     || 1) // the above is not strong enough a test to skip updating. los maybe? TODO (Schmorp)
802 root 1.99 m.flags_ = 0;
803 root 1.75 }
804     /* if the object is being removed, we can't make intelligent
805     * decisions, because remove_ob can't really pass the object
806     * that is being removed.
807     */
808 root 1.24 else if (action == UP_OBJ_CHANGE || action == UP_OBJ_REMOVE)
809 root 1.99 m.flags_ = 0;
810 root 1.24 else if (action == UP_OBJ_FACE)
811 root 1.29 /* Nothing to do for that case */ ;
812 root 1.24 else
813 root 1.27 LOG (llevError, "update_object called with invalid action: %d\n", action);
814 elmex 1.1
815 root 1.75 if (op->more)
816 root 1.24 update_object (op->more, action);
817 elmex 1.1 }
818    
819 root 1.21 object::object ()
820     {
821 root 1.22 SET_FLAG (this, FLAG_REMOVED);
822    
823     expmul = 1.0;
824     face = blank_face;
825     }
826    
827     object::~object ()
828     {
829 root 1.121 unlink ();
830 root 1.119
831 root 1.22 free_key_values (this);
832     }
833    
834 root 1.112 static int object_count;
835    
836 root 1.24 void object::link ()
837 root 1.22 {
838 root 1.112 assert (!index);//D
839 root 1.202 uuid = UUID::gen ();
840 root 1.112 count = ++object_count;
841 root 1.21
842 root 1.109 refcnt_inc ();
843 root 1.108 objects.insert (this);
844 root 1.21 }
845    
846 root 1.24 void object::unlink ()
847 root 1.21 {
848 root 1.121 if (!index)
849     return;
850    
851 root 1.108 objects.erase (this);
852 root 1.109 refcnt_dec ();
853 root 1.98 }
854    
855 root 1.96 void
856 root 1.98 object::activate ()
857 root 1.96 {
858 root 1.98 /* If already on active list, don't do anything */
859 root 1.108 if (active)
860 root 1.98 return;
861    
862 elmex 1.97 if (has_active_speed ())
863 root 1.108 actives.insert (this);
864 root 1.98 }
865 root 1.96
866 root 1.98 void
867     object::activate_recursive ()
868     {
869     activate ();
870    
871 root 1.104 for (object *op = inv; op; op = op->below)
872 root 1.98 op->activate_recursive ();
873 root 1.96 }
874    
875     /* This function removes object 'op' from the list of active
876     * objects.
877     * This should only be used for style maps or other such
878     * reference maps where you don't want an object that isn't
879     * in play chewing up cpu time getting processed.
880     * The reverse of this is to call update_ob_speed, which
881     * will do the right thing based on the speed of the object.
882     */
883     void
884 root 1.98 object::deactivate ()
885 root 1.96 {
886     /* If not on the active list, nothing needs to be done */
887 root 1.108 if (!active)
888 root 1.96 return;
889    
890 root 1.108 actives.erase (this);
891 root 1.98 }
892 root 1.96
893 root 1.98 void
894     object::deactivate_recursive ()
895     {
896 root 1.104 for (object *op = inv; op; op = op->below)
897 root 1.98 op->deactivate_recursive ();
898    
899     deactivate ();
900 root 1.96 }
901    
902 root 1.106 void
903     object::set_flag_inv (int flag, int value)
904     {
905     for (object *op = inv; op; op = op->below)
906     {
907     op->flag [flag] = value;
908     op->set_flag_inv (flag, value);
909     }
910     }
911    
912 root 1.89 /*
913     * Remove and free all objects in the inventory of the given object.
914     * object.c ?
915     */
916     void
917     object::destroy_inv (bool drop_to_ground)
918     {
919 root 1.94 // need to check first, because the checks below might segfault
920     // as we might be on an invalid mapspace and crossfire code
921     // is too buggy to ensure that the inventory is empty.
922 root 1.217 // corollary: if you create arrows etc. with stuff in its inventory,
923 root 1.94 // cf will crash below with off-map x and y
924     if (!inv)
925     return;
926    
927 root 1.89 /* Only if the space blocks everything do we not process -
928     * if some form of movement is allowed, let objects
929     * drop on that space.
930     */
931 root 1.92 if (!drop_to_ground
932     || !map
933 root 1.206 || map->in_memory != MAP_ACTIVE
934 root 1.122 || map->nodrop
935 root 1.95 || ms ().move_block == MOVE_ALL)
936 root 1.89 {
937     while (inv)
938 root 1.92 {
939 root 1.217 inv->destroy_inv (false);
940 root 1.92 inv->destroy ();
941     }
942 root 1.89 }
943     else
944     { /* Put objects in inventory onto this space */
945     while (inv)
946     {
947     object *op = inv;
948    
949     if (op->flag [FLAG_STARTEQUIP]
950     || op->flag [FLAG_NO_DROP]
951     || op->type == RUNE
952     || op->type == TRAP
953 root 1.110 || op->flag [FLAG_IS_A_TEMPLATE]
954     || op->flag [FLAG_DESTROY_ON_DEATH])
955 root 1.217 op->destroy (true);
956 root 1.89 else
957 root 1.93 map->insert (op, x, y);
958 root 1.89 }
959     }
960     }
961    
962 root 1.21 object *object::create ()
963     {
964 root 1.42 object *op = new object;
965 root 1.22 op->link ();
966     return op;
967 root 1.21 }
968 elmex 1.1
969 root 1.82 void
970     object::do_destroy ()
971 root 1.14 {
972 root 1.82 if (flag [FLAG_IS_LINKED])
973     remove_button_link (this);
974 root 1.29
975 root 1.82 if (flag [FLAG_FRIENDLY])
976 root 1.140 remove_friendly_object (this);
977 root 1.32
978 root 1.213 remove ();
979    
980     attachable::do_destroy ();
981 root 1.14
982 root 1.112 deactivate ();
983     unlink ();
984 root 1.92
985 root 1.82 flag [FLAG_FREED] = 1;
986 root 1.14
987 root 1.57 // hack to ensure that freed objects still have a valid map
988     {
989     static maptile *freed_map; // freed objects are moved here to avoid crashes
990    
991     if (!freed_map)
992     {
993     freed_map = new maptile;
994    
995 root 1.186 freed_map->path = "<freed objects map>";
996 root 1.57 freed_map->name = "/internal/freed_objects_map";
997     freed_map->width = 3;
998     freed_map->height = 3;
999 root 1.201 freed_map->nodrop = 1;
1000 root 1.57
1001 root 1.96 freed_map->alloc ();
1002 root 1.206 freed_map->in_memory = MAP_ACTIVE;
1003 root 1.57 }
1004    
1005     map = freed_map;
1006     x = 1;
1007     y = 1;
1008     }
1009    
1010 root 1.88 if (more)
1011     {
1012     more->destroy ();
1013     more = 0;
1014     }
1015 root 1.82
1016 root 1.162 head = 0;
1017    
1018     // clear those pointers that likely might cause circular references
1019     owner = 0;
1020     enemy = 0;
1021     attacked_by = 0;
1022     current_weapon = 0;
1023 root 1.82 }
1024    
1025     void
1026     object::destroy (bool destroy_inventory)
1027     {
1028     if (destroyed ())
1029     return;
1030    
1031 root 1.219 if (!is_head () && !head->destroyed ())
1032     {
1033     LOG (llevError | logBacktrace, "tried to destroy the tail of an object");
1034     head->destroy (destroy_inventory);
1035     }
1036    
1037 root 1.217 destroy_inv (!destroy_inventory);
1038 root 1.22
1039 root 1.173 if (is_head ())
1040     if (sound_destroy)
1041     play_sound (sound_destroy);
1042     else if (flag [FLAG_MONSTER])
1043     play_sound (sound_find ("monster_destroy")); // quick hack, too lazy to create a generic mechanism
1044 root 1.169
1045 root 1.82 attachable::destroy ();
1046 elmex 1.1 }
1047    
1048 root 1.63 /* op->remove ():
1049 elmex 1.1 * This function removes the object op from the linked list of objects
1050     * which it is currently tied to. When this function is done, the
1051     * object will have no environment. If the object previously had an
1052     * environment, the x and y coordinates will be updated to
1053     * the previous environment.
1054     */
1055 root 1.24 void
1056 root 1.128 object::do_remove ()
1057 root 1.24 {
1058 root 1.45 object *tmp, *last = 0;
1059     object *otmp;
1060 root 1.26
1061 root 1.213 if (flag [FLAG_REMOVED])
1062 root 1.29 return;
1063 root 1.24
1064 root 1.82 INVOKE_OBJECT (REMOVE, this);
1065 root 1.26
1066 root 1.213 if (object *pl = visible_to ())
1067     esrv_del_item (pl->contr, count);
1068    
1069     flag [FLAG_REMOVED] = true;
1070    
1071 root 1.59 if (more)
1072     more->remove ();
1073 root 1.24
1074     /*
1075     * In this case, the object to be removed is in someones
1076     * inventory.
1077     */
1078 root 1.59 if (env)
1079 root 1.24 {
1080 root 1.208 adjust_weight (env, -total_weight ());
1081 root 1.24
1082 root 1.208 *(above ? &above->below : &env->inv) = below;
1083 root 1.24
1084 root 1.96 if (below)
1085 root 1.59 below->above = above;
1086 root 1.24
1087     /* we set up values so that it could be inserted into
1088     * the map, but we don't actually do that - it is up
1089     * to the caller to decide what we want to do.
1090     */
1091 root 1.208 map = env->map;
1092     x = env->x;
1093     y = env->y;
1094     above = 0;
1095     below = 0;
1096     env = 0;
1097    
1098     /* NO_FIX_PLAYER is set when a great many changes are being
1099     * made to players inventory. If set, avoiding the call
1100     * to save cpu time.
1101     */
1102     if ((otmp = in_player ()) && otmp->contr && !QUERY_FLAG (otmp, FLAG_NO_FIX_PLAYER))
1103     otmp->update_stats ();
1104 root 1.59 }
1105     else if (map)
1106     {
1107 root 1.96 if (type == PLAYER)
1108     {
1109 root 1.130 // leaving a spot always closes any open container on the ground
1110     if (container && !container->env)
1111     // this causes spurious floorbox updates, but it ensures
1112     // that the CLOSE event is being sent.
1113     close_container ();
1114    
1115 root 1.96 --map->players;
1116 root 1.100 map->touch ();
1117 root 1.96 }
1118    
1119 root 1.98 map->dirty = true;
1120 root 1.117 mapspace &ms = this->ms ();
1121 elmex 1.1
1122 root 1.29 /* link the object above us */
1123 root 1.59 if (above)
1124     above->below = below;
1125 root 1.29 else
1126 root 1.117 ms.top = below; /* we were top, set new top */
1127 root 1.24
1128 root 1.29 /* Relink the object below us, if there is one */
1129 root 1.59 if (below)
1130     below->above = above;
1131 root 1.29 else
1132     {
1133     /* Nothing below, which means we need to relink map object for this space
1134     * use translated coordinates in case some oddness with map tiling is
1135     * evident
1136     */
1137 root 1.59 if (GET_MAP_OB (map, x, y) != this)
1138 root 1.117 LOG (llevError, "remove_ob: GET_MAP_OB does not return object to be removed even though it appears to be on the bottom? %s\n", debug_desc ());
1139 elmex 1.1
1140 root 1.117 ms.bot = above; /* goes on above it. */
1141 root 1.8 }
1142 root 1.26
1143 root 1.59 above = 0;
1144     below = 0;
1145 root 1.26
1146 root 1.59 if (map->in_memory == MAP_SAVING)
1147 root 1.29 return;
1148 elmex 1.1
1149 root 1.82 int check_walk_off = !flag [FLAG_NO_APPLY];
1150 elmex 1.1
1151 root 1.175 if (object *pl = ms.player ())
1152     {
1153     if (pl->container == this)
1154     /* If a container that the player is currently using somehow gets
1155     * removed (most likely destroyed), update the player view
1156     * appropriately.
1157     */
1158     pl->close_container ();
1159    
1160 root 1.218 //TODO: the floorbox prev/next might need updating
1161     esrv_del_item (pl->contr, count);
1162 root 1.175 }
1163    
1164 root 1.117 for (tmp = ms.bot; tmp; tmp = tmp->above)
1165 root 1.24 {
1166 root 1.29 /* No point updating the players look faces if he is the object
1167     * being removed.
1168 root 1.24 */
1169 root 1.29
1170 root 1.96 /* See if object moving off should effect something */
1171 root 1.50 if (check_walk_off
1172 root 1.59 && ((move_type & tmp->move_off)
1173     && (move_type & ~tmp->move_off & ~tmp->move_block) == 0))
1174 root 1.29 {
1175 elmex 1.72 move_apply (tmp, this, 0);
1176 root 1.24
1177 root 1.59 if (destroyed ())
1178 root 1.50 LOG (llevError, "BUG: remove_ob(): name %s, destroyed leaving object\n", tmp->debug_desc ());
1179 root 1.8 }
1180    
1181 root 1.29 last = tmp;
1182     }
1183 root 1.26
1184 root 1.96 /* last == NULL if there are no objects on this space */
1185     //TODO: this makes little sense, why only update the topmost object?
1186 root 1.59 if (!last)
1187 root 1.99 map->at (x, y).flags_ = 0;
1188 root 1.29 else
1189     update_object (last, UP_OBJ_REMOVE);
1190 root 1.26
1191 root 1.82 if (flag [FLAG_BLOCKSVIEW] || glow_radius)
1192 root 1.59 update_all_los (map, x, y);
1193 elmex 1.1 }
1194     }
1195    
1196     /*
1197     * merge_ob(op,top):
1198     *
1199     * This function goes through all objects below and including top, and
1200     * merges op to the first matching object.
1201     * If top is NULL, it is calculated.
1202     * Returns pointer to object if it succeded in the merge, otherwise NULL
1203     */
1204 root 1.24 object *
1205     merge_ob (object *op, object *top)
1206     {
1207     if (!op->nrof)
1208 elmex 1.1 return 0;
1209 root 1.29
1210 root 1.194 if (!top)
1211 root 1.82 for (top = op; top && top->above; top = top->above)
1212     ;
1213 root 1.29
1214 root 1.82 for (; top; top = top->below)
1215 root 1.214 if (object::can_merge (op, top))
1216     {
1217     top->nrof += op->nrof;
1218    
1219     if (object *pl = top->visible_to ())
1220     esrv_update_item (UPD_NROF, pl, top);
1221    
1222     op->weight = 0; // cancel the addition above
1223     op->carrying = 0; // must be 0 already
1224 root 1.66
1225 root 1.214 op->destroy (1);
1226 root 1.24
1227 root 1.214 return top;
1228     }
1229 root 1.29
1230 root 1.45 return 0;
1231 elmex 1.1 }
1232    
1233 root 1.138 void
1234     object::expand_tail ()
1235     {
1236     if (more)
1237     return;
1238    
1239     object *prev = this;
1240    
1241 root 1.160 for (archetype *at = (archetype *)arch->more; at; at = (archetype *)at->more)
1242 root 1.138 {
1243     object *op = arch_to_object (at);
1244    
1245     op->name = name;
1246     op->name_pl = name_pl;
1247     op->title = title;
1248    
1249     op->head = this;
1250     prev->more = op;
1251    
1252     prev = op;
1253     }
1254     }
1255    
1256 elmex 1.1 /*
1257 root 1.117 * same as insert_ob_in_map except it handles separate coordinates and does a clean
1258     * job preparing multi-part monsters.
1259 elmex 1.1 */
1260 root 1.24 object *
1261 root 1.49 insert_ob_in_map_at (object *op, maptile *m, object *originator, int flag, int x, int y)
1262 root 1.24 {
1263 root 1.93 for (object *tmp = op->head_ (); tmp; tmp = tmp->more)
1264 root 1.24 {
1265 root 1.159 tmp->x = x + tmp->arch->x;
1266     tmp->y = y + tmp->arch->y;
1267 elmex 1.1 }
1268 root 1.29
1269 root 1.24 return insert_ob_in_map (op, m, originator, flag);
1270 elmex 1.1 }
1271    
1272     /*
1273     * insert_ob_in_map (op, map, originator, flag):
1274     * This function inserts the object in the two-way linked list
1275     * which represents what is on a map.
1276     * The second argument specifies the map, and the x and y variables
1277     * in the object about to be inserted specifies the position.
1278     *
1279     * originator: Player, monster or other object that caused 'op' to be inserted
1280     * into 'map'. May be NULL.
1281     *
1282     * flag is a bitmask about special things to do (or not do) when this
1283     * function is called. see the object.h file for the INS_ values.
1284     * Passing 0 for flag gives proper default values, so flag really only needs
1285     * to be set if special handling is needed.
1286     *
1287     * Return value:
1288     * new object if 'op' was merged with other object
1289     * NULL if 'op' was destroyed
1290     * just 'op' otherwise
1291     */
1292 root 1.24 object *
1293 root 1.49 insert_ob_in_map (object *op, maptile *m, object *originator, int flag)
1294 elmex 1.1 {
1295 root 1.138 assert (!op->flag [FLAG_FREED]);
1296    
1297 root 1.117 op->remove ();
1298    
1299 root 1.187 /* Ideally, the caller figures this out. However, it complicates a lot
1300     * of areas of callers (eg, anything that uses find_free_spot would now
1301     * need extra work
1302     */
1303     if (!xy_normalise (m, op->x, op->y))
1304 root 1.24 {
1305 root 1.217 op->destroy (1);
1306 root 1.187 return 0;
1307 elmex 1.1 }
1308 root 1.25
1309 root 1.117 if (object *more = op->more)
1310 root 1.155 if (!insert_ob_in_map (more, m, originator, flag))
1311     return 0;
1312 root 1.25
1313 root 1.24 CLEAR_FLAG (op, FLAG_REMOVED);
1314 root 1.8
1315 root 1.117 op->map = m;
1316     mapspace &ms = op->ms ();
1317 root 1.24
1318     /* this has to be done after we translate the coordinates.
1319     */
1320     if (op->nrof && !(flag & INS_NO_MERGE))
1321 root 1.155 for (object *tmp = ms.bot; tmp; tmp = tmp->above)
1322 root 1.66 if (object::can_merge (op, tmp))
1323 root 1.25 {
1324 root 1.218 // TODO: we atcually want to update tmp, not op,
1325     // but some caller surely breaks when we return tmp
1326     // from here :/
1327 root 1.25 op->nrof += tmp->nrof;
1328 root 1.208 tmp->destroy (1);
1329 root 1.25 }
1330 root 1.24
1331     CLEAR_FLAG (op, FLAG_APPLIED); /* hack for fixing F_APPLIED in items of dead people */
1332     CLEAR_FLAG (op, FLAG_INV_LOCKED);
1333 root 1.25
1334 root 1.24 if (!QUERY_FLAG (op, FLAG_ALIVE))
1335     CLEAR_FLAG (op, FLAG_NO_STEAL);
1336    
1337     if (flag & INS_BELOW_ORIGINATOR)
1338     {
1339     if (originator->map != op->map || originator->x != op->x || originator->y != op->y)
1340     {
1341     LOG (llevError, "insert_ob_in_map called with INS_BELOW_ORIGINATOR when originator not on same space!\n");
1342     abort ();
1343     }
1344 root 1.25
1345 root 1.24 op->above = originator;
1346     op->below = originator->below;
1347 root 1.25
1348 root 1.24 if (op->below)
1349     op->below->above = op;
1350     else
1351 root 1.117 ms.bot = op;
1352 root 1.25
1353 root 1.24 /* since *below* originator, no need to update top */
1354     originator->below = op;
1355 elmex 1.1 }
1356 root 1.24 else
1357     {
1358 root 1.218 object *top, *floor = NULL;
1359    
1360 root 1.117 top = ms.bot;
1361    
1362 root 1.24 /* If there are other objects, then */
1363 root 1.191 if (top)
1364 root 1.24 {
1365 root 1.96 object *last = 0;
1366 root 1.24
1367     /*
1368     * If there are multiple objects on this space, we do some trickier handling.
1369     * We've already dealt with merging if appropriate.
1370     * Generally, we want to put the new object on top. But if
1371     * flag contains INS_ABOVE_FLOOR_ONLY, once we find the last
1372     * floor, we want to insert above that and no further.
1373     * Also, if there are spell objects on this space, we stop processing
1374     * once we get to them. This reduces the need to traverse over all of
1375     * them when adding another one - this saves quite a bit of cpu time
1376     * when lots of spells are cast in one area. Currently, it is presumed
1377     * that flying non pickable objects are spell objects.
1378     */
1379 root 1.117 for (top = ms.bot; top; top = top->above)
1380 root 1.24 {
1381     if (QUERY_FLAG (top, FLAG_IS_FLOOR) || QUERY_FLAG (top, FLAG_OVERLAY_FLOOR))
1382     floor = top;
1383 root 1.26
1384 root 1.24 if (QUERY_FLAG (top, FLAG_NO_PICK) && (top->move_type & (MOVE_FLY_LOW | MOVE_FLY_HIGH)) && !QUERY_FLAG (top, FLAG_IS_FLOOR))
1385     {
1386     /* We insert above top, so we want this object below this */
1387     top = top->below;
1388     break;
1389     }
1390 root 1.26
1391 root 1.24 last = top;
1392     }
1393 root 1.26
1394 root 1.24 /* Don't want top to be NULL, so set it to the last valid object */
1395     top = last;
1396 root 1.8
1397 root 1.24 /* We let update_position deal with figuring out what the space
1398     * looks like instead of lots of conditions here.
1399     * makes things faster, and effectively the same result.
1400     */
1401    
1402     /* Have object 'fall below' other objects that block view.
1403 root 1.135 * Unless those objects are exits.
1404 root 1.24 * If INS_ON_TOP is used, don't do this processing
1405     * Need to find the object that in fact blocks view, otherwise
1406     * stacking is a bit odd.
1407     */
1408 root 1.117 if (!(flag & INS_ON_TOP)
1409     && ms.flags () & P_BLOCKSVIEW
1410 root 1.135 && (op->face && !faces [op->face].visibility))
1411 root 1.24 {
1412     for (last = top; last != floor; last = last->below)
1413     if (QUERY_FLAG (last, FLAG_BLOCKSVIEW) && (last->type != EXIT))
1414     break;
1415 root 1.117
1416 root 1.24 /* Check to see if we found the object that blocks view,
1417     * and make sure we have a below pointer for it so that
1418     * we can get inserted below this one, which requires we
1419     * set top to the object below us.
1420     */
1421     if (last && last->below && last != floor)
1422     top = last->below;
1423 root 1.8 }
1424 root 1.24 } /* If objects on this space */
1425 root 1.25
1426 root 1.24 if (flag & INS_ABOVE_FLOOR_ONLY)
1427     top = floor;
1428    
1429     /* Top is the object that our object (op) is going to get inserted above.
1430     */
1431    
1432     /* First object on this space */
1433     if (!top)
1434     {
1435 root 1.117 op->above = ms.bot;
1436 root 1.25
1437 root 1.24 if (op->above)
1438     op->above->below = op;
1439 root 1.25
1440 root 1.96 op->below = 0;
1441 root 1.117 ms.bot = op;
1442 root 1.24 }
1443     else
1444     { /* get inserted into the stack above top */
1445     op->above = top->above;
1446 root 1.25
1447 root 1.24 if (op->above)
1448     op->above->below = op;
1449 root 1.25
1450 root 1.24 op->below = top;
1451     top->above = op;
1452     }
1453 root 1.25
1454 root 1.96 if (!op->above)
1455 root 1.117 ms.top = op;
1456 root 1.24 } /* else not INS_BELOW_ORIGINATOR */
1457 root 1.8
1458 root 1.24 if (op->type == PLAYER)
1459 root 1.96 {
1460     op->contr->do_los = 1;
1461     ++op->map->players;
1462 root 1.100 op->map->touch ();
1463 root 1.96 }
1464 root 1.24
1465 root 1.98 op->map->dirty = true;
1466    
1467 root 1.191 if (object *pl = ms.player ())
1468 root 1.218 //TODO: the floorbox prev/next might need updating
1469 root 1.217 esrv_send_item (pl, op);
1470 root 1.24
1471     /* If this object glows, it may affect lighting conditions that are
1472     * visible to others on this map. But update_all_los is really
1473     * an inefficient way to do this, as it means los for all players
1474     * on the map will get recalculated. The players could very well
1475     * be far away from this change and not affected in any way -
1476     * this should get redone to only look for players within range,
1477 root 1.99 * or just updating the P_UPTODATE for spaces within this area
1478 root 1.24 * of effect may be sufficient.
1479     */
1480 root 1.84 if (op->map->darkness && (op->glow_radius != 0))
1481 root 1.24 update_all_los (op->map, op->x, op->y);
1482    
1483     /* updates flags (blocked, alive, no magic, etc) for this map space */
1484     update_object (op, UP_OBJ_INSERT);
1485    
1486 root 1.82 INVOKE_OBJECT (INSERT, op);
1487    
1488 root 1.24 /* Don't know if moving this to the end will break anything. However,
1489 root 1.70 * we want to have floorbox_update called before calling this.
1490 root 1.24 *
1491     * check_move_on() must be after this because code called from
1492     * check_move_on() depends on correct map flags (so functions like
1493     * blocked() and wall() work properly), and these flags are updated by
1494     * update_object().
1495     */
1496    
1497     /* if this is not the head or flag has been passed, don't check walk on status */
1498 root 1.155 if (!(flag & INS_NO_WALK_ON) && op->head_ () == op)
1499 root 1.24 {
1500     if (check_move_on (op, originator))
1501 root 1.82 return 0;
1502 elmex 1.1
1503 root 1.24 /* If we are a multi part object, lets work our way through the check
1504     * walk on's.
1505     */
1506 root 1.155 for (object *tmp = op->more; tmp; tmp = tmp->more)
1507 root 1.24 if (check_move_on (tmp, originator))
1508 root 1.82 return 0;
1509 elmex 1.1 }
1510 root 1.25
1511 root 1.24 return op;
1512 elmex 1.1 }
1513    
1514     /* this function inserts an object in the map, but if it
1515 root 1.75 * finds an object of its own type, it'll remove that one first.
1516     * op is the object to insert it under: supplies x and the map.
1517 elmex 1.1 */
1518 root 1.24 void
1519     replace_insert_ob_in_map (const char *arch_string, object *op)
1520     {
1521     /* first search for itself and remove any old instances */
1522 elmex 1.1
1523 root 1.208 for (object *tmp = op->ms ().bot; tmp; tmp = tmp->above)
1524 root 1.158 if (!strcmp (tmp->arch->archname, arch_string)) /* same archetype */
1525 root 1.208 tmp->destroy (1);
1526    
1527     object *tmp = arch_to_object (archetype::find (arch_string));
1528 elmex 1.1
1529 root 1.208 tmp->x = op->x;
1530     tmp->y = op->y;
1531 elmex 1.1
1532 root 1.208 insert_ob_in_map (tmp, op->map, op, 0);
1533 root 1.24 }
1534 elmex 1.1
1535 root 1.93 object *
1536     object::insert_at (object *where, object *originator, int flags)
1537     {
1538 root 1.205 if (where->env)
1539     return where->env->insert (this);
1540     else
1541     return where->map->insert (this, where->x, where->y, originator, flags);
1542 root 1.93 }
1543    
1544 elmex 1.1 /*
1545 root 1.209 * decrease(object, number) decreases a specified number from
1546 root 1.208 * the amount of an object. If the amount reaches 0, the object
1547 elmex 1.1 * is subsequently removed and freed.
1548     *
1549     * Return value: 'op' if something is left, NULL if the amount reached 0
1550     */
1551 root 1.208 bool
1552 root 1.209 object::decrease (sint32 nr)
1553 elmex 1.1 {
1554 root 1.212 if (!nr)
1555     return true;
1556    
1557 root 1.208 nr = min (nr, nrof);
1558 elmex 1.1
1559 root 1.208 nrof -= nr;
1560 root 1.24
1561 root 1.208 if (nrof)
1562 elmex 1.1 {
1563 root 1.208 adjust_weight (env, -weight * nr); // carrying == 0
1564 elmex 1.1
1565 root 1.212 if (object *pl = visible_to ())
1566     esrv_update_item (UPD_NROF, pl, this);
1567 root 1.29
1568 root 1.212 return true;
1569 elmex 1.1 }
1570 root 1.24 else
1571     {
1572 root 1.212 destroy (1);
1573     return false;
1574 elmex 1.1 }
1575     }
1576    
1577 root 1.209 /*
1578 root 1.210 * split(ob,nr) splits up ob into two parts. The part which
1579 root 1.209 * is returned contains nr objects, and the remaining parts contains
1580 root 1.210 * the rest (or is removed and returned if that number is 0).
1581     * On failure, NULL is returned.
1582 root 1.209 */
1583 root 1.208 object *
1584 root 1.209 object::split (sint32 nr)
1585 root 1.208 {
1586 root 1.212 int have = number_of ();
1587    
1588     if (have < nr)
1589 root 1.209 return 0;
1590 root 1.212 else if (have == nr)
1591 root 1.209 {
1592     remove ();
1593     return this;
1594     }
1595     else
1596     {
1597     decrease (nr);
1598    
1599     object *op = object_create_clone (this);
1600     op->nrof = nr;
1601     return op;
1602     }
1603     }
1604    
1605 root 1.24 object *
1606     insert_ob_in_ob (object *op, object *where)
1607     {
1608 root 1.59 if (!where)
1609 root 1.24 {
1610 root 1.53 char *dump = dump_object (op);
1611     LOG (llevError, "Trying to put object in NULL.\n%s\n", dump);
1612     free (dump);
1613 root 1.24 return op;
1614     }
1615 root 1.29
1616 root 1.154 if (where->head_ () != where)
1617 root 1.24 {
1618 root 1.153 LOG (llevError | logBacktrace, "Warning: Tried to insert object into wrong part of multipart object.\n");
1619 root 1.24 where = where->head;
1620     }
1621 root 1.29
1622 root 1.59 return where->insert (op);
1623     }
1624    
1625     /*
1626     * env->insert (op)
1627     * This function inserts the object op in the linked list
1628     * inside the object environment.
1629     *
1630     * The function returns now pointer to inserted item, and return value can
1631     * be != op, if items are merged. -Tero
1632     */
1633     object *
1634     object::insert (object *op)
1635     {
1636 root 1.24 if (op->more)
1637     {
1638     LOG (llevError, "Tried to insert multipart object %s (%d)\n", &op->name, op->count);
1639     return op;
1640     }
1641 root 1.29
1642 root 1.208 op->remove ();
1643    
1644     op->flag [FLAG_OBJ_ORIGINAL] = 0;
1645 root 1.182
1646 root 1.24 if (op->nrof)
1647 root 1.208 for (object *tmp = inv; tmp; tmp = tmp->below)
1648     if (object::can_merge (tmp, op))
1649     {
1650     /* return the original object and remove inserted object
1651     (client needs the original object) */
1652     tmp->nrof += op->nrof;
1653 root 1.214
1654     if (object *pl = tmp->visible_to ())
1655     esrv_update_item (UPD_NROF, pl, tmp);
1656    
1657 root 1.210 adjust_weight (this, op->total_weight ());
1658    
1659 root 1.208 op->destroy (1);
1660     op = tmp;
1661     goto inserted;
1662     }
1663    
1664     op->owner = 0; // it's his/hers now. period.
1665     op->map = 0;
1666     op->x = 0;
1667     op->y = 0;
1668    
1669     op->above = 0;
1670     op->below = inv;
1671     op->env = this;
1672    
1673     if (inv)
1674     inv->above = op;
1675 root 1.24
1676 root 1.208 inv = op;
1677 elmex 1.1
1678 root 1.208 op->flag [FLAG_REMOVED] = 0;
1679 elmex 1.1
1680 root 1.214 if (object *pl = op->visible_to ())
1681     esrv_send_item (pl, op);
1682    
1683 root 1.208 adjust_weight (this, op->total_weight ());
1684 elmex 1.1
1685 root 1.208 inserted:
1686 elmex 1.1 /* reset the light list and los of the players on the map */
1687 root 1.208 if (op->glow_radius && map && map->darkness)
1688     update_all_los (map, x, y);
1689 elmex 1.1
1690 root 1.214 // if this is a player's inventory, update stats
1691     if (type == PLAYER && !flag [FLAG_NO_FIX_PLAYER])
1692     update_stats ();
1693 root 1.59
1694 root 1.82 INVOKE_OBJECT (INSERT, this);
1695    
1696 elmex 1.1 return op;
1697     }
1698    
1699     /*
1700     * Checks if any objects has a move_type that matches objects
1701     * that effect this object on this space. Call apply() to process
1702     * these events.
1703     *
1704     * Any speed-modification due to SLOW_MOVE() of other present objects
1705     * will affect the speed_left of the object.
1706     *
1707     * originator: Player, monster or other object that caused 'op' to be inserted
1708     * into 'map'. May be NULL.
1709     *
1710     * Return value: 1 if 'op' was destroyed, 0 otherwise.
1711     *
1712     * 4-21-95 added code to check if appropriate skill was readied - this will
1713     * permit faster movement by the player through this terrain. -b.t.
1714     *
1715     * MSW 2001-07-08: Check all objects on space, not just those below
1716     * object being inserted. insert_ob_in_map may not put new objects
1717     * on top.
1718     */
1719 root 1.24 int
1720     check_move_on (object *op, object *originator)
1721 elmex 1.1 {
1722 root 1.48 object *tmp;
1723 root 1.49 maptile *m = op->map;
1724 root 1.48 int x = op->x, y = op->y;
1725 root 1.26
1726 root 1.48 MoveType move_on, move_slow, move_block;
1727 root 1.24
1728     if (QUERY_FLAG (op, FLAG_NO_APPLY))
1729     return 0;
1730    
1731     move_on = GET_MAP_MOVE_ON (op->map, op->x, op->y);
1732     move_slow = GET_MAP_MOVE_SLOW (op->map, op->x, op->y);
1733     move_block = GET_MAP_MOVE_BLOCK (op->map, op->x, op->y);
1734    
1735     /* if nothing on this space will slow op down or be applied,
1736     * no need to do checking below. have to make sure move_type
1737     * is set, as lots of objects don't have it set - we treat that
1738     * as walking.
1739     */
1740     if (op->move_type && !(op->move_type & move_on) && !(op->move_type & move_slow))
1741     return 0;
1742 elmex 1.1
1743 root 1.24 /* This is basically inverse logic of that below - basically,
1744     * if the object can avoid the move on or slow move, they do so,
1745     * but can't do it if the alternate movement they are using is
1746     * blocked. Logic on this seems confusing, but does seem correct.
1747     */
1748     if ((op->move_type & ~move_on & ~move_block) != 0 && (op->move_type & ~move_slow & ~move_block) != 0)
1749     return 0;
1750    
1751     /* The objects have to be checked from top to bottom.
1752     * Hence, we first go to the top:
1753     */
1754    
1755 root 1.104 for (tmp = op->ms ().bot; tmp && tmp->above; tmp = tmp->above)
1756 root 1.24 {
1757     /* Trim the search when we find the first other spell effect
1758     * this helps performance so that if a space has 50 spell objects,
1759     * we don't need to check all of them.
1760     */
1761     if ((tmp->move_type & MOVE_FLY_LOW) && QUERY_FLAG (tmp, FLAG_NO_PICK))
1762     break;
1763     }
1764 root 1.26
1765     for (; tmp; tmp = tmp->below)
1766 root 1.24 {
1767     if (tmp == op)
1768     continue; /* Can't apply yourself */
1769 elmex 1.1
1770 root 1.24 /* Check to see if one of the movement types should be slowed down.
1771     * Second check makes sure that the movement types not being slowed
1772     * (~slow_move) is not blocked on this space - just because the
1773     * space doesn't slow down swimming (for example), if you can't actually
1774     * swim on that space, can't use it to avoid the penalty.
1775     */
1776     if (!QUERY_FLAG (op, FLAG_WIZPASS))
1777     {
1778     if ((!op->move_type && tmp->move_slow & MOVE_WALK) ||
1779     ((op->move_type & tmp->move_slow) && (op->move_type & ~tmp->move_slow & ~tmp->move_block) == 0))
1780     {
1781 elmex 1.1
1782 root 1.29 float
1783 root 1.120 diff = tmp->move_slow_penalty * fabs (op->speed);
1784 elmex 1.1
1785 root 1.24 if (op->type == PLAYER)
1786 root 1.26 if ((QUERY_FLAG (tmp, FLAG_IS_HILLY) && find_skill_by_number (op, SK_CLIMBING)) ||
1787     (QUERY_FLAG (tmp, FLAG_IS_WOODED) && find_skill_by_number (op, SK_WOODSMAN)))
1788     diff /= 4.0;
1789    
1790 root 1.24 op->speed_left -= diff;
1791 root 1.8 }
1792     }
1793 elmex 1.1
1794 root 1.24 /* Basically same logic as above, except now for actual apply. */
1795     if ((!op->move_type && tmp->move_on & MOVE_WALK) ||
1796     ((op->move_type & tmp->move_on) && (op->move_type & ~tmp->move_on & ~tmp->move_block) == 0))
1797     {
1798 elmex 1.72 move_apply (tmp, op, originator);
1799 root 1.24
1800 root 1.48 if (op->destroyed ())
1801 root 1.24 return 1;
1802    
1803     /* what the person/creature stepped onto has moved the object
1804     * someplace new. Don't process any further - if we did,
1805     * have a feeling strange problems would result.
1806     */
1807     if (op->map != m || op->x != x || op->y != y)
1808     return 0;
1809 root 1.8 }
1810 elmex 1.1 }
1811 root 1.26
1812 root 1.24 return 0;
1813 elmex 1.1 }
1814    
1815     /*
1816     * present_arch(arch, map, x, y) searches for any objects with
1817     * a matching archetype at the given map and coordinates.
1818     * The first matching object is returned, or NULL if none.
1819     */
1820 root 1.24 object *
1821 root 1.49 present_arch (const archetype *at, maptile *m, int x, int y)
1822 root 1.24 {
1823 root 1.104 if (!m || out_of_map (m, x, y))
1824 root 1.24 {
1825     LOG (llevError, "Present_arch called outside map.\n");
1826     return NULL;
1827     }
1828 root 1.84
1829 root 1.104 for (object *tmp = m->at (x, y).bot; tmp; tmp = tmp->above)
1830 root 1.24 if (tmp->arch == at)
1831 elmex 1.1 return tmp;
1832 root 1.84
1833 elmex 1.1 return NULL;
1834     }
1835    
1836     /*
1837     * present(type, map, x, y) searches for any objects with
1838     * a matching type variable at the given map and coordinates.
1839     * The first matching object is returned, or NULL if none.
1840     */
1841 root 1.24 object *
1842 root 1.49 present (unsigned char type, maptile *m, int x, int y)
1843 root 1.24 {
1844     if (out_of_map (m, x, y))
1845     {
1846     LOG (llevError, "Present called outside map.\n");
1847     return NULL;
1848     }
1849 root 1.84
1850 root 1.104 for (object *tmp = m->at (x, y).bot; tmp; tmp = tmp->above)
1851 root 1.24 if (tmp->type == type)
1852 elmex 1.1 return tmp;
1853 root 1.84
1854 elmex 1.1 return NULL;
1855     }
1856    
1857     /*
1858     * present_in_ob(type, object) searches for any objects with
1859     * a matching type variable in the inventory of the given object.
1860     * The first matching object is returned, or NULL if none.
1861     */
1862 root 1.24 object *
1863     present_in_ob (unsigned char type, const object *op)
1864     {
1865 root 1.84 for (object *tmp = op->inv; tmp != NULL; tmp = tmp->below)
1866 root 1.24 if (tmp->type == type)
1867 elmex 1.1 return tmp;
1868 root 1.84
1869 elmex 1.1 return NULL;
1870     }
1871    
1872     /*
1873     * present_in_ob (type, str, object) searches for any objects with
1874     * a matching type & name variable in the inventory of the given object.
1875     * The first matching object is returned, or NULL if none.
1876     * This is mostly used by spell effect code, so that we only
1877     * have one spell effect at a time.
1878     * type can be used to narrow the search - if type is set,
1879     * the type must also match. -1 can be passed for the type,
1880     * in which case the type does not need to pass.
1881     * str is the string to match against. Note that we match against
1882     * the object name, not the archetype name. this is so that the
1883     * spell code can use one object type (force), but change it's name
1884     * to be unique.
1885     */
1886 root 1.24 object *
1887     present_in_ob_by_name (int type, const char *str, const object *op)
1888     {
1889 root 1.84 for (object *tmp = op->inv; tmp; tmp = tmp->below)
1890 root 1.82 if ((type == -1 || tmp->type == type) && (!strcmp (str, tmp->name)))
1891     return tmp;
1892 elmex 1.1
1893 root 1.82 return 0;
1894 elmex 1.1 }
1895    
1896     /*
1897     * present_arch_in_ob(archetype, object) searches for any objects with
1898     * a matching archetype in the inventory of the given object.
1899     * The first matching object is returned, or NULL if none.
1900     */
1901 root 1.24 object *
1902     present_arch_in_ob (const archetype *at, const object *op)
1903     {
1904 root 1.82 for (object *tmp = op->inv; tmp != NULL; tmp = tmp->below)
1905 root 1.24 if (tmp->arch == at)
1906 elmex 1.1 return tmp;
1907 root 1.82
1908 elmex 1.1 return NULL;
1909     }
1910    
1911     /*
1912     * activate recursively a flag on an object inventory
1913     */
1914 root 1.24 void
1915     flag_inv (object *op, int flag)
1916     {
1917 root 1.197 for (object *tmp = op->inv; tmp; tmp = tmp->below)
1918     {
1919     SET_FLAG (tmp, flag);
1920     flag_inv (tmp, flag);
1921     }
1922 root 1.82 }
1923    
1924     /*
1925     * deactivate recursively a flag on an object inventory
1926     */
1927 root 1.24 void
1928     unflag_inv (object *op, int flag)
1929     {
1930 root 1.197 for (object *tmp = op->inv; tmp; tmp = tmp->below)
1931     {
1932     CLEAR_FLAG (tmp, flag);
1933     unflag_inv (tmp, flag);
1934     }
1935 elmex 1.1 }
1936    
1937     /*
1938     * find_free_spot(object, map, x, y, start, stop) will search for
1939     * a spot at the given map and coordinates which will be able to contain
1940     * the given object. start and stop specifies how many squares
1941     * to search (see the freearr_x/y[] definition).
1942     * It returns a random choice among the alternatives found.
1943     * start and stop are where to start relative to the free_arr array (1,9
1944     * does all 4 immediate directions). This returns the index into the
1945     * array of the free spot, -1 if no spot available (dir 0 = x,y)
1946 root 1.196 * Note: This function does correctly handle tiled maps, but does not
1947 elmex 1.1 * inform the caller. However, insert_ob_in_map will update as
1948     * necessary, so the caller shouldn't need to do any special work.
1949     * Note - updated to take an object instead of archetype - this is necessary
1950     * because arch_blocked (now ob_blocked) needs to know the movement type
1951     * to know if the space in question will block the object. We can't use
1952     * the archetype because that isn't correct if the monster has been
1953     * customized, changed states, etc.
1954     */
1955 root 1.24 int
1956 root 1.49 find_free_spot (const object *ob, maptile *m, int x, int y, int start, int stop)
1957 root 1.24 {
1958 root 1.190 int altern[SIZEOFFREE];
1959 root 1.82 int index = 0, flag;
1960 root 1.24
1961 root 1.82 for (int i = start; i < stop; i++)
1962 root 1.24 {
1963 root 1.188 mapxy pos (m, x, y); pos.move (i);
1964    
1965     if (!pos.normalise ())
1966     continue;
1967    
1968     mapspace &ms = *pos;
1969 root 1.189
1970     if (ms.flags () & P_IS_ALIVE)
1971     continue;
1972 root 1.188
1973     /* However, often
1974     * ob doesn't have any move type (when used to place exits)
1975     * so the AND operation in OB_TYPE_MOVE_BLOCK doesn't work.
1976     */
1977 root 1.200 if (ob && ob->move_type == 0 && ms.move_block != MOVE_ALL)
1978 root 1.190 {
1979     altern [index++] = i;
1980     continue;
1981     }
1982 root 1.24
1983     /* Basically, if we find a wall on a space, we cut down the search size.
1984     * In this way, we won't return spaces that are on another side of a wall.
1985     * This mostly work, but it cuts down the search size in all directions -
1986     * if the space being examined only has a wall to the north and empty
1987     * spaces in all the other directions, this will reduce the search space
1988     * to only the spaces immediately surrounding the target area, and
1989     * won't look 2 spaces south of the target space.
1990     */
1991 root 1.188 if (ms.move_block == MOVE_ALL && maxfree[i] < stop)
1992     {
1993     stop = maxfree[i];
1994     continue;
1995     }
1996    
1997     /* Note it is intentional that we check ob - the movement type of the
1998     * head of the object should correspond for the entire object.
1999     */
2000     if (OB_TYPE_MOVE_BLOCK (ob, ms.move_block))
2001     continue;
2002    
2003 root 1.196 if (ob->blocked (m, pos.x, pos.y))
2004     continue;
2005    
2006 root 1.188 altern [index++] = i;
2007 elmex 1.1 }
2008 root 1.74
2009 root 1.24 if (!index)
2010     return -1;
2011 root 1.74
2012 root 1.124 return altern [rndm (index)];
2013 elmex 1.1 }
2014    
2015     /*
2016 root 1.49 * find_first_free_spot(archetype, maptile, x, y) works like
2017 elmex 1.1 * find_free_spot(), but it will search max number of squares.
2018     * But it will return the first available spot, not a random choice.
2019     * Changed 0.93.2: Have it return -1 if there is no free spot available.
2020     */
2021 root 1.24 int
2022 root 1.49 find_first_free_spot (const object *ob, maptile *m, int x, int y)
2023 root 1.24 {
2024 root 1.82 for (int i = 0; i < SIZEOFFREE; i++)
2025 root 1.188 if (!ob->blocked (m, x + freearr_x[i], y + freearr_y[i]))
2026 root 1.82 return i;
2027 root 1.24
2028     return -1;
2029 elmex 1.1 }
2030    
2031     /*
2032     * The function permute(arr, begin, end) randomly reorders the array
2033     * arr[begin..end-1].
2034 root 1.82 * now uses a fisher-yates shuffle, old permute was broken
2035 elmex 1.1 */
2036 root 1.24 static void
2037     permute (int *arr, int begin, int end)
2038 elmex 1.1 {
2039 root 1.82 arr += begin;
2040     end -= begin;
2041    
2042     while (--end)
2043 root 1.124 swap (arr [end], arr [rndm (end + 1)]);
2044 elmex 1.1 }
2045    
2046     /* new function to make monster searching more efficient, and effective!
2047     * This basically returns a randomized array (in the passed pointer) of
2048     * the spaces to find monsters. In this way, it won't always look for
2049     * monsters to the north first. However, the size of the array passed
2050     * covers all the spaces, so within that size, all the spaces within
2051     * the 3x3 area will be searched, just not in a predictable order.
2052     */
2053 root 1.24 void
2054     get_search_arr (int *search_arr)
2055 elmex 1.1 {
2056 root 1.82 int i;
2057 elmex 1.1
2058 root 1.24 for (i = 0; i < SIZEOFFREE; i++)
2059 root 1.82 search_arr[i] = i;
2060 elmex 1.1
2061 root 1.24 permute (search_arr, 1, SIZEOFFREE1 + 1);
2062     permute (search_arr, SIZEOFFREE1 + 1, SIZEOFFREE2 + 1);
2063     permute (search_arr, SIZEOFFREE2 + 1, SIZEOFFREE);
2064 elmex 1.1 }
2065    
2066     /*
2067     * find_dir(map, x, y, exclude) will search some close squares in the
2068     * given map at the given coordinates for live objects.
2069     * It will not considered the object given as exclude among possible
2070     * live objects.
2071     * It returns the direction toward the first/closest live object if finds
2072     * any, otherwise 0.
2073     * Perhaps incorrectly, but I'm making the assumption that exclude
2074     * is actually want is going to try and move there. We need this info
2075     * because we have to know what movement the thing looking to move
2076     * there is capable of.
2077     */
2078 root 1.24 int
2079 root 1.49 find_dir (maptile *m, int x, int y, object *exclude)
2080 root 1.24 {
2081 root 1.82 int i, max = SIZEOFFREE, mflags;
2082 root 1.29
2083     sint16 nx, ny;
2084 root 1.82 object *tmp;
2085     maptile *mp;
2086 root 1.29
2087     MoveType blocked, move_type;
2088 root 1.24
2089 root 1.155 if (exclude && exclude->head_ () != exclude)
2090 root 1.24 {
2091     exclude = exclude->head;
2092     move_type = exclude->move_type;
2093     }
2094     else
2095     {
2096     /* If we don't have anything, presume it can use all movement types. */
2097     move_type = MOVE_ALL;
2098     }
2099    
2100     for (i = 1; i < max; i++)
2101     {
2102     mp = m;
2103     nx = x + freearr_x[i];
2104     ny = y + freearr_y[i];
2105    
2106     mflags = get_map_flags (m, &mp, nx, ny, &nx, &ny);
2107 root 1.75
2108 root 1.24 if (mflags & P_OUT_OF_MAP)
2109 root 1.75 max = maxfree[i];
2110 root 1.24 else
2111     {
2112 root 1.82 mapspace &ms = mp->at (nx, ny);
2113    
2114     blocked = ms.move_block;
2115 root 1.24
2116     if ((move_type & blocked) == move_type)
2117 root 1.75 max = maxfree[i];
2118 root 1.24 else if (mflags & P_IS_ALIVE)
2119     {
2120 root 1.84 for (tmp = ms.bot; tmp; tmp = tmp->above)
2121 root 1.82 if ((tmp->flag [FLAG_MONSTER] || tmp->type == PLAYER)
2122 root 1.155 && (tmp != exclude || (tmp->head_ () != tmp && tmp->head_ () != exclude)))
2123 root 1.75 break;
2124    
2125 root 1.24 if (tmp)
2126 root 1.75 return freedir[i];
2127 root 1.8 }
2128     }
2129 elmex 1.1 }
2130 root 1.75
2131 root 1.24 return 0;
2132 elmex 1.1 }
2133    
2134     /*
2135     * distance(object 1, object 2) will return the square of the
2136     * distance between the two given objects.
2137     */
2138 root 1.24 int
2139     distance (const object *ob1, const object *ob2)
2140     {
2141 root 1.82 return (ob1->x - ob2->x) * (ob1->x - ob2->x) + (ob1->y - ob2->y) * (ob1->y - ob2->y);
2142 elmex 1.1 }
2143    
2144     /*
2145     * find_dir_2(delta-x,delta-y) will return a direction in which
2146     * an object which has subtracted the x and y coordinates of another
2147     * object, needs to travel toward it.
2148     */
2149 root 1.24 int
2150     find_dir_2 (int x, int y)
2151     {
2152 root 1.75 int q;
2153 elmex 1.1
2154 root 1.24 if (y)
2155     q = x * 100 / y;
2156 elmex 1.1 else if (x)
2157 root 1.24 q = -300 * x;
2158 elmex 1.1 else
2159     return 0;
2160    
2161 root 1.24 if (y > 0)
2162     {
2163     if (q < -242)
2164     return 3;
2165     if (q < -41)
2166     return 2;
2167     if (q < 41)
2168     return 1;
2169     if (q < 242)
2170     return 8;
2171     return 7;
2172     }
2173 elmex 1.1
2174     if (q < -242)
2175 root 1.24 return 7;
2176 elmex 1.1 if (q < -41)
2177 root 1.24 return 6;
2178 elmex 1.1 if (q < 41)
2179 root 1.24 return 5;
2180 elmex 1.1 if (q < 242)
2181 root 1.24 return 4;
2182 elmex 1.1
2183 root 1.24 return 3;
2184 elmex 1.1 }
2185    
2186     /*
2187     * dirdiff(dir1, dir2) returns how many 45-degrees differences there is
2188     * between two directions (which are expected to be absolute (see absdir())
2189     */
2190 root 1.24 int
2191     dirdiff (int dir1, int dir2)
2192     {
2193 root 1.82 int d;
2194 root 1.24
2195     d = abs (dir1 - dir2);
2196     if (d > 4)
2197 elmex 1.1 d = 8 - d;
2198 root 1.82
2199 elmex 1.1 return d;
2200     }
2201    
2202     /* peterm:
2203     * do LOS stuff for ball lightning. Go after the closest VISIBLE monster.
2204     * Basically, this is a table of directions, and what directions
2205     * one could go to go back to us. Eg, entry 15 below is 4, 14, 16.
2206     * This basically means that if direction is 15, then it could either go
2207     * direction 4, 14, or 16 to get back to where we are.
2208     * Moved from spell_util.c to object.c with the other related direction
2209     * functions.
2210     */
2211 root 1.82 int reduction_dir[SIZEOFFREE][3] = {
2212 root 1.24 {0, 0, 0}, /* 0 */
2213     {0, 0, 0}, /* 1 */
2214     {0, 0, 0}, /* 2 */
2215     {0, 0, 0}, /* 3 */
2216     {0, 0, 0}, /* 4 */
2217     {0, 0, 0}, /* 5 */
2218     {0, 0, 0}, /* 6 */
2219     {0, 0, 0}, /* 7 */
2220     {0, 0, 0}, /* 8 */
2221     {8, 1, 2}, /* 9 */
2222     {1, 2, -1}, /* 10 */
2223     {2, 10, 12}, /* 11 */
2224     {2, 3, -1}, /* 12 */
2225     {2, 3, 4}, /* 13 */
2226     {3, 4, -1}, /* 14 */
2227     {4, 14, 16}, /* 15 */
2228     {5, 4, -1}, /* 16 */
2229     {4, 5, 6}, /* 17 */
2230     {6, 5, -1}, /* 18 */
2231     {6, 20, 18}, /* 19 */
2232     {7, 6, -1}, /* 20 */
2233     {6, 7, 8}, /* 21 */
2234     {7, 8, -1}, /* 22 */
2235     {8, 22, 24}, /* 23 */
2236     {8, 1, -1}, /* 24 */
2237     {24, 9, 10}, /* 25 */
2238     {9, 10, -1}, /* 26 */
2239     {10, 11, -1}, /* 27 */
2240     {27, 11, 29}, /* 28 */
2241     {11, 12, -1}, /* 29 */
2242     {12, 13, -1}, /* 30 */
2243     {12, 13, 14}, /* 31 */
2244     {13, 14, -1}, /* 32 */
2245     {14, 15, -1}, /* 33 */
2246     {33, 15, 35}, /* 34 */
2247     {16, 15, -1}, /* 35 */
2248     {17, 16, -1}, /* 36 */
2249     {18, 17, 16}, /* 37 */
2250     {18, 17, -1}, /* 38 */
2251     {18, 19, -1}, /* 39 */
2252     {41, 19, 39}, /* 40 */
2253     {19, 20, -1}, /* 41 */
2254     {20, 21, -1}, /* 42 */
2255     {20, 21, 22}, /* 43 */
2256     {21, 22, -1}, /* 44 */
2257     {23, 22, -1}, /* 45 */
2258     {45, 47, 23}, /* 46 */
2259     {23, 24, -1}, /* 47 */
2260     {24, 9, -1}
2261     }; /* 48 */
2262 elmex 1.1
2263     /* Recursive routine to step back and see if we can
2264     * find a path to that monster that we found. If not,
2265     * we don't bother going toward it. Returns 1 if we
2266     * can see a direct way to get it
2267     * Modified to be map tile aware -.MSW
2268     */
2269 root 1.24 int
2270 root 1.49 can_see_monsterP (maptile *m, int x, int y, int dir)
2271 root 1.24 {
2272 root 1.29 sint16 dx, dy;
2273 root 1.75 int mflags;
2274 root 1.24
2275     if (dir < 0)
2276     return 0; /* exit condition: invalid direction */
2277    
2278     dx = x + freearr_x[dir];
2279     dy = y + freearr_y[dir];
2280    
2281     mflags = get_map_flags (m, &m, dx, dy, &dx, &dy);
2282    
2283     /* This functional arguably was incorrect before - it was
2284     * checking for P_WALL - that was basically seeing if
2285     * we could move to the monster - this is being more
2286     * literal on if we can see it. To know if we can actually
2287     * move to the monster, we'd need the monster passed in or
2288     * at least its move type.
2289     */
2290     if (mflags & (P_OUT_OF_MAP | P_BLOCKSVIEW))
2291     return 0;
2292    
2293     /* yes, can see. */
2294     if (dir < 9)
2295     return 1;
2296 root 1.75
2297     return can_see_monsterP (m, x, y, reduction_dir[dir][0])
2298     | can_see_monsterP (m, x, y, reduction_dir[dir][1])
2299     | can_see_monsterP (m, x, y, reduction_dir[dir][2]);
2300 root 1.24 }
2301    
2302 elmex 1.1 /*
2303     * can_pick(picker, item): finds out if an object is possible to be
2304     * picked up by the picker. Returnes 1 if it can be
2305     * picked up, otherwise 0.
2306     *
2307     * Cf 0.91.3 - don't let WIZ's pick up anything - will likely cause
2308     * core dumps if they do.
2309     *
2310     * Add a check so we can't pick up invisible objects (0.93.8)
2311     */
2312 root 1.24 int
2313     can_pick (const object *who, const object *item)
2314     {
2315     return /*QUERY_FLAG(who,FLAG_WIZ)|| */
2316     (item->weight > 0 && !QUERY_FLAG (item, FLAG_NO_PICK) &&
2317     !QUERY_FLAG (item, FLAG_ALIVE) && !item->invisible && (who->type == PLAYER || item->weight < who->weight / 3));
2318 elmex 1.1 }
2319    
2320     /*
2321     * create clone from object to another
2322     */
2323 root 1.24 object *
2324     object_create_clone (object *asrc)
2325     {
2326 root 1.155 object *dst = 0, *tmp, *src, *prev, *item;
2327 elmex 1.1
2328 root 1.24 if (!asrc)
2329 root 1.62 return 0;
2330    
2331 root 1.155 src = asrc->head_ ();
2332 root 1.24
2333 root 1.62 prev = 0;
2334 root 1.155 for (object *part = src; part; part = part->more)
2335 root 1.24 {
2336 root 1.65 tmp = part->clone ();
2337 root 1.24 tmp->x -= src->x;
2338     tmp->y -= src->y;
2339 root 1.62
2340 root 1.24 if (!part->head)
2341     {
2342     dst = tmp;
2343 root 1.62 tmp->head = 0;
2344 root 1.24 }
2345     else
2346 root 1.75 tmp->head = dst;
2347 root 1.62
2348     tmp->more = 0;
2349    
2350 root 1.24 if (prev)
2351     prev->more = tmp;
2352 root 1.62
2353 root 1.24 prev = tmp;
2354 elmex 1.1 }
2355 root 1.24
2356     for (item = src->inv; item; item = item->below)
2357 root 1.48 insert_ob_in_ob (object_create_clone (item), dst);
2358 elmex 1.1
2359 root 1.24 return dst;
2360 elmex 1.1 }
2361    
2362     /* This returns the first object in who's inventory that
2363     * has the same type and subtype match.
2364     * returns NULL if no match.
2365     */
2366 root 1.24 object *
2367     find_obj_by_type_subtype (const object *who, int type, int subtype)
2368 elmex 1.1 {
2369 root 1.82 for (object *tmp = who->inv; tmp; tmp = tmp->below)
2370 root 1.24 if (tmp->type == type && tmp->subtype == subtype)
2371     return tmp;
2372 elmex 1.1
2373 root 1.82 return 0;
2374 elmex 1.1 }
2375    
2376     /* If ob has a field named key, return the link from the list,
2377     * otherwise return NULL.
2378     *
2379     * key must be a passed in shared string - otherwise, this won't
2380     * do the desired thing.
2381     */
2382 root 1.24 key_value *
2383     get_ob_key_link (const object *ob, const char *key)
2384     {
2385 root 1.82 for (key_value *link = ob->key_values; link; link = link->next)
2386 root 1.48 if (link->key == key)
2387     return link;
2388 root 1.24
2389 root 1.82 return 0;
2390 root 1.24 }
2391 elmex 1.1
2392     /*
2393     * Returns the value of op has an extra_field for key, or NULL.
2394     *
2395     * The argument doesn't need to be a shared string.
2396     *
2397     * The returned string is shared.
2398     */
2399 root 1.24 const char *
2400     get_ob_key_value (const object *op, const char *const key)
2401     {
2402 root 1.35 key_value *link;
2403     shstr_cmp canonical_key (key);
2404 root 1.24
2405 root 1.35 if (!canonical_key)
2406 root 1.24 {
2407     /* 1. There being a field named key on any object
2408     * implies there'd be a shared string to find.
2409     * 2. Since there isn't, no object has this field.
2410     * 3. Therefore, *this* object doesn't have this field.
2411     */
2412 root 1.35 return 0;
2413 elmex 1.1 }
2414    
2415 root 1.24 /* This is copied from get_ob_key_link() above -
2416     * only 4 lines, and saves the function call overhead.
2417     */
2418 root 1.35 for (link = op->key_values; link; link = link->next)
2419     if (link->key == canonical_key)
2420     return link->value;
2421    
2422     return 0;
2423 elmex 1.1 }
2424    
2425     /*
2426     * Updates the canonical_key in op to value.
2427     *
2428     * canonical_key is a shared string (value doesn't have to be).
2429     *
2430     * Unless add_key is TRUE, it won't add fields, only change the value of existing
2431     * keys.
2432     *
2433     * Returns TRUE on success.
2434     */
2435 root 1.24 int
2436     set_ob_key_value_s (object *op, const shstr & canonical_key, const char *value, int add_key)
2437     {
2438 root 1.82 key_value *field = NULL, *last = NULL;
2439 root 1.24
2440     for (field = op->key_values; field != NULL; field = field->next)
2441     {
2442     if (field->key != canonical_key)
2443     {
2444     last = field;
2445     continue;
2446     }
2447    
2448     if (value)
2449     field->value = value;
2450     else
2451     {
2452     /* Basically, if the archetype has this key set,
2453     * we need to store the null value so when we save
2454     * it, we save the empty value so that when we load,
2455     * we get this value back again.
2456     */
2457 root 1.159 if (get_ob_key_link (op->arch, canonical_key))
2458 root 1.24 field->value = 0;
2459     else
2460     {
2461     if (last)
2462     last->next = field->next;
2463     else
2464     op->key_values = field->next;
2465    
2466 root 1.29 delete field;
2467 root 1.24 }
2468     }
2469     return TRUE;
2470     }
2471     /* IF we get here, key doesn't exist */
2472    
2473     /* No field, we'll have to add it. */
2474    
2475     if (!add_key)
2476 root 1.82 return FALSE;
2477    
2478 root 1.24 /* There isn't any good reason to store a null
2479     * value in the key/value list. If the archetype has
2480     * this key, then we should also have it, so shouldn't
2481     * be here. If user wants to store empty strings,
2482     * should pass in ""
2483     */
2484     if (value == NULL)
2485 elmex 1.1 return TRUE;
2486 root 1.24
2487     field = new key_value;
2488    
2489     field->key = canonical_key;
2490     field->value = value;
2491     /* Usual prepend-addition. */
2492     field->next = op->key_values;
2493     op->key_values = field;
2494    
2495     return TRUE;
2496 elmex 1.1 }
2497    
2498     /*
2499     * Updates the key in op to value.
2500     *
2501     * If add_key is FALSE, this will only update existing keys,
2502     * and not add new ones.
2503     * In general, should be little reason FALSE is ever passed in for add_key
2504     *
2505     * Returns TRUE on success.
2506     */
2507 root 1.24 int
2508     set_ob_key_value (object *op, const char *key, const char *value, int add_key)
2509 root 1.11 {
2510 root 1.29 shstr key_ (key);
2511 root 1.24
2512 root 1.11 return set_ob_key_value_s (op, key_, value, add_key);
2513 elmex 1.1 }
2514 root 1.31
2515 root 1.34 object::depth_iterator::depth_iterator (object *container)
2516     : iterator_base (container)
2517     {
2518     while (item->inv)
2519     item = item->inv;
2520     }
2521    
2522 root 1.31 void
2523 root 1.34 object::depth_iterator::next ()
2524 root 1.31 {
2525 root 1.34 if (item->below)
2526     {
2527     item = item->below;
2528    
2529     while (item->inv)
2530     item = item->inv;
2531     }
2532 root 1.31 else
2533 root 1.34 item = item->env;
2534 root 1.31 }
2535 root 1.34
2536 elmex 1.97 const char *
2537     object::flag_desc (char *desc, int len) const
2538     {
2539     char *p = desc;
2540     bool first = true;
2541    
2542 root 1.101 *p = 0;
2543    
2544 elmex 1.97 for (int i = 0; i < NUM_FLAGS; i++)
2545     {
2546     if (len <= 10) // magic constant!
2547     {
2548     snprintf (p, len, ",...");
2549     break;
2550     }
2551    
2552 root 1.101 if (flag [i])
2553 elmex 1.97 {
2554     int cnt = snprintf (p, len, "%s%d", first ? "" : ",", i);
2555     len -= cnt;
2556     p += cnt;
2557     first = false;
2558     }
2559     }
2560    
2561     return desc;
2562     }
2563    
2564 root 1.101 // return a suitable string describing an object in enough detail to find it
2565 root 1.36 const char *
2566     object::debug_desc (char *info) const
2567     {
2568 elmex 1.97 char flagdesc[512];
2569     char info2[256 * 4];
2570 root 1.36 char *p = info;
2571    
2572 root 1.203 p += snprintf (p, 512, "{cnt:%d,uuid:%s,name:\"%s\"%s%s,flags:[%s],type:%d}",
2573     count,
2574     uuid.c_str (),
2575 root 1.36 &name,
2576 root 1.117 title ? "\",title:\"" : "",
2577 elmex 1.97 title ? (const char *)title : "",
2578     flag_desc (flagdesc, 512), type);
2579 root 1.36
2580 root 1.217 if (!flag[FLAG_REMOVED] && env)
2581 root 1.36 p += snprintf (p, 256, "(in %s)", env->debug_desc (info2));
2582    
2583     if (map)
2584 root 1.96 p += snprintf (p, 256, "(on %s@%d+%d)", &map->path, x, y);
2585 root 1.36
2586     return info;
2587     }
2588    
2589     const char *
2590     object::debug_desc () const
2591     {
2592 root 1.143 static char info[3][256 * 4];
2593     static int info_idx;
2594 root 1.36
2595 root 1.143 return debug_desc (info [++info_idx % 3]);
2596 root 1.114 }
2597    
2598 root 1.125 struct region *
2599     object::region () const
2600     {
2601     return map ? map->region (x, y)
2602     : region::default_region ();
2603     }
2604    
2605 root 1.129 const materialtype_t *
2606     object::dominant_material () const
2607     {
2608 root 1.165 if (materialtype_t *mt = name_to_material (materialname))
2609     return mt;
2610 root 1.129
2611 root 1.165 return name_to_material (shstr_unknown);
2612 root 1.129 }
2613    
2614 root 1.130 void
2615     object::open_container (object *new_container)
2616     {
2617     if (container == new_container)
2618     return;
2619    
2620     if (object *old_container = container)
2621     {
2622     if (INVOKE_OBJECT (CLOSE, old_container, ARG_OBJECT (this)))
2623     return;
2624    
2625     #if 0
2626     // remove the "Close old_container" object.
2627     if (object *closer = old_container->inv)
2628     if (closer->type == CLOSE_CON)
2629     closer->destroy ();
2630     #endif
2631    
2632 root 1.216 old_container->flag [FLAG_APPLIED] = false;
2633 root 1.130 container = 0;
2634    
2635     esrv_update_item (UPD_FLAGS, this, old_container);
2636     new_draw_info_format (NDI_UNIQUE, 0, this, "You close %s.", query_name (old_container));
2637 root 1.177 play_sound (sound_find ("chest_close"));
2638 root 1.130 }
2639    
2640     if (new_container)
2641     {
2642     if (INVOKE_OBJECT (OPEN, new_container, ARG_OBJECT (this)))
2643     return;
2644    
2645     // TODO: this does not seem to serve any purpose anymore?
2646     #if 0
2647     // insert the "Close Container" object.
2648     if (archetype *closer = new_container->other_arch)
2649     {
2650     object *closer = arch_to_object (new_container->other_arch);
2651     closer->flag [FLAG_NO_MAP_SAVE] = 1;
2652     new_container->insert (closer);
2653     }
2654     #endif
2655    
2656 root 1.132 new_draw_info_format (NDI_UNIQUE, 0, this, "You open %s.", query_name (new_container));
2657    
2658 root 1.216 new_container->flag [FLAG_APPLIED] = true;
2659 root 1.130 container = new_container;
2660    
2661     esrv_update_item (UPD_FLAGS, this, new_container);
2662 root 1.131 esrv_send_inventory (this, new_container);
2663 root 1.177 play_sound (sound_find ("chest_open"));
2664 root 1.130 }
2665     }
2666    
2667 root 1.164 object *
2668     object::force_find (const shstr name)
2669     {
2670     /* cycle through his inventory to look for the MARK we want to
2671     * place
2672     */
2673     for (object *tmp = inv; tmp; tmp = tmp->below)
2674     if (tmp->type == FORCE && tmp->slaying == name)
2675     return splay (tmp);
2676    
2677     return 0;
2678     }
2679    
2680     void
2681     object::force_add (const shstr name, int duration)
2682     {
2683     if (object *force = force_find (name))
2684     force->destroy ();
2685    
2686     object *force = get_archetype (FORCE_NAME);
2687    
2688     force->slaying = name;
2689     force->stats.food = 1;
2690     force->speed_left = -1.f;
2691    
2692     force->set_speed (duration ? 1.f / duration : 0.f);
2693     force->flag [FLAG_IS_USED_UP] = true;
2694     force->flag [FLAG_APPLIED] = true;
2695    
2696     insert (force);
2697     }
2698    
2699 root 1.178 void
2700 root 1.208 object::play_sound (faceidx sound)
2701 root 1.178 {
2702     if (!sound)
2703     return;
2704    
2705     if (flag [FLAG_REMOVED])
2706     return;
2707    
2708     if (env)
2709     {
2710     if (object *pl = in_player ())
2711     pl->contr->play_sound (sound);
2712     }
2713     else
2714     map->play_sound (sound, x, y);
2715     }
2716