ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/object.C
Revision: 1.221
Committed: Thu Apr 24 12:06:01 2008 UTC (16 years, 1 month ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.220: +2 -0 lines
Log Message:
*** empty log message ***

File Contents

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