Crossfire Server  1.75.0
time.cpp
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
20 #include "global.h"
21 
22 #include <stdlib.h>
23 
24 #include "spells.h"
25 #include "sproto.h"
26 #include "object.h"
27 
38 void remove_door(object *op) {
39  int i;
40  object *tmp;
41 
42  for (i = 1; i < 9; i += 2)
43  if ((tmp = map_find_by_type(op->map, op->x+freearr_x[i], op->y+freearr_y[i], DOOR)) != NULL) {
44  tmp->speed = 0.1;
46  tmp->speed_left = -0.2;
47  }
48 
49  if (op->other_arch) {
50  tmp = arch_to_object(op->other_arch);
51  tmp->level = op->level;
52  object_insert_in_map_at(tmp, op->map, op, 0, op->x, op->y);
53  }
54  object_remove(op);
56 }
57 
64 void remove_locked_door(object *op) {
65  int i;
66  object *tmp;
67 
68  for (i = 1; i < 9; i += 2) {
69  tmp = map_find_by_type(op->map, op->x+freearr_x[i], op->y+freearr_y[i], LOCKED_DOOR);
70  if (tmp && tmp->slaying == op->slaying) {/* same key both doors */
71  tmp->speed = 0.1;
73  tmp->speed_left = -0.2;
74  }
75  }
76  if (op->other_arch) {
77  tmp = arch_to_object(op->other_arch);
78  tmp->level = op->level;
79  object_insert_in_map_at(tmp, op->map, op, 0, op->x, op->y);
80  }
81  object_remove(op);
83 }
84 
97 static int generate_monster_inv(object *gen) {
98  int i;
99  int nx, ny;
100  object *op, *head = NULL;
101  const char *code;
102  int qty = 0;
103 
104  /* Code below assumes the generator is on a map, as it tries
105  * to place the monster on the map. So if the generator
106  * isn't on a map, complain and exit.
107  */
108  if (gen->map == NULL) {
109  LOG(llevError, "Generator (%s) not on a map?\n", gen->name);
110  return FALSE;
111  }
112 
113  /*First count number of objects in inv*/
114  FOR_INV_PREPARE(gen, op)
115  qty++;
116  FOR_INV_FINISH();
117  if (!qty) {
118  LOG(llevError, "Generator (%s) has no inventory in generate_monster_inv?\n", gen->name);
119  return FALSE;/*No inventory*/
120  }
121  qty = rndm(0, qty-1);
122  op = NULL;
123  FOR_INV_PREPARE(gen, tmp) {
124  op = tmp;
125  if (qty == 0)
126  break;
127  qty--;
128  } FOR_INV_FINISH();
129  i = object_find_multi_free_spot_within_radius(op, gen, &nx, &ny);
130  if (i == -1)
131  return FALSE;
132  head = object_create_clone(op);
135  if (rndm(0, 9))
136  generate_artifact(head, gen->map->difficulty);
137  code = object_get_value(gen, "generator_code");
138  if (code) {
139  object_set_value(head, "generator_code", code, 1);
140  }
141  object_insert_in_map_at(head, gen->map, gen, 0, nx, ny);
142  if (QUERY_FLAG(head, FLAG_FREED))
143  return TRUE;
144  object_fix_multipart(head);
145  if (HAS_RANDOM_ITEMS(head)) {
146  create_treasure(head->randomitems, head, 0, gen->map->difficulty, 0);
147  if (QUERY_FLAG(head, FLAG_MONSTER)) {
149  }
150  }
151  return TRUE;
152 }
153 
164 static int generate_monster_arch(object *gen) {
165  int i;
166  int nx, ny;
167  object *op;
168  const char *code;
169 
170  if (gen->other_arch == NULL) {
171  LOG(llevError, "Generator without other_arch: %s\n", gen->name);
172  return FALSE;
173  }
174  /* Code below assumes the generator is on a map, as it tries
175  * to place the monster on the map. So if the generator
176  * isn't on a map, complain and exit.
177  */
178  if (gen->map == NULL) {
179  LOG(llevError, "Generator (%s) not on a map?\n", gen->name);
180  return FALSE;
181  }
183  if (i == -1)
184  return FALSE;
185 
186  op = object_create_clone(&gen->other_arch->clone);
187  if (rndm(0, 9))
188  generate_artifact(op, gen->map->difficulty);
189  object *ins = object_insert_in_map_at(op, gen->map, gen, 0, nx, ny);
190  /* Object insert in map at can return NULL when failing to place something
191  * because the tile is blocked or because the monster was immediately killed
192  * by a spell effect on the space they were trying to be added to.
193  * Banishment in particular is guilty of causing the latter.
194  *
195  * Regardless, it appears to be intended behavior, but wasn't accounted for here.
196  *
197  * Ensure we actually got op back before continuing to process.
198  */
199  if (ins == NULL)
200  return FALSE;
201  op = ins; // Make sure we look at the object we got back. I *think* the pointer should be the same, but to be safe...
202  if (QUERY_FLAG(op, FLAG_FREED))
203  return TRUE;
204  if (HAS_RANDOM_ITEMS(op)) {
205  create_treasure(op->randomitems, op, 0, gen->map->difficulty, 0);
206  if (QUERY_FLAG(op, FLAG_MONSTER)) {
208  }
209  }
210  code = object_get_value(gen, "generator_code");
211  if (code) {
212  object_set_value(op, "generator_code", code, 1);
213  }
214 
215  return TRUE;
216 }
217 
224 static void generate_monster(object *gen) {
225  int8_t children, max_children;
226  int8_t x, y;
227  const char *code, *value;
228  int did_gen = 0;
229 
230  if (GENERATE_SPEED(gen) && rndm(0, GENERATE_SPEED(gen)-1))
231  return;
232 
233  value = object_get_value(gen, "generator_max_map");
234  if (value) {
235  max_children = (int8_t)strtol(value, NULL, 10);
236  if (max_children < 1)
237  return;
238  code = object_get_value(gen, "generator_code");
239  if (code) {
240  /* Generator has a limit and has created some,
241  * so count how many already exist
242  */
243  children = 0;
244  for (x = 0; x < MAP_WIDTH(gen->map); x++) {
245  for (y = 0; y < MAP_HEIGHT(gen->map); y++) {
246  FOR_MAP_PREPARE(gen->map, x, y, tmp) {
247  value = object_get_value(tmp, "generator_code");
248  if (value && value == code) {
249  children++;
250  }
251  } FOR_MAP_FINISH();
252  }
253  }
254  /* and return without generating if there are already enough */
255  if (children >= max_children+1)
256  return;
257  } else {
258  /* Generator has a limit, but hasn't created anything yet,
259  * so no need to count, just set code and go
260  */
261  value = object_get_value(gen, "generator_name");
262  if (value) {
263  object_set_value(gen, "generator_code", value, 1);
264  } else if (gen->name) {
265  object_set_value(gen, "generator_code", gen->name, 1);
266  } else {
267  object_set_value(gen, "generator_code", "generator", 1);
268  }
269  }
270  } /* If this has a max map generator limit */
271 
273  did_gen = generate_monster_inv(gen);
274  else
275  did_gen = generate_monster_arch(gen);
276 
277  /* See if generator has a generator_limit limit set */
278  if (object_value_set(gen, "generator_limit")) {
279  value = object_get_value(gen, "generator_limit");
280 
281  /* Only do this if we actually made a monster. If the generator
282  * was unable to create a monster (no space for example),
283  * we don't want to prematurely remove the generator.
284  */
285  if (value && did_gen) {
286  int limit = atoi(value), num_generated = 0;
287 
288  value = object_get_value(gen, "generator_generated");
289  if (value)
290  num_generated = atoi(value);
291 
292  if (num_generated++ >= limit) {
294  object_remove(gen);
296  } else {
297  char buf[50];
298 
299  snprintf(buf, sizeof(buf), "%d", num_generated);
300  object_set_value(gen, "generator_generated", buf, 1);
301  }
302  }
303  }
304 }
305 
313 static void remove_force(object *op) {
314  if (--op->duration > 0) {
315  check_spell_expiry(op);
316  return;
317  }
318 
319  switch (op->subtype) {
320  case FORCE_CONFUSION:
321  if (op->env != NULL) {
323  draw_ext_info(NDI_UNIQUE, 0, op->env,
325  "You regain your senses.");
326  }
327  break;
328 
330  /* The force is into the item that was created */
331  if (op->env != NULL && op->inv != NULL) {
332  object *inv = op->inv;
333  object *pl = object_get_player_container(op);
334 
335  object_remove(inv);
336 
337  // FIXME: For whatever reason, leaving an item transformed this way somewhere that it gets saved
338  // propagates the NO_PICK flag from the force down to the item. Clearing that here
339  // fixes the symptom, but not the underlying logic that causes the problem to occur.
340  CLEAR_FLAG(inv, FLAG_NO_PICK);
341 
342  inv->weight = (inv->nrof ? (int32_t)(op->env->weight/inv->nrof) : op->env->weight);
343  if (op->env->env) {
344  object_insert_in_ob(inv, op->env->env);
345  if (pl) {
346  char name[HUGE_BUF];
347 
348  query_short_name(inv, name, HUGE_BUF);
350  "Your %s recovers its original form.",
351  name);
352  }
353  } else {
354  /* Object on map */
355  object_insert_in_map_at(inv, op->env->map, NULL, 0, op->env->x, op->env->y);
356  }
357  inv = op->env;
358  object_remove(op);
360  object_remove(inv);
361  }
362  return;
363 
364  default:
365  break;
366  }
367 
368  if (op->env != NULL) {
370  change_abil(op->env, op);
371  fix_object(op->env);
372  }
373  object_remove(op);
375 }
376 
383 static void animate_trigger(object *op) {
384  if ((unsigned char)++op->stats.wc >= NUM_ANIMATIONS(op)) {
385  op->stats.wc = 0;
386  check_trigger(op, NULL);
387  } else {
388  SET_ANIMATION(op, op->stats.wc);
390  }
391 }
392 
399 static void move_hole(object *op) { /* 1 = opening, 0 = closing */
400  if (op->value) { /* We're opening */
401  if (--op->stats.wc <= 0) { /* Opened, let's stop */
402  op->stats.wc = 0;
403  op->speed = 0;
405 
406  /* Hard coding this makes sense for holes I suppose */
407  op->move_on = MOVE_WALK;
408  FOR_ABOVE_PREPARE(op, tmp)
409  ob_move_on(op, tmp, tmp);
411  }
412 
413  op->state = op->stats.wc;
414  animate_object(op, 0);
416  return;
417  }
418  /* We're closing */
419  op->move_on = 0;
420 
421  op->stats.wc++;
422  if ((int)op->stats.wc >= NUM_ANIMATIONS(op))
423  op->stats.wc = NUM_ANIMATIONS(op)-1;
424 
425  op->state = op->stats.wc;
426  animate_object(op, 0);
428  if ((unsigned char)op->stats.wc == (NUM_ANIMATIONS(op)-1)) {
429  op->speed = 0;
430  object_update_speed(op); /* closed, let's stop */
431  return;
432  }
433 }
434 
455 object *stop_item(object *op) {
456  if (free_no_drop(op))
457  return NULL;
458 
459  if (op->map == NULL)
460  return op;
461 
462  switch (op->type) {
463  case THROWN_OBJ: {
464  object *payload = op->inv;
465 
466  if (payload == NULL)
467  return NULL;
468  object_remove(payload);
469  object_remove(op);
471  return payload;
472  }
473 
474  case ARROW:
475  if (op->speed >= MIN_ACTIVE_SPEED)
476  op = fix_stopped_arrow(op);
477  return op;
478 
479  default:
480  return op;
481  }
482 }
483 
495 void fix_stopped_item(object *op, mapstruct *map, object *originator) {
496  if (map == NULL)
497  return;
498  if (QUERY_FLAG(op, FLAG_REMOVED))
499  object_insert_in_map(op, map, originator, 0);
500  else if (op->type == ARROW)
501  object_merge(op, NULL); /* only some arrows actually need this */
502 }
503 
512 object *fix_stopped_arrow(object *op) {
513  if (free_no_drop(op))
514  return NULL;
515 
516  if (rndm(0, 99) < op->stats.food) {
517  /* Small chance of breaking */
518  object_remove(op);
520  return NULL;
521  }
522 
523  op->direction = 0;
524  op->move_on = 0;
525  op->move_type = 0;
526  op->speed = 0;
528  op->stats.wc = op->stats.sp;
529  op->stats.dam = op->stats.hp;
530  op->attacktype = op->stats.grace;
531  if (op->slaying != NULL)
533 
534  if (op->skill != NULL)
536 
537  if (op->spellarg != NULL) {
538  op->slaying = add_string(op->spellarg);
539  free(op->spellarg);
540  op->spellarg = NULL;
541  } else
542  op->slaying = NULL;
543 
544  /* Reset these to zero, so that object_can_merge will work properly */
545  op->spellarg = NULL;
546  op->stats.sp = 0;
547  op->stats.hp = 0;
548  op->stats.grace = 0;
549  op->level = 0;
550  animate_object(op, 0);
551  object_clear_owner(op); /* So that stopped arrows will be saved */
553  return op;
554 }
555 
565 int free_no_drop(object *op) {
566  if (!QUERY_FLAG(op, FLAG_NO_DROP)) {
567  return 0;
568  }
569 
570  if (!QUERY_FLAG(op, FLAG_REMOVED)) {
571  object_remove(op);
572  }
573 
575  return 1;
576 }
577 
592 void change_object(object *op) {
593  object *env;
594  int i;
595  int friendly;
596  int unaggressive;
597  object *owner;
598 
599  if (op->other_arch == NULL) {
600  LOG(llevError, "Change object (%s) without other_arch error.\n", op->name);
601  return;
602  }
603 
604  /* In non-living items only change when food value is 0 */
605  if (!QUERY_FLAG(op, FLAG_ALIVE)) {
606  if (op->stats.food-- > 0)
607  return;
608  else
609  op->stats.food = 1; /* so 1 other_arch is made */
610  }
611 
612  env = op->env;
613  object_remove(op);
614  friendly = QUERY_FLAG(op, FLAG_FRIENDLY);
615  unaggressive = QUERY_FLAG(op, FLAG_UNAGGRESSIVE);
616  owner = object_get_owner(op);
617  for (i = 0; i < op->stats.food; i++) {
618  object *tmp;
619 
620  tmp = arch_to_object(op->other_arch);
621  if (op->type == LAMP)
622  tmp->stats.food = op->stats.food-1;
623  tmp->stats.hp = op->stats.hp;
624  if (friendly) {
625  SET_FLAG(tmp, FLAG_FRIENDLY);
626  add_friendly_object(tmp);
627  tmp->attack_movement = PETMOVE;
628  if (owner != NULL)
629  object_set_owner(tmp, owner);
630  }
631  if (unaggressive)
633  if (env) {
634  tmp->x = env->x,
635  tmp->y = env->y;
636  tmp = object_insert_in_ob(tmp, env);
637  }
638  // If there is more to the object, put in the map,
639  // then initiate the process of setting up multipartdom.
640  else if (tmp->arch->more)
641  {
642  tmp->map = op->map;
643  // Get the best free spot for the object
644  // Using the clone of the arch because I do not think that the actual object is ready yet.
645  if (object_find_multi_free_spot_around(&tmp->arch->clone, op, &tmp->x, &tmp->y) != 0)
646  {
647  LOG(llevInfo, "change_object: Failed to find a spot to put changing multipart object\n");
648  // Put the orignal object back.
650  // Free the failed object
652  // Bail out so we don't break things.
653  return;
654  }
657  }
658  else{
659  // Single-size objects work here.
660  object_insert_to_free_spot_or_free(tmp, op->map, op->x, op->y, 1, SIZEOFFREE1+1, op);
661  }
662  }
663  if (friendly)
666 }
667 
678 void move_firewall(object *op) {
679  object *spell;
680 
681  if (!op->map)
682  return; /* dm has created a firewall in his inventory */
683 
684  spell = op->inv;
685  if (!spell) {
686  LOG(llevError, "firewall '%s' in (%s, %d, %d) has no spell\n", op->name, op->map->path, op->x, op->y);
687  return;
688  }
689 
690  cast_spell(op, op, op->direction ? op->direction : get_random_dir(), spell, NULL);
691 }
692 
693 
707 void move_player_mover(object *op) {
708  int dir = op->stats.sp;
709  int16_t nx, ny;
710  mapstruct *m;
711 
712  if (!op->map) {
713  if (op->env && op->env->map)
714  LOG(llevError, "move_player_mover: mover not in a map at %s %d %d!\n", op->env->map->path, op->env->x, op->env->y);
715  else
716  LOG(llevError, "move_player_mover: mover not in a map at undefinite location!");
717  op->speed = 0;
719  return;
720  }
721 
722  /* Determine direction now for random movers so we do the right thing */
723  if (!dir)
724  dir = get_random_dir();
725 
726  FOR_MAP_PREPARE(op->map, op->x, op->y, victim) {
727  if (QUERY_FLAG(victim, FLAG_ALIVE)
728  && !QUERY_FLAG(victim, FLAG_WIZPASS)
729  && (victim->move_type&op->move_type || !victim->move_type)) {
730  victim = HEAD(victim);
731 
732  if (QUERY_FLAG(op, FLAG_LIFESAVE) && op->stats.hp-- < 0) {
733  object_remove(op);
735  return;
736  }
737  nx = op->x+freearr_x[dir];
738  ny = op->y+freearr_y[dir];
739  m = op->map;
740  if (get_map_flags(m, &m, nx, ny, &nx, &ny)&P_OUT_OF_MAP) {
741  LOG(llevError, "move_player_mover: Trying to push player off the map! map=%s (%d, %d)\n", m->path, op->x, op->y);
742  return;
743  }
744 
745  if (should_director_abort(op, victim))
746  return;
747 
748  FOR_MAP_PREPARE(m, nx, ny, nextmover) {
749  if (nextmover->type == PLAYERMOVER)
750  nextmover->speed_left = -.99;
751  if (QUERY_FLAG(nextmover, FLAG_ALIVE)) {
752  op->speed_left = -1.1; /* wait until the next thing gets out of the way */
753  }
754  } FOR_MAP_FINISH();
755 
756  if (victim->type == PLAYER) {
757  /* only level >= 1 movers move people */
758  if (op->level) {
759  /* Following is a bit of hack. We need to make sure it
760  * is cleared, otherwise the player will get stuck in
761  * place. This can happen if the player used a spell to
762  * get to this space.
763  */
764  victim->contr->fire_on = 0;
765  victim->speed_left = -FABS(victim->speed);
766  move_player(victim, dir);
767  } else
768  return;
769  } else
770  move_object(victim, dir);
771 
772  if (!op->stats.maxsp && op->attacktype)
773  op->stats.maxsp = 2.0;
774 
775  if (op->attacktype) { /* flag to paralyze the player */
776  victim->speed_left = -FABS(op->stats.maxsp*victim->speed/op->speed);
777  /* Not sure why, but for some chars on metalforge, they
778  * would sometimes get -inf speed_left, and from the
779  * description, it could only happen here, so just put
780  * a lower sanity limit. My only guess is that the
781  * mover has 0 speed.
782  */
783  if (victim->speed_left < -5.0)
784  victim->speed_left = -5.0;
785  }
786  }
787  } FOR_MAP_FINISH();
788 }
789 
796 void process_object(object *op) {
797  if (getenv("CF_DEBUG_PROCESS")) {
798  LOG(llevDebug, "processing %s (%d), speed %.3f\n", op->name, op->count, op->speed);
799  }
801  return;
802 
803  if (events_execute_object_event(op, EVENT_TIME, NULL, NULL, NULL, SCRIPT_FIX_NOTHING) != 0)
804  return;
805 
806  if (QUERY_FLAG(op, FLAG_REMOVED)) {
807  return;
808  }
809 
810  if (QUERY_FLAG(op, FLAG_MONSTER))
811  if (monster_move(op) || QUERY_FLAG(op, FLAG_FREED))
812  return;
813 
814  if ((QUERY_FLAG(op, FLAG_ANIMATE) && op->anim_speed == 0)
815  || (op->temp_animation && op->temp_anim_speed == 0)) {
816  op->state++;
817  if (op->type == PLAYER)
818  animate_object(op, op->facing);
819  else
820  animate_object(op, op->direction);
821 
822  if (QUERY_FLAG(op, FLAG_SEE_ANYWHERE))
823  make_sure_seen(op);
824  }
825  if (QUERY_FLAG(op, FLAG_CHANGING) && !op->state) {
826  change_object(op);
827  return;
828  }
830  generate_monster(op);
831 
832  /* If object can be used up, decrement 'food' and eventually remove it.
833  * Well, unless the object has a duration, in which case that should
834  * dictate how long it lasts and not food.
835  * Otherwise, you end up with artifact foods creating forces
836  * that ultimately starve the player to death.
837  */
838  if (QUERY_FLAG(op, FLAG_IS_USED_UP) && (op->duration > 0 || (--op->stats.food) <= 0)) {
839  if (QUERY_FLAG(op, FLAG_APPLIED)) {
840  remove_force(op);
841  } else {
842  if (op->env != NULL && op->env->type == PLAYER) {
843  sstring key;
844  key_value *used_up_message;
845 
846  key = add_string("used_up_message");
847  used_up_message = object_get_key_value(op, key);
848  free_string(key);
849 
850  if (used_up_message != NULL) {
853  "The %s %s.", op->name, used_up_message->value);
854  }
855  }
856 
857  object_remove(op);
858  if (QUERY_FLAG(op, FLAG_SEE_ANYWHERE))
859  make_sure_not_seen(op);
861  }
862  return;
863  }
864  ob_process(op);
865 }
866 
867 void legacy_remove_force(object *op) {
868  remove_force(op);
869 }
870 
871 void legacy_animate_trigger(object *op) {
872  animate_trigger(op);
873 }
874 
875 void legacy_move_hole(object *op) {
876  move_hole(op);
877 }
Error, serious thing.
Definition: logger.h:11
#define FLAG_NO_DROP
Object can&#39;t be dropped.
Definition: define.h:276
void change_object(object *op)
Replaces op with its other_arch if it has reached its end of life.
Definition: time.cpp:592
uint16_t attack_movement
What kind of attack movement.
Definition: object.h:401
void make_sure_not_seen(const object *op)
The object which is supposed to be visible through walls has just been removed from the map...
Definition: los.cpp:718
#define MSG_TYPE_ITEM_CHANGE
Item has changed in some way.
Definition: newclient.h:681
#define MOVE_WALK
Object walks.
Definition: define.h:398
#define UP_OBJ_FACE
Only thing that changed was the face.
Definition: object.h:533
#define MSG_TYPE_ITEM
Item related information.
Definition: newclient.h:429
Spell-related defines: spellpath, subtypes, ...
int move_player(object *op, int dir)
Move player in the given direction.
Definition: player.cpp:2962
Information.
Definition: logger.h:12
struct archetype * arch
Pointer to archetype.
Definition: object.h:424
object * object_get_owner(object *op)
Returns the object which this object marks as being the owner.
Definition: object.cpp:789
void animate_object(object *op, int dir)
Updates the face-variable of an object.
Definition: anim.cpp:44
void object_unset_flag_inv(object *op, int flag)
Desactivate recursively a flag on an object inventory.
Definition: object.cpp:3241
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
Definition: logger.cpp:58
key_value * object_get_key_value(const object *ob, const char *key)
Search for a field by key.
Definition: object.cpp:4306
int8_t direction
Means the object is moving that way.
Definition: object.h:344
#define FABS(x)
Decstations have trouble with fabs()...
Definition: define.h:22
int rndm(int min, int max)
Returns a number between min and max.
Definition: utils.cpp:162
void object_handle_death_animation(object *op)
Definition: object.cpp:5395
int free_no_drop(object *op)
Check whether the given object is FLAG_NO_DROP.
Definition: time.cpp:565
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...) PRINTF_ARGS(6
int16_t grace
Grace.
Definition: living.h:44
See Projectile.
Definition: object.h:122
#define FLAG_FRIENDLY
Will help players.
Definition: define.h:233
int get_random_dir(void)
Returns a random direction (1..8).
Definition: utils.cpp:400
void fix_stopped_item(object *op, mapstruct *map, object *originator)
Put stopped item where stop_item() had found it.
Definition: time.cpp:495
void fix_object(object *op)
Updates all abilities given by applied objects in the inventory of the given object.
Definition: living.cpp:1132
void object_remove(object *op)
This function removes the object op from the linked list of objects which it is currently tied to...
Definition: object.cpp:1818
#define HUGE_BUF
Used for messages - some can be quite long.
Definition: define.h:37
#define SET_ANIMATION(ob, newanim)
Definition: global.h:164
sstring slaying
Which race to do double damage to.
Definition: object.h:327
sstring add_string(const char *str)
Share a string.
Definition: shstr.cpp:137
int32_t value
How much money it is worth (or contains)
Definition: object.h:360
#define MAP_HEIGHT(m)
Map height.
Definition: map.h:78
Each object (this also means archetypes!) could have a few of these "dangling" from it; this could al...
Definition: object.h:42
void remove_friendly_object(object *op)
Removes the specified object from the linked list of friendly objects.
Definition: friend.cpp:52
void generate_artifact(object *op, int difficulty)
Decides randomly which artifact the object should be turned into.
Definition: artifact.cpp:177
#define FLAG_CONFUSED
Will also be unable to cast spells.
Definition: define.h:299
int16_t y
Position in the map for this object.
Definition: object.h:335
void check_spell_expiry(object *spell)
Checks if player should be warned of soon expiring spell.
#define FLAG_SEE_ANYWHERE
The object will be visible behind walls.
Definition: define.h:306
#define TRUE
Definition: compat.h:11
int16_t duration
Number of moves (see &#39;speed&#39;) spell lasts.
Definition: object.h:415
MoveType move_on
Move types affected moving on to this space.
Definition: object.h:439
int monster_move(object *op)
Main monster processing routine.
Definition: monster.cpp:867
#define FALSE
Definition: compat.h:14
#define MSG_TYPE_ITEM_REMOVE
Item removed from inv.
Definition: newclient.h:679
void object_set_owner(object *op, object *owner)
Sets the owner and sets the skill and exp pointers to owner&#39;s current skill and experience objects...
Definition: object.cpp:825
void process_object(object *op)
Main object move function.
Definition: time.cpp:796
int16_t x
Definition: object.h:335
#define NDI_BLACK
Definition: newclient.h:246
Global type definitions and header inclusions.
#define PETMOVE
If the upper four bits of attack_movement are set to this number, the monster follows a player until ...
Definition: define.h:502
uint8_t temp_anim_speed
Ticks between temporary animation-frames.
Definition: object.h:432
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
Sends message to player(s).
Definition: main.cpp:308
See Mover.
Definition: object.h:145
uint8_t anim_speed
Ticks between animation-frames.
Definition: object.h:429
void move_player_mover(object *op)
This function takes a PLAYERMOVER as an argument, and performs the function of a player mover...
Definition: time.cpp:707
#define FLAG_REMOVED
Object is not in any map or invenory.
Definition: define.h:219
int32_t weight
Attributes of the object.
Definition: object.h:375
void legacy_animate_trigger(object *op)
Definition: time.cpp:871
void make_sure_seen(const object *op)
The object is supposed to be visible through walls, thus check if any players are nearby...
Definition: los.cpp:695
static std::shared_ptr< inja::Environment > env
Rendering environment.
Definition: mapper.cpp:2222
#define FLAG_IS_USED_UP
When (–food<0) the object will exit.
Definition: define.h:247
object * object_create_clone(object *asrc)
Create clone from object to another.
Definition: object.cpp:3894
#define SCRIPT_FIX_NOTHING
Definition: global.h:381
int change_abil(object *op, object *tmp)
Permanently alters an object&#39;s stats/flags based on another object.
Definition: living.cpp:394
void free_string(sstring str)
This will reduce the refcount, and if it has reached 0, str will be freed.
Definition: shstr.cpp:294
method_ret ob_process(object *op)
Processes an object, giving it the opportunity to move or react.
Definition: ob_methods.cpp:67
int16_t level
Level of creature or object.
Definition: object.h:361
int16_t sp
Spell points.
Definition: living.h:42
#define MSG_TYPE_ATTRIBUTE_BAD_EFFECT_END
End of a bad effect.
Definition: newclient.h:602
void object_free(object *ob, int flags)
Frees everything allocated by an object, removes it from the list of used objects, and puts it on the list of free objects.
Definition: object.cpp:1577
#define FREE_OBJ_FREE_INVENTORY
Free inventory objects; if not set, drop inventory.
Definition: object.h:546
#define FLAG_ALIVE
Object can fight (or be fought)
Definition: define.h:217
void create_treasure(treasurelist *t, object *op, int flag, int difficulty, int tries)
This calls the appropriate treasure creation function.
Definition: treasure.cpp:287
int check_trigger(object *op, object *cause)
Definition: button.cpp:518
static int generate_monster_inv(object *gen)
Will generate a monster according to parameters of generator.
Definition: time.cpp:97
object * object_insert_in_map(object *op, mapstruct *m, object *originator, int flag)
This function inserts the object in the two-way linked list which represents what is on a map...
Definition: object.cpp:2346
static int generate_monster_arch(object *gen)
Generate a monster from the other_arch field.
Definition: time.cpp:164
float speed
Frequency of object &#39;moves&#39; relative to server tick rate.
Definition: object.h:337
object * arch_to_object(archetype *at)
Creates and returns a new object which is a copy of the given archetype.
Definition: arch.cpp:227
char path[HUGE_BUF]
Filename of the map.
Definition: map.h:360
void legacy_move_hole(object *op)
Definition: time.cpp:875
#define FOR_ABOVE_FINISH()
Finishes FOR_ABOVE_PREPARE().
Definition: define.h:717
object * env
Pointer to the object which is the environment.
Definition: object.h:301
#define SET_FLAG(xyz, p)
Definition: define.h:384
#define FLAG_UNAGGRESSIVE
Monster doesn&#39;t attack players.
Definition: define.h:259
#define QUERY_FLAG(xyz, p)
Definition: define.h:386
void monster_check_apply_all(object *monster)
Calls monster_check_apply() for all inventory objects.
Definition: monster.cpp:2001
#define MSG_TYPE_ATTRIBUTE
Changes to attributes (stats, resistances, etc)
Definition: newclient.h:421
void object_fix_multipart(object *tmp)
Ensures specified object has its more parts correctly inserted in map.
Definition: object.cpp:4670
void object_free_drop_inventory(object *ob)
Frees everything allocated by an object, removes it from the list of used objects, and puts it on the list of free objects.
Definition: object.cpp:1545
short freearr_x[SIZEOFFREE]
X offset when searching around a spot.
Definition: object.cpp:299
#define FOR_INV_FINISH()
Finishes FOR_INV_PREPARE().
Definition: define.h:700
This is a game-map.
Definition: map.h:320
#define FLAG_CHANGING
Changes to other_arch when anim is done.
Definition: define.h:250
#define FOR_ABOVE_PREPARE(op_, it_)
Constructs a loop iterating over all objects above an object.
Definition: define.h:710
int object_find_multi_free_spot_around(const object *ob, const object *gen, int16_t *hx, int16_t *hy)
Sets hx and hy to the coords to insert a possibly multi-tile ob at, around gen.
Definition: object.cpp:3281
#define INS_NO_WALK_ON
Don&#39;t call check_walk_on against the originator.
Definition: object.h:584
sstring object_get_value(const object *op, const char *const key)
Get an extra value by key.
Definition: object.cpp:4331
#define FLAG_IS_A_TEMPLATE
Object has no ingame life until instantiated.
Definition: define.h:362
static void generate_monster(object *gen)
Main generator function.
Definition: time.cpp:224
method_ret ob_move_on(object *op, object *victim, object *originator)
Makes an object move on top of another one.
Definition: ob_methods.cpp:134
#define P_OUT_OF_MAP
This space is outside the map.
Definition: map.h:254
uint8_t state
How the object was last drawn (animation)
Definition: object.h:359
#define FORCE_CONFUSION
Definition: spells.h:144
#define FREE_AND_CLEAR_STR(xyz)
Release the shared string, and set it to NULL.
Definition: global.h:200
static void remove_force(object *op)
Move for FORCE objects.
Definition: time.cpp:313
int16_t dam
How much damage this object does when hitting.
Definition: living.h:46
#define HEAD(op)
Returns the head part of an object.
Definition: object.h:609
#define INS_ABOVE_FLOOR_ONLY
Put object immediatly above the floor.
Definition: object.h:583
int object_find_multi_free_spot_within_radius(const object *ob, const object *gen, int *hx, int *hy)
Sets hx and hy to the coords to insert a possibly multi-tile ob at, within radius of generator...
Definition: object.cpp:3397
See Locked Door.
Definition: object.h:128
living stats
Str, Con, Dex, etc.
Definition: object.h:378
#define GENERATE_SPEED(xyz)
Definition: define.h:437
See Door.
Definition: object.h:131
const Animations * temp_animation
A temporary animation.
Definition: object.h:431
void add_friendly_object(object *op)
Add a new friendly object to the list of friendly objects.
Definition: friend.cpp:32
void remove_locked_door(object *op)
Same as remove_door() but for locked doors.
Definition: time.cpp:64
float speed_left
How much speed is left to spend this round.
Definition: object.h:338
object * stop_item(object *op)
An item (ARROW or such) stops moving.
Definition: time.cpp:455
void legacy_remove_force(object *op)
Definition: time.cpp:867
struct mapstruct * map
Pointer to the map in which this object is present.
Definition: object.h:305
Lamp.
Definition: object.h:206
short freearr_y[SIZEOFFREE]
Y offset when searching around a spot.
Definition: object.cpp:305
#define FOR_MAP_FINISH()
Finishes FOR_MAP_PREPARE().
Definition: define.h:753
int8_t facing
Object is oriented/facing that way.
Definition: object.h:345
object * object_merge(object *op, object *top)
This function goes through all objects below and including top, and merges op to the first matching o...
Definition: object.cpp:2036
See Player.
Definition: object.h:112
struct archetype * other_arch
Pointer used for various things - mostly used for what this objects turns into or what this object cr...
Definition: object.h:425
struct treasurelist * randomitems
Items to be generated.
Definition: object.h:395
#define FLAG_ANIMATE
The object looks at archetype for faces.
Definition: define.h:229
Object structure, the core of Crossfire.
#define FLAG_GENERATOR
Will generate type ob->stats.food.
Definition: define.h:235
#define INS_NO_MERGE
Don&#39;t try to merge with other items.
Definition: object.h:582
static event_registration m
Definition: citylife.cpp:424
#define NUM_ANIMATIONS(ob)
Definition: global.h:173
MoveType move_type
Type of movement this object uses.
Definition: object.h:436
sstring name
The name of the object, obviously...
Definition: object.h:319
#define MAP_WIDTH(m)
Map width.
Definition: map.h:76
Only for debugging purposes.
Definition: logger.h:13
uint32_t nrof
Number of objects.
Definition: object.h:342
int get_map_flags(mapstruct *oldmap, mapstruct **newmap, int16_t x, int16_t y, int16_t *nx, int16_t *ny)
This rolls up wall, blocks_magic, blocks_view, etc, all into one function that just returns a P_...
Definition: map.cpp:300
static void animate_trigger(object *op)
Animate a TRIGGER.
Definition: time.cpp:383
#define CLEAR_FLAG(xyz, p)
Definition: define.h:385
uint8_t type
PLAYER, BULLET, etc.
Definition: object.h:348
#define FLAG_APPLIED
Object is ready for use by living.
Definition: define.h:222
int move_object(object *op, int dir)
Try to move op in the direction "dir".
Definition: move.cpp:39
sstring value
Key&#39;s value.
Definition: object.h:44
char * spellarg
Optional argument when casting obj::spell.
Definition: object.h:421
#define FLAG_LIFESAVE
Saves a players&#39; life once, then destr.
Definition: define.h:293
void object_update_speed(object *op)
Updates the speed of an object.
Definition: object.cpp:1334
int object_set_value(object *op, const char *key, const char *value, int add_key)
Updates the key in op to value.
Definition: object.cpp:4484
object * inv
Pointer to the first object in the inventory.
Definition: object.h:298
#define EVENT_TIME
Triggered each time the object can react/move.
Definition: events.h:40
object * fix_stopped_arrow(object *op)
An ARROW stops moving.
Definition: time.cpp:512
#define MIN_ACTIVE_SPEED
Cut off point of when an object is put on the active list or not.
Definition: define.h:662
#define FORCE_TRANSFORMED_ITEM
Definition: spells.h:146
sstring skill
Name of the skill this object uses/grants.
Definition: object.h:329
static void move_hole(object *op)
Move a HOLE.
Definition: time.cpp:399
int16_t maxsp
Max spell points.
Definition: living.h:43
uint32_t attacktype
Bitmask of attacks this object does.
Definition: object.h:352
void object_clear_owner(object *op)
Clears the owner of specified object.
Definition: object.cpp:808
#define FLAG_MONSTER
Will attack players.
Definition: define.h:232
int events_execute_object_event(object *op, int eventcode, object *activator, object *third, const char *message, int fix)
Execute an event on the specified object.
Definition: events.cpp:309
#define NDI_UNIQUE
Print immediately, don&#39;t buffer.
Definition: newclient.h:270
#define SIZEOFFREE1
Definition: define.h:153
archetype * more
Next part of a linked object.
Definition: object.h:486
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Constructs a loop iterating over all objects of a map tile.
Definition: define.h:746
#define FREE_OBJ_DROP_ABOVE_FLOOR
If FREE_OBJ_FREE_INVENTORY is not set, drop inventory just above ground instead on top...
Definition: object.h:548
int32_t food
How much food in stomach.
Definition: living.h:48
StringBuffer * buf
Definition: readable.cpp:1563
uint8_t subtype
Subtype of object.
Definition: object.h:349
uint16_t difficulty
What level the player should be to play here.
Definition: map.h:338
object * object_get_player_container(object *op)
Finds the player carrying an object.
Definition: object.cpp:592
const char * sstring
Definition: sstring.h:2
object * object_insert_in_ob(object *op, object *where)
This function inserts the object op in the linked list inside the object environment.
Definition: object.cpp:2842
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Same as object_insert_in_map() except it handle separate coordinates and do a clean job preparing mul...
Definition: object.cpp:2085
int8_t wc
Weapon Class, lower WC increases probability of hitting.
Definition: living.h:37
int should_director_abort(const object *op, const object *victim)
Check if op should abort moving victim because of it&#39;s race or slaying.
Definition: apply.cpp:68
void object_update(object *op, int action)
object_update() updates the array which represents the map.
Definition: object.cpp:1419
tag_t count
Unique object number for this object.
Definition: object.h:307
#define FLAG_NO_PICK
Object can&#39;t be picked up.
Definition: define.h:226
#define FLAG_WIZPASS
The wizard can go through walls.
Definition: define.h:302
void object_insert_to_free_spot_or_free(object *op, mapstruct *map, int x, int y, int start, int stop, object *originator)
Inserts an object into its map.
Definition: object.cpp:4776
void query_short_name(const object *op, char *buf, size_t size)
query_short_name(object) is similar to query_name(), but doesn&#39;t contain any information about object...
Definition: item.cpp:518
object * map_find_by_type(mapstruct *m, int x, int y, uint8_t type)
Searches for any objects with a matching type variable at the given map and coordinates.
Definition: object.cpp:3130
#define FLAG_CONTENT_ON_GEN
Use
Definition: define.h:361
object clone
An object from which to do object_copy()
Definition: object.h:487
bool object_value_set(const object *op, const char *const key)
Determine if an extra value is set.
Definition: object.cpp:4361
void remove_door(object *op)
Remove non locked doors.
Definition: time.cpp:38
#define HAS_RANDOM_ITEMS(op)
This return TRUE if object has still randomitems which could be expanded.
Definition: define.h:184
#define FOR_INV_PREPARE(op_, it_)
Constructs a loop iterating over the inventory of an object.
Definition: define.h:693
int cast_spell(object *op, object *caster, int dir, object *spell_ob, char *stringarg)
Main dispatch when someone casts a spell.
int16_t hp
Hit Points.
Definition: living.h:40
#define FLAG_FREED
Object is in the list of free objects.
Definition: define.h:220
void move_firewall(object *op)
Move for FIREWALL.
Definition: time.cpp:678