1 /**
2  * @file
3  * @brief Monster-affecting enchantment spells.
4  *           Other targeted enchantments are handled in spl-zap.cc.
5 **/
6 
7 #include "AppHdr.h"
8 
9 #include "spl-monench.h"
10 
11 #include "env.h"
12 #include "message.h"
13 #include "spl-util.h"
14 #include "terrain.h"
15 
englaciate(coord_def where,int pow,actor * agent)16 int englaciate(coord_def where, int pow, actor *agent)
17 {
18     actor *victim = actor_at(where);
19 
20     if (!victim || victim == agent)
21         return 0;
22 
23     if (agent->is_monster() && mons_aligned(agent, victim))
24         return 0; // don't let monsters hit friendlies
25 
26     monster* mons = victim->as_monster();
27 
28     if (victim->res_cold() > 0
29         || victim->is_stationary())
30     {
31         if (!mons)
32             canned_msg(MSG_YOU_UNAFFECTED);
33         else if (!mons_is_firewood(*mons))
34             simple_monster_message(*mons, " is unaffected.");
35         return 0;
36     }
37 
38     int duration = (roll_dice(3, pow) / 6
39                     - victim->get_hit_dice() / 2)
40                     * BASELINE_DELAY;
41 
42     if (duration <= 0)
43     {
44         if (!mons)
45             canned_msg(MSG_YOU_RESIST);
46         else
47             simple_monster_message(*mons, " resists.");
48         return 0;
49     }
50 
51     if ((!mons && you.get_mutation_level(MUT_COLD_BLOODED))
52         || (mons && mons_class_flag(mons->type, M_COLD_BLOOD)))
53     {
54         duration *= 2;
55     }
56 
57     if (!mons)
58         return slow_player(duration);
59 
60     return do_slow_monster(*mons, agent, duration);
61 }
62 
cast_englaciation(int pow,bool fail)63 spret cast_englaciation(int pow, bool fail)
64 {
65     fail_check();
66     mpr("You radiate an aura of cold.");
67     apply_area_visible([pow] (coord_def where) {
68         return englaciate(where, pow, &you);
69     }, you.pos());
70     return spret::success;
71 }
72 
73 /** Corona a monster.
74  *
75  *  @param mons the monster to get a backlight.
76  *  @returns true if it got backlit (even if it was already).
77  */
backlight_monster(monster * mons)78 bool backlight_monster(monster* mons)
79 {
80     const mon_enchant bklt = mons->get_ench(ENCH_CORONA);
81     const mon_enchant zin_bklt = mons->get_ench(ENCH_SILVER_CORONA);
82     const int lvl = bklt.degree + zin_bklt.degree;
83 
84     mons->add_ench(mon_enchant(ENCH_CORONA, 1));
85 
86     if (lvl == 0)
87         simple_monster_message(*mons, " is outlined in light.");
88     else if (lvl == 4)
89         simple_monster_message(*mons, " glows brighter for a moment.");
90     else
91         simple_monster_message(*mons, " glows brighter.");
92 
93     return true;
94 }
95 
do_slow_monster(monster & mon,const actor * agent,int dur)96 bool do_slow_monster(monster& mon, const actor* agent, int dur)
97 {
98     if (mon.stasis())
99         return true;
100 
101     if (!mon.is_stationary()
102         && mon.add_ench(mon_enchant(ENCH_SLOW, 0, agent, dur)))
103     {
104         if (!mon.paralysed() && !mon.petrified()
105             && simple_monster_message(mon, " seems to slow down."))
106         {
107             return true;
108         }
109     }
110 
111     return false;
112 }
113