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 |
… | |
… | |
233 | disconnect (); |
234 | disconnect (); |
234 | |
235 | |
235 | attachable::do_destroy (); |
236 | attachable::do_destroy (); |
236 | |
237 | |
237 | if (ob) |
238 | if (ob) |
|
|
239 | { |
|
|
240 | // potentially fix a bug where ob->contr is non-null while ob->contr->ob is null, causing a segfault. |
|
|
241 | // temporarily backed out patchset 4025 to see if THIS change causes crashes |
|
|
242 | //ob->contr = 0; |
238 | ob->destroy (); |
243 | ob->destroy (); |
|
|
244 | } |
239 | |
245 | |
240 | ob = observe = viewpoint = 0; |
246 | ob = observe = viewpoint = 0; |
241 | } |
247 | } |
242 | |
248 | |
243 | player::~player () |
249 | player::~player () |
… | |
… | |
327 | #endif |
333 | #endif |
328 | return op; |
334 | return op; |
329 | } |
335 | } |
330 | |
336 | |
331 | /* I believe this can safely go to 2, 3 is questionable, 4 will likely |
337 | /* I believe this can safely go to 2, 3 is questionable, 4 will likely |
332 | * result in a monster paths backtracking. It basically determines how large a |
338 | * result in a monster paths backtracking. It basically determines how large a |
333 | * detour a monster will take from the direction path when looking |
339 | * detour a monster will take from the direction path when looking |
334 | * for a path to the player. The values are in the amount of direction |
340 | * for a path to the player. The values are in the amount of direction |
335 | * the deviation is |
341 | * the deviation is |
336 | */ |
342 | */ |
337 | #define DETOUR_AMOUNT 2 |
343 | #define DETOUR_AMOUNT 2 |
… | |
… | |
416 | } |
422 | } |
417 | else |
423 | else |
418 | { |
424 | { |
419 | /* direct path is blocked - try taking a side step to |
425 | /* direct path is blocked - try taking a side step to |
420 | * either the left or right. |
426 | * either the left or right. |
421 | * Note increase the values in the loop below to be |
427 | * Note increase the values in the loop below to be |
422 | * more than -1/1 respectively will mean the monster takes |
428 | * more than -1/1 respectively will mean the monster takes |
423 | * bigger detour. Have to be careful about these values getting |
429 | * bigger detour. Have to be careful about these values getting |
424 | * too big (3 or maybe 4 or higher) as the monster may just try |
430 | * too big (3 or maybe 4 or higher) as the monster may just try |
425 | * stepping back and forth |
431 | * stepping back and forth |
426 | */ |
432 | */ |
… | |
… | |
511 | for (object *next, *op = pl->inv; op; op = next) |
517 | for (object *next, *op = pl->inv; op; op = next) |
512 | { |
518 | { |
513 | next = op->below; |
519 | next = op->below; |
514 | |
520 | |
515 | /* Forces get applied per default, unless they have the |
521 | /* Forces get applied per default, unless they have the |
516 | * flag "neutral" set. Sorry but I can't think of a better way |
522 | * flag "neutral" set. Sorry but I can't think of a better way |
517 | */ |
523 | */ |
518 | if (op->type == FORCE && !op->flag [FLAG_NEUTRAL]) |
524 | if (op->type == FORCE && !op->flag [FLAG_NEUTRAL]) |
519 | op->set_flag (FLAG_APPLIED); |
525 | op->set_flag (FLAG_APPLIED); |
520 | |
526 | |
521 | /* we never give weapons/armour if these cannot be used |
527 | /* we never give weapons/armour if these cannot be used |
522 | * by this player due to race restrictions |
528 | * by this player due to race restrictions |
523 | */ |
529 | */ |
524 | if (pl->type == PLAYER) |
530 | if (pl->type == PLAYER) |
525 | { |
531 | { |
526 | if ((!pl->flag [FLAG_USE_ARMOUR] |
532 | if ((!pl->flag [FLAG_USE_ARMOUR] |
527 | && |
533 | && |
… | |
… | |
1149 | } |
1155 | } |
1150 | |
1156 | |
1151 | /* routine for both players and monsters. We call this when |
1157 | /* routine for both players and monsters. We call this when |
1152 | * there is a possibility for our action distrubing our hiding |
1158 | * there is a possibility for our action distrubing our hiding |
1153 | * place or invisiblity spell. Artefact invisiblity causes |
1159 | * place or invisiblity spell. Artefact invisiblity causes |
1154 | * "noise" instead. If we arent invisible to begin with, we |
1160 | * "noise" instead. If we arent invisible to begin with, we |
1155 | * return 0. |
1161 | * return 0. |
1156 | */ |
1162 | */ |
1157 | static int |
1163 | static int |
1158 | action_makes_visible (object *op) |
1164 | action_makes_visible (object *op) |
1159 | { |
1165 | { |
1160 | if (op->invisible && op->flag [FLAG_ALIVE]) |
1166 | if (op->invisible && op->flag [FLAG_ALIVE]) |
… | |
… | |
1183 | return 0; |
1189 | return 0; |
1184 | } |
1190 | } |
1185 | |
1191 | |
1186 | /* |
1192 | /* |
1187 | * Find an arrow in the inventory and after that |
1193 | * Find an arrow in the inventory and after that |
1188 | * in the right type container (quiver). Pointer to the |
1194 | * in the right type container (quiver). Pointer to the |
1189 | * found object is returned. |
1195 | * found object is returned. |
1190 | */ |
1196 | */ |
1191 | static object * |
1197 | static object * |
1192 | find_arrow (object *op, const char *type) |
1198 | find_arrow (object *op, const char *type) |
1193 | { |
1199 | { |
… | |
… | |
1312 | y = op->y; |
1318 | y = op->y; |
1313 | |
1319 | |
1314 | /* find the first target */ |
1320 | /* find the first target */ |
1315 | for (i = 0, found = 0; i < 20; i++) |
1321 | for (i = 0, found = 0; i < 20; i++) |
1316 | { |
1322 | { |
1317 | x += freearr_x[dir]; |
1323 | x += DIRX (dir); |
1318 | y += freearr_y[dir]; |
1324 | y += DIRY (dir); |
1319 | mflags = get_map_flags (m, &m, x, y, &x, &y); |
1325 | mflags = get_map_flags (m, &m, x, y, &x, &y); |
1320 | |
1326 | |
1321 | if (mflags & P_OUT_OF_MAP || mflags & P_BLOCKSVIEW) |
1327 | if (mflags & P_OUT_OF_MAP || mflags & P_BLOCKSVIEW) |
1322 | { |
1328 | { |
1323 | tmp = 0; |
1329 | tmp = 0; |
… | |
… | |
1346 | |
1352 | |
1347 | return find_better_arrow (op, tmp, type, &i); |
1353 | return find_better_arrow (op, tmp, type, &i); |
1348 | } |
1354 | } |
1349 | |
1355 | |
1350 | /* |
1356 | /* |
1351 | * Creature fires a bow - op can be monster or player. Returns |
1357 | * Creature fires a bow - op can be monster or player. Returns |
1352 | * 1 if bow was actually fired, 0 otherwise. |
1358 | * 1 if bow was actually fired, 0 otherwise. |
1353 | * op is the object firing the bow. |
1359 | * op is the object firing the bow. |
1354 | * part is for multipart creatures - the part firing the bow. |
1360 | * part is for multipart creatures - the part firing the bow. |
1355 | * dir is the direction of fire. |
1361 | * dir is the direction of fire. |
1356 | * wc_mod is any special modifier to give (used in special player fire modes) |
1362 | * wc_mod is any special modifier to give (used in special player fire modes) |
… | |
… | |
1464 | SET_ANIMATION (arrow, arrow->direction); |
1470 | SET_ANIMATION (arrow, arrow->direction); |
1465 | |
1471 | |
1466 | /* update the speed */ |
1472 | /* update the speed */ |
1467 | |
1473 | |
1468 | arrow->speed_left = 0; |
1474 | arrow->speed_left = 0; |
1469 | arrow->set_speed (max (2.f, |
1475 | arrow->set_speed (max (2.f, |
1470 | ((bow->flag [FLAG_NO_STRENGTH] ? 0 : dam_bonus[op->stats.Str]) + bow->magic + arrow->magic) / 5.f |
1476 | ((bow->flag [FLAG_NO_STRENGTH] ? 0 : dam_bonus[op->stats.Str]) + bow->magic + arrow->magic) / 5.f |
1471 | + bow->stats.dam / 7.f |
1477 | + bow->stats.dam / 7.f |
1472 | )); |
1478 | )); |
1473 | |
1479 | |
1474 | int wc = op->stats.wc + wc_mod - arrow->magic - arrow->stats.wc; |
1480 | int wc = op->stats.wc + wc_mod - arrow->magic - arrow->stats.wc; |
… | |
… | |
1498 | arrow->stats.dam = clamp (arrow->stats.dam + op->stats.dam + arrow->magic, MIN_DAM, MAX_DAM); |
1504 | arrow->stats.dam = clamp (arrow->stats.dam + op->stats.dam + arrow->magic, MIN_DAM, MAX_DAM); |
1499 | |
1505 | |
1500 | arrow->stats.wc = clamp (wc, MIN_WC, MAX_WC); |
1506 | arrow->stats.wc = clamp (wc, MIN_WC, MAX_WC); |
1501 | arrow->move_type = MOVE_FLY_LOW; |
1507 | arrow->move_type = MOVE_FLY_LOW; |
1502 | arrow->move_on = MOVE_FLY_LOW | MOVE_WALK; |
1508 | arrow->move_on = MOVE_FLY_LOW | MOVE_WALK; |
|
|
1509 | arrow->set_flag (FLAG_NO_PICK); |
1503 | |
1510 | |
1504 | op->play_sound (sound_find ("fire_arrow")); |
1511 | op->play_sound (sound_find ("fire_arrow")); |
1505 | m->insert (arrow, sx, sy, op); |
1512 | m->insert (arrow, sx, sy, op); |
1506 | |
1513 | |
1507 | if (!arrow->destroyed ()) |
1514 | if (!arrow->destroyed ()) |
… | |
… | |
1532 | ret = fire_bow (op, op, NULL, op->contr->bowtype - bow_n + 1, wcmod, op->x, op->y); |
1539 | ret = fire_bow (op, op, NULL, op->contr->bowtype - bow_n + 1, wcmod, op->x, op->y); |
1533 | } |
1540 | } |
1534 | else if (op->contr->bowtype == bow_threewide) |
1541 | else if (op->contr->bowtype == bow_threewide) |
1535 | { |
1542 | { |
1536 | ret = fire_bow (op, op, NULL, dir, 0, op->x, op->y); |
1543 | ret = fire_bow (op, op, NULL, dir, 0, op->x, op->y); |
1537 | ret |= fire_bow (op, op, NULL, dir, -5, op->x + freearr_x[absdir (dir + 2)], op->y + freearr_y[absdir (dir + 2)]); |
1544 | ret |= fire_bow (op, op, NULL, dir, -5, op->x + DIRX (absdir (dir + 2)), op->y + DIRY (absdir (dir + 2))); |
1538 | ret |= fire_bow (op, op, NULL, dir, -5, op->x + freearr_x[absdir (dir - 2)], op->y + freearr_y[absdir (dir - 2)]); |
1545 | ret |= fire_bow (op, op, NULL, dir, -5, op->x + DIRX (absdir (dir - 2)), op->y + DIRY (absdir (dir - 2))); |
1539 | } |
1546 | } |
1540 | else if (op->contr->bowtype == bow_spreadshot) |
1547 | else if (op->contr->bowtype == bow_spreadshot) |
1541 | { |
1548 | { |
1542 | ret = fire_bow (op, op, NULL, dir, 0, op->x, op->y); |
1549 | ret = fire_bow (op, op, NULL, dir, 0, op->x, op->y); |
1543 | ret |= fire_bow (op, op, NULL, absdir (dir - 1), -5, op->x, op->y); |
1550 | ret |= fire_bow (op, op, NULL, absdir (dir - 1), -5, op->x, op->y); |
… | |
… | |
1703 | for (tmp = container->inv; tmp; tmp = tmp->below) |
1710 | for (tmp = container->inv; tmp; tmp = tmp->below) |
1704 | { |
1711 | { |
1705 | if (door->type == DOOR && tmp->type == KEY) |
1712 | if (door->type == DOOR && tmp->type == KEY) |
1706 | break; |
1713 | break; |
1707 | |
1714 | |
1708 | /* For sanity, we should really check door type, but other stuff |
1715 | /* For sanity, we should really check door type, but other stuff |
1709 | * (like containers) can be locked with special keys |
1716 | * (like containers) can be locked with special keys |
1710 | */ |
1717 | */ |
1711 | if (tmp->slaying && tmp->type == SPECIAL_KEY && tmp->slaying == door->slaying) |
1718 | if (tmp->slaying && tmp->type == SPECIAL_KEY && tmp->slaying == door->slaying) |
1712 | break; |
1719 | break; |
1713 | } |
1720 | } |
… | |
… | |
1767 | /* find_key |
1774 | /* find_key |
1768 | * We try to find a key for the door as passed. If we find a key |
1775 | * We try to find a key for the door as passed. If we find a key |
1769 | * and successfully use it, we return the key, otherwise NULL |
1776 | * and successfully use it, we return the key, otherwise NULL |
1770 | * This function merges both normal and locked door, since the logic |
1777 | * This function merges both normal and locked door, since the logic |
1771 | * for both is the same - just the specific key is different. |
1778 | * for both is the same - just the specific key is different. |
1772 | * pl is the player, |
1779 | * pl is the player, |
1773 | * inv is the objects inventory to searched |
1780 | * inv is the objects inventory to searched |
1774 | * door is the door we are trying to match against. |
1781 | * door is the door we are trying to match against. |
1775 | * This function can be called recursively to search containers. |
1782 | * This function can be called recursively to search containers. |
1776 | */ |
1783 | */ |
1777 | object * |
1784 | object * |
1778 | find_key (object *pl, object *container, object *door) |
1785 | find_key (object *pl, object *container, object *door) |
… | |
… | |
1850 | { |
1857 | { |
1851 | --op->speed_left; |
1858 | --op->speed_left; |
1852 | return true; |
1859 | return true; |
1853 | } |
1860 | } |
1854 | |
1861 | |
1855 | sint16 nx = freearr_x[dir] + op->x; |
1862 | sint16 nx = DIRX (dir) + op->x; |
1856 | sint16 ny = freearr_y[dir] + op->y; |
1863 | sint16 ny = DIRY (dir) + op->y; |
1857 | |
1864 | |
1858 | if (out_of_map (op->map, nx, ny)) |
1865 | if (out_of_map (op->map, nx, ny)) |
1859 | return false; |
1866 | return false; |
1860 | |
1867 | |
1861 | /* If braced, or can't move to the square, and it is not out of the |
1868 | /* If braced, or can't move to the square, and it is not out of the |
… | |
… | |
2596 | |
2603 | |
2597 | /* There is a maximum depletion total per level. */ |
2604 | /* There is a maximum depletion total per level. */ |
2598 | if (this_stat < -1 - op->level / BALSL_MAX_LOSS_RATIO) |
2605 | if (this_stat < -1 - op->level / BALSL_MAX_LOSS_RATIO) |
2599 | { |
2606 | { |
2600 | lose_this_stat = 0; |
2607 | lose_this_stat = 0; |
2601 | /* Take loss chance vs keep chance to see if we |
2608 | /* Take loss chance vs keep chance to see if we |
2602 | retain the stat. */ |
2609 | retain the stat. */ |
2603 | } |
2610 | } |
2604 | else |
2611 | else |
2605 | { |
2612 | { |
2606 | if (random_roll (0, loss_chance + keep_chance - 1, op, PREFER_LOW) < keep_chance) |
2613 | if (random_roll (0, loss_chance + keep_chance - 1, op, PREFER_LOW) < keep_chance) |
… | |
… | |
2867 | level = -(10 + (2 * ob->map->darklevel ())); |
2874 | level = -(10 + (2 * ob->map->darklevel ())); |
2868 | |
2875 | |
2869 | /* scan through all nearby squares for terrain to hide in */ |
2876 | /* scan through all nearby squares for terrain to hide in */ |
2870 | for (i = 0, x = ob->x, y = ob->y; |
2877 | for (i = 0, x = ob->x, y = ob->y; |
2871 | i <= SIZEOFFREE1; |
2878 | i <= SIZEOFFREE1; |
2872 | i++, x = ob->x + freearr_x[i], y = ob->y + freearr_y[i]) |
2879 | i++, x = ob->x + DIRX (i), y = ob->y + DIRY (i)) |
2873 | { |
2880 | { |
2874 | mflag = get_map_flags (ob->map, NULL, x, y, NULL, NULL); |
2881 | mflag = get_map_flags (ob->map, NULL, x, y, NULL, NULL); |
2875 | if (mflag & P_OUT_OF_MAP) |
2882 | if (mflag & P_OUT_OF_MAP) |
2876 | continue; |
2883 | continue; |
2877 | |
2884 | |
… | |
… | |
2949 | friendly = who->flag [FLAG_FRIENDLY]; |
2956 | friendly = who->flag [FLAG_FRIENDLY]; |
2950 | |
2957 | |
2951 | /* search adjacent squares */ |
2958 | /* search adjacent squares */ |
2952 | for (i = 1; i < 9; i++) |
2959 | for (i = 1; i < 9; i++) |
2953 | { |
2960 | { |
2954 | x = who->x + freearr_x[i]; |
2961 | x = who->x + DIRX (i); |
2955 | y = who->y + freearr_y[i]; |
2962 | y = who->y + DIRY (i); |
2956 | m = who->map; |
2963 | m = who->map; |
2957 | mflags = get_map_flags (m, &m, x, y, &x, &y); |
2964 | mflags = get_map_flags (m, &m, x, y, &x, &y); |
2958 | /* space must be blocked if there is a monster. If not |
2965 | /* space must be blocked if there is a monster. If not |
2959 | * blocked, don't need to check this space. |
2966 | * blocked, don't need to check this space. |
2960 | */ |
2967 | */ |
… | |
… | |
3006 | |
3013 | |
3007 | get_rangevector (pl, op, &rv, 0x1); |
3014 | get_rangevector (pl, op, &rv, 0x1); |
3008 | |
3015 | |
3009 | /* starting with the 'head' part, lets loop |
3016 | /* starting with the 'head' part, lets loop |
3010 | * through the object and find if it has any |
3017 | * through the object and find if it has any |
3011 | * part that is in the los array but isn't on |
3018 | * part that is in the los array but isn't on |
3012 | * a blocked los square. |
3019 | * a blocked los square. |
3013 | * we use the archetype to figure out offsets. |
3020 | * we use the archetype to figure out offsets. |
3014 | */ |
3021 | */ |
3015 | while (op) |
3022 | while (op) |
3016 | { |
3023 | { |