ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/object.C
Revision: 1.337
Committed: Thu May 6 21:45:49 2010 UTC (14 years ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-3_0
Changes since 1.336: +26 -24 lines
Log Message:
next try at weight updates

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