ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/object.C
Revision: 1.353
Committed: Fri Jan 27 22:00:39 2012 UTC (12 years, 3 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.352: +2 -2 lines
Log Message:
remove unused variables, kernel_panic

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