Crossfire Server, Trunk  1.75.0
pets.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 
19 #include "global.h"
20 
21 #include <assert.h>
22 #include <ctype.h>
23 #include <stdlib.h>
24 #include <string.h>
25 
26 #include "sproto.h"
27 
34 static void mark_inventory_as_no_drop(object *ob) {
35  FOR_INV_PREPARE(ob, tmp)
36  SET_FLAG(tmp, FLAG_NO_DROP);
38 }
39 
54 object *pets_get_enemy(object *pet, rv_vector *rv) {
55  object *owner, *tmp, *attacker, *tmp3;
56  int i;
57  int16_t x, y;
58  mapstruct *nm;
59  int search_arr[SIZEOFFREE];
60  int mflags;
61 
62  attacker = pet->attacked_by; /*pointer to attacking enemy*/
63  pet->attacked_by = NULL; /*clear this, since we are dealing with it*/
64 
65  owner = object_get_owner(pet);
66  if (owner != NULL) {
67  /* If the owner has turned on the pet, make the pet
68  * unfriendly.
69  */
70  if (monster_check_enemy(owner, rv) == pet) {
73  pet->attack_movement &= ~PETMOVE;
74  return owner;
75  }
76  } else {
77  /* else the owner is no longer around, so the
78  * pet no longer needs to be friendly.
79  */
82  pet->attack_movement &= ~PETMOVE;
83  return NULL;
84  }
85  /* If they are not on the same map, the pet won't be agressive */
86  if (!on_same_map(pet, owner))
87  return NULL;
88 
89  /* See if the pet has an existing enemy. If so, don't start a new one*/
90  tmp = monster_check_enemy(pet, rv);
91  if (tmp != NULL) {
92  if (tmp != owner || QUERY_FLAG(pet, FLAG_CONFUSED) || !QUERY_FLAG(pet, FLAG_FRIENDLY))
93  return tmp;
94 
95  /* without this check, you can actually get pets with
96  * enemy set to owner!
97  */
98  object_set_enemy(pet, NULL);
99  }
100  get_search_arr(search_arr);
101 
102  if (owner->type == PLAYER && owner->contr->petmode == pet_sad) {
103  tmp = monster_find_nearest_enemy(pet, owner);
104  if (tmp != NULL && get_rangevector(pet, tmp, rv, 0))
105  return tmp;
106  /* if we got here we still have no enemy */
107  /* we return NULL to avoid heading back to the owner */
108  object_set_enemy(pet, NULL);
109  return NULL;
110  }
111 
112  /* Since the pet has no existing enemy, look for anything nasty
113  * around the owner that it should go and attack.
114  */
115  tmp3 = NULL;
116  for (i = 0; i < SIZEOFFREE; i++) {
117  x = owner->x+freearr_x[search_arr[i]];
118  y = owner->y+freearr_y[search_arr[i]];
119  nm = owner->map;
120  /* Only look on the space if there is something alive there. */
121  mflags = get_map_flags(nm, &nm, x, y, &x, &y);
122  if (!(mflags&P_OUT_OF_MAP) && mflags&P_IS_ALIVE) {
123  FOR_MAP_PREPARE(nm, x, y, tmp) {
124  object *tmp2 = HEAD(tmp);
125 
126  if (QUERY_FLAG(tmp2, FLAG_ALIVE)
127  && ((!QUERY_FLAG(tmp2, FLAG_FRIENDLY) && tmp2->type != PLAYER) || pets_should_arena_attack(pet, owner, tmp2))
128  && !QUERY_FLAG(tmp2, FLAG_UNAGGRESSIVE)
129  && tmp2 != pet
130  && tmp2 != owner
131  && monster_can_detect_enemy(pet, tmp2, rv)) {
132  if (!monster_can_see_enemy(pet, tmp2)) {
133  if (tmp3 == NULL)
134  tmp3 = tmp2;
135  } else {
136  object_set_enemy(pet, tmp2);
137  if (monster_check_enemy(pet, rv) != NULL)
138  return tmp2;
139  object_set_enemy(pet, NULL);
140  }
141  }/* if this is a valid enemy */
142  } FOR_MAP_FINISH();/* for objects on this space */
143  }/* if there is something living on this space */
144  } /* for loop of spaces around the owner */
145 
146  /* fine, we went through the whole loop and didn't find one we could
147  see, take what we have */
148  if (tmp3 != NULL) {
149  object_set_enemy(pet, tmp3);
150  if (monster_check_enemy(pet, rv) != NULL)
151  return tmp3;
152  object_set_enemy(pet, NULL);
153  }
154 
155  /* No threat to owner, check to see if the pet has an attacker*/
156  if (attacker != NULL) {
157  /* need to be sure this is the right one! */
158  if (attacker->count == pet->attacked_by_count) {
159  /* also need to check to make sure it is not freindly */
160  /* or otherwise non-hostile, and is an appropriate target */
161  if (!QUERY_FLAG(attacker, FLAG_FRIENDLY) && on_same_map(pet, attacker)) {
162  object_set_enemy(pet, attacker);
163  if (monster_check_enemy(pet, rv) != NULL)
164  return attacker;
165  object_set_enemy(pet, NULL);
166  }
167  }
168  }
169 
170  /* Don't have an attacker or legal enemy, so look for a new one!.
171  * This looks for one around where the pet is. Thus, you could lead
172  * a pet to danger, then take a few steps back. This code is basically
173  * the same as the code that looks around the owner.
174  */
175  if (owner->type == PLAYER && owner->contr->petmode != pet_defend) {
176  tmp3 = NULL;
177  for (i = 0; i < SIZEOFFREE; i++) {
178  x = pet->x+freearr_x[search_arr[i]];
179  y = pet->y+freearr_y[search_arr[i]];
180  nm = pet->map;
181  /* Only look on the space if there is something alive there. */
182  mflags = get_map_flags(nm, &nm, x, y, &x, &y);
183  if (!(mflags&P_OUT_OF_MAP) && mflags&P_IS_ALIVE) {
184  FOR_MAP_PREPARE(nm, x, y, tmp) {
185  object *tmp2 = HEAD(tmp);
186  if (QUERY_FLAG(tmp2, FLAG_ALIVE)
187  && ((!QUERY_FLAG(tmp2, FLAG_FRIENDLY) && tmp2->type != PLAYER) || pets_should_arena_attack(pet, owner, tmp2))
188  && !QUERY_FLAG(tmp2, FLAG_UNAGGRESSIVE)
189  && tmp2 != pet
190  && tmp2 != owner
191  && monster_can_detect_enemy(pet, tmp2, rv)) {
192  if (!monster_can_see_enemy(pet, tmp2)) {
193  assert(tmp3 == NULL);
194  } else {
195  object_set_enemy(pet, tmp2);
196  if (monster_check_enemy(pet, rv) != NULL)
197  return tmp2;
198  object_set_enemy(pet, NULL);
199  }
200  } /* make sure we can get to the bugger */
201  } FOR_MAP_FINISH();/* for objects on this space */
202  } /* if there is something living on this space */
203  } /* for loop of spaces around the pet */
204  } /* pet in defence mode */
205 
206  /* fine, we went through the whole loop and didn't find one we could
207  see, take what we have */
208  if (tmp3 != NULL) {
209  object_set_enemy(pet, tmp3);
210  if (monster_check_enemy(pet, rv) != NULL)
211  return tmp3;
212  object_set_enemy(pet, NULL);
213  }
214 
215  /* Didn't find anything - return the owner's enemy or NULL */
216  return monster_check_enemy(pet, rv);
217 }
218 
225 void pets_terminate_all(object *owner) {
226  objectlink *link = get_friends_of(owner), *cur;
227  if (!link) {
228  return;
229  }
230  for (cur = link; cur != NULL; cur = cur->next) {
231  object *ob = cur->ob;
232  if (!QUERY_FLAG(ob, FLAG_REMOVED))
233  object_remove(ob);
236  }
237 
238  free_objectlink(link);
239 }
240 
249 void pets_attempt_follow(object *for_owner, int force) {
250  objectlink *list = get_friends_of(for_owner), *cur;
251  object *owner;
252  if (!list) {
253  return;
254  }
255 
256  for (cur = list; cur != NULL; cur = cur->next) {
257  if (cur->ob->type != PLAYER
258  && QUERY_FLAG(cur->ob, FLAG_FRIENDLY)
259  && (owner = object_get_owner(cur->ob)) != NULL
260  && (for_owner == NULL || for_owner == owner)
261  && (force || !on_same_map(owner, cur->ob))) {
262  /* follow owner checks map status for us. Note that pet can
263  * die in pets_follow_owner(), so check for obl->ob existence
264  */
265  pets_follow_owner(cur->ob, owner);
266  if (cur->ob && QUERY_FLAG(cur->ob, FLAG_REMOVED) && FABS(cur->ob->speed) > MIN_ACTIVE_SPEED) {
267  LOG(llevMonster, "(pet failed to follow)\n");
268  remove_friendly_object(cur->ob);
270  }
271  }
272  }
274 }
275 
284 void pets_follow_owner(object *ob, object *owner) {
285  int dir;
286 
287  if (!QUERY_FLAG(ob, FLAG_REMOVED))
288  object_remove(ob);
289 
290  if (owner->map == NULL) {
291  LOG(llevError, "Can't follow owner: no map.\n");
292  return;
293  }
294  if (owner->map->in_memory != MAP_IN_MEMORY) {
295  LOG(llevError, "Owner of the pet not on a map in memory!?\n");
296  return;
297  }
298  dir = object_find_free_spot(ob, owner->map, owner->x, owner->y, 1, SIZEOFFREE);
299 
300  if (dir == -1) {
301  LOG(llevMonster, "No space for pet to follow, freeing %s.\n", ob->name);
302  return; /* Will be freed since it's removed */
303  }
304  object_insert_in_map_at(ob, owner->map, NULL, 0, owner->x+freearr_x[dir], owner->y+freearr_y[dir]);
305  if (owner->type == PLAYER) /* Uh, I hope this is always true... */
307  "Your pet magically appears next to you");
308  return;
309 }
310 
317 void pets_move(object *ob) {
318  int dir, i;
319  tag_t tag;
320  int16_t dx, dy;
321  object *owner;
322  mapstruct *m;
323 
324  /* Check to see if player pulled out */
325  owner = object_get_owner(ob);
326  if (owner == NULL) {
327  object_remove(ob); /* Will be freed when returning */
330  LOG(llevMonster, "Pet: no owner, leaving.\n");
331  return;
332  }
333 
334  /* move monster into the owners map if not in the same map */
335  if (!on_same_map(ob, owner)) {
336  pets_follow_owner(ob, owner);
337  return;
338  }
339  /* Calculate Direction */
340  if (owner->type == PLAYER && owner->contr->petmode == pet_sad) {
341  /* in S&D mode, if we have no enemy, run randomly about. */
342  for (i = 0; i < 15; i++) {
343  dir = get_random_dir();
344  dx = ob->x+freearr_x[dir];
345  dy = ob->y+freearr_y[dir];
346  m = ob->map;
347  if (!(get_map_flags(ob->map, &m, dx, dy, &dx, &dy)&P_OUT_OF_MAP)
348  && !OB_TYPE_MOVE_BLOCK(ob, GET_MAP_MOVE_BLOCK(m, dx, dy)))
349  break;
350  }
351  } else {
352  rv_vector rv;
353 
354  if (get_rangevector(ob, owner, &rv, 0))
355  dir = rv.direction;
356  else
357  dir = get_random_dir();
358  }
359  ob->direction = dir;
360 
361  tag = ob->count;
362  /* move_ob returns 0 if the object couldn't move. If that is the
363  * case, lets do some other work.
364  */
365  if (!move_ob(ob, dir, ob)) {
366  object *part;
367 
368  /* the failed move_ob above may destroy the pet, so check here */
369  if (object_was_destroyed(ob, tag))
370  return;
371 
372  for (part = ob; part != NULL; part = part->more) {
373  dx = part->x+freearr_x[dir];
374  dy = part->y+freearr_y[dir];
375  m = get_map_from_coord(part->map, &dx, &dy);
376  if (m == NULL)
377  continue;
378 
379  FOR_MAP_PREPARE(m, dx, dy, ob2) {
380  object *new_ob;
381 
382  new_ob = HEAD(ob2);
383  if (new_ob == ob)
384  break;
385  if (new_ob == owner)
386  return;
387  if (object_get_owner(new_ob) == owner)
388  break;
389 
390  /* Hmm. Did we try to move into an enemy monster? If so,
391  * make it our enemy.
392  */
393  if (QUERY_FLAG(new_ob, FLAG_ALIVE)
395  && !QUERY_FLAG(new_ob, FLAG_UNAGGRESSIVE)
396  && !QUERY_FLAG(new_ob, FLAG_FRIENDLY)) {
397  object_set_enemy(ob, new_ob);
398  if (new_ob->enemy == NULL)
399  object_set_enemy(new_ob, ob);
400  return;
401  } else if (new_ob->type == PLAYER) {
402  draw_ext_info(NDI_UNIQUE, 0, new_ob,
404  "You stand in the way of someones pet.");
405  return;
406  }
407  } FOR_MAP_FINISH();
408  }
409  /* Try a different course */
410  dir = absdir(dir+4-(RANDOM()%5)-(RANDOM()%5));
411  (void)move_ob(ob, dir, ob);
412  }
413  return;
414 }
415 
416 /****************************************************************************
417  *
418  * GOLEM SPELL CODE
419  *
420  ****************************************************************************/
421 
434 static object *fix_summon_pet(archetype *at, object *op, int dir) {
435  archetype *atmp;
436  object *tmp = NULL, *prev = NULL, *head = NULL;
437 
438  for (atmp = at; atmp != NULL; atmp = atmp->more) {
439  tmp = arch_to_object(atmp);
440  if (atmp == at) {
441 
442  /* Ensure the golem can actually move if no move_type defined.
443  * This check is redundant since this is checked at server startup. */
444  if (tmp->move_type == 0) {
445  LOG(llevError, "summoned %s [%s] is without move_type!\n", tmp->name, atmp->name);
446  tmp->move_type = MOVE_WALK;
447  }
448 
449  object_set_owner(tmp, op);
450  if (op->type == PLAYER) {
451  tmp->stats.exp = 0;
452  add_friendly_object(tmp);
453  SET_FLAG(tmp, FLAG_FRIENDLY);
454  CLEAR_FLAG(tmp, FLAG_MONSTER);
455  } else if (QUERY_FLAG(op, FLAG_FRIENDLY)) {
456  object *owner = object_get_owner(op);
457 
458  if (owner != NULL) {/* For now, we transfer ownership */
459  object_set_owner(tmp, owner);
460  tmp->attack_movement = PETMOVE;
461  add_friendly_object(tmp);
462  SET_FLAG(tmp, FLAG_FRIENDLY);
463  }
464  }
465  if (op->type != PLAYER) {
466  tmp->attack_movement = PETMOVE;
467  tmp->speed_left = -1;
468  tmp->type = 0;
469  object_set_enemy(tmp, op->enemy);
470  } else
471  tmp->type = GOLEM;
472  }
473  if (head == NULL)
474  head = tmp;
475  tmp->x = op->x+freearr_x[dir]+tmp->arch->clone.x;
476  tmp->y = op->y+freearr_y[dir]+tmp->arch->clone.y;
477  tmp->map = op->map;
478  if (tmp->invisible)
479  tmp->invisible = 0;
480  if (head != tmp)
481  tmp->head = head,
482  prev->more = tmp;
483  prev = tmp;
484  }
485  head->direction = dir;
486 
487  if (head->randomitems) {
488  create_treasure(head->randomitems, head, GT_STARTEQUIP, 6, 0);
489  if (QUERY_FLAG(head, FLAG_MONSTER)) {
491  }
492  }
494 
495  /* need to change some monster attr to prevent problems/crashing */
496  head->last_heal = 0;
497  head->last_eat = 0;
498  head->last_grace = 0;
499  head->last_sp = 0;
500  head->other_arch = NULL;
501  head->stats.exp = 0;
502  CLEAR_FLAG(head, FLAG_CHANGING);
504  CLEAR_FLAG(head, FLAG_GENERATOR);
505  CLEAR_FLAG(head, FLAG_SPLITTING);
506  if (head->attacktype&AT_GHOSTHIT)
507  head->attacktype = (AT_PHYSICAL|AT_DRAIN);
508 
509  return head;
510 }
511 
519 void pets_move_golem(object *op) {
520  int made_attack = 0;
521  object *tmp;
522  tag_t tag;
523  object *owner;
524 
525  if (QUERY_FLAG(op, FLAG_MONSTER))
526  return; /* Has already been moved */
527 
528  owner = object_get_owner(op);
529  if (owner == NULL) {
530  LOG(llevDebug, "Golem without owner destructed.\n");
531  object_remove(op);
533  return;
534  }
535  /* It would be nice to have a cleaner way of what message to print
536  * when the golem expires than these hard coded entries.
537  * Note it is intentional that a golems duration is based on its
538  * hp, and not duration
539  */
540  if (--op->stats.hp < 0) {
541  if (op->msg != NULL)
543  op->msg);
544  owner->contr->ranges[range_golem] = NULL;
545  owner->contr->golem_count = 0;
547  object_remove(op);
549  return;
550  }
551 
552  /* Do golem attacks/movement for single & multisq golems.
553  * Assuming here that op is the 'head' object. Pass only op to
554  * move_ob (makes recursive calls to other parts)
555  * move_ob returns 0 if the creature was not able to move.
556  */
557  tag = op->count;
558  if (move_ob(op, op->direction, op))
559  return;
560  if (object_was_destroyed(op, tag))
561  return;
562 
563  for (tmp = op; tmp; tmp = tmp->more) {
564  int16_t x = tmp->x+DIRX(op), y = tmp->y+DIRY(op);
565  object *victim;
566  mapstruct *m;
567  int mflags;
568 
569  m = op->map;
570  mflags = get_map_flags(m, &m, x, y, &x, &y);
571 
572  if (mflags&P_OUT_OF_MAP)
573  continue;
574 
575  victim = NULL;
576  FOR_MAP_PREPARE(op->map, x, y, tmp)
577  if (QUERY_FLAG(tmp, FLAG_ALIVE)) {
578  victim = tmp;
579  break;
580  }
581  FOR_MAP_FINISH();
582 
583  /* We used to call will_hit_self to make sure we don't
584  * hit ourselves, but that didn't work, and I don't really
585  * know if that was more efficient anyways than this.
586  * This at least works. Note that victim->head can be NULL,
587  * but since we are not trying to dereferance that pointer,
588  * that isn't a problem.
589  */
590  if (victim != NULL && victim != op && victim->head != op) {
591  /* for golems with race fields, we don't attack
592  * aligned races
593  */
594 
595  if (victim->race != NULL && op->race != NULL && strstr(op->race, victim->race)) {
596  if (owner != NULL)
599  "%s avoids damaging %s.",
600  op->name, victim->name);
601  } else if (victim == owner) {
602  if (owner != NULL)
605  "%s avoids damaging you.",
606  op->name);
607  } else {
608  attack_ob(victim, op);
609  made_attack = 1;
610  }
611  } /* If victim */
612  }
613  if (made_attack)
615 }
616 
630 void pets_control_golem(object *op, int dir) {
631  op->direction = dir;
632 }
633 
651 int pets_summon_golem(object *op, object *caster, int dir, object *spob) {
652  object *tmp;
653  const object *god = NULL;
654  archetype *at;
655  char buf[MAX_BUF];
656 
657  /* Because there can be different golem spells, player may want to
658  * 'lose' their old golem.
659  */
660  if (op->type == PLAYER
661  && op->contr->ranges[range_golem] != NULL
662  && op->contr->golem_count == op->contr->ranges[range_golem]->count) {
663  draw_ext_info(NDI_UNIQUE, 0, op,
665  "You dismiss your existing golem.");
668  op->contr->ranges[range_golem] = NULL;
669  op->contr->golem_count = -1;
670  }
671 
672  if (spob->other_arch != NULL)
673  at = spob->other_arch;
674  else if (spob->race != NULL) {
675  god = find_god(determine_god(caster));
676  if (god == NULL) {
679  "You must worship a god to cast %s.",
680  spob->name);
681  return 0;
682  }
683 
684  at = determine_holy_arch(god, spob->race);
685  if (at == NULL) {
688  "%s has no %s for you to call.",
689  god->name, spob->race);
690  return 0;
691  }
692  } else {
693  LOG(llevError, "Spell %s lacks other_arch\n", spob->name);
694  return 0;
695  }
696 
697  if (!dir)
698  dir = object_find_free_spot(NULL, op->map, op->x, op->y, 1, SIZEOFFREE1+1);
699 
700  if (dir == -1
701  || ob_blocked(&at->clone, op->map, op->x+freearr_x[dir], op->y+freearr_y[dir])) {
702  draw_ext_info(NDI_UNIQUE, 0, op,
704  "There is something in the way.");
705  return 0;
706  }
707  /* basically want to get proper map/coordinates for this object */
708  tmp = fix_summon_pet(at, op, dir);
709  if (tmp == NULL) {
710  draw_ext_info(NDI_UNIQUE, 0, op,
712  "Your spell fails.");
713  return 0;
714  }
715 
716  if (op->type == PLAYER) {
717  tmp->type = GOLEM;
718  object_set_owner(tmp, op);
719  set_spell_skill(op, caster, spob, tmp);
720  op->contr->ranges[range_golem] = tmp;
721  op->contr->golem_count = tmp->count;
722  /* give the player control of the golem */
723  op->contr->shoottype = range_golem;
724  } else {
725  if (QUERY_FLAG(op, FLAG_FRIENDLY)) {
726  object *owner = object_get_owner(op);
727 
728  if (owner != NULL) { /* For now, we transfer ownership */
729  object_set_owner(tmp, owner);
730  tmp->attack_movement = PETMOVE;
731  add_friendly_object(tmp);
732  set_spell_skill(op, caster, spob, tmp);
733  SET_FLAG(tmp, FLAG_FRIENDLY);
734  }
735  }
736  SET_FLAG(tmp, FLAG_MONSTER);
737  }
738 
739  /* make the speed positive.*/
740  tmp->speed = FABS(tmp->speed);
741 
742  /* This sets the level dependencies on dam and hp for monsters */
743  /* players can't cope with too strong summonings. */
744  /* but monsters can. reserve these for players. */
745  if (op->type == PLAYER) {
746  tmp->stats.hp += spob->duration+SP_level_duration_adjust(caster, spob);
747  tmp->stats.maxhp = tmp->stats.hp;
748  if (!spob->stats.dam)
749  tmp->stats.dam += SP_level_dam_adjust(caster, spob);
750  else
751  tmp->stats.dam = spob->stats.dam+SP_level_dam_adjust(caster, spob);
752  tmp->speed += .02*SP_level_range_adjust(caster, spob);
753  tmp->speed = MIN(tmp->speed, 1.0);
754  if (spob->attacktype)
755  tmp->attacktype = spob->attacktype;
756  }
757  tmp->stats.wc -= SP_level_wc_adjust(caster, spob);
758 
759  /* limit the speed to 0.3 for non-players, 1 for players. */
760 
761  /* make experience increase in proportion to the strength.
762  * this is a bit simplistic - we are basically just looking at how
763  * often the sp doubles and use that as the ratio.
764  */
765  tmp->stats.exp *= 1+(MAX(spob->stats.maxgrace, spob->stats.sp)/caster_level(caster, spob));
766  tmp->speed_left = 0;
767  tmp->direction = dir;
768 
769  /* Holy spell - some additional tailoring */
770  if (god != NULL) {
771  object *tmp2;
772 
773  snprintf(buf, sizeof(buf), "%s of %s", spob->name, god->name);
774  buf[0] = toupper(buf[0]);
775  for (tmp2 = tmp; tmp2; tmp2 = tmp2->more) {
776  if (tmp2->name != NULL)
777  free_string(tmp2->name);
778  tmp2->name = add_string(buf);
779  }
780  tmp->attacktype |= god->attacktype;
781  memcpy(tmp->resist, god->resist, sizeof(tmp->resist));
782  if (tmp->race != NULL)
783  FREE_AND_CLEAR_STR(tmp->race);
784  if (god->race != NULL)
785  tmp->race = add_string(god->race);
786  if (tmp->slaying != NULL)
788  if (god->slaying != NULL)
789  tmp->slaying = add_string(god->slaying);
790  /* safety, we must allow a god's servants some reasonable attack */
791  if (!(tmp->attacktype&AT_PHYSICAL))
792  tmp->attacktype |= AT_PHYSICAL;
793  }
794 
795  object_insert_in_map_at(tmp, tmp->map, op, 0, tmp->x, tmp->y);
796  return 1;
797 }
798 
799 /***************************************************************************
800  *
801  * Summon monster/pet/other object code
802  *
803  ***************************************************************************/
804 
819 static object *choose_cult_monster(object *pl, const object *god, int summon_level) {
820  char buf[MAX_BUF];
821  const char *race;
822  int racenr, i;
823  object *otmp;
824 
825  /* Determine the number of races available */
826  racenr = 0;
827  safe_strncpy(buf, god->race, sizeof(buf));
828  race = strtok(buf, ",");
829  while (race) {
830  racenr++;
831  race = strtok(NULL, ",");
832  }
833 
834  /* next, randomly select a race from the aligned_races string */
835  if (racenr > 1) {
836  racenr = rndm(0, racenr-1);
837  safe_strncpy(buf, god->race, sizeof(buf));
838  race = strtok(buf, ",");
839  for (i = 0; i < racenr; i++)
840  race = strtok(NULL, ",");
841  } else
842  race = god->race;
843 
844  otmp = races_get_random_monster(race, summon_level);
845  if (!otmp) {
848  "The spell fails! %s's creatures are beyond the range of your summons",
849  god->name);
850  }
851  return otmp;
852 }
853 
872 int pets_summon_object(object *op, object *caster, object *spell_ob, int dir, const char *stringarg) {
873  int16_t x, y, nrof = 1, i;
874  archetype *summon_arch;
875  int ndir, mult;
876 
877  if (spell_ob->other_arch != NULL) {
878  summon_arch = spell_ob->other_arch;
879  } else if (spell_ob->randomitems != NULL) {
880  int level = caster_level(caster, spell_ob);
881  treasure *tr, *lasttr = NULL;
882 
883  /* In old code, this was a very convuluted for statement,
884  * with all the checks in the 'for' portion itself. Much
885  * more readable to break some of the conditions out.
886  */
887  for (tr = spell_ob->randomitems->items; tr; tr = tr->next) {
888  if (level < tr->magic)
889  break;
890  lasttr = tr;
891  if (stringarg != NULL && !strcmp(tr->item->name, stringarg))
892  break;
893  if (tr->next == NULL || tr->next->item == NULL)
894  break;
895  }
896  if (lasttr == NULL) {
897  LOG(llevError, "Treasurelist %s did not generate a valid entry in pets_summon_object\n", spell_ob->randomitems->name);
898  draw_ext_info(NDI_UNIQUE, 0, op,
900  "The spell fails to summon any monsters.");
901  return 0;
902  }
903  summon_arch = lasttr->item;
904  nrof = lasttr->nrof;
905  } else if (spell_ob->race != NULL && !strcmp(spell_ob->race, "GODCULTMON")) {
906  const object *god = find_god(determine_god(op));
907  object *mon, *owner;
908  int summon_level, tries;
909 
910  if (god == NULL) {
911  owner = object_get_owner(op);
912  if (owner != NULL) {
913  god = find_god(determine_god(owner));
914  }
915  }
916  /* If we can't find a god, can't get what monster to summon */
917  if (god == NULL)
918  return 0;
919 
920  if (god->race == NULL) {
923  "%s has no creatures that you may summon!",
924  god->name);
925  return 0;
926  }
927  /* the summon level */
928  summon_level = caster_level(caster, spell_ob);
929  if (summon_level == 0)
930  summon_level = 1;
931  tries = 0;
932  do {
933  mon = choose_cult_monster(op, god, summon_level);
934  if (mon == NULL) {
937  "%s fails to send anything.",
938  god->name);
939  return 0;
940  }
941  ndir = dir;
942  if (!ndir)
943  ndir = object_find_free_spot(mon, op->map, op->x, op->y, 1, SIZEOFFREE);
944  if (ndir == -1
945  || ob_blocked(mon, op->map, op->x+freearr_x[ndir], op->y+freearr_y[ndir])) {
946  ndir = -1;
947  if (++tries == 5) {
948  draw_ext_info(NDI_UNIQUE, 0, op,
950  "There is something in the way.");
951  return 0;
952  }
953  }
954  } while (ndir == -1);
955  if (mon->level > summon_level/2)
956  nrof = random_roll(1, 2, op, PREFER_HIGH);
957  else
958  nrof = die_roll(2, 2, op, PREFER_HIGH);
959  summon_arch = mon->arch;
960  } else {
961  summon_arch = NULL;
962  }
963 
964  if (spell_ob->stats.dam)
965  nrof += spell_ob->stats.dam+SP_level_dam_adjust(caster, spell_ob);
966 
967  if (summon_arch == NULL) {
969  "There is no monsters available for summoning.");
970  return 0;
971  }
972 
973  if (dir) {
974  /* Only fail if caster specified a blocked direction. */
975  x = freearr_x[dir];
976  y = freearr_y[dir];
977  if (ob_blocked(&summon_arch->clone, op->map, op->x+x, op->y+y)) {
979  "There is something in the way.");
980  return 0;
981  }
982  }
983 
984  mult = (RANDOM()%2 ? -1 : 1);
985 
986  for (i = 1; i <= nrof; i++) {
987  archetype *atmp;
988  object *prev = NULL, *head = NULL, *tmp;
989 
990  if (dir) {
991  ndir = absdir(dir+(i/2)*mult);
992  mult = -mult;
993  } else
994  ndir = object_find_free_spot(&summon_arch->clone, op->map, op->x, op->y, 1, SIZEOFFREE);
995 
996  x = ndir > 0 ? freearr_x[ndir] : 0;
997  y = ndir > 0 ? freearr_y[ndir] : 0;
998  if (ndir == -1 || ob_blocked(&summon_arch->clone, op->map, op->x+x, op->y+y))
999  continue;
1000 
1001  for (atmp = summon_arch; atmp != NULL; atmp = atmp->more) {
1002  tmp = arch_to_object(atmp);
1003  if (atmp == summon_arch) {
1004  if (QUERY_FLAG(tmp, FLAG_MONSTER)) {
1005  object_set_owner(tmp, op);
1006  set_spell_skill(op, caster, spell_ob, tmp);
1007  object_set_enemy(tmp, op->enemy);
1008  tmp->type = 0;
1009  CLEAR_FLAG(tmp, FLAG_SLEEP);
1010  if (op->type == PLAYER || QUERY_FLAG(op, FLAG_FRIENDLY)) {
1011  /* If this is not set, we make it friendly */
1012  if (!QUERY_FLAG(spell_ob, FLAG_MONSTER)) {
1013  SET_FLAG(tmp, FLAG_FRIENDLY);
1014  add_friendly_object(tmp);
1015  tmp->stats.exp = 0;
1016  if (spell_ob->attack_movement)
1017  tmp->attack_movement = spell_ob->attack_movement;
1018  if (object_get_owner(op) != NULL)
1020  }
1021  }
1022  }
1023  if (tmp->speed > MIN_ACTIVE_SPEED)
1024  tmp->speed_left = -1;
1025  }
1026  if (head == NULL)
1027  head = tmp;
1028  else {
1029  tmp->head = head;
1030  prev->more = tmp;
1031  }
1032  prev = tmp;
1033  }
1034  head->direction = freedir[ndir];
1035  head->stats.exp = 0;
1036  head = object_insert_in_map_at(head, op->map, op, 0, op->x+x, op->y+y);
1037  if (head != NULL && head->randomitems) {
1038  create_treasure(head->randomitems, head, GT_STARTEQUIP, 6, 0);
1039  if (QUERY_FLAG(head, FLAG_MONSTER)) {
1041  }
1042  }
1043  if (head != NULL) {
1045  }
1046  } /* for i < nrof */
1047  return 1;
1048 }
1049 
1059 static object *get_real_owner(object *ob) {
1060  object *realowner = ob;
1061 
1062  if (realowner == NULL)
1063  return NULL;
1064 
1065  while (object_get_owner(realowner) != NULL) {
1066  realowner = object_get_owner(realowner);
1067  }
1068  return realowner;
1069 }
1070 
1086 int pets_should_arena_attack(object *pet, object *owner, object *target) {
1087  object *rowner, *towner;
1088 
1089  /* exit if the target, pet, or owner is null. */
1090  if (target == NULL || pet == NULL || owner == NULL)
1091  return 0;
1092 
1093  /* get the owners of itself and the target, this is to deal with pets of
1094  pets */
1095  rowner = get_real_owner(owner);
1096  if (target->type != PLAYER) {
1097  towner = get_real_owner(target);
1098  } else {
1099  towner = NULL;
1100  }
1101 
1102  /* if the pet has no owner, exit with error */
1103  if (rowner == NULL) {
1104  LOG(llevError, "Pet has no owner.\n");
1105  return 0;
1106  }
1107 
1108  /* if the target is not a player, and has no owner, we shouldn't be here
1109  */
1110  if (towner == NULL && target->type != PLAYER) {
1111  LOG(llevError, "Target is not a player but has no owner. We should not be here.\n");
1112  return 0;
1113  }
1114 
1115  /* make sure that the owner is a player */
1116  if (rowner->type != PLAYER)
1117  return 0;
1118 
1119  /* abort if the petmode is not arena */
1120  if (rowner->contr->petmode != pet_arena)
1121  return 0;
1122 
1123  /* abort if the pet, it's owner, or the target is not on battleground*/
1124  if (!(op_on_battleground(pet, NULL, NULL, NULL)
1125  && op_on_battleground(owner, NULL, NULL, NULL)
1126  && op_on_battleground(target, NULL, NULL, NULL)))
1127  return 0;
1128 
1129  /* if the target is a monster, make sure it's owner is not the same */
1130  if (target->type != PLAYER && rowner == towner)
1131  return 0;
1132 
1133  /* check if the target is a player which affects how it will handle
1134  parties */
1135  if (target->type != PLAYER) {
1136  /* if the target is owned by a player make sure than make sure
1137  it's not in the same party */
1138  if (towner->type == PLAYER && rowner->contr->party != NULL) {
1139  if (rowner->contr->party == towner->contr->party)
1140  return 0;
1141  }
1142  } else {
1143  /* if the target is a player make sure than make sure it's not
1144  in the same party */
1145  if (rowner->contr->party != NULL) {
1146  if (rowner->contr->party == target->contr->party)
1147  return 0;
1148  }
1149  }
1150 
1151  return 1;
1152 }
SP_level_range_adjust
int SP_level_range_adjust(const object *caster, const object *spob)
Adjust the range of the spell based on level.
Definition: spell_util.cpp:338
object_was_destroyed
#define object_was_destroyed(op, old_tag)
Checks if an object still exists.
Definition: object.h:70
living::exp
int64_t exp
Experience.
Definition: living.h:47
UP_OBJ_FACE
#define UP_OBJ_FACE
Only thing that changed was the face.
Definition: object.h:533
PLAYER
@ PLAYER
Definition: object.h:112
object_get_owner
object * object_get_owner(object *op)
Returns the object which this object marks as being the owner.
Definition: object.cpp:804
set_spell_skill
void set_spell_skill(object *op, object *caster, object *spob, object *dest)
Utility function to assign the correct skill when casting.
Definition: spell_util.cpp:94
global.h
choose_cult_monster
static object * choose_cult_monster(object *pl, const object *god, int summon_level)
Returns a monster (chosen at random) that this particular player (and his god) find acceptable.
Definition: pets.cpp:819
safe_strncpy
#define safe_strncpy
Definition: compat.h:27
FOR_MAP_FINISH
#define FOR_MAP_FINISH()
Finishes FOR_MAP_PREPARE().
Definition: define.h:724
remove_friendly_object
void remove_friendly_object(object *op)
Removes the specified object from the linked list of friendly objects.
Definition: friend.cpp:52
living::maxhp
int16_t maxhp
Max hit points.
Definition: living.h:41
pets_terminate_all
void pets_terminate_all(object *owner)
Removes all pets someone owns.
Definition: pets.cpp:225
FLAG_STAND_STILL
#define FLAG_STAND_STILL
NPC will not (ever) move.
Definition: define.h:308
FLAG_CONFUSED
#define FLAG_CONFUSED
Will also be unable to cast spells.
Definition: define.h:311
llevError
@ llevError
Error, serious thing.
Definition: logger.h:11
FABS
#define FABS(x)
Decstations have trouble with fabs()...
Definition: define.h:22
pets_control_golem
void pets_control_golem(object *op, int dir)
Makes the golem go in specified direction.
Definition: pets.cpp:630
LOG
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
Definition: logger.cpp:58
SET_FLAG
#define SET_FLAG(xyz, p)
Definition: define.h:224
archetype::more
archetype * more
Next part of a linked object.
Definition: object.h:486
monster_can_detect_enemy
int monster_can_detect_enemy(object *op, object *enemy, rv_vector *rv)
Determine if we can 'detect' the enemy.
Definition: monster.cpp:2581
FLAG_GENERATOR
#define FLAG_GENERATOR
Will generate type ob->stats.food.
Definition: define.h:248
pets_get_enemy
object * pets_get_enemy(object *pet, rv_vector *rv)
Given that 'pet' is a friendly object, this function returns a monster the pet should attack,...
Definition: pets.cpp:54
player::golem_count
uint32_t golem_count
To track the golem.
Definition: player.h:119
SIZEOFFREE1
#define SIZEOFFREE1
Definition: define.h:153
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
treasurelist::items
treasure * items
Items in this list, linked.
Definition: treasure.h:92
get_random_dir
int get_random_dir(void)
Returns a random direction (1..8).
Definition: utils.cpp:400
op_on_battleground
int op_on_battleground(object *op, int *x, int *y, archetype **trophy)
Check if the given object (usually a player) is standing on a battleground tile.
Definition: player.cpp:4262
get_friends_of
objectlink * get_friends_of(const object *owner)
Get a list of friendly objects for the specified owner.
Definition: friend.cpp:117
pet_defend
@ pet_defend
Stay close to the owner.
Definition: player.h:60
AT_PHYSICAL
#define AT_PHYSICAL
Definition: attack.h:76
object::arch
struct archetype * arch
Pointer to archetype.
Definition: object.h:424
object::attack_movement
uint16_t attack_movement
What kind of attack movement.
Definition: object.h:401
absdir
int absdir(int d)
Computes an absolute direction.
Definition: object.cpp:3714
object::speed
float speed
Frequency of object 'moves' relative to server tick rate.
Definition: object.h:337
object_set_enemy
void object_set_enemy(object *op, object *enemy)
Sets the enemy of an object.
Definition: object.cpp:915
MSG_TYPE_SPELL_PET
#define MSG_TYPE_SPELL_PET
Pet related messages.
Definition: newclient.h:635
object::invisible
int16_t invisible
How much longer the object will be invis.
Definition: object.h:370
object::x
int16_t x
Definition: object.h:335
object::speed_left
float speed_left
How much speed is left to spend this round.
Definition: object.h:338
object::map
struct mapstruct * map
Pointer to the map in which this object is present.
Definition: object.h:305
pets_summon_golem
int pets_summon_golem(object *op, object *caster, int dir, object *spob)
Summons a monster.
Definition: pets.cpp:651
object_set_owner
void object_set_owner(object *op, object *owner)
Sets the owner and sets the skill and exp pointers to owner's current skill and experience objects.
Definition: object.cpp:840
draw_ext_info_format
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...) PRINTF_ARGS(6
mark_inventory_as_no_drop
static void mark_inventory_as_no_drop(object *ob)
Mark all inventory items as FLAG_NO_DROP.
Definition: pets.cpp:34
MIN
#define MIN(x, y)
Definition: compat.h:21
races_get_random_monster
object * races_get_random_monster(const char *race, int level)
Get a random monster of specified race and level at most the specified one.
Definition: races.cpp:22
SP_level_duration_adjust
int SP_level_duration_adjust(const object *caster, const object *spob)
Adjust the duration of the spell based on level.
Definition: spell_util.cpp:312
object::direction
int8_t direction
Means the object is moving that way.
Definition: object.h:344
object::count
tag_t count
Unique object number for this object.
Definition: object.h:307
DIRX
#define DIRX(xyz)
Definition: define.h:457
llevMonster
@ llevMonster
Many many details.
Definition: logger.h:14
object::enemy
object * enemy
Monster/player to follow even if not closest.
Definition: object.h:391
rndm
int rndm(int min, int max)
Returns a number between min and max.
Definition: utils.cpp:162
range_golem
@ range_golem
Control golem.
Definition: player.h:34
P_IS_ALIVE
#define P_IS_ALIVE
Something alive is on this space.
Definition: map.h:237
MSG_TYPE_MISC
#define MSG_TYPE_MISC
Messages that don't go elsewhere.
Definition: newclient.h:416
object::level
int16_t level
Level of creature or object.
Definition: object.h:361
GT_STARTEQUIP
@ GT_STARTEQUIP
Generated items have the FLAG_STARTEQUIP.
Definition: treasure.h:33
buf
StringBuffer * buf
Definition: readable.cpp:1565
MAX
#define MAX(x, y)
Definition: compat.h:24
object::resist
int16_t resist[NROFATTACKS]
Resistance adjustments for attacks.
Definition: object.h:351
find_god
const object * find_god(const char *name)
Returns a god's object from its name.
Definition: holy.cpp:317
draw_ext_info
vs only yadda is in because all tags get reset on the next draw_ext_info In the second since it is all in one draw_ext_info
Definition: media-tags.txt:61
FLAG_ALIVE
#define FLAG_ALIVE
Object can fight (or be fought)
Definition: define.h:230
object::y
int16_t y
Position in the map for this object.
Definition: object.h:335
m
static event_registration m
Definition: citylife.cpp:422
MAP_IN_MEMORY
#define MAP_IN_MEMORY
Map is fully loaded.
Definition: map.h:126
monster_find_nearest_enemy
object * monster_find_nearest_enemy(object *npc, object *owner)
Returns the nearest enemy (monster or generator) which is visible to npc.
Definition: monster.cpp:175
object_free_drop_inventory
void object_free_drop_inventory(object *ob)
Frees everything allocated by an object, removes it from the list of used objects,...
Definition: object.cpp:1560
object_update
void object_update(object *op, int action)
object_update() updates the array which represents the map.
Definition: object.cpp:1434
object::contr
struct player * contr
Pointer to the player which control this object.
Definition: object.h:284
PREFER_HIGH
#define PREFER_HIGH
Definition: define.h:557
determine_god
const char * determine_god(object *op)
Determines if op worships a god.
Definition: gods.cpp:55
freearr_y
short freearr_y[SIZEOFFREE]
Y offset when searching around a spot.
Definition: object.cpp:305
move_ob
int move_ob(object *op, int dir, object *originator)
Op is trying to move in direction dir.
Definition: move.cpp:58
MOVE_WALK
#define MOVE_WALK
Object walks.
Definition: define.h:392
player::ranges
object * ranges[range_size]
Object for each range.
Definition: player.h:116
archetype::clone
object clone
An object from which to do object_copy()
Definition: object.h:487
add_string
sstring add_string(const char *str)
This will add 'str' to the hash table.
Definition: shstr.cpp:124
treasurelist::name
sstring name
Usually monster-name/combination.
Definition: treasure.h:86
pets_should_arena_attack
int pets_should_arena_attack(object *pet, object *owner, object *target)
Determines if checks so pets don't attack players or other pets should be overruled by the arena petm...
Definition: pets.cpp:1086
HEAD
#define HEAD(op)
Returns the head part of an object.
Definition: object.h:607
treasure::nrof
uint16_t nrof
Random 1 to nrof items are generated.
Definition: treasure.h:79
object::move_type
MoveType move_type
Type of movement this object uses.
Definition: object.h:436
pets_move_golem
void pets_move_golem(object *op)
Handles a golem's movement.
Definition: pets.cpp:519
object::type
uint8_t type
PLAYER, BULLET, etc.
Definition: object.h:348
living::dam
int16_t dam
How much damage this object does when hitting.
Definition: living.h:46
treasure::item
struct archetype * item
Which item this link can be.
Definition: treasure.h:64
GET_MAP_MOVE_BLOCK
#define GET_MAP_MOVE_BLOCK(M, X, Y)
Gets the blocking state of a square.
Definition: map.h:192
FOR_INV_FINISH
#define FOR_INV_FINISH()
Finishes FOR_INV_PREPARE().
Definition: define.h:671
GOLEM
@ GOLEM
Definition: object.h:150
caster_level
int caster_level(const object *caster, const object *spell)
This function returns the effective level the spell is being cast at.
Definition: spell_util.cpp:194
FLAG_UNAGGRESSIVE
#define FLAG_UNAGGRESSIVE
Monster doesn't attack players.
Definition: define.h:272
pets_attempt_follow
void pets_attempt_follow(object *for_owner, int force)
Check pets so they try to follow their master around the world.
Definition: pets.cpp:249
tag_t
uint32_t tag_t
Object tag, unique during the whole game.
Definition: object.h:14
archetype
The archetype structure is a set of rules on how to generate and manipulate objects which point to ar...
Definition: object.h:483
player::shoottype
rangetype shoottype
Which range-attack is being used by player.
Definition: player.h:112
sproto.h
FLAG_NO_DROP
#define FLAG_NO_DROP
Object can't be dropped.
Definition: define.h:288
living::sp
int16_t sp
Spell points.
Definition: living.h:42
get_map_from_coord
mapstruct * get_map_from_coord(mapstruct *m, int16_t *x, int16_t *y)
This is basically the same as out_of_map above(), but instead we return NULL if no map is valid (coor...
Definition: map.cpp:2334
MSG_TYPE_SPELL
#define MSG_TYPE_SPELL
Spell related info.
Definition: newclient.h:414
random_roll
int random_roll(int min, int max, const object *op, int goodbad)
Roll a random number between min and max.
Definition: utils.cpp:42
MSG_SUBTYPE_NONE
#define MSG_SUBTYPE_NONE
Definition: newclient.h:423
object::race
sstring race
Human, goblin, dragon, etc.
Definition: object.h:326
ob_blocked
int ob_blocked(const object *ob, mapstruct *m, int16_t x, int16_t y)
Returns true if the given object can't fit in the given spot.
Definition: map.cpp:491
FLAG_SPLITTING
#define FLAG_SPLITTING
Object splits into stats.food other objs.
Definition: define.h:266
object_insert_in_map_at
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:2100
object::other_arch
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
treasure::next
treasure * next
Next treasure-item in a linked list.
Definition: treasure.h:69
FLAG_MONSTER
#define FLAG_MONSTER
Will attack players.
Definition: define.h:245
SIZEOFFREE
#define SIZEOFFREE
Definition: define.h:155
P_OUT_OF_MAP
#define P_OUT_OF_MAP
This space is outside the map.
Definition: map.h:249
MAX_BUF
#define MAX_BUF
Used for all kinds of things.
Definition: define.h:35
SP_level_wc_adjust
int SP_level_wc_adjust(const object *caster, const object *spob)
Returns adjusted wc based on the caster and the spell.
Definition: spell_util.cpp:362
object::head
object * head
Points to the main object of a large body.
Definition: object.h:304
free_string
void free_string(sstring str)
This will reduce the refcount, and if it has reached 0, str will be freed.
Definition: shstr.cpp:280
monster_check_apply_all
void monster_check_apply_all(object *monster)
Calls monster_check_apply() for all inventory objects.
Definition: monster.cpp:1999
pet_sad
@ pet_sad
Try to find enemies.
Definition: player.h:59
living::wc
int8_t wc
Weapon Class, lower WC increases probability of hitting.
Definition: living.h:37
RANDOM
#define RANDOM()
Definition: define.h:638
FREE_AND_CLEAR_STR
#define FREE_AND_CLEAR_STR(xyz)
Release the shared string, and set it to NULL.
Definition: global.h:200
living::maxgrace
int16_t maxgrace
Maximum grace.
Definition: living.h:45
FOR_MAP_PREPARE
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Constructs a loop iterating over all objects of a map tile.
Definition: define.h:717
get_search_arr
void get_search_arr(int *search_arr)
New function to make monster searching more efficient, and effective! This basically returns a random...
Definition: object.cpp:3642
FLAG_REMOVED
#define FLAG_REMOVED
Object is not in any map or invenory.
Definition: define.h:232
monster_can_see_enemy
int monster_can_see_enemy(object *op, object *enemy)
Assuming no walls/barriers, lets check to see if its possible to see an enemy.
Definition: monster.cpp:2758
NDI_UNIQUE
#define NDI_UNIQUE
Print immediately, don't buffer.
Definition: newclient.h:265
object::slaying
sstring slaying
Which race to do double damage to.
Definition: object.h:327
FLAG_FRIENDLY
#define FLAG_FRIENDLY
Will help players.
Definition: define.h:246
object::name
sstring name
The name of the object, obviously...
Definition: object.h:319
SP_level_dam_adjust
int SP_level_dam_adjust(const object *caster, const object *spob)
Returns adjusted damage based on the caster.
Definition: spell_util.cpp:287
pets_summon_object
int pets_summon_object(object *op, object *caster, object *spell_ob, int dir, const char *stringarg)
General purpose summoning function.
Definition: pets.cpp:872
MSG_TYPE_SPELL_FAILURE
#define MSG_TYPE_SPELL_FAILURE
Spell failure messages.
Definition: newclient.h:636
add_friendly_object
void add_friendly_object(object *op)
Add a new friendly object to the list of friendly objects.
Definition: friend.cpp:32
get_map_flags
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
mapstruct
This is a game-map.
Definition: map.h:315
get_real_owner
static object * get_real_owner(object *ob)
Recursively look through the owner property of objects until the real owner is found.
Definition: pets.cpp:1059
object_find_free_spot
int object_find_free_spot(const object *ob, mapstruct *m, int x, int y, int start, int stop)
object_find_free_spot(object, map, x, y, start, stop) will search for a spot at the given map and coo...
Definition: object.cpp:3559
pets_follow_owner
void pets_follow_owner(object *ob, object *owner)
A pet is trying to follow its owner.
Definition: pets.cpp:284
mapstruct::in_memory
uint32_t in_memory
Combination of IN_MEMORY_xxx flags.
Definition: map.h:335
object::attacked_by_count
tag_t attacked_by_count
The tag of attacker, so we can be sure.
Definition: object.h:393
object::msg
sstring msg
If this is a book/sign/magic mouth/etc.
Definition: object.h:330
rv_vector
This is used by get_rangevector to determine where the other creature is.
Definition: map.h:370
monster_check_enemy
object * monster_check_enemy(object *npc, rv_vector *rv)
Checks npc->enemy and returns that enemy if still valid, NULL otherwise.
Definition: monster.cpp:72
on_same_map
int on_same_map(const object *op1, const object *op2)
Checks whether 2 objects are on the same map or not.
Definition: map.cpp:2611
pet_arena
@ pet_arena
Attack other players in arena.
Definition: player.h:61
CLEAR_FLAG
#define CLEAR_FLAG(xyz, p)
Definition: define.h:225
object::attacked_by
object * attacked_by
This object start to attack us! only player & monster.
Definition: object.h:392
object::duration
int16_t duration
Number of moves (see 'speed') spell lasts.
Definition: object.h:415
die_roll
int die_roll(int num, int size, const object *op, int goodbad)
Roll a number of dice (2d3, 4d6).
Definition: utils.cpp:122
arch_to_object
object * arch_to_object(archetype *at)
Creates and returns a new object which is a copy of the given archetype.
Definition: arch.cpp:227
level
int level
Definition: readable.cpp:1563
get_rangevector
int get_rangevector(object *op1, const object *op2, rv_vector *retval, int flags)
From map.c This is used by get_player to determine where the other creature is.
Definition: map.cpp:2505
player::party
partylist * party
Party this player is part of.
Definition: player.h:203
MIN_ACTIVE_SPEED
#define MIN_ACTIVE_SPEED
Cut off point of when an object is put on the active list or not.
Definition: define.h:633
object::randomitems
struct treasurelist * randomitems
Items to be generated.
Definition: object.h:395
object_remove
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:1833
pets_move
void pets_move(object *ob)
Handles a pet's movement.
Definition: pets.cpp:317
freedir
int freedir[SIZEOFFREE]
Direction we're pointing on this spot.
Definition: object.cpp:317
OB_TYPE_MOVE_BLOCK
#define OB_TYPE_MOVE_BLOCK(ob1, type)
Basic macro to see if if ob1 can not move onto a space based on the 'type' move_block parameter Add c...
Definition: define.h:426
archetype::name
sstring name
More definite name, like "generate_kobold".
Definition: object.h:484
PETMOVE
#define PETMOVE
If the upper four bits of attack_movement are set to this number, the monster follows a player until ...
Definition: define.h:495
object::stats
living stats
Str, Con, Dex, etc.
Definition: object.h:378
treasure
treasure is one element in a linked list, which together consist of a complete treasure-list.
Definition: treasure.h:63
list
How to Install a Crossfire Server on you must install a python script engine on your computer Python is the default script engine of Crossfire You can find the python engine you have only to install them The VisualC Crossfire settings are for but you habe then to change the pathes in the VC settings Go in Settings C and Settings Link and change the optional include and libs path to the new python installation path o except the maps ! You must download a map package and install them the share folder Its must look like doubleclick on crossfire32 dsw There are projects in your libcross lib and plugin_python You need to compile all Easiest way is to select the plugin_python ReleaseLog as active this will compile all others too Then in Visual C press< F7 > to compile If you don t have an appropriate compiler you can try to get the the VC copies the crossfire32 exe in the crossfire folder and the plugin_python dll in the crossfire share plugins folder we will remove it when we get time for it o Last showing lots of weird write to the Crossfire mailing list
Definition: INSTALL_WIN32.txt:50
object::more
object * more
Pointer to the rest of a large body of objects.
Definition: object.h:303
attack_ob
int attack_ob(object *op, object *hitter)
Simple wrapper for attack_ob_simple(), will use hitter's values.
Definition: attack.cpp:937
freearr_x
short freearr_x[SIZEOFFREE]
X offset when searching around a spot.
Definition: object.cpp:299
player::petmode
petmode_t petmode
Which petmode?
Definition: player.h:115
FLAG_CHANGING
#define FLAG_CHANGING
Changes to other_arch when anim is done.
Definition: define.h:263
AT_GHOSTHIT
#define AT_GHOSTHIT
Definition: attack.h:85
object::attacktype
uint32_t attacktype
Bitmask of attacks this object does.
Definition: object.h:352
rv_vector::direction
int direction
General direction to the targer.
Definition: map.h:374
FLAG_SLEEP
#define FLAG_SLEEP
NPC is sleeping.
Definition: define.h:307
FOR_INV_PREPARE
#define FOR_INV_PREPARE(op_, it_)
Constructs a loop iterating over the inventory of an object.
Definition: define.h:664
living::hp
int16_t hp
Hit Points.
Definition: living.h:40
create_treasure
void create_treasure(treasurelist *t, object *op, int flag, int difficulty, int tries)
This calls the appropriate treasure creation function.
Definition: treasure.cpp:263
fix_summon_pet
static object * fix_summon_pet(archetype *at, object *op, int dir)
This makes multisquare/single square monsters proper for map insertion.
Definition: pets.cpp:434
AT_DRAIN
#define AT_DRAIN
Definition: attack.h:83
llevDebug
@ llevDebug
Only for debugging purposes.
Definition: logger.h:13
DIRY
#define DIRY(xyz)
Definition: define.h:458
determine_holy_arch
archetype * determine_holy_arch(const object *god, const char *type)
Determines the archetype for holy servant and god avatar.
Definition: gods.cpp:676