ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/object.C
Revision: 1.295
Committed: Fri Nov 6 13:03:34 2009 UTC (14 years, 6 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.294: +9 -8 lines
Log Message:
make effectively static symbols actually static, part 2

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