diff options
author | Robert Vollmert <rvollmert@gmx.net> | 2009-11-05 20:50:54 +0100 |
---|---|---|
committer | Robert Vollmert <rvollmert@gmx.net> | 2009-11-05 22:30:03 +0100 |
commit | dc3f573c6ef467ddcc4a837ce90ca9df3b502c2e (patch) | |
tree | f7915736d0a9bad11d83c3ff8a0263577a27e979 /crawl-ref/source/behold.cc | |
parent | 31124ec682c2b826f169c23e808fa741a3033a04 (diff) | |
download | crawl-ref-dc3f573c6ef467ddcc4a837ce90ca9df3b502c2e.tar.gz crawl-ref-dc3f573c6ef467ddcc4a837ce90ca9df3b502c2e.zip |
Unify mesmerisation code.
There were several places that had copies of the same code, checking
whether mesmerisation blocked movement to a given target.
The various mesmerisation functions have become methods of player
and were moved into behold.cc.
Diffstat (limited to 'crawl-ref/source/behold.cc')
-rw-r--r-- | crawl-ref/source/behold.cc | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/crawl-ref/source/behold.cc b/crawl-ref/source/behold.cc new file mode 100644 index 0000000000..37571e1b0a --- /dev/null +++ b/crawl-ref/source/behold.cc @@ -0,0 +1,173 @@ +#include "AppHdr.h" + +#include "player.h" + +#include "coord.h" +#include "debug.h" +#include "env.h" +#include "los.h" +#include "mon-util.h" +#include "monster.h" +#include "random.h" +#include "stuff.h" +#include "view.h" + +// Add a monster to the list of beholders. +void player::add_beholder(const monsters* mon) +{ + if (!duration[DUR_MESMERISED]) + { + duration[DUR_MESMERISED] = 7; + beholders.push_back(mon->mindex()); + mprf(MSGCH_WARN, "You are mesmerised by %s!", + mon->name(DESC_NOCAP_THE).c_str()); + } + else + { + duration[DUR_MESMERISED] += 5; + if (!beheld_by(mon)) + beholders.push_back(mon->mindex()); + } + + if (duration[DUR_MESMERISED] > 12) + duration[DUR_MESMERISED] = 12; +} + +// Whether player is mesmerised. +bool player::beheld() const +{ + ASSERT(duration[DUR_MESMERISED] > 0 == !beholders.empty()); + return (duration[DUR_MESMERISED] > 0); +} + +// Whether player is mesmerised by the given monster. +bool player::beheld_by(const monsters* mon) const +{ + for (unsigned int i = 0; i < beholders.size(); i++) + if (beholders[i] == mon->mindex()) + return (true); + return (false); +} + +// Checks whether a beholder keeps you from moving to +// target, and returns one if it exists. +monsters* player::get_beholder(const coord_def &target) const +{ + for (unsigned int i = 0; i < beholders.size(); i++) + { + monsters *mon = &menv[beholders[i]]; + const int olddist = grid_distance(you.pos(), mon->pos()); + const int newdist = grid_distance(target, mon->pos()); + + if (olddist < newdist) + return (mon); + } + return (NULL); +} + +monsters* player::get_any_beholder() const +{ + if (beholders.size() > 0) + return (&menv[beholders[0]]); + else + return (NULL); +} + +// Removes a monster from the list of beholders if present. +void player::remove_beholder(const monsters *mon) +{ + for (unsigned int i = 0; i < beholders.size(); i++) + if (beholders[i] == mon->mindex()) + { + beholders.erase(beholders.begin() + i); + _removed_beholder(); + return; + } +} + +// Clear the list of beholders. Doesn't message. +void player::clear_beholders() +{ + beholders.clear(); + duration[DUR_MESMERISED] = 0; +} + +// Possibly end mesmerisation if a loud noise happened. +void player::beholders_check_noise(int loudness) +{ + if (loudness >= 20 && you.beheld()) + { + mprf("For a moment, you cannot hear the mermaid%s!", + beholders.size() > 1 ? "s" : ""); + clear_beholders(); + _removed_beholder(); + } +} + +// Update all beholders' status after changes. +void player::update_beholders() +{ + if (!beheld()) + return; + bool removed = false; + for (int i = beholders.size() - 1; i >= 0; i--) + { + const monsters* mon = &menv[beholders[i]]; + if (!_possible_beholder(mon)) + { + beholders.erase(beholders.begin() + i); + removed = true; + } + } + if (removed) + _removed_beholder(); +} + +// Update a single beholder. +void player::update_beholder(const monsters *mon) +{ + if (_possible_beholder(mon)) + return; + for (unsigned int i = 0; i < beholders.size(); i++) + if (beholders[i] = mon->mindex()) + { + beholders.erase(beholders.begin() + i); + _removed_beholder(); + return; + } +} + +// Helper function that resets the duration and messages if the player +// is no longer mesmerised. +void player::_removed_beholder() +{ + if (beholders.empty()) + { + duration[DUR_MESMERISED] = 0; + mpr(coinflip() ? "You break out of your daze!" + : "You are no longer entranced.", + MSGCH_DURATION); + } +} + +// Helper function that checks whether the given monster is a possible +// beholder. +bool player::_possible_beholder(const monsters *mon) const +{ + if (silenced(you.pos())) + return (false); + if (!mon->alive() || !mons_near(mon) || mons_friendly(mon) + || mon->submerged() || mon->confused() || mons_cannot_move(mon) + || mon->asleep() || silenced(mon->pos())) + { + return (false); + } + + // TODO: replace this by see/see_no_trans. + int walls = num_feats_between(you.pos(), mon->pos(), + DNGN_UNSEEN, DNGN_MAXOPAQUE); + if (walls > 0) + return (false); + + return (true); +} |