ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/object.C
Revision: 1.243
Committed: Sat May 17 00:17:02 2008 UTC (16 years ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.242: +11 -6 lines
Log Message:
many bugfixes

File Contents

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