ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/object.C
Revision: 1.253
Committed: Sun Aug 17 22:46:26 2008 UTC (15 years, 9 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.252: +3 -7 lines
Log Message:
fix flags updating, make ->player rely on P_PLAYER

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