ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/object.C
Revision: 1.315
Committed: Fri Mar 26 21:43:43 2010 UTC (14 years, 2 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.314: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

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