ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/object.C
Revision: 1.255
Committed: Sun Aug 31 02:01:41 2008 UTC (15 years, 8 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.254: +0 -1 lines
Log Message:
remove FLAG_CLIENT_SENT for good

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