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 (©) 2001 Mark Wedel & Crossfire Development Team |
5 | * Copyright (©) 2001 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 <cmath> |
25 | #include <cmath> |
26 | |
26 | |
… | |
… | |
251 | */ |
251 | */ |
252 | static int |
252 | static int |
253 | prepare_weapon (object *op, object *improver, object *weapon) |
253 | prepare_weapon (object *op, object *improver, object *weapon) |
254 | { |
254 | { |
255 | int sacrifice_count, i; |
255 | int sacrifice_count, i; |
256 | char buf[MAX_BUF]; |
|
|
257 | |
256 | |
258 | if (weapon->level != 0) |
257 | if (weapon->level != 0) |
259 | { |
258 | { |
260 | op->failmsg ("Weapon is already prepared!"); |
259 | op->failmsg ("Weapon is already prepared!"); |
261 | return 0; |
260 | return 0; |
… | |
… | |
290 | "Your sacrifice was accepted." |
289 | "Your sacrifice was accepted." |
291 | "Your *%s may be improved %d times.", |
290 | "Your *%s may be improved %d times.", |
292 | &weapon->name, weapon->level |
291 | &weapon->name, weapon->level |
293 | )); |
292 | )); |
294 | |
293 | |
295 | sprintf (buf, "%s's %s", &op->name, &weapon->name); |
294 | weapon->name = weapon->name_pl = format ("%s's %s", &op->name, &weapon->name); |
296 | weapon->name = weapon->name_pl = buf; |
|
|
297 | weapon->nrof = 0; /* prevents preparing n weapons in the same |
295 | weapon->nrof = 0; /* prevents preparing n weapons in the same |
298 | slot at once! */ |
296 | slot at once! */ |
299 | improver->decrease (); |
297 | improver->decrease (); |
300 | weapon->last_eat = 0; |
298 | weapon->last_eat = 0; |
301 | return 1; |
299 | return 1; |
… | |
… | |
692 | // elmex: only identify if we need to, for example so that generated money doesn't |
690 | // elmex: only identify if we need to, for example so that generated money doesn't |
693 | // get an 'identified' flag so easily. |
691 | // get an 'identified' flag so easily. |
694 | if (item->need_identify ()) |
692 | if (item->need_identify ()) |
695 | identify (item); |
693 | identify (item); |
696 | |
694 | |
697 | insert_ob_in_map_at (item, converter->map, converter, 0, converter->x, converter->y); |
695 | item->insert_at (converter, 0, INS_NO_WALK_ON); |
|
|
696 | |
698 | return 1; |
697 | return 1; |
699 | } |
698 | } |
700 | |
699 | |
701 | /** |
700 | /** |
702 | * Handle apply on containers. |
701 | * Handle apply on containers. |
… | |
… | |
733 | op->close_container (); |
732 | op->close_container (); |
734 | return 1; |
733 | return 1; |
735 | } |
734 | } |
736 | else if (!sack->env) |
735 | else if (!sack->env) |
737 | { |
736 | { |
738 | // active, but not ours: some other player has opened it |
737 | // active on floor, but not ours: some other player has opened it |
|
|
738 | // normally this only happens to dms standing on the same space. |
|
|
739 | // but it doesn't hurt to handle it. |
739 | op->failmsgf ("Somebody else is using the %s already.", query_name (sack)); |
740 | op->failmsgf ("Somebody else is using the %s already.", query_name (sack)); |
740 | return 1; |
741 | return 1; |
741 | } |
742 | } |
|
|
743 | } |
742 | |
744 | |
743 | // fall through to opening it (active in inv) |
745 | // it's locked? |
|
|
746 | if (sack->slaying) |
744 | } |
747 | { |
745 | else if (sack->env) |
748 | if (object *tmp = find_key (op, op, sack)) |
|
|
749 | { |
|
|
750 | op->statusmsg (format ("You unlock %s with %s.", query_name (sack), query_name (tmp))); |
|
|
751 | } |
|
|
752 | else |
|
|
753 | { |
|
|
754 | sack->flag [FLAG_APPLIED] = false; // might be applied in inv, let the user close it |
|
|
755 | esrv_update_item (UPD_FLAGS, op, sack); |
|
|
756 | op->statusmsg (format ("You don't have the key to unlock %s.", query_name (sack))); |
|
|
757 | return 1; |
|
|
758 | } |
|
|
759 | } |
|
|
760 | |
|
|
761 | if (sack->env && !sack->flag [FLAG_APPLIED]) |
746 | { |
762 | { |
747 | // it is in our env, so activate it, do not open yet |
763 | // it is in our env, so activate it, do not open yet |
748 | op->close_container (); |
764 | op->close_container (); |
749 | sack->flag [FLAG_APPLIED] = 1; |
765 | sack->flag [FLAG_APPLIED] = true; |
750 | esrv_update_item (UPD_FLAGS, op, sack); |
766 | esrv_update_item (UPD_FLAGS, op, sack); |
751 | op->statusmsg (format ("You ready %s.", query_name (sack))); |
767 | op->statusmsg (format ("You ready %s.", query_name (sack))); |
752 | return 1; |
|
|
753 | } |
|
|
754 | |
|
|
755 | // it's locked? |
|
|
756 | if (sack->slaying) |
|
|
757 | { |
768 | } |
758 | if (object *tmp = find_key (op, op, sack)) |
|
|
759 | op->statusmsg (format ("You unlock %s with %s.", query_name (sack), query_name (tmp))); |
|
|
760 | else |
769 | else |
761 | { |
|
|
762 | op->statusmsg (format ("You don't have the key to unlock %s.", query_name (sack))); |
|
|
763 | return 1; |
|
|
764 | } |
|
|
765 | } |
|
|
766 | |
|
|
767 | op->open_container (sack); |
770 | op->open_container (sack); |
768 | |
771 | |
769 | return 1; |
772 | return 1; |
770 | } |
773 | } |
771 | |
774 | |
772 | /** |
775 | /** |
… | |
… | |
1060 | who->flag [FLAG_READY_WEAPON] = false; |
1063 | who->flag [FLAG_READY_WEAPON] = false; |
1061 | |
1064 | |
1062 | // unapplying a weapon or skill tool should also unapply the skill it governs |
1065 | // unapplying a weapon or skill tool should also unapply the skill it governs |
1063 | // but this is hard, as it shouldn't do so when the skill can |
1066 | // but this is hard, as it shouldn't do so when the skill can |
1064 | // be used for other reasons |
1067 | // be used for other reasons |
|
|
1068 | //TODO: really? |
1065 | if (who->chosen_skill) |
1069 | if (who->chosen_skill) |
1066 | if (!who->chosen_skill->flag [FLAG_CAN_USE_SKILL]) |
1070 | if (!who->chosen_skill->flag [FLAG_CAN_USE_SKILL]) |
1067 | unapply_special (who, op, 0); |
1071 | unapply_special (who, who->chosen_skill, 0); |
1068 | |
1072 | |
1069 | break; |
1073 | break; |
1070 | |
1074 | |
|
|
1075 | case RANGED: |
1071 | case BOW: |
1076 | case BOW: |
1072 | case WAND: |
1077 | case WAND: |
1073 | case ROD: |
1078 | case ROD: |
1074 | case HORN: |
1079 | case HORN: |
1075 | case RANGED: |
|
|
1076 | if (player *pl = who->contr) |
1080 | if (player *pl = who->contr) |
1077 | { |
1081 | { |
1078 | who->statusmsg (format ("You unready %s.", query_name (op))); |
1082 | who->statusmsg (format ("You unready %s.", query_name (op))); |
1079 | change_abil (who, op); |
1083 | change_abil (who, op); |
1080 | } |
1084 | } |
… | |
… | |
1389 | |
1393 | |
1390 | static bool |
1394 | static bool |
1391 | apply_special (object *who, object *op, int aflags) |
1395 | apply_special (object *who, object *op, int aflags) |
1392 | { |
1396 | { |
1393 | int basic_flag = aflags & AP_MODE; |
1397 | int basic_flag = aflags & AP_MODE; |
1394 | object *tmp, *tmp2, *skop = NULL; |
1398 | object *tmp, *skop = NULL; |
1395 | |
|
|
1396 | if (who == NULL) |
|
|
1397 | { |
|
|
1398 | LOG (llevError, "apply_special() from object without environment.\n"); |
|
|
1399 | return 1; |
|
|
1400 | } |
|
|
1401 | |
|
|
1402 | //TODO: remove these when apply_special is no longer exposed |
|
|
1403 | if (op->env != who) |
|
|
1404 | return 1; /* op is not in inventory */ |
|
|
1405 | |
1399 | |
1406 | /* trying to unequip op */ |
1400 | /* trying to unequip op */ |
1407 | if (op->flag [FLAG_APPLIED]) |
1401 | if (op->flag [FLAG_APPLIED]) |
1408 | { |
1402 | { |
1409 | /* always apply, so no reason to unapply */ |
1403 | /* always apply, so no reason to unapply */ |
1410 | if (basic_flag == AP_APPLY) |
1404 | if (basic_flag == AP_APPLY) |
1411 | return 0; |
1405 | return 0; |
1412 | |
|
|
1413 | if (!(aflags & AP_IGNORE_CURSE) && (op->flag [FLAG_CURSED] || op->flag [FLAG_DAMNED])) |
|
|
1414 | { |
|
|
1415 | who->failmsgf ("No matter how hard you try, you just can't remove %s." CANNOT_REMOVE_CURSED, query_name (op)); |
|
|
1416 | return 1; |
|
|
1417 | } |
|
|
1418 | |
1406 | |
1419 | return unapply_special (who, op, aflags); |
1407 | return unapply_special (who, op, aflags); |
1420 | } |
1408 | } |
1421 | else if (basic_flag == AP_UNAPPLY) |
1409 | else if (basic_flag == AP_UNAPPLY) |
1422 | return 0; |
1410 | return 0; |
… | |
… | |
1540 | //TODO: unapplying should unapply the skill, though |
1528 | //TODO: unapplying should unapply the skill, though |
1541 | op->set_flag (FLAG_APPLIED); |
1529 | op->set_flag (FLAG_APPLIED); |
1542 | break; |
1530 | break; |
1543 | |
1531 | |
1544 | case SKILL: |
1532 | case SKILL: |
1545 | if (!(aflags & AP_NO_SLOT)) |
|
|
1546 | { |
|
|
1547 | // skill is used on it's own, as opposed to being a chosen_skill |
|
|
1548 | |
|
|
1549 | if (skill_flags [op->subtype] & (SF_NEED_ITEM | SF_MANA)) |
|
|
1550 | { |
|
|
1551 | who->failmsgf ( |
|
|
1552 | "You feel as if you wanted to do something funny, but you can't remember what. " |
|
|
1553 | "H<The %s skill needs something else to function, for example a tool, weapon, rod, or spell. " |
|
|
1554 | "It cannot be used on its own.>", |
|
|
1555 | &op->skill |
|
|
1556 | ); |
|
|
1557 | if (tmp) who->insert (tmp); |
|
|
1558 | return 1; |
|
|
1559 | } |
|
|
1560 | |
|
|
1561 | if (skill_flags [op->subtype] & SF_AUTARK |
|
|
1562 | || !(skill_flags [op->subtype] & (SF_COMBAT | SF_RANGED))) |
|
|
1563 | { |
|
|
1564 | if (skill_flags [op->subtype] & SF_USE) |
|
|
1565 | who->failmsgf ( |
|
|
1566 | "You feel as if you wanted to do something funny, but you can't remember what. " |
|
|
1567 | "H<The %s skill cannot be readied, instead, try C<use_skill %s>.>", |
|
|
1568 | &op->skill, &op->skill |
|
|
1569 | ); |
|
|
1570 | else |
|
|
1571 | who->failmsgf ( |
|
|
1572 | "You feel as if you wanted to do something funny, but you can't remember what. " |
|
|
1573 | "H<The %s skill cannot be readied or used, it is always active.>", |
|
|
1574 | &op->skill |
|
|
1575 | ); |
|
|
1576 | |
|
|
1577 | if (tmp) who->insert (tmp); |
|
|
1578 | |
|
|
1579 | return 1; |
|
|
1580 | } |
|
|
1581 | |
|
|
1582 | if (who->contr) |
1533 | if (who->contr) |
1583 | if (op->invisible) |
1534 | if (op->invisible) |
1584 | who->statusmsg (format ("You can now use the %s skill.", &op->skill)); |
1535 | who->statusmsg (format ("You can now use the %s skill.", &op->skill)); |
1585 | else |
1536 | else |
1586 | who->statusmsg (format ("You ready %s.", query_name (op))); |
1537 | who->statusmsg (format ("You ready %s.", query_name (op))); |
1587 | } |
|
|
1588 | |
1538 | |
1589 | who->set_flag (FLAG_READY_SKILL); |
1539 | who->set_flag (FLAG_READY_SKILL); |
1590 | op->set_flag (FLAG_APPLIED); |
1540 | op->set_flag (FLAG_APPLIED); |
1591 | change_abil (who, op); |
1541 | change_abil (who, op); |
1592 | break; |
1542 | break; |
… | |
… | |
1816 | * matching item. |
1766 | * matching item. |
1817 | **/ |
1767 | **/ |
1818 | void |
1768 | void |
1819 | handle_apply_yield (object *tmp) |
1769 | handle_apply_yield (object *tmp) |
1820 | { |
1770 | { |
1821 | if (shstr_tmp yield = tmp->kv (shstr_on_use_yield)) |
1771 | if (shstr_tmp yield = tmp->kv [shstr_on_use_yield]) |
1822 | archetype::get (yield)->insert_at (tmp, tmp, INS_BELOW_ORIGINATOR); |
1772 | archetype::get (yield)->insert_at (tmp, tmp, INS_BELOW_ORIGINATOR); |
1823 | } |
1773 | } |
1824 | |
1774 | |
1825 | /** |
1775 | /** |
1826 | * Handles applying a potion. |
1776 | * Handles applying a potion. |
… | |
… | |
1828 | int |
1778 | int |
1829 | apply_potion (object *op, object *tmp) |
1779 | apply_potion (object *op, object *tmp) |
1830 | { |
1780 | { |
1831 | int got_one = 0, i; |
1781 | int got_one = 0, i; |
1832 | object *force = 0; |
1782 | object *force = 0; |
1833 | |
|
|
1834 | object *floor = GET_MAP_OB (op->map, op->x, op->y); |
|
|
1835 | |
1783 | |
1836 | if (get_map_flags (op->map, NULL, op->x, op->y, NULL, NULL) & P_SAFE) |
1784 | if (get_map_flags (op->map, NULL, op->x, op->y, NULL, NULL) & P_SAFE) |
1837 | { |
1785 | { |
1838 | op->failmsg ("Gods prevent you from using this here, it's sacred ground!"); |
1786 | op->failmsg ("Gods prevent you from using this here, it's sacred ground!"); |
1839 | |
1787 | |
… | |
… | |
1993 | for (i = 0; i < NROFATTACKS; i++) |
1941 | for (i = 0; i < NROFATTACKS; i++) |
1994 | { |
1942 | { |
1995 | if (tmp->resist[i]) |
1943 | if (tmp->resist[i]) |
1996 | { |
1944 | { |
1997 | if (!force) |
1945 | if (!force) |
1998 | force = get_archetype (FORCE_NAME); |
1946 | force = archetype::get (FORCE_NAME); |
1999 | |
1947 | |
2000 | memcpy (force->resist, tmp->resist, sizeof (tmp->resist)); |
1948 | memcpy (force->resist, tmp->resist, sizeof (tmp->resist)); |
2001 | force->type = POTION_EFFECT; |
1949 | force->type = POTION_EFFECT; |
2002 | break; /* Only need to find one protection since we copy entire batch */ |
1950 | break; /* Only need to find one protection since we copy entire batch */ |
2003 | } |
1951 | } |
… | |
… | |
2061 | void |
2009 | void |
2062 | move_apply (object *trap, object *victim, object *originator) |
2010 | move_apply (object *trap, object *victim, object *originator) |
2063 | { |
2011 | { |
2064 | static int recursion_depth = 0; |
2012 | static int recursion_depth = 0; |
2065 | |
2013 | |
|
|
2014 | trap = trap->head_ (); |
|
|
2015 | |
2066 | /* Only exits affect DMs. */ |
2016 | /* Only exits affect DMs. */ |
2067 | if (victim->flag [FLAG_WIZPASS] && trap->type != EXIT && trap->type != SIGN) |
2017 | if (victim->flag [FLAG_WIZPASS] && trap->type != EXIT && trap->type != SIGN) |
2068 | return; |
2018 | return; |
2069 | |
2019 | |
2070 | /* move_apply() is the most likely candidate for causing unwanted and |
2020 | /* move_apply() is the most likely candidate for causing unwanted and |
2071 | * possibly unlimited recursion. |
2021 | * possibly unlimited recursion. |
2072 | */ |
2022 | */ |
|
|
2023 | |
2073 | /* The following was changed because it was causing perfectly correct |
2024 | /* The following was changed because it was causing perfectly correct |
2074 | * maps to fail. 1) it's not an error to recurse: |
2025 | * maps to fail. 1) it's not an error to recurse: |
2075 | * rune detonates, summoning monster. monster lands on nearby rune. |
2026 | * rune detonates, summoning monster. monster lands on nearby rune. |
2076 | * nearby rune detonates. This sort of recursion is expected and |
2027 | * nearby rune detonates. This sort of recursion is expected and |
2077 | * proper. This code was causing needless crashes. |
2028 | * proper. This code was causing needless crashes. |
… | |
… | |
2082 | "[trap arch %s, name %s; victim arch %s, name %s]\n", &trap->arch->archname, &trap->name, &victim->arch->archname, &victim->name); |
2033 | "[trap arch %s, name %s; victim arch %s, name %s]\n", &trap->arch->archname, &trap->name, &victim->arch->archname, &victim->name); |
2083 | return; |
2034 | return; |
2084 | } |
2035 | } |
2085 | |
2036 | |
2086 | recursion_depth++; |
2037 | recursion_depth++; |
2087 | if (trap->head) |
|
|
2088 | trap = trap->head; |
|
|
2089 | |
2038 | |
2090 | if (!INVOKE_OBJECT (MOVE_TRIGGER, trap, ARG_OBJECT (victim), ARG_OBJECT (originator))) |
2039 | if (!INVOKE_OBJECT (MOVE_TRIGGER, trap, ARG_OBJECT (victim), ARG_OBJECT (originator))) |
2091 | switch (trap->type) |
2040 | switch (trap->type) |
2092 | { |
2041 | { |
2093 | case PLAYERMOVER: |
2042 | case PLAYERMOVER: |
… | |
… | |
2103 | |
2052 | |
2104 | /* Just put in some sanity check. I think there is a bug in the |
2053 | /* Just put in some sanity check. I think there is a bug in the |
2105 | * above with some objects have zero speed, and thus the player |
2054 | * above with some objects have zero speed, and thus the player |
2106 | * getting permanently paralyzed. |
2055 | * getting permanently paralyzed. |
2107 | */ |
2056 | */ |
2108 | if (victim->speed_left < -50.f) |
2057 | victim->speed_left = max (-50.f, victim->speed_left); |
2109 | victim->speed_left = -50.f; |
|
|
2110 | /* LOG(llevDebug, "apply, playermove, player speed_left=%f\n", victim->speed_left); */ |
2058 | /* LOG(llevDebug, "apply, playermove, player speed_left=%f\n", victim->speed_left); */ |
2111 | } |
2059 | } |
2112 | break; |
2060 | break; |
2113 | |
2061 | |
2114 | case SPINNER: |
2062 | case SPINNER: |
… | |
… | |
2146 | case ARROW: |
2094 | case ARROW: |
2147 | /* bad bug: monster throw a object, make a step forwards, step on object , |
2095 | /* bad bug: monster throw a object, make a step forwards, step on object , |
2148 | * trigger this here and get hit by own missile - and will be own enemy. |
2096 | * trigger this here and get hit by own missile - and will be own enemy. |
2149 | * Victim then is his own enemy and will start to kill herself (this is |
2097 | * Victim then is his own enemy and will start to kill herself (this is |
2150 | * removed) but we have not synced victim and his missile. To avoid senseless |
2098 | * removed) but we have not synced victim and his missile. To avoid senseless |
2151 | * action, we avoid hits here |
2099 | * action, we avoid hits here |
2152 | */ |
2100 | */ |
2153 | if ((victim->flag [FLAG_ALIVE] && trap->has_active_speed ()) |
2101 | if ((victim->flag [FLAG_ALIVE] && trap->has_active_speed ()) |
2154 | && trap->owner != victim) |
2102 | && trap->owner != victim) |
2155 | hit_with_arrow (trap, victim); |
2103 | hit_with_arrow (trap, victim); |
2156 | break; |
2104 | break; |
… | |
… | |
2363 | if (failure <= -1 && failure > -15) |
2311 | if (failure <= -1 && failure > -15) |
2364 | { /* wonder */ |
2312 | { /* wonder */ |
2365 | object *tmp; |
2313 | object *tmp; |
2366 | |
2314 | |
2367 | op->failmsg ("Your spell warps!"); |
2315 | op->failmsg ("Your spell warps!"); |
2368 | tmp = get_archetype (SPELL_WONDER); |
2316 | tmp = archetype::get (SPELL_WONDER); |
2369 | cast_wonder (op, op, 0, tmp); |
2317 | cast_wonder (op, op, 0, tmp); |
2370 | tmp->destroy (); |
2318 | tmp->destroy (); |
2371 | } |
2319 | } |
2372 | else if (failure <= -15 && failure > -35) |
2320 | else if (failure <= -15 && failure > -35) |
2373 | { /* drain mana */ |
2321 | { /* drain mana */ |
… | |
… | |
2393 | op->failmsg ("The magic recoils on you!"); |
2341 | op->failmsg ("The magic recoils on you!"); |
2394 | blind_player (op, op, power); |
2342 | blind_player (op, op, power); |
2395 | } |
2343 | } |
2396 | else if (failure <= -80) |
2344 | else if (failure <= -80) |
2397 | { /* blast the immediate area */ |
2345 | { /* blast the immediate area */ |
2398 | object *tmp = get_archetype (LOOSE_MANA); |
2346 | object *tmp = archetype::get (LOOSE_MANA); |
2399 | cast_magic_storm (op, tmp, power); |
2347 | cast_magic_storm (op, tmp, power); |
2400 | op->failmsg ("You unleash uncontrolled mana!"); |
2348 | op->failmsg ("You unleash uncontrolled mana!"); |
2401 | tmp->destroy (); |
2349 | tmp->destroy (); |
2402 | } |
2350 | } |
2403 | } |
2351 | } |
… | |
… | |
3077 | * the selected object to "burn". -b.t. |
3025 | * the selected object to "burn". -b.t. |
3078 | */ |
3026 | */ |
3079 | static void |
3027 | static void |
3080 | apply_lighter (object *who, object *lighter) |
3028 | apply_lighter (object *who, object *lighter) |
3081 | { |
3029 | { |
3082 | int is_player_env = 0; |
|
|
3083 | |
|
|
3084 | if (object *item = who->mark ()) |
3030 | if (object *item = who->mark ()) |
3085 | { |
3031 | { |
3086 | if (!auto_apply_lighter (who, item, lighter)) |
3032 | if (!auto_apply_lighter (who, item, lighter)) |
3087 | return; |
3033 | return; |
3088 | |
3034 | |
… | |
… | |
3345 | |
3291 | |
3346 | strcpy (got, find); |
3292 | strcpy (got, find); |
3347 | got[len] = '\0'; |
3293 | got[len] = '\0'; |
3348 | |
3294 | |
3349 | /* Now create new item, remove used ones when required. */ |
3295 | /* Now create new item, remove used ones when required. */ |
3350 | new_item = get_archetype (got); |
3296 | new_item = archetype::get (got); |
3351 | if (!new_item) |
3297 | if (!new_item) |
3352 | { |
3298 | { |
3353 | pl->failmsgf ("This %s is strange, better to not use it.", query_base_name (marked, 0)); |
3299 | pl->failmsgf ("This %s is strange, better to not use it.", query_base_name (marked, 0)); |
3354 | return; |
3300 | return; |
3355 | } |
3301 | } |
… | |
… | |
3382 | * them in this function - they are passed to apply_special |
3328 | * them in this function - they are passed to apply_special |
3383 | */ |
3329 | */ |
3384 | static bool |
3330 | static bool |
3385 | manual_apply (object *who, object *op, int aflag) |
3331 | manual_apply (object *who, object *op, int aflag) |
3386 | { |
3332 | { |
3387 | op = op->head_ (); |
|
|
3388 | |
|
|
3389 | if (op->flag [FLAG_UNPAID] && !op->flag [FLAG_APPLIED]) |
|
|
3390 | { |
|
|
3391 | if (who->contr) |
|
|
3392 | { |
|
|
3393 | examine (who, op); |
|
|
3394 | //who->failmsg ("You should pay for it first! H<You cannot use items marked as unpaid.>");//TODO remove |
|
|
3395 | return 1; |
|
|
3396 | } |
|
|
3397 | else |
|
|
3398 | return 0; /* monsters just skip unpaid items */ |
|
|
3399 | } |
|
|
3400 | |
|
|
3401 | if (INVOKE_OBJECT (APPLY, op, ARG_OBJECT (who))) |
3333 | if (INVOKE_OBJECT (APPLY, op, ARG_OBJECT (who))) |
3402 | return RESULT_INT (0); |
3334 | return RESULT_INT (0); |
3403 | else if (apply_types_inv_only [op->type]) |
3335 | else if (apply_types_inv_only [op->type]) |
3404 | { |
3336 | { |
3405 | // special item, using slot system, needs to be in inv |
3337 | // special item, using slot system, needs to be in inv |
… | |
… | |
3435 | |
3367 | |
3436 | break; |
3368 | break; |
3437 | |
3369 | |
3438 | case EXIT: |
3370 | case EXIT: |
3439 | if (!EXIT_PATH (op)) |
3371 | if (!EXIT_PATH (op)) |
3440 | who->failmsgf ("The %s is closed. H<And will stay closed, until somebody fires up the map editor and adds it.>", query_name (op)); |
3372 | who->failmsgf ("The %s is closed. H<This exit doesn't lead anywhere at the moment, and this is unlikely to change.>", query_name (op)); |
3441 | else |
3373 | else |
3442 | { |
3374 | { |
3443 | /* Don't display messages for random maps. */ |
3375 | /* Don't display messages for random maps. */ |
3444 | if (op->msg && EXIT_PATH (op) != shstr_random_map_exit) |
3376 | if (op->msg && EXIT_PATH (op) != shstr_random_map_exit) |
3445 | who->statusmsg (op->msg, NDI_NAVY); |
3377 | who->statusmsg (op->msg, NDI_NAVY); |
… | |
… | |
3518 | check_improve_weapon (who, op); |
3450 | check_improve_weapon (who, op); |
3519 | break; |
3451 | break; |
3520 | |
3452 | |
3521 | case CLOCK: |
3453 | case CLOCK: |
3522 | { |
3454 | { |
3523 | char buf[MAX_BUF]; |
|
|
3524 | timeofday_t tod; |
3455 | timeofday_t tod; |
3525 | |
3456 | |
3526 | get_tod (&tod); |
3457 | get_tod (&tod); |
3527 | who->play_sound (sound_find ("sound_clock")); |
3458 | who->play_sound (sound_find ("sound_clock")); |
3528 | who->statusmsg (format ( |
3459 | who->statusmsg (format ( |
… | |
… | |
3552 | |
3483 | |
3553 | return 1; |
3484 | return 1; |
3554 | } |
3485 | } |
3555 | else |
3486 | else |
3556 | { |
3487 | { |
3557 | who->statusmsg (format ("I don't know how to apply the %s.", query_name (op))); |
3488 | who->statusmsg (format ("I don't know how to apply the %s. H<This object cannot be applied.>", query_name (op))); |
3558 | return 0; |
3489 | return 0; |
3559 | } |
3490 | } |
3560 | } |
3491 | } |
3561 | |
3492 | |
3562 | /** |
3493 | /** |
… | |
… | |
3625 | object::apply (object *ob, int aflags) |
3556 | object::apply (object *ob, int aflags) |
3626 | { |
3557 | { |
3627 | if (!ob) // simplifies a lot of callers |
3558 | if (!ob) // simplifies a lot of callers |
3628 | return true; |
3559 | return true; |
3629 | |
3560 | |
|
|
3561 | ob = ob->head_ (); |
|
|
3562 | |
|
|
3563 | if (ob->flag [FLAG_UNPAID] && !ob->flag [FLAG_APPLIED]) |
|
|
3564 | { |
|
|
3565 | if (contr) |
|
|
3566 | { |
|
|
3567 | examine (this, ob); |
|
|
3568 | //who->failmsg ("You should pay for it first! H<You cannot use items marked as unpaid.>");//TODO remove |
|
|
3569 | return 1; |
|
|
3570 | } |
|
|
3571 | else |
|
|
3572 | return 0; /* monsters just skip unpaid items */ |
|
|
3573 | } |
|
|
3574 | |
3630 | if (contr) |
3575 | if (contr) |
3631 | { |
3576 | { |
3632 | if (!ob->env && (move_type & MOVE_FLYING)) |
3577 | if (!ob->env && (move_type & MOVE_FLYING)) |
3633 | { |
3578 | { |
3634 | /* player is flying and applying object not in inventory */ |
3579 | /* player is flying and applying object not in inventory */ |
… | |
… | |
3647 | bool want_apply = |
3592 | bool want_apply = |
3648 | aflags & AP_APPLY ? true |
3593 | aflags & AP_APPLY ? true |
3649 | : aflags & AP_UNAPPLY ? false |
3594 | : aflags & AP_UNAPPLY ? false |
3650 | : !ob->flag [FLAG_APPLIED]; // AP_TOGGLE |
3595 | : !ob->flag [FLAG_APPLIED]; // AP_TOGGLE |
3651 | |
3596 | |
|
|
3597 | // cannot unapply cursed items |
|
|
3598 | if (!want_apply |
|
|
3599 | && (ob->flag [FLAG_CURSED] || ob->flag [FLAG_DAMNED]) |
|
|
3600 | && ob->flag [FLAG_APPLIED] |
|
|
3601 | && !(aflags & AP_IGNORE_CURSE)) |
|
|
3602 | { |
|
|
3603 | failmsgf ("No matter how hard you try, you just can't remove %s." CANNOT_REMOVE_CURSED, ob->query_name ()); |
|
|
3604 | return 0; |
|
|
3605 | } |
|
|
3606 | |
3652 | object_ptr *slot = 0; |
3607 | object_ptr *slot = 0; |
3653 | |
3608 | |
3654 | // detect the slot, if this is a player |
3609 | // detect the slot, if this is a player |
3655 | if (contr && !(aflags & AP_NO_SLOT)) |
3610 | if (contr && !(aflags & AP_NO_SLOT)) |
3656 | { |
3611 | { |
… | |
… | |
3661 | case WEAPON: |
3616 | case WEAPON: |
3662 | slot = &contr->combat_ob; |
3617 | slot = &contr->combat_ob; |
3663 | oslot = contr->ranged_ob; |
3618 | oslot = contr->ranged_ob; |
3664 | break; |
3619 | break; |
3665 | |
3620 | |
|
|
3621 | case RANGED: |
3666 | case BOW: |
3622 | case BOW: |
3667 | case RANGED: |
|
|
3668 | case SPELL: |
3623 | case SPELL: |
3669 | case WAND: |
3624 | case WAND: |
3670 | case ROD: |
3625 | case ROD: |
3671 | case HORN: |
3626 | case HORN: |
3672 | case BUILDER: |
3627 | case BUILDER: |
… | |
… | |
3674 | oslot = contr->combat_ob; |
3629 | oslot = contr->combat_ob; |
3675 | break; |
3630 | break; |
3676 | |
3631 | |
3677 | // oh, the humanity |
3632 | // oh, the humanity |
3678 | case SKILL: |
3633 | case SKILL: |
3679 | if (aflags & AP_NO_SLOT) |
3634 | // skill is used on it's own, as opposed to being a chosen_skill |
|
|
3635 | |
|
|
3636 | if (skill_flags [ob->subtype] & (SF_NEED_ITEM | SF_MANA)) |
3680 | break; |
3637 | { |
|
|
3638 | failmsgf ( |
|
|
3639 | "You feel as if you wanted to do something funny, but you can't remember what. " |
|
|
3640 | "H<The %s skill needs something else to function, for example a tool, weapon, rod, or spell. " |
|
|
3641 | "It cannot be used on its own.>", |
|
|
3642 | &ob->skill |
|
|
3643 | ); |
|
|
3644 | return 1; |
|
|
3645 | } |
|
|
3646 | |
|
|
3647 | if (skill_flags [ob->subtype] & SF_AUTARK |
|
|
3648 | || !(skill_flags [ob->subtype] & (SF_COMBAT | SF_RANGED))) |
|
|
3649 | { |
|
|
3650 | if (skill_flags [ob->subtype] & SF_USE) |
|
|
3651 | failmsgf ( |
|
|
3652 | "You feel as if you wanted to do something funny, but you can't remember what. " |
|
|
3653 | "H<The %s skill cannot be readied, instead, try C<use_skill %s>.>", |
|
|
3654 | &ob->skill, &ob->skill |
|
|
3655 | ); |
|
|
3656 | else |
|
|
3657 | failmsgf ( |
|
|
3658 | "You feel as if you wanted to do something funny, but you can't remember what. " |
|
|
3659 | "H<The %s skill cannot be readied or used, it is always active.>", |
|
|
3660 | &ob->skill |
|
|
3661 | ); |
|
|
3662 | |
|
|
3663 | return 1; |
|
|
3664 | } |
3681 | |
3665 | |
3682 | if (skill_flags [ob->subtype] & SF_NEED_ITEM) |
3666 | if (skill_flags [ob->subtype] & SF_NEED_ITEM) |
3683 | break; |
3667 | break; |
3684 | |
3668 | |
3685 | if (skill_flags [ob->subtype] & SF_COMBAT) |
3669 | if (skill_flags [ob->subtype] & SF_COMBAT) |
… | |
… | |
3702 | // only one slot can be active |
3686 | // only one slot can be active |
3703 | if (want_apply) |
3687 | if (want_apply) |
3704 | { |
3688 | { |
3705 | // clear slot unless we are in it already |
3689 | // clear slot unless we are in it already |
3706 | if (*slot != ob) |
3690 | if (*slot != ob) |
3707 | apply (*slot, AP_UNAPPLY); |
3691 | if (!apply (*slot, AP_UNAPPLY)) |
|
|
3692 | return false; |
3708 | |
3693 | |
3709 | // unapply other slot, because we want to become active |
3694 | // unapply other slot, because we want to become active |
3710 | apply (oslot, AP_UNAPPLY); |
3695 | if (!apply (oslot, AP_UNAPPLY)) |
|
|
3696 | return false; |
3711 | } |
3697 | } |
3712 | |
3698 | |
3713 | // clear item from slot if applied |
3699 | // clear item from slot if applied |
3714 | if (!want_apply && current_weapon == ob) |
3700 | if (!want_apply && current_weapon == ob) |
3715 | current_weapon = 0; |
3701 | current_weapon = 0; |
… | |
… | |
3734 | * Generates shop floor's item, and treasures. |
3720 | * Generates shop floor's item, and treasures. |
3735 | */ |
3721 | */ |
3736 | int |
3722 | int |
3737 | auto_apply (object *op) |
3723 | auto_apply (object *op) |
3738 | { |
3724 | { |
3739 | object *tmp = NULL, *tmp2; |
3725 | object *tmp = NULL; |
3740 | int i; |
3726 | int i; |
3741 | |
3727 | |
3742 | op->clr_flag (FLAG_AUTO_APPLY); |
3728 | op->clr_flag (FLAG_AUTO_APPLY); |
3743 | |
3729 | |
3744 | switch (op->type) |
3730 | switch (op->type) |
… | |
… | |
3830 | while (invtmp->stats.hp-- > 0) |
3816 | while (invtmp->stats.hp-- > 0) |
3831 | create_treasure (invtmp->randomitems, invtmp, 0, difficulty, 0); |
3817 | create_treasure (invtmp->randomitems, invtmp, 0, difficulty, 0); |
3832 | |
3818 | |
3833 | invtmp->randomitems = NULL; |
3819 | invtmp->randomitems = NULL; |
3834 | } |
3820 | } |
3835 | else if (invtmp && invtmp->arch |
3821 | else if (invtmp->arch |
3836 | && invtmp->type != TREASURE && invtmp->type != SPELL && invtmp->type != CLASS && invtmp->has_random_items ()) |
3822 | && invtmp->type != TREASURE && invtmp->type != SPELL && invtmp->type != CLASS |
|
|
3823 | && invtmp->has_random_items ()) |
3837 | { |
3824 | { |
3838 | create_treasure (invtmp->randomitems, invtmp, 0, difficulty, 0); |
3825 | create_treasure (invtmp->randomitems, invtmp, 0, difficulty, 0); |
3839 | /* Need to clear this so that we never try to create |
3826 | /* Need to clear this so that we never try to create |
3840 | * treasure again for this object |
3827 | * treasure again for this object |
3841 | */ |
3828 | */ |