Atrinik Server  4.0
monster.c
Go to the documentation of this file.
1 /*************************************************************************
2  * Atrinik, a Multiplayer Online Role Playing Game *
3  * *
4  * Copyright (C) 2009-2014 Alex Tokar and Atrinik Development Team *
5  * *
6  * Fork from Crossfire (Multiplayer game for X-windows). *
7  * *
8  * This program is free software; you can redistribute it and/or modify *
9  * it under the terms of the GNU General Public License as published by *
10  * the Free Software Foundation; either version 2 of the License, or *
11  * (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this program; if not, write to the Free Software *
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
21  * *
22  * The author can be reached at admin@atrinik.org *
23  ************************************************************************/
24 
32 #include <global.h>
33 #include <toolkit/packet.h>
34 #include <toolkit/string.h>
35 #include <monster_data.h>
36 #include <faction.h>
37 #include <plugin.h>
38 #include <monster_guard.h>
39 #include <arch.h>
40 #include <player.h>
41 #include <object.h>
42 #include <player.h>
43 #include <object_methods.h>
44 #include <waypoint.h>
45 
46 static int can_detect_enemy(object *op, object *enemy, rv_vector *rv);
47 static object *find_nearest_enemy(object *ob);
48 static int move_randomly(object *op);
49 static int can_hit(object *ob1, rv_vector *rv);
50 static object *monster_choose_random_spell(object *monster, uint32_t flags);
51 static int monster_cast_spell(object *head, object *part, int dir, rv_vector *rv, uint32_t flags);
52 static int monster_use_bow(object *head, object *part, int dir);
53 static int dist_att(int dir, object *part, rv_vector *rv);
54 static int run_att(int dir, object *ob, object *part, rv_vector *rv);
55 static int hitrun_att(int dir, object *ob);
56 static int wait_att(int dir, object *ob, object *part, rv_vector *rv);
57 static int disthit_att(int dir, object *ob, object *part, rv_vector *rv);
58 static int wait_att2(int dir, rv_vector *rv);
59 static void circ1_move(object *ob);
60 static void circ2_move(object *ob);
61 static void pace_movev(object *ob);
62 static void pace_moveh(object *ob);
63 static void pace2_movev(object *ob);
64 static void pace2_moveh(object *ob);
65 static void rand_move(object *ob);
66 
85 void set_npc_enemy(object *npc, object *enemy, rv_vector *rv)
86 {
87  object *aggro_wp;
88  rv_vector rv2;
89 
90  /* Do nothing if new enemy == old enemy */
91  if (enemy == npc->enemy && (enemy == NULL || enemy->count == npc->enemy_count)) {
92  return;
93  }
94 
95  /* Players don't need waypoints, speed updates or aggro counters */
96  if (npc->type == PLAYER) {
97  npc->enemy = enemy;
98 
99  if (enemy) {
100  npc->enemy_count = enemy->count;
101  }
102 
103  return;
104  }
105 
106  /* Non-aggro-waypoint related stuff */
107  if (enemy) {
108  if (rv == NULL) {
109  rv = &rv2;
110  }
111 
112  get_rangevector(npc, enemy, rv, RV_DIAGONAL_DISTANCE);
113  npc->enemy_count = enemy->count;
114 
115  /* important: that's our "we lose aggro count" - reset to zero here */
116  npc->last_eat = 0;
117 
118  /* Monster has changed status from normal to attack - let's hear it! */
119  if (npc->enemy == NULL && !QUERY_FLAG(npc, FLAG_FRIENDLY)) {
120  play_sound_map(npc->map, CMD_SOUND_EFFECT, "growl.ogg", npc->x, npc->y, 0, 0);
121  }
122 
123  if (QUERY_FLAG(npc, FLAG_UNAGGRESSIVE)) {
124  /* The unaggressives look after themselves 8) */
126  }
127  } else {
128  object *base = living_get_base_info(npc);
129  object *wp = waypoint_get_active(npc);
130 
131  if (base && !wp) {
132  object *return_wp = waypoint_get_home(npc);
133 
134 #ifdef DEBUG_PATHFINDING
135  LOG(DEBUG, "%s lost aggro and is returning home (%s:%d,%d)", STRING_OBJ_NAME(npc), base->slaying, base->x, base->y);
136 #endif
137 
138  if (!return_wp) {
139  return_wp = arch_to_object(arches[ARCH_WAYPOINT]);
140  object_insert_into(return_wp, npc, 0);
141  return_wp->owner = npc;
142  return_wp->ownercount = npc->count;
143  FREE_AND_ADD_REF_HASH(return_wp->name, shstr_cons.home);
144  /* mark as return-home wp */
145  SET_FLAG(return_wp, FLAG_REFLECTING);
146  /* mark as best-effort wp */
147  SET_FLAG(return_wp, FLAG_NO_ATTACK);
148  }
149 
150  return_wp->stats.hp = base->x;
151  return_wp->stats.sp = base->y;
152  FREE_AND_ADD_REF_HASH(return_wp->slaying, base->slaying);
153  /* Activate wp */
154  SET_FLAG(return_wp, FLAG_CURSED);
155  /* reset best-effort timer */
156  return_wp->stats.Int = 0;
157 
158  /* setup move_type to use waypoints */
159  return_wp->move_type = npc->move_type;
160  npc->move_type = (npc->move_type & LO4) | WPOINT;
161 
162  wp = return_wp;
163  }
164 
165  /* TODO: add a little pause to the active waypoint */
166  }
167 
168  npc->enemy = enemy;
169  /* Update speed */
170  set_mobile_speed(npc, 0);
171 
172  /* TODO: check intelligence against lower limit to allow pathfind */
173  aggro_wp = waypoint_get_aggro(npc);
174 
175  /* Create a new aggro wp for npc? */
176  if (!aggro_wp && enemy) {
177  aggro_wp = arch_to_object(arches[ARCH_WAYPOINT]);
178  object_insert_into(aggro_wp, npc, 0);
179  /* Mark as aggro WP */
180  SET_FLAG(aggro_wp, FLAG_DAMNED);
181  aggro_wp->owner = npc;
182 #ifdef DEBUG_PATHFINDING
183  LOG(DEBUG, "created wp for '%s'", STRING_OBJ_NAME(npc));
184 #endif
185  }
186 
187  /* Set up waypoint target (if we actually got a waypoint) */
188  if (aggro_wp) {
189  if (enemy) {
190  aggro_wp->enemy_count = npc->enemy_count;
191  aggro_wp->enemy = enemy;
192  FREE_AND_ADD_REF_HASH(aggro_wp->name, enemy->name);
193 #ifdef DEBUG_PATHFINDING
194  LOG(DEBUG, "got wp for '%s' -> '%s'", npc->name, enemy->name);
195 #endif
196  } else {
197  aggro_wp->enemy = NULL;
198 #ifdef DEBUG_PATHFINDING
199  LOG(DEBUG, "cleared aggro wp for '%s'", npc->name);
200 #endif
201  }
202  }
203 
204  if (enemy != NULL) {
205  monster_enemy_signal(npc, enemy);
208  } else {
209  object_set_value(npc, "was_provoked", NULL, 0);
210  }
211 }
212 
224 static void monster_enemy_signal_map(object *npc, mapstruct *map,
225  object *spawn_point, uint32_t dist)
226 {
227  objectlink *ol;
228 
229  for (ol = map->linked_spawn_points; ol != NULL; ol = ol->next) {
230  if (ol->objlink.ob == spawn_point) {
231  continue;
232  }
233 
234  /* Ensure the spawn point has a spawned monster. */
235  if (!OBJECT_VALID(ol->objlink.ob->enemy, ol->objlink.ob->enemy_count)) {
236  continue;
237  }
238 
239  /* Ensure the spawned monster doesn't yet have an enemy. */
240  if (OBJECT_VALID(ol->objlink.ob->enemy->enemy,
241  ol->objlink.ob->enemy->enemy_count)) {
242  continue;
243  }
244 
245  rv_vector rv;
246 
247  if ((spawn_point->title == NULL ||
248  ol->objlink.ob->title != spawn_point->title) &&
249  (!get_rangevector(npc, ol->objlink.ob->enemy, &rv,
250  RV_DIAGONAL_DISTANCE) || rv.distance > dist ||
251  !monster_is_ally_of(npc, ol->objlink.ob->enemy))) {
252  continue;
253  }
254 
255  if (object_get_value(npc, "was_provoked") != NULL) {
256  object_set_value(ol->objlink.ob->enemy, "was_provoked", "1", 1);
257  }
258 
259  set_npc_enemy(ol->objlink.ob->enemy, npc->enemy, NULL);
260  }
261 }
262 
270 void monster_enemy_signal(object *npc, object *enemy)
271 {
272  object *spawn_point_info;
273 
274  HARD_ASSERT(npc != NULL);
275  HARD_ASSERT(enemy != NULL);
276 
277  SOFT_ASSERT(npc->map != NULL, "NPC has no map: %s", object_get_str(npc));
278  SOFT_ASSERT(enemy->map != NULL, "Enemy has no map: %s",
279  object_get_str(enemy));
280 
281  if (monster_signal_chance[npc->stats.Int] == 0 ||
282  !rndm_chance(monster_signal_chance[npc->stats.Int])) {
283  return;
284  }
285 
286  spawn_point_info = object_find_type(npc, SPAWN_POINT_INFO);
287 
288  if (spawn_point_info == NULL || !OBJECT_VALID(spawn_point_info->owner,
289  spawn_point_info->ownercount)) {
290  return;
291  }
292 
293  int32_t dist = 0;
294  rv_vector rv;
295 
296  if (get_rangevector(npc, enemy, &rv, 0)) {
297  dist = (int32_t) ((double) npc->item_power * 1.5) - rv.distance;
298 
299  if (dist < 0) {
300  dist = 0;
301  }
302  }
303 
304  /* Signal the map the spawn point is on. */
305  monster_enemy_signal_map(npc, npc->map, spawn_point_info->owner, dist);
306 
307  /* Signal all the tiled maps that are in memory. */
308  for (size_t i = 0; i < TILED_NUM_DIR; i++) {
309  if (npc->map->tile_map[i] != NULL &&
310  npc->map->tile_map[i]->in_memory == MAP_IN_MEMORY) {
311  monster_enemy_signal_map(npc, npc->map->tile_map[i],
312  spawn_point_info->owner, dist);
313  }
314  }
315 }
316 
326 object *check_enemy(object *npc, rv_vector *rv)
327 {
328  if (npc->enemy == NULL) {
329  return NULL;
330  }
331 
332  if (!OBJECT_VALID(npc->enemy, npc->enemy_count) || npc == npc->enemy || !IS_LIVE(npc->enemy) || is_friend_of(npc, npc->enemy)) {
333  set_npc_enemy(npc, NULL, NULL);
334  return NULL;
335  }
336 
337  return can_detect_enemy(npc, npc->enemy, rv) ? npc->enemy : NULL;
338 }
339 
350 object *find_enemy(object *npc, rv_vector *rv)
351 {
352  object *tmp = NULL;
353 
354  /* If we are berserk, we don't care about others - we attack all we can
355  * find. */
356  if (QUERY_FLAG(npc, FLAG_BERSERK)) {
357  /* Always clear the attacker entry */
358  npc->attacked_by = NULL;
359  tmp = find_nearest_enemy(npc);
360 
361  if (tmp) {
362  get_rangevector(npc, tmp, rv, 0);
363  }
364 
365  return tmp;
366  }
367 
368  tmp = check_enemy(npc, rv);
369 
370  if (!tmp) {
371  /* If we have an attacker, check him */
373  /* We don't want a fight evil vs evil or good against non evil. */
374  if (is_friend_of(npc, npc->attacked_by)) {
375  /* Skip it, but let's wake up */
376  CLEAR_FLAG(npc, FLAG_SLEEP);
377  } else if (on_same_map(npc, npc->attacked_by)) {
378  /* The only thing we must know... */
379 
380  CLEAR_FLAG(npc, FLAG_SLEEP);
381  set_npc_enemy(npc, npc->attacked_by, rv);
382  /* Always clear the attacker entry */
383  npc->attacked_by = NULL;
384 
385  /* Face our attacker */
386  return npc->enemy;
387  }
388  }
389 
390  /* We have no legal enemy or attacker, so we try to target a new
391  * one. */
392  if (!QUERY_FLAG(npc, FLAG_UNAGGRESSIVE)) {
393  tmp = find_nearest_enemy(npc);
394 
395  if (tmp != npc->enemy) {
396  set_npc_enemy(npc, tmp, rv);
397  }
398  } else if (npc->enemy) {
399  /* Make sure to clear the enemy, even if FLAG_UNAGRESSIVE is true */
400  set_npc_enemy(npc, NULL, NULL);
401  }
402  }
403 
404  if (tmp != NULL) {
405  monster_enemy_signal(npc, tmp);
406  }
407 
408  return tmp;
409 }
410 
424 static int can_detect_enemy(object *op, object *enemy, rv_vector *rv)
425 {
426  /* Will check for legal maps too */
427  if (!op || !enemy || !on_same_map(op, enemy)) {
428  return 0;
429  }
430 
431  /* We check for sys_invisible and normal */
432  if (IS_INVISIBLE(enemy, op) || QUERY_FLAG(enemy, FLAG_INVULNERABLE)) {
433  return 0;
434  }
435 
436  if (!get_rangevector(op, enemy, rv, 0)) {
437  return 0;
438  }
439 
440  /* If our enemy is too far away ... */
441  if ((int) rv->distance >= MAX(MAX_AGGRO_RANGE, op->item_power)) {
442  /* Then start counting until our mob loses aggro... */
443  if (++op->last_eat > MAX_AGGRO_TIME) {
444  set_npc_enemy(op, NULL, NULL);
445  return 0;
446  }
447  } else {
448  /* Our mob is aggroed again - because target is in range again */
449  op->last_eat = 0;
450  }
451 
452  return 1;
453 }
454 
465 static bool monster_can_move(object *op)
466 {
467  if (monster_data_dialogs_num(op) != 0) {
468  return false;
469  }
470 
471  return true;
472 }
473 
475 static void process_func(object *op)
476 {
477  HARD_ASSERT(op != NULL);
478 
479  SOFT_ASSERT(op->head == NULL, "Called on a tail part: %s",
480  object_get_str(op));
481 
482  /* Monsters not on maps don't do anything. */
483  if (op->map == NULL) {
484  return;
485  }
486 
487  /* If we are here, we're never paralyzed anymore */
489 
490  /* Cleanup stale interfaces. */
492 
493  /* Here is the heart of the mob attack and target area.
494  * find_enemy() checks the old enemy or gets us a new one. */
495 
496  object *enemy;
497  rv_vector rv;
498  /* We never ever attack */
499  if (QUERY_FLAG(op, FLAG_NO_ATTACK)) {
500  if (op->enemy != NULL) {
501  set_npc_enemy(op, NULL, NULL);
502  }
503 
504  enemy = NULL;
505  } else if ((enemy = find_enemy(op, &rv)) != NULL) {
506  CLEAR_FLAG(op, FLAG_SLEEP);
507  op->direction = rv.direction;
508 
509  if (rv.distance <= 1 && rv.distance_z == 0) {
510  op->anim_flags |= ANIM_FLAG_ATTACKING;
511  }
512 
513  if (!enemy->attacked_by || (enemy->attacked_by && enemy->attacked_by_distance > (int) rv.distance)) {
514  /* We have an enemy, just tell him we want him dead */
515  enemy->attacked_by = op;
516  enemy->attacked_by_count = op->count;
517  /* Now the attacked foe knows how near we are */
518  enemy->attacked_by_distance = (int16_t) rv.distance;
519  }
520  }
521 
522  /* Generate hp, if applicable */
523  if (op->stats.Con && op->stats.hp < op->stats.maxhp) {
524  if (++op->last_heal > 5) {
525  op->last_heal = 0;
526  op->stats.hp += op->stats.Con;
527 
528  if (op->stats.hp > op->stats.maxhp) {
529  op->stats.hp = op->stats.maxhp;
530  }
531  }
532 
533  /* So if the monster has gained enough HP that they are no longer afraid
534  * */
535  if (QUERY_FLAG(op, FLAG_RUN_AWAY) && op->stats.hp >=
536  (int32_t) (((double) op->run_away / 100.0) *
537  (double) op->stats.maxhp)) {
539  }
540  }
541 
542  /* Generate sp, if applicable */
543  if (op->stats.Pow && op->stats.sp < op->stats.maxsp) {
544  op->last_sp += (int16_t) (8.0 * (double) op->stats.Pow /
545  FABS(op->speed));
546  /* causes Pow/16 sp/tick */
547  op->stats.sp += op->last_sp / 128;
548  op->last_sp %= 128;
549 
550  if (op->stats.sp > op->stats.maxsp) {
551  op->stats.sp = op->stats.maxsp;
552  }
553  }
554 
555  /* Time to regain some "guts"... */
556  if (QUERY_FLAG(op, FLAG_SCARED) && rndm_chance(20)) {
557  CLEAR_FLAG(op, FLAG_SCARED);
558  }
559 
560  if (op->behavior & BEHAVIOR_SPELL_FRIENDLY) {
561  if (op->last_grace) {
562  op->last_grace--;
563  }
564 
565  if (op->stats.Dex && rndm_chance(op->stats.Dex)) {
566  if (QUERY_FLAG(op, FLAG_CAST_SPELL) && !op->last_grace) {
567  if (monster_cast_spell(op, op, 0, NULL, SPELL_DESC_FRIENDLY)) {
568  /* Add monster casting delay */
569  op->last_grace += op->magic;
570  }
571  }
572  }
573  }
574 
575  /* If we don't have an enemy, do special movement or the like */
576  if (enemy == NULL) {
577  object *spawn_point_info;
578 
579  if (QUERY_FLAG(op, FLAG_ONLY_ATTACK) || ((spawn_point_info = object_find_type(op, SPAWN_POINT_INFO)) && spawn_point_info->owner && !OBJECT_VALID(spawn_point_info->owner, spawn_point_info->ownercount))) {
581  object_remove(op, 0);
582  object_destroy(op);
583  return;
584  }
585 
586  if (!QUERY_FLAG(op, FLAG_STAND_STILL)) {
587  if (op->move_type & HI4) {
588  if (!monster_can_move(op)) {
589  return;
590  }
591 
592  switch (op->move_type & HI4) {
593  case CIRCLE1:
594  circ1_move(op);
595  break;
596 
597  case CIRCLE2:
598  circ2_move(op);
599  break;
600 
601  case PACEV:
602  pace_movev(op);
603  break;
604 
605  case PACEH:
606  pace_moveh(op);
607  break;
608 
609  case PACEV2:
610  pace2_movev(op);
611  break;
612 
613  case PACEH2:
614  pace2_moveh(op);
615  break;
616 
617  case RANDO:
618  rand_move(op);
619  break;
620 
621  case RANDO2:
622  move_randomly(op);
623  break;
624 
625  case WPOINT: {
626  object *wp = waypoint_get_active(op);
627  if (wp != NULL) {
628  waypoint_move(wp, op);
629  }
630  break;
631  }
632  }
633 
634  return;
635  } else if (QUERY_FLAG(op, FLAG_RANDOM_MOVE)) {
636  if (monster_can_move(op)) {
637  move_randomly(op);
638  }
639  }
640  }
641 
642  return;
643  }
644 
645  object *part = rv.part != NULL ? rv.part : op;
646  int dir = rv.direction;
647 
648  /* Move the check for scared up here - if the monster was scared,
649  * we were not doing any of the logic below, so might as well save
650  * a few CPU cycles. */
651  if (!QUERY_FLAG(op, FLAG_SCARED)) {
652  if (op->last_grace) {
653  op->last_grace--;
654  }
655 
656  if (op->stats.Dex && rndm_chance(op->stats.Dex)) {
657  if (QUERY_FLAG(op, FLAG_CAST_SPELL) && !op->last_grace) {
659  /* Add monster casting delay */
660  op->last_grace += op->magic;
661  return;
662  }
663  }
664 
665  if (QUERY_FLAG(op, FLAG_READY_BOW) && rndm_chance(4)) {
666  if (monster_use_bow(op, part, dir) && rndm_chance(2)) {
667  return;
668  }
669  }
670  }
671  }
672 
673  if (QUERY_FLAG(op, FLAG_SCARED) || QUERY_FLAG(op, FLAG_RUN_AWAY)) {
674  dir = absdir(dir + 4);
675  }
676 
677  if (QUERY_FLAG(op, FLAG_CONFUSED)) {
678  dir = get_randomized_dir(dir);
679  }
680 
681  int special_dir = 0;
682  if (!QUERY_FLAG(op, FLAG_SCARED)) {
683  if (op->attack_move_type & LO4) {
684  switch (op->attack_move_type & LO4) {
685  case DISTATT:
686  special_dir = dist_att(dir, part, &rv);
687  break;
688 
689  case RUNATT:
690  special_dir = run_att(dir, op, part, &rv);
691  break;
692 
693  case HITRUN:
694  special_dir = hitrun_att(dir, op);
695  break;
696 
697  case WAITATT:
698  special_dir = wait_att(dir, op, part, &rv);
699  break;
700 
701  case RUSH:
702  case ALLRUN:
703  special_dir = dir;
704  break;
705 
706  case DISTHIT:
707  special_dir = disthit_att(dir, op, part, &rv);
708  break;
709 
710  case WAIT2:
711  special_dir = wait_att2(dir, &rv);
712  break;
713 
714  default:
715  LOG(DEBUG, "Illegal low mon-move: %d", op->attack_move_type & LO4);
716  }
717 
718  if (special_dir == 0) {
719  return;
720  }
721  }
722  }
723 
724  /* Try to move closer to enemy, or follow whatever special attack behavior
725  * is */
726  if (!QUERY_FLAG(op, FLAG_STAND_STILL) && (QUERY_FLAG(op, FLAG_SCARED) || QUERY_FLAG(op, FLAG_RUN_AWAY) || !can_hit(part, &rv) || ((op->attack_move_type & LO4) && special_dir != dir))) {
727  object *aggro_wp = waypoint_get_aggro(op);
728 
729  /* TODO: make (intelligent) monsters go to last known position of enemy
730  * if out of range/sight */
731 
732  /* If special attack move -> follow it instead of going towards enemy */
733  if (((op->attack_move_type & LO4) && special_dir != dir)) {
734  aggro_wp = NULL;
735  dir = special_dir;
736  }
737 
738  /* If valid aggro wp (and no special attack), and not scared, use it for
739  * movement */
740  if (aggro_wp && aggro_wp->enemy && aggro_wp->enemy == op->enemy && (rv.distance_z != 0 || rv.distance > 1) && !QUERY_FLAG(op, FLAG_SCARED) && !QUERY_FLAG(op, FLAG_RUN_AWAY)) {
741  waypoint_move(aggro_wp, op);
742  return;
743  } else {
744  int maxdiff = (QUERY_FLAG(op, FLAG_ONLY_ATTACK) || rndm_chance(2)) ? 1 : 2;
745 
746  /* Can the monster move directly toward player? */
747  if (move_object(op, dir)) {
748  return;
749  }
750 
751  /* Try move around corners if !close */
752  for (int diff = 1; diff <= maxdiff; diff++) {
753  /* try different detours */
754  /* Try left or right first? */
755  int m = 1 - (RANDOM() & 2);
756 
757  if (move_object(op, absdir(dir + diff * m)) ||
758  move_object(op, absdir(dir - diff * m))) {
759  return;
760  }
761  }
762  }
763  }
764 
765  /* Eneq(@csd.uu.se): Patch to make RUN_AWAY or SCARED monsters move a random
766  * direction if they can't move away. */
768  if (move_randomly(op)) {
769  return;
770  }
771  }
772 
773  /* Hit enemy if possible */
774  if (!QUERY_FLAG(op, FLAG_SCARED) && !QUERY_FLAG(enemy, FLAG_REMOVED) && can_hit(part, &rv)) {
775  if (QUERY_FLAG(op, FLAG_RUN_AWAY)) {
776  part->stats.wc -= 10;
777 
778  /* As long we are > 0, we are not ready to swing */
779  if (op->weapon_speed_left <= 0) {
780  skill_attack(enemy, part, 0, NULL);
781  op->weapon_speed_left += FABS((int) op->weapon_speed_left) + 1;
782  }
783 
784  part->stats.wc += 10;
785  } else {
786  /* As long we are > 0, we are not ready to swing */
787  if (op->weapon_speed_left <= 0) {
788  skill_attack(enemy, part, 0, NULL);
789  op->weapon_speed_left += FABS((int) op->weapon_speed_left) + 1;
790  }
791  }
792  }
793 
794  /* Might be freed by ghost-attack or hit-back */
795  if (OBJECT_FREE(part)) {
796  return;
797  }
798 
799  if (QUERY_FLAG(op, FLAG_ONLY_ATTACK)) {
800  object_destruct(op);
801  return;
802  }
803 
804  monster_data_enemy_update(op, enemy);
805 }
806 
811 {
812  OBJECT_METHODS(MONSTER)->process_func = process_func;
813 }
814 
830 static int can_detect_target(object *op, object *target, unsigned int range,
831  unsigned int srange, rv_vector *rv)
832 {
833  /* We check for sys_invisible and normal */
834  if (IS_INVISIBLE(target, op) || QUERY_FLAG(target, FLAG_INVULNERABLE)) {
835  return 0;
836  }
837 
838  if (!get_rangevector(op, target, rv, 0)) {
839  return 0;
840  }
841 
842  if (QUERY_FLAG(target, FLAG_STEALTH) && !QUERY_FLAG(op, FLAG_XRAYS)) {
843  if (srange < rv->distance) {
844  return 0;
845  }
846  } else {
847  if (range < rv->distance) {
848  return 0;
849  }
850  }
851 
852  return 1;
853 }
854 
862 static object *find_nearest_enemy(object *ob)
863 {
864  object *tmp;
865  int aggro_range, aggro_stealth;
866  rv_vector rv;
867  int i, j, xt, yt;
868  mapstruct *m;
869 
870  aggro_range = ob->item_power;
871 
872  if (ob->enemy || ob->attacked_by) {
873  aggro_range += 3;
874  }
875 
876  if (QUERY_FLAG(ob, FLAG_SLEEP) || QUERY_FLAG(ob, FLAG_BLIND)) {
877  aggro_range /= 2;
878  aggro_stealth = aggro_range - 2;
879  } else {
880  aggro_stealth = aggro_range - 2;
881  }
882 
883  if (aggro_stealth < MIN_MON_RADIUS) {
884  aggro_stealth = MIN_MON_RADIUS;
885  }
886 
887  for (i = -aggro_range; i <= aggro_range; i++) {
888  for (j = -aggro_range; j <= aggro_range; j++) {
889  xt = ob->x + i;
890  yt = ob->y + j;
891 
892  if (!(m = get_map_from_coord2(ob->map, &xt, &yt))) {
893  continue;
894  }
895 
896  /* Nothing alive here? Move on... */
897  if (!(GET_MAP_FLAGS(m, xt, yt) & (P_IS_MONSTER | P_IS_PLAYER))) {
898  continue;
899  }
900 
901  for (tmp = GET_MAP_OB(m, xt, yt); tmp; tmp = tmp->above) {
902  /* Get head. */
903  if (tmp->head) {
904  tmp = tmp->head;
905  }
906 
907  /* Skip the monster looking for enemy and not alive objects. */
908  if (tmp == ob || !IS_LIVE(tmp)) {
909  continue;
910  }
911 
912  if (!can_detect_target(ob, tmp, aggro_range, aggro_stealth,
913  &rv)) {
914  continue;
915  }
916 
917  if (!obj_in_line_of_sight(tmp, &rv)) {
918  continue;
919  }
920 
921  /* Now check the friend status, whether we can reach the enemy,
922  * and LOS. */
923  if (!is_friend_of(ob, tmp)) {
924  return tmp;
925  }
926 
927  monster_guard_check(ob, tmp, NULL, rv.distance);
928  }
929  }
930  }
931 
932  return NULL;
933 }
934 
942 static int move_randomly(object *op)
943 {
944  int i, r;
945  int dirs[8] = {1, 2, 3, 4, 5, 6, 7, 8};
946 
947  mapstruct *basemap = NULL;
948  rv_vector rv;
949  if (op->item_race != 0 || op->item_level != 0) {
950  object *base = living_find_base_info(op);
951  if (base != NULL) {
952  basemap = ready_map_name(base->slaying, NULL, MAP_NAME_SHARED);
953  if (basemap != NULL) {
954  if (!get_rangevector_from_mapcoords(basemap, base->x, base->y,
955  op->map, op->x, op->y, &rv, RV_NO_DISTANCE)) {
956  basemap = NULL;
957  }
958  }
959  }
960  }
961 
962  /* Give up to 8 chances for a monster to move randomly */
963  for (i = 0; i < 8; i++) {
964  int t = dirs[i];
965 
966  /* Perform a single random shuffle of the remaining directions */
967  r = i + rndm(0, 8 - i - 1);
968  dirs[i] = dirs[r];
969  dirs[r] = t;
970 
971  r = dirs[i];
972 
973  /* Check x and y direction of possible move against limit parameters */
974  if (basemap != NULL) {
975  if (abs(rv.distance_x + freearr_x[r]) > op->item_race) {
976  continue;
977  }
978 
979  if (abs(rv.distance_y + freearr_y[r]) > op->item_level) {
980  continue;
981  }
982  }
983 
984  if (HAS_EVENT(op, EVENT_AI)) {
985  int ret = trigger_event(EVENT_AI,
986  NULL,
987  op,
988  NULL,
989  NULL,
991  r,
992  0,
993  0);
994  if (ret == 1) {
995  /* Cancel random movement. */
996  return 0;
997  } else if (ret == 2) {
998  /* Keep trying. */
999  continue;
1000  }
1001  }
1002 
1003  if (move_object(op, r)) {
1004  return 1;
1005  }
1006  }
1007 
1008  return 0;
1009 }
1010 
1020 static int can_hit(object *ob1, rv_vector *rv)
1021 {
1022  if (QUERY_FLAG(ob1, FLAG_CONFUSED) && !rndm_chance(3)) {
1023  return 0;
1024  }
1025 
1026  return rv->distance_z == 0 && abs(rv->distance_x) < 2 &&
1027  abs(rv->distance_y) < 2;
1028 }
1029 
1030 #define MAX_KNOWN_SPELLS 20
1031 
1041 static object *monster_choose_random_spell(object *monster, uint32_t flags)
1042 {
1043  object * altern[MAX_KNOWN_SPELLS], *tmp;
1044  spell_struct *spell;
1045  int i = 0, j;
1046 
1047  for (tmp = monster->inv; tmp != NULL; tmp = tmp->below) {
1048  if (tmp->type == ABILITY) {
1049  /* Check and see if it's actually a useful spell */
1050  if ((spell = find_spell(tmp->stats.sp)) != NULL && !(spell->path & (PATH_INFO | PATH_TRANSMUTE | PATH_TRANSFER | PATH_LIGHT)) && spell->flags & flags) {
1051  if (tmp->stats.maxsp) {
1052  for (j = 0; i < MAX_KNOWN_SPELLS && j < tmp->stats.maxsp; j++) {
1053  altern[i++] = tmp;
1054  }
1055  } else {
1056  altern[i++] = tmp;
1057  }
1058 
1059  if (i == MAX_KNOWN_SPELLS) {
1060  break;
1061  }
1062  }
1063 
1064  }
1065  }
1066 
1067  if (!i) {
1068  return NULL;
1069  }
1070 
1071  return altern[rndm(1, i) - 1];
1072 }
1073 
1083 static int monster_spell_useful(object *target, int spell_id)
1084 {
1085  switch (spell_id) {
1086  case SP_MINOR_HEAL:
1087  case SP_GREATER_HEAL:
1088  return target->stats.hp != target->stats.maxhp;
1089  }
1090 
1091  return 1;
1092 }
1093 
1110 static int monster_cast_spell(object *head, object *part, int dir, rv_vector *rv, uint32_t flags)
1111 {
1112  object *spell_item, *target = NULL;
1113  spell_struct *sp;
1114  int sp_typ, ability;
1115 
1116  if ((spell_item = monster_choose_random_spell(head, flags)) == NULL) {
1117  /* Will be turned on when picking up book */
1118  CLEAR_FLAG(head, FLAG_CAST_SPELL);
1119  return 0;
1120  }
1121 
1122  /* Only considering long range spells if we're not looking for friendly
1123  * target. */
1124  if (spell_item->stats.hp != -1 && rv) {
1125  /* Alternate long-range spell: check how far away enemy is */
1126  if (rv->distance > 6) {
1127  sp_typ = spell_item->stats.hp;
1128  } else {
1129  sp_typ = spell_item->stats.sp;
1130  }
1131  } else {
1132  sp_typ = spell_item->stats.sp;
1133 
1134  /* Not looking for friendly target, but this is a friendly spell, and
1135  * it's not the
1136  * same as long range one? */
1137  if (rv && spells[sp_typ].flags & SPELL_DESC_FRIENDLY && sp_typ != spell_item->stats.hp) {
1138  return 0;
1139  }
1140  }
1141 
1142  if (sp_typ == -1 || (sp = find_spell(sp_typ)) == NULL) {
1143  return 0;
1144  }
1145 
1146  /* Monster doesn't have enough spellpoints */
1147  if (head->stats.sp < SP_level_spellpoint_cost(head, sp_typ, -1)) {
1148  return 0;
1149  }
1150 
1151  /* Spell should be cast on caster (ie, heal, strength) */
1152  if (sp->flags & SPELL_DESC_SELF) {
1153  dir = 0;
1154 
1155  if (rv && !monster_spell_useful(head, sp_typ)) {
1156  return 0;
1157  }
1158  }
1159 
1160  if (!rv) {
1161  int i, j, xt, yt;
1162  object *tmp;
1163  mapstruct *m;
1164 
1165  for (i = -sp->range; !target && i <= sp->range; i++) {
1166  for (j = -sp->range; !target && j <= sp->range; j++) {
1167  xt = head->x + i;
1168  yt = head->y + j;
1169 
1170  if (!(m = get_map_from_coord2(head->map, &xt, &yt))) {
1171  continue;
1172  }
1173 
1174  /* Nothing alive here? Move on... */
1175  if (!(GET_MAP_FLAGS(m, xt, yt) & (P_IS_MONSTER | P_IS_PLAYER))) {
1176  continue;
1177  }
1178 
1179  for (tmp = GET_MAP_OB(m, xt, yt); tmp; tmp = tmp->above) {
1180  /* Get head. */
1181  if (tmp->head) {
1182  tmp = tmp->head;
1183  }
1184 
1185  /* Skip the monster and not alive objects. */
1186  if (tmp == head || !IS_LIVE(tmp)) {
1187  continue;
1188  }
1189 
1190  if (is_friend_of(head, tmp) && monster_spell_useful(tmp, sp_typ)) {
1191  target = tmp;
1192  break;
1193  }
1194  }
1195  }
1196  }
1197 
1198  if (!target) {
1199  return 0;
1200  }
1201  }
1202 
1203  ability = (spell_item->type == ABILITY && QUERY_FLAG(spell_item, FLAG_IS_MAGICAL));
1204 
1205  head->stats.sp -= SP_level_spellpoint_cost(head, sp_typ, -1);
1206  /* Add default cast time from spell force to monster */
1207  head->last_grace += spell_item->last_grace;
1208 
1209  /* If we're casting this spell on another object, we need to adjust some
1210  * parameters accordingly... */
1211  if (target) {
1212  return cast_spell(target, part, dir, sp_typ, ability, CAST_NPC, NULL);
1213  }
1214 
1215  /* Otherwise a normal cast. */
1216  return cast_spell(part, part, dir, sp_typ, ability, CAST_NORMAL, NULL);
1217 }
1218 
1230 static int monster_use_bow(object *head, object *part, int dir)
1231 {
1232  FOR_INV_PREPARE(head, tmp) {
1233  if (tmp->type == BOW && QUERY_FLAG(tmp, FLAG_APPLIED)) {
1234  object_ranged_fire(tmp, part, dir, NULL);
1235  return 1;
1236  }
1237  } FOR_INV_FINISH();
1238 
1239  LOG(ERROR, "Monster %s has FLAG_READY_BOW without a bow.",
1240  object_get_str(head));
1241  CLEAR_FLAG(head, FLAG_READY_BOW);
1242  return 0;
1243 }
1244 
1256 static int dist_att(int dir, object *part, rv_vector *rv)
1257 {
1258  if (can_hit(part, rv)) {
1259  return dir;
1260  }
1261 
1262  if (rv->distance < 10) {
1263  return absdir(dir + 4);
1264  } else if (rv->distance > 18) {
1265  return dir;
1266  }
1267 
1268  return 0;
1269 }
1270 
1284 static int run_att(int dir, object *ob, object *part, rv_vector *rv)
1285 {
1286  if ((can_hit(part, rv) && ob->move_status < 20) || ob->move_status < 20) {
1287  ob->move_status++;
1288  return dir;
1289  } else if (ob->move_status > 20) {
1290  ob->move_status = 0;
1291  }
1292 
1293  return absdir(dir + 4);
1294 }
1295 
1305 static int hitrun_att(int dir, object *ob)
1306 {
1307  if (ob->move_status++ < 25) {
1308  return dir;
1309  } else if (ob->move_status < 50) {
1310  return absdir(dir + 4);
1311  } else {
1312  ob->move_status = 0;
1313  }
1314 
1315  return absdir(dir + 4);
1316 }
1317 
1331 static int wait_att(int dir, object *ob, object *part, rv_vector *rv)
1332 {
1333  if (ob->move_status || can_hit(part, rv)) {
1334  ob->move_status++;
1335  }
1336 
1337  if (ob->move_status == 0) {
1338  return 0;
1339  } else if (ob->move_status < 10) {
1340  return dir;
1341  } else if (ob->move_status < 15) {
1342  return absdir(dir + 4);
1343  }
1344 
1345  ob->move_status = 0;
1346  return 0;
1347 }
1348 
1362 static int disthit_att(int dir, object *ob, object *part, rv_vector *rv)
1363 {
1364  if (ob->stats.maxhp && (ob->stats.hp * 100) / ob->stats.maxhp < ob->run_away) {
1365  return absdir(dir + 4);
1366  }
1367 
1368  return dist_att(dir, part, rv);
1369 }
1370 
1380 static int wait_att2(int dir, rv_vector *rv)
1381 {
1382  if (rv->distance < 9) {
1383  return absdir(dir + 4);
1384  }
1385 
1386  return 0;
1387 }
1388 
1394 static void circ1_move(object *ob)
1395 {
1396  static const int circle[12] = {3, 3, 4, 5, 5, 6, 7, 7, 8, 1, 1, 2};
1397 
1398  if (++ob->move_status > 11) {
1399  ob->move_status = 0;
1400  }
1401 
1402  if (!move_object(ob, circle[ob->move_status])) {
1403  move_object(ob, rndm(1, 8));
1404  }
1405 }
1406 
1412 static void circ2_move(object *ob)
1413 {
1414  static const int circle[20] = {3, 3, 3, 4, 4, 5, 5, 5, 6, 6, 7, 7, 7, 8, 8, 1, 1, 1, 2, 2};
1415 
1416  if (++ob->move_status > 19) {
1417  ob->move_status = 0;
1418  }
1419 
1420  if (!move_object(ob, circle[ob->move_status])) {
1421  move_object(ob, rndm(1, 8));
1422  }
1423 }
1424 
1430 static void pace_movev(object *ob)
1431 {
1432  if (ob->move_status++ > 6) {
1433  ob->move_status = 0;
1434  }
1435 
1436  if (ob->move_status < 4) {
1437  move_object(ob, 5);
1438  } else {
1439  move_object(ob, 1);
1440  }
1441 }
1442 
1448 static void pace_moveh(object *ob)
1449 {
1450  if (ob->move_status++ > 6) {
1451  ob->move_status = 0;
1452  }
1453 
1454  if (ob->move_status < 4) {
1455  move_object(ob, 3);
1456  } else {
1457  move_object(ob, 7);
1458  }
1459 }
1460 
1466 static void pace2_movev(object *ob)
1467 {
1468  if (ob->move_status++ > 16) {
1469  ob->move_status = 0;
1470  }
1471 
1472  if (ob->move_status < 6) {
1473  move_object(ob, 5);
1474  } else if (ob->move_status < 8) {
1475  return;
1476  } else if (ob->move_status < 13) {
1477  move_object(ob, 1);
1478  }
1479 }
1480 
1486 static void pace2_moveh(object *ob)
1487 {
1488  if (ob->move_status++ > 16) {
1489  ob->move_status = 0;
1490  }
1491 
1492  if (ob->move_status < 6) {
1493  move_object(ob, 3);
1494  } else if (ob->move_status < 8) {
1495  return;
1496  } else if (ob->move_status < 13) {
1497  move_object(ob, 7);
1498  }
1499 }
1500 
1506 static void rand_move(object *ob)
1507 {
1508  int i;
1509 
1510  if (ob->move_status < 1 || ob->move_status > 8 || !move_object(ob, ob->move_status || rndm_chance(9))) {
1511  for (i = 0; i < 5; i++) {
1512  if (move_object(ob, ob->move_status = rndm(1, 8))) {
1513  return;
1514  }
1515  }
1516  }
1517 }
1518 
1530 static char *find_matching_message(const char *msg, const char *match)
1531 {
1532  const char *cp = msg, *cp1, *cp2;
1533  char regex[MAX_BUF], *cp3;
1534  int gotmatch = 0;
1535 
1536  while (1) {
1537  if (strncmp(cp, "@match ", 7)) {
1538  LOG(DEBUG, "Invalid message: %s", msg);
1539  return NULL;
1540  } else {
1541  /* Find the end of the line, and copy the regex portion into it */
1542  cp2 = strchr(cp + 7, '\n');
1543 
1544  if (!cp2) {
1545  LOG(DEBUG, "Found empty match response: %s", msg);
1546  return NULL;
1547  }
1548 
1549  strncpy(regex, cp + 7, (cp2 - cp - 7));
1550  regex[cp2 - cp - 7] = '\0';
1551 
1552  /* Find the next match command */
1553  cp1 = strstr(cp + 6, "\n@match");
1554 
1555  /* Got a match - handle * as special case. */
1556  if (regex[0] == '*') {
1557  gotmatch = 1;
1558  } else {
1559  char *pipe_sep, *pnext = NULL;
1560 
1561  /* Need to parse all the | separators. Our re_cmp isn't
1562  * really a fully blown regex parser. */
1563  for (pipe_sep = regex; pipe_sep; pipe_sep = pnext) {
1564  pnext = strchr(pipe_sep, '|');
1565 
1566  if (pnext) {
1567  *pnext = '\0';
1568  pnext++;
1569  }
1570 
1571  if (re_cmp(match, pipe_sep)) {
1572  gotmatch = 1;
1573  break;
1574  }
1575  }
1576  }
1577 
1578  if (gotmatch) {
1579  if (cp1) {
1580  cp3 = emalloc(cp1 - cp2 + 1);
1581  strncpy(cp3, cp2 + 1, cp1 - cp2);
1582  cp3[cp1 - cp2 - 1] = '\0';
1583  } else {
1584  /* If no next match, just want the rest of the string */
1585  cp3 = estrdup(cp2 + 1);
1586  }
1587 
1588  return cp3;
1589  }
1590 
1591  gotmatch = 0;
1592 
1593  if (cp1) {
1594  cp = cp1 + 1;
1595  } else {
1596  return NULL;
1597  }
1598  }
1599  }
1600 }
1601 
1615 int talk_to_npc(object *op, object *npc, char *txt)
1616 {
1617  size_t ret = 0;
1618 
1619  if (HAS_EVENT(npc, EVENT_SAY)) {
1620  /* Trigger the SAY event */
1621  ret = trigger_event(EVENT_SAY, op, npc, NULL, txt, 0, 0, 0, 0);
1622  } else if (npc->msg != NULL && *npc->msg == '@') {
1623  char *cp = find_matching_message(npc->msg, txt);
1624 
1625  if (cp != NULL) {
1626  ret = strlen(cp);
1627 
1628  if (op->type == PLAYER) {
1629  packet_struct *packet = packet_new(CLIENT_CMD_INTERFACE, 256,
1630  256);
1631 
1632  packet_debug_data(packet, 0, "\nInterface data type");
1633  packet_append_uint8(packet, CMD_INTERFACE_TEXT);
1634  packet_debug_data(packet, 0, "Text");
1635  packet_append_string_len(packet, cp, ret);
1636  packet_append_uint8(packet, '\0');
1637 
1638  packet_debug_data(packet, 0, "\nInterface data type");
1639  packet_append_uint8(packet, CMD_INTERFACE_ANIM);
1640  packet_debug_data(packet, 0, "Animation ID");
1641  packet_append_uint16(packet, npc->animation_id);
1642  packet_debug_data(packet, 0, "Animation speed");
1643  packet_append_uint8(packet, npc->anim_speed);
1644  packet_debug_data(packet, 0, "Direction");
1645  packet_append_uint8(packet, npc->direction);
1646 
1647  packet_debug_data(packet, 0, "\nInterface data type");
1648  packet_append_uint8(packet, CMD_INTERFACE_TITLE);
1649  packet_debug_data(packet, 0, "Title");
1650  packet_append_string_terminated(packet, npc->name);
1651 
1652  socket_send_packet(CONTR(op)->cs, packet);
1653  } else {
1654  char buf[HUGE_BUF];
1655  char *name = object_get_name_s(npc, NULL);
1656  snprintf(buf, sizeof(buf), "\n%s says: %s", name, cp);
1657  efree(name);
1658  draw_info_map(CHAT_TYPE_GAME, NULL, COLOR_WHITE, op->map, op->x,
1659  op->y, MAP_INFO_NORMAL, op, op, buf);
1660  }
1661 
1662  efree(cp);
1663  }
1664  }
1665 
1666  if (op->type == PLAYER) {
1667  player_set_talking_to(CONTR(op), npc);
1668  }
1669 
1670  uint32_t secs = INTERFACE_TIMEOUT(ret);
1671  monster_data_dialogs_add(npc, op, MIN(secs, INTERFACE_TIMEOUT_MAX));
1672 
1673  return ret != 0;
1674 }
1675 
1685 int is_friend_of(object *op, object *obj)
1686 {
1687  if (op == NULL || obj == NULL) {
1688  return 0;
1689  }
1690 
1691  /* We are obviously friends with ourselves. */
1692  if (op == obj) {
1693  return 1;
1694  }
1695 
1696  if (!IS_LIVE(op) && !IS_LIVE(obj)) {
1697  return 0;
1698  }
1699 
1700  /* Berserk */
1701  if (QUERY_FLAG(op, FLAG_BERSERK)) {
1702  return 0;
1703  }
1704 
1705  /* If on PVP area, they won't be friendly */
1706  if (pvp_area(op, obj)) {
1707  return 0;
1708  }
1709 
1710  if (op->type == PLAYER && obj->type == PLAYER) {
1711  return 1;
1712  }
1713 
1714  if (op->type == MONSTER && OBJECT_VALID(op->enemy, op->enemy_count) &&
1715  obj == op->enemy) {
1716  return 0;
1717  }
1718 
1719  if (obj->type == MONSTER && OBJECT_VALID(obj->enemy, obj->enemy_count) &&
1720  op == obj->enemy) {
1721  return 0;
1722  }
1723 
1724  if (op->type == PLAYER && CONTR(op)->combat_force) {
1725  return 0;
1726  }
1727 
1728  if (op->type != PLAYER) {
1729  shstr *name = object_get_value(op, "faction");
1730  if (name == NULL) {
1731  return 0;
1732  }
1733 
1734  faction_t faction = faction_find(name);
1735  if (faction == NULL || !faction_is_friend(faction, obj)) {
1736  return 0;
1737  }
1738  }
1739 
1740  if (obj->type != PLAYER) {
1741  shstr *name = object_get_value(obj, "faction");
1742  if (name == NULL) {
1743  return 0;
1744  }
1745 
1746  faction_t faction = faction_find(name);
1747  if (faction == NULL || !faction_is_friend(faction, op)) {
1748  return 0;
1749  }
1750  }
1751 
1752  return 1;
1753 }
1754 
1764 int check_good_weapon(object *who, object *item)
1765 {
1766  object *other_weap;
1767  int val = 0, i;
1768 
1769  /* Cursed or damned; never better. */
1770  if (QUERY_FLAG(item, FLAG_CURSED) || QUERY_FLAG(item, FLAG_DAMNED)) {
1771  return 0;
1772  }
1773 
1774  for (other_weap = who->inv; other_weap; other_weap = other_weap->below) {
1775  if (other_weap->type == item->type && QUERY_FLAG(other_weap, FLAG_APPLIED)) {
1776  break;
1777  }
1778  }
1779 
1780  /* No other weapons */
1781  if (other_weap == NULL) {
1782  return 1;
1783  }
1784 
1785  val = item->stats.dam - other_weap->stats.dam;
1786  val += (item->magic - other_weap->magic) * 3;
1787 
1788  /* Monsters don't really get benefits from things like regen rates
1789  * from items. But the bonus for their stats are very important. */
1790  for (i = 0; i < NUM_STATS; i++) {
1791  val += (get_attr_value(&item->stats, i) - get_attr_value(&other_weap->stats, i)) * 2;
1792  }
1793 
1794  if (val > 0) {
1795  CLEAR_FLAG(other_weap, FLAG_APPLIED);
1796  return 1;
1797  }
1798 
1799  return 0;
1800 }
1801 
1811 int check_good_armour(object *who, object *item)
1812 {
1813  object *other_armour;
1814  int val = 0, i;
1815 
1816  /* Cursed or damned; never better. */
1817  if (QUERY_FLAG(item, FLAG_CURSED) || QUERY_FLAG(item, FLAG_DAMNED)) {
1818  return 0;
1819  }
1820 
1821  for (other_armour = who->inv; other_armour; other_armour = other_armour->below) {
1822  if (other_armour->type == item->type && QUERY_FLAG(other_armour, FLAG_APPLIED)) {
1823  break;
1824  }
1825  }
1826 
1827  /* No other armour, use the new */
1828  if (other_armour == NULL) {
1829  return 1;
1830  }
1831 
1832  /* See which is better */
1833  val = item->stats.ac - other_armour->stats.ac;
1834  val += (item->magic - other_armour->magic) * 3;
1835 
1836  for (i = 0; i < NROFATTACKS; i++) {
1837  if (item->protection[i] > other_armour->protection[i]) {
1838  val++;
1839  } else if (item->protection[i] < other_armour->protection[i]) {
1840  val--;
1841  }
1842  }
1843 
1844  if (val > 0) {
1845  CLEAR_FLAG(other_armour, FLAG_APPLIED);
1846  return 1;
1847  }
1848 
1849  return 0;
1850 }
1851 
1852 bool monster_is_ally_of(object *op, object *target)
1853 {
1854  shstr *op_faction_name = object_get_value(op, "faction");
1855 
1856  if (op_faction_name == NULL) {
1857  return false;
1858  }
1859 
1860  shstr *target_faction_name = object_get_value(target, "faction");
1861 
1862  if (target_faction_name == NULL) {
1863  return false;
1864  }
1865 
1866  faction_t op_faction = faction_find(op_faction_name);
1867 
1868  if (op_faction == NULL) {
1869  return false;
1870  }
1871 
1872  faction_t target_faction = faction_find(target_faction_name);
1873 
1874  if (target_faction == NULL) {
1875  return false;
1876  }
1877 
1878  return faction_is_alliance(op_faction, target_faction);
1879 }
1880 
1886 void
1888 {
1889  HARD_ASSERT(op != NULL);
1890  HARD_ASSERT(op->type == MONSTER);
1891  SOFT_ASSERT(op->map != NULL, "Monster is not on a map: %s",
1892  object_get_str(op));
1893 
1894  FOR_INV_PREPARE(op, tmp) {
1895  if (tmp->type == ARROW && tmp->attacked_by_count != 0) {
1896  object_remove(tmp, 0);
1897  tmp->x = op->x;
1898  tmp->y = op->y;
1899  object_insert_map(tmp, op->map, op, 0);
1900  }
1901  } FOR_INV_FINISH();
1902 }
#define FREE_AND_ADD_REF_HASH(_sv_, _nv_)
Definition: global.h:116
Definition: object.h:94
#define MONSTER
Definition: define.h:353
void object_destroy(object *ob)
Definition: object.c:1441
static void pace_moveh(object *ob)
Definition: monster.c:1448
#define TILED_NUM_DIR
Definition: global.h:210
int16_t ac
Definition: living.h:93
tag_t ownercount
Definition: object.h:219
uint8_t move_type
Definition: object.h:384
#define MAP_IN_MEMORY
Definition: map.h:170
uint8_t item_level
Definition: object.h:375
int get_rangevector(object *op1, object *op2, rv_vector *retval, int flags)
Definition: map.c:2238
#define SPELL_DESC_ENEMY
Definition: spells.h:124
int direction
Definition: map.h:787
bool object_set_value(object *op, const char *key, const char *value, bool add_key)
Definition: object.c:2635
static char * find_matching_message(const char *msg, const char *match)
Definition: monster.c:1530
Definition: object.h:488
#define STRING_OBJ_NAME(__ob__)
Definition: global.h:264
object * waypoint_get_active(object *npc)
Definition: waypoint.c:53
static int hitrun_att(int dir, object *ob)
Definition: monster.c:1305
#define FLAG_CURSED
Definition: define.h:1154
tag_t attacked_by_count
Definition: object.h:222
void monster_enemy_signal(object *npc, object *enemy)
Definition: monster.c:270
unsigned int distance
Definition: map.h:775
tag_t enemy_count
Definition: object.h:216
#define RV_NO_DISTANCE
Definition: map.h:813
int trigger_event(int event_type, object *const activator, object *const me, object *const other, const char *msg, int parm1, int parm2, int parm3, int flags)
Definition: plugins.c:510
mapstruct * get_map_from_coord2(mapstruct *m, int *x, int *y)
Definition: map.c:2000
#define FLAG_SLEEP
Definition: define.h:868
#define FOR_INV_PREPARE(op_, it_)
Definition: define.h:1691
int get_randomized_dir(int dir)
Definition: move.c:53
#define MIN_MON_RADIUS
Definition: global.h:176
#define FOR_INV_FINISH()
Definition: define.h:1698
objectlink * linked_spawn_points
Definition: map.h:591
int range
Definition: spells.h:147
uint32_t in_memory
Definition: map.h:627
#define FLAG_FRIENDLY
Definition: define.h:926
int16_t last_heal
Definition: object.h:310
#define INTERFACE_TIMEOUT(ret)
Definition: define.h:1578
#define BOW
Definition: define.h:174
OBJECT_TYPE_INIT_DEFINE(monster)
Definition: monster.c:810
object * waypoint_get_home(object *npc)
Definition: waypoint.c:98
static int monster_spell_useful(object *target, int spell_id)
Definition: monster.c:1083
#define SPELL_DESC_DIRECTION
Definition: spells.h:118
shstr * object_get_value(const object *op, const char *const key)
Definition: object.c:2515
int distance_x
Definition: map.h:778
#define CIRCLE2
Definition: define.h:1431
#define FLAG_CAST_SPELL
Definition: define.h:1078
#define INTERFACE_TIMEOUT_MAX
Definition: define.h:1574
const char * slaying
Definition: object.h:180
int16_t last_sp
Definition: object.h:313
#define FLAG_BLIND
Definition: define.h:884
static int disthit_att(int dir, object *ob, object *part, rv_vector *rv)
Definition: monster.c:1362
#define HAS_EVENT(ob, event)
Definition: plugin.h:179
struct obj * above
Definition: object.h:120
#define RANDO
Definition: define.h:1452
int obj_in_line_of_sight(object *obj, rv_vector *rv)
Definition: los.c:427
#define FLAG_INVULNERABLE
Definition: define.h:1229
void object_destruct(object *op)
Definition: object.c:1521
static int absdir(int d)
Definition: define.h:1838
static int wait_att(int dir, object *ob, object *part, rv_vector *rv)
Definition: monster.c:1331
#define WAITATT
Definition: define.h:1410
#define IS_LIVE(op)
Definition: define.h:841
#define PLAYER
Definition: define.h:122
#define SPELL_DESC_SELF
Definition: spells.h:120
#define BEHAVIOR_SPELL_FRIENDLY
Definition: object.h:600
#define FLAG_PARALYZED
Definition: define.h:876
int8_t get_attr_value(const living *stats, int attr)
Definition: living.c:305
int SP_level_spellpoint_cost(object *caster, int spell_type, int caster_level)
Definition: spell_util.c:1072
int16_t sp
Definition: living.h:78
#define OBJECT_FREE(_ob_)
Definition: object.h:554
size_t monster_data_dialogs_num(object *op)
Definition: monster_data.c:321
#define QUERY_FLAG(xyz, p)
Definition: define.h:761
struct obj * enemy
Definition: object.h:196
void monster_data_dialogs_cleanup(object *op)
Definition: monster_data.c:349
static void pace2_moveh(object *ob)
Definition: monster.c:1486
int8_t Int
Definition: living.h:112
void object_remove(object *op, int flags)
Definition: object.c:1623
#define FLAG_STAND_STILL
Definition: define.h:1133
int16_t maxsp
Definition: living.h:81
object * check_enemy(object *npc, rv_vector *rv)
Definition: monster.c:326
int8_t Con
Definition: living.h:109
int32_t hp
Definition: living.h:72
int cast_spell(object *op, object *caster, int dir, int type, int ability, int item, const char *stringarg)
Definition: spell_util.c:192
void player_set_talking_to(player *pl, object *npc)
Definition: player.c:2647
#define FLAG_BERSERK
Definition: define.h:1221
char * object_get_name_s(const object *op, const object *caller)
Definition: item.c:398
void monster_data_enemy_update(object *op, object *enemy)
Definition: monster_data.c:89
object * ob
Definition: object.h:496
#define PATH_TRANSMUTE
Definition: spells.h:66
int object_ranged_fire(object *op, object *shooter, int dir, double *delay)
#define SPAWN_POINT_INFO
Definition: define.h:369
static void circ2_move(object *ob)
Definition: monster.c:1412
int distance_y
Definition: map.h:781
#define EVENT_AI
Definition: plugin.h:101
const char * title
Definition: object.h:171
#define FLAG_DAMNED
Definition: define.h:1158
int16_t y
Definition: object.h:276
int32_t maxhp
Definition: living.h:75
static int can_hit(object *ob1, rv_vector *rv)
Definition: monster.c:1020
static int monster_use_bow(object *head, object *part, int dir)
Definition: monster.c:1230
archetype_t * arches[ARCH_MAX]
Definition: arch.c:45
#define P_IS_PLAYER
Definition: map.h:256
void set_npc_enemy(object *npc, object *enemy, rv_vector *rv)
Definition: monster.c:85
#define RUNATT
Definition: define.h:1406
#define ABILITY
Definition: define.h:449
const char * object_get_str(const object *op)
Definition: object.c:3151
spell_struct * find_spell(int spelltype)
Definition: spell_util.c:160
int8_t direction
Definition: object.h:350
uint8_t item_race
Definition: object.h:372
#define MAP_INFO_NORMAL
Definition: global.h:83
static int can_detect_target(object *op, object *target, unsigned int range, unsigned int srange, rv_vector *rv)
Definition: monster.c:830
int is_friend_of(object *op, object *obj)
Definition: monster.c:1685
#define FLAG_STEALTH
Definition: define.h:1146
#define DISTHIT
Definition: define.h:1416
#define RUSH
Definition: define.h:1412
static int dist_att(int dir, object *part, rv_vector *rv)
Definition: monster.c:1256
double weapon_speed_left
Definition: object.h:478
#define CAST_NPC
Definition: spells.h:288
void monster_data_dialogs_purge(object *op)
Definition: monster_data.c:389
uint16_t animation_id
Definition: object.h:322
object * object_insert_into(object *op, object *where, int flag)
Definition: object.c:2158
bool faction_is_friend(faction_t faction, object *op)
Definition: faction.c:618
struct mapdef * map
Definition: object.h:139
#define ALLRUN
Definition: define.h:1414
#define PATH_INFO
Definition: spells.h:64
#define FLAG_SCARED
Definition: define.h:880
#define PACEH
Definition: define.h:1437
#define FLAG_RANDOM_MOVE
Definition: define.h:1137
#define DISTATT
Definition: define.h:1404
int16_t dam
Definition: living.h:87
#define MAX_AGGRO_RANGE
Definition: global.h:178
const char * name
Definition: object.h:168
#define SET_FLAG(xyz, p)
Definition: define.h:741
faction_t faction_find(shstr *name)
Definition: faction.c:382
object * waypoint_get_aggro(object *npc)
Definition: waypoint.c:75
object * arch_to_object(archetype_t *at)
Definition: arch.c:446
uint32_t flags
Definition: spells.h:189
void set_mobile_speed(object *op, int idx)
Definition: living.c:1785
#define move_object(__op, __dir)
Definition: global.h:253
struct obj * below
Definition: object.h:114
void monster_data_dialogs_add(object *op, object *activator, uint32_t secs)
Definition: monster_data.c:214
static void pace_movev(object *ob)
Definition: monster.c:1430
int16_t last_grace
Definition: object.h:316
#define RANDO2
Definition: define.h:1455
struct mapdef * tile_map[TILED_NUM]
Definition: map.h:550
uint8_t anim_speed
Definition: object.h:393
#define FLAG_NO_ATTACK
Definition: define.h:1225
union oblnk::@3 objlink
int talk_to_npc(object *op, object *npc, char *txt)
Definition: monster.c:1615
static int wait_att2(int dir, rv_vector *rv)
Definition: monster.c:1380
#define CIRCLE1
Definition: define.h:1428
#define PACEV
Definition: define.h:1461
int8_t item_power
Definition: object.h:442
#define IS_INVISIBLE(__ob_, __player_)
Definition: define.h:1356
#define EVENT_SAY
Definition: plugin.h:85
#define ARROW
Definition: define.h:170
The 'waypoint' archetype.
Definition: arch.h:55
uint8_t attack_move_type
Definition: object.h:387
static object * find_nearest_enemy(object *ob)
Definition: monster.c:862
static void monster_enemy_signal_map(object *npc, mapstruct *map, object *spawn_point, uint32_t dist)
Definition: monster.c:224
double speed
Definition: object.h:469
bool monster_guard_check(object *op, object *target, const char *msg, uint32_t distance)
#define MAX_AGGRO_TIME
Definition: global.h:180
static object * monster_choose_random_spell(object *monster, uint32_t flags)
Definition: monster.c:1041
static int run_att(int dir, object *ob, object *part, rv_vector *rv)
Definition: monster.c:1284
#define FLAG_READY_BOW
Definition: define.h:1106
object * living_get_base_info(object *op)
Definition: living.c:1732
int16_t x
Definition: object.h:273
int pvp_area(object *attacker, object *victim)
Definition: player.c:977
int16_t last_eat
Definition: object.h:319
#define FLAG_REMOVED
Definition: define.h:930
int16_t wc
Definition: living.h:90
object * object_insert_map(object *op, mapstruct *m, object *originator, int flag)
Definition: object.c:1741
spell_struct spells[NROFREALSPELLS]
Definition: spellist.h:34
void play_sound_map(mapstruct *map, int type, const char *filename, int x, int y, int loop, int volume)
Definition: sounds.c:159
static int move_randomly(object *op)
Definition: monster.c:942
#define FLAG_ONLY_ATTACK
Definition: define.h:1141
int check_good_weapon(object *who, object *item)
Definition: monster.c:1764
#define MAP_NAME_SHARED
Definition: map.h:157
#define EVENT_AI_RANDOM_MOVE
Definition: plugin.h:109
#define FLAG_APPLIED
Definition: define.h:1182
#define HITRUN
Definition: define.h:1408
int8_t protection[NROFATTACKS]
Definition: object.h:439
int8_t move_status
Definition: object.h:381
#define NUM_STATS
Definition: living.h:49
#define PATH_LIGHT
Definition: spells.h:76
#define RV_DIAGONAL_DISTANCE
Definition: map.h:809
int on_same_map(object *op1, object *op2)
Definition: map.c:2414
struct obj * owner
Definition: object.h:207
int skill_attack(object *tmp, object *pl, int dir, char *string)
Definition: skill_util.c:377
#define FLAG_XRAYS
Definition: define.h:1110
shstr_constants shstr_cons
Definition: init.c:58
uint32_t path
Definition: spells.h:192
tag_t count
Definition: object.h:142
int get_rangevector_from_mapcoords(mapstruct *map1, int x, int y, mapstruct *map2, int x2, int y2, rv_vector *retval, int flags)
Definition: map.c:2297
living stats
Definition: object.h:481
int distance_z
Definition: map.h:784
int8_t Dex
Definition: living.h:106
void draw_info_map(uint8_t type, const char *name, const char *color, mapstruct *map, int x, int y, int dist, object *op, object *op2, const char *buf)
Definition: info.c:195
struct oblnk * next
Definition: object.h:500
void monster_guard_activate_gate(object *op, int state)
Definition: monster_guard.c:52
int freearr_x[SIZEOFFREE]
Definition: object.c:84
uint8_t behavior
Definition: object.h:399
uint8_t type
Definition: object.h:360
#define CLEAR_FLAG(xyz, p)
Definition: define.h:751
#define OBJECT_METHODS(type)
int16_t attacked_by_distance
Definition: object.h:289
object * part
Definition: map.h:790
static int can_detect_enemy(object *op, object *enemy, rv_vector *rv)
Definition: monster.c:424
const char * msg
Definition: object.h:183
void waypoint_move(object *op, object *npc)
Definition: waypoint.c:283
int monster_signal_chance[MAX_STAT+1]
Definition: living.c:152
#define OBJECT_VALID(_ob_, _count_)
Definition: object.h:548
#define WAIT2
Definition: define.h:1418
object * object_find_type(object *op, uint8_t type)
Definition: object.c:2284
#define FLAG_IS_MAGICAL
Definition: define.h:1129
bool faction_is_alliance(faction_t faction, faction_t faction2)
Definition: faction.c:663
int8_t Pow
Definition: living.h:115
struct obj * inv
Definition: object.h:123
uint8_t anim_flags
Definition: object.h:390
struct obj * head
Definition: object.h:136
#define P_IS_MONSTER
Definition: map.h:258
void monster_drop_arrows(object *op)
Definition: monster.c:1887
#define WPOINT
Definition: define.h:1472
static int monster_cast_spell(object *head, object *part, int dir, rv_vector *rv, uint32_t flags)
Definition: monster.c:1110
#define FLAG_UNAGGRESSIVE
Definition: define.h:1020
uint8_t run_away
Definition: object.h:402
mapstruct * ready_map_name(const char *name, mapstruct *originator, int flags)
Definition: map.c:1584
#define FLAG_CONFUSED
Definition: define.h:872
#define PACEH2
Definition: define.h:1445
static bool monster_can_move(object *op)
Definition: monster.c:465
object * living_find_base_info(object *op)
Definition: living.c:1705
#define PACEV2
Definition: define.h:1469
object * find_enemy(object *npc, rv_vector *rv)
Definition: monster.c:350
Definition: map.h:536
#define CAST_NORMAL
Definition: spells.h:275
#define FLAG_REFLECTING
Definition: define.h:984
#define FLAG_RUN_AWAY
Definition: define.h:1049
static void circ1_move(object *ob)
Definition: monster.c:1394
int freearr_y[SIZEOFFREE]
Definition: object.c:99
int8_t magic
Definition: object.h:341
#define SPELL_DESC_FRIENDLY
Definition: spells.h:122
#define PATH_TRANSFER
Definition: spells.h:68
static void pace2_movev(object *ob)
Definition: monster.c:1466
static void process_func(object *op)
Definition: monster.c:475
struct obj * attacked_by
Definition: object.h:199
int check_good_armour(object *who, object *item)
Definition: monster.c:1811
static void rand_move(object *ob)
Definition: monster.c:1506
const char * re_cmp(const char *, const char *)
Definition: re-cmp.c:76