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,2009,2010 Marc Alexander Lehmann / Robin Redeker / 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 (©) 2002 Mark Wedel & Crossfire Development Team |
5 | * Copyright (©) 2002 Mark Wedel & Crossfire Development Team |
6 | * Copyright (©) 1992 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. |
12 | * |
12 | * |
13 | * 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, |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | * GNU General Public License for more details. |
16 | * GNU General Public License for more details. |
17 | * |
17 | * |
18 | * You should have received a copy of the Affero GNU General Public License |
18 | * You should have received a copy of the Affero GNU General Public License |
19 | * and the GNU General Public License along with this program. If not, see |
19 | * and the GNU General Public License along with this program. If not, see |
20 | * <http://www.gnu.org/licenses/>. |
20 | * <http://www.gnu.org/licenses/>. |
21 | * |
21 | * |
22 | * The authors can be reached via e-mail to <support@deliantra.net> |
22 | * The authors can be reached via e-mail to <support@deliantra.net> |
23 | */ |
23 | */ |
24 | |
24 | |
25 | //+GPL |
25 | //+GPL |
26 | |
26 | |
… | |
… | |
51 | npc->enemy = npc->owner->enemy; |
51 | npc->enemy = npc->owner->enemy; |
52 | } |
52 | } |
53 | |
53 | |
54 | /* periodically, a monster may change its target. Also, if the object |
54 | /* periodically, a monster may change its target. Also, if the object |
55 | * has been destroyed, etc, clear the enemy. |
55 | * has been destroyed, etc, clear the enemy. |
56 | * TODO: this should be changed, because it invokes to attack forced or |
56 | * TODO: this should be changed, because it invokes to attack forced or |
57 | * attacked monsters to leave the attacker alone, before it is destroyed |
57 | * attacked monsters to leave the attacker alone, before it is destroyed |
58 | */ |
58 | */ |
59 | /* I had removed the random target leave, this invokes problems with friendly |
59 | /* 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 |
60 | * objects, getting attacked and defending herself - they don't try to attack |
61 | * again then but perhaps get attack on and on |
61 | * 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 |
62 | * If we include a aggravated flag in , we can handle evil vs evil and good vs good |
63 | * too. */ |
63 | * too. */ |
64 | |
64 | |
65 | if (npc->enemy) |
65 | if (npc->enemy) |
66 | { |
66 | { |
… | |
… | |
105 | * of direction, revisit them after looking at all the other spaces. |
105 | * of direction, revisit them after looking at all the other spaces. |
106 | * |
106 | * |
107 | * Note that being this may skip some number of spaces, it will |
107 | * Note that being this may skip some number of spaces, it will |
108 | * not necessarily find the nearest living creature - it basically |
108 | * not necessarily find the nearest living creature - it basically |
109 | * chooses one from within a 3 space radius, and since it skips |
109 | * chooses one from within a 3 space radius, and since it skips |
110 | * the first few directions, it could very well choose something |
110 | * the first few directions, it could very well choose something |
111 | * 3 spaces away even though something directly north is closer. |
111 | * 3 spaces away even though something directly north is closer. |
112 | * |
112 | * |
113 | * this function is map tile aware. |
113 | * this function is map tile aware. |
114 | */ |
114 | */ |
115 | object * |
115 | object * |
… | |
… | |
125 | for (i = 0; i < SIZEOFFREE; i++) |
125 | for (i = 0; i < SIZEOFFREE; i++) |
126 | { |
126 | { |
127 | /* modified to implement smart searching using search_arr |
127 | /* modified to implement smart searching using search_arr |
128 | * guidance array to determine direction of search order |
128 | * guidance array to determine direction of search order |
129 | */ |
129 | */ |
130 | nx = npc->x + freearr_x[search_arr[i]]; |
130 | nx = npc->x + DIRX (search_arr[i]); |
131 | ny = npc->y + freearr_y[search_arr[i]]; |
131 | ny = npc->y + DIRY (search_arr[i]); |
132 | m = npc->map; |
132 | m = npc->map; |
133 | |
133 | |
134 | mflags = get_map_flags (m, &m, nx, ny, &nx, &ny); |
134 | mflags = get_map_flags (m, &m, nx, ny, &nx, &ny); |
135 | |
135 | |
136 | if (mflags & P_OUT_OF_MAP) |
136 | if (mflags & P_OUT_OF_MAP) |
… | |
… | |
173 | |
173 | |
174 | return tmp; |
174 | return tmp; |
175 | } |
175 | } |
176 | |
176 | |
177 | /* Here is the main enemy selection. |
177 | /* Here is the main enemy selection. |
178 | * We want this: if there is an enemy, attack him until its not possible or |
178 | * We want this: if there is an enemy, attack him until its not possible or |
179 | * one of both is dead. |
179 | * one of both is dead. |
180 | * If we have no enemy and we are... |
180 | * If we have no enemy and we are... |
181 | * a monster: try to find a player, a pet or a friendly monster |
181 | * 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 |
182 | * 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 |
183 | * a neutral: fight a attacker (but there should be none), then do nothing |
… | |
… | |
250 | radius = MIN_MON_RADIUS; |
250 | radius = MIN_MON_RADIUS; |
251 | else if (op->map |
251 | else if (op->map |
252 | && !enemy->invisible |
252 | && !enemy->invisible |
253 | && !stand_in_light (enemy) |
253 | && !stand_in_light (enemy) |
254 | && (!op->flag[FLAG_SEE_IN_DARK] || !op->flag [FLAG_SEE_INVISIBLE])) |
254 | && (!op->flag[FLAG_SEE_IN_DARK] || !op->flag [FLAG_SEE_INVISIBLE])) |
255 | /* This covers the situation where the monster is in the dark |
255 | /* 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 |
256 | * and has an enemy. If the enemy has no carried light (or isnt |
257 | * glowing!) then the monster has trouble finding the enemy. |
257 | * glowing!) then the monster has trouble finding the enemy. |
258 | * Remember we already checked to see if the monster can see in |
258 | * Remember we already checked to see if the monster can see in |
259 | * the dark. */ |
259 | * the dark. */ |
260 | radius = min (radius, MIN_MON_RADIUS + MAX_DARKNESS - op->map->darklevel ()); |
260 | min_it (radius, MIN_MON_RADIUS + MAX_DARKNESS - op->map->darklevel ()); |
261 | |
261 | |
262 | if (enemy->flag [FLAG_STEALTH]) |
262 | if (enemy->flag [FLAG_STEALTH]) |
263 | radius = radius / 2 + 1; |
263 | radius = radius / 2 + 1; |
264 | |
264 | |
265 | /* enemy should already be on this map, so don't really need to check |
265 | /* enemy should already be on this map, so don't really need to check |
… | |
… | |
371 | flag = 1; |
371 | flag = 1; |
372 | break; |
372 | break; |
373 | } |
373 | } |
374 | } |
374 | } |
375 | |
375 | |
376 | if (((!(monster->pick_up & 32)) && flag) || ((monster->pick_up & 32) && (!flag))) |
376 | if (((!(monster->pick_up & 32)) && flag) || ((monster->pick_up & 32) && !flag)) |
377 | return 1; |
377 | return 1; |
378 | |
378 | |
379 | return 0; |
379 | return 0; |
380 | } |
380 | } |
381 | |
381 | |
… | |
… | |
395 | * affect stacking on this space. |
395 | * affect stacking on this space. |
396 | */ |
396 | */ |
397 | static void |
397 | static void |
398 | monster_check_pickup (object *monster) |
398 | monster_check_pickup (object *monster) |
399 | { |
399 | { |
400 | object *tmp, *next; |
|
|
401 | |
|
|
402 | for (tmp = monster->below; tmp != NULL; tmp = next) |
400 | for (object *next, *tmp = monster->below; tmp; tmp = next) |
403 | { |
401 | { |
404 | next = tmp->below; |
402 | next = tmp->below; |
|
|
403 | |
405 | if (monster_can_pick (monster, tmp)) |
404 | if (monster_can_pick (monster, tmp)) |
406 | { |
405 | { |
407 | tmp->remove (); |
406 | tmp->remove (); |
408 | tmp = insert_ob_in_ob (tmp, monster); |
407 | tmp = insert_ob_in_ob (tmp, monster); |
409 | monster_check_apply (monster, tmp); |
408 | monster_check_apply (monster, tmp); |
… | |
… | |
536 | val = (item->resist[ATNR_PHYSICAL] - other_armour->resist[ATNR_PHYSICAL]) / 5; |
535 | val = (item->resist[ATNR_PHYSICAL] - other_armour->resist[ATNR_PHYSICAL]) / 5; |
537 | val += (item->magic - other_armour->magic) * 3; |
536 | val += (item->magic - other_armour->magic) * 3; |
538 | |
537 | |
539 | /* for the other protections, do weigh them very much in the equation - |
538 | /* 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 |
539 | * 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. |
540 | * 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 |
541 | * 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. |
542 | * value. If the reverse, then decrease the value of this item some. |
544 | */ |
543 | */ |
545 | for (i = 1; i < NROFATTACKS; i++) |
544 | for (i = 1; i < NROFATTACKS; i++) |
546 | { |
545 | { |
… | |
… | |
652 | mon->set_flag (FLAG_READY_SKILL); |
651 | mon->set_flag (FLAG_READY_SKILL); |
653 | return; |
652 | return; |
654 | } |
653 | } |
655 | |
654 | |
656 | /* if we don't match one of the above types, return now. |
655 | /* 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, |
656 | * can_apply_object will say that we can apply things like flesh, |
658 | * bolts, and whatever else, because it only checks against the |
657 | * bolts, and whatever else, because it only checks against the |
659 | * body_info locations. |
658 | * body_info locations. |
660 | */ |
659 | */ |
661 | if (!flag) |
660 | if (!flag) |
662 | return; |
661 | return; |
… | |
… | |
916 | object *owner; |
915 | object *owner; |
917 | rv_vector rv1; |
916 | rv_vector rv1; |
918 | |
917 | |
919 | /* If you want monsters to cast spells over friends, this spell should |
918 | /* 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 |
919 | * 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 |
920 | * 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 |
921 | * clear path to the player, the side aspects of the code will still hit |
923 | * other monsters) |
922 | * other monsters) |
924 | */ |
923 | */ |
925 | if (!(dir = path_to_player (part, pl, 0))) |
924 | if (!(dir = path_to_player (part, pl, 0))) |
926 | return 0; |
925 | return 0; |
… | |
… | |
991 | object *owner; |
990 | object *owner; |
992 | rv_vector rv1; |
991 | rv_vector rv1; |
993 | |
992 | |
994 | /* If you want monsters to cast spells over friends, this spell should |
993 | /* 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 |
994 | * 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 |
995 | * 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 |
996 | * clear path to the player, the side aspects of the code will still hit |
998 | * other monsters) |
997 | * other monsters) |
999 | */ |
998 | */ |
1000 | if (!(dir = path_to_player (part, pl, 0))) |
999 | if (!(dir = path_to_player (part, pl, 0))) |
1001 | return 0; |
1000 | return 0; |
… | |
… | |
1033 | |
1032 | |
1034 | /* monster_use_skill()-implemented 95-04-28 to allow monster skill use. |
1033 | /* 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 |
1034 | * Note that monsters do not need the skills SK_MELEE_WEAPON and |
1036 | * SK_MISSILE_WEAPON to make those respective attacks, if we |
1035 | * SK_MISSILE_WEAPON to make those respective attacks, if we |
1037 | * required that we would drastically increase the memory |
1036 | * required that we would drastically increase the memory |
1038 | * requirements of CF!! |
1037 | * requirements of CF!! |
1039 | * |
1038 | * |
1040 | * The skills we are treating here are all but those. -b.t. |
1039 | * The skills we are treating here are all but those. -b.t. |
1041 | * |
1040 | * |
1042 | * At the moment this is only useful for throwing, perhaps for |
1041 | * 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 |
1042 | * stealing. TODO: This should be more integrated in the game. -MT, 25.11.01 |
1044 | */ |
1043 | */ |
1045 | static int |
1044 | static int |
… | |
… | |
1273 | /* for target facing, we copy this value here for fast access */ |
1272 | /* for target facing, we copy this value here for fast access */ |
1274 | if (oph->head) /* force update the head - one arch one pic */ |
1273 | if (oph->head) /* force update the head - one arch one pic */ |
1275 | oph = oph->head; |
1274 | oph = oph->head; |
1276 | |
1275 | |
1277 | if (op->flag [FLAG_NO_ATTACK]) /* we never ever attack */ |
1276 | if (op->flag [FLAG_NO_ATTACK]) /* we never ever attack */ |
1278 | enemy = op->enemy = NULL; |
1277 | enemy = op->enemy = 0; |
1279 | else if ((enemy = find_enemy (op, &rv))) |
1278 | else if ((enemy = find_enemy (op, &rv))) |
1280 | /* we have an enemy, just tell him we want him dead */ |
1279 | /* we have an enemy, just tell him we want him dead */ |
1281 | enemy->attacked_by = op; /* our ptr */ |
1280 | enemy->attacked_by = op; /* our ptr */ |
1282 | |
1281 | |
1283 | /* generate hp, if applicable */ |
1282 | /* generate hp, if applicable */ |
1284 | if (op->stats.Con > 0 && op->stats.hp < op->stats.maxhp) |
1283 | if (op->stats.Con > 0 && op->stats.hp < op->stats.maxhp) |
1285 | { |
1284 | { |
1286 | /* last heal is in funny units. Dividing by speed puts |
1285 | /* last heal is in funny units. Dividing by speed puts |
1287 | * the regeneration rate on a basis of time instead of |
1286 | * the regeneration rate on a basis of time instead of |
1288 | * #moves the monster makes. The scaling by 8 is |
1287 | * #moves the monster makes. The scaling by 8 is |
1289 | * to capture 8th's of a hp fraction regens |
1288 | * to capture 8th's of a hp fraction regens |
1290 | */ |
1289 | */ |
1291 | uint32_t last_heal = op->last_heal + op->stats.Con * 8 / op->speed; |
1290 | 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 */ |
1291 | 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; |
1292 | op->last_heal = last_heal % 32; |
1294 | |
1293 | |
… | |
… | |
1301 | if (op->stats.Pow > 0 && op->stats.sp < op->stats.maxsp) |
1300 | if (op->stats.Pow > 0 && op->stats.sp < op->stats.maxsp) |
1302 | { |
1301 | { |
1303 | /* last_sp is in funny units. Dividing by speed puts |
1302 | /* last_sp is in funny units. Dividing by speed puts |
1304 | * the regeneration rate on a basis of time instead of |
1303 | * the regeneration rate on a basis of time instead of |
1305 | * #moves the monster makes. The scaling by 8 is |
1304 | * #moves the monster makes. The scaling by 8 is |
1306 | * to capture 8th's of a sp fraction regens |
1305 | * to capture 8th's of a sp fraction regens |
1307 | */ |
1306 | */ |
1308 | |
1307 | |
1309 | uint32_t last_sp = op->last_sp + op->stats.Pow * 8 / op->speed; |
1308 | 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 */ |
1309 | 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; |
1310 | op->last_sp = last_sp % 128; |
… | |
… | |
1436 | { |
1435 | { |
1437 | get_rangevector (part, enemy, &rv1, 0x1); |
1436 | get_rangevector (part, enemy, &rv1, 0x1); |
1438 | dir = rv1.direction; |
1437 | dir = rv1.direction; |
1439 | |
1438 | |
1440 | /* hm, not sure about this part - in original was a scared flag here too |
1439 | /* 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 |
1440 | * but that we test above... so can be old code here |
1442 | */ |
1441 | */ |
1443 | if (op->flag [FLAG_RUN_AWAY]) |
1442 | if (op->flag [FLAG_RUN_AWAY]) |
1444 | dir = absdir (dir + 4); |
1443 | dir = absdir (dir + 4); |
1445 | |
1444 | |
1446 | if (op->flag [FLAG_CONFUSED]) |
1445 | if (op->flag [FLAG_CONFUSED]) |
… | |
… | |
1657 | |
1656 | |
1658 | return 0; |
1657 | return 0; |
1659 | } |
1658 | } |
1660 | |
1659 | |
1661 | /* determine if we can 'detect' the enemy. Check for walls blocking the |
1660 | /* 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 |
1661 | * 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. |
1662 | * 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 |
1663 | * 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 |
1664 | * 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 |
1665 | * OR y distance being within some range - that seemed wrong - both should |
1667 | * be within the valid range. MSW 2001-08-05 |
1666 | * be within the valid range. MSW 2001-08-05 |
1668 | * Returns 0 if enemy can not be detected, 1 if it is detected |
1667 | * Returns 0 if enemy can not be detected, 1 if it is detected |
… | |
… | |
1693 | */ |
1692 | */ |
1694 | if (op->is_player ()) |
1693 | if (op->is_player ()) |
1695 | return 0; |
1694 | return 0; |
1696 | |
1695 | |
1697 | /* Quality invisible? Bah, we wont see them w/o SEE_INVISIBLE |
1696 | /* 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 |
1697 | * flag (which was already checked) in can_see_enemy (). Lets get out of here |
1699 | */ |
1698 | */ |
1700 | if (enemy->invisible && (!enemy->contr || (!enemy->contr->tmp_invis && !enemy->contr->hidden))) |
1699 | if (enemy->invisible && (!enemy->contr || (!enemy->contr->tmp_invis && !enemy->contr->hidden))) |
1701 | return 0; |
1700 | return 0; |
1702 | |
1701 | |
1703 | int radius = MIN_MON_RADIUS; |
1702 | int radius = MIN_MON_RADIUS; |
… | |
… | |
1728 | |
1727 | |
1729 | radius += bonus / 5; |
1728 | radius += bonus / 5; |
1730 | hide_discovery += bonus * 5; |
1729 | hide_discovery += bonus * 5; |
1731 | } /* else creature has modifiers for hiding */ |
1730 | } /* else creature has modifiers for hiding */ |
1732 | |
1731 | |
1733 | /* Radii stealth adjustment. Only if you are stealthy |
1732 | /* Radii stealth adjustment. Only if you are stealthy |
1734 | * will you be able to sneak up closer to creatures */ |
1733 | * will you be able to sneak up closer to creatures */ |
1735 | if (enemy->flag [FLAG_STEALTH]) |
1734 | if (enemy->flag [FLAG_STEALTH]) |
1736 | { |
1735 | { |
1737 | radius /= 2; |
1736 | radius /= 2; |
1738 | hide_discovery /= 3; |
1737 | hide_discovery /= 3; |
… | |
… | |
1747 | if (op->flag [FLAG_SEE_IN_DARK] && !is_true_undead (enemy)) |
1746 | if (op->flag [FLAG_SEE_IN_DARK] && !is_true_undead (enemy)) |
1748 | radius += op->map->darklevel () / 2; |
1747 | radius += op->map->darklevel () / 2; |
1749 | else |
1748 | else |
1750 | radius -= op->map->darklevel () / 2; |
1749 | radius -= op->map->darklevel () / 2; |
1751 | |
1750 | |
1752 | /* op next to a monster (and not in complete darkness) |
1751 | /* op next to a monster (and not in complete darkness) |
1753 | * the monster should have a chance to see you. |
1752 | * the monster should have a chance to see you. |
1754 | */ |
1753 | */ |
1755 | if (radius < MIN_MON_RADIUS && op->map->darklevel () < MAX_DARKNESS && rv->distance <= 1) |
1754 | if (radius < MIN_MON_RADIUS && op->map->darklevel () < MAX_DARKNESS && rv->distance <= 1) |
1756 | radius = MIN_MON_RADIUS; |
1755 | radius = MIN_MON_RADIUS; |
1757 | } /* if on dark map */ |
1756 | } /* if on dark map */ |
1758 | |
1757 | |
… | |
… | |
1764 | * vector is real distance, so in theory this should be 18 to |
1763 | * vector is real distance, so in theory this should be 18 to |
1765 | * find that. |
1764 | * find that. |
1766 | */ |
1765 | */ |
1767 | // note that the above reasoning was utter bullshit even at the time it was written |
1766 | // note that the above reasoning was utter bullshit even at the time it was written |
1768 | // we use 25, lets see if we have the cpu time for it |
1767 | // we use 25, lets see if we have the cpu time for it |
1769 | radius = min (25, radius); |
1768 | min_it (radius, 25); |
1770 | |
1769 | |
1771 | /* Enemy in range! Now test for detection */ |
1770 | /* Enemy in range! Now test for detection */ |
1772 | if (rv->distance <= radius) |
1771 | if (rv->distance <= radius) |
1773 | { |
1772 | { |
1774 | /* ah, we are within range, detected? take cases */ |
1773 | /* ah, we are within range, detected? take cases */ |
… | |
… | |
1808 | /* Wasn't detected above, so still hidden */ |
1807 | /* Wasn't detected above, so still hidden */ |
1809 | return 0; |
1808 | return 0; |
1810 | } |
1809 | } |
1811 | |
1810 | |
1812 | /* determine if op stands in a lighted square. This is not a very |
1811 | /* 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 |
1812 | * intelligent algorithm. For one thing, we ignore los here, SO it |
1814 | * is possible for a bright light to illuminate a player on the |
1813 | * is possible for a bright light to illuminate a player on the |
1815 | * other side of a wall (!). |
1814 | * other side of a wall (!). |
1816 | */ |
1815 | */ |
1817 | int |
1816 | int |
1818 | stand_in_light (object *op) |
1817 | stand_in_light (object *op) |
1819 | { |
1818 | { |
1820 | if (op) |
1819 | if (op) |
… | |
… | |
1846 | } |
1845 | } |
1847 | |
1846 | |
1848 | return 0; |
1847 | return 0; |
1849 | } |
1848 | } |
1850 | |
1849 | |
1851 | /* assuming no walls/barriers, lets check to see if its *possible* |
1850 | /* assuming no walls/barriers, lets check to see if its *possible* |
1852 | * to see an enemy. Note, "detection" is different from "seeing". |
1851 | * to see an enemy. Note, "detection" is different from "seeing". |
1853 | * See can_detect_enemy() for more details. -b.t. |
1852 | * See can_detect_enemy() for more details. -b.t. |
1854 | * return 0 if can't be seen, 1 if can be |
1853 | * return 0 if can't be seen, 1 if can be |
1855 | */ |
1854 | */ |
1856 | int |
1855 | int |
… | |
… | |
1861 | /* safety */ |
1860 | /* safety */ |
1862 | if (!looker || !enemy || !looker->flag [FLAG_ALIVE]) |
1861 | if (!looker || !enemy || !looker->flag [FLAG_ALIVE]) |
1863 | return 0; |
1862 | return 0; |
1864 | |
1863 | |
1865 | /* we dont give a full treatment of xrays here (shorter range than normal, |
1864 | /* 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 |
1865 | * see through walls). Should we change the code elsewhere to make you |
1867 | * blind even if you can xray? |
1866 | * blind even if you can xray? |
1868 | */ |
1867 | */ |
1869 | if (looker->flag [FLAG_BLIND] && !looker->flag [FLAG_XRAYS]) |
1868 | if (looker->flag [FLAG_BLIND] && !looker->flag [FLAG_XRAYS]) |
1870 | return 0; |
1869 | return 0; |
1871 | |
1870 | |
1872 | /* checking for invisible things */ |
1871 | /* checking for invisible things */ |
1873 | if (enemy->invisible) |
1872 | if (enemy->invisible) |
1874 | { |
1873 | { |
1875 | /* HIDDEN ENEMY. by definition, you can't see hidden stuff! |
1874 | /* HIDDEN ENEMY. by definition, you can't see hidden stuff! |
1876 | * However,if you carry any source of light, then the hidden |
1875 | * However,if you carry any source of light, then the hidden |
1877 | * creature is seeable (and stupid) */ |
1876 | * creature is seeable (and stupid) */ |
1878 | |
1877 | |
1879 | if (enemy->has_carried_lights ()) |
1878 | if (enemy->has_carried_lights ()) |
1880 | { |
1879 | { |
… | |
… | |
1899 | } |
1898 | } |
1900 | else if (looker->is_player ()) /* for players, a (possible) shortcut */ |
1899 | else if (looker->is_player ()) /* for players, a (possible) shortcut */ |
1901 | if (player_can_view (looker, enemy)) |
1900 | if (player_can_view (looker, enemy)) |
1902 | return 1; |
1901 | return 1; |
1903 | |
1902 | |
1904 | /* ENEMY IN DARK MAP. Without infravision, the enemy is not seen |
1903 | /* ENEMY IN DARK MAP. Without infravision, the enemy is not seen |
1905 | * unless they carry a light or stand in light. Darkness doesnt |
1904 | * unless they carry a light or stand in light. Darkness doesnt |
1906 | * inhibit the undead per se (but we should give their archs |
1905 | * inhibit the undead per se (but we should give their archs |
1907 | * CAN_SEE_IN_DARK, this is just a safety |
1906 | * CAN_SEE_IN_DARK, this is just a safety |
1908 | * we care about the enemy maps status, not the looker. |
1907 | * we care about the enemy maps status, not the looker. |
1909 | * only relevant for tiled maps, but it is possible that the |
1908 | * 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 |
1909 | * enemy is on a bright map and the looker on a dark - in that |
1911 | * case, the looker can still see the enemy |
1910 | * case, the looker can still see the enemy |
1912 | */ |
1911 | */ |