ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/object.C
Revision: 1.290
Committed: Sun Oct 11 05:43:35 2009 UTC (14 years, 7 months ago) by sf-marcmagus
Content type: text/plain
Branch: MAIN
Changes since 1.289: +12 -5 lines
Log Message:
Give artifact foods sufficiently long duration so they're worth having.
Make artifact foods effects not stack with themselves, so they're not way too good.
Add a couple of new artifact mushrooms.
Make all mushroom types available when crafting mushrooms using woodsman: each craft attempt will generate a random mushroom type.
Tweak force_add so it can't cause improved sustenance, provide force_set_timer so they can be reset.

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