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 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 (©) 2001 Mark Wedel & Crossfire Development Team |
6 | * Copyright (©) 2001 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 |
9 | * the terms of the Affero GNU General Public License as published by the |
10 | * 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 |
11 | * Free Software Foundation, either version 3 of the License, or (at your |
11 | * option) any later version. |
12 | * option) any later version. |
12 | * |
13 | * |
13 | * This program is distributed in the hope that it will be useful, |
14 | * This program is distributed in the hope that it will be useful, |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | * GNU General Public License for more details. |
17 | * GNU General Public License for more details. |
17 | * |
18 | * |
18 | * You should have received a copy of the Affero GNU General Public License |
19 | * 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 |
20 | * and the GNU General Public License along with this program. If not, see |
20 | * <http://www.gnu.org/licenses/>. |
21 | * <http://www.gnu.org/licenses/>. |
21 | * |
22 | * |
22 | * The authors can be reached via e-mail to <support@deliantra.net> |
23 | * The authors can be reached via e-mail to <support@deliantra.net> |
23 | */ |
24 | */ |
24 | |
25 | |
25 | #include <cmath> |
26 | #include <cmath> |
26 | |
27 | |
… | |
… | |
65 | |
66 | |
66 | static const struct apply_types_player_only : typeset |
67 | static const struct apply_types_player_only : typeset |
67 | { |
68 | { |
68 | apply_types_player_only () |
69 | apply_types_player_only () |
69 | { |
70 | { |
|
|
71 | set (TRANSPORT); |
70 | set (EXIT); |
72 | set (EXIT); |
71 | set (BOOK); |
73 | set (BOOK); |
72 | set (SIGN); |
74 | set (SIGN); |
73 | set (BOOK); |
75 | set (BOOK); |
74 | set (SKILLSCROLL); |
76 | set (SKILLSCROLL); |
… | |
… | |
250 | */ |
252 | */ |
251 | static int |
253 | static int |
252 | prepare_weapon (object *op, object *improver, object *weapon) |
254 | prepare_weapon (object *op, object *improver, object *weapon) |
253 | { |
255 | { |
254 | int sacrifice_count, i; |
256 | int sacrifice_count, i; |
255 | char buf[MAX_BUF]; |
|
|
256 | |
257 | |
257 | if (weapon->level != 0) |
258 | if (weapon->level != 0) |
258 | { |
259 | { |
259 | op->failmsg ("Weapon is already prepared!"); |
260 | op->failmsg ("Weapon is already prepared!"); |
260 | return 0; |
261 | return 0; |
… | |
… | |
289 | "Your sacrifice was accepted." |
290 | "Your sacrifice was accepted." |
290 | "Your *%s may be improved %d times.", |
291 | "Your *%s may be improved %d times.", |
291 | &weapon->name, weapon->level |
292 | &weapon->name, weapon->level |
292 | )); |
293 | )); |
293 | |
294 | |
294 | sprintf (buf, "%s's %s", &op->name, &weapon->name); |
295 | weapon->name = weapon->name_pl = format ("%s's %s", &op->name, &weapon->name); |
295 | weapon->name = weapon->name_pl = buf; |
|
|
296 | weapon->nrof = 0; /* prevents preparing n weapons in the same |
296 | weapon->nrof = 0; /* prevents preparing n weapons in the same |
297 | slot at once! */ |
297 | slot at once! */ |
298 | improver->decrease (); |
298 | improver->decrease (); |
299 | weapon->last_eat = 0; |
299 | weapon->last_eat = 0; |
300 | return 1; |
300 | return 1; |
… | |
… | |
306 | * Returns 0 if it was not able to work for some reason. |
306 | * Returns 0 if it was not able to work for some reason. |
307 | * |
307 | * |
308 | * Checks if weapon was prepared, if enough potions on the floor, ... |
308 | * Checks if weapon was prepared, if enough potions on the floor, ... |
309 | * |
309 | * |
310 | * We are hiding extra information about the weapon in the level and |
310 | * We are hiding extra information about the weapon in the level and |
311 | * last_eat numbers for an object. Hopefully this won't break anything ?? |
311 | * last_eat numbers for an object. Hopefully this won't break anything ?? |
312 | * level == max improve last_eat == current improve |
312 | * level == max improve last_eat == current improve |
313 | */ |
313 | */ |
314 | static int |
314 | static int |
315 | improve_weapon (object *op, object *improver, object *weapon) |
315 | improve_weapon (object *op, object *improver, object *weapon) |
316 | { |
316 | { |
… | |
… | |
341 | "powerful for you to use. Unready it if you " |
341 | "powerful for you to use. Unready it if you " |
342 | "really want to improve it."); |
342 | "really want to improve it."); |
343 | return 0; |
343 | return 0; |
344 | } |
344 | } |
345 | |
345 | |
346 | /* This just increases damage by 5 points, no matter what. No sacrifice |
346 | /* This just increases damage by 5 points, no matter what. No sacrifice |
347 | * is needed. Since stats.dam is now a 16 bit value and not 8 bit, |
347 | * is needed. Since stats.dam is now a 16 bit value and not 8 bit, |
348 | * don't put any maximum value on damage - the limit is how much the |
348 | * don't put any maximum value on damage - the limit is how much the |
349 | * weapon can be improved. |
349 | * weapon can be improved. |
350 | */ |
350 | */ |
351 | if (improver->stats.sp == IMPROVE_DAMAGE) |
351 | if (improver->stats.sp == IMPROVE_DAMAGE) |
352 | { |
352 | { |
353 | weapon->stats.dam += 5; |
353 | weapon->stats.dam += 5; |
354 | weapon->weight += 5000; /* 5 KG's */ |
354 | weapon->weight += 5000; /* 5 KG's */ |
… | |
… | |
477 | * the stats of a player w/ armour as well as a weapon |
477 | * the stats of a player w/ armour as well as a weapon |
478 | * will probably horribly unbalance the game. Magic enchanting |
478 | * will probably horribly unbalance the game. Magic enchanting |
479 | * depends on the level of the character - ie the plus |
479 | * depends on the level of the character - ie the plus |
480 | * value (magic) of the armour can never be increased beyond |
480 | * value (magic) of the armour can never be increased beyond |
481 | * the level of the character / 10 -- rounding upish, nor may |
481 | * the level of the character / 10 -- rounding upish, nor may |
482 | * the armour value of the piece of equipment exceed either |
482 | * the armour value of the piece of equipment exceed either |
483 | * the users level or 90) |
483 | * the users level or 90) |
484 | * Modified by MSW for partial resistance. Only support |
484 | * Modified by MSW for partial resistance. Only support |
485 | * changing of physical area right now. |
485 | * changing of physical area right now. |
486 | */ |
486 | */ |
487 | static int |
487 | static int |
… | |
… | |
668 | item->nrof *= nr; |
668 | item->nrof *= nr; |
669 | |
669 | |
670 | if (converter->flag [FLAG_PRECIOUS]) |
670 | if (converter->flag [FLAG_PRECIOUS]) |
671 | item->set_flag (FLAG_UNPAID); |
671 | item->set_flag (FLAG_UNPAID); |
672 | |
672 | |
673 | if (converter->is_in_shop ()) |
673 | if (converter->is_in_shop ()) |
674 | { |
674 | { |
675 | // converters on shop floors don't work anymore, bug lets check for it |
675 | // converters on shop floors don't work anymore, bug lets check for it |
676 | // and report in case someone still does it. |
676 | // and report in case someone still does it. |
677 | LOG (llevDebug, "ITEMBUG: broken converter, converters on shop floor don't work: %s\n", |
677 | LOG (llevDebug, "ITEMBUG: broken converter, converters on shop floor don't work: %s\n", |
678 | converter->debug_desc ()); |
678 | converter->debug_desc ()); |
… | |
… | |
681 | else if (price_in < sint64 (item->nrof) * item->value) |
681 | else if (price_in < sint64 (item->nrof) * item->value) |
682 | { |
682 | { |
683 | LOG (llevDebug, "converter output price higher than input: %s at %s (%d, %d) in value %d, out value %d for %s\n", |
683 | LOG (llevDebug, "converter output price higher than input: %s at %s (%d, %d) in value %d, out value %d for %s\n", |
684 | &converter->name, &converter->map->path, converter->x, converter->y, price_in, item->nrof * item->value, &item->name); |
684 | &converter->name, &converter->map->path, converter->x, converter->y, price_in, item->nrof * item->value, &item->name); |
685 | /** |
685 | /** |
686 | * elmex: we are going to let the game continue, as the mapcreator |
686 | * elmex: we are going to let the game continue, as the mapcreator |
687 | * hopefully had something in mind when doing this. |
687 | * hopefully had something in mind when doing this. |
688 | */ |
688 | */ |
689 | } |
689 | } |
690 | |
690 | |
691 | // elmex: only identify if we need to, for example so that generated money doesn't |
691 | // elmex: only identify if we need to, for example so that generated money doesn't |
692 | // get an 'identified' flag so easily. |
692 | // get an 'identified' flag so easily. |
693 | if (need_identify (item)) |
693 | if (item->need_identify ()) |
694 | identify (item); |
694 | identify (item); |
695 | |
695 | |
696 | insert_ob_in_map_at (item, converter->map, converter, 0, converter->x, converter->y); |
696 | item->insert_at (converter, 0, INS_NO_WALK_ON); |
|
|
697 | |
697 | return 1; |
698 | return 1; |
698 | } |
699 | } |
699 | |
700 | |
700 | /** |
701 | /** |
701 | * Handle apply on containers. |
702 | * Handle apply on containers. |
702 | * By Eneq(@csd.uu.se). |
703 | * By Eneq(@csd.uu.se). |
703 | * Moved to own function and added many features [Tero.Haatanen@lut.fi] |
704 | * Moved to own function and added many features [Tero.Haatanen@lut.fi] |
704 | * added the alchemical cauldron to the code -b.t. |
705 | * added the alchemical cauldron to the code -b.t. |
705 | */ |
706 | */ |
706 | static int |
707 | static int |
… | |
… | |
732 | op->close_container (); |
733 | op->close_container (); |
733 | return 1; |
734 | return 1; |
734 | } |
735 | } |
735 | else if (!sack->env) |
736 | else if (!sack->env) |
736 | { |
737 | { |
737 | // active, but not ours: some other player has opened it |
738 | // active on floor, but not ours: some other player has opened it |
|
|
739 | // normally this only happens to dms standing on the same space. |
|
|
740 | // but it doesn't hurt to handle it. |
738 | op->failmsgf ("Somebody else is using the %s already.", query_name (sack)); |
741 | op->failmsgf ("Somebody else is using the %s already.", query_name (sack)); |
739 | return 1; |
742 | return 1; |
740 | } |
743 | } |
|
|
744 | } |
741 | |
745 | |
742 | // fall through to opening it (active in inv) |
746 | // it's locked? |
|
|
747 | if (sack->slaying) |
743 | } |
748 | { |
744 | else if (sack->env) |
749 | if (object *tmp = find_key (op, op, sack)) |
|
|
750 | { |
|
|
751 | op->statusmsg (format ("You unlock %s with %s.", query_name (sack), query_name (tmp))); |
|
|
752 | } |
|
|
753 | else |
|
|
754 | { |
|
|
755 | sack->flag [FLAG_APPLIED] = false; // might be applied in inv, let the user close it |
|
|
756 | esrv_update_item (UPD_FLAGS, op, sack); |
|
|
757 | op->statusmsg (format ("You don't have the key to unlock %s.", query_name (sack))); |
|
|
758 | return 1; |
|
|
759 | } |
|
|
760 | } |
|
|
761 | |
|
|
762 | if (sack->env && !sack->flag [FLAG_APPLIED]) |
745 | { |
763 | { |
746 | // it is in our env, so activate it, do not open yet |
764 | // it is in our env, so activate it, do not open yet |
747 | op->close_container (); |
765 | op->close_container (); |
748 | sack->flag [FLAG_APPLIED] = 1; |
766 | sack->flag [FLAG_APPLIED] = true; |
749 | esrv_update_item (UPD_FLAGS, op, sack); |
767 | esrv_update_item (UPD_FLAGS, op, sack); |
750 | op->statusmsg (format ("You ready %s.", query_name (sack))); |
768 | op->statusmsg (format ("You ready %s.", query_name (sack))); |
751 | return 1; |
|
|
752 | } |
|
|
753 | |
|
|
754 | // it's locked? |
|
|
755 | if (sack->slaying) |
|
|
756 | { |
769 | } |
757 | if (object *tmp = find_key (op, op, sack)) |
|
|
758 | op->statusmsg (format ("You unlock %s with %s.", query_name (sack), query_name (tmp))); |
|
|
759 | else |
770 | else |
760 | { |
|
|
761 | op->statusmsg (format ("You don't have the key to unlock %s.", query_name (sack))); |
|
|
762 | return 1; |
|
|
763 | } |
|
|
764 | } |
|
|
765 | |
|
|
766 | op->open_container (sack); |
771 | op->open_container (sack); |
767 | |
772 | |
768 | return 1; |
773 | return 1; |
769 | } |
774 | } |
770 | |
775 | |
771 | /** |
776 | /** |
… | |
… | |
864 | { |
869 | { |
865 | /* Somebody dropped an unpaid item, just move to an adjacent place. */ |
870 | /* Somebody dropped an unpaid item, just move to an adjacent place. */ |
866 | int i = find_free_spot (op, op->map, op->x, op->y, 1, 9); |
871 | int i = find_free_spot (op, op->map, op->x, op->y, 1, 9); |
867 | |
872 | |
868 | if (i != -1) |
873 | if (i != -1) |
869 | rv = transfer_ob (op, op->x + freearr_x[i], op->y + freearr_y[i], 0, shop_mat); |
874 | rv = transfer_ob (op, op->x + DIRX (i), op->y + DIRY (i), 0, shop_mat); |
870 | |
875 | |
871 | return 0; |
876 | return 0; |
872 | } |
877 | } |
873 | |
878 | |
874 | /* Removed code that checked for multipart objects - it appears that |
879 | /* Removed code that checked for multipart objects - it appears that |
… | |
… | |
917 | if (i == -1) |
922 | if (i == -1) |
918 | LOG (llevError, "Internal shop-mat problem.\n"); |
923 | LOG (llevError, "Internal shop-mat problem.\n"); |
919 | else |
924 | else |
920 | { |
925 | { |
921 | op->remove (); |
926 | op->remove (); |
922 | op->x += freearr_x[i]; |
927 | op->x += DIRX (i); |
923 | op->y += freearr_y[i]; |
928 | op->y += DIRY (i); |
924 | rv = insert_ob_in_map (op, op->map, shop_mat, 0) == NULL; |
929 | rv = insert_ob_in_map (op, op->map, shop_mat, 0) == NULL; |
925 | } |
930 | } |
926 | } |
931 | } |
927 | |
932 | |
928 | op->clr_flag (FLAG_NO_APPLY); |
933 | op->clr_flag (FLAG_NO_APPLY); |
… | |
… | |
968 | } |
973 | } |
969 | |
974 | |
970 | /* Sign or magic mouth? Do we need to see it, or does it talk to us? |
975 | /* Sign or magic mouth? Do we need to see it, or does it talk to us? |
971 | * No way to know for sure. The presumption is basically that if |
976 | * No way to know for sure. The presumption is basically that if |
972 | * move_on is zero, it needs to be manually applied (doesn't talk |
977 | * move_on is zero, it needs to be manually applied (doesn't talk |
973 | * to us). |
978 | * to us). |
974 | */ |
979 | */ |
975 | if (op->flag [FLAG_BLIND] && !op->flag [FLAG_WIZ] && !sign->move_on) |
980 | if (op->flag [FLAG_BLIND] && !op->flag [FLAG_WIZ] && !sign->move_on) |
976 | { |
981 | { |
977 | op->failmsg ("You are unable to read while blind!"); |
982 | op->failmsg ("You are unable to read while blind!"); |
978 | return; |
983 | return; |
… | |
… | |
1015 | |
1020 | |
1016 | victim->play_sound (trap->sound ? trap->sound : sound_find ("fall_hole")); |
1021 | victim->play_sound (trap->sound ? trap->sound : sound_find ("fall_hole")); |
1017 | victim->statusmsg ("You fall through the hole!", NDI_RED); |
1022 | victim->statusmsg ("You fall through the hole!", NDI_RED); |
1018 | |
1023 | |
1019 | transfer_ob (victim, |
1024 | transfer_ob (victim, |
1020 | EXIT_X (trap) + freearr_x[dir], |
1025 | EXIT_X (trap) + DIRX (dir), |
1021 | EXIT_Y (trap) + freearr_y[dir], |
1026 | EXIT_Y (trap) + DIRY (dir), |
1022 | 0, victim); |
1027 | 0, victim); |
1023 | } |
1028 | } |
1024 | |
1029 | |
1025 | /** |
1030 | /** |
1026 | * Unapplies specified item. |
1031 | * Unapplies specified item. |
… | |
… | |
1059 | who->flag [FLAG_READY_WEAPON] = false; |
1064 | who->flag [FLAG_READY_WEAPON] = false; |
1060 | |
1065 | |
1061 | // unapplying a weapon or skill tool should also unapply the skill it governs |
1066 | // unapplying a weapon or skill tool should also unapply the skill it governs |
1062 | // but this is hard, as it shouldn't do so when the skill can |
1067 | // but this is hard, as it shouldn't do so when the skill can |
1063 | // be used for other reasons |
1068 | // be used for other reasons |
|
|
1069 | //TODO: really? |
1064 | if (who->chosen_skill) |
1070 | if (who->chosen_skill) |
1065 | if (!who->chosen_skill->flag [FLAG_CAN_USE_SKILL]) |
1071 | if (!who->chosen_skill->flag [FLAG_CAN_USE_SKILL]) |
1066 | unapply_special (who, op, 0); |
1072 | unapply_special (who, who->chosen_skill, 0); |
1067 | |
1073 | |
1068 | break; |
1074 | break; |
1069 | |
1075 | |
|
|
1076 | case RANGED: |
1070 | case BOW: |
1077 | case BOW: |
1071 | case WAND: |
1078 | case WAND: |
1072 | case ROD: |
1079 | case ROD: |
1073 | case HORN: |
1080 | case HORN: |
1074 | case RANGED: |
|
|
1075 | if (player *pl = who->contr) |
1081 | if (player *pl = who->contr) |
1076 | { |
1082 | { |
1077 | who->statusmsg (format ("You unready %s.", query_name (op))); |
1083 | who->statusmsg (format ("You unready %s.", query_name (op))); |
1078 | change_abil (who, op); |
1084 | change_abil (who, op); |
1079 | } |
1085 | } |
… | |
… | |
1281 | |
1287 | |
1282 | /* if we have an applied weapon/shield, and unapply it would free |
1288 | /* if we have an applied weapon/shield, and unapply it would free |
1283 | * enough slots to equip the new item, then just set "can |
1289 | * enough slots to equip the new item, then just set "can |
1284 | * apply unapply". We don't care about the logic below - if you have a |
1290 | * apply unapply". We don't care about the logic below - if you have a |
1285 | * shield equipped and try to equip another shield, there is only |
1291 | * shield equipped and try to equip another shield, there is only |
1286 | * one choice. However, the check for the number of body locations |
1292 | * one choice. However, the check for the number of body locations |
1287 | * does take into the account cases where what is being applied |
1293 | * does take into the account cases where what is being applied |
1288 | * may be two handed for example. |
1294 | * may be two handed for example. |
1289 | */ |
1295 | */ |
1290 | if (ws) |
1296 | if (ws) |
1291 | if ((who->slot[i].used - ws->slot[i].info + op->slot[i].info) >= 0) |
1297 | if ((who->slot[i].used - ws->slot[i].info + op->slot[i].info) >= 0) |
… | |
… | |
1310 | else if (tmp != tmp1) |
1316 | else if (tmp != tmp1) |
1311 | retval |= CAN_APPLY_UNAPPLY_MULT; |
1317 | retval |= CAN_APPLY_UNAPPLY_MULT; |
1312 | |
1318 | |
1313 | /* This object isn't using up all the slots, so there must |
1319 | /* This object isn't using up all the slots, so there must |
1314 | * be another. If so, and it the new item doesn't need all |
1320 | * be another. If so, and it the new item doesn't need all |
1315 | * the slots, the player then has a choice. |
1321 | * the slots, the player then has a choice. |
1316 | */ |
1322 | */ |
1317 | if ((who->slot[i].used - tmp1->slot[i].info != who->slot[i].info) |
1323 | if ((who->slot[i].used - tmp1->slot[i].info != who->slot[i].info) |
1318 | && abs (op->slot[i].info) < who->slot[i].info) |
1324 | && abs (op->slot[i].info) < who->slot[i].info) |
1319 | retval |= CAN_APPLY_UNAPPLY_CHOICE; |
1325 | retval |= CAN_APPLY_UNAPPLY_CHOICE; |
1320 | |
1326 | |
… | |
… | |
1388 | |
1394 | |
1389 | static bool |
1395 | static bool |
1390 | apply_special (object *who, object *op, int aflags) |
1396 | apply_special (object *who, object *op, int aflags) |
1391 | { |
1397 | { |
1392 | int basic_flag = aflags & AP_MODE; |
1398 | int basic_flag = aflags & AP_MODE; |
1393 | object *tmp, *tmp2, *skop = NULL; |
1399 | object *tmp, *skop = NULL; |
1394 | |
|
|
1395 | if (who == NULL) |
|
|
1396 | { |
|
|
1397 | LOG (llevError, "apply_special() from object without environment.\n"); |
|
|
1398 | return 1; |
|
|
1399 | } |
|
|
1400 | |
|
|
1401 | //TODO: remove these when apply_special is no longer exposed |
|
|
1402 | if (op->env != who) |
|
|
1403 | return 1; /* op is not in inventory */ |
|
|
1404 | |
1400 | |
1405 | /* trying to unequip op */ |
1401 | /* trying to unequip op */ |
1406 | if (op->flag [FLAG_APPLIED]) |
1402 | if (op->flag [FLAG_APPLIED]) |
1407 | { |
1403 | { |
1408 | /* always apply, so no reason to unapply */ |
1404 | /* always apply, so no reason to unapply */ |
1409 | if (basic_flag == AP_APPLY) |
1405 | if (basic_flag == AP_APPLY) |
1410 | return 0; |
1406 | return 0; |
1411 | |
|
|
1412 | if (!(aflags & AP_IGNORE_CURSE) && (op->flag [FLAG_CURSED] || op->flag [FLAG_DAMNED])) |
|
|
1413 | { |
|
|
1414 | who->failmsgf ("No matter how hard you try, you just can't remove %s." CANNOT_REMOVE_CURSED, query_name (op)); |
|
|
1415 | return 1; |
|
|
1416 | } |
|
|
1417 | |
1407 | |
1418 | return unapply_special (who, op, aflags); |
1408 | return unapply_special (who, op, aflags); |
1419 | } |
1409 | } |
1420 | else if (basic_flag == AP_UNAPPLY) |
1410 | else if (basic_flag == AP_UNAPPLY) |
1421 | return 0; |
1411 | return 0; |
… | |
… | |
1483 | return 1; |
1473 | return 1; |
1484 | } |
1474 | } |
1485 | |
1475 | |
1486 | /* Ok. We are now at the state where we can apply the new object. |
1476 | /* Ok. We are now at the state where we can apply the new object. |
1487 | * Note that we don't have the checks for can_use_... |
1477 | * Note that we don't have the checks for can_use_... |
1488 | * below - that is already taken care of by can_apply_object. |
1478 | * below - that is already taken care of by can_apply_object. |
1489 | */ |
1479 | */ |
1490 | |
1480 | |
1491 | // split away all the other items from the stack, so only one item is left |
1481 | // split away all the other items from the stack, so only one item is left |
1492 | tmp = op->nrof > 1 ? op->split (op->nrof - 1) : 0; |
1482 | tmp = op->nrof > 1 ? op->split (op->nrof - 1) : 0; |
1493 | |
1483 | |
… | |
… | |
1539 | //TODO: unapplying should unapply the skill, though |
1529 | //TODO: unapplying should unapply the skill, though |
1540 | op->set_flag (FLAG_APPLIED); |
1530 | op->set_flag (FLAG_APPLIED); |
1541 | break; |
1531 | break; |
1542 | |
1532 | |
1543 | case SKILL: |
1533 | case SKILL: |
1544 | if (!(aflags & AP_NO_SLOT)) |
|
|
1545 | { |
|
|
1546 | // skill is used on it's own, as opposed to being a chosen_skill |
|
|
1547 | |
|
|
1548 | if (skill_flags [op->subtype] & (SF_NEED_ITEM | SF_MANA)) |
|
|
1549 | { |
|
|
1550 | who->failmsgf ( |
|
|
1551 | "You feel as if you wanted to do something funny, but you can't remember what. " |
|
|
1552 | "H<The %s skill needs something else to function, for example a tool, weapon, rod, or spell. " |
|
|
1553 | "It cannot be used on its own.>", |
|
|
1554 | &op->skill |
|
|
1555 | ); |
|
|
1556 | if (tmp) who->insert (tmp); |
|
|
1557 | return 1; |
|
|
1558 | } |
|
|
1559 | |
|
|
1560 | if (skill_flags [op->subtype] & SF_AUTARK |
|
|
1561 | || !(skill_flags [op->subtype] & (SF_COMBAT | SF_RANGED))) |
|
|
1562 | { |
|
|
1563 | if (skill_flags [op->subtype] & SF_USE) |
|
|
1564 | who->failmsgf ( |
|
|
1565 | "You feel as if you wanted to do something funny, but you can't remember what. " |
|
|
1566 | "H<The %s skill cannot be readied, instead, try C<use_skill %s>.>", |
|
|
1567 | &op->skill, &op->skill |
|
|
1568 | ); |
|
|
1569 | else |
|
|
1570 | who->failmsgf ( |
|
|
1571 | "You feel as if you wanted to do something funny, but you can't remember what. " |
|
|
1572 | "H<The %s skill cannot be readied or used, it is always active.>", |
|
|
1573 | &op->skill |
|
|
1574 | ); |
|
|
1575 | |
|
|
1576 | if (tmp) who->insert (tmp); |
|
|
1577 | |
|
|
1578 | return 1; |
|
|
1579 | } |
|
|
1580 | |
|
|
1581 | if (who->contr) |
1534 | if (who->contr) |
1582 | if (op->invisible) |
1535 | if (op->invisible) |
1583 | who->statusmsg (format ("You can now use the %s skill.", &op->skill)); |
1536 | who->statusmsg (format ("You can now use the %s skill.", &op->skill)); |
1584 | else |
1537 | else |
1585 | who->statusmsg (format ("You ready %s.", query_name (op))); |
1538 | who->statusmsg (format ("You ready %s.", query_name (op))); |
1586 | } |
|
|
1587 | |
1539 | |
1588 | who->set_flag (FLAG_READY_SKILL); |
1540 | who->set_flag (FLAG_READY_SKILL); |
1589 | op->set_flag (FLAG_APPLIED); |
1541 | op->set_flag (FLAG_APPLIED); |
1590 | change_abil (who, op); |
1542 | change_abil (who, op); |
1591 | break; |
1543 | break; |
… | |
… | |
1719 | arch_flag = 1; |
1671 | arch_flag = 1; |
1720 | name_flag = 1; |
1672 | name_flag = 1; |
1721 | race_flag = 1; |
1673 | race_flag = 1; |
1722 | } |
1674 | } |
1723 | |
1675 | |
1724 | /* If the director has race set, only affect objects with a arch, |
1676 | /* If the director has race set, only affect objects with a arch, |
1725 | * name or race that matches. |
1677 | * name or race that matches. |
1726 | */ |
1678 | */ |
1727 | if ((op->race) && |
1679 | if ((op->race) && |
1728 | ((!(victim->arch && arch_flag && victim->arch->archname) || op->race != victim->arch->archname)) && |
1680 | ((!(victim->arch && arch_flag && victim->arch->archname) || op->race != victim->arch->archname)) && |
1729 | ((!(victim->name && name_flag) || op->race != victim->name)) && |
1681 | ((!(victim->name && name_flag) || op->race != victim->name)) && |
… | |
… | |
1762 | |
1714 | |
1763 | /* if the player has a marked item, identify that if it needs to be |
1715 | /* if the player has a marked item, identify that if it needs to be |
1764 | * identified. If it doesn't, then go through the player inventory. |
1716 | * identified. If it doesn't, then go through the player inventory. |
1765 | */ |
1717 | */ |
1766 | if (object *marked = pl->mark ()) |
1718 | if (object *marked = pl->mark ()) |
1767 | if (!marked->flag [FLAG_IDENTIFIED] && need_identify (marked)) |
1719 | if (!marked->flag [FLAG_IDENTIFIED] && marked->need_identify ()) |
1768 | { |
1720 | { |
1769 | if (operate_altar (altar, &money, pl)) |
1721 | if (operate_altar (altar, &money, pl)) |
1770 | { |
1722 | { |
1771 | identify (marked); |
1723 | identify (marked); |
1772 | |
1724 | |
… | |
… | |
1778 | } |
1730 | } |
1779 | } |
1731 | } |
1780 | |
1732 | |
1781 | for (object *id = pl->inv; id; id = id->below) |
1733 | for (object *id = pl->inv; id; id = id->below) |
1782 | { |
1734 | { |
1783 | if (!id->flag [FLAG_IDENTIFIED] && !id->invisible && need_identify (id)) |
1735 | if (!id->flag [FLAG_IDENTIFIED] && !id->invisible && id->need_identify ()) |
1784 | { |
1736 | { |
1785 | if (operate_altar (altar, &money, pl)) |
1737 | if (operate_altar (altar, &money, pl)) |
1786 | { |
1738 | { |
1787 | identify (id); |
1739 | identify (id); |
1788 | |
1740 | |
… | |
… | |
1815 | * matching item. |
1767 | * matching item. |
1816 | **/ |
1768 | **/ |
1817 | void |
1769 | void |
1818 | handle_apply_yield (object *tmp) |
1770 | handle_apply_yield (object *tmp) |
1819 | { |
1771 | { |
1820 | if (shstr_tmp yield = tmp->kv (shstr_on_use_yield)) |
1772 | if (shstr_tmp yield = tmp->kv [shstr_on_use_yield]) |
1821 | archetype::get (yield)->insert_at (tmp, tmp, INS_BELOW_ORIGINATOR); |
1773 | archetype::get (yield)->insert_at (tmp, tmp, INS_BELOW_ORIGINATOR); |
1822 | } |
1774 | } |
1823 | |
1775 | |
1824 | /** |
1776 | /** |
1825 | * Handles applying a potion. |
1777 | * Handles applying a potion. |
… | |
… | |
1827 | int |
1779 | int |
1828 | apply_potion (object *op, object *tmp) |
1780 | apply_potion (object *op, object *tmp) |
1829 | { |
1781 | { |
1830 | int got_one = 0, i; |
1782 | int got_one = 0, i; |
1831 | object *force = 0; |
1783 | object *force = 0; |
1832 | |
|
|
1833 | object *floor = GET_MAP_OB (op->map, op->x, op->y); |
|
|
1834 | |
1784 | |
1835 | if (get_map_flags (op->map, NULL, op->x, op->y, NULL, NULL) & P_SAFE) |
1785 | if (get_map_flags (op->map, NULL, op->x, op->y, NULL, NULL) & P_SAFE) |
1836 | { |
1786 | { |
1837 | op->failmsg ("Gods prevent you from using this here, it's sacred ground!"); |
1787 | op->failmsg ("Gods prevent you from using this here, it's sacred ground!"); |
1838 | |
1788 | |
… | |
… | |
1992 | for (i = 0; i < NROFATTACKS; i++) |
1942 | for (i = 0; i < NROFATTACKS; i++) |
1993 | { |
1943 | { |
1994 | if (tmp->resist[i]) |
1944 | if (tmp->resist[i]) |
1995 | { |
1945 | { |
1996 | if (!force) |
1946 | if (!force) |
1997 | force = get_archetype (FORCE_NAME); |
1947 | force = archetype::get (FORCE_NAME); |
1998 | |
1948 | |
1999 | memcpy (force->resist, tmp->resist, sizeof (tmp->resist)); |
1949 | memcpy (force->resist, tmp->resist, sizeof (tmp->resist)); |
2000 | force->type = POTION_EFFECT; |
1950 | force->type = POTION_EFFECT; |
2001 | break; /* Only need to find one protection since we copy entire batch */ |
1951 | break; /* Only need to find one protection since we copy entire batch */ |
2002 | } |
1952 | } |
… | |
… | |
2060 | void |
2010 | void |
2061 | move_apply (object *trap, object *victim, object *originator) |
2011 | move_apply (object *trap, object *victim, object *originator) |
2062 | { |
2012 | { |
2063 | static int recursion_depth = 0; |
2013 | static int recursion_depth = 0; |
2064 | |
2014 | |
|
|
2015 | trap = trap->head_ (); |
|
|
2016 | |
2065 | /* Only exits affect DMs. */ |
2017 | /* Only exits affect DMs. */ |
2066 | if (victim->flag [FLAG_WIZPASS] && trap->type != EXIT && trap->type != SIGN) |
2018 | if (victim->flag [FLAG_WIZPASS] && trap->type != EXIT && trap->type != SIGN) |
2067 | return; |
2019 | return; |
2068 | |
2020 | |
2069 | /* move_apply() is the most likely candidate for causing unwanted and |
2021 | /* move_apply() is the most likely candidate for causing unwanted and |
2070 | * possibly unlimited recursion. |
2022 | * possibly unlimited recursion. |
2071 | */ |
2023 | */ |
|
|
2024 | |
2072 | /* The following was changed because it was causing perfectly correct |
2025 | /* The following was changed because it was causing perfectly correct |
2073 | * maps to fail. 1) it's not an error to recurse: |
2026 | * maps to fail. 1) it's not an error to recurse: |
2074 | * rune detonates, summoning monster. monster lands on nearby rune. |
2027 | * rune detonates, summoning monster. monster lands on nearby rune. |
2075 | * nearby rune detonates. This sort of recursion is expected and |
2028 | * nearby rune detonates. This sort of recursion is expected and |
2076 | * proper. This code was causing needless crashes. |
2029 | * proper. This code was causing needless crashes. |
2077 | */ |
2030 | */ |
2078 | if (recursion_depth >= 500) |
2031 | if (recursion_depth >= 500) |
2079 | { |
2032 | { |
2080 | LOG (llevDebug, "WARNING: move_apply(): aborting recursion " |
2033 | LOG (llevDebug, "WARNING: move_apply(): aborting recursion " |
2081 | "[trap arch %s, name %s; victim arch %s, name %s]\n", &trap->arch->archname, &trap->name, &victim->arch->archname, &victim->name); |
2034 | "[trap arch %s, name %s; victim arch %s, name %s]\n", &trap->arch->archname, &trap->name, &victim->arch->archname, &victim->name); |
2082 | return; |
2035 | return; |
2083 | } |
2036 | } |
2084 | |
2037 | |
2085 | recursion_depth++; |
2038 | recursion_depth++; |
2086 | if (trap->head) |
|
|
2087 | trap = trap->head; |
|
|
2088 | |
2039 | |
2089 | if (!INVOKE_OBJECT (MOVE_TRIGGER, trap, ARG_OBJECT (victim), ARG_OBJECT (originator))) |
2040 | if (!INVOKE_OBJECT (MOVE_TRIGGER, trap, ARG_OBJECT (victim), ARG_OBJECT (originator))) |
2090 | switch (trap->type) |
2041 | switch (trap->type) |
2091 | { |
2042 | { |
2092 | case PLAYERMOVER: |
2043 | case PLAYERMOVER: |
… | |
… | |
2102 | |
2053 | |
2103 | /* Just put in some sanity check. I think there is a bug in the |
2054 | /* Just put in some sanity check. I think there is a bug in the |
2104 | * above with some objects have zero speed, and thus the player |
2055 | * above with some objects have zero speed, and thus the player |
2105 | * getting permanently paralyzed. |
2056 | * getting permanently paralyzed. |
2106 | */ |
2057 | */ |
2107 | if (victim->speed_left < -50.f) |
2058 | victim->speed_left = max (-50.f, victim->speed_left); |
2108 | victim->speed_left = -50.f; |
|
|
2109 | /* LOG(llevDebug, "apply, playermove, player speed_left=%f\n", victim->speed_left); */ |
2059 | /* LOG(llevDebug, "apply, playermove, player speed_left=%f\n", victim->speed_left); */ |
2110 | } |
2060 | } |
2111 | break; |
2061 | break; |
2112 | |
2062 | |
2113 | case SPINNER: |
2063 | case SPINNER: |
… | |
… | |
2145 | case ARROW: |
2095 | case ARROW: |
2146 | /* bad bug: monster throw a object, make a step forwards, step on object , |
2096 | /* bad bug: monster throw a object, make a step forwards, step on object , |
2147 | * trigger this here and get hit by own missile - and will be own enemy. |
2097 | * trigger this here and get hit by own missile - and will be own enemy. |
2148 | * Victim then is his own enemy and will start to kill herself (this is |
2098 | * Victim then is his own enemy and will start to kill herself (this is |
2149 | * removed) but we have not synced victim and his missile. To avoid senseless |
2099 | * removed) but we have not synced victim and his missile. To avoid senseless |
2150 | * action, we avoid hits here |
2100 | * action, we avoid hits here |
2151 | */ |
2101 | */ |
2152 | if ((victim->flag [FLAG_ALIVE] && trap->has_active_speed ()) |
2102 | if ((victim->flag [FLAG_ALIVE] && trap->has_active_speed ()) |
2153 | && trap->owner != victim) |
2103 | && trap->owner != victim) |
2154 | hit_with_arrow (trap, victim); |
2104 | hit_with_arrow (trap, victim); |
2155 | break; |
2105 | break; |
… | |
… | |
2179 | } |
2129 | } |
2180 | |
2130 | |
2181 | for (ab = trap->above, max = 100, sound_was_played = 0; --max && ab; ab = ab_next) |
2131 | for (ab = trap->above, max = 100, sound_was_played = 0; --max && ab; ab = ab_next) |
2182 | { |
2132 | { |
2183 | /* need to set this up, since if we do transfer the object, |
2133 | /* need to set this up, since if we do transfer the object, |
2184 | * ab->above would be bogus |
2134 | * ab->above would be bogus |
2185 | */ |
2135 | */ |
2186 | ab_next = ab->above; |
2136 | ab_next = ab->above; |
2187 | |
2137 | |
2188 | if ((ab->move_type && trap->move_on) || ab->move_type == 0) |
2138 | if ((ab->move_type && trap->move_on) || ab->move_type == 0) |
2189 | { |
2139 | { |
… | |
… | |
2362 | if (failure <= -1 && failure > -15) |
2312 | if (failure <= -1 && failure > -15) |
2363 | { /* wonder */ |
2313 | { /* wonder */ |
2364 | object *tmp; |
2314 | object *tmp; |
2365 | |
2315 | |
2366 | op->failmsg ("Your spell warps!"); |
2316 | op->failmsg ("Your spell warps!"); |
2367 | tmp = get_archetype (SPELL_WONDER); |
2317 | tmp = archetype::get (SPELL_WONDER); |
2368 | cast_wonder (op, op, 0, tmp); |
2318 | cast_wonder (op, op, 0, tmp); |
2369 | tmp->destroy (); |
2319 | tmp->destroy (); |
2370 | } |
2320 | } |
2371 | else if (failure <= -15 && failure > -35) |
2321 | else if (failure <= -15 && failure > -35) |
2372 | { /* drain mana */ |
2322 | { /* drain mana */ |
… | |
… | |
2392 | op->failmsg ("The magic recoils on you!"); |
2342 | op->failmsg ("The magic recoils on you!"); |
2393 | blind_player (op, op, power); |
2343 | blind_player (op, op, power); |
2394 | } |
2344 | } |
2395 | else if (failure <= -80) |
2345 | else if (failure <= -80) |
2396 | { /* blast the immediate area */ |
2346 | { /* blast the immediate area */ |
2397 | object *tmp = get_archetype (LOOSE_MANA); |
2347 | object *tmp = archetype::get (LOOSE_MANA); |
2398 | cast_magic_storm (op, tmp, power); |
2348 | cast_magic_storm (op, tmp, power); |
2399 | op->failmsg ("You unleash uncontrolled mana!"); |
2349 | op->failmsg ("You unleash uncontrolled mana!"); |
2400 | tmp->destroy (); |
2350 | tmp->destroy (); |
2401 | } |
2351 | } |
2402 | } |
2352 | } |
… | |
… | |
2592 | * |
2542 | * |
2593 | * 2- The learner's skill level in literacy adjusts the chance to learn |
2543 | * 2- The learner's skill level in literacy adjusts the chance to learn |
2594 | * a spell. |
2544 | * a spell. |
2595 | * |
2545 | * |
2596 | * 3 -Automatically fail to learn if you read while confused |
2546 | * 3 -Automatically fail to learn if you read while confused |
2597 | * |
2547 | * |
2598 | * Overall, chances are the same but a player will find having a high |
2548 | * Overall, chances are the same but a player will find having a high |
2599 | * literacy rate very useful! -b.t. |
2549 | * literacy rate very useful! -b.t. |
2600 | */ |
2550 | */ |
2601 | if (op->flag [FLAG_CONFUSED]) |
2551 | if (op->flag [FLAG_CONFUSED]) |
2602 | { |
2552 | { |
2603 | op->failmsg ("In your confused state you flub the wording of the text!"); |
2553 | op->failmsg ("In your confused state you flub the wording of the text!"); |
2604 | scroll_failure (op, 0 - random_roll (0, spell->level, op, PREFER_LOW), max (spell->stats.sp, spell->stats.grace)); |
2554 | scroll_failure (op, 0 - random_roll (0, spell->level, op, PREFER_LOW), max (spell->stats.sp, spell->stats.grace)); |
… | |
… | |
3076 | * the selected object to "burn". -b.t. |
3026 | * the selected object to "burn". -b.t. |
3077 | */ |
3027 | */ |
3078 | static void |
3028 | static void |
3079 | apply_lighter (object *who, object *lighter) |
3029 | apply_lighter (object *who, object *lighter) |
3080 | { |
3030 | { |
3081 | int is_player_env = 0; |
|
|
3082 | |
|
|
3083 | if (object *item = who->mark ()) |
3031 | if (object *item = who->mark ()) |
3084 | { |
3032 | { |
3085 | if (!auto_apply_lighter (who, item, lighter)) |
3033 | if (!auto_apply_lighter (who, item, lighter)) |
3086 | return; |
3034 | return; |
3087 | |
3035 | |
… | |
… | |
3344 | |
3292 | |
3345 | strcpy (got, find); |
3293 | strcpy (got, find); |
3346 | got[len] = '\0'; |
3294 | got[len] = '\0'; |
3347 | |
3295 | |
3348 | /* Now create new item, remove used ones when required. */ |
3296 | /* Now create new item, remove used ones when required. */ |
3349 | new_item = get_archetype (got); |
3297 | new_item = archetype::get (got); |
3350 | if (!new_item) |
3298 | if (!new_item) |
3351 | { |
3299 | { |
3352 | pl->failmsgf ("This %s is strange, better to not use it.", query_base_name (marked, 0)); |
3300 | pl->failmsgf ("This %s is strange, better to not use it.", query_base_name (marked, 0)); |
3353 | return; |
3301 | return; |
3354 | } |
3302 | } |
… | |
… | |
3381 | * them in this function - they are passed to apply_special |
3329 | * them in this function - they are passed to apply_special |
3382 | */ |
3330 | */ |
3383 | static bool |
3331 | static bool |
3384 | manual_apply (object *who, object *op, int aflag) |
3332 | manual_apply (object *who, object *op, int aflag) |
3385 | { |
3333 | { |
3386 | op = op->head_ (); |
|
|
3387 | |
|
|
3388 | if (op->flag [FLAG_UNPAID] && !op->flag [FLAG_APPLIED]) |
|
|
3389 | { |
|
|
3390 | if (who->contr) |
|
|
3391 | { |
|
|
3392 | examine (who, op); |
|
|
3393 | //who->failmsg ("You should pay for it first! H<You cannot use items marked as unpaid.>");//TODO remove |
|
|
3394 | return 1; |
|
|
3395 | } |
|
|
3396 | else |
|
|
3397 | return 0; /* monsters just skip unpaid items */ |
|
|
3398 | } |
|
|
3399 | |
|
|
3400 | if (INVOKE_OBJECT (APPLY, op, ARG_OBJECT (who))) |
3334 | if (INVOKE_OBJECT (APPLY, op, ARG_OBJECT (who))) |
3401 | return RESULT_INT (0); |
3335 | return RESULT_INT (0); |
3402 | else if (apply_types_inv_only [op->type]) |
3336 | else if (apply_types_inv_only [op->type]) |
3403 | { |
3337 | { |
3404 | // special item, using slot system, needs to be in inv |
3338 | // special item, using slot system, needs to be in inv |
… | |
… | |
3434 | |
3368 | |
3435 | break; |
3369 | break; |
3436 | |
3370 | |
3437 | case EXIT: |
3371 | case EXIT: |
3438 | if (!EXIT_PATH (op)) |
3372 | if (!EXIT_PATH (op)) |
3439 | who->failmsgf ("The %s is closed. H<And will stay closed, until somebody fires up the map editor and adds it.>", query_name (op)); |
3373 | 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)); |
3440 | else |
3374 | else |
3441 | { |
3375 | { |
3442 | /* Don't display messages for random maps. */ |
3376 | /* Don't display messages for random maps. */ |
3443 | if (op->msg && EXIT_PATH (op) != shstr_random_map_exit) |
3377 | if (op->msg && EXIT_PATH (op) != shstr_random_map_exit) |
3444 | who->statusmsg (op->msg, NDI_NAVY); |
3378 | who->statusmsg (op->msg, NDI_NAVY); |
… | |
… | |
3517 | check_improve_weapon (who, op); |
3451 | check_improve_weapon (who, op); |
3518 | break; |
3452 | break; |
3519 | |
3453 | |
3520 | case CLOCK: |
3454 | case CLOCK: |
3521 | { |
3455 | { |
3522 | char buf[MAX_BUF]; |
|
|
3523 | timeofday_t tod; |
3456 | timeofday_t tod; |
3524 | |
3457 | |
3525 | get_tod (&tod); |
3458 | get_tod (&tod); |
3526 | who->play_sound (sound_find ("sound_clock")); |
3459 | who->play_sound (sound_find ("sound_clock")); |
3527 | who->statusmsg (format ( |
3460 | who->statusmsg (format ( |
… | |
… | |
3551 | |
3484 | |
3552 | return 1; |
3485 | return 1; |
3553 | } |
3486 | } |
3554 | else |
3487 | else |
3555 | { |
3488 | { |
3556 | who->statusmsg (format ("I don't know how to apply the %s.", query_name (op))); |
3489 | who->statusmsg (format ("I don't know how to apply the %s. H<This object cannot be applied.>", query_name (op))); |
3557 | return 0; |
3490 | return 0; |
3558 | } |
3491 | } |
3559 | } |
3492 | } |
3560 | |
3493 | |
3561 | /** |
3494 | /** |
… | |
… | |
3624 | object::apply (object *ob, int aflags) |
3557 | object::apply (object *ob, int aflags) |
3625 | { |
3558 | { |
3626 | if (!ob) // simplifies a lot of callers |
3559 | if (!ob) // simplifies a lot of callers |
3627 | return true; |
3560 | return true; |
3628 | |
3561 | |
|
|
3562 | ob = ob->head_ (); |
|
|
3563 | |
|
|
3564 | if (ob->flag [FLAG_UNPAID] && !ob->flag [FLAG_APPLIED]) |
|
|
3565 | { |
|
|
3566 | if (contr) |
|
|
3567 | { |
|
|
3568 | examine (this, ob); |
|
|
3569 | //who->failmsg ("You should pay for it first! H<You cannot use items marked as unpaid.>");//TODO remove |
|
|
3570 | return 1; |
|
|
3571 | } |
|
|
3572 | else |
|
|
3573 | return 0; /* monsters just skip unpaid items */ |
|
|
3574 | } |
|
|
3575 | |
3629 | if (contr) |
3576 | if (contr) |
3630 | { |
3577 | { |
3631 | if (!ob->env && (move_type & MOVE_FLYING)) |
3578 | if (!ob->env && (move_type & MOVE_FLYING)) |
3632 | { |
3579 | { |
3633 | /* player is flying and applying object not in inventory */ |
3580 | /* player is flying and applying object not in inventory */ |
… | |
… | |
3646 | bool want_apply = |
3593 | bool want_apply = |
3647 | aflags & AP_APPLY ? true |
3594 | aflags & AP_APPLY ? true |
3648 | : aflags & AP_UNAPPLY ? false |
3595 | : aflags & AP_UNAPPLY ? false |
3649 | : !ob->flag [FLAG_APPLIED]; // AP_TOGGLE |
3596 | : !ob->flag [FLAG_APPLIED]; // AP_TOGGLE |
3650 | |
3597 | |
|
|
3598 | // cannot unapply cursed items |
|
|
3599 | if (!want_apply |
|
|
3600 | && (ob->flag [FLAG_CURSED] || ob->flag [FLAG_DAMNED]) |
|
|
3601 | && ob->flag [FLAG_APPLIED] |
|
|
3602 | && !(aflags & AP_IGNORE_CURSE)) |
|
|
3603 | { |
|
|
3604 | failmsgf ("No matter how hard you try, you just can't remove %s." CANNOT_REMOVE_CURSED, ob->query_name ()); |
|
|
3605 | return 0; |
|
|
3606 | } |
|
|
3607 | |
3651 | object_ptr *slot = 0; |
3608 | object_ptr *slot = 0; |
3652 | |
3609 | |
3653 | // detect the slot, if this is a player |
3610 | // detect the slot, if this is a player |
3654 | if (contr && !(aflags & AP_NO_SLOT)) |
3611 | if (contr && !(aflags & AP_NO_SLOT)) |
3655 | { |
3612 | { |
… | |
… | |
3660 | case WEAPON: |
3617 | case WEAPON: |
3661 | slot = &contr->combat_ob; |
3618 | slot = &contr->combat_ob; |
3662 | oslot = contr->ranged_ob; |
3619 | oslot = contr->ranged_ob; |
3663 | break; |
3620 | break; |
3664 | |
3621 | |
|
|
3622 | case RANGED: |
3665 | case BOW: |
3623 | case BOW: |
3666 | case RANGED: |
|
|
3667 | case SPELL: |
3624 | case SPELL: |
3668 | case WAND: |
3625 | case WAND: |
3669 | case ROD: |
3626 | case ROD: |
3670 | case HORN: |
3627 | case HORN: |
3671 | case BUILDER: |
3628 | case BUILDER: |
… | |
… | |
3673 | oslot = contr->combat_ob; |
3630 | oslot = contr->combat_ob; |
3674 | break; |
3631 | break; |
3675 | |
3632 | |
3676 | // oh, the humanity |
3633 | // oh, the humanity |
3677 | case SKILL: |
3634 | case SKILL: |
3678 | if (aflags & AP_NO_SLOT) |
3635 | // skill is used on it's own, as opposed to being a chosen_skill |
|
|
3636 | |
|
|
3637 | if (skill_flags [ob->subtype] & (SF_NEED_ITEM | SF_MANA)) |
3679 | break; |
3638 | { |
|
|
3639 | failmsgf ( |
|
|
3640 | "You feel as if you wanted to do something funny, but you can't remember what. " |
|
|
3641 | "H<The %s skill needs something else to function, for example a tool, weapon, rod, or spell. " |
|
|
3642 | "It cannot be used on its own.>", |
|
|
3643 | &ob->skill |
|
|
3644 | ); |
|
|
3645 | return 1; |
|
|
3646 | } |
|
|
3647 | |
|
|
3648 | if (skill_flags [ob->subtype] & SF_AUTARK |
|
|
3649 | || !(skill_flags [ob->subtype] & (SF_COMBAT | SF_RANGED))) |
|
|
3650 | { |
|
|
3651 | if (skill_flags [ob->subtype] & SF_USE) |
|
|
3652 | failmsgf ( |
|
|
3653 | "You feel as if you wanted to do something funny, but you can't remember what. " |
|
|
3654 | "H<The %s skill cannot be readied, instead, try C<use_skill %s>.>", |
|
|
3655 | &ob->skill, &ob->skill |
|
|
3656 | ); |
|
|
3657 | else |
|
|
3658 | failmsgf ( |
|
|
3659 | "You feel as if you wanted to do something funny, but you can't remember what. " |
|
|
3660 | "H<The %s skill cannot be readied or used, it is always active.>", |
|
|
3661 | &ob->skill |
|
|
3662 | ); |
|
|
3663 | |
|
|
3664 | return 1; |
|
|
3665 | } |
3680 | |
3666 | |
3681 | if (skill_flags [ob->subtype] & SF_NEED_ITEM) |
3667 | if (skill_flags [ob->subtype] & SF_NEED_ITEM) |
3682 | break; |
3668 | break; |
3683 | |
3669 | |
3684 | if (skill_flags [ob->subtype] & SF_COMBAT) |
3670 | if (skill_flags [ob->subtype] & SF_COMBAT) |
… | |
… | |
3701 | // only one slot can be active |
3687 | // only one slot can be active |
3702 | if (want_apply) |
3688 | if (want_apply) |
3703 | { |
3689 | { |
3704 | // clear slot unless we are in it already |
3690 | // clear slot unless we are in it already |
3705 | if (*slot != ob) |
3691 | if (*slot != ob) |
3706 | apply (*slot, AP_UNAPPLY); |
3692 | if (!apply (*slot, AP_UNAPPLY)) |
|
|
3693 | return false; |
3707 | |
3694 | |
3708 | // unapply other slot, because we want to become active |
3695 | // unapply other slot, because we want to become active |
3709 | apply (oslot, AP_UNAPPLY); |
3696 | if (!apply (oslot, AP_UNAPPLY)) |
|
|
3697 | return false; |
3710 | } |
3698 | } |
3711 | |
3699 | |
3712 | // clear item from slot if applied |
3700 | // clear item from slot if applied |
3713 | if (!want_apply && current_weapon == ob) |
3701 | if (!want_apply && current_weapon == ob) |
3714 | current_weapon = 0; |
3702 | current_weapon = 0; |
… | |
… | |
3733 | * Generates shop floor's item, and treasures. |
3721 | * Generates shop floor's item, and treasures. |
3734 | */ |
3722 | */ |
3735 | int |
3723 | int |
3736 | auto_apply (object *op) |
3724 | auto_apply (object *op) |
3737 | { |
3725 | { |
3738 | object *tmp = NULL, *tmp2; |
3726 | object *tmp = NULL; |
3739 | int i; |
3727 | int i; |
3740 | |
3728 | |
3741 | op->clr_flag (FLAG_AUTO_APPLY); |
3729 | op->clr_flag (FLAG_AUTO_APPLY); |
3742 | |
3730 | |
3743 | switch (op->type) |
3731 | switch (op->type) |
… | |
… | |
3829 | while (invtmp->stats.hp-- > 0) |
3817 | while (invtmp->stats.hp-- > 0) |
3830 | create_treasure (invtmp->randomitems, invtmp, 0, difficulty, 0); |
3818 | create_treasure (invtmp->randomitems, invtmp, 0, difficulty, 0); |
3831 | |
3819 | |
3832 | invtmp->randomitems = NULL; |
3820 | invtmp->randomitems = NULL; |
3833 | } |
3821 | } |
3834 | else if (invtmp && invtmp->arch |
3822 | else if (invtmp->arch |
3835 | && invtmp->type != TREASURE && invtmp->type != SPELL && invtmp->type != CLASS && invtmp->has_random_items ()) |
3823 | && invtmp->type != TREASURE && invtmp->type != SPELL && invtmp->type != CLASS |
|
|
3824 | && invtmp->has_random_items ()) |
3836 | { |
3825 | { |
3837 | create_treasure (invtmp->randomitems, invtmp, 0, difficulty, 0); |
3826 | create_treasure (invtmp->randomitems, invtmp, 0, difficulty, 0); |
3838 | /* Need to clear this so that we never try to create |
3827 | /* Need to clear this so that we never try to create |
3839 | * treasure again for this object |
3828 | * treasure again for this object |
3840 | */ |
3829 | */ |
3841 | invtmp->randomitems = NULL; |
3830 | invtmp->randomitems = NULL; |
3842 | } |
3831 | } |
3843 | } |
3832 | } |