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.72 by root, Fri Nov 6 12:27:06 2009 UTC vs.
Revision 1.82 by root, Sun Mar 28 16:17:28 2010 UTC

1/* 1/*
2 * This file is part of Deliantra, the Roguelike Realtime MMORPG. 2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 * 3 *
4 * Copyright (©) 2005,2006,2007,2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team 4 * Copyright (©) 2005,2006,2007,2008,2009,2010 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team 5 * Copyright (©) 2002 Mark Wedel & Crossfire Development Team
6 * Copyright (©) 1992,2007 Frank Tore Johansen 6 * Copyright (©) 1992 Frank Tore Johansen
7 * 7 *
8 * Deliantra is free software: you can redistribute it and/or modify it under 8 * Deliantra is free software: you can redistribute it and/or modify it under
9 * the terms of the Affero GNU General Public License as published by the 9 * the terms of the Affero GNU General Public License as published by the
10 * Free Software Foundation, either version 3 of the License, or (at your 10 * Free Software Foundation, either version 3 of the License, or (at your
11 * option) any later version. 11 * option) any later version.
153 * Currently, only move_monster calls this function. 153 * Currently, only move_monster calls this function.
154 * Fix function so that we always make calls to get_rangevector 154 * Fix function so that we always make calls to get_rangevector
155 * if we have a valid target - function as not doing so in 155 * if we have a valid target - function as not doing so in
156 * many cases. 156 * many cases.
157 */ 157 */
158object * 158static object *
159find_enemy (object *npc, rv_vector * rv) 159find_enemy (object *npc, rv_vector * rv)
160{ 160{
161 object *attacker, *tmp = NULL; 161 object *attacker, *tmp = NULL;
162 162
163 attacker = npc->attacked_by; /* save this for later use. This can be a attacker. */ 163 attacker = npc->attacked_by; /* save this for later use. This can be a attacker. */
231/* Sees if this monster should wake up. 231/* Sees if this monster should wake up.
232 * Currently, this is only called from move_monster, and 232 * Currently, this is only called from move_monster, and
233 * if enemy is set, then so should be rv. 233 * if enemy is set, then so should be rv.
234 * returns 1 if the monster should wake up, 0 otherwise. 234 * returns 1 if the monster should wake up, 0 otherwise.
235 */ 235 */
236int 236static int
237check_wakeup (object *op, object *enemy, rv_vector *rv) 237check_wakeup (object *op, object *enemy, rv_vector *rv)
238{ 238{
239 /* Trim work - if no enemy, no need to do anything below */ 239 /* Trim work - if no enemy, no need to do anything below */
240 if (!enemy) 240 if (!enemy)
241 return 0; 241 return 0;
272 } 272 }
273 273
274 return 0; 274 return 0;
275} 275}
276 276
277int 277static int
278move_randomly (object *op) 278move_randomly (object *op)
279{ 279{
280 /* Give up to 15 chances for a monster to move randomly */ 280 /* Give up to 15 chances for a monster to move randomly */
281 for (int i = 0; i < 15; i++) 281 for (int i = 0; i < 15; i++)
282 if (move_object (op, rndm (8) + 1)) 282 if (op->move (rndm (8) + 1))
283 return 1; 283 return 1;
284 284
285 return 0; 285 return 0;
286} 286}
287 287
403 next = tmp->below; 403 next = tmp->below;
404 if (monster_can_pick (monster, tmp)) 404 if (monster_can_pick (monster, tmp))
405 { 405 {
406 tmp->remove (); 406 tmp->remove ();
407 tmp = insert_ob_in_ob (tmp, monster); 407 tmp = insert_ob_in_ob (tmp, monster);
408 (void) monster_check_apply (monster, tmp); 408 monster_check_apply (monster, tmp);
409 } 409 }
410
410 /* We could try to re-establish the cycling, of the space, but probably 411 /* We could try to re-establish the cycling, of the space, but probably
411 * not a big deal to just bail out. 412 * not a big deal to just bail out.
412 */ 413 */
413 if (next && next->destroyed ()) 414 if (next && next->destroyed ())
414 return; 415 return;
785 static int circle[12] = { 3, 3, 4, 5, 5, 6, 7, 7, 8, 1, 1, 2 }; 786 static int circle[12] = { 3, 3, 4, 5, 5, 6, 7, 7, 8, 1, 1, 2 };
786 787
787 if (++ob->move_status > 11) 788 if (++ob->move_status > 11)
788 ob->move_status = 0; 789 ob->move_status = 0;
789 790
790 if (!(move_object (ob, circle[ob->move_status]))) 791 if (!(ob->move (circle[ob->move_status])))
791 move_object (ob, rndm (8) + 1); 792 ob->move (rndm (8) + 1);
792} 793}
793 794
794static void 795static void
795circ2_move (object *ob) 796circ2_move (object *ob)
796{ 797{
797 static int circle[20] = { 3, 3, 3, 4, 4, 5, 5, 5, 6, 6, 7, 7, 7, 8, 8, 1, 1, 1, 2, 2 }; 798 static int circle[20] = { 3, 3, 3, 4, 4, 5, 5, 5, 6, 6, 7, 7, 7, 8, 8, 1, 1, 1, 2, 2 };
798 799
799 if (++ob->move_status > 19) 800 if (++ob->move_status > 19)
800 ob->move_status = 0; 801 ob->move_status = 0;
801 802
802 if (!(move_object (ob, circle[ob->move_status]))) 803 if (!(ob->move (circle[ob->move_status])))
803 move_object (ob, rndm (8) + 1); 804 ob->move (rndm (8) + 1);
804} 805}
805 806
806static void 807static void
807pace_movev (object *ob) 808pace_movev (object *ob)
808{ 809{
809 if (ob->move_status++ > 6) 810 if (ob->move_status++ > 6)
810 ob->move_status = 0; 811 ob->move_status = 0;
811 812
812 if (ob->move_status < 4) 813 if (ob->move_status < 4)
813 move_object (ob, 5); 814 ob->move (5);
814 else 815 else
815 move_object (ob, 1); 816 ob->move (1);
816} 817}
817 818
818static void 819static void
819pace_moveh (object *ob) 820pace_moveh (object *ob)
820{ 821{
821 if (ob->move_status++ > 6) 822 if (ob->move_status++ > 6)
822 ob->move_status = 0; 823 ob->move_status = 0;
823 824
824 if (ob->move_status < 4) 825 if (ob->move_status < 4)
825 move_object (ob, 3); 826 ob->move (3);
826 else 827 else
827 move_object (ob, 7); 828 ob->move (7);
828} 829}
829 830
830static void 831static void
831pace2_movev (object *ob) 832pace2_movev (object *ob)
832{ 833{
833 if (ob->move_status++ > 16) 834 if (ob->move_status++ > 16)
834 ob->move_status = 0; 835 ob->move_status = 0;
835 836
836 if (ob->move_status < 6) 837 if (ob->move_status < 6)
837 move_object (ob, 5); 838 ob->move (5);
838 else if (ob->move_status < 8) 839 else if (ob->move_status < 8)
839 return; 840 return;
840 else if (ob->move_status < 13) 841 else if (ob->move_status < 13)
841 move_object (ob, 1); 842 ob->move (1);
842 else 843 else
843 return; 844 return;
844} 845}
845 846
846static void 847static void
848{ 849{
849 if (ob->move_status++ > 16) 850 if (ob->move_status++ > 16)
850 ob->move_status = 0; 851 ob->move_status = 0;
851 852
852 if (ob->move_status < 6) 853 if (ob->move_status < 6)
853 move_object (ob, 3); 854 ob->move (3);
854 else if (ob->move_status < 8) 855 else if (ob->move_status < 8)
855 return; 856 return;
856 else if (ob->move_status < 13) 857 else if (ob->move_status < 13)
857 move_object (ob, 7); 858 ob->move (7);
858 else 859 else
859 return; 860 return;
860} 861}
861 862
862static void 863static void
863rand_move (object *ob) 864rand_move (object *ob)
864{ 865{
865 if (ob->move_status < 1 || ob->move_status > 8 || !(move_object (ob, ob->move_status || !(rndm (9))))) 866 if (ob->move_status < 1 || ob->move_status > 8 || !(ob->move (ob->move_status || !(rndm (9)))))
866 for (int i = 0; i < 5; i++) 867 for (int i = 0; i < 5; i++)
867 if (move_object (ob, ob->move_status = rndm (8) + 1)) 868 if (ob->move (ob->move_status = rndm (8) + 1))
868 return; 869 return;
869} 870}
870 871
871#define MAX_KNOWN_SPELLS 20 872#define MAX_KNOWN_SPELLS 20
872 873
873/* Returns a randomly selected spell. This logic is still 874/* Returns a randomly selected spell. This logic is still
874 * less than ideal. This code also only seems to deal with 875 * less than ideal. This code also only seems to deal with
875 * wizard spells, as the check is against sp, and not grace. 876 * wizard spells, as the check is against sp, and not grace.
876 * can mosnters know cleric spells? 877 * can mosnters know cleric spells?
877 */ 878 */
878object * 879static object *
879monster_choose_random_spell (object *monster) 880monster_choose_random_spell (object *monster)
880{ 881{
881 object *altern[MAX_KNOWN_SPELLS]; 882 object *altern[MAX_KNOWN_SPELLS];
882 int i = 0; 883 int i = 0;
883 884
906 * part is the part of the monster we are checking against. 907 * part is the part of the monster we are checking against.
907 * pl is the target. 908 * pl is the target.
908 * dir is the direction to case. 909 * dir is the direction to case.
909 * rv is the vector which describes where the enemy is. 910 * rv is the vector which describes where the enemy is.
910 */ 911 */
911int 912static int
912monster_cast_spell (object *head, object *part, object *pl, int dir, rv_vector * rv) 913monster_cast_spell (object *head, object *part, object *pl, int dir, rv_vector * rv)
913{ 914{
914 object *spell_item; 915 object *spell_item;
915 object *owner; 916 object *owner;
916 rv_vector rv1; 917 rv_vector rv1;
982 head->spellitem = NULL; 983 head->spellitem = NULL;
983 984
984 return cast_spell (part, part, dir, spell_item, NULL); 985 return cast_spell (part, part, dir, spell_item, NULL);
985} 986}
986 987
987int 988static int
988monster_use_scroll (object *head, object *part, object *pl, int dir, rv_vector * rv) 989monster_use_scroll (object *head, object *part, object *pl, int dir, rv_vector * rv)
989{ 990{
990 object *scroll; 991 object *scroll;
991 object *owner; 992 object *owner;
992 rv_vector rv1; 993 rv_vector rv1;
1040 * The skills we are treating here are all but those. -b.t. 1041 * The skills we are treating here are all but those. -b.t.
1041 * 1042 *
1042 * At the moment this is only useful for throwing, perhaps for 1043 * At the moment this is only useful for throwing, perhaps for
1043 * stealing. TODO: This should be more integrated in the game. -MT, 25.11.01 1044 * stealing. TODO: This should be more integrated in the game. -MT, 25.11.01
1044 */ 1045 */
1045int 1046static int
1046monster_use_skill (object *head, object *part, object *pl, int dir) 1047monster_use_skill (object *head, object *part, object *pl, int dir)
1047{ 1048{
1048 object *skill, *owner; 1049 object *skill, *owner;
1049 1050
1050 if (!(dir = path_to_player (part, pl, 0))) 1051 if (!(dir = path_to_player (part, pl, 0)))
1059 } 1060 }
1060 1061
1061 if (QUERY_FLAG (head, FLAG_CONFUSED)) 1062 if (QUERY_FLAG (head, FLAG_CONFUSED))
1062 dir = absdir (dir + rndm (3) + rndm (3) - 2); 1063 dir = absdir (dir + rndm (3) + rndm (3) - 2);
1063 1064
1065 object *new_skill = 0;
1066
1064 /* skill selection - monster will use the next unused skill. 1067 // skill selection - monster will use the last unused skill
1065 * well...the following scenario will allow the monster to 1068 // and rotate, eventually cycling through all skills.
1066 * toggle between 2 skills. One day it would be nice to make
1067 * more skills available to monsters.
1068 */
1069 for (skill = head->inv; skill; skill = skill->below) 1069 for (skill = head->inv; skill; skill = skill->below)
1070 if (skill->type == SKILL && skill != head->chosen_skill) 1070 if (skill->type == SKILL && skill != head->chosen_skill)
1071 { 1071 new_skill = skill;
1072
1073 if (new_skill)
1072 head->chosen_skill = skill; 1074 splay (head->chosen_skill = new_skill);
1073 break;
1074 }
1075
1076 if (!skill && !head->chosen_skill) 1075 else if (!head->chosen_skill)
1077 { 1076 {
1078 LOG (llevDebug, "Error: Monster %s (%d) has FLAG_READY_SKILL without skill.\n", &head->name, head->count); 1077 LOG (llevDebug, "Error: Monster %s (%d) has FLAG_READY_SKILL without skill.\n", &head->name, head->count);
1079 CLEAR_FLAG (head, FLAG_READY_SKILL); 1078 CLEAR_FLAG (head, FLAG_READY_SKILL);
1080 return 0; 1079 return 0;
1081 } 1080 }
1083 /* use skill */ 1082 /* use skill */
1084 return do_skill (head, part, head->chosen_skill, dir, NULL); 1083 return do_skill (head, part, head->chosen_skill, dir, NULL);
1085} 1084}
1086 1085
1087/* Monster will use a ranged spell attack. */ 1086/* Monster will use a ranged spell attack. */
1088int 1087static int
1089monster_use_range (object *head, object *part, object *pl, int dir) 1088monster_use_range (object *head, object *part, object *pl, int dir)
1090{ 1089{
1091 object *wand, *owner; 1090 object *wand, *owner;
1092 int at_least_one = 0; 1091 int at_least_one = 0;
1093 1092
1130 } 1129 }
1131 else if (wand->type == ROD || wand->type == HORN) 1130 else if (wand->type == ROD || wand->type == HORN)
1132 { 1131 {
1133 /* Found rod/horn, let's use it if possible */ 1132 /* Found rod/horn, let's use it if possible */
1134 at_least_one = 1; 1133 at_least_one = 1;
1135 if (wand->stats.hp < MAX (wand->inv->stats.sp, wand->inv->stats.grace)) 1134 if (wand->stats.hp < max (wand->inv->stats.sp, wand->inv->stats.grace))
1136 continue; 1135 continue;
1137 1136
1138 /* drain charge before casting spell - can be a case where the 1137 /* drain charge before casting spell - can be a case where the
1139 * spell destroys the monster, and rod, so if done after, results 1138 * spell destroys the monster, and rod, so if done after, results
1140 * in crash. 1139 * in crash.
1153 LOG (llevError, "Error: Monster %s (%d) HAS_READY_RANGE() without wand/horn/rod.\n", &head->name, head->count); 1152 LOG (llevError, "Error: Monster %s (%d) HAS_READY_RANGE() without wand/horn/rod.\n", &head->name, head->count);
1154 CLEAR_FLAG (head, FLAG_READY_RANGE); 1153 CLEAR_FLAG (head, FLAG_READY_RANGE);
1155 return 0; 1154 return 0;
1156} 1155}
1157 1156
1158int 1157static int
1159monster_use_bow (object *head, object *part, object *pl, int dir) 1158monster_use_bow (object *head, object *part, object *pl, int dir)
1160{ 1159{
1161 object *owner; 1160 object *owner;
1162 1161
1163 if (!(dir = path_to_player (part, pl, 0))) 1162 if (!(dir = path_to_player (part, pl, 0)))
1180} 1179}
1181 1180
1182void 1181void
1183npc_call_help (object *op) 1182npc_call_help (object *op)
1184{ 1183{
1185 unordered_mapwalk (op, -7, -7, 7, 7) 1184 unordered_mapwalk (mapwalk_buf, op, -7, -7, 7, 7)
1186 { 1185 {
1187 mapspace &ms = m->at (nx, ny); 1186 mapspace &ms = m->at (nx, ny);
1188 1187
1189 /* If nothing alive on this space, no need to search the space. */ 1188 /* If nothing alive on this space, no need to search the space. */
1190 if (!(ms.flags () & P_IS_ALIVE)) 1189 if (!(ms.flags () & P_IS_ALIVE))
1292 * 1291 *
1293 * Cast to sint32 before comparing to maxhp since otherwise an (sint16) 1292 * Cast to sint32 before comparing to maxhp since otherwise an (sint16)
1294 * overflow might produce monsters with negative hp. 1293 * overflow might produce monsters with negative hp.
1295 */ 1294 */
1296 1295
1297 op->last_heal += (int) ((float) (8 * op->stats.Con) / FABS (op->speed)); 1296 op->last_heal += (int) ((float) (8 * op->stats.Con) / op->speed);
1298 op->stats.hp = MIN ((sint32) op->stats.hp + op->last_heal / 32, op->stats.maxhp); /* causes Con/4 hp/tick */ 1297 op->stats.hp = min ((sint32) op->stats.hp + op->last_heal / 32, op->stats.maxhp); /* causes Con/4 hp/tick */
1299 op->last_heal %= 32; 1298 op->last_heal %= 32;
1300 1299
1301 /* So if the monster has gained enough HP that they are no longer afraid */ 1300 /* So if the monster has gained enough HP that they are no longer afraid */
1302 if (QUERY_FLAG (op, FLAG_RUN_AWAY) && op->stats.hp >= (signed short)(((float)op->run_away / 100.f) * (float)op->stats.maxhp)) 1301 if (QUERY_FLAG (op, FLAG_RUN_AWAY) && op->stats.hp >= (signed short)(((float)op->run_away / 100.f) * (float)op->stats.maxhp))
1303 CLEAR_FLAG (op, FLAG_RUN_AWAY); 1302 CLEAR_FLAG (op, FLAG_RUN_AWAY);
1316 * 1315 *
1317 * Cast to sint32 before comparing to maxhp since otherwise an (sint16) 1316 * Cast to sint32 before comparing to maxhp since otherwise an (sint16)
1318 * overflow might produce monsters with negative sp. 1317 * overflow might produce monsters with negative sp.
1319 */ 1318 */
1320 1319
1321 op->last_sp += (int) ((float) (8 * op->stats.Pow) / fabsf (op->speed)); 1320 op->last_sp += (int) ((float) (8 * op->stats.Pow) / op->speed);
1322 op->stats.sp = min (op->stats.sp + op->last_sp / 128, op->stats.maxsp); /* causes Pow/16 sp/tick */ 1321 op->stats.sp = min (op->stats.sp + op->last_sp / 128, op->stats.maxsp); /* causes Pow/16 sp/tick */
1323 op->last_sp %= 128; 1322 op->last_sp %= 128;
1324 } 1323 }
1325 1324
1326 /* this should probably get modified by many more values. 1325 /* this should probably get modified by many more values.
1522 dir = sdir; 1521 dir = sdir;
1523 else if (smell) 1522 else if (smell)
1524 { 1523 {
1525 // no better smell found, so assume the player jumped, and erase this smell 1524 // no better smell found, so assume the player jumped, and erase this smell
1526 //printf ("erasing smell %d\n", op->ms ().smell);//D 1525 //printf ("erasing smell %d\n", op->ms ().smell);//D
1527 unordered_mapwalk (op, -1, -1, 1, 1) 1526 unordered_mapwalk (mapwalk_buf, op, -1, -1, 1, 1)
1528 m->at (nx, ny).smell = 0; 1527 m->at (nx, ny).smell = 0;
1529 } 1528 }
1530 } 1529 }
1531 1530
1532//+GPL 1531//+GPL
1579 if (!dir) 1578 if (!dir)
1580 return 0; 1579 return 0;
1581 1580
1582 if (!QUERY_FLAG (op, FLAG_STAND_STILL)) 1581 if (!QUERY_FLAG (op, FLAG_STAND_STILL))
1583 { 1582 {
1584 if (move_object (op, dir)) /* Can the monster move directly toward player? */ 1583 if (op->move (dir)) /* Can the monster move directly toward player? */
1585 { 1584 {
1586 /* elmex: Turn our monster after it moved if it has DISTATT attack */ 1585 /* elmex: Turn our monster after it moved if it has DISTATT attack */
1587 if ((op->attack_movement & LO4) == DISTATT) 1586 if ((op->attack_movement & LO4) == DISTATT)
1588 op->direction = pre_att_dir; 1587 op->direction = pre_att_dir;
1589 1588
1598 for (diff = 1; diff <= maxdiff; diff++) 1597 for (diff = 1; diff <= maxdiff; diff++)
1599 { 1598 {
1600 /* try different detours */ 1599 /* try different detours */
1601 int m = 1 - rndm (2) * 2; /* Try left or right first? */ 1600 int m = 1 - rndm (2) * 2; /* Try left or right first? */
1602 1601
1603 if (move_object (op, absdir (dir + diff * m)) || move_object (op, absdir (dir - diff * m))) 1602 if (op->move (absdir (dir + diff * m)) || op->move (absdir (dir - diff * m)))
1604 return 0; 1603 return 0;
1605 } 1604 }
1606 } 1605 }
1607 } /* if monster is not standing still */ 1606 } /* if monster is not standing still */
1608 1607
1839 1838
1840 if (op->glow_radius > 0) 1839 if (op->glow_radius > 0)
1841 return 1; 1840 return 1;
1842 1841
1843 if (op->map) 1842 if (op->map)
1844 unordered_mapwalk (op, -MAX_LIGHT_RADIUS, -MAX_LIGHT_RADIUS, MAX_LIGHT_RADIUS, MAX_LIGHT_RADIUS) 1843 unordered_mapwalk (mapwalk_buf, op, -MAX_LIGHT_RADIUS, -MAX_LIGHT_RADIUS, MAX_LIGHT_RADIUS, MAX_LIGHT_RADIUS)
1845 { 1844 {
1846 /* Check the spaces with the max light radius to see if any of them 1845 /* Check the spaces with the max light radius to see if any of them
1847 * have lights, and if any of them light the player enough, then return 1. 1846 * have lights, and if any of them light the player enough, then return 1.
1848 */ 1847 */
1849 int light = m->at (nx, ny).light; 1848 int light = m->at (nx, ny).light;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines