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.263 by root, Thu May 13 12:13:22 2010 UTC vs.
Revision 1.278 by root, Thu Nov 17 04:49:22 2016 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 (©) 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
690 // 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
691 // get an 'identified' flag so easily. 691 // get an 'identified' flag so easily.
692 if (item->need_identify ()) 692 if (item->need_identify ())
693 identify (item); 693 identify (item);
694 694
695 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
696 return 1; 697 return 1;
697} 698}
698 699
699/** 700/**
700 * Handle apply on containers. 701 * Handle apply on containers.
1069 if (!who->chosen_skill->flag [FLAG_CAN_USE_SKILL]) 1070 if (!who->chosen_skill->flag [FLAG_CAN_USE_SKILL])
1070 unapply_special (who, who->chosen_skill, 0); 1071 unapply_special (who, who->chosen_skill, 0);
1071 1072
1072 break; 1073 break;
1073 1074
1075 case RANGED:
1074 case BOW: 1076 case BOW:
1075 case WAND: 1077 case WAND:
1076 case ROD: 1078 case ROD:
1077 case HORN: 1079 case HORN:
1078 case RANGED:
1079 if (player *pl = who->contr) 1080 if (player *pl = who->contr)
1080 { 1081 {
1081 who->statusmsg (format ("You unready %s.", query_name (op))); 1082 who->statusmsg (format ("You unready %s.", query_name (op)));
1082 change_abil (who, op); 1083 change_abil (who, op);
1083 } 1084 }
1392 1393
1393static bool 1394static bool
1394apply_special (object *who, object *op, int aflags) 1395apply_special (object *who, object *op, int aflags)
1395{ 1396{
1396 int basic_flag = aflags & AP_MODE; 1397 int basic_flag = aflags & AP_MODE;
1397 object *tmp, *tmp2, *skop = NULL; 1398 object *tmp, *skop = NULL;
1398
1399 if (who == NULL)
1400 {
1401 LOG (llevError, "apply_special() from object without environment.\n");
1402 return 1;
1403 }
1404
1405 //TODO: remove these when apply_special is no longer exposed
1406 if (op->env != who)
1407 return 1; /* op is not in inventory */
1408 1399
1409 /* trying to unequip op */ 1400 /* trying to unequip op */
1410 if (op->flag [FLAG_APPLIED]) 1401 if (op->flag [FLAG_APPLIED])
1411 { 1402 {
1412 /* always apply, so no reason to unapply */ 1403 /* always apply, so no reason to unapply */
1413 if (basic_flag == AP_APPLY) 1404 if (basic_flag == AP_APPLY)
1414 return 0; 1405 return 0;
1415
1416 if (!(aflags & AP_IGNORE_CURSE) && (op->flag [FLAG_CURSED] || op->flag [FLAG_DAMNED]))
1417 {
1418 who->failmsgf ("No matter how hard you try, you just can't remove %s." CANNOT_REMOVE_CURSED, query_name (op));
1419 return 1;
1420 }
1421 1406
1422 return unapply_special (who, op, aflags); 1407 return unapply_special (who, op, aflags);
1423 } 1408 }
1424 else if (basic_flag == AP_UNAPPLY) 1409 else if (basic_flag == AP_UNAPPLY)
1425 return 0; 1410 return 0;
1543 //TODO: unapplying should unapply the skill, though 1528 //TODO: unapplying should unapply the skill, though
1544 op->set_flag (FLAG_APPLIED); 1529 op->set_flag (FLAG_APPLIED);
1545 break; 1530 break;
1546 1531
1547 case SKILL: 1532 case SKILL:
1548 if (!(aflags & AP_NO_SLOT))
1549 {
1550 // skill is used on it's own, as opposed to being a chosen_skill
1551
1552 if (skill_flags [op->subtype] & (SF_NEED_ITEM | SF_MANA))
1553 {
1554 who->failmsgf (
1555 "You feel as if you wanted to do something funny, but you can't remember what. "
1556 "H<The %s skill needs something else to function, for example a tool, weapon, rod, or spell. "
1557 "It cannot be used on its own.>",
1558 &op->skill
1559 );
1560 if (tmp) who->insert (tmp);
1561 return 1;
1562 }
1563
1564 if (skill_flags [op->subtype] & SF_AUTARK
1565 || !(skill_flags [op->subtype] & (SF_COMBAT | SF_RANGED)))
1566 {
1567 if (skill_flags [op->subtype] & SF_USE)
1568 who->failmsgf (
1569 "You feel as if you wanted to do something funny, but you can't remember what. "
1570 "H<The %s skill cannot be readied, instead, try C<use_skill %s>.>",
1571 &op->skill, &op->skill
1572 );
1573 else
1574 who->failmsgf (
1575 "You feel as if you wanted to do something funny, but you can't remember what. "
1576 "H<The %s skill cannot be readied or used, it is always active.>",
1577 &op->skill
1578 );
1579
1580 if (tmp) who->insert (tmp);
1581
1582 return 1;
1583 }
1584
1585 if (who->contr) 1533 if (who->contr)
1586 if (op->invisible) 1534 if (op->invisible)
1587 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));
1588 else 1536 else
1589 who->statusmsg (format ("You ready %s.", query_name (op))); 1537 who->statusmsg (format ("You ready %s.", query_name (op)));
1590 }
1591 1538
1592 who->set_flag (FLAG_READY_SKILL); 1539 who->set_flag (FLAG_READY_SKILL);
1593 op->set_flag (FLAG_APPLIED); 1540 op->set_flag (FLAG_APPLIED);
1594 change_abil (who, op); 1541 change_abil (who, op);
1595 break; 1542 break;
1819 * matching item. 1766 * matching item.
1820 **/ 1767 **/
1821void 1768void
1822handle_apply_yield (object *tmp) 1769handle_apply_yield (object *tmp)
1823{ 1770{
1824 if (shstr_tmp yield = tmp->kv (shstr_on_use_yield)) 1771 if (shstr_tmp yield = tmp->kv [shstr_on_use_yield])
1825 archetype::get (yield)->insert_at (tmp, tmp, INS_BELOW_ORIGINATOR); 1772 archetype::get (yield)->insert_at (tmp, tmp, INS_BELOW_ORIGINATOR);
1826} 1773}
1827 1774
1828/** 1775/**
1829 * Handles applying a potion. 1776 * Handles applying a potion.
1831int 1778int
1832apply_potion (object *op, object *tmp) 1779apply_potion (object *op, object *tmp)
1833{ 1780{
1834 int got_one = 0, i; 1781 int got_one = 0, i;
1835 object *force = 0; 1782 object *force = 0;
1836
1837 object *floor = GET_MAP_OB (op->map, op->x, op->y);
1838 1783
1839 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)
1840 { 1785 {
1841 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!");
1842 1787
1996 for (i = 0; i < NROFATTACKS; i++) 1941 for (i = 0; i < NROFATTACKS; i++)
1997 { 1942 {
1998 if (tmp->resist[i]) 1943 if (tmp->resist[i])
1999 { 1944 {
2000 if (!force) 1945 if (!force)
2001 force = get_archetype (FORCE_NAME); 1946 force = archetype::get (FORCE_NAME);
2002 1947
2003 memcpy (force->resist, tmp->resist, sizeof (tmp->resist)); 1948 memcpy (force->resist, tmp->resist, sizeof (tmp->resist));
2004 force->type = POTION_EFFECT; 1949 force->type = POTION_EFFECT;
2005 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 */
2006 } 1951 }
2149 case ARROW: 2094 case ARROW:
2150 /* 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 ,
2151 * 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.
2152 * 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
2153 * 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
2154 * action, we avoid hits here 2099 * action, we avoid hits here
2155 */ 2100 */
2156 if ((victim->flag [FLAG_ALIVE] && trap->has_active_speed ()) 2101 if ((victim->flag [FLAG_ALIVE] && trap->has_active_speed ())
2157 && trap->owner != victim) 2102 && trap->owner != victim)
2158 hit_with_arrow (trap, victim); 2103 hit_with_arrow (trap, victim);
2159 break; 2104 break;
2366 if (failure <= -1 && failure > -15) 2311 if (failure <= -1 && failure > -15)
2367 { /* wonder */ 2312 { /* wonder */
2368 object *tmp; 2313 object *tmp;
2369 2314
2370 op->failmsg ("Your spell warps!"); 2315 op->failmsg ("Your spell warps!");
2371 tmp = get_archetype (SPELL_WONDER); 2316 tmp = archetype::get (SPELL_WONDER);
2372 cast_wonder (op, op, 0, tmp); 2317 cast_wonder (op, op, 0, tmp);
2373 tmp->destroy (); 2318 tmp->destroy ();
2374 } 2319 }
2375 else if (failure <= -15 && failure > -35) 2320 else if (failure <= -15 && failure > -35)
2376 { /* drain mana */ 2321 { /* drain mana */
2396 op->failmsg ("The magic recoils on you!"); 2341 op->failmsg ("The magic recoils on you!");
2397 blind_player (op, op, power); 2342 blind_player (op, op, power);
2398 } 2343 }
2399 else if (failure <= -80) 2344 else if (failure <= -80)
2400 { /* blast the immediate area */ 2345 { /* blast the immediate area */
2401 object *tmp = get_archetype (LOOSE_MANA); 2346 object *tmp = archetype::get (LOOSE_MANA);
2402 cast_magic_storm (op, tmp, power); 2347 cast_magic_storm (op, tmp, power);
2403 op->failmsg ("You unleash uncontrolled mana!"); 2348 op->failmsg ("You unleash uncontrolled mana!");
2404 tmp->destroy (); 2349 tmp->destroy ();
2405 } 2350 }
2406 } 2351 }
3080 * the selected object to "burn". -b.t. 3025 * the selected object to "burn". -b.t.
3081 */ 3026 */
3082static void 3027static void
3083apply_lighter (object *who, object *lighter) 3028apply_lighter (object *who, object *lighter)
3084{ 3029{
3085 int is_player_env = 0;
3086
3087 if (object *item = who->mark ()) 3030 if (object *item = who->mark ())
3088 { 3031 {
3089 if (!auto_apply_lighter (who, item, lighter)) 3032 if (!auto_apply_lighter (who, item, lighter))
3090 return; 3033 return;
3091 3034
3348 3291
3349 strcpy (got, find); 3292 strcpy (got, find);
3350 got[len] = '\0'; 3293 got[len] = '\0';
3351 3294
3352 /* Now create new item, remove used ones when required. */ 3295 /* Now create new item, remove used ones when required. */
3353 new_item = get_archetype (got); 3296 new_item = archetype::get (got);
3354 if (!new_item) 3297 if (!new_item)
3355 { 3298 {
3356 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));
3357 return; 3300 return;
3358 } 3301 }
3385 * them in this function - they are passed to apply_special 3328 * them in this function - they are passed to apply_special
3386 */ 3329 */
3387static bool 3330static bool
3388manual_apply (object *who, object *op, int aflag) 3331manual_apply (object *who, object *op, int aflag)
3389{ 3332{
3390 op = op->head_ ();
3391
3392 if (op->flag [FLAG_UNPAID] && !op->flag [FLAG_APPLIED])
3393 {
3394 if (who->contr)
3395 {
3396 examine (who, op);
3397 //who->failmsg ("You should pay for it first! H<You cannot use items marked as unpaid.>");//TODO remove
3398 return 1;
3399 }
3400 else
3401 return 0; /* monsters just skip unpaid items */
3402 }
3403
3404 if (INVOKE_OBJECT (APPLY, op, ARG_OBJECT (who))) 3333 if (INVOKE_OBJECT (APPLY, op, ARG_OBJECT (who)))
3405 return RESULT_INT (0); 3334 return RESULT_INT (0);
3406 else if (apply_types_inv_only [op->type]) 3335 else if (apply_types_inv_only [op->type])
3407 { 3336 {
3408 // special item, using slot system, needs to be in inv 3337 // special item, using slot system, needs to be in inv
3438 3367
3439 break; 3368 break;
3440 3369
3441 case EXIT: 3370 case EXIT:
3442 if (!EXIT_PATH (op)) 3371 if (!EXIT_PATH (op))
3443 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));
3444 else 3373 else
3445 { 3374 {
3446 /* Don't display messages for random maps. */ 3375 /* Don't display messages for random maps. */
3447 if (op->msg && EXIT_PATH (op) != shstr_random_map_exit) 3376 if (op->msg && EXIT_PATH (op) != shstr_random_map_exit)
3448 who->statusmsg (op->msg, NDI_NAVY); 3377 who->statusmsg (op->msg, NDI_NAVY);
3554 3483
3555 return 1; 3484 return 1;
3556 } 3485 }
3557 else 3486 else
3558 { 3487 {
3559 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)));
3560 return 0; 3489 return 0;
3561 } 3490 }
3562} 3491}
3563 3492
3564/** 3493/**
3627object::apply (object *ob, int aflags) 3556object::apply (object *ob, int aflags)
3628{ 3557{
3629 if (!ob) // simplifies a lot of callers 3558 if (!ob) // simplifies a lot of callers
3630 return true; 3559 return true;
3631 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
3632 if (contr) 3575 if (contr)
3633 { 3576 {
3634 if (!ob->env && (move_type & MOVE_FLYING)) 3577 if (!ob->env && (move_type & MOVE_FLYING))
3635 { 3578 {
3636 /* player is flying and applying object not in inventory */ 3579 /* player is flying and applying object not in inventory */
3649 bool want_apply = 3592 bool want_apply =
3650 aflags & AP_APPLY ? true 3593 aflags & AP_APPLY ? true
3651 : aflags & AP_UNAPPLY ? false 3594 : aflags & AP_UNAPPLY ? false
3652 : !ob->flag [FLAG_APPLIED]; // AP_TOGGLE 3595 : !ob->flag [FLAG_APPLIED]; // AP_TOGGLE
3653 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
3654 object_ptr *slot = 0; 3607 object_ptr *slot = 0;
3655 3608
3656 // detect the slot, if this is a player 3609 // detect the slot, if this is a player
3657 if (contr && !(aflags & AP_NO_SLOT)) 3610 if (contr && !(aflags & AP_NO_SLOT))
3658 { 3611 {
3663 case WEAPON: 3616 case WEAPON:
3664 slot = &contr->combat_ob; 3617 slot = &contr->combat_ob;
3665 oslot = contr->ranged_ob; 3618 oslot = contr->ranged_ob;
3666 break; 3619 break;
3667 3620
3621 case RANGED:
3668 case BOW: 3622 case BOW:
3669 case RANGED:
3670 case SPELL: 3623 case SPELL:
3671 case WAND: 3624 case WAND:
3672 case ROD: 3625 case ROD:
3673 case HORN: 3626 case HORN:
3674 case BUILDER: 3627 case BUILDER:
3676 oslot = contr->combat_ob; 3629 oslot = contr->combat_ob;
3677 break; 3630 break;
3678 3631
3679 // oh, the humanity 3632 // oh, the humanity
3680 case SKILL: 3633 case SKILL:
3681 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))
3682 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 }
3683 3665
3684 if (skill_flags [ob->subtype] & SF_NEED_ITEM) 3666 if (skill_flags [ob->subtype] & SF_NEED_ITEM)
3685 break; 3667 break;
3686 3668
3687 if (skill_flags [ob->subtype] & SF_COMBAT) 3669 if (skill_flags [ob->subtype] & SF_COMBAT)
3704 // only one slot can be active 3686 // only one slot can be active
3705 if (want_apply) 3687 if (want_apply)
3706 { 3688 {
3707 // clear slot unless we are in it already 3689 // clear slot unless we are in it already
3708 if (*slot != ob) 3690 if (*slot != ob)
3709 apply (*slot, AP_UNAPPLY); 3691 if (!apply (*slot, AP_UNAPPLY))
3692 return false;
3710 3693
3711 // unapply other slot, because we want to become active 3694 // unapply other slot, because we want to become active
3712 apply (oslot, AP_UNAPPLY); 3695 if (!apply (oslot, AP_UNAPPLY))
3696 return false;
3713 } 3697 }
3714 3698
3715 // clear item from slot if applied 3699 // clear item from slot if applied
3716 if (!want_apply && current_weapon == ob) 3700 if (!want_apply && current_weapon == ob)
3717 current_weapon = 0; 3701 current_weapon = 0;
3736 * Generates shop floor's item, and treasures. 3720 * Generates shop floor's item, and treasures.
3737 */ 3721 */
3738int 3722int
3739auto_apply (object *op) 3723auto_apply (object *op)
3740{ 3724{
3741 object *tmp = NULL, *tmp2; 3725 object *tmp = NULL;
3742 int i; 3726 int i;
3743 3727
3744 op->clr_flag (FLAG_AUTO_APPLY); 3728 op->clr_flag (FLAG_AUTO_APPLY);
3745 3729
3746 switch (op->type) 3730 switch (op->type)
3832 while (invtmp->stats.hp-- > 0) 3816 while (invtmp->stats.hp-- > 0)
3833 create_treasure (invtmp->randomitems, invtmp, 0, difficulty, 0); 3817 create_treasure (invtmp->randomitems, invtmp, 0, difficulty, 0);
3834 3818
3835 invtmp->randomitems = NULL; 3819 invtmp->randomitems = NULL;
3836 } 3820 }
3837 else if (invtmp && invtmp->arch 3821 else if (invtmp->arch
3838 && 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 ())
3839 { 3824 {
3840 create_treasure (invtmp->randomitems, invtmp, 0, difficulty, 0); 3825 create_treasure (invtmp->randomitems, invtmp, 0, difficulty, 0);
3841 /* Need to clear this so that we never try to create 3826 /* Need to clear this so that we never try to create
3842 * treasure again for this object 3827 * treasure again for this object
3843 */ 3828 */

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines