ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/object.C
Revision: 1.225
Committed: Fri May 2 20:28:44 2008 UTC (16 years ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.224: +1 -0 lines
Log Message:
copy the map ptr when cloning an object

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