summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/fearmonger.cc
diff options
context:
space:
mode:
authorJude Brown <bookofjude@users.sourceforge.net>2010-09-22 23:06:38 +1000
committerJude Brown <bookofjude@users.sourceforge.net>2010-09-22 23:09:27 +1000
commit5fb424c0036042534a7433d5ccbbec737a706adb (patch)
tree6b1ee399674f68eec6ef1dcceab7bf43a83e2fa1 /crawl-ref/source/fearmonger.cc
parentc0f0a2dc7f95fe35614df8b8a134fa13835a69fa (diff)
downloadcrawl-ref-5fb424c0036042534a7433d5ccbbec737a706adb.tar.gz
crawl-ref-5fb424c0036042534a7433d5ccbbec737a706adb.zip
Implement fear as a monster spell, player status.
The opposite of mesmerisation: instead of not being able to move away from the creature in question, you are unable to move closer to them. This is useful for ranged fighters, but useless with monsters that will move closer to you. One merely needs to hold . until they arrive, or hit them with spells, etc. The range could be tweaked slightly. I've set it up as olddist >= newdist, which means that you get the following effect (where 5 is a monster causing fear, : are squares you cannot move into, . as normal): :::::::.. :::::::.. :::5::@.. :::::::.. :::::::.. Switching to olddist > newdist results in: ::::::... ::::::... :::5::@.. ::::::... ::::::... Square LOS may also make a difference in this case. No monster currently uses it, but giving them the spell "cause fear" works as imagined.
Diffstat (limited to 'crawl-ref/source/fearmonger.cc')
-rw-r--r--crawl-ref/source/fearmonger.cc190
1 files changed, 190 insertions, 0 deletions
diff --git a/crawl-ref/source/fearmonger.cc b/crawl-ref/source/fearmonger.cc
new file mode 100644
index 0000000000..6c33080ede
--- /dev/null
+++ b/crawl-ref/source/fearmonger.cc
@@ -0,0 +1,190 @@
+/*
+ * File: fearmonger.cc
+ * Summary: player methods dealing with mesmerisation.
+ */
+
+#include "AppHdr.h"
+
+#include "player.h"
+
+#include "coord.h"
+#include "debug.h"
+#include "env.h"
+#include "fprop.h"
+#include "mon-util.h"
+#include "monster.h"
+#include "random.h"
+#include "state.h"
+#include "stuff.h"
+#include "areas.h"
+
+// Add a monster to the list of fearmongers.
+void player::add_fearmonger(const monster* mon)
+{
+ if (is_sanctuary(you.pos()))
+ {
+ if (you.can_see(mon))
+ {
+ mprf("%s's aura of fear is muted, and has no effect on you.",
+ mon->name(DESC_CAP_THE).c_str());
+ }
+ else
+ {
+ mpr("The fearful aura is strangely muted, and has no effect on you.");
+ }
+ return;
+ }
+
+ if (!duration[DUR_AFRAID])
+ {
+ you.set_duration(DUR_AFRAID, 7, 12);
+ fearmongers.push_back(mon->mindex());
+ mprf(MSGCH_WARN, "You are terrified of %s!",
+ mon->name(DESC_NOCAP_THE).c_str());
+ }
+ else
+ {
+ you.increase_duration(DUR_AFRAID, 5, 12);
+ if (!afraid_of(mon))
+ fearmongers.push_back(mon->mindex());
+ }
+}
+
+// Whether player is mesmerised.
+bool player::afraid() const
+{
+ ASSERT(duration[DUR_AFRAID] > 0 == !fearmongers.empty());
+ return (duration[DUR_AFRAID] > 0);
+}
+
+// Whether player is mesmerised by the given monster.
+bool player::afraid_of(const monster* mon) const
+{
+ for (unsigned int i = 0; i < fearmongers.size(); i++)
+ if (fearmongers[i] == mon->mindex())
+ return (true);
+ return (false);
+}
+
+// Checks whether a fearmonger keeps you from moving to
+// target, and returns one if it exists.
+monster* player::get_fearmonger(const coord_def &target) const
+{
+ for (unsigned int i = 0; i < fearmongers.size(); i++)
+ {
+ monster* mon = &menv[fearmongers[i]];
+ const int olddist = grid_distance(pos(), mon->pos());
+ const int newdist = grid_distance(target, mon->pos());
+
+ if (olddist >= newdist)
+ return (mon);
+ }
+ return (NULL);
+}
+
+monster* player::get_any_fearmonger() const
+{
+ if (fearmongers.size() > 0)
+ return (&menv[fearmongers[0]]);
+ else
+ return (NULL);
+}
+
+// Removes a monster from the list of fearmongers if present.
+void player::remove_fearmonger(const monster* mon)
+{
+ for (unsigned int i = 0; i < fearmongers.size(); i++)
+ if (fearmongers[i] == mon->mindex())
+ {
+ fearmongers.erase(fearmongers.begin() + i);
+ _removed_fearmonger();
+ return;
+ }
+}
+
+// Clear the list of fearmongers. Doesn't message.
+void player::clear_fearmongers()
+{
+ fearmongers.clear();
+ duration[DUR_AFRAID] = 0;
+}
+
+// Possibly end mesmerisation if a loud noise happened.
+void player::fearmongers_check_noise(int loudness)
+{
+ if (loudness >= 20 && beheld())
+ {
+ mprf("For a moment, your terror fades away!");
+ clear_fearmongers();
+ _removed_fearmonger();
+ }
+}
+
+static void _removed_fearmonger_msg(const monster* mon)
+{
+ return;
+}
+
+// Update all fearmongers' status after changes.
+void player::update_fearmongers()
+{
+ if (!afraid())
+ return;
+ bool removed = false;
+ for (int i = fearmongers.size() - 1; i >= 0; i--)
+ {
+ const monster* mon = &menv[fearmongers[i]];
+ if (!_possible_fearmonger(mon))
+ {
+ fearmongers.erase(fearmongers.begin() + i);
+ removed = true;
+ _removed_fearmonger_msg(mon);
+ }
+ }
+ if (removed)
+ _removed_fearmonger();
+}
+
+// Update a single fearmonger.
+void player::update_fearmonger(const monster* mon)
+{
+ if (_possible_fearmonger(mon))
+ return;
+ for (unsigned int i = 0; i < fearmongers.size(); i++)
+ if (fearmongers[i] == mon->mindex())
+ {
+ fearmongers.erase(fearmongers.begin() + i);
+ _removed_fearmonger_msg(mon);
+ _removed_fearmonger();
+ return;
+ }
+}
+
+// Helper function that resets the duration and messages if the player
+// is no longer mesmerised.
+void player::_removed_fearmonger()
+{
+ if (fearmongers.empty())
+ {
+ duration[DUR_AFRAID] = 0;
+ mpr("You are no longer terrified.",
+ MSGCH_DURATION);
+ }
+}
+
+// Helper function that checks whether the given monster is a possible
+// fearmonger.
+bool player::_possible_fearmonger(const monster* mon) const
+{
+ if (crawl_state.game_is_arena())
+ return (false);
+
+ return (mon->alive()
+ && !silenced(pos()) && !silenced(mon->pos())
+ && see_cell(mon->pos()) && mon->see_cell(pos())
+ && !mon->submerged() && !mon->confused()
+ && !mon->asleep() && !mon->cannot_move()
+ && !mon->wont_attack() && !mon->pacified()
+ && !mon->berserk() && !mons_is_fleeing(mon)
+ && !is_sanctuary(you.pos()));
+}