ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/object.C
Revision: 1.325
Committed: Wed Apr 14 21:36:31 2010 UTC (14 years, 1 month ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.324: +15 -0 lines
Log Message:
find_makr_object > mark, fix throwing

File Contents

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