1 | /* |
1 | /* |
2 | * This file is part of Crossfire TRT, the Roguelike Realtime MORPG. |
2 | * This file is part of Deliantra, the Roguelike Realtime MMORPG. |
3 | * |
3 | * |
4 | * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team |
4 | * Copyright (©) 2005,2006,2007,2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team |
5 | * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team |
5 | * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team |
6 | * Copyright (©) 1992,2007 Frank Tore Johansen |
6 | * Copyright (©) 1992,2007 Frank Tore Johansen |
7 | * |
7 | * |
8 | * Crossfire TRT is free software: you can redistribute it and/or modify |
8 | * Deliantra is free software: you can redistribute it and/or modify |
9 | * 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 |
10 | * the Free Software Foundation, either version 3 of the License, or |
10 | * the Free Software Foundation, either version 3 of the License, or |
11 | * (at your option) any later version. |
11 | * (at your 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, |
… | |
… | |
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 GNU General Public License |
18 | * You should have received a copy of the GNU General Public License |
19 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
19 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
20 | * |
20 | * |
21 | * The authors can be reached via e-mail to <crossfire@schmorp.de> |
21 | * The authors can be reached via e-mail to <support@deliantra.net> |
22 | */ |
22 | */ |
23 | |
23 | |
24 | #include <global.h> |
24 | #include <global.h> |
25 | #include <sproto.h> |
25 | #include <sproto.h> |
26 | #include <spells.h> |
26 | #include <spells.h> |
… | |
… | |
372 | if (!check_wakeup (op, enemy, &rv)) |
372 | if (!check_wakeup (op, enemy, &rv)) |
373 | return 0; |
373 | return 0; |
374 | } |
374 | } |
375 | |
375 | |
376 | /* check if monster pops out of hidden spot */ |
376 | /* check if monster pops out of hidden spot */ |
377 | if (op->hide) |
377 | if (op->flag [FLAG_HIDDEN]) |
378 | do_hidden_move (op); |
378 | do_hidden_move (op); |
379 | |
379 | |
380 | if (op->pick_up) |
380 | if (op->pick_up) |
381 | monster_check_pickup (op); |
381 | monster_check_pickup (op); |
382 | |
382 | |
… | |
… | |
386 | /* If we don't have an enemy, do special movement or the like */ |
386 | /* If we don't have an enemy, do special movement or the like */ |
387 | if (!enemy) |
387 | if (!enemy) |
388 | { |
388 | { |
389 | if (QUERY_FLAG (op, FLAG_ONLY_ATTACK)) |
389 | if (QUERY_FLAG (op, FLAG_ONLY_ATTACK)) |
390 | { |
390 | { |
391 | op->destroy (); |
391 | op->drop_and_destroy (); |
392 | return 1; |
392 | return 1; |
393 | } |
393 | } |
394 | |
394 | |
395 | /* Probably really a bug for a creature to have both |
395 | /* Probably really a bug for a creature to have both |
396 | * stand still and a movement type set. |
396 | * stand still and a movement type set. |
… | |
… | |
650 | if (QUERY_FLAG (part, FLAG_FREED)) /* Might be freed by ghost-attack or hit-back */ |
650 | if (QUERY_FLAG (part, FLAG_FREED)) /* Might be freed by ghost-attack or hit-back */ |
651 | return 1; |
651 | return 1; |
652 | |
652 | |
653 | if (QUERY_FLAG (op, FLAG_ONLY_ATTACK)) |
653 | if (QUERY_FLAG (op, FLAG_ONLY_ATTACK)) |
654 | { |
654 | { |
655 | op->remove (); |
|
|
656 | op->destroy (); |
655 | op->drop_and_destroy (); |
657 | return 1; |
656 | return 1; |
658 | } |
657 | } |
|
|
658 | |
659 | return 0; |
659 | return 0; |
660 | } |
660 | } |
661 | |
661 | |
662 | int |
662 | int |
663 | can_hit (object *ob1, object *ob2, rv_vector * rv) |
663 | can_hit (object *ob1, object *ob2, rv_vector * rv) |
… | |
… | |
1705 | |
1705 | |
1706 | /* use this for invis also */ |
1706 | /* use this for invis also */ |
1707 | hide_discovery = op->stats.Int / 5; |
1707 | hide_discovery = op->stats.Int / 5; |
1708 | |
1708 | |
1709 | /* Determine Detection radii */ |
1709 | /* Determine Detection radii */ |
1710 | if (!enemy->hide) /* to detect non-hidden (eg dark/invis enemy) */ |
1710 | if (!enemy->flag [FLAG_HIDDEN]) /* to detect non-hidden (eg dark/invis enemy) */ |
1711 | radius = max (MIN_MON_RADIUS, op->stats.Wis / 5 + 1); |
1711 | radius = max (MIN_MON_RADIUS, op->stats.Wis / 5 + 1); |
1712 | else |
1712 | else |
1713 | { /* a level/INT/Dex adjustment for hiding */ |
1713 | { /* a level/INT/Dex adjustment for hiding */ |
1714 | int bonus = op->level / 2 + op->stats.Int / 5; |
1714 | int bonus = op->level / 2 + op->stats.Int / 5; |
1715 | |
1715 | |
… | |
… | |
1768 | // note that the above reasoning was utter bullshit even at the time it was written |
1768 | // note that the above reasoning was utter bullshit even at the time it was written |
1769 | // we use 25, lets see if we have the cpu time for it |
1769 | // we use 25, lets see if we have the cpu time for it |
1770 | radius = min (25, radius); |
1770 | radius = min (25, radius); |
1771 | |
1771 | |
1772 | /* Enemy in range! Now test for detection */ |
1772 | /* Enemy in range! Now test for detection */ |
1773 | if ((int) rv->distance <= radius) |
1773 | if (rv->distance <= radius) |
1774 | { |
1774 | { |
1775 | /* ah, we are within range, detected? take cases */ |
1775 | /* ah, we are within range, detected? take cases */ |
1776 | if (!enemy->invisible) /* enemy in dark squares... are seen! */ |
1776 | if (!enemy->invisible) /* enemy in dark squares... are seen! */ |
1777 | return 1; |
1777 | return 1; |
1778 | |
1778 | |
1779 | /* hidden or low-quality invisible */ |
1779 | /* hidden or low-quality invisible */ |
1780 | if (enemy->hide && rv->distance <= 1 && rndm (100) <= hide_discovery) |
1780 | if (enemy->flag [FLAG_HIDDEN] && rv->distance <= 1 && rndm (100) <= hide_discovery) |
1781 | { |
1781 | { |
1782 | make_visible (enemy); |
1782 | make_visible (enemy); |
1783 | |
1783 | |
1784 | /* inform players of new status */ |
1784 | /* inform players of new status */ |
1785 | if (enemy->type == PLAYER && player_can_view (enemy, op)) |
1785 | if (enemy->type == PLAYER && player_can_view (enemy, op)) |
… | |
… | |
1816 | * other side of a wall (!). |
1816 | * other side of a wall (!). |
1817 | */ |
1817 | */ |
1818 | int |
1818 | int |
1819 | stand_in_light (object *op) |
1819 | stand_in_light (object *op) |
1820 | { |
1820 | { |
1821 | sint16 nx, ny; |
|
|
1822 | maptile *m; |
|
|
1823 | |
|
|
1824 | if (!op) |
1821 | if (!op) |
1825 | return 0; |
1822 | return 0; |
1826 | |
1823 | |
1827 | if (op->glow_radius > 0) |
1824 | if (op->glow_radius > 0) |
1828 | return 1; |
1825 | return 1; |
1829 | |
1826 | |
1830 | if (op->map) |
1827 | if (op->map) |
1831 | { |
1828 | { |
1832 | int x, y, x1, y1; |
|
|
1833 | |
|
|
1834 | /* Check the spaces with the max light radius to see if any of them |
1829 | /* Check the spaces with the max light radius to see if any of them |
1835 | * have lights, and if any of them light the player enough, then return 1. |
1830 | * have lights, and if any of them light the player enough, then return 1. |
1836 | */ |
1831 | */ |
1837 | for (x = op->x - MAX_LIGHT_RADII; x <= op->x + MAX_LIGHT_RADII; x++) |
1832 | for (int x = op->x - MAX_LIGHT_RADII; x <= op->x + MAX_LIGHT_RADII; x++) |
1838 | { |
1833 | { |
1839 | for (y = op->y - MAX_LIGHT_RADII; y <= op->y + MAX_LIGHT_RADII; y++) |
1834 | for (int y = op->y - MAX_LIGHT_RADII; y <= op->y + MAX_LIGHT_RADII; y++) |
1840 | { |
1835 | { |
1841 | m = op->map; |
1836 | maptile *m = op->map; |
1842 | nx = x; |
1837 | sint16 nx = x; |
1843 | ny = y; |
1838 | sint16 ny = y; |
1844 | |
1839 | |
1845 | if (get_map_flags (m, &m, nx, ny, &nx, &ny) & P_OUT_OF_MAP) |
1840 | if (xy_normalise (m, nx, ny)) |
1846 | continue; |
1841 | if (idistance (x - op->x, y - op->y) < m->at (nx, ny).light) |
1847 | |
|
|
1848 | x1 = abs (x - op->x) * abs (x - op->x); |
|
|
1849 | y1 = abs (y - op->y) * abs (y - op->y); |
|
|
1850 | if (isqrt (x1 + y1) < GET_MAP_LIGHT (m, nx, ny)) |
|
|
1851 | return 1; |
1842 | return 1; |
1852 | } |
1843 | } |
1853 | } |
1844 | } |
1854 | } |
1845 | } |
1855 | |
1846 | |
1856 | return 0; |
1847 | return 0; |
… | |
… | |
1884 | * However,if you carry any source of light, then the hidden |
1875 | * However,if you carry any source of light, then the hidden |
1885 | * creature is seeable (and stupid) */ |
1876 | * creature is seeable (and stupid) */ |
1886 | |
1877 | |
1887 | if (has_carried_lights (enemy)) |
1878 | if (has_carried_lights (enemy)) |
1888 | { |
1879 | { |
1889 | if (enemy->hide) |
1880 | if (enemy->flag [FLAG_HIDDEN]) |
1890 | { |
1881 | { |
1891 | make_visible (enemy); |
1882 | make_visible (enemy); |
1892 | new_draw_info (NDI_UNIQUE, 0, enemy, "Your light reveals your hiding spot!"); |
1883 | new_draw_info (NDI_UNIQUE, 0, enemy, "Your light reveals your hiding spot!"); |
1893 | } |
1884 | } |
|
|
1885 | |
1894 | return 1; |
1886 | return 1; |
1895 | } |
1887 | } |
1896 | else if (enemy->hide) |
1888 | else if (enemy->flag [FLAG_HIDDEN]) |
1897 | return 0; |
1889 | return 0; |
1898 | |
1890 | |
1899 | /* Invisible enemy. Break apart the check for invis undead/invis looker |
1891 | /* Invisible enemy. Break apart the check for invis undead/invis looker |
1900 | * into more simple checks - the QUERY_FLAG doesn't return 1/0 values, |
1892 | * into more simple checks - the QUERY_FLAG doesn't return 1/0 values, |
1901 | * and making it a conditional makes the code pretty ugly. |
1893 | * and making it a conditional makes the code pretty ugly. |
1902 | */ |
1894 | */ |
1903 | if (!QUERY_FLAG (looker, FLAG_SEE_INVISIBLE)) |
1895 | if (!QUERY_FLAG (looker, FLAG_SEE_INVISIBLE)) |
1904 | { |
|
|
1905 | if (makes_invisible_to (enemy, looker)) |
1896 | if (makes_invisible_to (enemy, looker)) |
1906 | return 0; |
1897 | return 0; |
1907 | } |
|
|
1908 | } |
1898 | } |
1909 | else if (looker->type == PLAYER) /* for players, a (possible) shortcut */ |
1899 | else if (looker->type == PLAYER) /* for players, a (possible) shortcut */ |
1910 | if (player_can_view (looker, enemy)) |
1900 | if (player_can_view (looker, enemy)) |
1911 | return 1; |
1901 | return 1; |
1912 | |
1902 | |
… | |
… | |
1923 | && (!QUERY_FLAG (looker, FLAG_SEE_IN_DARK) || !is_true_undead (looker) || !QUERY_FLAG (looker, FLAG_XRAYS))) |
1913 | && (!QUERY_FLAG (looker, FLAG_SEE_IN_DARK) || !is_true_undead (looker) || !QUERY_FLAG (looker, FLAG_XRAYS))) |
1924 | return 0; |
1914 | return 0; |
1925 | |
1915 | |
1926 | return 1; |
1916 | return 1; |
1927 | } |
1917 | } |
|
|
1918 | |