ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/apply.C
(Generate patch)

Comparing deliantra/server/server/apply.C (file contents):
Revision 1.257 by root, Thu Apr 15 00:36:51 2010 UTC vs.
Revision 1.283 by root, Sat Nov 17 23:40:03 2018 UTC

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
66static const struct apply_types_player_only : typeset 67static 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 */
251static int 253static int
252prepare_weapon (object *op, object *improver, object *weapon) 254prepare_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 */
314static int 314static int
315improve_weapon (object *op, object *improver, object *weapon) 315improve_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 */
487static int 487static 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 */
706static int 707static 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
1389static bool 1395static bool
1390apply_special (object *who, object *op, int aflags) 1396apply_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 **/
1817void 1769void
1818handle_apply_yield (object *tmp) 1770handle_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.
1827int 1779int
1828apply_potion (object *op, object *tmp) 1780apply_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 }
2060void 2010void
2061move_apply (object *trap, object *victim, object *originator) 2011move_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 */
3078static void 3028static void
3079apply_lighter (object *who, object *lighter) 3029apply_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 */
3383static bool 3331static bool
3384manual_apply (object *who, object *op, int aflag) 3332manual_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/**
3624object::apply (object *ob, int aflags) 3557object::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 */
3735int 3723int
3736auto_apply (object *op) 3724auto_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 }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines