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.96 by root, Wed Nov 16 23:42:02 2016 UTC vs.
Revision 1.101 by root, Wed Dec 5 19:03:27 2018 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 (©) 2017,2018 Marc Alexander Lehmann / the Deliantra team
4 * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016 Marc Alexander Lehmann / Robin Redeker / the Deliantra team 5 * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 * Copyright (©) 2002 Mark Wedel & Crossfire Development Team 6 * Copyright (©) 2002 Mark Wedel & Crossfire Development Team
6 * Copyright (©) 1992 Frank Tore Johansen 7 * Copyright (©) 1992 Frank Tore Johansen
7 * 8 *
8 * Deliantra is free software: you can redistribute it and/or modify it under 9 * Deliantra is free software: you can redistribute it and/or modify it under
51 npc->enemy = npc->owner->enemy; 52 npc->enemy = npc->owner->enemy;
52 } 53 }
53 54
54 /* periodically, a monster may change its target. Also, if the object 55 /* periodically, a monster may change its target. Also, if the object
55 * has been destroyed, etc, clear the enemy. 56 * has been destroyed, etc, clear the enemy.
56 * TODO: this should be changed, because it invokes to attack forced or 57 * TODO: this should be changed, because it invokes to attack forced or
57 * attacked monsters to leave the attacker alone, before it is destroyed 58 * attacked monsters to leave the attacker alone, before it is destroyed
58 */ 59 */
59 /* I had removed the random target leave, this invokes problems with friendly 60 /* I had removed the random target leave, this invokes problems with friendly
60 * objects, getting attacked and defending herself - they don't try to attack 61 * objects, getting attacked and defending herself - they don't try to attack
61 * again then but perhaps get attack on and on 62 * again then but perhaps get attack on and on
62 * If we include a aggravated flag in , we can handle evil vs evil and good vs good 63 * If we include a aggravated flag in , we can handle evil vs evil and good vs good
63 * too. */ 64 * too. */
64 65
65 if (npc->enemy) 66 if (npc->enemy)
66 { 67 {
105 * of direction, revisit them after looking at all the other spaces. 106 * of direction, revisit them after looking at all the other spaces.
106 * 107 *
107 * Note that being this may skip some number of spaces, it will 108 * Note that being this may skip some number of spaces, it will
108 * not necessarily find the nearest living creature - it basically 109 * not necessarily find the nearest living creature - it basically
109 * chooses one from within a 3 space radius, and since it skips 110 * chooses one from within a 3 space radius, and since it skips
110 * the first few directions, it could very well choose something 111 * the first few directions, it could very well choose something
111 * 3 spaces away even though something directly north is closer. 112 * 3 spaces away even though something directly north is closer.
112 * 113 *
113 * this function is map tile aware. 114 * this function is map tile aware.
114 */ 115 */
115object * 116object *
125 for (i = 0; i < SIZEOFFREE; i++) 126 for (i = 0; i < SIZEOFFREE; i++)
126 { 127 {
127 /* modified to implement smart searching using search_arr 128 /* modified to implement smart searching using search_arr
128 * guidance array to determine direction of search order 129 * guidance array to determine direction of search order
129 */ 130 */
130 nx = npc->x + freearr_x[search_arr[i]]; 131 nx = npc->x + DIRX (search_arr[i]);
131 ny = npc->y + freearr_y[search_arr[i]]; 132 ny = npc->y + DIRY (search_arr[i]);
132 m = npc->map; 133 m = npc->map;
133 134
134 mflags = get_map_flags (m, &m, nx, ny, &nx, &ny); 135 mflags = get_map_flags (m, &m, nx, ny, &nx, &ny);
135 136
136 if (mflags & P_OUT_OF_MAP) 137 if (mflags & P_OUT_OF_MAP)
173 174
174 return tmp; 175 return tmp;
175 } 176 }
176 177
177 /* Here is the main enemy selection. 178 /* Here is the main enemy selection.
178 * We want this: if there is an enemy, attack him until its not possible or 179 * We want this: if there is an enemy, attack him until its not possible or
179 * one of both is dead. 180 * one of both is dead.
180 * If we have no enemy and we are... 181 * If we have no enemy and we are...
181 * a monster: try to find a player, a pet or a friendly monster 182 * a monster: try to find a player, a pet or a friendly monster
182 * a friendly: only target a monster which is targeting you first or targeting a player 183 * a friendly: only target a monster which is targeting you first or targeting a player
183 * a neutral: fight a attacker (but there should be none), then do nothing 184 * a neutral: fight a attacker (but there should be none), then do nothing
250 radius = MIN_MON_RADIUS; 251 radius = MIN_MON_RADIUS;
251 else if (op->map 252 else if (op->map
252 && !enemy->invisible 253 && !enemy->invisible
253 && !stand_in_light (enemy) 254 && !stand_in_light (enemy)
254 && (!op->flag[FLAG_SEE_IN_DARK] || !op->flag [FLAG_SEE_INVISIBLE])) 255 && (!op->flag[FLAG_SEE_IN_DARK] || !op->flag [FLAG_SEE_INVISIBLE]))
255 /* This covers the situation where the monster is in the dark 256 /* This covers the situation where the monster is in the dark
256 * and has an enemy. If the enemy has no carried light (or isnt 257 * and has an enemy. If the enemy has no carried light (or isnt
257 * glowing!) then the monster has trouble finding the enemy. 258 * glowing!) then the monster has trouble finding the enemy.
258 * Remember we already checked to see if the monster can see in 259 * Remember we already checked to see if the monster can see in
259 * the dark. */ 260 * the dark. */
260 min_it (radius, MIN_MON_RADIUS + MAX_DARKNESS - op->map->darklevel ()); 261 min_it (radius, MIN_MON_RADIUS + MAX_DARKNESS - op->map->darklevel ());
261 262
262 if (enemy->flag [FLAG_STEALTH]) 263 if (enemy->flag [FLAG_STEALTH])
263 radius = radius / 2 + 1; 264 radius = radius / 2 + 1;
371 flag = 1; 372 flag = 1;
372 break; 373 break;
373 } 374 }
374 } 375 }
375 376
376 if (((!(monster->pick_up & 32)) && flag) || ((monster->pick_up & 32) && (!flag))) 377 if (((!(monster->pick_up & 32)) && flag) || ((monster->pick_up & 32) && !flag))
377 return 1; 378 return 1;
378 379
379 return 0; 380 return 0;
380} 381}
381 382
395 * affect stacking on this space. 396 * affect stacking on this space.
396 */ 397 */
397static void 398static void
398monster_check_pickup (object *monster) 399monster_check_pickup (object *monster)
399{ 400{
400 object *tmp, *next;
401
402 for (tmp = monster->below; tmp != NULL; tmp = next) 401 for (object *next, *tmp = monster->below; tmp; tmp = next)
403 { 402 {
404 next = tmp->below; 403 next = tmp->below;
404
405 if (monster_can_pick (monster, tmp)) 405 if (monster_can_pick (monster, tmp))
406 { 406 {
407 tmp->remove (); 407 tmp->remove ();
408 tmp = insert_ob_in_ob (tmp, monster); 408 tmp = insert_ob_in_ob (tmp, monster);
409 monster_check_apply (monster, tmp); 409 monster_check_apply (monster, tmp);
536 val = (item->resist[ATNR_PHYSICAL] - other_armour->resist[ATNR_PHYSICAL]) / 5; 536 val = (item->resist[ATNR_PHYSICAL] - other_armour->resist[ATNR_PHYSICAL]) / 5;
537 val += (item->magic - other_armour->magic) * 3; 537 val += (item->magic - other_armour->magic) * 3;
538 538
539 /* for the other protections, do weigh them very much in the equation - 539 /* for the other protections, do weigh them very much in the equation -
540 * it is the armor protection which is most important, because there is 540 * it is the armor protection which is most important, because there is
541 * no good way to know what the player may attack the monster with. 541 * no good way to know what the player may attack the monster with.
542 * So if the new item has better protection than the old, give that higher 542 * So if the new item has better protection than the old, give that higher
543 * value. If the reverse, then decrease the value of this item some. 543 * value. If the reverse, then decrease the value of this item some.
544 */ 544 */
545 for (i = 1; i < NROFATTACKS; i++) 545 for (i = 1; i < NROFATTACKS; i++)
546 { 546 {
652 mon->set_flag (FLAG_READY_SKILL); 652 mon->set_flag (FLAG_READY_SKILL);
653 return; 653 return;
654 } 654 }
655 655
656 /* if we don't match one of the above types, return now. 656 /* if we don't match one of the above types, return now.
657 * can_apply_object will say that we can apply things like flesh, 657 * can_apply_object will say that we can apply things like flesh,
658 * bolts, and whatever else, because it only checks against the 658 * bolts, and whatever else, because it only checks against the
659 * body_info locations. 659 * body_info locations.
660 */ 660 */
661 if (!flag) 661 if (!flag)
662 return; 662 return;
916 object *owner; 916 object *owner;
917 rv_vector rv1; 917 rv_vector rv1;
918 918
919 /* If you want monsters to cast spells over friends, this spell should 919 /* If you want monsters to cast spells over friends, this spell should
920 * be removed. It probably should be in most cases, since monsters still 920 * be removed. It probably should be in most cases, since monsters still
921 * don't care about residual effects (ie, casting a cone which may have a 921 * don't care about residual effects (ie, casting a cone which may have a
922 * clear path to the player, the side aspects of the code will still hit 922 * clear path to the player, the side aspects of the code will still hit
923 * other monsters) 923 * other monsters)
924 */ 924 */
925 if (!(dir = path_to_player (part, pl, 0))) 925 if (!(dir = path_to_player (part, pl, 0)))
926 return 0; 926 return 0;
991 object *owner; 991 object *owner;
992 rv_vector rv1; 992 rv_vector rv1;
993 993
994 /* If you want monsters to cast spells over friends, this spell should 994 /* If you want monsters to cast spells over friends, this spell should
995 * be removed. It probably should be in most cases, since monsters still 995 * be removed. It probably should be in most cases, since monsters still
996 * don't care about residual effects (ie, casting a cone which may have a 996 * don't care about residual effects (ie, casting a cone which may have a
997 * clear path to the player, the side aspects of the code will still hit 997 * clear path to the player, the side aspects of the code will still hit
998 * other monsters) 998 * other monsters)
999 */ 999 */
1000 if (!(dir = path_to_player (part, pl, 0))) 1000 if (!(dir = path_to_player (part, pl, 0)))
1001 return 0; 1001 return 0;
1033 1033
1034/* monster_use_skill()-implemented 95-04-28 to allow monster skill use. 1034/* monster_use_skill()-implemented 95-04-28 to allow monster skill use.
1035 * Note that monsters do not need the skills SK_MELEE_WEAPON and 1035 * Note that monsters do not need the skills SK_MELEE_WEAPON and
1036 * SK_MISSILE_WEAPON to make those respective attacks, if we 1036 * SK_MISSILE_WEAPON to make those respective attacks, if we
1037 * required that we would drastically increase the memory 1037 * required that we would drastically increase the memory
1038 * requirements of CF!! 1038 * requirements of CF!!
1039 * 1039 *
1040 * The skills we are treating here are all but those. -b.t. 1040 * The skills we are treating here are all but those. -b.t.
1041 * 1041 *
1042 * At the moment this is only useful for throwing, perhaps for 1042 * 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 1043 * stealing. TODO: This should be more integrated in the game. -MT, 25.11.01
1044 */ 1044 */
1045static int 1045static int
1284 if (op->stats.Con > 0 && op->stats.hp < op->stats.maxhp) 1284 if (op->stats.Con > 0 && op->stats.hp < op->stats.maxhp)
1285 { 1285 {
1286 /* last heal is in funny units. Dividing by speed puts 1286 /* last heal is in funny units. Dividing by speed puts
1287 * the regeneration rate on a basis of time instead of 1287 * the regeneration rate on a basis of time instead of
1288 * #moves the monster makes. The scaling by 8 is 1288 * #moves the monster makes. The scaling by 8 is
1289 * to capture 8th's of a hp fraction regens 1289 * to capture 8th's of a hp fraction regens
1290 */ 1290 */
1291 uint32_t last_heal = op->last_heal + op->stats.Con * 8 / op->speed; 1291 uint32_t last_heal = op->last_heal + op->stats.Con * 8 / op->speed;
1292 op->stats.hp = min (op->stats.hp + last_heal / 32, op->stats.maxhp); /* causes Con/4 hp/tick */ 1292 op->stats.hp = min (op->stats.hp + last_heal / 32, op->stats.maxhp); /* causes Con/4 hp/tick */
1293 op->last_heal = last_heal % 32; 1293 op->last_heal = last_heal % 32;
1294 1294
1301 if (op->stats.Pow > 0 && op->stats.sp < op->stats.maxsp) 1301 if (op->stats.Pow > 0 && op->stats.sp < op->stats.maxsp)
1302 { 1302 {
1303 /* last_sp is in funny units. Dividing by speed puts 1303 /* last_sp is in funny units. Dividing by speed puts
1304 * the regeneration rate on a basis of time instead of 1304 * the regeneration rate on a basis of time instead of
1305 * #moves the monster makes. The scaling by 8 is 1305 * #moves the monster makes. The scaling by 8 is
1306 * to capture 8th's of a sp fraction regens 1306 * to capture 8th's of a sp fraction regens
1307 */ 1307 */
1308 1308
1309 uint32_t last_sp = op->last_sp + op->stats.Pow * 8 / op->speed; 1309 uint32_t last_sp = op->last_sp + op->stats.Pow * 8 / op->speed;
1310 op->stats.sp = min (op->stats.sp + last_sp / 128, op->stats.maxsp); /* causes Pow/16 sp/tick */ 1310 op->stats.sp = min (op->stats.sp + last_sp / 128, op->stats.maxsp); /* causes Pow/16 sp/tick */
1311 op->last_sp = last_sp % 128; 1311 op->last_sp = last_sp % 128;
1436 { 1436 {
1437 get_rangevector (part, enemy, &rv1, 0x1); 1437 get_rangevector (part, enemy, &rv1, 0x1);
1438 dir = rv1.direction; 1438 dir = rv1.direction;
1439 1439
1440 /* hm, not sure about this part - in original was a scared flag here too 1440 /* hm, not sure about this part - in original was a scared flag here too
1441 * but that we test above... so can be old code here 1441 * but that we test above... so can be old code here
1442 */ 1442 */
1443 if (op->flag [FLAG_RUN_AWAY]) 1443 if (op->flag [FLAG_RUN_AWAY])
1444 dir = absdir (dir + 4); 1444 dir = absdir (dir + 4);
1445 1445
1446 if (op->flag [FLAG_CONFUSED]) 1446 if (op->flag [FLAG_CONFUSED])
1657 1657
1658 return 0; 1658 return 0;
1659} 1659}
1660 1660
1661/* determine if we can 'detect' the enemy. Check for walls blocking the 1661/* determine if we can 'detect' the enemy. Check for walls blocking the
1662 * los. Also, just because its hidden/invisible, we may be sensitive/smart 1662 * los. Also, just because its hidden/invisible, we may be sensitive/smart
1663 * enough (based on Wis & Int) to figure out where the enemy is. -b.t. 1663 * enough (based on Wis & Int) to figure out where the enemy is. -b.t.
1664 * modified by MSW to use the get_rangevector so that map tiling works 1664 * modified by MSW to use the get_rangevector so that map tiling works
1665 * properly. I also so odd code in place that checked for x distance 1665 * properly. I also so odd code in place that checked for x distance
1666 * OR y distance being within some range - that seemed wrong - both should 1666 * OR y distance being within some range - that seemed wrong - both should
1667 * be within the valid range. MSW 2001-08-05 1667 * be within the valid range. MSW 2001-08-05
1668 * Returns 0 if enemy can not be detected, 1 if it is detected 1668 * Returns 0 if enemy can not be detected, 1 if it is detected
1693 */ 1693 */
1694 if (op->is_player ()) 1694 if (op->is_player ())
1695 return 0; 1695 return 0;
1696 1696
1697 /* Quality invisible? Bah, we wont see them w/o SEE_INVISIBLE 1697 /* Quality invisible? Bah, we wont see them w/o SEE_INVISIBLE
1698 * flag (which was already checked) in can_see_enemy (). Lets get out of here 1698 * flag (which was already checked) in can_see_enemy (). Lets get out of here
1699 */ 1699 */
1700 if (enemy->invisible && (!enemy->contr || (!enemy->contr->tmp_invis && !enemy->contr->hidden))) 1700 if (enemy->invisible && (!enemy->contr || (!enemy->contr->tmp_invis && !enemy->contr->hidden)))
1701 return 0; 1701 return 0;
1702 1702
1703 int radius = MIN_MON_RADIUS; 1703 int radius = MIN_MON_RADIUS;
1728 1728
1729 radius += bonus / 5; 1729 radius += bonus / 5;
1730 hide_discovery += bonus * 5; 1730 hide_discovery += bonus * 5;
1731 } /* else creature has modifiers for hiding */ 1731 } /* else creature has modifiers for hiding */
1732 1732
1733 /* Radii stealth adjustment. Only if you are stealthy 1733 /* Radii stealth adjustment. Only if you are stealthy
1734 * will you be able to sneak up closer to creatures */ 1734 * will you be able to sneak up closer to creatures */
1735 if (enemy->flag [FLAG_STEALTH]) 1735 if (enemy->flag [FLAG_STEALTH])
1736 { 1736 {
1737 radius /= 2; 1737 radius /= 2;
1738 hide_discovery /= 3; 1738 hide_discovery /= 3;
1747 if (op->flag [FLAG_SEE_IN_DARK] && !is_true_undead (enemy)) 1747 if (op->flag [FLAG_SEE_IN_DARK] && !is_true_undead (enemy))
1748 radius += op->map->darklevel () / 2; 1748 radius += op->map->darklevel () / 2;
1749 else 1749 else
1750 radius -= op->map->darklevel () / 2; 1750 radius -= op->map->darklevel () / 2;
1751 1751
1752 /* op next to a monster (and not in complete darkness) 1752 /* op next to a monster (and not in complete darkness)
1753 * the monster should have a chance to see you. 1753 * the monster should have a chance to see you.
1754 */ 1754 */
1755 if (radius < MIN_MON_RADIUS && op->map->darklevel () < MAX_DARKNESS && rv->distance <= 1) 1755 if (radius < MIN_MON_RADIUS && op->map->darklevel () < MAX_DARKNESS && rv->distance <= 1)
1756 radius = MIN_MON_RADIUS; 1756 radius = MIN_MON_RADIUS;
1757 } /* if on dark map */ 1757 } /* if on dark map */
1758 1758
1808 /* Wasn't detected above, so still hidden */ 1808 /* Wasn't detected above, so still hidden */
1809 return 0; 1809 return 0;
1810} 1810}
1811 1811
1812/* determine if op stands in a lighted square. This is not a very 1812/* determine if op stands in a lighted square. This is not a very
1813 * intelligent algorithm. For one thing, we ignore los here, SO it 1813 * intelligent algorithm. For one thing, we ignore los here, SO it
1814 * is possible for a bright light to illuminate a player on the 1814 * is possible for a bright light to illuminate a player on the
1815 * other side of a wall (!). 1815 * other side of a wall (!).
1816 */ 1816 */
1817int 1817int
1818stand_in_light (object *op) 1818stand_in_light (object *op)
1819{ 1819{
1820 if (op) 1820 if (op)
1838 /* Check the spaces with the max light radius to see if any of them 1838 /* Check the spaces with the max light radius to see if any of them
1839 * have lights, and if any of them light the player enough, then return 1. 1839 * have lights, and if any of them light the player enough, then return 1.
1840 */ 1840 */
1841 int light = ms.light; 1841 int light = ms.light;
1842 1842
1843 if (expect_false (light > 0) && idistance (dx, dy) <= light) 1843 if (ecb_expect_false (light > 0) && idistance (dx, dy) <= light)
1844 return 1; 1844 return 1;
1845 } 1845 }
1846 } 1846 }
1847 1847
1848 return 0; 1848 return 0;
1849} 1849}
1850 1850
1851/* assuming no walls/barriers, lets check to see if its *possible* 1851/* assuming no walls/barriers, lets check to see if its *possible*
1852 * to see an enemy. Note, "detection" is different from "seeing". 1852 * to see an enemy. Note, "detection" is different from "seeing".
1853 * See can_detect_enemy() for more details. -b.t. 1853 * See can_detect_enemy() for more details. -b.t.
1854 * return 0 if can't be seen, 1 if can be 1854 * return 0 if can't be seen, 1 if can be
1855 */ 1855 */
1856int 1856int
1861 /* safety */ 1861 /* safety */
1862 if (!looker || !enemy || !looker->flag [FLAG_ALIVE]) 1862 if (!looker || !enemy || !looker->flag [FLAG_ALIVE])
1863 return 0; 1863 return 0;
1864 1864
1865 /* we dont give a full treatment of xrays here (shorter range than normal, 1865 /* we dont give a full treatment of xrays here (shorter range than normal,
1866 * see through walls). Should we change the code elsewhere to make you 1866 * see through walls). Should we change the code elsewhere to make you
1867 * blind even if you can xray? 1867 * blind even if you can xray?
1868 */ 1868 */
1869 if (looker->flag [FLAG_BLIND] && !looker->flag [FLAG_XRAYS]) 1869 if (looker->flag [FLAG_BLIND] && !looker->flag [FLAG_XRAYS])
1870 return 0; 1870 return 0;
1871 1871
1872 /* checking for invisible things */ 1872 /* checking for invisible things */
1873 if (enemy->invisible) 1873 if (enemy->invisible)
1874 { 1874 {
1875 /* HIDDEN ENEMY. by definition, you can't see hidden stuff! 1875 /* HIDDEN ENEMY. by definition, you can't see hidden stuff!
1876 * However,if you carry any source of light, then the hidden 1876 * However,if you carry any source of light, then the hidden
1877 * creature is seeable (and stupid) */ 1877 * creature is seeable (and stupid) */
1878 1878
1879 if (enemy->has_carried_lights ()) 1879 if (enemy->has_carried_lights ())
1880 { 1880 {
1899 } 1899 }
1900 else if (looker->is_player ()) /* for players, a (possible) shortcut */ 1900 else if (looker->is_player ()) /* for players, a (possible) shortcut */
1901 if (player_can_view (looker, enemy)) 1901 if (player_can_view (looker, enemy))
1902 return 1; 1902 return 1;
1903 1903
1904 /* ENEMY IN DARK MAP. Without infravision, the enemy is not seen 1904 /* ENEMY IN DARK MAP. Without infravision, the enemy is not seen
1905 * unless they carry a light or stand in light. Darkness doesnt 1905 * unless they carry a light or stand in light. Darkness doesnt
1906 * inhibit the undead per se (but we should give their archs 1906 * inhibit the undead per se (but we should give their archs
1907 * CAN_SEE_IN_DARK, this is just a safety 1907 * CAN_SEE_IN_DARK, this is just a safety
1908 * we care about the enemy maps status, not the looker. 1908 * we care about the enemy maps status, not the looker.
1909 * only relevant for tiled maps, but it is possible that the 1909 * only relevant for tiled maps, but it is possible that the
1910 * enemy is on a bright map and the looker on a dark - in that 1910 * enemy is on a bright map and the looker on a dark - in that
1911 * case, the looker can still see the enemy 1911 * case, the looker can still see the enemy
1912 */ 1912 */

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines