ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/monster.C
(Generate patch)

Comparing deliantra/server/server/monster.C (file contents):
Revision 1.18 by root, Tue Dec 26 08:55:00 2006 UTC vs.
Revision 1.24 by root, Thu Jan 18 21:27:19 2007 UTC

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#include <sproto.h> 26#include <sproto.h>
26#include <spells.h> 27#include <spells.h>
27#include <skills.h> 28#include <skills.h>
112find_nearest_living_creature (object *npc) 113find_nearest_living_creature (object *npc)
113{ 114{
114 int i, mflags; 115 int i, mflags;
115 sint16 nx, ny; 116 sint16 nx, ny;
116 maptile *m; 117 maptile *m;
117 object *tmp;
118 int search_arr[SIZEOFFREE]; 118 int search_arr[SIZEOFFREE];
119 119
120 get_search_arr (search_arr); 120 get_search_arr (search_arr);
121
121 for (i = 0; i < SIZEOFFREE; i++) 122 for (i = 0; i < SIZEOFFREE; i++)
122 { 123 {
123 /* modified to implement smart searching using search_arr 124 /* modified to implement smart searching using search_arr
124 * guidance array to determine direction of search order 125 * guidance array to determine direction of search order
125 */ 126 */
126 nx = npc->x + freearr_x[search_arr[i]]; 127 nx = npc->x + freearr_x[search_arr[i]];
127 ny = npc->y + freearr_y[search_arr[i]]; 128 ny = npc->y + freearr_y[search_arr[i]];
128 m = npc->map; 129 m = npc->map;
129 130
130 mflags = get_map_flags (m, &m, nx, ny, &nx, &ny); 131 mflags = get_map_flags (m, &m, nx, ny, &nx, &ny);
132
131 if (mflags & P_OUT_OF_MAP) 133 if (mflags & P_OUT_OF_MAP)
132 continue; 134 continue;
133 135
134 if (mflags & P_IS_ALIVE) 136 if (mflags & P_IS_ALIVE)
135 { 137 {
136 tmp = GET_MAP_OB (m, nx, ny); 138 for (object *tmp = m->at (nx, ny).top; tmp; tmp = tmp->below)
137 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)
138 tmp = tmp->above;
139
140 if (!tmp)
141 {
142 LOG (llevDebug, "find_nearest_living_creature: map %s (%d,%d) has is_alive set but did not find a monster?\n",
143 m->path, nx, ny);
144 }
145 else
146 {
147 if (can_see_monsterP (m, nx, ny, i)) 140 if (can_see_monsterP (m, nx, ny, i))
148 return tmp; 141 return tmp;
149 } 142 }
150 } /* is something living on this space */
151 } 143 }
152 return NULL; /* nothing found */ 144
145 return 0;
153} 146}
154 147
155 148
156/* 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
157 * our caller will find the information useful. 150 * our caller will find the information useful.
285 int i; 278 int i;
286 279
287 /* Give up to 15 chances for a monster to move randomly */ 280 /* Give up to 15 chances for a monster to move randomly */
288 for (i = 0; i < 15; i++) 281 for (i = 0; i < 15; i++)
289 { 282 {
290 if (move_object (op, RANDOM () % 8 + 1)) 283 if (move_object (op, rndm (8) + 1))
291 return 1; 284 return 1;
292 } 285 }
293 return 0; 286 return 0;
294} 287}
295 288
364 } 357 }
365 358
366 /* this should probably get modified by many more values. 359 /* this should probably get modified by many more values.
367 * (eg, creatures resistance to fear, level, etc. ) 360 * (eg, creatures resistance to fear, level, etc. )
368 */ 361 */
369 if (QUERY_FLAG (op, FLAG_SCARED) && !(RANDOM () % 20)) 362 if (QUERY_FLAG (op, FLAG_SCARED) && !(rndm (20)))
370 { 363 {
371 CLEAR_FLAG (op, FLAG_SCARED); /* Time to regain some "guts"... */ 364 CLEAR_FLAG (op, FLAG_SCARED); /* Time to regain some "guts"... */
372 } 365 }
373 366
374 if (INVOKE_OBJECT (MONSTER_MOVE, op, ARG_OBJECT (op->enemy))) 367 if (INVOKE_OBJECT (MONSTER_MOVE, op, ARG_OBJECT (op->enemy)))
493 * but that we test above... so can be old code here 486 * but that we test above... so can be old code here
494 */ 487 */
495 if (QUERY_FLAG (op, FLAG_RUN_AWAY)) 488 if (QUERY_FLAG (op, FLAG_RUN_AWAY))
496 dir = absdir (dir + 4); 489 dir = absdir (dir + 4);
497 if (QUERY_FLAG (op, FLAG_CONFUSED)) 490 if (QUERY_FLAG (op, FLAG_CONFUSED))
498 dir = absdir (dir + RANDOM () % 3 + RANDOM () % 3 - 2); 491 dir = absdir (dir + rndm (3) + rndm (3) - 2);
499 492
500 if (QUERY_FLAG (op, FLAG_CAST_SPELL) && !(RANDOM () % 3)) 493 if (QUERY_FLAG (op, FLAG_CAST_SPELL) && !(rndm (3)))
501 { 494 {
502 if (monster_cast_spell (op, part, enemy, dir, &rv1)) 495 if (monster_cast_spell (op, part, enemy, dir, &rv1))
503 return 0; 496 return 0;
504 } 497 }
505 498
506 if (QUERY_FLAG (op, FLAG_READY_SCROLL) && !(RANDOM () % 3)) 499 if (QUERY_FLAG (op, FLAG_READY_SCROLL) && !(rndm (3)))
507 { 500 {
508 if (monster_use_scroll (op, part, enemy, dir, &rv1)) 501 if (monster_use_scroll (op, part, enemy, dir, &rv1))
509 return 0; 502 return 0;
510 } 503 }
511 504
512 if (QUERY_FLAG (op, FLAG_READY_RANGE) && !(RANDOM () % 3)) 505 if (QUERY_FLAG (op, FLAG_READY_RANGE) && !(rndm (3)))
513 { 506 {
514 if (monster_use_range (op, part, enemy, dir)) 507 if (monster_use_range (op, part, enemy, dir))
515 return 0; 508 return 0;
516 } 509 }
517 if (QUERY_FLAG (op, FLAG_READY_SKILL) && !(RANDOM () % 3)) 510 if (QUERY_FLAG (op, FLAG_READY_SKILL) && !(rndm (3)))
518 { 511 {
519 if (monster_use_skill (op, rv.part, enemy, rv.direction)) 512 if (monster_use_skill (op, rv.part, enemy, rv.direction))
520 return 0; 513 return 0;
521 } 514 }
522 if (QUERY_FLAG (op, FLAG_READY_BOW) && !(RANDOM () % 2)) 515 if (QUERY_FLAG (op, FLAG_READY_BOW) && !(rndm (2)))
523 { 516 {
524 if (monster_use_bow (op, part, enemy, dir)) 517 if (monster_use_bow (op, part, enemy, dir))
525 return 0; 518 return 0;
526 } 519 }
527 } /* for processing of all parts */ 520 } /* for processing of all parts */
533 526
534 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))
535 dir = absdir (dir + 4); 528 dir = absdir (dir + 4);
536 529
537 if (QUERY_FLAG (op, FLAG_CONFUSED)) 530 if (QUERY_FLAG (op, FLAG_CONFUSED))
538 dir = absdir (dir + RANDOM () % 3 + RANDOM () % 3 - 2); 531 dir = absdir (dir + rndm (3) + rndm (3) - 2);
539 532
540 pre_att_dir = dir; /* remember the original direction */ 533 pre_att_dir = dir; /* remember the original direction */
541 534
542 if ((op->attack_movement & LO4) && !QUERY_FLAG (op, FLAG_SCARED)) 535 if ((op->attack_movement & LO4) && !QUERY_FLAG (op, FLAG_SCARED))
543 { 536 {
675can_hit (object *ob1, object *ob2, rv_vector * rv) 668can_hit (object *ob1, object *ob2, rv_vector * rv)
676{ 669{
677 object *more; 670 object *more;
678 rv_vector rv1; 671 rv_vector rv1;
679 672
680 if (QUERY_FLAG (ob1, FLAG_CONFUSED) && !(RANDOM () % 3)) 673 if (QUERY_FLAG (ob1, FLAG_CONFUSED) && !(rndm (3)))
681 return 0; 674 return 0;
682 675
683 if (abs (rv->distance_x) < 2 && abs (rv->distance_y) < 2) 676 if (abs (rv->distance_x) < 2 && abs (rv->distance_y) < 2)
684 return 1; 677 return 1;
685 678
794 return 0; /* Might hit owner with spell */ 787 return 0; /* Might hit owner with spell */
795 } 788 }
796 } 789 }
797 790
798 if (QUERY_FLAG (head, FLAG_CONFUSED)) 791 if (QUERY_FLAG (head, FLAG_CONFUSED))
799 dir = absdir (dir + RANDOM () % 3 + RANDOM () % 3 - 2); 792 dir = absdir (dir + rndm (3) + rndm (3) - 2);
800 793
801 /* If the monster hasn't already chosen a spell, choose one 794 /* If the monster hasn't already chosen a spell, choose one
802 * 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
803 * could be different by the time the monster goes again). 796 * could be different by the time the monster goes again).
804 */ 797 */
871 return 0; /* Might hit owner with spell */ 864 return 0; /* Might hit owner with spell */
872 } 865 }
873 } 866 }
874 867
875 if (QUERY_FLAG (head, FLAG_CONFUSED)) 868 if (QUERY_FLAG (head, FLAG_CONFUSED))
876 dir = absdir (dir + RANDOM () % 3 + RANDOM () % 3 - 2); 869 dir = absdir (dir + rndm (3) + rndm (3) - 2);
877 870
878 for (scroll = head->inv; scroll; scroll = scroll->below) 871 for (scroll = head->inv; scroll; scroll = scroll->below)
879 if (scroll->type == SCROLL && monster_should_cast_spell (head, scroll->inv)) 872 if (scroll->type == SCROLL && monster_should_cast_spell (head, scroll->inv))
880 break; 873 break;
881 874
920 913
921 if (dirdiff (dir, dir2) < 1) 914 if (dirdiff (dir, dir2) < 1)
922 return 0; /* Might hit owner with skill -thrown rocks for example ? */ 915 return 0; /* Might hit owner with skill -thrown rocks for example ? */
923 } 916 }
924 if (QUERY_FLAG (head, FLAG_CONFUSED)) 917 if (QUERY_FLAG (head, FLAG_CONFUSED))
925 dir = absdir (dir + RANDOM () % 3 + RANDOM () % 3 - 2); 918 dir = absdir (dir + rndm (3) + rndm (3) - 2);
926 919
927 /* skill selection - monster will use the next unused skill. 920 /* skill selection - monster will use the next unused skill.
928 * well...the following scenario will allow the monster to 921 * well...the following scenario will allow the monster to
929 * 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
930 * more skills available to monsters. 923 * more skills available to monsters.
964 957
965 if (dirdiff (dir, dir2) < 2) 958 if (dirdiff (dir, dir2) < 2)
966 return 0; /* Might hit owner with spell */ 959 return 0; /* Might hit owner with spell */
967 } 960 }
968 if (QUERY_FLAG (head, FLAG_CONFUSED)) 961 if (QUERY_FLAG (head, FLAG_CONFUSED))
969 dir = absdir (dir + RANDOM () % 3 + RANDOM () % 3 - 2); 962 dir = absdir (dir + rndm (3) + rndm (3) - 2);
970 963
971 for (wand = head->inv; wand != NULL; wand = wand->below) 964 for (wand = head->inv; wand != NULL; wand = wand->below)
972 { 965 {
973 if (wand->type == WAND) 966 if (wand->type == WAND)
974 { 967 {
1024 object *owner; 1017 object *owner;
1025 1018
1026 if (!(dir = path_to_player (part, pl, 0))) 1019 if (!(dir = path_to_player (part, pl, 0)))
1027 return 0; 1020 return 0;
1028 if (QUERY_FLAG (head, FLAG_CONFUSED)) 1021 if (QUERY_FLAG (head, FLAG_CONFUSED))
1029 dir = absdir (dir + RANDOM () % 3 + RANDOM () % 3 - 2); 1022 dir = absdir (dir + rndm (3) + rndm (3) - 2);
1030 1023
1031 if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = head->owner) != NULL) 1024 if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = head->owner) != NULL)
1032 { 1025 {
1033 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);
1034 1027
1524{ 1517{
1525 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 };
1526 if (++ob->move_status > 11) 1519 if (++ob->move_status > 11)
1527 ob->move_status = 0; 1520 ob->move_status = 0;
1528 if (!(move_object (ob, circle[ob->move_status]))) 1521 if (!(move_object (ob, circle[ob->move_status])))
1529 (void) move_object (ob, RANDOM () % 8 + 1); 1522 (void) move_object (ob, rndm (8) + 1);
1530} 1523}
1531 1524
1532void 1525void
1533circ2_move (object *ob) 1526circ2_move (object *ob)
1534{ 1527{
1535 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 };
1536 if (++ob->move_status > 19) 1529 if (++ob->move_status > 19)
1537 ob->move_status = 0; 1530 ob->move_status = 0;
1538 if (!(move_object (ob, circle[ob->move_status]))) 1531 if (!(move_object (ob, circle[ob->move_status])))
1539 (void) move_object (ob, RANDOM () % 8 + 1); 1532 (void) move_object (ob, rndm (8) + 1);
1540} 1533}
1541 1534
1542void 1535void
1543pace_movev (object *ob) 1536pace_movev (object *ob)
1544{ 1537{
1594void 1587void
1595rand_move (object *ob) 1588rand_move (object *ob)
1596{ 1589{
1597 int i; 1590 int i;
1598 1591
1599 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)))))
1600 for (i = 0; i < 5; i++) 1593 for (i = 0; i < 5; i++)
1601 if (move_object (ob, ob->move_status = RANDOM () % 8 + 1)) 1594 if (move_object (ob, ob->move_status = rndm (8) + 1))
1602 return; 1595 return;
1603} 1596}
1604 1597
1605void 1598void
1606check_earthwalls (object *op, maptile *m, int x, int y) 1599check_earthwalls (object *op, maptile *m, int x, int y)
1651 tmp = op; 1644 tmp = op;
1652 1645
1653 /* 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
1654 * marked item and throw it to the enemy. 1647 * marked item and throw it to the enemy.
1655 */ 1648 */
1656
1657 for (tmp = op->inv; tmp; tmp = tmp->below) 1649 for (tmp = op->inv; tmp; tmp = tmp->below)
1658 { 1650 {
1659
1660 /* Can't throw invisible objects or items that are applied */ 1651 /* Can't throw invisible objects or items that are applied */
1661 if (tmp->invisible || QUERY_FLAG (tmp, FLAG_APPLIED)) 1652 if (tmp->invisible || QUERY_FLAG (tmp, FLAG_APPLIED))
1662 continue; 1653 continue;
1663 1654
1664 if (QUERY_FLAG (tmp, FLAG_IS_THROWN)) 1655 if (QUERY_FLAG (tmp, FLAG_IS_THROWN))
1787 /* ah, we are within range, detected? take cases */ 1778 /* ah, we are within range, detected? take cases */
1788 if (!enemy->invisible) /* enemy in dark squares... are seen! */ 1779 if (!enemy->invisible) /* enemy in dark squares... are seen! */
1789 return 1; 1780 return 1;
1790 1781
1791 /* hidden or low-quality invisible */ 1782 /* hidden or low-quality invisible */
1792 if (enemy->hide && (rv->distance <= 1) && (RANDOM () % 100 <= hide_discovery)) 1783 if (enemy->hide && (rv->distance <= 1) && (rndm (100) <= hide_discovery))
1793 { 1784 {
1794 make_visible (enemy); 1785 make_visible (enemy);
1795 /* inform players of new status */ 1786 /* inform players of new status */
1796 if (enemy->type == PLAYER && player_can_view (enemy, op)) 1787 if (enemy->type == PLAYER && player_can_view (enemy, op))
1797 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);
1804 * do something to you. Decreasing the duration of invisible 1795 * do something to you. Decreasing the duration of invisible
1805 * 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
1806 * can then basically negate the spell. The spell isn't negated - 1797 * can then basically negate the spell. The spell isn't negated -
1807 * they just know where you are! 1798 * they just know where you are!
1808 */ 1799 */
1809 if ((RANDOM () % 50) <= hide_discovery) 1800 if ((rndm (50)) <= hide_discovery)
1810 { 1801 {
1811 if (enemy->type == PLAYER) 1802 if (enemy->type == PLAYER)
1812 { 1803 {
1813 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));
1814 } 1805 }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines