1 /**
2  * @file
3  * @brief Weapon enchantment spells.
4 **/
5 
6 #include "AppHdr.h"
7 
8 #include "spl-wpnench.h"
9 
10 #include "areas.h"
11 #include "god-item.h"
12 #include "god-passive.h"
13 #include "item-prop.h"
14 #include "message.h"
15 #include "player-equip.h"
16 #include "prompt.h"
17 #include "religion.h"
18 #include "shout.h"
19 #include "spl-miscast.h"
20 #include "spl-summoning.h"
21 
22 /** End your weapon branding spell.
23  *
24  * Returns the weapon to the previous brand, and ends DUR_EXCRUCIATING_WOUNDS.
25  * @param weapon The item in question (which may have just been unwielded).
26  * @param verbose whether to print a message about expiration.
27  */
end_weapon_brand(item_def & weapon,bool verbose)28 void end_weapon_brand(item_def &weapon, bool verbose)
29 {
30     ASSERT(you.duration[DUR_EXCRUCIATING_WOUNDS]);
31 
32     set_item_ego_type(weapon, OBJ_WEAPONS, you.props[ORIGINAL_BRAND_KEY]);
33     you.props.erase(ORIGINAL_BRAND_KEY);
34     you.duration[DUR_EXCRUCIATING_WOUNDS] = 0;
35 
36     if (verbose)
37     {
38         mprf(MSGCH_DURATION, "%s seems less pained.",
39              weapon.name(DESC_YOUR).c_str());
40     }
41 
42     you.wield_change = true;
43     const brand_type real_brand = get_weapon_brand(weapon);
44     if (real_brand == SPWPN_ANTIMAGIC)
45         calc_mp();
46     if (you.weapon() && is_holy_item(weapon) && you.form == transformation::lich)
47     {
48         mprf(MSGCH_DURATION, "%s falls away!", weapon.name(DESC_YOUR).c_str());
49         unequip_item(EQ_WEAPON);
50     }
51 }
52 
53 /**
54  * Temporarily brand a weapon with pain.
55  *
56  * @param[in] power         Spellpower.
57  * @param[in] fail          Whether you've already failed to cast.
58  * @return                  Success, fail, or abort.
59  */
cast_excruciating_wounds(int power,bool fail)60 spret cast_excruciating_wounds(int power, bool fail)
61 {
62     item_def& weapon = *you.weapon();
63     const brand_type which_brand = SPWPN_PAIN;
64     const brand_type orig_brand = get_weapon_brand(weapon);
65 
66     // Can only brand melee weapons.
67     if (is_range_weapon(weapon))
68     {
69         mpr("You cannot brand ranged weapons with this spell.");
70         return spret::abort;
71     }
72 
73     bool has_temp_brand = you.duration[DUR_EXCRUCIATING_WOUNDS];
74     if (!has_temp_brand && get_weapon_brand(weapon) == which_brand)
75     {
76         mpr("This weapon is already branded with pain.");
77         return spret::abort;
78     }
79 
80     const bool dangerous_disto = orig_brand == SPWPN_DISTORTION
81                                  && !have_passive(passive_t::safe_distortion);
82     if (dangerous_disto)
83     {
84         const string prompt =
85               "Really brand " + weapon.name(DESC_INVENTORY) + "?";
86         if (!yesno(prompt.c_str(), false, 'n'))
87         {
88             canned_msg(MSG_OK);
89             return spret::abort;
90         }
91     }
92 
93     fail_check();
94 
95     if (dangerous_disto)
96         unwield_distortion(true);
97 
98     noisy(spell_effect_noise(SPELL_EXCRUCIATING_WOUNDS), you.pos());
99     mprf("%s %s in agony.", weapon.name(DESC_YOUR).c_str(),
100                             silenced(you.pos()) ? "writhes" : "shrieks");
101 
102     if (!has_temp_brand)
103     {
104         you.props[ORIGINAL_BRAND_KEY] = get_weapon_brand(weapon);
105         set_item_ego_type(weapon, OBJ_WEAPONS, which_brand);
106         you.wield_change = true;
107         if (you.duration[DUR_SPWPN_PROTECTION])
108         {
109             you.duration[DUR_SPWPN_PROTECTION] = 0;
110             you.redraw_armour_class = true;
111         }
112         if (orig_brand == SPWPN_ANTIMAGIC)
113             calc_mp();
114         monster * spectral = find_spectral_weapon(&you);
115         if (orig_brand == SPWPN_SPECTRAL && spectral)
116             end_spectral_weapon(spectral, false);
117     }
118 
119     you.increase_duration(DUR_EXCRUCIATING_WOUNDS, 8 + roll_dice(2, power), 50);
120 
121     return spret::success;
122 }
123 
cast_confusing_touch(int power,bool fail)124 spret cast_confusing_touch(int power, bool fail)
125 {
126     fail_check();
127     msg::stream << you.hands_act("begin", "to glow ")
128                 << (you.duration[DUR_CONFUSING_TOUCH] ? "brighter" : "red")
129                 << "." << endl;
130 
131     you.set_duration(DUR_CONFUSING_TOUCH,
132                      max(10 + random2(power) / 5,
133                          you.duration[DUR_CONFUSING_TOUCH]),
134                      20, nullptr);
135     you.props["confusing touch power"] = power;
136 
137     return spret::success;
138 }
139