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.233 by root, Fri Apr 2 03:41:24 2010 UTC vs.
Revision 1.238 by root, Sun Apr 4 04:10:47 2010 UTC

30#include <skills.h> 30#include <skills.h>
31#include <tod.h> 31#include <tod.h>
32 32
33#include <sproto.h> 33#include <sproto.h>
34 34
35/* Want this regardless of rplay. */
36#include <sounds.h>
37
38/** 35/**
39 * Check if op should abort moving victim because of it's race or slaying. 36 * Check if op should abort moving victim because of it's race or slaying.
40 * Returns 1 if it should abort, returns 0 if it should continue. 37 * Returns 1 if it should abort, returns 0 if it should continue.
41 */ 38 */
42int 39int
951 item->nrof *= nr; 948 item->nrof *= nr;
952 949
953 if (converter->flag [FLAG_PRECIOUS]) 950 if (converter->flag [FLAG_PRECIOUS])
954 SET_FLAG (item, FLAG_UNPAID); 951 SET_FLAG (item, FLAG_UNPAID);
955 952
956 if (is_in_shop (converter)) 953 if (converter->is_in_shop ())
957 { 954 {
958 // converters on shop floors don't work anymore, bug lets check for it 955 // converters on shop floors don't work anymore, bug lets check for it
959 // and report in case someone still does it. 956 // and report in case someone still does it.
960 LOG (llevDebug, "ITEMBUG: broken converter, converters on shop floor don't work: %s\n", 957 LOG (llevDebug, "ITEMBUG: broken converter, converters on shop floor don't work: %s\n",
961 converter->debug_desc ()); 958 converter->debug_desc ());
1164 /* this is only used for players */ 1161 /* this is only used for players */
1165 rv = teleport (shop_mat, SHOP_MAT, op); 1162 rv = teleport (shop_mat, SHOP_MAT, op);
1166 1163
1167 if (has_unpaid) 1164 if (has_unpaid)
1168 op->contr->play_sound (sound_find ("shop_buy")); 1165 op->contr->play_sound (sound_find ("shop_buy"));
1169 else if (is_in_shop (op)) 1166 else if (op->is_in_shop ())
1170 op->contr->play_sound (sound_find ("shop_enter")); 1167 op->contr->play_sound (sound_find ("shop_enter"));
1171 else 1168 else
1172 op->contr->play_sound (sound_find ("shop_leave")); 1169 op->contr->play_sound (sound_find ("shop_leave"));
1173 1170
1174 if (shop_mat->msg) 1171 if (shop_mat->msg)
1175 op->statusmsg (shop_mat->msg); 1172 op->statusmsg (shop_mat->msg);
1176 /* This check below is a bit simplistic - generally it should be correct, 1173 /* This check below is a bit simplistic - generally it should be correct,
1177 * but there is never a guarantee that the bottom space on the map is 1174 * but there is never a guarantee that the bottom space on the map is
1178 * actually the shop floor. 1175 * actually the shop floor.
1179 */ 1176 */
1180 else if (!rv && !is_in_shop (op)) 1177 else if (!rv && !op->is_in_shop ())
1181 { 1178 {
1182 opinion = shopkeeper_approval (op->map, op); 1179 opinion = shopkeeper_approval (op->map, op);
1183 1180
1184 op->statusmsg ( 1181 op->statusmsg (
1185 opinion >= 0.90 ? "The shopkeeper gives you a friendly wave." 1182 opinion >= 0.90 ? "The shopkeeper gives you a friendly wave."
1830 { 1827 {
1831 spell_skill = find_skill_by_name (op, spell->skill); 1828 spell_skill = find_skill_by_name (op, spell->skill);
1832 1829
1833 if (!spell_skill) 1830 if (!spell_skill)
1834 { 1831 {
1835 op->failmsg (format ("You lack the skill %s to use this spell.", &spell->skill)); 1832 op->failmsg (format ("You lack the %s skill to use this spell.", &spell->skill));
1836 return; 1833 return;
1837 } 1834 }
1838 1835
1839 if (spell_skill->level < spell->level) 1836 if (spell_skill->level < spell->level)
1840 { 1837 {
2629 * being applied. 2626 * being applied.
2630 * 2627 *
2631 * aflag is special (always apply/unapply) flags. Nothing is done with 2628 * aflag is special (always apply/unapply) flags. Nothing is done with
2632 * them in this function - they are passed to apply_special 2629 * them in this function - they are passed to apply_special
2633 */ 2630 */
2634int 2631static int
2635manual_apply (object *who, object *op, int aflag) 2632manual_apply (object *who, object *op, int aflag)
2636{ 2633{
2637 op = op->head_ (); 2634 op = op->head_ ();
2638 2635
2639 if (QUERY_FLAG (op, FLAG_UNPAID) && !QUERY_FLAG (op, FLAG_APPLIED)) 2636 if (QUERY_FLAG (op, FLAG_UNPAID) && !QUERY_FLAG (op, FLAG_APPLIED))
2777 case BOW: 2774 case BOW:
2778 case RANGED: 2775 case RANGED:
2779 case BUILDER: 2776 case BUILDER:
2780 case SKILL_TOOL: 2777 case SKILL_TOOL:
2781 if (op->env != who) 2778 if (op->env != who)
2782 return 2; /* not in inventory */ 2779 who->failmsg (format ("You must get it first! H<You can only apply the %s if it is in your inventory.>\n", query_name (op)));
2783 2780 else
2784 apply_special (who, op, aflag); 2781 apply_special (who, op, aflag);
2782
2785 return 1; 2783 return 1;
2786 2784
2787 case DRINK: 2785 case DRINK:
2788 case FOOD: 2786 case FOOD:
2789 case FLESH: 2787 case FLESH:
2853 case ITEM_TRANSFORMER: 2851 case ITEM_TRANSFORMER:
2854 apply_item_transformer (who, op); 2852 apply_item_transformer (who, op);
2855 return 1; 2853 return 1;
2856 2854
2857 default: 2855 default:
2856 who->statusmsg (format ("I don't know how to apply the %s.", query_name (op)));
2858 return 0; 2857 return 0;
2859 } 2858 }
2860} 2859}
2861 2860
2862/* quiet suppresses the "don't know how to apply" and "you must get it first" 2861/*
2863 * messages as needed by player_apply_below(). But there can still be
2864 * "but you are floating high above the ground" messages.
2865 *
2866 * Same return value as apply() function. 2862 * Same return value as apply() function.
2867 */ 2863 */
2868int 2864bool
2869player_apply (object *pl, object *op, int aflag, int quiet) 2865player_apply (object *pl, object *op, int aflag)
2870{ 2866{
2871 if (!op->env && (pl->move_type & MOVE_FLYING)) 2867 if (!op->env && (pl->move_type & MOVE_FLYING))
2872 { 2868 {
2873 /* player is flying and applying object not in inventory */ 2869 /* player is flying and applying object not in inventory */
2874 if (!QUERY_FLAG (pl, FLAG_WIZ) && !(op->move_type & MOVE_FLYING)) 2870 if (!QUERY_FLAG (pl, FLAG_WIZ) && !(op->move_type & MOVE_FLYING))
2880 } 2876 }
2881 } 2877 }
2882 2878
2883 pl->contr->last_used = op; 2879 pl->contr->last_used = op;
2884 2880
2885 int tmp = manual_apply (pl, op, aflag); 2881 return pl->apply (op, aflag);
2886
2887 if (!quiet)
2888 {
2889 if (tmp == 0)
2890 pl->statusmsg (format ("I don't know how to apply the %s.", query_name (op)));
2891 else if (tmp == 2)
2892 pl->failmsg ("You must get it first!\n");
2893 }
2894
2895 return tmp;
2896} 2882}
2897 2883
2898/** 2884/**
2899 * player_apply_below attempts to apply the object 'below' the player. 2885 * player_apply_below attempts to apply the object 'below' the player.
2900 * If the player has an open container, we use that for below, otherwise 2886 * If the player has an open container, we use that for below, otherwise
2911 * we don't use a corrupt pointer for the next object, so we get the 2897 * we don't use a corrupt pointer for the next object, so we get the
2912 * next object in the stack before applying. This is can only be a 2898 * next object in the stack before applying. This is can only be a
2913 * problem if player_apply() has a bug in that it uses the object but does 2899 * problem if player_apply() has a bug in that it uses the object but does
2914 * not return a proper value. 2900 * not return a proper value.
2915 */ 2901 */
2902 //TODO: currently looks only at the topmost objetc, no longer at multiple floors
2903 // and also not on move_on floors. what was this for, anyways?
2916 for (object *next, *tmp = pl->container_ () ? pl->container_ ()->inv : pl->below; tmp; tmp = next) 2904 for (object *next, *tmp = pl->container_ () ? pl->container_ ()->inv : pl->below; tmp; tmp = next)
2917 { 2905 {
2918 next = tmp->below; 2906 next = tmp->below;
2919 2907
2920 if (QUERY_FLAG (tmp, FLAG_IS_FLOOR))
2921 floors++;
2922 else if (floors > 0)
2923 return; /* process only floor objects after first floor object */
2924
2925 /* If it is visible, player can apply it. If it is applied by 2908 /* If it is visible, player can apply it.
2926 * person moving on it, also activate. Added code to make it
2927 * so that at least one of players movement types be that which
2928 * the item needs.
2929 */ 2909 */
2930 if (!tmp->invisible || (tmp->move_on & pl->move_type)) 2910 if (!tmp->invisible)
2931 if (player_apply (pl, tmp, 0, 1) == 1) 2911 if (player_apply (pl, tmp, 0))
2932 return; 2912 break;
2933 2913
2934 if (floors >= 2) 2914 break;
2935 return; /* process at most two floor objects */
2936 } 2915 }
2937} 2916}
2938 2917
2939/** 2918/**
2940 * Unapplies specified item. 2919 * Unapplies specified item.
2957 switch (op->type) 2936 switch (op->type)
2958 { 2937 {
2959 case SKILL: 2938 case SKILL:
2960 if (player *pl = who->contr) 2939 if (player *pl = who->contr)
2961 if (op->invisible) 2940 if (op->invisible)
2962 pl->statusmsg (format ("You can no longer use the skill: %s.", &op->skill)); 2941 pl->statusmsg (format ("You can no longer use the %s skill.", &op->skill));
2963 else 2942 else
2964 pl->statusmsg (format ("You stop using the %s.", query_name (op))); 2943 pl->statusmsg (format ("You stop using the %s.", query_name (op)));
2965 2944
2966 change_abil (who, op); 2945 change_abil (who, op);
2967 who->flag [FLAG_READY_SKILL] = false; 2946 who->flag [FLAG_READY_SKILL] = false;
3054static object * 3033static object *
3055get_next_item_from_body_location (int loc, object *start) 3034get_next_item_from_body_location (int loc, object *start)
3056{ 3035{
3057 for (object *tmp = start; tmp; tmp = tmp->below) 3036 for (object *tmp = start; tmp; tmp = tmp->below)
3058 if (tmp->flag [FLAG_APPLIED] 3037 if (tmp->flag [FLAG_APPLIED]
3059 && tmp->slot[loc].info 3038 && tmp->slot [loc].info
3060 && (!tmp->invisible || tmp->type == SKILL)) 3039 && (!tmp->invisible || tmp->type == SKILL || tmp->type == SPELL))
3061 return tmp; 3040 return tmp;
3062 3041
3063 return 0; 3042 return 0;
3064} 3043}
3065 3044
3210 continue; 3189 continue;
3211 } 3190 }
3212 3191
3213 object *tmp1 = get_next_item_from_body_location (i, who->inv); 3192 object *tmp1 = get_next_item_from_body_location (i, who->inv);
3214 if (!tmp1) 3193 if (!tmp1)
3215 {
3216#if 0
3217 /* This is sort of an error, but happens a lot when old players
3218 * join in with more stuff equipped than they are now allowed.
3219 */
3220 LOG (llevError, "Can't find object using location %d on %s\n", i, who->name);
3221#endif
3222 retval |= CAN_APPLY_NEVER; 3194 retval |= CAN_APPLY_NEVER;
3223 }
3224 else 3195 else
3225 { 3196 {
3226 /* need to unapply something. However, if this something 3197 /* need to unapply something. However, if this something
3227 * is different than we had found before, it means they need 3198 * is different than we had found before, it means they need
3228 * to apply multiple objects 3199 * to apply multiple objects
3285 3256
3286// saner interface, returns successful status 3257// saner interface, returns successful status
3287bool 3258bool
3288object::apply (object *ob, int aflags) 3259object::apply (object *ob, int aflags)
3289{ 3260{
3290 bool want_apply = aflags & AP_APPLY; 3261 if (!ob) // simplifies a lot of callers
3291
3292 if (ob->flag [FLAG_APPLIED] == want_apply)
3293 return true; 3262 return true;
3294 3263
3264 bool want_apply =
3265 aflags & AP_APPLY ? true
3266 : aflags & AP_UNAPPLY ? false
3267 : !ob->flag [FLAG_APPLIED]; // AP_TOGGLE
3268
3269 object_ptr *slot = 0;
3270
3271 // detect the slot, if this is a player
3272 if (contr && !(aflags & AP_NO_SLOT))
3273 {
3274 object *oslot;
3275
3276 switch (ob->type)
3277 {
3278 case WEAPON:
3279 slot = &contr->combat_ob;
3280 oslot = contr->ranged_ob;
3281 break;
3282
3283 case BOW:
3284 case RANGED:
3285 case SPELL:
3286 case WAND:
3287 case ROD:
3288 case HORN:
3289 case BUILDER:
3290 slot = &contr->ranged_ob;
3291 oslot = contr->combat_ob;
3292 break;
3293
3294 // oh, the humanity
3295 case SKILL:
3296 if (aflags & AP_NO_SLOT)
3297 break;
3298
3299 if (skill_flags [ob->subtype] & SF_NEED_ITEM)
3300 break;
3301
3302 if (skill_flags [ob->subtype] & SF_COMBAT)
3303 {
3304 slot = &contr->combat_ob;
3305 oslot = contr->ranged_ob;
3306 }
3307 else if (skill_flags [ob->subtype] & SF_RANGED)
3308 {
3309 slot = &contr->ranged_ob;
3310 oslot = contr->combat_ob;
3311 }
3312
3313 break;
3314 }
3315
3316 // now handle slot exclusions
3317 if (slot)
3318 {
3319 // only one slot can be active
3320 if (want_apply)
3321 apply (oslot, AP_UNAPPLY);
3322
3323 // clear item from slot if applied
3324 if (!want_apply && *slot == ob)
3325 {
3326 *slot = 0;
3327
3328 if (current_weapon == ob)
3329 current_weapon = 0;
3330 }
3331 }
3332 }
3333
3334 if (ob->flag [FLAG_APPLIED] != want_apply)
3295 manual_apply (this, ob, aflags); 3335 manual_apply (this, ob, aflags);
3296 3336
3297 return ob->flag [FLAG_APPLIED] == want_apply; 3337 if (ob->flag [FLAG_APPLIED] != want_apply)
3338 return false;
3339
3340 if (slot)
3341 current_weapon = *slot = ob;
3342
3343 return true;
3298} 3344}
3299 3345
3300/** 3346/**
3301 * who is the object using the object. It can be a monster. 3347 * who is the object using the object. It can be a monster.
3302 * op is the object they are using. op is an equipment type item, 3348 * op is the object they are using. op is an equipment type item,
3325 " H<You lack enough unused item power to use this weapon, see the skills command.>" 3371 " H<You lack enough unused item power to use this weapon, see the skills command.>"
3326 3372
3327int 3373int
3328apply_special (object *who, object *op, int aflags) 3374apply_special (object *who, object *op, int aflags)
3329{ 3375{
3330 int basic_flag = aflags & AP_BASIC_FLAGS; 3376 int basic_flag = aflags & AP_MODE;
3331 object *tmp, *tmp2, *skop = NULL; 3377 object *tmp, *tmp2, *skop = NULL;
3332 3378
3333 if (who == NULL) 3379 if (who == NULL)
3334 { 3380 {
3335 LOG (llevError, "apply_special() from object without environment.\n"); 3381 LOG (llevError, "apply_special() from object without environment.\n");
3405 if (!skop) 3451 if (!skop)
3406 { 3452 {
3407 who->failmsg (format ("You need the %s skill to use this item!", &op->skill)); 3453 who->failmsg (format ("You need the %s skill to use this item!", &op->skill));
3408 return 1; 3454 return 1;
3409 } 3455 }
3410 else if (!who->apply (skop, AP_APPLY | AP_HAVE_WEAPON)) 3456 else if (!who->apply (skop, AP_APPLY | AP_NO_SLOT))
3411 { 3457 {
3412 who->failmsg (format ("You can't use the required %s skill!", &op->skill)); 3458 who->failmsg (format ("You can't use the required %s skill!", &op->skill));
3413 return 1; 3459 return 1;
3414 } 3460 }
3415 } 3461 }
3446 3492
3447 op->flag [FLAG_APPLIED] = true; 3493 op->flag [FLAG_APPLIED] = true;
3448 3494
3449 if (player *pl = who->contr) 3495 if (player *pl = who->contr)
3450 { 3496 {
3451 who->current_weapon = pl->combat_ob = op;
3452 who->statusmsg (format ("You wield %s.", query_name (op))); 3497 who->statusmsg (format ("You wield %s.", query_name (op)));
3453 change_abil (who, op); 3498 change_abil (who, op);
3454 } 3499 }
3455 else 3500 else
3456 who->change_skill (skop); 3501 who->change_skill (skop);
3479 //TODO: unapplying should unapply the skill, though 3524 //TODO: unapplying should unapply the skill, though
3480 SET_FLAG (op, FLAG_APPLIED); 3525 SET_FLAG (op, FLAG_APPLIED);
3481 break; 3526 break;
3482 3527
3483 case SKILL: 3528 case SKILL:
3484 if (skill_flags [op->subtype] & SF_NEED_ITEM && !(aflags & AP_HAVE_WEAPON)) 3529 if (!(aflags & AP_NO_SLOT))
3485 { 3530 {
3531 // skill is used on it's own, as opposed to being a chosen_skill
3532
3533 if (skill_flags [op->subtype] & (SF_NEED_ITEM | SF_MANA))
3534 {
3486 who->failmsg (format ( 3535 who->failmsg (format (
3487 "You feel as if you wanted to do something funny, but you can't remember what. " 3536 "You feel as if you wanted to do something funny, but you can't remember what. "
3488 "H<The skill %s needs an item to function, it cannot be used on its own.>", 3537 "H<The %s skill needs something else to function, for example a tool, weapon, rod, or spell. "
3538 "It cannot be used on its own.>",
3489 &op->skill 3539 &op->skill
3490 )); 3540 ));
3491 if (tmp) who->insert (tmp); 3541 if (tmp) who->insert (tmp);
3492 return 1; 3542 return 1;
3493 } 3543 }
3494 3544
3495 if (player *pl = who->contr)
3496 {
3497 if (skill_flags [op->subtype] & SF_COMBAT) 3545 if (skill_flags [op->subtype] & SF_AUTARK
3498 who->current_weapon = pl->combat_ob = op; 3546 || !(skill_flags [op->subtype] & (SF_COMBAT | SF_RANGED)))
3499 3547 {
3500 if (skill_flags [op->subtype] & SF_RANGED) 3548 if (skill_flags [op->subtype] & SF_USE)
3501 who->current_weapon = pl->ranged_ob = op; 3549 who->failmsg (format (
3502 3550 "You feel as if you wanted to do something funny, but you can't remember what. "
3503 if (op->invisible) 3551 "H<The %s skill cannot be readied, instead, try C<use_skill %s>.>",
3504 who->statusmsg (format ("Readied skill: %s.", op->skill ? &op->skill : &op->name)); 3552 &op->skill, &op->skill
3553 ));
3505 else 3554 else
3555 who->failmsg (format (
3556 "You feel as if you wanted to do something funny, but you can't remember what. "
3557 "H<The %s skill cannot be readied or used, it is always active.>",
3558 &op->skill, &op->skill
3559 ));
3560
3561 if (tmp) who->insert (tmp);
3562 return 1;
3563 }
3564
3565 if (who->contr)
3506 who->statusmsg (format ( 3566 who->statusmsg (format (
3507 "You ready %s." 3567 op->invisible ? "You can now use the %s skill." : "You ready %s.",
3508 "You can now use the skill: %s.",
3509 query_name (op), 3568 query_name (op),
3510 &op->skill 3569 &op->skill
3511 )); 3570 ));
3512 } 3571 }
3513 3572
3526 } 3585 }
3527 3586
3528 if (player *pl = who->contr) 3587 if (player *pl = who->contr)
3529 { 3588 {
3530 op->flag [FLAG_APPLIED] = true; 3589 op->flag [FLAG_APPLIED] = true;
3531 who->current_weapon = pl->ranged_ob = op;
3532 who->statusmsg (format ("You wield the %s.", query_name (op))); 3590 who->statusmsg (format ("You wield the %s.", query_name (op)));
3533 change_abil (who, op); 3591 change_abil (who, op);
3534 } 3592 }
3535 break; 3593 break;
3536 3594
3537 case RANGED: 3595 case RANGED:
3538 if (player *pl = who->contr) 3596 if (player *pl = who->contr)
3539 { 3597 {
3540 op->flag [FLAG_APPLIED] = true; 3598 op->flag [FLAG_APPLIED] = true;
3541 who->current_weapon = pl->ranged_ob = op;
3542 who->statusmsg (format ("You applied the %s.", query_name (op))); 3599 who->statusmsg (format ("You applied the %s.", query_name (op)));
3543 } 3600 }
3544 break; 3601 break;
3545 3602
3546 case SPELL: 3603 case SPELL:
3547 if (player *pl = who->contr) 3604 if (player *pl = who->contr)
3548 { 3605 {
3549 op->flag [FLAG_APPLIED] = true; 3606 op->flag [FLAG_APPLIED] = true;
3550 who->current_weapon = pl->ranged_ob = op;
3551 who->statusmsg (format ("You ready the spell %s.", query_name (op))); 3607 who->statusmsg (format ("You ready the spell %s.", query_name (op)));
3552 } 3608 }
3553 break; 3609 break;
3554 3610
3555 /*FALLTHROUGH*/ 3611 /*FALLTHROUGH*/
3568 op->flag [FLAG_APPLIED] = true; 3624 op->flag [FLAG_APPLIED] = true;
3569 3625
3570 if (player *pl = who->contr) 3626 if (player *pl = who->contr)
3571 { 3627 {
3572 who->statusmsg (format ("You ready %s.", query_name (op))); 3628 who->statusmsg (format ("You ready %s.", query_name (op)));
3573 who->current_weapon = pl->ranged_ob = op;
3574 3629
3575 if (op->type == BOW) 3630 if (op->type == BOW)
3576 who->statusmsg (format ("You will now fire %s with %s.", op->race ? &op->race : "nothing", query_name (op))); 3631 who->statusmsg (format ("You will now fire %s with %s.", op->race ? &op->race : "nothing", query_name (op)));
3577 3632
3578 change_abil (who, op); 3633 change_abil (who, op);
3590 break; 3645 break;
3591 3646
3592 case BUILDER: 3647 case BUILDER:
3593 if (player *pl = who->contr) 3648 if (player *pl = who->contr)
3594 { 3649 {
3595 who->current_weapon = pl->ranged_ob = op;
3596 who->statusmsg (format ("You ready your %s.", query_name (op))); 3650 who->statusmsg (format ("You ready your %s.", query_name (op)));
3597 //TODO: change_abil? 3651 //TODO: change_abil?
3598 } 3652 }
3599 break; 3653 break;
3600 3654

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines