ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/object.C
Revision: 1.362
Committed: Thu Jan 19 21:51:43 2017 UTC (7 years, 4 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.361: +16 -16 lines
Log Message:
*** empty log message ***

File Contents

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