ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/object.C
Revision: 1.249
Committed: Tue Jul 15 20:41:58 2008 UTC (15 years, 10 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.248: +1 -1 lines
Log Message:
goof

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     || (op->type == PLAYER && !(m.flags_ & P_PLAYER))
768     || (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     * to have move_allow right now.
776     */
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.92 {
916 root 1.217 inv->destroy_inv (false);
917 root 1.92 inv->destroy ();
918     }
919 root 1.89 }
920     else
921     { /* Put objects in inventory onto this space */
922     while (inv)
923     {
924     object *op = inv;
925    
926     if (op->flag [FLAG_STARTEQUIP]
927     || op->flag [FLAG_NO_DROP]
928     || op->type == RUNE
929     || op->type == TRAP
930 root 1.110 || op->flag [FLAG_IS_A_TEMPLATE]
931     || op->flag [FLAG_DESTROY_ON_DEATH])
932 root 1.217 op->destroy (true);
933 root 1.89 else
934 root 1.93 map->insert (op, x, y);
935 root 1.89 }
936     }
937     }
938    
939 root 1.21 object *object::create ()
940     {
941 root 1.42 object *op = new object;
942 root 1.22 op->link ();
943     return op;
944 root 1.21 }
945 elmex 1.1
946 root 1.223 static struct freed_map : maptile
947     {
948     freed_map ()
949     {
950 root 1.238 path = "<freed objects map>";
951     name = "/internal/freed_objects_map";
952     width = 3;
953     height = 3;
954     no_drop = 1;
955     no_reset = 1;
956 root 1.223
957     alloc ();
958     in_memory = MAP_ACTIVE;
959     }
960 root 1.229
961     ~freed_map ()
962     {
963     destroy ();
964     }
965 root 1.223 } freed_map; // freed objects are moved here to avoid crashes
966    
967 root 1.82 void
968     object::do_destroy ()
969 root 1.14 {
970 root 1.82 if (flag [FLAG_IS_LINKED])
971     remove_button_link (this);
972 root 1.29
973 root 1.82 if (flag [FLAG_FRIENDLY])
974 root 1.140 remove_friendly_object (this);
975 root 1.32
976 root 1.213 remove ();
977    
978     attachable::do_destroy ();
979 root 1.14
980 root 1.112 deactivate ();
981     unlink ();
982 root 1.92
983 root 1.82 flag [FLAG_FREED] = 1;
984 root 1.14
985 root 1.57 // hack to ensure that freed objects still have a valid map
986 root 1.223 map = &freed_map;
987     x = 1;
988     y = 1;
989 root 1.57
990 root 1.88 if (more)
991     {
992     more->destroy ();
993     more = 0;
994     }
995 root 1.82
996 root 1.162 head = 0;
997    
998     // clear those pointers that likely might cause circular references
999     owner = 0;
1000     enemy = 0;
1001     attacked_by = 0;
1002     current_weapon = 0;
1003 root 1.82 }
1004    
1005     void
1006     object::destroy (bool destroy_inventory)
1007     {
1008     if (destroyed ())
1009     return;
1010    
1011 root 1.219 if (!is_head () && !head->destroyed ())
1012     {
1013     LOG (llevError | logBacktrace, "tried to destroy the tail of an object");
1014     head->destroy (destroy_inventory);
1015 root 1.223 return;
1016 root 1.219 }
1017    
1018 root 1.217 destroy_inv (!destroy_inventory);
1019 root 1.22
1020 root 1.173 if (is_head ())
1021     if (sound_destroy)
1022     play_sound (sound_destroy);
1023     else if (flag [FLAG_MONSTER])
1024     play_sound (sound_find ("monster_destroy")); // quick hack, too lazy to create a generic mechanism
1025 root 1.169
1026 root 1.82 attachable::destroy ();
1027 elmex 1.1 }
1028    
1029 root 1.63 /* op->remove ():
1030 elmex 1.1 * This function removes the object op from the linked list of objects
1031     * which it is currently tied to. When this function is done, the
1032     * object will have no environment. If the object previously had an
1033     * environment, the x and y coordinates will be updated to
1034     * the previous environment.
1035     */
1036 root 1.24 void
1037 root 1.128 object::do_remove ()
1038 root 1.24 {
1039 root 1.45 object *tmp, *last = 0;
1040     object *otmp;
1041 root 1.26
1042 root 1.213 if (flag [FLAG_REMOVED])
1043 root 1.29 return;
1044 root 1.24
1045 root 1.82 INVOKE_OBJECT (REMOVE, this);
1046 root 1.26
1047 root 1.213 flag [FLAG_REMOVED] = true;
1048    
1049 root 1.59 if (more)
1050     more->remove ();
1051 root 1.24
1052     /*
1053     * In this case, the object to be removed is in someones
1054     * inventory.
1055     */
1056 root 1.59 if (env)
1057 root 1.24 {
1058 root 1.221 flag [FLAG_REMOVED] = false; // hack around the issue of visible_to checking flag_removed
1059 root 1.220 if (object *pl = visible_to ())
1060     esrv_del_item (pl->contr, count);
1061 root 1.221 flag [FLAG_REMOVED] = true; // hack around the issue of visible_to checking flag_removed
1062 root 1.220
1063 root 1.208 adjust_weight (env, -total_weight ());
1064 root 1.24
1065 root 1.237 /* we set up values so that it could be inserted into
1066     * the map, but we don't actually do that - it is up
1067     * to the caller to decide what we want to do.
1068     */
1069     map = env->map;
1070     x = env->x;
1071     y = env->y;
1072    
1073 root 1.236 // make sure cmov optimisation is applicable
1074 root 1.208 *(above ? &above->below : &env->inv) = below;
1075 root 1.236 *(below ? &below->above : &above ) = above; // &above is just a dummy
1076 root 1.24
1077 root 1.236 above = 0;
1078     below = 0;
1079     env = 0;
1080 root 1.24
1081 root 1.208 /* NO_FIX_PLAYER is set when a great many changes are being
1082     * made to players inventory. If set, avoiding the call
1083     * to save cpu time.
1084     */
1085     if ((otmp = in_player ()) && otmp->contr && !QUERY_FLAG (otmp, FLAG_NO_FIX_PLAYER))
1086     otmp->update_stats ();
1087 root 1.59 }
1088     else if (map)
1089     {
1090 root 1.220 map->dirty = true;
1091     mapspace &ms = this->ms ();
1092    
1093     if (object *pl = ms.player ())
1094 root 1.96 {
1095 root 1.220 if (type == PLAYER) // this == pl(!)
1096     {
1097     // leaving a spot always closes any open container on the ground
1098     if (container && !container->env)
1099     // this causes spurious floorbox updates, but it ensures
1100     // that the CLOSE event is being sent.
1101     close_container ();
1102    
1103     --map->players;
1104     map->touch ();
1105     }
1106     else if (pl->container == this)
1107     {
1108     // removing a container should close it
1109     close_container ();
1110     }
1111 root 1.130
1112 root 1.220 esrv_del_item (pl->contr, count);
1113 root 1.96 }
1114    
1115 root 1.29 /* link the object above us */
1116 root 1.236 // re-link, make sure compiler can easily use cmove
1117     *(above ? &above->below : &ms.top) = below;
1118     *(below ? &below->above : &ms.bot) = above;
1119 root 1.26
1120 root 1.59 above = 0;
1121     below = 0;
1122 root 1.26
1123 root 1.59 if (map->in_memory == MAP_SAVING)
1124 root 1.29 return;
1125 elmex 1.1
1126 root 1.82 int check_walk_off = !flag [FLAG_NO_APPLY];
1127 elmex 1.1
1128 root 1.175 if (object *pl = ms.player ())
1129     {
1130     if (pl->container == this)
1131     /* If a container that the player is currently using somehow gets
1132     * removed (most likely destroyed), update the player view
1133     * appropriately.
1134     */
1135     pl->close_container ();
1136    
1137 root 1.218 //TODO: the floorbox prev/next might need updating
1138 root 1.226 //esrv_del_item (pl->contr, count);
1139     //TODO: update floorbox to preserve ordering
1140     if (pl->contr->ns)
1141     pl->contr->ns->floorbox_update ();
1142 root 1.175 }
1143    
1144 root 1.117 for (tmp = ms.bot; tmp; tmp = tmp->above)
1145 root 1.24 {
1146 root 1.29 /* No point updating the players look faces if he is the object
1147     * being removed.
1148 root 1.24 */
1149 root 1.29
1150 root 1.96 /* See if object moving off should effect something */
1151 root 1.50 if (check_walk_off
1152 root 1.59 && ((move_type & tmp->move_off)
1153     && (move_type & ~tmp->move_off & ~tmp->move_block) == 0))
1154 root 1.29 {
1155 elmex 1.72 move_apply (tmp, this, 0);
1156 root 1.24
1157 root 1.59 if (destroyed ())
1158 root 1.50 LOG (llevError, "BUG: remove_ob(): name %s, destroyed leaving object\n", tmp->debug_desc ());
1159 root 1.8 }
1160    
1161 root 1.29 last = tmp;
1162     }
1163 root 1.26
1164 root 1.96 /* last == NULL if there are no objects on this space */
1165     //TODO: this makes little sense, why only update the topmost object?
1166 root 1.59 if (!last)
1167 root 1.99 map->at (x, y).flags_ = 0;
1168 root 1.29 else
1169     update_object (last, UP_OBJ_REMOVE);
1170 root 1.26
1171 root 1.82 if (flag [FLAG_BLOCKSVIEW] || glow_radius)
1172 root 1.59 update_all_los (map, x, y);
1173 elmex 1.1 }
1174     }
1175    
1176     /*
1177     * merge_ob(op,top):
1178     *
1179     * This function goes through all objects below and including top, and
1180     * merges op to the first matching object.
1181     * If top is NULL, it is calculated.
1182     * Returns pointer to object if it succeded in the merge, otherwise NULL
1183     */
1184 root 1.24 object *
1185     merge_ob (object *op, object *top)
1186     {
1187     if (!op->nrof)
1188 elmex 1.1 return 0;
1189 root 1.29
1190 root 1.194 if (!top)
1191 root 1.82 for (top = op; top && top->above; top = top->above)
1192     ;
1193 root 1.29
1194 root 1.82 for (; top; top = top->below)
1195 root 1.214 if (object::can_merge (op, top))
1196     {
1197     top->nrof += op->nrof;
1198    
1199     if (object *pl = top->visible_to ())
1200     esrv_update_item (UPD_NROF, pl, top);
1201    
1202     op->weight = 0; // cancel the addition above
1203     op->carrying = 0; // must be 0 already
1204 root 1.66
1205 root 1.214 op->destroy (1);
1206 root 1.24
1207 root 1.214 return top;
1208     }
1209 root 1.29
1210 root 1.45 return 0;
1211 elmex 1.1 }
1212    
1213 root 1.138 void
1214     object::expand_tail ()
1215     {
1216     if (more)
1217     return;
1218    
1219     object *prev = this;
1220    
1221 root 1.160 for (archetype *at = (archetype *)arch->more; at; at = (archetype *)at->more)
1222 root 1.138 {
1223     object *op = arch_to_object (at);
1224    
1225     op->name = name;
1226     op->name_pl = name_pl;
1227     op->title = title;
1228    
1229     op->head = this;
1230     prev->more = op;
1231    
1232     prev = op;
1233     }
1234     }
1235    
1236 elmex 1.1 /*
1237 root 1.117 * same as insert_ob_in_map except it handles separate coordinates and does a clean
1238     * job preparing multi-part monsters.
1239 elmex 1.1 */
1240 root 1.24 object *
1241 root 1.49 insert_ob_in_map_at (object *op, maptile *m, object *originator, int flag, int x, int y)
1242 root 1.24 {
1243 root 1.244 op->remove ();
1244    
1245 root 1.93 for (object *tmp = op->head_ (); tmp; tmp = tmp->more)
1246 root 1.24 {
1247 root 1.159 tmp->x = x + tmp->arch->x;
1248     tmp->y = y + tmp->arch->y;
1249 elmex 1.1 }
1250 root 1.29
1251 root 1.24 return insert_ob_in_map (op, m, originator, flag);
1252 elmex 1.1 }
1253    
1254     /*
1255     * insert_ob_in_map (op, map, originator, flag):
1256     * This function inserts the object in the two-way linked list
1257     * which represents what is on a map.
1258     * The second argument specifies the map, and the x and y variables
1259     * in the object about to be inserted specifies the position.
1260     *
1261     * originator: Player, monster or other object that caused 'op' to be inserted
1262     * into 'map'. May be NULL.
1263     *
1264     * flag is a bitmask about special things to do (or not do) when this
1265     * function is called. see the object.h file for the INS_ values.
1266     * Passing 0 for flag gives proper default values, so flag really only needs
1267     * to be set if special handling is needed.
1268     *
1269     * Return value:
1270     * new object if 'op' was merged with other object
1271     * NULL if 'op' was destroyed
1272     * just 'op' otherwise
1273     */
1274 root 1.24 object *
1275 root 1.49 insert_ob_in_map (object *op, maptile *m, object *originator, int flag)
1276 elmex 1.1 {
1277 root 1.244 if (op->is_on_map ())
1278     {
1279     LOG (llevError, "insert_ob_in_map called for object already on map");
1280     abort ();
1281     }
1282    
1283     if (op->env)
1284     {
1285     LOG (llevError, "insert_ob_in_map called for object in an inventory (proceeding)");
1286     op->remove ();
1287     }
1288 root 1.117
1289 root 1.245 if (op->face && !face_info (op->face))//D TODO: remove soon
1290     {//D
1291     LOG (llevError | logBacktrace, "op->face out of bounds: %s", op->debug_desc ());//D
1292     op->face = 1;//D
1293     }//D
1294    
1295 root 1.187 /* Ideally, the caller figures this out. However, it complicates a lot
1296     * of areas of callers (eg, anything that uses find_free_spot would now
1297     * need extra work
1298     */
1299     if (!xy_normalise (m, op->x, op->y))
1300 root 1.24 {
1301 root 1.232 op->head_ ()->destroy (1);// remove head_ once all tail object destroyers found
1302 root 1.187 return 0;
1303 elmex 1.1 }
1304 root 1.25
1305 root 1.117 if (object *more = op->more)
1306 root 1.155 if (!insert_ob_in_map (more, m, originator, flag))
1307     return 0;
1308 root 1.25
1309 root 1.24 CLEAR_FLAG (op, FLAG_REMOVED);
1310 root 1.8
1311 root 1.117 op->map = m;
1312     mapspace &ms = op->ms ();
1313 root 1.24
1314     /* this has to be done after we translate the coordinates.
1315     */
1316     if (op->nrof && !(flag & INS_NO_MERGE))
1317 root 1.155 for (object *tmp = ms.bot; tmp; tmp = tmp->above)
1318 root 1.66 if (object::can_merge (op, tmp))
1319 root 1.25 {
1320 root 1.237 // TODO: we actually want to update tmp, not op,
1321 root 1.218 // but some caller surely breaks when we return tmp
1322     // from here :/
1323 root 1.25 op->nrof += tmp->nrof;
1324 root 1.208 tmp->destroy (1);
1325 root 1.25 }
1326 root 1.24
1327     CLEAR_FLAG (op, FLAG_APPLIED); /* hack for fixing F_APPLIED in items of dead people */
1328     CLEAR_FLAG (op, FLAG_INV_LOCKED);
1329 root 1.25
1330 root 1.24 if (!QUERY_FLAG (op, FLAG_ALIVE))
1331     CLEAR_FLAG (op, FLAG_NO_STEAL);
1332    
1333     if (flag & INS_BELOW_ORIGINATOR)
1334     {
1335 root 1.241 if (originator->map != op->map || originator->x != op->x || originator->y != op->y)
1336 root 1.24 {
1337     LOG (llevError, "insert_ob_in_map called with INS_BELOW_ORIGINATOR when originator not on same space!\n");
1338     abort ();
1339     }
1340 root 1.25
1341 root 1.241 if (!originator->is_on_map ())
1342     LOG (llevDebug | logBacktrace, "insert_ob_in_map(%s) called with INS_BELOW_ORIGINATOR when originator '%s' not on map",
1343     op->debug_desc (), originator->debug_desc ());
1344    
1345 root 1.24 op->above = originator;
1346     op->below = originator->below;
1347 root 1.237 originator->below = op;
1348 root 1.25
1349 root 1.237 *(op->below ? &op->below->above : &ms.bot) = op;
1350 elmex 1.1 }
1351 root 1.24 else
1352     {
1353 root 1.237 object *floor = 0;
1354     object *top = ms.top;
1355 root 1.117
1356 root 1.24 /* If there are other objects, then */
1357 root 1.191 if (top)
1358 root 1.24 {
1359     /*
1360     * If there are multiple objects on this space, we do some trickier handling.
1361     * We've already dealt with merging if appropriate.
1362     * Generally, we want to put the new object on top. But if
1363     * flag contains INS_ABOVE_FLOOR_ONLY, once we find the last
1364     * floor, we want to insert above that and no further.
1365     * Also, if there are spell objects on this space, we stop processing
1366     * once we get to them. This reduces the need to traverse over all of
1367     * them when adding another one - this saves quite a bit of cpu time
1368     * when lots of spells are cast in one area. Currently, it is presumed
1369     * that flying non pickable objects are spell objects.
1370     */
1371 root 1.237 for (object *tmp = ms.bot; tmp; tmp = tmp->above)
1372 root 1.24 {
1373 root 1.237 if (QUERY_FLAG (tmp, FLAG_IS_FLOOR) || QUERY_FLAG (tmp, FLAG_OVERLAY_FLOOR))
1374     floor = tmp;
1375 root 1.26
1376 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))
1377 root 1.24 {
1378     /* We insert above top, so we want this object below this */
1379 root 1.237 top = tmp->below;
1380 root 1.24 break;
1381     }
1382 root 1.26
1383 root 1.237 top = tmp;
1384 root 1.24 }
1385 root 1.26
1386 root 1.24 /* We let update_position deal with figuring out what the space
1387     * looks like instead of lots of conditions here.
1388     * makes things faster, and effectively the same result.
1389     */
1390    
1391     /* Have object 'fall below' other objects that block view.
1392 root 1.135 * Unless those objects are exits.
1393 root 1.24 * If INS_ON_TOP is used, don't do this processing
1394     * Need to find the object that in fact blocks view, otherwise
1395     * stacking is a bit odd.
1396     */
1397 root 1.117 if (!(flag & INS_ON_TOP)
1398     && ms.flags () & P_BLOCKSVIEW
1399 root 1.135 && (op->face && !faces [op->face].visibility))
1400 root 1.24 {
1401 root 1.237 object *last;
1402    
1403 root 1.24 for (last = top; last != floor; last = last->below)
1404     if (QUERY_FLAG (last, FLAG_BLOCKSVIEW) && (last->type != EXIT))
1405     break;
1406 root 1.117
1407 root 1.24 /* Check to see if we found the object that blocks view,
1408     * and make sure we have a below pointer for it so that
1409     * we can get inserted below this one, which requires we
1410     * set top to the object below us.
1411     */
1412     if (last && last->below && last != floor)
1413     top = last->below;
1414 root 1.8 }
1415 root 1.24 } /* If objects on this space */
1416 root 1.25
1417 root 1.24 if (flag & INS_ABOVE_FLOOR_ONLY)
1418     top = floor;
1419    
1420 root 1.240 // insert object above top, or bottom-most if top = 0
1421 root 1.24 if (!top)
1422     {
1423 root 1.239 op->below = 0;
1424     op->above = ms.bot;
1425     ms.bot = op;
1426 root 1.25
1427 root 1.239 *(op->above ? &op->above->below : &ms.top) = op;
1428 root 1.24 }
1429     else
1430 root 1.240 {
1431 root 1.24 op->above = top->above;
1432 root 1.237 top->above = op;
1433 root 1.25
1434 root 1.24 op->below = top;
1435 root 1.237 *(op->above ? &op->above->below : &ms.top) = op;
1436 root 1.24 }
1437 root 1.240 }
1438 root 1.8
1439 root 1.24 if (op->type == PLAYER)
1440 root 1.96 {
1441     op->contr->do_los = 1;
1442     ++op->map->players;
1443 root 1.100 op->map->touch ();
1444 root 1.96 }
1445 root 1.24
1446 root 1.98 op->map->dirty = true;
1447    
1448 root 1.191 if (object *pl = ms.player ())
1449 root 1.218 //TODO: the floorbox prev/next might need updating
1450 root 1.226 //esrv_send_item (pl, op);
1451     //TODO: update floorbox to preserve ordering
1452     if (pl->contr->ns)
1453     pl->contr->ns->floorbox_update ();
1454 root 1.24
1455     /* If this object glows, it may affect lighting conditions that are
1456     * visible to others on this map. But update_all_los is really
1457     * an inefficient way to do this, as it means los for all players
1458     * on the map will get recalculated. The players could very well
1459     * be far away from this change and not affected in any way -
1460     * this should get redone to only look for players within range,
1461 root 1.99 * or just updating the P_UPTODATE for spaces within this area
1462 root 1.24 * of effect may be sufficient.
1463     */
1464 root 1.84 if (op->map->darkness && (op->glow_radius != 0))
1465 root 1.24 update_all_los (op->map, op->x, op->y);
1466    
1467     /* updates flags (blocked, alive, no magic, etc) for this map space */
1468     update_object (op, UP_OBJ_INSERT);
1469    
1470 root 1.82 INVOKE_OBJECT (INSERT, op);
1471    
1472 root 1.24 /* Don't know if moving this to the end will break anything. However,
1473 root 1.70 * we want to have floorbox_update called before calling this.
1474 root 1.24 *
1475     * check_move_on() must be after this because code called from
1476     * check_move_on() depends on correct map flags (so functions like
1477     * blocked() and wall() work properly), and these flags are updated by
1478     * update_object().
1479     */
1480    
1481     /* if this is not the head or flag has been passed, don't check walk on status */
1482 root 1.155 if (!(flag & INS_NO_WALK_ON) && op->head_ () == op)
1483 root 1.24 {
1484     if (check_move_on (op, originator))
1485 root 1.82 return 0;
1486 elmex 1.1
1487 root 1.24 /* If we are a multi part object, lets work our way through the check
1488     * walk on's.
1489     */
1490 root 1.155 for (object *tmp = op->more; tmp; tmp = tmp->more)
1491 root 1.24 if (check_move_on (tmp, originator))
1492 root 1.82 return 0;
1493 elmex 1.1 }
1494 root 1.25
1495 root 1.24 return op;
1496 elmex 1.1 }
1497    
1498     /* this function inserts an object in the map, but if it
1499 root 1.75 * finds an object of its own type, it'll remove that one first.
1500     * op is the object to insert it under: supplies x and the map.
1501 elmex 1.1 */
1502 root 1.24 void
1503     replace_insert_ob_in_map (const char *arch_string, object *op)
1504     {
1505     /* first search for itself and remove any old instances */
1506 elmex 1.1
1507 root 1.208 for (object *tmp = op->ms ().bot; tmp; tmp = tmp->above)
1508 root 1.158 if (!strcmp (tmp->arch->archname, arch_string)) /* same archetype */
1509 root 1.208 tmp->destroy (1);
1510    
1511     object *tmp = arch_to_object (archetype::find (arch_string));
1512 elmex 1.1
1513 root 1.208 tmp->x = op->x;
1514     tmp->y = op->y;
1515 elmex 1.1
1516 root 1.208 insert_ob_in_map (tmp, op->map, op, 0);
1517 root 1.24 }
1518 elmex 1.1
1519 root 1.93 object *
1520     object::insert_at (object *where, object *originator, int flags)
1521     {
1522 root 1.205 if (where->env)
1523     return where->env->insert (this);
1524     else
1525     return where->map->insert (this, where->x, where->y, originator, flags);
1526 root 1.93 }
1527    
1528 elmex 1.1 /*
1529 root 1.209 * decrease(object, number) decreases a specified number from
1530 root 1.208 * the amount of an object. If the amount reaches 0, the object
1531 elmex 1.1 * is subsequently removed and freed.
1532     *
1533     * Return value: 'op' if something is left, NULL if the amount reached 0
1534     */
1535 root 1.208 bool
1536 root 1.209 object::decrease (sint32 nr)
1537 elmex 1.1 {
1538 root 1.212 if (!nr)
1539     return true;
1540    
1541 root 1.208 nr = min (nr, nrof);
1542 elmex 1.1
1543 root 1.208 nrof -= nr;
1544 root 1.24
1545 root 1.208 if (nrof)
1546 elmex 1.1 {
1547 root 1.247 adjust_weight (env, -weight * max (1, nr)); // carrying == 0
1548 elmex 1.1
1549 root 1.212 if (object *pl = visible_to ())
1550     esrv_update_item (UPD_NROF, pl, this);
1551 root 1.29
1552 root 1.212 return true;
1553 elmex 1.1 }
1554 root 1.24 else
1555     {
1556 root 1.249 destroy ();
1557 root 1.212 return false;
1558 elmex 1.1 }
1559     }
1560    
1561 root 1.209 /*
1562 root 1.210 * split(ob,nr) splits up ob into two parts. The part which
1563 root 1.209 * is returned contains nr objects, and the remaining parts contains
1564 root 1.210 * the rest (or is removed and returned if that number is 0).
1565     * On failure, NULL is returned.
1566 root 1.209 */
1567 root 1.208 object *
1568 root 1.209 object::split (sint32 nr)
1569 root 1.208 {
1570 root 1.212 int have = number_of ();
1571    
1572     if (have < nr)
1573 root 1.209 return 0;
1574 root 1.212 else if (have == nr)
1575 root 1.209 {
1576     remove ();
1577     return this;
1578     }
1579     else
1580     {
1581     decrease (nr);
1582    
1583 root 1.230 object *op = deep_clone ();
1584 root 1.209 op->nrof = nr;
1585     return op;
1586     }
1587     }
1588    
1589 root 1.24 object *
1590     insert_ob_in_ob (object *op, object *where)
1591     {
1592 root 1.59 if (!where)
1593 root 1.24 {
1594 root 1.53 char *dump = dump_object (op);
1595     LOG (llevError, "Trying to put object in NULL.\n%s\n", dump);
1596     free (dump);
1597 root 1.24 return op;
1598     }
1599 root 1.29
1600 root 1.154 if (where->head_ () != where)
1601 root 1.24 {
1602 root 1.153 LOG (llevError | logBacktrace, "Warning: Tried to insert object into wrong part of multipart object.\n");
1603 root 1.24 where = where->head;
1604     }
1605 root 1.29
1606 root 1.59 return where->insert (op);
1607     }
1608    
1609     /*
1610     * env->insert (op)
1611     * This function inserts the object op in the linked list
1612     * inside the object environment.
1613     *
1614     * The function returns now pointer to inserted item, and return value can
1615     * be != op, if items are merged. -Tero
1616     */
1617     object *
1618     object::insert (object *op)
1619     {
1620 root 1.24 if (op->more)
1621     {
1622     LOG (llevError, "Tried to insert multipart object %s (%d)\n", &op->name, op->count);
1623     return op;
1624     }
1625 root 1.29
1626 root 1.208 op->remove ();
1627    
1628     op->flag [FLAG_OBJ_ORIGINAL] = 0;
1629 root 1.182
1630 root 1.24 if (op->nrof)
1631 root 1.208 for (object *tmp = inv; tmp; tmp = tmp->below)
1632     if (object::can_merge (tmp, op))
1633     {
1634     /* return the original object and remove inserted object
1635     (client needs the original object) */
1636     tmp->nrof += op->nrof;
1637 root 1.214
1638     if (object *pl = tmp->visible_to ())
1639     esrv_update_item (UPD_NROF, pl, tmp);
1640    
1641 root 1.210 adjust_weight (this, op->total_weight ());
1642    
1643 root 1.208 op->destroy (1);
1644     op = tmp;
1645     goto inserted;
1646     }
1647    
1648     op->owner = 0; // it's his/hers now. period.
1649     op->map = 0;
1650     op->x = 0;
1651     op->y = 0;
1652    
1653     op->above = 0;
1654     op->below = inv;
1655     op->env = this;
1656    
1657     if (inv)
1658     inv->above = op;
1659 root 1.24
1660 root 1.208 inv = op;
1661 elmex 1.1
1662 root 1.208 op->flag [FLAG_REMOVED] = 0;
1663 elmex 1.1
1664 root 1.214 if (object *pl = op->visible_to ())
1665     esrv_send_item (pl, op);
1666    
1667 root 1.208 adjust_weight (this, op->total_weight ());
1668 elmex 1.1
1669 root 1.208 inserted:
1670 elmex 1.1 /* reset the light list and los of the players on the map */
1671 root 1.208 if (op->glow_radius && map && map->darkness)
1672     update_all_los (map, x, y);
1673 elmex 1.1
1674 root 1.214 // if this is a player's inventory, update stats
1675     if (type == PLAYER && !flag [FLAG_NO_FIX_PLAYER])
1676     update_stats ();
1677 root 1.59
1678 root 1.82 INVOKE_OBJECT (INSERT, this);
1679    
1680 elmex 1.1 return op;
1681     }
1682    
1683     /*
1684     * Checks if any objects has a move_type that matches objects
1685     * that effect this object on this space. Call apply() to process
1686     * these events.
1687     *
1688     * Any speed-modification due to SLOW_MOVE() of other present objects
1689     * will affect the speed_left of the object.
1690     *
1691     * originator: Player, monster or other object that caused 'op' to be inserted
1692     * into 'map'. May be NULL.
1693     *
1694     * Return value: 1 if 'op' was destroyed, 0 otherwise.
1695     *
1696     * 4-21-95 added code to check if appropriate skill was readied - this will
1697     * permit faster movement by the player through this terrain. -b.t.
1698     *
1699     * MSW 2001-07-08: Check all objects on space, not just those below
1700     * object being inserted. insert_ob_in_map may not put new objects
1701     * on top.
1702     */
1703 root 1.24 int
1704     check_move_on (object *op, object *originator)
1705 elmex 1.1 {
1706 root 1.48 object *tmp;
1707 root 1.49 maptile *m = op->map;
1708 root 1.48 int x = op->x, y = op->y;
1709 root 1.26
1710 root 1.48 MoveType move_on, move_slow, move_block;
1711 root 1.24
1712     if (QUERY_FLAG (op, FLAG_NO_APPLY))
1713     return 0;
1714    
1715     move_on = GET_MAP_MOVE_ON (op->map, op->x, op->y);
1716     move_slow = GET_MAP_MOVE_SLOW (op->map, op->x, op->y);
1717     move_block = GET_MAP_MOVE_BLOCK (op->map, op->x, op->y);
1718    
1719     /* if nothing on this space will slow op down or be applied,
1720     * no need to do checking below. have to make sure move_type
1721     * is set, as lots of objects don't have it set - we treat that
1722     * as walking.
1723     */
1724     if (op->move_type && !(op->move_type & move_on) && !(op->move_type & move_slow))
1725     return 0;
1726 elmex 1.1
1727 root 1.24 /* This is basically inverse logic of that below - basically,
1728     * if the object can avoid the move on or slow move, they do so,
1729     * but can't do it if the alternate movement they are using is
1730     * blocked. Logic on this seems confusing, but does seem correct.
1731     */
1732     if ((op->move_type & ~move_on & ~move_block) != 0 && (op->move_type & ~move_slow & ~move_block) != 0)
1733     return 0;
1734    
1735     /* The objects have to be checked from top to bottom.
1736     * Hence, we first go to the top:
1737     */
1738    
1739 root 1.104 for (tmp = op->ms ().bot; tmp && tmp->above; tmp = tmp->above)
1740 root 1.24 {
1741     /* Trim the search when we find the first other spell effect
1742     * this helps performance so that if a space has 50 spell objects,
1743     * we don't need to check all of them.
1744     */
1745     if ((tmp->move_type & MOVE_FLY_LOW) && QUERY_FLAG (tmp, FLAG_NO_PICK))
1746     break;
1747     }
1748 root 1.26
1749     for (; tmp; tmp = tmp->below)
1750 root 1.24 {
1751     if (tmp == op)
1752     continue; /* Can't apply yourself */
1753 elmex 1.1
1754 root 1.24 /* Check to see if one of the movement types should be slowed down.
1755     * Second check makes sure that the movement types not being slowed
1756     * (~slow_move) is not blocked on this space - just because the
1757     * space doesn't slow down swimming (for example), if you can't actually
1758     * swim on that space, can't use it to avoid the penalty.
1759     */
1760     if (!QUERY_FLAG (op, FLAG_WIZPASS))
1761     {
1762     if ((!op->move_type && tmp->move_slow & MOVE_WALK) ||
1763     ((op->move_type & tmp->move_slow) && (op->move_type & ~tmp->move_slow & ~tmp->move_block) == 0))
1764     {
1765 elmex 1.1
1766 root 1.29 float
1767 root 1.120 diff = tmp->move_slow_penalty * fabs (op->speed);
1768 elmex 1.1
1769 root 1.24 if (op->type == PLAYER)
1770 root 1.26 if ((QUERY_FLAG (tmp, FLAG_IS_HILLY) && find_skill_by_number (op, SK_CLIMBING)) ||
1771     (QUERY_FLAG (tmp, FLAG_IS_WOODED) && find_skill_by_number (op, SK_WOODSMAN)))
1772     diff /= 4.0;
1773    
1774 root 1.24 op->speed_left -= diff;
1775 root 1.8 }
1776     }
1777 elmex 1.1
1778 root 1.24 /* Basically same logic as above, except now for actual apply. */
1779     if ((!op->move_type && tmp->move_on & MOVE_WALK) ||
1780     ((op->move_type & tmp->move_on) && (op->move_type & ~tmp->move_on & ~tmp->move_block) == 0))
1781     {
1782 elmex 1.72 move_apply (tmp, op, originator);
1783 root 1.24
1784 root 1.48 if (op->destroyed ())
1785 root 1.24 return 1;
1786    
1787     /* what the person/creature stepped onto has moved the object
1788     * someplace new. Don't process any further - if we did,
1789     * have a feeling strange problems would result.
1790     */
1791     if (op->map != m || op->x != x || op->y != y)
1792     return 0;
1793 root 1.8 }
1794 elmex 1.1 }
1795 root 1.26
1796 root 1.24 return 0;
1797 elmex 1.1 }
1798    
1799     /*
1800     * present_arch(arch, map, x, y) searches for any objects with
1801     * a matching archetype at the given map and coordinates.
1802     * The first matching object is returned, or NULL if none.
1803     */
1804 root 1.24 object *
1805 root 1.49 present_arch (const archetype *at, maptile *m, int x, int y)
1806 root 1.24 {
1807 root 1.104 if (!m || out_of_map (m, x, y))
1808 root 1.24 {
1809     LOG (llevError, "Present_arch called outside map.\n");
1810     return NULL;
1811     }
1812 root 1.84
1813 root 1.104 for (object *tmp = m->at (x, y).bot; tmp; tmp = tmp->above)
1814 root 1.231 if (tmp->arch->archname == at->archname)
1815 elmex 1.1 return tmp;
1816 root 1.84
1817 elmex 1.1 return NULL;
1818     }
1819    
1820     /*
1821     * present(type, map, x, y) searches for any objects with
1822     * a matching type variable at the given map and coordinates.
1823     * The first matching object is returned, or NULL if none.
1824     */
1825 root 1.24 object *
1826 root 1.49 present (unsigned char type, maptile *m, int x, int y)
1827 root 1.24 {
1828     if (out_of_map (m, x, y))
1829     {
1830     LOG (llevError, "Present called outside map.\n");
1831     return NULL;
1832     }
1833 root 1.84
1834 root 1.104 for (object *tmp = m->at (x, y).bot; tmp; tmp = tmp->above)
1835 root 1.24 if (tmp->type == type)
1836 elmex 1.1 return tmp;
1837 root 1.84
1838 elmex 1.1 return NULL;
1839     }
1840    
1841     /*
1842     * present_in_ob(type, object) searches for any objects with
1843     * a matching type variable in the inventory of the given object.
1844     * The first matching object is returned, or NULL if none.
1845     */
1846 root 1.24 object *
1847     present_in_ob (unsigned char type, const object *op)
1848     {
1849 root 1.84 for (object *tmp = op->inv; tmp != NULL; tmp = tmp->below)
1850 root 1.24 if (tmp->type == type)
1851 elmex 1.1 return tmp;
1852 root 1.84
1853 elmex 1.1 return NULL;
1854     }
1855    
1856     /*
1857     * present_in_ob (type, str, object) searches for any objects with
1858     * a matching type & name variable in the inventory of the given object.
1859     * The first matching object is returned, or NULL if none.
1860     * This is mostly used by spell effect code, so that we only
1861     * have one spell effect at a time.
1862     * type can be used to narrow the search - if type is set,
1863     * the type must also match. -1 can be passed for the type,
1864     * in which case the type does not need to pass.
1865     * str is the string to match against. Note that we match against
1866     * the object name, not the archetype name. this is so that the
1867     * spell code can use one object type (force), but change it's name
1868     * to be unique.
1869     */
1870 root 1.24 object *
1871     present_in_ob_by_name (int type, const char *str, const object *op)
1872     {
1873 root 1.84 for (object *tmp = op->inv; tmp; tmp = tmp->below)
1874 root 1.82 if ((type == -1 || tmp->type == type) && (!strcmp (str, tmp->name)))
1875     return tmp;
1876 elmex 1.1
1877 root 1.82 return 0;
1878 elmex 1.1 }
1879    
1880     /*
1881     * present_arch_in_ob(archetype, object) searches for any objects with
1882     * a matching archetype in the inventory of the given object.
1883     * The first matching object is returned, or NULL if none.
1884     */
1885 root 1.24 object *
1886     present_arch_in_ob (const archetype *at, const object *op)
1887     {
1888 root 1.231 for (object *tmp = op->inv; tmp; tmp = tmp->below)
1889     if (tmp->arch->archname == at->archname)
1890 elmex 1.1 return tmp;
1891 root 1.82
1892 elmex 1.1 return NULL;
1893     }
1894    
1895     /*
1896     * activate recursively a flag on an object inventory
1897     */
1898 root 1.24 void
1899     flag_inv (object *op, int flag)
1900     {
1901 root 1.197 for (object *tmp = op->inv; tmp; tmp = tmp->below)
1902     {
1903     SET_FLAG (tmp, flag);
1904     flag_inv (tmp, flag);
1905     }
1906 root 1.82 }
1907    
1908     /*
1909     * deactivate recursively a flag on an object inventory
1910     */
1911 root 1.24 void
1912     unflag_inv (object *op, int flag)
1913     {
1914 root 1.197 for (object *tmp = op->inv; tmp; tmp = tmp->below)
1915     {
1916     CLEAR_FLAG (tmp, flag);
1917     unflag_inv (tmp, flag);
1918     }
1919 elmex 1.1 }
1920    
1921     /*
1922     * find_free_spot(object, map, x, y, start, stop) will search for
1923     * a spot at the given map and coordinates which will be able to contain
1924     * the given object. start and stop specifies how many squares
1925     * to search (see the freearr_x/y[] definition).
1926     * It returns a random choice among the alternatives found.
1927     * start and stop are where to start relative to the free_arr array (1,9
1928     * does all 4 immediate directions). This returns the index into the
1929     * array of the free spot, -1 if no spot available (dir 0 = x,y)
1930 root 1.196 * Note: This function does correctly handle tiled maps, but does not
1931 elmex 1.1 * inform the caller. However, insert_ob_in_map will update as
1932     * necessary, so the caller shouldn't need to do any special work.
1933     * Note - updated to take an object instead of archetype - this is necessary
1934     * because arch_blocked (now ob_blocked) needs to know the movement type
1935     * to know if the space in question will block the object. We can't use
1936     * the archetype because that isn't correct if the monster has been
1937     * customized, changed states, etc.
1938     */
1939 root 1.24 int
1940 root 1.49 find_free_spot (const object *ob, maptile *m, int x, int y, int start, int stop)
1941 root 1.24 {
1942 root 1.190 int altern[SIZEOFFREE];
1943 root 1.82 int index = 0, flag;
1944 root 1.24
1945 root 1.82 for (int i = start; i < stop; i++)
1946 root 1.24 {
1947 root 1.188 mapxy pos (m, x, y); pos.move (i);
1948    
1949     if (!pos.normalise ())
1950     continue;
1951    
1952     mapspace &ms = *pos;
1953 root 1.189
1954     if (ms.flags () & P_IS_ALIVE)
1955     continue;
1956 root 1.188
1957     /* However, often
1958     * ob doesn't have any move type (when used to place exits)
1959     * so the AND operation in OB_TYPE_MOVE_BLOCK doesn't work.
1960     */
1961 root 1.200 if (ob && ob->move_type == 0 && ms.move_block != MOVE_ALL)
1962 root 1.190 {
1963     altern [index++] = i;
1964     continue;
1965     }
1966 root 1.24
1967     /* Basically, if we find a wall on a space, we cut down the search size.
1968     * In this way, we won't return spaces that are on another side of a wall.
1969     * This mostly work, but it cuts down the search size in all directions -
1970     * if the space being examined only has a wall to the north and empty
1971     * spaces in all the other directions, this will reduce the search space
1972     * to only the spaces immediately surrounding the target area, and
1973     * won't look 2 spaces south of the target space.
1974     */
1975 root 1.188 if (ms.move_block == MOVE_ALL && maxfree[i] < stop)
1976     {
1977     stop = maxfree[i];
1978     continue;
1979     }
1980    
1981     /* Note it is intentional that we check ob - the movement type of the
1982     * head of the object should correspond for the entire object.
1983     */
1984     if (OB_TYPE_MOVE_BLOCK (ob, ms.move_block))
1985     continue;
1986    
1987 root 1.196 if (ob->blocked (m, pos.x, pos.y))
1988     continue;
1989    
1990 root 1.188 altern [index++] = i;
1991 elmex 1.1 }
1992 root 1.74
1993 root 1.24 if (!index)
1994     return -1;
1995 root 1.74
1996 root 1.124 return altern [rndm (index)];
1997 elmex 1.1 }
1998    
1999     /*
2000 root 1.49 * find_first_free_spot(archetype, maptile, x, y) works like
2001 elmex 1.1 * find_free_spot(), but it will search max number of squares.
2002     * But it will return the first available spot, not a random choice.
2003     * Changed 0.93.2: Have it return -1 if there is no free spot available.
2004     */
2005 root 1.24 int
2006 root 1.49 find_first_free_spot (const object *ob, maptile *m, int x, int y)
2007 root 1.24 {
2008 root 1.82 for (int i = 0; i < SIZEOFFREE; i++)
2009 root 1.188 if (!ob->blocked (m, x + freearr_x[i], y + freearr_y[i]))
2010 root 1.82 return i;
2011 root 1.24
2012     return -1;
2013 elmex 1.1 }
2014    
2015     /*
2016     * The function permute(arr, begin, end) randomly reorders the array
2017     * arr[begin..end-1].
2018 root 1.82 * now uses a fisher-yates shuffle, old permute was broken
2019 elmex 1.1 */
2020 root 1.24 static void
2021     permute (int *arr, int begin, int end)
2022 elmex 1.1 {
2023 root 1.82 arr += begin;
2024     end -= begin;
2025    
2026     while (--end)
2027 root 1.124 swap (arr [end], arr [rndm (end + 1)]);
2028 elmex 1.1 }
2029    
2030     /* new function to make monster searching more efficient, and effective!
2031     * This basically returns a randomized array (in the passed pointer) of
2032     * the spaces to find monsters. In this way, it won't always look for
2033     * monsters to the north first. However, the size of the array passed
2034     * covers all the spaces, so within that size, all the spaces within
2035     * the 3x3 area will be searched, just not in a predictable order.
2036     */
2037 root 1.24 void
2038     get_search_arr (int *search_arr)
2039 elmex 1.1 {
2040 root 1.82 int i;
2041 elmex 1.1
2042 root 1.24 for (i = 0; i < SIZEOFFREE; i++)
2043 root 1.82 search_arr[i] = i;
2044 elmex 1.1
2045 root 1.24 permute (search_arr, 1, SIZEOFFREE1 + 1);
2046     permute (search_arr, SIZEOFFREE1 + 1, SIZEOFFREE2 + 1);
2047     permute (search_arr, SIZEOFFREE2 + 1, SIZEOFFREE);
2048 elmex 1.1 }
2049    
2050     /*
2051     * find_dir(map, x, y, exclude) will search some close squares in the
2052     * given map at the given coordinates for live objects.
2053     * It will not considered the object given as exclude among possible
2054     * live objects.
2055     * It returns the direction toward the first/closest live object if finds
2056     * any, otherwise 0.
2057     * Perhaps incorrectly, but I'm making the assumption that exclude
2058     * is actually want is going to try and move there. We need this info
2059     * because we have to know what movement the thing looking to move
2060     * there is capable of.
2061     */
2062 root 1.24 int
2063 root 1.49 find_dir (maptile *m, int x, int y, object *exclude)
2064 root 1.24 {
2065 root 1.82 int i, max = SIZEOFFREE, mflags;
2066 root 1.29
2067     sint16 nx, ny;
2068 root 1.82 object *tmp;
2069     maptile *mp;
2070 root 1.29
2071     MoveType blocked, move_type;
2072 root 1.24
2073 root 1.155 if (exclude && exclude->head_ () != exclude)
2074 root 1.24 {
2075     exclude = exclude->head;
2076     move_type = exclude->move_type;
2077     }
2078     else
2079     {
2080     /* If we don't have anything, presume it can use all movement types. */
2081     move_type = MOVE_ALL;
2082     }
2083    
2084     for (i = 1; i < max; i++)
2085     {
2086     mp = m;
2087     nx = x + freearr_x[i];
2088     ny = y + freearr_y[i];
2089    
2090     mflags = get_map_flags (m, &mp, nx, ny, &nx, &ny);
2091 root 1.75
2092 root 1.24 if (mflags & P_OUT_OF_MAP)
2093 root 1.75 max = maxfree[i];
2094 root 1.24 else
2095     {
2096 root 1.82 mapspace &ms = mp->at (nx, ny);
2097    
2098     blocked = ms.move_block;
2099 root 1.24
2100     if ((move_type & blocked) == move_type)
2101 root 1.75 max = maxfree[i];
2102 root 1.24 else if (mflags & P_IS_ALIVE)
2103     {
2104 root 1.84 for (tmp = ms.bot; tmp; tmp = tmp->above)
2105 root 1.82 if ((tmp->flag [FLAG_MONSTER] || tmp->type == PLAYER)
2106 root 1.155 && (tmp != exclude || (tmp->head_ () != tmp && tmp->head_ () != exclude)))
2107 root 1.75 break;
2108    
2109 root 1.24 if (tmp)
2110 root 1.75 return freedir[i];
2111 root 1.8 }
2112     }
2113 elmex 1.1 }
2114 root 1.75
2115 root 1.24 return 0;
2116 elmex 1.1 }
2117    
2118     /*
2119     * distance(object 1, object 2) will return the square of the
2120     * distance between the two given objects.
2121     */
2122 root 1.24 int
2123     distance (const object *ob1, const object *ob2)
2124     {
2125 root 1.82 return (ob1->x - ob2->x) * (ob1->x - ob2->x) + (ob1->y - ob2->y) * (ob1->y - ob2->y);
2126 elmex 1.1 }
2127    
2128     /*
2129     * find_dir_2(delta-x,delta-y) will return a direction in which
2130     * an object which has subtracted the x and y coordinates of another
2131     * object, needs to travel toward it.
2132     */
2133 root 1.24 int
2134     find_dir_2 (int x, int y)
2135     {
2136 root 1.75 int q;
2137 elmex 1.1
2138 root 1.24 if (y)
2139     q = x * 100 / y;
2140 elmex 1.1 else if (x)
2141 root 1.24 q = -300 * x;
2142 elmex 1.1 else
2143     return 0;
2144    
2145 root 1.24 if (y > 0)
2146     {
2147     if (q < -242)
2148     return 3;
2149     if (q < -41)
2150     return 2;
2151     if (q < 41)
2152     return 1;
2153     if (q < 242)
2154     return 8;
2155     return 7;
2156     }
2157 elmex 1.1
2158     if (q < -242)
2159 root 1.24 return 7;
2160 elmex 1.1 if (q < -41)
2161 root 1.24 return 6;
2162 elmex 1.1 if (q < 41)
2163 root 1.24 return 5;
2164 elmex 1.1 if (q < 242)
2165 root 1.24 return 4;
2166 elmex 1.1
2167 root 1.24 return 3;
2168 elmex 1.1 }
2169    
2170     /*
2171     * dirdiff(dir1, dir2) returns how many 45-degrees differences there is
2172     * between two directions (which are expected to be absolute (see absdir())
2173     */
2174 root 1.24 int
2175     dirdiff (int dir1, int dir2)
2176     {
2177 root 1.82 int d;
2178 root 1.24
2179     d = abs (dir1 - dir2);
2180     if (d > 4)
2181 elmex 1.1 d = 8 - d;
2182 root 1.82
2183 elmex 1.1 return d;
2184     }
2185    
2186     /* peterm:
2187     * do LOS stuff for ball lightning. Go after the closest VISIBLE monster.
2188     * Basically, this is a table of directions, and what directions
2189     * one could go to go back to us. Eg, entry 15 below is 4, 14, 16.
2190     * This basically means that if direction is 15, then it could either go
2191     * direction 4, 14, or 16 to get back to where we are.
2192     * Moved from spell_util.c to object.c with the other related direction
2193     * functions.
2194     */
2195 root 1.82 int reduction_dir[SIZEOFFREE][3] = {
2196 root 1.24 {0, 0, 0}, /* 0 */
2197     {0, 0, 0}, /* 1 */
2198     {0, 0, 0}, /* 2 */
2199     {0, 0, 0}, /* 3 */
2200     {0, 0, 0}, /* 4 */
2201     {0, 0, 0}, /* 5 */
2202     {0, 0, 0}, /* 6 */
2203     {0, 0, 0}, /* 7 */
2204     {0, 0, 0}, /* 8 */
2205     {8, 1, 2}, /* 9 */
2206     {1, 2, -1}, /* 10 */
2207     {2, 10, 12}, /* 11 */
2208     {2, 3, -1}, /* 12 */
2209     {2, 3, 4}, /* 13 */
2210     {3, 4, -1}, /* 14 */
2211     {4, 14, 16}, /* 15 */
2212     {5, 4, -1}, /* 16 */
2213     {4, 5, 6}, /* 17 */
2214     {6, 5, -1}, /* 18 */
2215     {6, 20, 18}, /* 19 */
2216     {7, 6, -1}, /* 20 */
2217     {6, 7, 8}, /* 21 */
2218     {7, 8, -1}, /* 22 */
2219     {8, 22, 24}, /* 23 */
2220     {8, 1, -1}, /* 24 */
2221     {24, 9, 10}, /* 25 */
2222     {9, 10, -1}, /* 26 */
2223     {10, 11, -1}, /* 27 */
2224     {27, 11, 29}, /* 28 */
2225     {11, 12, -1}, /* 29 */
2226     {12, 13, -1}, /* 30 */
2227     {12, 13, 14}, /* 31 */
2228     {13, 14, -1}, /* 32 */
2229     {14, 15, -1}, /* 33 */
2230     {33, 15, 35}, /* 34 */
2231     {16, 15, -1}, /* 35 */
2232     {17, 16, -1}, /* 36 */
2233     {18, 17, 16}, /* 37 */
2234     {18, 17, -1}, /* 38 */
2235     {18, 19, -1}, /* 39 */
2236     {41, 19, 39}, /* 40 */
2237     {19, 20, -1}, /* 41 */
2238     {20, 21, -1}, /* 42 */
2239     {20, 21, 22}, /* 43 */
2240     {21, 22, -1}, /* 44 */
2241     {23, 22, -1}, /* 45 */
2242     {45, 47, 23}, /* 46 */
2243     {23, 24, -1}, /* 47 */
2244     {24, 9, -1}
2245     }; /* 48 */
2246 elmex 1.1
2247     /* Recursive routine to step back and see if we can
2248     * find a path to that monster that we found. If not,
2249     * we don't bother going toward it. Returns 1 if we
2250     * can see a direct way to get it
2251     * Modified to be map tile aware -.MSW
2252     */
2253 root 1.24 int
2254 root 1.49 can_see_monsterP (maptile *m, int x, int y, int dir)
2255 root 1.24 {
2256 root 1.29 sint16 dx, dy;
2257 root 1.75 int mflags;
2258 root 1.24
2259     if (dir < 0)
2260     return 0; /* exit condition: invalid direction */
2261    
2262     dx = x + freearr_x[dir];
2263     dy = y + freearr_y[dir];
2264    
2265     mflags = get_map_flags (m, &m, dx, dy, &dx, &dy);
2266    
2267     /* This functional arguably was incorrect before - it was
2268     * checking for P_WALL - that was basically seeing if
2269     * we could move to the monster - this is being more
2270     * literal on if we can see it. To know if we can actually
2271     * move to the monster, we'd need the monster passed in or
2272     * at least its move type.
2273     */
2274     if (mflags & (P_OUT_OF_MAP | P_BLOCKSVIEW))
2275     return 0;
2276    
2277     /* yes, can see. */
2278     if (dir < 9)
2279     return 1;
2280 root 1.75
2281     return can_see_monsterP (m, x, y, reduction_dir[dir][0])
2282     | can_see_monsterP (m, x, y, reduction_dir[dir][1])
2283     | can_see_monsterP (m, x, y, reduction_dir[dir][2]);
2284 root 1.24 }
2285    
2286 elmex 1.1 /*
2287     * can_pick(picker, item): finds out if an object is possible to be
2288     * picked up by the picker. Returnes 1 if it can be
2289     * picked up, otherwise 0.
2290     *
2291     * Cf 0.91.3 - don't let WIZ's pick up anything - will likely cause
2292     * core dumps if they do.
2293     *
2294     * Add a check so we can't pick up invisible objects (0.93.8)
2295     */
2296 root 1.24 int
2297     can_pick (const object *who, const object *item)
2298     {
2299     return /*QUERY_FLAG(who,FLAG_WIZ)|| */
2300     (item->weight > 0 && !QUERY_FLAG (item, FLAG_NO_PICK) &&
2301     !QUERY_FLAG (item, FLAG_ALIVE) && !item->invisible && (who->type == PLAYER || item->weight < who->weight / 3));
2302 elmex 1.1 }
2303    
2304     /*
2305     * create clone from object to another
2306     */
2307 root 1.24 object *
2308 root 1.230 object::deep_clone ()
2309 root 1.24 {
2310 root 1.230 assert (("deep_clone called on non-head object", is_head ()));
2311 elmex 1.1
2312 root 1.230 object *dst = clone ();
2313 root 1.24
2314 root 1.230 object *prev = dst;
2315     for (object *part = this->more; part; part = part->more)
2316 root 1.24 {
2317 root 1.224 object *tmp = part->clone ();
2318 root 1.230 tmp->head = dst;
2319     prev->more = tmp;
2320 root 1.24 prev = tmp;
2321 elmex 1.1 }
2322 root 1.24
2323 root 1.230 for (object *item = inv; item; item = item->below)
2324     insert_ob_in_ob (item->deep_clone (), dst);
2325 elmex 1.1
2326 root 1.24 return dst;
2327 elmex 1.1 }
2328    
2329     /* This returns the first object in who's inventory that
2330     * has the same type and subtype match.
2331     * returns NULL if no match.
2332     */
2333 root 1.24 object *
2334     find_obj_by_type_subtype (const object *who, int type, int subtype)
2335 elmex 1.1 {
2336 root 1.82 for (object *tmp = who->inv; tmp; tmp = tmp->below)
2337 root 1.24 if (tmp->type == type && tmp->subtype == subtype)
2338     return tmp;
2339 elmex 1.1
2340 root 1.82 return 0;
2341 elmex 1.1 }
2342    
2343 root 1.228 const shstr &
2344     object::kv_get (const shstr &key) const
2345 root 1.24 {
2346 root 1.228 for (key_value *kv = key_values; kv; kv = kv->next)
2347     if (kv->key == key)
2348     return kv->value;
2349 root 1.24
2350 root 1.228 return shstr_null;
2351 root 1.24 }
2352 elmex 1.1
2353 root 1.228 void
2354     object::kv_set (const shstr &key, const shstr &value)
2355 root 1.24 {
2356 root 1.228 for (key_value *kv = key_values; kv; kv = kv->next)
2357     if (kv->key == key)
2358     {
2359     kv->value = value;
2360     return;
2361     }
2362 root 1.24
2363 root 1.228 key_value *kv = new key_value;
2364 elmex 1.1
2365 root 1.228 kv->next = key_values;
2366     kv->key = key;
2367     kv->value = value;
2368 root 1.35
2369 root 1.228 key_values = kv;
2370 elmex 1.1 }
2371    
2372 root 1.228 void
2373     object::kv_del (const shstr &key)
2374 root 1.24 {
2375 root 1.228 for (key_value **kvp = &key_values; *kvp; kvp = &(*kvp)->next)
2376     if ((*kvp)->key == key)
2377     {
2378     key_value *kv = *kvp;
2379     *kvp = (*kvp)->next;
2380     delete kv;
2381     return;
2382     }
2383 elmex 1.1 }
2384 root 1.31
2385 root 1.34 object::depth_iterator::depth_iterator (object *container)
2386     : iterator_base (container)
2387     {
2388     while (item->inv)
2389     item = item->inv;
2390     }
2391    
2392 root 1.31 void
2393 root 1.34 object::depth_iterator::next ()
2394 root 1.31 {
2395 root 1.34 if (item->below)
2396     {
2397     item = item->below;
2398    
2399     while (item->inv)
2400     item = item->inv;
2401     }
2402 root 1.31 else
2403 root 1.34 item = item->env;
2404 root 1.31 }
2405 root 1.34
2406 elmex 1.97 const char *
2407     object::flag_desc (char *desc, int len) const
2408     {
2409     char *p = desc;
2410     bool first = true;
2411    
2412 root 1.101 *p = 0;
2413    
2414 elmex 1.97 for (int i = 0; i < NUM_FLAGS; i++)
2415     {
2416     if (len <= 10) // magic constant!
2417     {
2418     snprintf (p, len, ",...");
2419     break;
2420     }
2421    
2422 root 1.101 if (flag [i])
2423 elmex 1.97 {
2424     int cnt = snprintf (p, len, "%s%d", first ? "" : ",", i);
2425     len -= cnt;
2426     p += cnt;
2427     first = false;
2428     }
2429     }
2430    
2431     return desc;
2432     }
2433    
2434 root 1.101 // return a suitable string describing an object in enough detail to find it
2435 root 1.36 const char *
2436     object::debug_desc (char *info) const
2437     {
2438 elmex 1.97 char flagdesc[512];
2439     char info2[256 * 4];
2440 root 1.36 char *p = info;
2441    
2442 elmex 1.242 p += snprintf (p, 512, "{cnt:%d,uuid:%s,name:\"%s\"%s%s%s,flags:[%s],type:%d}",
2443 root 1.203 count,
2444     uuid.c_str (),
2445 root 1.36 &name,
2446 elmex 1.242 title ? ",title:\"" : "",
2447 elmex 1.97 title ? (const char *)title : "",
2448 elmex 1.242 title ? "\"" : "",
2449 elmex 1.97 flag_desc (flagdesc, 512), type);
2450 root 1.36
2451 root 1.217 if (!flag[FLAG_REMOVED] && env)
2452 root 1.36 p += snprintf (p, 256, "(in %s)", env->debug_desc (info2));
2453    
2454     if (map)
2455 root 1.96 p += snprintf (p, 256, "(on %s@%d+%d)", &map->path, x, y);
2456 root 1.36
2457     return info;
2458     }
2459    
2460     const char *
2461     object::debug_desc () const
2462     {
2463 root 1.143 static char info[3][256 * 4];
2464     static int info_idx;
2465 root 1.36
2466 root 1.143 return debug_desc (info [++info_idx % 3]);
2467 root 1.114 }
2468    
2469 root 1.125 struct region *
2470     object::region () const
2471     {
2472     return map ? map->region (x, y)
2473     : region::default_region ();
2474     }
2475    
2476 root 1.129 const materialtype_t *
2477     object::dominant_material () const
2478     {
2479 root 1.165 if (materialtype_t *mt = name_to_material (materialname))
2480     return mt;
2481 root 1.129
2482 root 1.165 return name_to_material (shstr_unknown);
2483 root 1.129 }
2484    
2485 root 1.130 void
2486     object::open_container (object *new_container)
2487     {
2488     if (container == new_container)
2489     return;
2490    
2491 root 1.220 object *old_container = container;
2492    
2493     if (old_container)
2494 root 1.130 {
2495     if (INVOKE_OBJECT (CLOSE, old_container, ARG_OBJECT (this)))
2496     return;
2497    
2498     #if 0
2499     // remove the "Close old_container" object.
2500     if (object *closer = old_container->inv)
2501     if (closer->type == CLOSE_CON)
2502     closer->destroy ();
2503     #endif
2504    
2505 root 1.220 // make sure the container is available
2506     esrv_send_item (this, old_container);
2507    
2508 root 1.216 old_container->flag [FLAG_APPLIED] = false;
2509 root 1.130 container = 0;
2510    
2511 root 1.220 // client needs item update to make it work, client bug requires this to be separate
2512 root 1.130 esrv_update_item (UPD_FLAGS, this, old_container);
2513 root 1.220
2514 root 1.130 new_draw_info_format (NDI_UNIQUE, 0, this, "You close %s.", query_name (old_container));
2515 root 1.177 play_sound (sound_find ("chest_close"));
2516 root 1.130 }
2517    
2518     if (new_container)
2519     {
2520     if (INVOKE_OBJECT (OPEN, new_container, ARG_OBJECT (this)))
2521     return;
2522    
2523     // TODO: this does not seem to serve any purpose anymore?
2524     #if 0
2525     // insert the "Close Container" object.
2526     if (archetype *closer = new_container->other_arch)
2527     {
2528     object *closer = arch_to_object (new_container->other_arch);
2529     closer->flag [FLAG_NO_MAP_SAVE] = 1;
2530     new_container->insert (closer);
2531     }
2532     #endif
2533    
2534 root 1.132 new_draw_info_format (NDI_UNIQUE, 0, this, "You open %s.", query_name (new_container));
2535    
2536 root 1.220 // make sure the container is available, client bug requires this to be separate
2537     esrv_send_item (this, new_container);
2538    
2539 root 1.216 new_container->flag [FLAG_APPLIED] = true;
2540 root 1.130 container = new_container;
2541    
2542 root 1.220 // client needs flag change
2543 root 1.130 esrv_update_item (UPD_FLAGS, this, new_container);
2544 root 1.131 esrv_send_inventory (this, new_container);
2545 root 1.177 play_sound (sound_find ("chest_open"));
2546 root 1.130 }
2547 root 1.220 // else if (!old_container->env && contr && contr->ns)
2548     // contr->ns->floorbox_reset ();
2549 root 1.130 }
2550    
2551 root 1.164 object *
2552     object::force_find (const shstr name)
2553     {
2554     /* cycle through his inventory to look for the MARK we want to
2555     * place
2556     */
2557     for (object *tmp = inv; tmp; tmp = tmp->below)
2558     if (tmp->type == FORCE && tmp->slaying == name)
2559     return splay (tmp);
2560    
2561     return 0;
2562     }
2563    
2564     void
2565     object::force_add (const shstr name, int duration)
2566     {
2567     if (object *force = force_find (name))
2568     force->destroy ();
2569    
2570     object *force = get_archetype (FORCE_NAME);
2571    
2572     force->slaying = name;
2573     force->stats.food = 1;
2574     force->speed_left = -1.f;
2575    
2576     force->set_speed (duration ? 1.f / duration : 0.f);
2577     force->flag [FLAG_IS_USED_UP] = true;
2578     force->flag [FLAG_APPLIED] = true;
2579    
2580     insert (force);
2581     }
2582    
2583 root 1.178 void
2584 root 1.208 object::play_sound (faceidx sound)
2585 root 1.178 {
2586     if (!sound)
2587     return;
2588    
2589     if (flag [FLAG_REMOVED])
2590     return;
2591    
2592     if (env)
2593     {
2594     if (object *pl = in_player ())
2595     pl->contr->play_sound (sound);
2596     }
2597     else
2598     map->play_sound (sound, x, y);
2599     }
2600