ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/object.C
Revision: 1.317
Committed: Fri Apr 2 03:41:24 2010 UTC (14 years, 1 month ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.316: +31 -38 lines
Log Message:
preliminary check-in with dbeugging code

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