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 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 | #include <assert.h> |
25 | #include <assert.h> |
26 | #include <global.h> |
26 | #include <global.h> |
27 | #include <living.h> |
27 | #include <living.h> |
28 | #include <material.h> |
28 | #include <material.h> |
29 | #include <skills.h> |
29 | #include <skills.h> |
30 | #include <sounds.h> |
30 | #include <sounds.h> |
31 | #include <sproto.h> |
31 | #include <sproto.h> |
32 | |
|
|
33 | typedef struct att_msg_str |
|
|
34 | { |
|
|
35 | char *msg1; |
|
|
36 | char *msg2; |
|
|
37 | } att_msg; |
|
|
38 | |
32 | |
39 | /*#define ATTACK_DEBUG*/ |
33 | /*#define ATTACK_DEBUG*/ |
40 | |
34 | |
41 | /* did_make_save_item just checks to make sure the item actually |
35 | /* did_make_save_item just checks to make sure the item actually |
42 | * made its saving throw based on the tables. It does not take |
36 | * made its saving throw based on the tables. It does not take |
… | |
… | |
254 | * returns 1 if it hits something, 0 otherwise. |
248 | * returns 1 if it hits something, 0 otherwise. |
255 | */ |
249 | */ |
256 | int |
250 | int |
257 | hit_map (object *op, int dir, uint32_t type, int full_hit) |
251 | hit_map (object *op, int dir, uint32_t type, int full_hit) |
258 | { |
252 | { |
259 | maptile *map; |
|
|
260 | sint16 x, y; |
253 | sint16 x, y; |
261 | int retflag = 0; /* added this flag.. will return 1 if it hits a monster */ |
254 | int retflag = 0; /* added this flag.. will return 1 if it hits a monster */ |
262 | |
255 | |
263 | if (op->flag [FLAG_FREED]) |
256 | if (op->flag [FLAG_FREED]) |
264 | { |
257 | { |
… | |
… | |
364 | if (op->destroyed ()) |
357 | if (op->destroyed ()) |
365 | break; |
358 | break; |
366 | } |
359 | } |
367 | } |
360 | } |
368 | |
361 | |
369 | return 0; |
362 | return retflag; |
370 | } |
363 | } |
371 | |
364 | |
372 | static void |
365 | static void |
373 | attack_message (int dam, int type, object *op, object *hitter) |
366 | attack_message (int dam, int type, object *op, object *hitter) |
374 | { |
367 | { |
… | |
… | |
1080 | |
1073 | |
1081 | return 0; |
1074 | return 0; |
1082 | } |
1075 | } |
1083 | |
1076 | |
1084 | if (hit_something && op->speed >= 10.0) |
1077 | if (hit_something && op->speed >= 10.0) |
1085 | op->speed -= 1.0; |
1078 | op->set_speed (op->speed - 1.f); |
1086 | |
1079 | |
1087 | /* Missile missed victim - reassemble missile */ |
1080 | /* Missile missed victim - reassemble missile */ |
1088 | if (container) |
1081 | if (container) |
1089 | { |
1082 | { |
1090 | hitter->remove (); |
1083 | hitter->remove (); |
… | |
… | |
1158 | * MSW 2002-07-17 |
1151 | * MSW 2002-07-17 |
1159 | */ |
1152 | */ |
1160 | int |
1153 | int |
1161 | kill_object (object *op, int dam, object *hitter, int type) |
1154 | kill_object (object *op, int dam, object *hitter, int type) |
1162 | { |
1155 | { |
1163 | char buf[MAX_BUF]; |
|
|
1164 | shstr skill; |
1156 | shstr skill; |
1165 | int maxdam = 0; |
1157 | int maxdam = 0; |
1166 | int battleg = 0; /* true if op standing on battleground */ |
1158 | int battleg = 0; /* true if op standing on battleground */ |
1167 | int pk = 0; /* true if op and what controls hitter are both players */ |
1159 | int pk = 0; /* true if op and what controls hitter are both players */ |
1168 | object *owner = 0; |
1160 | object *owner = 0; |
… | |
… | |
1271 | skill = owner->current_weapon->skill; |
1263 | skill = owner->current_weapon->skill; |
1272 | else |
1264 | else |
1273 | { |
1265 | { |
1274 | LOG (llevError | logBacktrace, |
1266 | LOG (llevError | logBacktrace, |
1275 | "BUG: kill_object - unable to find skill that killed monster\n" |
1267 | "BUG: kill_object - unable to find skill that killed monster\n" |
1276 | "op: %s\n" "hitter: %s\n" "owner: %s\n", |
1268 | "op: %s\n" "hitter: %s\n" "op: %s\n", |
1277 | owner->debug_desc (), hitter->debug_desc (), op->debug_desc ()); |
1269 | op->debug_desc (), hitter->debug_desc (), op->debug_desc ()); |
1278 | skill = 0; |
1270 | skill = 0; |
1279 | } |
1271 | } |
1280 | |
1272 | |
1281 | /* We have the skill we want to credit to - now find the object this goes |
1273 | /* We have the skill we want to credit to - now find the object this goes |
1282 | * to. Make sure skop is an actual skill, and not a skill tool! |
1274 | * to. Make sure skop is an actual skill, and not a skill tool! |
… | |
… | |
1434 | int |
1426 | int |
1435 | hit_player (object *op, int dam, object *hitter, uint32_t type, int full_hit) |
1427 | hit_player (object *op, int dam, object *hitter, uint32_t type, int full_hit) |
1436 | { |
1428 | { |
1437 | int magic = type & AT_MAGIC; |
1429 | int magic = type & AT_MAGIC; |
1438 | int body_attack = op && op->head; /* Did we hit op's head? */ |
1430 | int body_attack = op && op->head; /* Did we hit op's head? */ |
1439 | int maxdam = 0, ndam = 0, attacktype = 1; |
1431 | int maxdam = 0, ndam = 0; |
1440 | int maxattacktype; |
1432 | int maxattacktype; |
1441 | int simple_attack; |
1433 | int simple_attack; |
1442 | int rtn_kill = 0; |
1434 | int rtn_kill = 0; |
1443 | int friendlyfire; |
1435 | int friendlyfire; |
1444 | |
1436 | |
… | |
… | |
1813 | int maxduration; |
1805 | int maxduration; |
1814 | |
1806 | |
1815 | tmp = present_in_ob_by_name (FORCE, shstr_confusion, op); |
1807 | tmp = present_in_ob_by_name (FORCE, shstr_confusion, op); |
1816 | if (!tmp) |
1808 | if (!tmp) |
1817 | { |
1809 | { |
1818 | tmp = get_archetype (FORCE_NAME); |
1810 | tmp = archetype::get (FORCE_NAME); |
1819 | tmp = insert_ob_in_ob (tmp, op); |
1811 | tmp = insert_ob_in_ob (tmp, op); |
1820 | } |
1812 | } |
1821 | |
1813 | |
1822 | /* Duration added per hit and max. duration of confusion both depend |
1814 | /* Duration added per hit and max. duration of confusion both depend |
1823 | * on the player's resistance |
1815 | * on the player's resistance |
1824 | */ |
1816 | */ |
1825 | tmp->speed = 0.05; |
1817 | tmp->set_speed (0.05); |
1826 | tmp->subtype = FORCE_CONFUSION; |
1818 | tmp->subtype = FORCE_CONFUSION; |
1827 | tmp->duration = 8 + max (1, 5 * (100 - op->resist[ATNR_CONFUSION]) / 100); |
1819 | tmp->duration = 8 + max (1, 5 * (100 - op->resist[ATNR_CONFUSION]) / 100); |
1828 | tmp->name = shstr_confusion; |
1820 | tmp->name = shstr_confusion; |
1829 | maxduration = max (2, 30 * (100 - op->resist[ATNR_CONFUSION]) / 100); |
1821 | maxduration = max (2, 30 * (100 - op->resist[ATNR_CONFUSION]) / 100); |
1830 | |
1822 | |
… | |
… | |
1838 | } |
1830 | } |
1839 | |
1831 | |
1840 | void |
1832 | void |
1841 | blind_player (object *op, object *hitter, int dam) |
1833 | blind_player (object *op, object *hitter, int dam) |
1842 | { |
1834 | { |
1843 | object *tmp, *owner; |
|
|
1844 | |
|
|
1845 | /* Save some work if we know it isn't going to affect the player */ |
1835 | /* Save some work if we know it isn't going to affect the player */ |
1846 | if (op->resist[ATNR_BLIND] == 100) |
1836 | if (op->resist[ATNR_BLIND] == 100) |
1847 | return; |
1837 | return; |
1848 | |
1838 | |
1849 | tmp = present_in_ob (BLINDNESS, op); |
1839 | object *tmp = present_in_ob (BLINDNESS, op); |
1850 | if (!tmp) |
1840 | if (!tmp) |
1851 | { |
1841 | { |
1852 | tmp = get_archetype (shstr_blindness); |
1842 | tmp = archetype::get (shstr_blindness); |
1853 | tmp->set_flag (FLAG_BLIND); |
1843 | tmp->set_flag (FLAG_BLIND); |
1854 | tmp->set_flag (FLAG_APPLIED); |
1844 | tmp->set_flag (FLAG_APPLIED); |
1855 | /* use floats so we don't lose too much precision due to rounding errors. |
1845 | // use floats so we don't lose too much precision due to rounding errors. |
1856 | * speed is a float anyways. |
1846 | tmp->set_speed (lerp<float> (op->resist [ATNR_BLIND], 0, 100, tmp->speed, MIN_ACTIVE_SPEED)); |
1857 | */ |
|
|
1858 | tmp->speed = tmp->speed * (100.0 - (float) op->resist[ATNR_BLIND]) / 100; |
|
|
1859 | |
1847 | |
1860 | tmp = insert_ob_in_ob (tmp, op); |
1848 | tmp = insert_ob_in_ob (tmp, op); |
1861 | change_abil (op, tmp); /* Mostly to display any messages */ |
1849 | change_abil (op, tmp); /* Mostly to display any messages */ |
1862 | op->update_stats (); /* This takes care of some other stuff */ |
1850 | op->update_stats (); /* This takes care of some other stuff */ |
1863 | |
1851 | |
1864 | if (hitter->owner) |
|
|
1865 | owner = hitter->owner; |
|
|
1866 | else |
|
|
1867 | owner = hitter; |
|
|
1868 | |
|
|
1869 | new_draw_info_format (NDI_UNIQUE, 0, owner, "Your attack blinds %s!", query_name (op)); |
1852 | new_draw_info_format (NDI_UNIQUE, 0, hitter->outer_owner (), "Your attack blinds %s!", query_name (op)); |
1870 | } |
1853 | } |
|
|
1854 | |
1871 | tmp->stats.food += dam; |
1855 | tmp->stats.food += dam; |
1872 | if (tmp->stats.food > 10) |
1856 | min_it (tmp->stats.food, 10); |
1873 | tmp->stats.food = 10; |
|
|
1874 | } |
1857 | } |
1875 | |
1858 | |
1876 | void |
1859 | void |
1877 | paralyze_player (object *op, object *hitter, int dam) |
1860 | paralyze_player (object *op, object *hitter, int dam) |
1878 | { |
1861 | { |
… | |
… | |
2174 | |
2157 | |
2175 | if (owner && owner != hitter) |
2158 | if (owner && owner != hitter) |
2176 | { |
2159 | { |
2177 | if (op->type != PLAYER || owner->type != PLAYER) |
2160 | if (op->type != PLAYER || owner->type != PLAYER) |
2178 | change_exp (owner, op->stats.exp / (rate * 2), |
2161 | change_exp (owner, op->stats.exp / (rate * 2), |
2179 | hitter->chosen_skill ? hitter->chosen_skill->skill : (const char *) 0, SK_EXP_TOTAL); |
2162 | hitter->chosen_skill ? hitter->chosen_skill->skill : shstr (), SK_EXP_TOTAL); |
2180 | } |
2163 | } |
2181 | else if (op->type != PLAYER || hitter->type != PLAYER) |
2164 | else if (op->type != PLAYER || hitter->type != PLAYER) |
2182 | change_exp (hitter, op->stats.exp / (rate * 2), |
2165 | change_exp (hitter, op->stats.exp / (rate * 2), |
2183 | hitter->chosen_skill ? hitter->chosen_skill->skill : (const char *) 0, 0); |
2166 | hitter->chosen_skill ? hitter->chosen_skill->skill : shstr (), 0); |
2184 | |
2167 | |
2185 | change_exp (op, -op->stats.exp / rate, NULL, 0); |
2168 | change_exp (op, -op->stats.exp / rate, shstr (), 0); |
2186 | } |
2169 | } |
2187 | |
2170 | |
2188 | dam = 1; /* Drain is an effect. Still return 1 - otherwise, if you have pure |
2171 | dam = 1; /* Drain is an effect. Still return 1 - otherwise, if you have pure |
2189 | * drain attack, you won't know that you are actually sucking out EXP, |
2172 | * drain attack, you won't know that you are actually sucking out EXP, |
2190 | * as the messages will say you missed |
2173 | * as the messages will say you missed |