1 | /* |
1 | /* |
2 | CrossFire, A Multiplayer game for X-windows |
2 | * CrossFire, A Multiplayer game for X-windows |
3 | |
3 | * |
|
|
4 | * Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team |
4 | Copyright (C) 2002 Mark Wedel & Crossfire Development Team |
5 | * Copyright (C) 2002 Mark Wedel & Crossfire Development Team |
5 | Copyright (C) 1992 Frank Tore Johansen |
6 | * Copyright (C) 1992 Frank Tore Johansen |
6 | |
7 | * |
7 | This program is free software; you can redistribute it and/or modify |
8 | * This program is free software; you can redistribute it and/or modify |
8 | it under the terms of the GNU General Public License as published by |
9 | * it under the terms of the GNU General Public License as published by |
9 | the Free Software Foundation; either version 2 of the License, or |
10 | * the Free Software Foundation; either version 2 of the License, or |
10 | (at your option) any later version. |
11 | * (at your option) any later version. |
11 | |
12 | * |
12 | This program is distributed in the hope that it will be useful, |
13 | * This program is distributed in the hope that it will be useful, |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | GNU General Public License for more details. |
16 | * GNU General Public License for more details. |
16 | |
17 | * |
17 | You should have received a copy of the GNU General Public License |
18 | * You should have received a copy of the GNU General Public License |
18 | along with this program; if not, write to the Free Software |
19 | * along with this program; if not, write to the Free Software |
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
20 | |
21 | * |
21 | The authors can be reached via e-mail at <crossfire@schmorp.de> |
22 | * The authors can be reached via e-mail at <crossfire@schmorp.de> |
22 | */ |
23 | */ |
23 | |
24 | |
24 | #include <global.h> |
25 | #include <global.h> |
25 | #ifndef __CEXTRACT__ |
|
|
26 | # include <sproto.h> |
26 | #include <sproto.h> |
27 | # include <spells.h> |
27 | #include <spells.h> |
28 | # include <skills.h> |
28 | #include <skills.h> |
29 | #endif |
|
|
30 | |
|
|
31 | |
29 | |
32 | #define MIN_MON_RADIUS 3 /* minimum monster detection radius */ |
30 | #define MIN_MON_RADIUS 3 /* minimum monster detection radius */ |
33 | |
|
|
34 | |
31 | |
35 | /* checks npc->enemy and returns that enemy if still valid, |
32 | /* checks npc->enemy and returns that enemy if still valid, |
36 | * NULL otherwise. |
33 | * NULL otherwise. |
37 | * this is map tile aware. |
34 | * this is map tile aware. |
38 | * If this returns an enemy, the range vector rv should also be |
35 | * If this returns an enemy, the range vector rv should also be |
… | |
… | |
116 | find_nearest_living_creature (object *npc) |
113 | find_nearest_living_creature (object *npc) |
117 | { |
114 | { |
118 | int i, mflags; |
115 | int i, mflags; |
119 | sint16 nx, ny; |
116 | sint16 nx, ny; |
120 | maptile *m; |
117 | maptile *m; |
121 | object *tmp; |
|
|
122 | int search_arr[SIZEOFFREE]; |
118 | int search_arr[SIZEOFFREE]; |
123 | |
119 | |
124 | get_search_arr (search_arr); |
120 | get_search_arr (search_arr); |
|
|
121 | |
125 | for (i = 0; i < SIZEOFFREE; i++) |
122 | for (i = 0; i < SIZEOFFREE; i++) |
126 | { |
123 | { |
127 | /* modified to implement smart searching using search_arr |
124 | /* modified to implement smart searching using search_arr |
128 | * guidance array to determine direction of search order |
125 | * guidance array to determine direction of search order |
129 | */ |
126 | */ |
130 | nx = npc->x + freearr_x[search_arr[i]]; |
127 | nx = npc->x + freearr_x[search_arr[i]]; |
131 | ny = npc->y + freearr_y[search_arr[i]]; |
128 | ny = npc->y + freearr_y[search_arr[i]]; |
132 | m = npc->map; |
129 | m = npc->map; |
133 | |
130 | |
134 | mflags = get_map_flags (m, &m, nx, ny, &nx, &ny); |
131 | mflags = get_map_flags (m, &m, nx, ny, &nx, &ny); |
|
|
132 | |
135 | if (mflags & P_OUT_OF_MAP) |
133 | if (mflags & P_OUT_OF_MAP) |
136 | continue; |
134 | continue; |
137 | |
135 | |
138 | if (mflags & P_IS_ALIVE) |
136 | if (mflags & P_IS_ALIVE) |
139 | { |
137 | { |
140 | tmp = get_map_ob (m, nx, ny); |
138 | for (object *tmp = m->at (nx, ny).top; tmp; tmp = tmp->below) |
141 | while (tmp != NULL && !QUERY_FLAG (tmp, FLAG_MONSTER) && !QUERY_FLAG (tmp, FLAG_GENERATOR) && tmp->type != PLAYER) |
139 | if (tmp->flag [FLAG_MONSTER] || tmp->flag [FLAG_GENERATOR] || tmp->type == PLAYER) |
142 | tmp = tmp->above; |
|
|
143 | |
|
|
144 | if (!tmp) |
|
|
145 | { |
|
|
146 | LOG (llevDebug, "find_nearest_living_creature: map %s (%d,%d) has is_alive set but did not find a monster?\n", |
|
|
147 | m->path, nx, ny); |
|
|
148 | } |
|
|
149 | else |
|
|
150 | { |
|
|
151 | if (can_see_monsterP (m, nx, ny, i)) |
140 | if (can_see_monsterP (m, nx, ny, i)) |
152 | return tmp; |
141 | return tmp; |
153 | } |
142 | } |
154 | } /* is something living on this space */ |
|
|
155 | } |
143 | } |
156 | return NULL; /* nothing found */ |
144 | |
|
|
145 | return 0; |
157 | } |
146 | } |
158 | |
147 | |
159 | |
148 | |
160 | /* Tries to find an enmy for npc. We pass the range vector since |
149 | /* Tries to find an enmy for npc. We pass the range vector since |
161 | * our caller will find the information useful. |
150 | * our caller will find the information useful. |
… | |
… | |
289 | int i; |
278 | int i; |
290 | |
279 | |
291 | /* Give up to 15 chances for a monster to move randomly */ |
280 | /* Give up to 15 chances for a monster to move randomly */ |
292 | for (i = 0; i < 15; i++) |
281 | for (i = 0; i < 15; i++) |
293 | { |
282 | { |
294 | if (move_object (op, RANDOM () % 8 + 1)) |
283 | if (move_object (op, rndm (8) + 1)) |
295 | return 1; |
284 | return 1; |
296 | } |
285 | } |
297 | return 0; |
286 | return 0; |
298 | } |
287 | } |
299 | |
288 | |
… | |
… | |
368 | } |
357 | } |
369 | |
358 | |
370 | /* this should probably get modified by many more values. |
359 | /* this should probably get modified by many more values. |
371 | * (eg, creatures resistance to fear, level, etc. ) |
360 | * (eg, creatures resistance to fear, level, etc. ) |
372 | */ |
361 | */ |
373 | if (QUERY_FLAG (op, FLAG_SCARED) && !(RANDOM () % 20)) |
362 | if (QUERY_FLAG (op, FLAG_SCARED) && !(rndm (20))) |
374 | { |
363 | { |
375 | CLEAR_FLAG (op, FLAG_SCARED); /* Time to regain some "guts"... */ |
364 | CLEAR_FLAG (op, FLAG_SCARED); /* Time to regain some "guts"... */ |
376 | } |
365 | } |
377 | |
366 | |
378 | if (INVOKE_OBJECT (MONSTER_MOVE, op, ARG_OBJECT (op->enemy))) |
367 | if (INVOKE_OBJECT (MONSTER_MOVE, op, ARG_OBJECT (op->enemy))) |
… | |
… | |
457 | } /* stand still */ |
446 | } /* stand still */ |
458 | return 0; |
447 | return 0; |
459 | } /* no enemy */ |
448 | } /* no enemy */ |
460 | |
449 | |
461 | /* We have an enemy. Block immediately below is for pets */ |
450 | /* We have an enemy. Block immediately below is for pets */ |
462 | if ((op->attack_movement & HI4) == PETMOVE && (owner = get_owner (op)) != NULL && !on_same_map (op, owner)) |
451 | if ((op->attack_movement & HI4) == PETMOVE && (owner = op->owner) != NULL && !on_same_map (op, owner)) |
463 | return follow_owner (op, owner); |
452 | return follow_owner (op, owner); |
464 | |
453 | |
465 | /* doppleganger code to change monster facing to that of the nearest |
454 | /* doppleganger code to change monster facing to that of the nearest |
466 | * player. Hmm. The code is here, but no monster in the current |
455 | * player. Hmm. The code is here, but no monster in the current |
467 | * arch set uses it. |
456 | * arch set uses it. |
… | |
… | |
497 | * but that we test above... so can be old code here |
486 | * but that we test above... so can be old code here |
498 | */ |
487 | */ |
499 | if (QUERY_FLAG (op, FLAG_RUN_AWAY)) |
488 | if (QUERY_FLAG (op, FLAG_RUN_AWAY)) |
500 | dir = absdir (dir + 4); |
489 | dir = absdir (dir + 4); |
501 | if (QUERY_FLAG (op, FLAG_CONFUSED)) |
490 | if (QUERY_FLAG (op, FLAG_CONFUSED)) |
502 | dir = absdir (dir + RANDOM () % 3 + RANDOM () % 3 - 2); |
491 | dir = absdir (dir + rndm (3) + rndm (3) - 2); |
503 | |
492 | |
504 | if (QUERY_FLAG (op, FLAG_CAST_SPELL) && !(RANDOM () % 3)) |
493 | if (QUERY_FLAG (op, FLAG_CAST_SPELL) && !(rndm (3))) |
505 | { |
494 | { |
506 | if (monster_cast_spell (op, part, enemy, dir, &rv1)) |
495 | if (monster_cast_spell (op, part, enemy, dir, &rv1)) |
507 | return 0; |
496 | return 0; |
508 | } |
497 | } |
509 | |
498 | |
510 | if (QUERY_FLAG (op, FLAG_READY_SCROLL) && !(RANDOM () % 3)) |
499 | if (QUERY_FLAG (op, FLAG_READY_SCROLL) && !(rndm (3))) |
511 | { |
500 | { |
512 | if (monster_use_scroll (op, part, enemy, dir, &rv1)) |
501 | if (monster_use_scroll (op, part, enemy, dir, &rv1)) |
513 | return 0; |
502 | return 0; |
514 | } |
503 | } |
515 | |
504 | |
516 | if (QUERY_FLAG (op, FLAG_READY_RANGE) && !(RANDOM () % 3)) |
505 | if (QUERY_FLAG (op, FLAG_READY_RANGE) && !(rndm (3))) |
517 | { |
506 | { |
518 | if (monster_use_range (op, part, enemy, dir)) |
507 | if (monster_use_range (op, part, enemy, dir)) |
519 | return 0; |
508 | return 0; |
520 | } |
509 | } |
521 | if (QUERY_FLAG (op, FLAG_READY_SKILL) && !(RANDOM () % 3)) |
510 | if (QUERY_FLAG (op, FLAG_READY_SKILL) && !(rndm (3))) |
522 | { |
511 | { |
523 | if (monster_use_skill (op, rv.part, enemy, rv.direction)) |
512 | if (monster_use_skill (op, rv.part, enemy, rv.direction)) |
524 | return 0; |
513 | return 0; |
525 | } |
514 | } |
526 | if (QUERY_FLAG (op, FLAG_READY_BOW) && !(RANDOM () % 2)) |
515 | if (QUERY_FLAG (op, FLAG_READY_BOW) && !(rndm (2))) |
527 | { |
516 | { |
528 | if (monster_use_bow (op, part, enemy, dir)) |
517 | if (monster_use_bow (op, part, enemy, dir)) |
529 | return 0; |
518 | return 0; |
530 | } |
519 | } |
531 | } /* for processing of all parts */ |
520 | } /* for processing of all parts */ |
… | |
… | |
537 | |
526 | |
538 | if (QUERY_FLAG (op, FLAG_SCARED) || QUERY_FLAG (op, FLAG_RUN_AWAY)) |
527 | if (QUERY_FLAG (op, FLAG_SCARED) || QUERY_FLAG (op, FLAG_RUN_AWAY)) |
539 | dir = absdir (dir + 4); |
528 | dir = absdir (dir + 4); |
540 | |
529 | |
541 | if (QUERY_FLAG (op, FLAG_CONFUSED)) |
530 | if (QUERY_FLAG (op, FLAG_CONFUSED)) |
542 | dir = absdir (dir + RANDOM () % 3 + RANDOM () % 3 - 2); |
531 | dir = absdir (dir + rndm (3) + rndm (3) - 2); |
543 | |
532 | |
544 | pre_att_dir = dir; /* remember the original direction */ |
533 | pre_att_dir = dir; /* remember the original direction */ |
545 | |
534 | |
546 | if ((op->attack_movement & LO4) && !QUERY_FLAG (op, FLAG_SCARED)) |
535 | if ((op->attack_movement & LO4) && !QUERY_FLAG (op, FLAG_SCARED)) |
547 | { |
536 | { |
… | |
… | |
679 | can_hit (object *ob1, object *ob2, rv_vector * rv) |
668 | can_hit (object *ob1, object *ob2, rv_vector * rv) |
680 | { |
669 | { |
681 | object *more; |
670 | object *more; |
682 | rv_vector rv1; |
671 | rv_vector rv1; |
683 | |
672 | |
684 | if (QUERY_FLAG (ob1, FLAG_CONFUSED) && !(RANDOM () % 3)) |
673 | if (QUERY_FLAG (ob1, FLAG_CONFUSED) && !(rndm (3))) |
685 | return 0; |
674 | return 0; |
686 | |
675 | |
687 | if (abs (rv->distance_x) < 2 && abs (rv->distance_y) < 2) |
676 | if (abs (rv->distance_x) < 2 && abs (rv->distance_y) < 2) |
688 | return 1; |
677 | return 1; |
689 | |
678 | |
… | |
… | |
788 | * other monsters) |
777 | * other monsters) |
789 | */ |
778 | */ |
790 | if (!(dir = path_to_player (part, pl, 0))) |
779 | if (!(dir = path_to_player (part, pl, 0))) |
791 | return 0; |
780 | return 0; |
792 | |
781 | |
793 | if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = get_owner (head)) != NULL) |
782 | if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = head->owner) != NULL) |
794 | { |
783 | { |
795 | get_rangevector (head, owner, &rv1, 0x1); |
784 | get_rangevector (head, owner, &rv1, 0x1); |
796 | if (dirdiff (dir, rv1.direction) < 2) |
785 | if (dirdiff (dir, rv1.direction) < 2) |
797 | { |
786 | { |
798 | return 0; /* Might hit owner with spell */ |
787 | return 0; /* Might hit owner with spell */ |
799 | } |
788 | } |
800 | } |
789 | } |
801 | |
790 | |
802 | if (QUERY_FLAG (head, FLAG_CONFUSED)) |
791 | if (QUERY_FLAG (head, FLAG_CONFUSED)) |
803 | dir = absdir (dir + RANDOM () % 3 + RANDOM () % 3 - 2); |
792 | dir = absdir (dir + rndm (3) + rndm (3) - 2); |
804 | |
793 | |
805 | /* If the monster hasn't already chosen a spell, choose one |
794 | /* If the monster hasn't already chosen a spell, choose one |
806 | * I'm not sure if it really make sense to pre-select spells (events |
795 | * I'm not sure if it really make sense to pre-select spells (events |
807 | * could be different by the time the monster goes again). |
796 | * could be different by the time the monster goes again). |
808 | */ |
797 | */ |
… | |
… | |
865 | * other monsters) |
854 | * other monsters) |
866 | */ |
855 | */ |
867 | if (!(dir = path_to_player (part, pl, 0))) |
856 | if (!(dir = path_to_player (part, pl, 0))) |
868 | return 0; |
857 | return 0; |
869 | |
858 | |
870 | if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = get_owner (head)) != NULL) |
859 | if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = head->owner) != NULL) |
871 | { |
860 | { |
872 | get_rangevector (head, owner, &rv1, 0x1); |
861 | get_rangevector (head, owner, &rv1, 0x1); |
873 | if (dirdiff (dir, rv1.direction) < 2) |
862 | if (dirdiff (dir, rv1.direction) < 2) |
874 | { |
863 | { |
875 | return 0; /* Might hit owner with spell */ |
864 | return 0; /* Might hit owner with spell */ |
876 | } |
865 | } |
877 | } |
866 | } |
878 | |
867 | |
879 | if (QUERY_FLAG (head, FLAG_CONFUSED)) |
868 | if (QUERY_FLAG (head, FLAG_CONFUSED)) |
880 | dir = absdir (dir + RANDOM () % 3 + RANDOM () % 3 - 2); |
869 | dir = absdir (dir + rndm (3) + rndm (3) - 2); |
881 | |
870 | |
882 | for (scroll = head->inv; scroll; scroll = scroll->below) |
871 | for (scroll = head->inv; scroll; scroll = scroll->below) |
883 | if (scroll->type == SCROLL && monster_should_cast_spell (head, scroll->inv)) |
872 | if (scroll->type == SCROLL && monster_should_cast_spell (head, scroll->inv)) |
884 | break; |
873 | break; |
885 | |
874 | |
… | |
… | |
916 | object *skill, *owner; |
905 | object *skill, *owner; |
917 | |
906 | |
918 | if (!(dir = path_to_player (part, pl, 0))) |
907 | if (!(dir = path_to_player (part, pl, 0))) |
919 | return 0; |
908 | return 0; |
920 | |
909 | |
921 | if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = get_owner (head)) != NULL) |
910 | if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = head->owner) != NULL) |
922 | { |
911 | { |
923 | int dir2 = find_dir_2 (head->x - owner->x, head->y - owner->y); |
912 | int dir2 = find_dir_2 (head->x - owner->x, head->y - owner->y); |
924 | |
913 | |
925 | if (dirdiff (dir, dir2) < 1) |
914 | if (dirdiff (dir, dir2) < 1) |
926 | return 0; /* Might hit owner with skill -thrown rocks for example ? */ |
915 | return 0; /* Might hit owner with skill -thrown rocks for example ? */ |
927 | } |
916 | } |
928 | if (QUERY_FLAG (head, FLAG_CONFUSED)) |
917 | if (QUERY_FLAG (head, FLAG_CONFUSED)) |
929 | dir = absdir (dir + RANDOM () % 3 + RANDOM () % 3 - 2); |
918 | dir = absdir (dir + rndm (3) + rndm (3) - 2); |
930 | |
919 | |
931 | /* skill selection - monster will use the next unused skill. |
920 | /* skill selection - monster will use the next unused skill. |
932 | * well...the following scenario will allow the monster to |
921 | * well...the following scenario will allow the monster to |
933 | * toggle between 2 skills. One day it would be nice to make |
922 | * toggle between 2 skills. One day it would be nice to make |
934 | * more skills available to monsters. |
923 | * more skills available to monsters. |
… | |
… | |
960 | int at_least_one = 0; |
949 | int at_least_one = 0; |
961 | |
950 | |
962 | if (!(dir = path_to_player (part, pl, 0))) |
951 | if (!(dir = path_to_player (part, pl, 0))) |
963 | return 0; |
952 | return 0; |
964 | |
953 | |
965 | if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = get_owner (head)) != NULL) |
954 | if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = head->owner) != NULL) |
966 | { |
955 | { |
967 | int dir2 = find_dir_2 (head->x - owner->x, head->y - owner->y); |
956 | int dir2 = find_dir_2 (head->x - owner->x, head->y - owner->y); |
968 | |
957 | |
969 | if (dirdiff (dir, dir2) < 2) |
958 | if (dirdiff (dir, dir2) < 2) |
970 | return 0; /* Might hit owner with spell */ |
959 | return 0; /* Might hit owner with spell */ |
971 | } |
960 | } |
972 | if (QUERY_FLAG (head, FLAG_CONFUSED)) |
961 | if (QUERY_FLAG (head, FLAG_CONFUSED)) |
973 | dir = absdir (dir + RANDOM () % 3 + RANDOM () % 3 - 2); |
962 | dir = absdir (dir + rndm (3) + rndm (3) - 2); |
974 | |
963 | |
975 | for (wand = head->inv; wand != NULL; wand = wand->below) |
964 | for (wand = head->inv; wand != NULL; wand = wand->below) |
976 | { |
965 | { |
977 | if (wand->type == WAND) |
966 | if (wand->type == WAND) |
978 | { |
967 | { |
… | |
… | |
987 | { |
976 | { |
988 | if (wand->arch) |
977 | if (wand->arch) |
989 | { |
978 | { |
990 | CLEAR_FLAG (wand, FLAG_ANIMATE); |
979 | CLEAR_FLAG (wand, FLAG_ANIMATE); |
991 | wand->face = wand->arch->clone.face; |
980 | wand->face = wand->arch->clone.face; |
992 | wand->speed = 0; |
981 | wand->set_speed (0); |
993 | update_ob_speed (wand); |
|
|
994 | } |
982 | } |
995 | } |
983 | } |
996 | /* Success */ |
984 | /* Success */ |
997 | return 1; |
985 | return 1; |
998 | } |
986 | } |
… | |
… | |
1029 | object *owner; |
1017 | object *owner; |
1030 | |
1018 | |
1031 | if (!(dir = path_to_player (part, pl, 0))) |
1019 | if (!(dir = path_to_player (part, pl, 0))) |
1032 | return 0; |
1020 | return 0; |
1033 | if (QUERY_FLAG (head, FLAG_CONFUSED)) |
1021 | if (QUERY_FLAG (head, FLAG_CONFUSED)) |
1034 | dir = absdir (dir + RANDOM () % 3 + RANDOM () % 3 - 2); |
1022 | dir = absdir (dir + rndm (3) + rndm (3) - 2); |
1035 | |
1023 | |
1036 | if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = get_owner (head)) != NULL) |
1024 | if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = head->owner) != NULL) |
1037 | { |
1025 | { |
1038 | int dir2 = find_dir_2 (head->x - owner->x, head->y - owner->y); |
1026 | int dir2 = find_dir_2 (head->x - owner->x, head->y - owner->y); |
1039 | |
1027 | |
1040 | if (dirdiff (dir, dir2) < 1) |
1028 | if (dirdiff (dir, dir2) < 1) |
1041 | return 0; /* Might hit owner with arrow */ |
1029 | return 0; /* Might hit owner with arrow */ |
… | |
… | |
1352 | /* Don't use it right now */ |
1340 | /* Don't use it right now */ |
1353 | return; |
1341 | return; |
1354 | } |
1342 | } |
1355 | else if (item->type == WEAPON) |
1343 | else if (item->type == WEAPON) |
1356 | flag = check_good_weapon (mon, item); |
1344 | flag = check_good_weapon (mon, item); |
1357 | else if (IS_ARMOR (item)) |
1345 | else if (item->is_armor ()) |
1358 | flag = check_good_armour (mon, item); |
1346 | flag = check_good_armour (mon, item); |
1359 | /* Should do something more, like make sure this is a better item */ |
1347 | /* Should do something more, like make sure this is a better item */ |
1360 | else if (item->type == RING) |
1348 | else if (item->type == RING) |
1361 | flag = 1; |
1349 | flag = 1; |
1362 | else if (item->type == WAND || item->type == ROD || item->type == HORN) |
1350 | else if (item->type == WAND || item->type == ROD || item->type == HORN) |
… | |
… | |
1433 | mflags = get_map_flags (m, &m, sx, sy, &sx, &sy); |
1421 | mflags = get_map_flags (m, &m, sx, sy, &sx, &sy); |
1434 | /* If nothing alive on this space, no need to search the space. */ |
1422 | /* If nothing alive on this space, no need to search the space. */ |
1435 | if ((mflags & P_OUT_OF_MAP) || !(mflags & P_IS_ALIVE)) |
1423 | if ((mflags & P_OUT_OF_MAP) || !(mflags & P_IS_ALIVE)) |
1436 | continue; |
1424 | continue; |
1437 | |
1425 | |
1438 | for (npc = get_map_ob (m, sx, sy); npc != NULL; npc = npc->above) |
1426 | for (npc = GET_MAP_OB (m, sx, sy); npc != NULL; npc = npc->above) |
1439 | if (QUERY_FLAG (npc, FLAG_ALIVE) && QUERY_FLAG (npc, FLAG_UNAGGRESSIVE)) |
1427 | if (QUERY_FLAG (npc, FLAG_ALIVE) && QUERY_FLAG (npc, FLAG_UNAGGRESSIVE)) |
1440 | npc->enemy = op->enemy; |
1428 | npc->enemy = op->enemy; |
1441 | } |
1429 | } |
1442 | } |
1430 | } |
1443 | |
1431 | |
… | |
… | |
1529 | { |
1517 | { |
1530 | static int circle[12] = { 3, 3, 4, 5, 5, 6, 7, 7, 8, 1, 1, 2 }; |
1518 | static int circle[12] = { 3, 3, 4, 5, 5, 6, 7, 7, 8, 1, 1, 2 }; |
1531 | if (++ob->move_status > 11) |
1519 | if (++ob->move_status > 11) |
1532 | ob->move_status = 0; |
1520 | ob->move_status = 0; |
1533 | if (!(move_object (ob, circle[ob->move_status]))) |
1521 | if (!(move_object (ob, circle[ob->move_status]))) |
1534 | (void) move_object (ob, RANDOM () % 8 + 1); |
1522 | (void) move_object (ob, rndm (8) + 1); |
1535 | } |
1523 | } |
1536 | |
1524 | |
1537 | void |
1525 | void |
1538 | circ2_move (object *ob) |
1526 | circ2_move (object *ob) |
1539 | { |
1527 | { |
1540 | static int circle[20] = { 3, 3, 3, 4, 4, 5, 5, 5, 6, 6, 7, 7, 7, 8, 8, 1, 1, 1, 2, 2 }; |
1528 | static int circle[20] = { 3, 3, 3, 4, 4, 5, 5, 5, 6, 6, 7, 7, 7, 8, 8, 1, 1, 1, 2, 2 }; |
1541 | if (++ob->move_status > 19) |
1529 | if (++ob->move_status > 19) |
1542 | ob->move_status = 0; |
1530 | ob->move_status = 0; |
1543 | if (!(move_object (ob, circle[ob->move_status]))) |
1531 | if (!(move_object (ob, circle[ob->move_status]))) |
1544 | (void) move_object (ob, RANDOM () % 8 + 1); |
1532 | (void) move_object (ob, rndm (8) + 1); |
1545 | } |
1533 | } |
1546 | |
1534 | |
1547 | void |
1535 | void |
1548 | pace_movev (object *ob) |
1536 | pace_movev (object *ob) |
1549 | { |
1537 | { |
… | |
… | |
1599 | void |
1587 | void |
1600 | rand_move (object *ob) |
1588 | rand_move (object *ob) |
1601 | { |
1589 | { |
1602 | int i; |
1590 | int i; |
1603 | |
1591 | |
1604 | if (ob->move_status < 1 || ob->move_status > 8 || !(move_object (ob, ob->move_status || !(RANDOM () % 9)))) |
1592 | if (ob->move_status < 1 || ob->move_status > 8 || !(move_object (ob, ob->move_status || !(rndm (9))))) |
1605 | for (i = 0; i < 5; i++) |
1593 | for (i = 0; i < 5; i++) |
1606 | if (move_object (ob, ob->move_status = RANDOM () % 8 + 1)) |
1594 | if (move_object (ob, ob->move_status = rndm (8) + 1)) |
1607 | return; |
1595 | return; |
1608 | } |
1596 | } |
1609 | |
1597 | |
1610 | void |
1598 | void |
1611 | check_earthwalls (object *op, maptile *m, int x, int y) |
1599 | check_earthwalls (object *op, maptile *m, int x, int y) |
1612 | { |
1600 | { |
1613 | object *tmp; |
1601 | object *tmp; |
1614 | |
1602 | |
1615 | for (tmp = get_map_ob (m, x, y); tmp != NULL; tmp = tmp->above) |
1603 | for (tmp = GET_MAP_OB (m, x, y); tmp != NULL; tmp = tmp->above) |
1616 | { |
1604 | { |
1617 | if (tmp->type == EARTHWALL) |
1605 | if (tmp->type == EARTHWALL) |
1618 | { |
1606 | { |
1619 | hit_player (tmp, op->stats.dam, op, AT_PHYSICAL, 1); |
1607 | hit_player (tmp, op->stats.dam, op, AT_PHYSICAL, 1); |
1620 | return; |
1608 | return; |
… | |
… | |
1625 | void |
1613 | void |
1626 | check_doors (object *op, maptile *m, int x, int y) |
1614 | check_doors (object *op, maptile *m, int x, int y) |
1627 | { |
1615 | { |
1628 | object *tmp; |
1616 | object *tmp; |
1629 | |
1617 | |
1630 | for (tmp = get_map_ob (m, x, y); tmp != NULL; tmp = tmp->above) |
1618 | for (tmp = GET_MAP_OB (m, x, y); tmp != NULL; tmp = tmp->above) |
1631 | { |
1619 | { |
1632 | if (tmp->type == DOOR) |
1620 | if (tmp->type == DOOR) |
1633 | { |
1621 | { |
1634 | hit_player (tmp, 1000, op, AT_PHYSICAL, 1); |
1622 | hit_player (tmp, 1000, op, AT_PHYSICAL, 1); |
1635 | return; |
1623 | return; |
… | |
… | |
1656 | tmp = op; |
1644 | tmp = op; |
1657 | |
1645 | |
1658 | /* New throw code: look through the inventory. Grap the first legal is_thrown |
1646 | /* New throw code: look through the inventory. Grap the first legal is_thrown |
1659 | * marked item and throw it to the enemy. |
1647 | * marked item and throw it to the enemy. |
1660 | */ |
1648 | */ |
1661 | |
|
|
1662 | for (tmp = op->inv; tmp; tmp = tmp->below) |
1649 | for (tmp = op->inv; tmp; tmp = tmp->below) |
1663 | { |
1650 | { |
1664 | |
|
|
1665 | /* Can't throw invisible objects or items that are applied */ |
1651 | /* Can't throw invisible objects or items that are applied */ |
1666 | if (tmp->invisible || QUERY_FLAG (tmp, FLAG_APPLIED)) |
1652 | if (tmp->invisible || QUERY_FLAG (tmp, FLAG_APPLIED)) |
1667 | continue; |
1653 | continue; |
1668 | |
1654 | |
1669 | if (QUERY_FLAG (tmp, FLAG_IS_THROWN)) |
1655 | if (QUERY_FLAG (tmp, FLAG_IS_THROWN)) |
… | |
… | |
1792 | /* ah, we are within range, detected? take cases */ |
1778 | /* ah, we are within range, detected? take cases */ |
1793 | if (!enemy->invisible) /* enemy in dark squares... are seen! */ |
1779 | if (!enemy->invisible) /* enemy in dark squares... are seen! */ |
1794 | return 1; |
1780 | return 1; |
1795 | |
1781 | |
1796 | /* hidden or low-quality invisible */ |
1782 | /* hidden or low-quality invisible */ |
1797 | if (enemy->hide && (rv->distance <= 1) && (RANDOM () % 100 <= hide_discovery)) |
1783 | if (enemy->hide && (rv->distance <= 1) && (rndm (100) <= hide_discovery)) |
1798 | { |
1784 | { |
1799 | make_visible (enemy); |
1785 | make_visible (enemy); |
1800 | /* inform players of new status */ |
1786 | /* inform players of new status */ |
1801 | if (enemy->type == PLAYER && player_can_view (enemy, op)) |
1787 | if (enemy->type == PLAYER && player_can_view (enemy, op)) |
1802 | new_draw_info_format (NDI_UNIQUE, 0, enemy, "You are discovered by %s!", &op->name); |
1788 | new_draw_info_format (NDI_UNIQUE, 0, enemy, "You are discovered by %s!", &op->name); |
… | |
… | |
1809 | * do something to you. Decreasing the duration of invisible |
1795 | * do something to you. Decreasing the duration of invisible |
1810 | * doesn't make a lot of sense IMO, as a bunch of stupid creatures |
1796 | * doesn't make a lot of sense IMO, as a bunch of stupid creatures |
1811 | * can then basically negate the spell. The spell isn't negated - |
1797 | * can then basically negate the spell. The spell isn't negated - |
1812 | * they just know where you are! |
1798 | * they just know where you are! |
1813 | */ |
1799 | */ |
1814 | if ((RANDOM () % 50) <= hide_discovery) |
1800 | if ((rndm (50)) <= hide_discovery) |
1815 | { |
1801 | { |
1816 | if (enemy->type == PLAYER) |
1802 | if (enemy->type == PLAYER) |
1817 | { |
1803 | { |
1818 | new_draw_info_format (NDI_UNIQUE, 0, enemy, "You see %s noticing your position.", query_name (op)); |
1804 | new_draw_info_format (NDI_UNIQUE, 0, enemy, "You see %s noticing your position.", query_name (op)); |
1819 | } |
1805 | } |