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 
224 void pets_terminate(object *pet)
225 {
226  if (pet->owner && pet->owner->contr && pet->owner->contr->ranges[range_golem] == pet) {
227  pet->owner->contr->ranges[range_golem] = nullptr;
228  pet->owner->contr->golem_count = 0;
229  }
230  if (!QUERY_FLAG(pet, FLAG_REMOVED))
231  object_remove(pet);
234 }
235 
242 void pets_terminate_all(object *owner) {
243  objectlink *link = get_friends_of(owner), *cur;
244  if (!link) {
245  return;
246  }
247  for (cur = link; cur != NULL; cur = cur->next) {
248  pets_terminate(cur->ob);
249  }
250 
251  free_objectlink(link);
252 }
253 
262 void pets_attempt_follow(object *for_owner, int force) {
263  objectlink *list = get_friends_of(for_owner), *cur;
264  object *owner;
265  if (!list) {
266  return;
267  }
268 
269  for (cur = list; cur != NULL; cur = cur->next) {
270  if (cur->ob->type != PLAYER
271  && QUERY_FLAG(cur->ob, FLAG_FRIENDLY)
272  && (owner = object_get_owner(cur->ob)) != NULL
273  && (for_owner == NULL || for_owner == owner)
274  && (force || !on_same_map(owner, cur->ob))) {
275  /* follow owner checks map status for us. Note that pet can
276  * die in pets_follow_owner(), so check for obl->ob existence
277  */
278  pets_follow_owner(cur->ob, owner);
279  if (cur->ob && QUERY_FLAG(cur->ob, FLAG_REMOVED) && FABS(cur->ob->speed) > MIN_ACTIVE_SPEED) {
280  LOG(llevMonster, "(pet failed to follow)\n");
281  remove_friendly_object(cur->ob);
283  }
284  }
285  }
287 }
288 
297 void pets_follow_owner(object *ob, object *owner) {
298  int dir;
299 
300  if (!QUERY_FLAG(ob, FLAG_REMOVED))
301  object_remove(ob);
302 
303  if (owner->map == NULL) {
304  LOG(llevError, "Can't follow owner: no map.\n");
305  return;
306  }
307  if (owner->map->in_memory != MAP_IN_MEMORY) {
308  LOG(llevError, "Owner of the pet not on a map in memory!?\n");
309  return;
310  }
311  dir = object_find_free_spot(ob, owner->map, owner->x, owner->y, 1, SIZEOFFREE);
312 
313  if (dir == -1) {
314  LOG(llevMonster, "No space for pet to follow, freeing %s.\n", ob->name);
315  return; /* Will be freed since it's removed */
316  }
317  object_insert_in_map_at(ob, owner->map, NULL, 0, owner->x+freearr_x[dir], owner->y+freearr_y[dir]);
318  if (owner->type == PLAYER) /* Uh, I hope this is always true... */
320  "Your pet magically appears next to you");
321  return;
322 }
323 
330 void pets_move(object *ob) {
331  int dir, i;
332  tag_t tag;
333  int16_t dx, dy;
334  object *owner;
335  mapstruct *m;
336 
337  /* Check to see if player pulled out */
338  owner = object_get_owner(ob);
339  if (owner == NULL) {
340  object_remove(ob); /* Will be freed when returning */
343  LOG(llevMonster, "Pet: no owner, leaving.\n");
344  return;
345  }
346 
347  /* move monster into the owners map if not in the same map */
348  if (!on_same_map(ob, owner)) {
349  pets_follow_owner(ob, owner);
350  return;
351  }
352  /* Calculate Direction */
353  if (owner->type == PLAYER && owner->contr->petmode == pet_sad) {
354  /* in S&D mode, if we have no enemy, run randomly about. */
355  for (i = 0; i < 15; i++) {
356  dir = get_random_dir();
357  dx = ob->x+freearr_x[dir];
358  dy = ob->y+freearr_y[dir];
359  m = ob->map;
360  if (!(get_map_flags(ob->map, &m, dx, dy, &dx, &dy)&P_OUT_OF_MAP)
361  && !OB_TYPE_MOVE_BLOCK(ob, GET_MAP_MOVE_BLOCK(m, dx, dy)))
362  break;
363  }
364  } else {
365  rv_vector rv;
366 
367  if (get_rangevector(ob, owner, &rv, 0))
368  dir = rv.direction;
369  else
370  dir = get_random_dir();
371  }
372  ob->direction = dir;
373 
374  tag = ob->count;
375  /* move_ob returns 0 if the object couldn't move. If that is the
376  * case, lets do some other work.
377  */
378  if (!move_ob(ob, dir, ob)) {
379  object *part;
380 
381  /* the failed move_ob above may destroy the pet, so check here */
382  if (object_was_destroyed(ob, tag))
383  return;
384 
385  for (part = ob; part != NULL; part = part->more) {
386  dx = part->x+freearr_x[dir];
387  dy = part->y+freearr_y[dir];
388  m = get_map_from_coord(part->map, &dx, &dy);
389  if (m == NULL)
390  continue;
391 
392  FOR_MAP_PREPARE(m, dx, dy, ob2) {
393  object *new_ob;
394 
395  new_ob = HEAD(ob2);
396  if (new_ob == ob)
397  break;
398  if (new_ob == owner)
399  return;
400  if (object_get_owner(new_ob) == owner)
401  break;
402 
403  /* Hmm. Did we try to move into an enemy monster? If so,
404  * make it our enemy.
405  */
406  if (QUERY_FLAG(new_ob, FLAG_ALIVE)
408  && !QUERY_FLAG(new_ob, FLAG_UNAGGRESSIVE)
409  && !QUERY_FLAG(new_ob, FLAG_FRIENDLY)) {
410  object_set_enemy(ob, new_ob);
411  if (new_ob->enemy == NULL)
412  object_set_enemy(new_ob, ob);
413  return;
414  } else if (new_ob->type == PLAYER) {
415  draw_ext_info(NDI_UNIQUE, 0, new_ob,
417  "You stand in the way of someones pet.");
418  return;
419  }
420  } FOR_MAP_FINISH();
421  }
422  /* Try a different course */
423  dir = absdir(dir+4-(RANDOM()%5)-(RANDOM()%5));
424  (void)move_ob(ob, dir, ob);
425  }
426  return;
427 }
428 
429 /****************************************************************************
430  *
431  * GOLEM SPELL CODE
432  *
433  ****************************************************************************/
434 
447 static object *fix_summon_pet(archetype *at, object *op, int dir) {
448  archetype *atmp;
449  object *tmp = NULL, *prev = NULL, *head = NULL;
450 
451  for (atmp = at; atmp != NULL; atmp = atmp->more) {
452  tmp = arch_to_object(atmp);
453  if (atmp == at) {
454 
455  /* Ensure the golem can actually move if no move_type defined.
456  * This check is redundant since this is checked at server startup. */
457  if (tmp->move_type == 0) {
458  LOG(llevError, "summoned %s [%s] is without move_type!\n", tmp->name, atmp->name);
459  tmp->move_type = MOVE_WALK;
460  }
461 
462  object_set_owner(tmp, op);
463  if (op->type == PLAYER) {
464  tmp->stats.exp = 0;
465  add_friendly_object(tmp);
466  SET_FLAG(tmp, FLAG_FRIENDLY);
467  CLEAR_FLAG(tmp, FLAG_MONSTER);
468  } else if (QUERY_FLAG(op, FLAG_FRIENDLY)) {
469  object *owner = object_get_owner(op);
470 
471  if (owner != NULL) {/* For now, we transfer ownership */
472  object_set_owner(tmp, owner);
473  tmp->attack_movement = PETMOVE;
474  add_friendly_object(tmp);
475  SET_FLAG(tmp, FLAG_FRIENDLY);
476  }
477  }
478  if (op->type != PLAYER) {
479  tmp->attack_movement = PETMOVE;
480  tmp->speed_left = -1;
481  tmp->type = 0;
482  object_set_enemy(tmp, op->enemy);
483  } else
484  tmp->type = GOLEM;
485  }
486  if (head == NULL)
487  head = tmp;
488  tmp->x = op->x+freearr_x[dir]+tmp->arch->clone.x;
489  tmp->y = op->y+freearr_y[dir]+tmp->arch->clone.y;
490  tmp->map = op->map;
491  if (tmp->invisible)
492  tmp->invisible = 0;
493  if (head != tmp)
494  tmp->head = head,
495  prev->more = tmp;
496  prev = tmp;
497  }
498  head->direction = dir;
499 
500  if (head->randomitems) {
501  create_treasure(head->randomitems, head, GT_STARTEQUIP, 6, 0);
502  if (QUERY_FLAG(head, FLAG_MONSTER)) {
504  }
505  }
507 
508  /* need to change some monster attr to prevent problems/crashing */
509  head->last_heal = 0;
510  head->last_eat = 0;
511  head->last_grace = 0;
512  head->last_sp = 0;
513  head->other_arch = NULL;
514  head->stats.exp = 0;
515  CLEAR_FLAG(head, FLAG_CHANGING);
517  CLEAR_FLAG(head, FLAG_GENERATOR);
518  CLEAR_FLAG(head, FLAG_SPLITTING);
519  if (head->attacktype&AT_GHOSTHIT)
520  head->attacktype = (AT_PHYSICAL|AT_DRAIN);
521 
522  return head;
523 }
524 
532 void pets_move_golem(object *op) {
533  int made_attack = 0;
534  object *tmp;
535  tag_t tag;
536  object *owner;
537 
538  if (QUERY_FLAG(op, FLAG_MONSTER))
539  return; /* Has already been moved */
540 
541  owner = object_get_owner(op);
542  if (owner == NULL) {
543  LOG(llevDebug, "Golem without owner destructed.\n");
544  object_remove(op);
546  return;
547  }
548  /* It would be nice to have a cleaner way of what message to print
549  * when the golem expires than these hard coded entries.
550  * Note it is intentional that a golems duration is based on its
551  * hp, and not duration
552  */
553  if (--op->stats.hp < 0) {
554  if (op->msg != NULL)
556  op->msg);
557  owner->contr->ranges[range_golem] = NULL;
558  owner->contr->golem_count = 0;
560  object_remove(op);
562  return;
563  }
564 
565  /* Do golem attacks/movement for single & multisq golems.
566  * Assuming here that op is the 'head' object. Pass only op to
567  * move_ob (makes recursive calls to other parts)
568  * move_ob returns 0 if the creature was not able to move.
569  */
570  tag = op->count;
571  if (move_ob(op, op->direction, op))
572  return;
573  if (object_was_destroyed(op, tag))
574  return;
575 
576  for (tmp = op; tmp; tmp = tmp->more) {
577  int16_t x = tmp->x+DIRX(op), y = tmp->y+DIRY(op);
578  object *victim;
579  mapstruct *m;
580  int mflags;
581 
582  m = op->map;
583  mflags = get_map_flags(m, &m, x, y, &x, &y);
584 
585  if (mflags&P_OUT_OF_MAP)
586  continue;
587 
588  victim = NULL;
589  FOR_MAP_PREPARE(op->map, x, y, tmp)
590  if (QUERY_FLAG(tmp, FLAG_ALIVE)) {
591  victim = tmp;
592  break;
593  }
594  FOR_MAP_FINISH();
595 
596  /* We used to call will_hit_self to make sure we don't
597  * hit ourselves, but that didn't work, and I don't really
598  * know if that was more efficient anyways than this.
599  * This at least works. Note that victim->head can be NULL,
600  * but since we are not trying to dereferance that pointer,
601  * that isn't a problem.
602  */
603  if (victim != NULL && victim != op && victim->head != op) {
604  /* for golems with race fields, we don't attack
605  * aligned races
606  */
607 
608  if (victim->race != NULL && op->race != NULL && strstr(op->race, victim->race)) {
609  if (owner != NULL)
612  "%s avoids damaging %s.",
613  op->name, victim->name);
614  } else if (victim == owner) {
615  if (owner != NULL)
618  "%s avoids damaging you.",
619  op->name);
620  } else {
621  attack_ob(victim, op);
622  made_attack = 1;
623  }
624  } /* If victim */
625  }
626  if (made_attack)
628 }
629 
643 void pets_control_golem(object *op, int dir) {
644  op->direction = dir;
645 }
646 
664 int pets_summon_golem(object *op, object *caster, int dir, object *spob) {
665  object *tmp;
666  const object *god = NULL;
667  archetype *at;
668  char buf[MAX_BUF];
669 
670  /* Because there can be different golem spells, player may want to
671  * 'lose' their old golem.
672  */
673  if (op->type == PLAYER
674  && op->contr->ranges[range_golem] != NULL
675  && op->contr->golem_count == op->contr->ranges[range_golem]->count) {
676  draw_ext_info(NDI_UNIQUE, 0, op,
678  "You dismiss your existing golem.");
681  op->contr->ranges[range_golem] = NULL;
682  op->contr->golem_count = -1;
683  }
684 
685  if (spob->other_arch != NULL)
686  at = spob->other_arch;
687  else if (spob->race != NULL) {
688  god = find_god(determine_god(caster));
689  if (god == NULL) {
692  "You must worship a god to cast %s.",
693  spob->name);
694  return 0;
695  }
696 
697  at = determine_holy_arch(god, spob->race);
698  if (at == NULL) {
701  "%s has no %s for you to call.",
702  god->name, spob->race);
703  return 0;
704  }
705  } else {
706  LOG(llevError, "Spell %s lacks other_arch\n", spob->name);
707  return 0;
708  }
709 
710  if (!dir)
711  dir = object_find_free_spot(NULL, op->map, op->x, op->y, 1, SIZEOFFREE1+1);
712 
713  if (dir == -1
714  || ob_blocked(&at->clone, op->map, op->x+freearr_x[dir], op->y+freearr_y[dir])) {
715  draw_ext_info(NDI_UNIQUE, 0, op,
717  "There is something in the way.");
718  return 0;
719  }
720  /* basically want to get proper map/coordinates for this object */
721  tmp = fix_summon_pet(at, op, dir);
722  if (tmp == NULL) {
723  draw_ext_info(NDI_UNIQUE, 0, op,
725  "Your spell fails.");
726  return 0;
727  }
728 
729  if (op->type == PLAYER) {
730  tmp->type = GOLEM;
731  object_set_owner(tmp, op);
732  set_spell_skill(op, caster, spob, tmp);
733  op->contr->ranges[range_golem] = tmp;
734  op->contr->golem_count = tmp->count;
735  /* give the player control of the golem */
736  op->contr->shoottype = range_golem;
737  } else {
738  if (QUERY_FLAG(op, FLAG_FRIENDLY)) {
739  object *owner = object_get_owner(op);
740 
741  if (owner != NULL) { /* For now, we transfer ownership */
742  object_set_owner(tmp, owner);
743  tmp->attack_movement = PETMOVE;
744  add_friendly_object(tmp);
745  set_spell_skill(op, caster, spob, tmp);
746  SET_FLAG(tmp, FLAG_FRIENDLY);
747  }
748  }
749  SET_FLAG(tmp, FLAG_MONSTER);
750  }
751 
752  /* make the speed positive.*/
753  tmp->speed = FABS(tmp->speed);
754 
755  /* This sets the level dependencies on dam and hp for monsters */
756  /* players can't cope with too strong summonings. */
757  /* but monsters can. reserve these for players. */
758  if (op->type == PLAYER) {
759  tmp->stats.hp += spob->duration+SP_level_duration_adjust(caster, spob);
760  tmp->stats.maxhp = tmp->stats.hp;
761  if (!spob->stats.dam)
762  tmp->stats.dam += SP_level_dam_adjust(caster, spob);
763  else
764  tmp->stats.dam = spob->stats.dam+SP_level_dam_adjust(caster, spob);
765  tmp->speed += .02*SP_level_range_adjust(caster, spob);
766  tmp->speed = MIN(tmp->speed, 1.0);
767  if (spob->attacktype)
768  tmp->attacktype = spob->attacktype;
769  }
770  tmp->stats.wc -= SP_level_wc_adjust(caster, spob);
771 
772  /* limit the speed to 0.3 for non-players, 1 for players. */
773 
774  /* make experience increase in proportion to the strength.
775  * this is a bit simplistic - we are basically just looking at how
776  * often the sp doubles and use that as the ratio.
777  */
778  tmp->stats.exp *= 1+(MAX(spob->stats.maxgrace, spob->stats.sp)/caster_level(caster, spob));
779  tmp->speed_left = 0;
780  tmp->direction = dir;
781 
782  /* Holy spell - some additional tailoring */
783  if (god != NULL) {
784  object *tmp2;
785 
786  snprintf(buf, sizeof(buf), "%s of %s", spob->name, god->name);
787  buf[0] = toupper(buf[0]);
788  for (tmp2 = tmp; tmp2; tmp2 = tmp2->more) {
789  if (tmp2->name != NULL)
790  free_string(tmp2->name);
791  tmp2->name = add_string(buf);
792  }
793  tmp->attacktype |= god->attacktype;
794  memcpy(tmp->resist, god->resist, sizeof(tmp->resist));
795  if (tmp->race != NULL)
796  FREE_AND_CLEAR_STR(tmp->race);
797  if (god->race != NULL)
798  tmp->race = add_string(god->race);
799  if (tmp->slaying != NULL)
801  if (god->slaying != NULL)
802  tmp->slaying = add_string(god->slaying);
803  /* safety, we must allow a god's servants some reasonable attack */
804  if (!(tmp->attacktype&AT_PHYSICAL))
805  tmp->attacktype |= AT_PHYSICAL;
806  }
807 
808  object_insert_in_map_at(tmp, tmp->map, op, 0, tmp->x, tmp->y);
809  return 1;
810 }
811 
812 /***************************************************************************
813  *
814  * Summon monster/pet/other object code
815  *
816  ***************************************************************************/
817 
832 static object *choose_cult_monster(object *pl, const object *god, int summon_level) {
833  char buf[MAX_BUF];
834  const char *race;
835  int racenr, i;
836  object *otmp;
837 
838  /* Determine the number of races available */
839  racenr = 0;
840  safe_strncpy(buf, god->race, sizeof(buf));
841  race = strtok(buf, ",");
842  while (race) {
843  racenr++;
844  race = strtok(NULL, ",");
845  }
846 
847  /* next, randomly select a race from the aligned_races string */
848  if (racenr > 1) {
849  racenr = rndm(0, racenr-1);
850  safe_strncpy(buf, god->race, sizeof(buf));
851  race = strtok(buf, ",");
852  for (i = 0; i < racenr; i++)
853  race = strtok(NULL, ",");
854  } else
855  race = god->race;
856 
857  otmp = races_get_random_monster(race, summon_level);
858  if (!otmp) {
861  "The spell fails! %s's creatures are beyond the range of your summons",
862  god->name);
863  }
864  return otmp;
865 }
866 
885 int pets_summon_object(object *op, object *caster, object *spell_ob, int dir, const char *stringarg) {
886  int16_t x, y, nrof = 1, i;
887  archetype *summon_arch;
888  int ndir, mult;
889 
890  if (spell_ob->other_arch != NULL) {
891  summon_arch = spell_ob->other_arch;
892  } else if (spell_ob->randomitems != NULL) {
893  int level = caster_level(caster, spell_ob);
894  treasure *tr, *lasttr = NULL;
895 
896  /* In old code, this was a very convuluted for statement,
897  * with all the checks in the 'for' portion itself. Much
898  * more readable to break some of the conditions out.
899  */
900  for (tr = spell_ob->randomitems->items; tr; tr = tr->next) {
901  if (level < tr->magic)
902  break;
903  lasttr = tr;
904  if (stringarg != NULL && !strcmp(tr->item->name, stringarg))
905  break;
906  if (tr->next == NULL || tr->next->item == NULL)
907  break;
908  }
909  if (lasttr == NULL) {
910  LOG(llevError, "Treasurelist %s did not generate a valid entry in pets_summon_object\n", spell_ob->randomitems->name);
911  draw_ext_info(NDI_UNIQUE, 0, op,
913  "The spell fails to summon any monsters.");
914  return 0;
915  }
916  summon_arch = lasttr->item;
917  nrof = lasttr->nrof;
918  } else if (spell_ob->race != NULL && !strcmp(spell_ob->race, "GODCULTMON")) {
919  const object *god = find_god(determine_god(op));
920  object *mon, *owner;
921  int summon_level, tries;
922 
923  if (god == NULL) {
924  owner = object_get_owner(op);
925  if (owner != NULL) {
926  god = find_god(determine_god(owner));
927  }
928  }
929  /* If we can't find a god, can't get what monster to summon */
930  if (god == NULL)
931  return 0;
932 
933  if (god->race == NULL) {
936  "%s has no creatures that you may summon!",
937  god->name);
938  return 0;
939  }
940  /* the summon level */
941  summon_level = caster_level(caster, spell_ob);
942  if (summon_level == 0)
943  summon_level = 1;
944  tries = 0;
945  do {
946  mon = choose_cult_monster(op, god, summon_level);
947  if (mon == NULL) {
950  "%s fails to send anything.",
951  god->name);
952  return 0;
953  }
954  ndir = dir;
955  if (!ndir)
956  ndir = object_find_free_spot(mon, op->map, op->x, op->y, 1, SIZEOFFREE);
957  if (ndir == -1
958  || ob_blocked(mon, op->map, op->x+freearr_x[ndir], op->y+freearr_y[ndir])) {
959  ndir = -1;
960  if (++tries == 5) {
961  draw_ext_info(NDI_UNIQUE, 0, op,
963  "There is something in the way.");
964  return 0;
965  }
966  }
967  } while (ndir == -1);
968  if (mon->level > summon_level/2)
969  nrof = random_roll(1, 2, op, PREFER_HIGH);
970  else
971  nrof = die_roll(2, 2, op, PREFER_HIGH);
972  summon_arch = mon->arch;
973  } else {
974  summon_arch = NULL;
975  }
976 
977  if (spell_ob->stats.dam)
978  nrof += spell_ob->stats.dam+SP_level_dam_adjust(caster, spell_ob);
979 
980  if (summon_arch == NULL) {
982  "There is no monsters available for summoning.");
983  return 0;
984  }
985 
986  if (dir) {
987  /* Only fail if caster specified a blocked direction. */
988  x = freearr_x[dir];
989  y = freearr_y[dir];
990  if (ob_blocked(&summon_arch->clone, op->map, op->x+x, op->y+y)) {
992  "There is something in the way.");
993  return 0;
994  }
995  }
996 
997  mult = (RANDOM()%2 ? -1 : 1);
998 
999  for (i = 1; i <= nrof; i++) {
1000  archetype *atmp;
1001  object *prev = NULL, *head = NULL, *tmp;
1002 
1003  if (dir) {
1004  ndir = absdir(dir+(i/2)*mult);
1005  mult = -mult;
1006  } else
1007  ndir = object_find_free_spot(&summon_arch->clone, op->map, op->x, op->y, 1, SIZEOFFREE);
1008 
1009  x = ndir > 0 ? freearr_x[ndir] : 0;
1010  y = ndir > 0 ? freearr_y[ndir] : 0;
1011  if (ndir == -1 || ob_blocked(&summon_arch->clone, op->map, op->x+x, op->y+y))
1012  continue;
1013 
1014  for (atmp = summon_arch; atmp != NULL; atmp = atmp->more) {
1015  tmp = arch_to_object(atmp);
1016  if (atmp == summon_arch) {
1017  if (QUERY_FLAG(tmp, FLAG_MONSTER)) {
1018  object_set_owner(tmp, op);
1019  set_spell_skill(op, caster, spell_ob, tmp);
1020  object_set_enemy(tmp, op->enemy);
1021  tmp->type = 0;
1022  CLEAR_FLAG(tmp, FLAG_SLEEP);
1023  if (op->type == PLAYER || QUERY_FLAG(op, FLAG_FRIENDLY)) {
1024  /* If this is not set, we make it friendly */
1025  if (!QUERY_FLAG(spell_ob, FLAG_MONSTER)) {
1026  SET_FLAG(tmp, FLAG_FRIENDLY);
1027  add_friendly_object(tmp);
1028  tmp->stats.exp = 0;
1029  if (spell_ob->attack_movement)
1030  tmp->attack_movement = spell_ob->attack_movement;
1031  if (object_get_owner(op) != NULL)
1033  }
1034  }
1035  }
1036  if (tmp->speed > MIN_ACTIVE_SPEED)
1037  tmp->speed_left = -1;
1038  }
1039  if (head == NULL)
1040  head = tmp;
1041  else {
1042  tmp->head = head;
1043  prev->more = tmp;
1044  }
1045  prev = tmp;
1046  }
1047  head->direction = freedir[ndir];
1048  head->stats.exp = 0;
1049  head = object_insert_in_map_at(head, op->map, op, 0, op->x+x, op->y+y);
1050  if (head != NULL && head->randomitems) {
1051  create_treasure(head->randomitems, head, GT_STARTEQUIP, 6, 0);
1052  if (QUERY_FLAG(head, FLAG_MONSTER)) {
1054  }
1055  }
1056  if (head != NULL) {
1058  }
1059  } /* for i < nrof */
1060  return 1;
1061 }
1062 
1072 static object *get_real_owner(object *ob) {
1073  object *realowner = ob;
1074 
1075  if (realowner == NULL)
1076  return NULL;
1077 
1078  while (object_get_owner(realowner) != NULL) {
1079  realowner = object_get_owner(realowner);
1080  }
1081  return realowner;
1082 }
1083 
1099 int pets_should_arena_attack(object *pet, object *owner, object *target) {
1100  object *rowner, *towner;
1101 
1102  /* exit if the target, pet, or owner is null. */
1103  if (target == NULL || pet == NULL || owner == NULL)
1104  return 0;
1105 
1106  /* get the owners of itself and the target, this is to deal with pets of
1107  pets */
1108  rowner = get_real_owner(owner);
1109  if (target->type != PLAYER) {
1110  towner = get_real_owner(target);
1111  } else {
1112  towner = NULL;
1113  }
1114 
1115  /* if the pet has no owner, exit with error */
1116  if (rowner == NULL) {
1117  LOG(llevError, "Pet has no owner.\n");
1118  return 0;
1119  }
1120 
1121  /* if the target is not a player, and has no owner, we shouldn't be here
1122  */
1123  if (towner == NULL && target->type != PLAYER) {
1124  LOG(llevError, "Target is not a player but has no owner. We should not be here.\n");
1125  return 0;
1126  }
1127 
1128  /* make sure that the owner is a player */
1129  if (rowner->type != PLAYER)
1130  return 0;
1131 
1132  /* abort if the petmode is not arena */
1133  if (rowner->contr->petmode != pet_arena)
1134  return 0;
1135 
1136  /* abort if the pet, it's owner, or the target is not on battleground*/
1137  if (!(op_on_battleground(pet, NULL, NULL, NULL)
1138  && op_on_battleground(owner, NULL, NULL, NULL)
1139  && op_on_battleground(target, NULL, NULL, NULL)))
1140  return 0;
1141 
1142  /* if the target is a monster, make sure it's owner is not the same */
1143  if (target->type != PLAYER && rowner == towner)
1144  return 0;
1145 
1146  /* check if the target is a player which affects how it will handle
1147  parties */
1148  if (target->type != PLAYER) {
1149  /* if the target is owned by a player make sure than make sure
1150  it's not in the same party */
1151  if (towner->type == PLAYER && rowner->contr->party != NULL) {
1152  if (rowner->contr->party == towner->contr->party)
1153  return 0;
1154  }
1155  } else {
1156  /* if the target is a player make sure than make sure it's not
1157  in the same party */
1158  if (rowner->contr->party != NULL) {
1159  if (rowner->contr->party == target->contr->party)
1160  return 0;
1161  }
1162  }
1163 
1164  return 1;
1165 }
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:789
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:832
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
object::owner
object * owner
Pointer to the object which controls this one.
Definition: object.h:387
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:242
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:643
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:2701
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:4259
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:3699
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:900
MSG_TYPE_SPELL_PET
#define MSG_TYPE_SPELL_PET
Pet related messages.
Definition: newclient.h:636
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:664
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:825
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:417
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:424
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:183
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:1545
object_update
void object_update(object *op, int action)
object_update() updates the array which represents the map.
Definition: object.cpp:1419
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:1099
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:532
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:262
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:2352
MSG_TYPE_SPELL
#define MSG_TYPE_SPELL
Spell related info.
Definition: newclient.h:415
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:424
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:489
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:2085
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:2012
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:3627
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:2878
NDI_UNIQUE
#define NDI_UNIQUE
Print immediately, don't buffer.
Definition: newclient.h:266
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:885
MSG_TYPE_SPELL_FAILURE
#define MSG_TYPE_SPELL_FAILURE
Spell failure messages.
Definition: newclient.h:637
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:1072
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:3544
pets_follow_owner
void pets_follow_owner(object *ob, object *owner)
A pet is trying to follow its owner.
Definition: pets.cpp:297
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:80
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:2629
pet_arena
@ pet_arena
Attack other players in arena.
Definition: player.h:61
CLEAR_FLAG
#define CLEAR_FLAG(xyz, p)
Definition: define.h:225
pets_terminate
void pets_terminate(object *pet)
Removes a pet, taking care of clearning the owner's fields if needed.
Definition: pets.cpp:224
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:2523
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:1818
pets_move
void pets_move(object *ob)
Handles a pet's movement.
Definition: pets.cpp:330
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:287
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:447
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