… | |
… | |
2642 | if (op == pl->combat_ob) pl->combat_ob = 0; |
2642 | if (op == pl->combat_ob) pl->combat_ob = 0; |
2643 | } |
2643 | } |
2644 | |
2644 | |
2645 | switch (op->type) |
2645 | switch (op->type) |
2646 | { |
2646 | { |
|
|
2647 | case SKILL_TOOL: |
|
|
2648 | // unapplying a skill tool should also unapply the skill it governs |
|
|
2649 | // but this is hard, as it shouldn't do so when the skill can |
|
|
2650 | // be used for other reasons |
|
|
2651 | for (object *tmp = who->inv; tmp; tmp = tmp->below) |
|
|
2652 | if (tmp->skill == op->skill |
|
|
2653 | && tmp->type == SKILL |
|
|
2654 | && tmp->flag [FLAG_APPLIED] |
|
|
2655 | && !tmp->flag [FLAG_CAN_USE_SKILL]) |
|
|
2656 | unapply_special (who, tmp, 0); |
|
|
2657 | |
|
|
2658 | change_abil (who, op); |
|
|
2659 | break; |
|
|
2660 | |
2647 | case WEAPON: |
2661 | case WEAPON: |
2648 | new_draw_info_format (NDI_UNIQUE, 0, who, "You unwield %s.", query_name (op)); |
2662 | new_draw_info_format (NDI_UNIQUE, 0, who, "You unwield %s.", query_name (op)); |
2649 | |
2663 | |
2650 | change_abil (who, op); |
2664 | change_abil (who, op); |
2651 | CLEAR_FLAG (who, FLAG_READY_WEAPON); |
2665 | CLEAR_FLAG (who, FLAG_READY_WEAPON); |
2652 | clear_skill (who); |
2666 | clear_skill (who); |
2653 | break; |
2667 | break; |
2654 | |
2668 | |
2655 | case SKILL: /* allows objects to impart skills */ |
|
|
2656 | case SKILL_TOOL: |
2669 | case SKILL: |
2657 | if (op != who->chosen_skill) |
2670 | if (op != who->chosen_skill) |
2658 | LOG (llevError, "BUG: apply_special(): applied skill is not a chosen skill\n"); |
2671 | LOG (llevError, "BUG: apply_special(): applied skill is not a chosen skill\n"); |
2659 | |
2672 | |
2660 | if (who->contr) |
2673 | if (who->contr) |
2661 | { |
2674 | { |
… | |
… | |
2784 | /** |
2797 | /** |
2785 | * Returns the object that is using location 'loc'. |
2798 | * Returns the object that is using location 'loc'. |
2786 | * Note that 'start' is the first object to start examing - we |
2799 | * Note that 'start' is the first object to start examing - we |
2787 | * then go through the below of this. In this way, you can do |
2800 | * then go through the below of this. In this way, you can do |
2788 | * something like: |
2801 | * something like: |
2789 | * tmp = get_item_from_body_location(who->inv, 1); |
2802 | * tmp = get_next_item_from_body_location(who->inv, 1); |
2790 | * if (tmp) tmp1 = get_item_from_body_location(tmp->below, 1); |
2803 | * if (tmp) tmp1 = get_next_item_from_body_location(tmp->below, 1); |
2791 | * to find the second object that may use this location, etc. |
2804 | * to find the second object that may use this location, etc. |
2792 | * Returns NULL if no match is found. |
2805 | * Returns NULL if no match is found. |
2793 | * loc is the index into the array we are looking for a match. |
2806 | * loc is the index into the array we are looking for a match. |
2794 | * don't return invisible objects unless they are skill objects |
2807 | * don't return invisible objects unless they are skill objects |
2795 | * invisible other objects that use |
2808 | * invisible other objects that use |
2796 | * up body locations can be used as restrictions. |
2809 | * up body locations can be used as restrictions. |
2797 | */ |
2810 | */ |
2798 | static object * |
2811 | static object * |
2799 | get_item_from_body_location (int loc, object *start) |
2812 | get_next_item_from_body_location (int loc, object *start) |
2800 | { |
2813 | { |
2801 | if (start) |
2814 | if (start) |
2802 | for (object *tmp = start; tmp; tmp = tmp->below) |
2815 | for (object *tmp = start; tmp; tmp = tmp->below) |
2803 | if (QUERY_FLAG (tmp, FLAG_APPLIED) && tmp->slot[loc].info && (!tmp->invisible || tmp->type == SKILL)) |
2816 | if (tmp->flag [FLAG_APPLIED] |
|
|
2817 | && tmp->slot[loc].info |
|
|
2818 | && !tmp->invisible) |
2804 | return tmp; |
2819 | return tmp; |
2805 | |
2820 | |
2806 | return 0; |
2821 | return 0; |
2807 | } |
2822 | } |
2808 | |
2823 | |
… | |
… | |
2850 | /* We do a while loop - may need to remove several items in order |
2865 | /* We do a while loop - may need to remove several items in order |
2851 | * to free up enough slots. |
2866 | * to free up enough slots. |
2852 | */ |
2867 | */ |
2853 | while ((who->slot[i].used + op->slot[i].info) < 0) |
2868 | while ((who->slot[i].used + op->slot[i].info) < 0) |
2854 | { |
2869 | { |
2855 | object *tmp = get_item_from_body_location (i, last); |
2870 | object *tmp = get_next_item_from_body_location (i, last); |
2856 | |
2871 | |
2857 | if (!tmp) |
2872 | if (!tmp) |
2858 | { |
2873 | { |
2859 | #if 0 |
2874 | #if 0 |
2860 | /* Not a bug - we'll get this if the player has cursed items |
2875 | /* Not a bug - we'll get this if the player has cursed items |
… | |
… | |
2898 | * Checks to see if 'who' can apply object 'op'. |
2913 | * Checks to see if 'who' can apply object 'op'. |
2899 | * Returns 0 if apply can be done without anything special. |
2914 | * Returns 0 if apply can be done without anything special. |
2900 | * Otherwise returns a bitmask - potentially several of these may be |
2915 | * Otherwise returns a bitmask - potentially several of these may be |
2901 | * set, but largely depends on circumstance - in the future, processing |
2916 | * set, but largely depends on circumstance - in the future, processing |
2902 | * may be pruned once we know some status (eg, once CAN_APPLY_NEVER |
2917 | * may be pruned once we know some status (eg, once CAN_APPLY_NEVER |
2903 | * is set, do we really are what the other flags may be?) |
2918 | * is set, do we really care what the other flags may be?) |
2904 | * |
2919 | * |
2905 | * See include/define.h for detailed description of the meaning of |
2920 | * See include/define.h for detailed description of the meaning of |
2906 | * these return values. |
2921 | * these return values. |
2907 | */ |
2922 | */ |
2908 | int |
2923 | int |
… | |
… | |
2917 | for (int i = 0; i < NUM_BODY_LOCATIONS; i++) |
2932 | for (int i = 0; i < NUM_BODY_LOCATIONS; i++) |
2918 | { |
2933 | { |
2919 | if (op->slot[i].info) |
2934 | if (op->slot[i].info) |
2920 | { |
2935 | { |
2921 | /* Item uses more slots than we have */ |
2936 | /* Item uses more slots than we have */ |
2922 | if (abs (op->slot[i].info) > who->slot[i].info) |
2937 | if (who->slot[i].info + op->slot [i].info < 0) |
2923 | { |
2938 | { |
2924 | /* Could return now for efficiency - rest of info below isn't |
2939 | /* Could return now for efficiency - rest of info below isn't |
2925 | * really needed. |
2940 | * really needed. |
2926 | */ |
2941 | */ |
2927 | retval |= CAN_APPLY_NEVER; |
2942 | retval |= CAN_APPLY_NEVER; |
2928 | } |
2943 | } |
2929 | else if ((who->slot[i].used + op->slot[i].info) < 0) |
2944 | else if (who->slot[i].used + op->slot[i].info < 0) |
2930 | { |
2945 | { |
2931 | /* in this case, equipping this would use more free spots than |
2946 | /* in this case, equipping this would use more free spots than |
2932 | * we have. |
2947 | * we have. |
2933 | */ |
2948 | */ |
2934 | |
2949 | |
… | |
… | |
2945 | { |
2960 | { |
2946 | retval |= CAN_APPLY_UNAPPLY; |
2961 | retval |= CAN_APPLY_UNAPPLY; |
2947 | continue; |
2962 | continue; |
2948 | } |
2963 | } |
2949 | |
2964 | |
2950 | object *tmp1 = get_item_from_body_location (i, who->inv); |
2965 | object *tmp1 = get_next_item_from_body_location (i, who->inv); |
2951 | if (!tmp1) |
2966 | if (!tmp1) |
2952 | { |
2967 | { |
2953 | #if 0 |
2968 | #if 0 |
2954 | /* This is sort of an error, but happens a lot when old players |
2969 | /* This is sort of an error, but happens a lot when old players |
2955 | * join in with more stuff equipped than they are now allowed. |
2970 | * join in with more stuff equipped than they are now allowed. |
… | |
… | |
2963 | /* need to unapply something. However, if this something |
2978 | /* need to unapply something. However, if this something |
2964 | * is different than we had found before, it means they need |
2979 | * is different than we had found before, it means they need |
2965 | * to apply multiple objects |
2980 | * to apply multiple objects |
2966 | */ |
2981 | */ |
2967 | retval |= CAN_APPLY_UNAPPLY; |
2982 | retval |= CAN_APPLY_UNAPPLY; |
|
|
2983 | |
2968 | if (!tmp) |
2984 | if (!tmp) |
2969 | tmp = tmp1; |
2985 | tmp = tmp1; |
2970 | else if (tmp != tmp1) |
2986 | else if (tmp != tmp1) |
2971 | retval |= CAN_APPLY_UNAPPLY_MULT; |
2987 | retval |= CAN_APPLY_UNAPPLY_MULT; |
2972 | |
2988 | |
… | |
… | |
3262 | if (who->type == PLAYER) |
3278 | if (who->type == PLAYER) |
3263 | esrv_send_item (who, tmp2); |
3279 | esrv_send_item (who, tmp2); |
3264 | |
3280 | |
3265 | return 0; |
3281 | return 0; |
3266 | |
3282 | |
3267 | /* this part is needed for skill-tools */ |
3283 | case SKILL_TOOL: |
|
|
3284 | // applying a skill tool also readies the skill |
|
|
3285 | SET_FLAG (op, FLAG_APPLIED); |
|
|
3286 | skop = find_skill_by_name (who, op->skill); |
|
|
3287 | if (!skop->flag [FLAG_APPLIED]) |
|
|
3288 | apply_special (who, skop, AP_APPLY); |
|
|
3289 | break; |
|
|
3290 | |
3268 | case SKILL: |
3291 | case SKILL: |
3269 | case SKILL_TOOL: |
|
|
3270 | if (who->chosen_skill) |
3292 | if (who->chosen_skill) |
3271 | { |
3293 | { |
3272 | LOG (llevError, "BUG: apply_special(): can't apply two skills\n"); |
3294 | LOG (llevError, "BUG: apply_special(): can't apply two skills\n"); |
3273 | return 1; |
3295 | return 1; |
3274 | } |
3296 | } |