Apply the new ground_level method.
[crawl.git] / crawl-ref / source / behold.cc
blob70068f1651e12e4476e583f2da552f8f6ac89db8
1 /*
2 * File: behold.cc
3 * Summary: player methods dealing with mesmerisation.
4 */
6 #include "AppHdr.h"
8 #include "player.h"
10 #include "coord.h"
11 #include "debug.h"
12 #include "env.h"
13 #include "fprop.h"
14 #include "mon-util.h"
15 #include "monster.h"
16 #include "random.h"
17 #include "state.h"
18 #include "stuff.h"
19 #include "areas.h"
21 // Add a monster to the list of beholders.
22 void player::add_beholder(const monster* mon)
24 if (is_sanctuary(you.pos()))
26 if (you.can_see(mon))
28 mprf("%s's singing sounds muted, and has no effect on you.",
29 mon->name(DESC_CAP_THE).c_str());
31 else
33 mpr("The melody is strangely muted, and has no effect on you.");
35 return;
38 if (!duration[DUR_MESMERISED])
40 you.set_duration(DUR_MESMERISED, 7, 12);
41 beholders.push_back(mon->mindex());
42 mprf(MSGCH_WARN, "You are mesmerised by %s!",
43 mon->name(DESC_NOCAP_THE).c_str());
45 else
47 you.increase_duration(DUR_MESMERISED, 5, 12);
48 if (!beheld_by(mon))
49 beholders.push_back(mon->mindex());
53 // Whether player is mesmerised.
54 bool player::beheld() const
56 ASSERT(duration[DUR_MESMERISED] > 0 == !beholders.empty());
57 return (duration[DUR_MESMERISED] > 0);
60 // Whether player is mesmerised by the given monster.
61 bool player::beheld_by(const monster* mon) const
63 for (unsigned int i = 0; i < beholders.size(); i++)
64 if (beholders[i] == mon->mindex())
65 return (true);
66 return (false);
69 // Checks whether a beholder keeps you from moving to
70 // target, and returns one if it exists.
71 monster* player::get_beholder(const coord_def &target) const
73 for (unsigned int i = 0; i < beholders.size(); i++)
75 monster* mon = &menv[beholders[i]];
76 const int olddist = grid_distance(pos(), mon->pos());
77 const int newdist = grid_distance(target, mon->pos());
79 if (olddist < newdist)
80 return (mon);
82 return (NULL);
85 monster* player::get_any_beholder() const
87 if (beholders.size() > 0)
88 return (&menv[beholders[0]]);
89 else
90 return (NULL);
93 // Removes a monster from the list of beholders if present.
94 void player::remove_beholder(const monster* mon)
96 for (unsigned int i = 0; i < beholders.size(); i++)
97 if (beholders[i] == mon->mindex())
99 beholders.erase(beholders.begin() + i);
100 _removed_beholder();
101 return;
105 // Clear the list of beholders. Doesn't message.
106 void player::clear_beholders()
108 beholders.clear();
109 duration[DUR_MESMERISED] = 0;
112 // Possibly end mesmerisation if a loud noise happened.
113 void player::beholders_check_noise(int loudness)
115 if (loudness >= 20 && beheld())
117 mprf("For a moment, you cannot hear the mermaid%s!",
118 beholders.size() > 1 ? "s" : "");
119 clear_beholders();
120 _removed_beholder();
124 static void _removed_beholder_msg(const monster* mon)
126 if (!mon->alive() || mons_genus(mon->type) != MONS_MERMAID
127 || mon->submerged() || !you.see_cell(mon->pos()))
129 return;
132 if (is_sanctuary(you.pos()) && !mons_is_fleeing(mon))
134 if (you.can_see(mon))
136 mprf("%s's singing becomes strangely muted.",
137 mon->name(DESC_CAP_THE).c_str());
139 else
140 mpr("Something's singing becomes strangely muted.");
142 return;
145 if (you.can_see(mon))
147 if (silenced(you.pos()) || silenced(mon->pos()))
149 mprf("You can no longer hear %s's singing!",
150 mon->name(DESC_NOCAP_THE).c_str());
151 return;
153 mprf("%s stops singing.", mon->name(DESC_CAP_THE).c_str());
154 return;
157 mpr("Something stops singing.");
160 // Update all beholders' status after changes.
161 void player::update_beholders()
163 if (!beheld())
164 return;
165 bool removed = false;
166 for (int i = beholders.size() - 1; i >= 0; i--)
168 const monster* mon = &menv[beholders[i]];
169 if (!_possible_beholder(mon))
171 beholders.erase(beholders.begin() + i);
172 removed = true;
173 _removed_beholder_msg(mon);
176 if (removed)
177 _removed_beholder();
180 // Update a single beholder.
181 void player::update_beholder(const monster* mon)
183 if (_possible_beholder(mon))
184 return;
185 for (unsigned int i = 0; i < beholders.size(); i++)
186 if (beholders[i] == mon->mindex())
188 beholders.erase(beholders.begin() + i);
189 _removed_beholder_msg(mon);
190 _removed_beholder();
191 return;
195 // Helper function that resets the duration and messages if the player
196 // is no longer mesmerised.
197 void player::_removed_beholder()
199 if (beholders.empty())
201 duration[DUR_MESMERISED] = 0;
202 mpr(coinflip() ? "You break out of your daze!"
203 : "You are no longer entranced.",
204 MSGCH_DURATION);
208 // Helper function that checks whether the given monster is a possible
209 // beholder.
210 bool player::_possible_beholder(const monster* mon) const
212 if (crawl_state.game_is_arena())
213 return (false);
215 return (mon->alive() && mons_genus(mon->type) == MONS_MERMAID
216 && !silenced(pos()) && !silenced(mon->pos())
217 && !mon->has_ench(ENCH_MUTE)
218 && see_cell(mon->pos()) && mon->see_cell(pos())
219 && !mon->submerged() && !mon->confused()
220 && !mon->asleep() && !mon->cannot_move()
221 && !mon->wont_attack() && !mon->pacified()
222 && !mon->berserk() && !mons_is_fleeing(mon)
223 && !is_sanctuary(you.pos()));