2 * File: spl-selfench.cc
3 * Summary: Self-enchantment spells.
8 #include "spl-selfench.h"
14 #include "godconduct.h"
23 #include "spl-other.h"
26 #include "transform.h"
29 int allowed_deaths_door_hp(void)
31 int hp
= you
.skills
[SK_NECROMANCY
] / 2;
33 if (you
.religion
== GOD_KIKUBAAQUDGHA
&& !player_under_penance())
36 return std::max(hp
, 1);
39 bool cast_deaths_door(int pow
)
42 mpr("You're already dead!");
43 else if (you
.duration
[DUR_DEATHS_DOOR
])
44 mpr("Your appeal for an extension has been denied.");
47 mpr("You feel invincible!");
48 mpr("You seem to hear sand running through an hourglass...",
51 set_hp(allowed_deaths_door_hp(), false);
52 deflate_hp(you
.hp_max
, false);
54 you
.set_duration(DUR_DEATHS_DOOR
, 10 + random2avg(13, 3)
55 + (random2(pow
) / 10));
57 if (you
.duration
[DUR_DEATHS_DOOR
] > 25 * BASELINE_DELAY
)
58 you
.duration
[DUR_DEATHS_DOOR
] = (23 + random2(5)) * BASELINE_DELAY
;
65 static bool _know_spell(spell_type spell
)
67 if (spell
== NUM_SPELLS
)
70 if (!you
.has_spell(spell
))
72 mprf("You don't know how to extend %s.", spell_title(spell
));
76 int fail
= spell_fail(spell
);
77 dprf("fail = %d", fail
);
79 if (fail
> random2(50) + 50)
81 mprf("Your knowledge of %s fails you.", spell_title(spell
));
88 static spell_type
_brand_spell()
90 const item_def
*wpn
= you
.weapon();
95 const int wpn_type
= get_vorpal_type(*wpn
);
96 switch(get_weapon_brand(*wpn
))
100 return SPELL_FIRE_BRAND
;
103 return SPELL_FREEZING_AURA
;
105 if (wpn_type
== DVORP_CRUSHING
)
106 return SPELL_MAXWELLS_SILVER_HAMMER
;
109 if (wpn_type
== DVORP_CRUSHING
)
111 return SPELL_POISON_WEAPON
;
113 return SPELL_EXCRUCIATING_WOUNDS
;
115 return SPELL_LETHAL_INFUSION
;
116 case SPWPN_DISTORTION
:
117 return SPELL_WARP_BRAND
;
123 static spell_type
_transform_spell()
127 case TRAN_BLADE_HANDS
:
128 return SPELL_BLADE_HANDS
;
130 return SPELL_SPIDER_FORM
;
132 return SPELL_STATUE_FORM
;
134 return SPELL_ICE_FORM
;
136 return SPELL_DRAGON_FORM
;
138 return SPELL_NECROMUTATION
;
140 return NUM_SPELLS
; // no spell
142 return SPELL_PORKALATOR
; // Kirke/Nemelex only
148 void extension(int pow
)
150 int contamination
= random2(2);
152 if (you
.duration
[DUR_HASTE
] && _know_spell(SPELL_HASTE
))
154 potion_effect(POT_SPEED
, pow
);
158 if (you
.duration
[DUR_SLOW
] && _know_spell(SPELL_SLOW
)) // heh heh
159 potion_effect(POT_SLOWING
, pow
);
161 if (you
.duration
[DUR_LEVITATION
] && !you
.duration
[DUR_CONTROLLED_FLIGHT
]
162 && _know_spell(SPELL_LEVITATION
))
164 levitate_player(pow
);
167 if (you
.duration
[DUR_INVIS
] && _know_spell(SPELL_INVISIBILITY
))
169 potion_effect(POT_INVISIBILITY
, pow
);
173 if (you
.duration
[DUR_ICY_ARMOUR
] && _know_spell(SPELL_OZOCUBUS_ARMOUR
))
174 ice_armour(pow
, true);
176 if (you
.duration
[DUR_REPEL_MISSILES
] && _know_spell(SPELL_REPEL_MISSILES
))
179 if (you
.duration
[DUR_REGENERATION
] && _know_spell(SPELL_REGENERATION
)
180 && you
.form
!= TRAN_LICH
)
185 if (you
.duration
[DUR_DEFLECT_MISSILES
]
186 && _know_spell(SPELL_DEFLECT_MISSILES
))
191 if (you
.duration
[DUR_FIRE_SHIELD
] && _know_spell(SPELL_RING_OF_FLAMES
))
193 you
.increase_duration(DUR_FIRE_SHIELD
, random2(pow
/ 20), 50);
194 mpr("Your ring of flames roars with new vigour!");
197 if (!you
.duration
[DUR_WEAPON_BRAND
] < 1 && _know_spell(_brand_spell()))
199 you
.increase_duration(DUR_WEAPON_BRAND
, 5 + random2(8), 80);
202 if (you
.duration
[DUR_SWIFTNESS
] && _know_spell(SPELL_SWIFTNESS
))
205 if (you
.duration
[DUR_INSULATION
] && _know_spell(SPELL_INSULATION
))
206 cast_insulation(pow
);
208 if (you
.duration
[DUR_CONTROLLED_FLIGHT
] && _know_spell(SPELL_FLY
))
211 if (you
.duration
[DUR_CONTROL_TELEPORT
]
212 && _know_spell(SPELL_CONTROL_TELEPORT
))
214 cast_teleport_control(pow
);
217 if (you
.duration
[DUR_RESIST_POISON
] && _know_spell(SPELL_RESIST_POISON
))
218 cast_resist_poison(pow
);
220 if (you
.duration
[DUR_TRANSFORMATION
] && _know_spell(_transform_spell()))
222 mpr("Your transformation has been extended.");
223 you
.increase_duration(DUR_TRANSFORMATION
, random2(pow
), 100,
224 "Your transformation has been extended.");
226 if (you
.form
== TRAN_LICH
227 && is_good_god(you
.religion
))
229 // possible with Xom or a card
233 // Give a warning if it won't last long enough for the
235 transformation_expiration_warning();
238 if (you
.duration
[DUR_STONESKIN
] && _know_spell(SPELL_STONESKIN
))
241 if (you
.duration
[DUR_PHASE_SHIFT
] && _know_spell(SPELL_PHASE_SHIFT
))
242 cast_phase_shift(pow
);
244 if (you
.duration
[DUR_SEE_INVISIBLE
] && _know_spell(SPELL_SEE_INVISIBLE
))
245 cast_see_invisible(pow
);
247 if (you
.duration
[DUR_SILENCE
] && _know_spell(SPELL_SILENCE
))
248 cast_silence(pow
); //how precisely did you cast extension?
250 if (you
.duration
[DUR_CONDENSATION_SHIELD
]
251 && _know_spell(SPELL_CONDENSATION_SHIELD
))
253 cast_condensation_shield(pow
);
256 if (you
.duration
[DUR_DEATH_CHANNEL
] && _know_spell(SPELL_DEATH_CHANNEL
))
257 cast_death_channel(pow
);
259 if (you
.duration
[DUR_DEATHS_DOOR
] && _know_spell(SPELL_DEATHS_DOOR
))
260 cast_deaths_door(pow
); // just for the fail message
263 contaminate_player(contamination
, true);
266 void remove_ice_armour()
268 mpr("Your icy armour melts away.", MSGCH_DURATION
);
269 you
.redraw_armour_class
= true;
270 you
.duration
[DUR_ICY_ARMOUR
] = 0;
273 void ice_armour(int pow
, bool extending
)
275 if (!player_effectively_in_light_armour())
278 mpr("You are wearing too much armour.");
283 if (you
.duration
[DUR_STONEMAIL
] || you
.duration
[DUR_STONESKIN
])
286 mpr("The spell conflicts with another spell still in effect.");
291 if (you
.duration
[DUR_ICY_ARMOUR
])
292 mpr("Your icy armour thickens.");
295 if (you
.form
== TRAN_ICE_BEAST
)
296 mpr("Your icy body feels more resilient.");
298 mpr("A film of ice covers your body!");
300 you
.redraw_armour_class
= true;
303 you
.increase_duration(DUR_ICY_ARMOUR
, 20 + random2(pow
) + random2(pow
), 50,
307 void missile_prot(int pow
)
309 you
.increase_duration(DUR_REPEL_MISSILES
, 8 + roll_dice(2, pow
), 100,
310 "You feel protected from missiles.");
313 void deflection(int pow
)
315 you
.increase_duration(DUR_DEFLECT_MISSILES
, 15 + random2(pow
), 100,
316 "You feel very safe from missiles.");
319 void remove_regen(bool divine_ability
)
321 mpr("Your skin stops crawling.", MSGCH_DURATION
);
322 you
.duration
[DUR_REGENERATION
] = 0;
325 mpr("You feel less resistant to magic.", MSGCH_DURATION
);
326 you
.attribute
[ATTR_DIVINE_REGENERATION
] = 0;
330 void cast_regen(int pow
, bool divine_ability
)
332 you
.increase_duration(DUR_REGENERATION
, 5 + roll_dice(2, pow
/ 3 + 1), 100,
333 "Your skin crawls.");
337 mpr("You feel resistant to magic.");
338 you
.attribute
[ATTR_DIVINE_REGENERATION
] = 1;
342 void cast_berserk(void)
347 void cast_swiftness(int power
)
351 mpr("The water foams!");
355 if (!you
.duration
[DUR_SWIFTNESS
] && player_movement_speed() <= 6)
357 mpr("You can't move any more quickly.");
361 // [dshaligram] Removed the on-your-feet bit. Sounds odd when
362 // you're levitating, for instance.
363 you
.increase_duration(DUR_SWIFTNESS
, 20 + random2(power
), 100,
365 did_god_conduct(DID_HASTY
, 8, true);
368 void cast_fly(int power
)
370 const int dur_change
= 25 + random2(power
) + random2(power
);
371 const bool was_levitating
= you
.airborne();
373 you
.increase_duration(DUR_LEVITATION
, dur_change
, 100);
374 you
.increase_duration(DUR_CONTROLLED_FLIGHT
, dur_change
, 100);
381 mpr("You feel more buoyant.");
384 void cast_insulation(int power
)
386 you
.increase_duration(DUR_INSULATION
, 10 + random2(power
), 100,
387 "You feel insulated.");
390 void cast_resist_poison(int power
)
392 you
.increase_duration(DUR_RESIST_POISON
, 10 + random2(power
), 100,
393 "You feel resistant to poison.");
396 void cast_teleport_control(int power
)
398 you
.increase_duration(DUR_CONTROL_TELEPORT
, 10 + random2(power
), 50,
399 "You feel in control.");
402 int cast_selective_amnesia(std::string
*pre_msg
)
404 if (you
.spell_no
== 0)
406 canned_msg(MSG_NO_SPELLS
);
414 // Pick a spell to forget.
417 mpr("Forget which spell ([?*] list [ESC] exit)? ", MSGCH_PROMPT
);
420 if (key_is_escape(keyin
))
426 if (keyin
== '?' || keyin
== '*')
428 keyin
= list_spells(false, false, false);
432 if (!isaalpha(keyin
))
438 spell
= get_spell_by_letter(keyin
);
439 slot
= get_spell_slot_by_letter(keyin
);
441 if (spell
== SPELL_NO_SPELL
)
442 mpr("You don't know that spell.");
448 mpr(pre_msg
->c_str());
450 const int ep_gain
= spell_mana(spell
);
451 del_spell_from_memory_by_slot(slot
);
455 inc_mp(ep_gain
, false);
456 mpr("The spell releases its latent energy back to you as "
463 void cast_see_invisible(int pow
)
465 if (you
.can_see_invisible())
466 mpr("You feel as though your vision will be sharpened longer.");
469 mpr("Your vision seems to sharpen.");
471 // We might have to turn autopickup back on again.
472 // TODO: Once the spell times out we might want to check all monsters
473 // in LOS for invisibility and turn autopickup off again, if
475 autotoggle_autopickup(false);
478 // No message if you already are under the spell.
479 you
.increase_duration(DUR_SEE_INVISIBLE
, 10 + random2(2 + pow
/2), 100);
482 void cast_silence(int pow
)
484 if (!you
.attribute
[ATTR_WAS_SILENCED
])
485 mpr("A profound silence engulfs you.");
487 you
.attribute
[ATTR_WAS_SILENCED
] = 1;
489 you
.increase_duration(DUR_SILENCE
, 10 + random2avg(pow
, 2), 100);
490 invalidate_agrid(true);
493 you
.update_beholders();
495 learned_something_new(HINT_YOU_SILENCE
);
498 void cast_liquefaction(int pow
)
500 flash_view_delay(BROWN
, 80);
501 flash_view_delay(YELLOW
, 80);
502 flash_view_delay(BROWN
, 140);
504 mpr("The ground around you becomes liquefied!");
506 you
.increase_duration(DUR_LIQUEFYING
, 10 + random2avg(pow
, 2), 100);
507 invalidate_agrid(true);