1 /**
2  * @file
3  * @brief Self-enchantment spells.
4 **/
5 
6 #include "AppHdr.h"
7 
8 #include "spl-selfench.h"
9 
10 #include <cmath>
11 
12 #include "areas.h"
13 #include "coordit.h" // radius_iterator
14 #include "env.h"
15 #include "god-passive.h"
16 #include "hints.h"
17 #include "items.h" // stack_iterator
18 #include "libutil.h"
19 #include "message.h"
20 #include "output.h"
21 #include "prompt.h"
22 #include "religion.h"
23 #include "spl-util.h"
24 #include "stringutil.h"
25 #include "terrain.h"
26 #include "transform.h"
27 #include "tilepick.h"
28 #include "view.h"
29 
cast_deaths_door(int pow,bool fail)30 spret cast_deaths_door(int pow, bool fail)
31 {
32     fail_check();
33     mpr("You stand defiantly in death's doorway!");
34     mprf(MSGCH_SOUND, "You seem to hear sand running through an hourglass...");
35 
36     you.set_duration(DUR_DEATHS_DOOR, 10 + random2avg(13, 3)
37                                        + (random2(pow) / 10));
38 
39     const int hp = max(calc_spell_power(SPELL_DEATHS_DOOR, true) / 10, 1);
40     you.attribute[ATTR_DEATHS_DOOR_HP] = hp;
41     set_hp(hp);
42 
43     if (you.duration[DUR_DEATHS_DOOR] > 25 * BASELINE_DELAY)
44         you.duration[DUR_DEATHS_DOOR] = (23 + random2(5)) * BASELINE_DELAY;
45     return spret::success;
46 }
47 
remove_ice_armour()48 void remove_ice_armour()
49 {
50     mprf(MSGCH_DURATION, "Your icy armour melts away.");
51     you.redraw_armour_class = true;
52     you.duration[DUR_ICY_ARMOUR] = 0;
53 }
54 
ice_armour(int pow,bool fail)55 spret ice_armour(int pow, bool fail)
56 {
57     fail_check();
58 
59     if (you.duration[DUR_ICY_ARMOUR])
60         mpr("Your icy armour thickens.");
61     else if (you.form == transformation::ice_beast)
62         mpr("Your icy body feels more resilient.");
63     else
64         mpr("A film of ice covers your body!");
65 
66     you.increase_duration(DUR_ICY_ARMOUR, random_range(40, 50), 50);
67     you.props[ICY_ARMOUR_KEY] = pow;
68     you.redraw_armour_class = true;
69 
70     return spret::success;
71 }
72 
cast_revivification(int pow,bool fail)73 spret cast_revivification(int pow, bool fail)
74 {
75     fail_check();
76     mpr("Your body is healed in an amazingly painful way.");
77 
78     const int loss = 6 + binomial(9, 8, pow);
79     dec_max_hp(loss * you.hp_max / 100);
80     set_hp(you.hp_max);
81 
82     if (you.duration[DUR_DEATHS_DOOR])
83     {
84         mprf(MSGCH_DURATION, "Your life is in your own hands once again.");
85         // XXX: better cause name?
86         paralyse_player("Death's Door abortion");
87         you.duration[DUR_DEATHS_DOOR] = 0;
88     }
89     return spret::success;
90 }
91 
cast_swiftness(int power,bool fail)92 spret cast_swiftness(int power, bool fail)
93 {
94     fail_check();
95 
96     if (you.in_liquid())
97     {
98         // Hint that the player won't be faster until they leave the liquid.
99         mprf("The %s foams!", you.in_water() ? "water"
100                                              : "liquid ground");
101     }
102 
103     you.set_duration(DUR_SWIFTNESS, 12 + random2(power)/2, 30,
104                      "You feel quick.");
105     you.attribute[ATTR_SWIFTNESS] = you.duration[DUR_SWIFTNESS];
106 
107     return spret::success;
108 }
109 
cast_selective_amnesia(const string & pre_msg)110 int cast_selective_amnesia(const string &pre_msg)
111 {
112     if (you.spell_no == 0)
113     {
114         canned_msg(MSG_NO_SPELLS);
115         return 0;
116     }
117 
118     int keyin = 0;
119     spell_type spell;
120     int slot;
121 
122     // Pick a spell to forget.
123     keyin = list_spells(false, false, false, "Forget which spell?");
124     redraw_screen();
125     update_screen();
126 
127     if (isaalpha(keyin))
128     {
129         spell = get_spell_by_letter(keyin);
130         slot = get_spell_slot_by_letter(keyin);
131 
132         const bool in_library = you.spell_library[spell];
133         if (spell != SPELL_NO_SPELL)
134         {
135             const string prompt = make_stringf(
136                     "Forget %s, freeing %d spell level%s for a total of %d?%s",
137                     spell_title(spell), spell_levels_required(spell),
138                     spell_levels_required(spell) != 1 ? "s" : "",
139                     player_spell_levels() + spell_levels_required(spell),
140                     in_library ? "" : " This spell is not in your library!");
141 
142             if (yesno(prompt.c_str(), in_library, 'n', false))
143             {
144                 if (!pre_msg.empty())
145                     mpr(pre_msg);
146                 del_spell_from_memory_by_slot(slot);
147                 return 1;
148             }
149         }
150     }
151 
152     return -1;
153 }
154 
cast_wereblood(int pow,bool fail)155 spret cast_wereblood(int pow, bool fail)
156 {
157     fail_check();
158 
159     if (you.duration[DUR_WEREBLOOD])
160         mpr("Your blood is freshly infused with primal strength!");
161     else
162         mpr("Your blood is infused with primal strength.");
163 
164     you.set_duration(DUR_WEREBLOOD, 20 + random2avg(pow, 2));
165 
166     you.props[WEREBLOOD_KEY] = 0;
167     return spret::success;
168 }
169 
cast_silence(int pow,bool fail)170 spret cast_silence(int pow, bool fail)
171 {
172     fail_check();
173     mpr("A profound silence engulfs you.");
174 
175     you.increase_duration(DUR_SILENCE, 10 + pow/4 + random2avg(pow/2, 2), 100);
176     invalidate_agrid(true);
177 
178     if (you.beheld())
179         you.update_beholders();
180 
181     learned_something_new(HINT_YOU_SILENCE);
182     return spret::success;
183 }
184 
cast_liquefaction(int pow,bool fail)185 spret cast_liquefaction(int pow, bool fail)
186 {
187     fail_check();
188     flash_view_delay(UA_PLAYER, BROWN, 80);
189     flash_view_delay(UA_PLAYER, YELLOW, 80);
190     flash_view_delay(UA_PLAYER, BROWN, 140);
191 
192     mpr("The ground around you becomes liquefied!");
193 
194     you.increase_duration(DUR_LIQUEFYING, 10 + random2avg(pow, 2), 100);
195     invalidate_agrid(true);
196     return spret::success;
197 }
198 
cast_transform(int pow,transformation which_trans,bool fail)199 spret cast_transform(int pow, transformation which_trans, bool fail)
200 {
201     if (!transform(pow, which_trans, false, true)
202         || !check_form_stat_safety(which_trans))
203     {
204         return spret::abort;
205     }
206 
207     fail_check();
208     transform(pow, which_trans);
209     return spret::success;
210 }
211