ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/object.C
Revision: 1.342
Committed: Sun Apr 10 20:30:53 2011 UTC (13 years, 1 month ago) by sf-kernelpanic
Content type: text/plain
Branch: MAIN
Changes since 1.341: +4 -3 lines
Log Message:
object.C: don't merge "renamed" items

Before, it was possible to just pickup one item from a stack, rename
it and "taint" the stack with the new name by just dropping it.

With this patch the renamed item will not be merged into the stack.

Objects with the same "custom" name will still merge.

Another use case would be the separation of certain types of items which
are often found in dungeons, e.g. levitation boots. One could rename one
pair of levitation boots and use it whenever he needs to, and other
boots which would normally merge with it will form a new stack.

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