ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/object.C
Revision: 1.227
Committed: Sat May 3 09:04:17 2008 UTC (16 years ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.226: +20 -28 lines
Log Message:
do not use the copy constructor and assignment opertaor of object anymore

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