summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/spl-monench.cc
diff options
context:
space:
mode:
authorJohanna Ploog <j-p-e-g@users.sourceforge.net>2010-08-22 12:28:44 +0200
committerJohanna Ploog <j-p-e-g@users.sourceforge.net>2010-08-22 13:59:57 +0200
commit2d5f3c5367ec0d4dce1a0e9403ed50a58766e13d (patch)
treef75826a47445ced7b2ca9b2eb61189c8e1c05321 /crawl-ref/source/spl-monench.cc
parent2af507a7653a0a2da55c7a0e2ed75bcfe402e475 (diff)
downloadcrawl-ref-2d5f3c5367ec0d4dce1a0e9403ed50a58766e13d.tar.gz
crawl-ref-2d5f3c5367ec0d4dce1a0e9403ed50a58766e13d.zip
Move non-self-enchantment spells into new file.
Merge spells2-4.cc into one file.
Diffstat (limited to 'crawl-ref/source/spl-monench.cc')
-rw-r--r--crawl-ref/source/spl-monench.cc221
1 files changed, 221 insertions, 0 deletions
diff --git a/crawl-ref/source/spl-monench.cc b/crawl-ref/source/spl-monench.cc
new file mode 100644
index 0000000000..707a9f15b9
--- /dev/null
+++ b/crawl-ref/source/spl-monench.cc
@@ -0,0 +1,221 @@
+/*
+ * File: spl-monench.cc
+ * Summary: Monster-affecting enchantment spells.
+ * Other targeted enchantments are handled in spl-zap.cc.
+ */
+
+#include "AppHdr.h"
+
+#include "spl-monench.h"
+#include "externs.h"
+
+#include "areas.h"
+#include "coord.h"
+#include "env.h"
+#include "message.h"
+#include "mon-place.h"
+#include "mon-stuff.h"
+#include "random.h"
+#include "shout.h"
+#include "spl-util.h"
+#include "stuff.h"
+#include "terrain.h"
+#include "viewmap.h"
+
+static int _sleep_monsters(coord_def where, int pow, int, actor *)
+{
+ monsters *monster = monster_at(where);
+ if (!monster)
+ return (0);
+
+ if (!monster->can_hibernate(true))
+ return (0);
+
+ if (monster->check_res_magic(pow))
+ return (0);
+
+ const int res = monster->res_cold();
+ if (res > 0 && one_chance_in(std::max(4 - res, 1)))
+ return (0);
+
+ if (monster->has_ench(ENCH_SLEEP_WARY) && !one_chance_in(3))
+ return (0);
+
+ monster->hibernate();
+ monster->expose_to_element(BEAM_COLD, 2);
+ return (1);
+}
+
+void cast_mass_sleep(int pow)
+{
+ apply_area_visible(_sleep_monsters, pow);
+}
+
+// This is a hack until we set an is_beast flag in the monster data
+// (which we might never do, this is sort of minor.)
+// It's a list of monster types which can be affected by beast taming.
+static bool _is_domesticated_animal(int type)
+{
+ const monster_type types[] = {
+ MONS_GIANT_BAT, MONS_HOUND, MONS_JACKAL, MONS_RAT,
+ MONS_YAK, MONS_WYVERN, MONS_HIPPOGRIFF, MONS_GRIFFON,
+ MONS_DEATH_YAK, MONS_WAR_DOG, MONS_GREY_RAT,
+ MONS_GREEN_RAT, MONS_ORANGE_RAT, MONS_SHEEP,
+ MONS_HOG, MONS_GIANT_FROG, MONS_GIANT_TOAD,
+ MONS_SPINY_FROG, MONS_BLINK_FROG, MONS_WOLF, MONS_WARG,
+ MONS_BEAR, MONS_GRIZZLY_BEAR, MONS_POLAR_BEAR, MONS_BLACK_BEAR
+ };
+
+ for (unsigned int i = 0; i < ARRAYSZ(types); ++i)
+ if (types[i] == type)
+ return (true);
+
+ return (false);
+}
+
+static int _tame_beast_monsters(coord_def where, int pow, int, actor *)
+{
+ monsters *monster = monster_at(where);
+ if (monster == NULL)
+ return 0;
+
+ if (!_is_domesticated_animal(monster->type) || monster->friendly()
+ || player_will_anger_monster(monster))
+ {
+ return 0;
+ }
+
+ // 50% bonus for dogs
+ if (monster->type == MONS_HOUND || monster->type == MONS_WAR_DOG )
+ pow += (pow / 2);
+
+ if (you.species == SP_HILL_ORC && monster->type == MONS_WARG)
+ pow += (pow / 2);
+
+ if (monster->check_res_magic(pow))
+ return 0;
+
+ simple_monster_message(monster, " is tamed!");
+
+ if (random2(100) < random2(pow / 10))
+ monster->attitude = ATT_FRIENDLY; // permanent
+ else
+ monster->add_ench(ENCH_CHARM); // temporary
+ mons_att_changed(monster);
+
+ return 1;
+}
+
+void cast_tame_beasts(int pow)
+{
+ apply_area_visible(_tame_beast_monsters, pow);
+}
+
+bool backlight_monsters(coord_def where, int pow, int garbage)
+{
+ UNUSED(pow);
+ UNUSED(garbage);
+
+ monsters *monster = monster_at(where);
+ if (monster == NULL)
+ return (false);
+
+ // Already glowing.
+ if (mons_class_flag(monster->type, M_GLOWS_LIGHT)
+ || mons_class_flag(monster->type, M_GLOWS_RADIATION))
+ {
+ return (false);
+ }
+
+ mon_enchant bklt = monster->get_ench(ENCH_CORONA);
+ const int lvl = bklt.degree;
+
+ // This enchantment overrides invisibility (neat).
+ if (monster->has_ench(ENCH_INVIS))
+ {
+ if (!monster->has_ench(ENCH_CORONA))
+ {
+ monster->add_ench(
+ mon_enchant(ENCH_CORONA, 1, KC_OTHER, random_range(30, 50)));
+ simple_monster_message(monster, " is lined in light.");
+ }
+ return (true);
+ }
+
+ monster->add_ench(mon_enchant(ENCH_CORONA, 1));
+
+ if (lvl == 0)
+ simple_monster_message(monster, " is outlined in light.");
+ else if (lvl == 4)
+ simple_monster_message(monster, " glows brighter for a moment.");
+ else
+ simple_monster_message(monster, " glows brighter.");
+
+ return (true);
+}
+
+bool do_slow_monster(monsters* mon, kill_category whose_kill)
+{
+ // Try to remove haste, if monster is hasted.
+ if (mon->del_ench(ENCH_HASTE, true))
+ {
+ if (simple_monster_message(mon, " is no longer moving quickly."))
+ return (true);
+ }
+
+ // Not hasted, slow it.
+ if (!mon->has_ench(ENCH_SLOW)
+ && !mons_is_stationary(mon)
+ && mon->add_ench(mon_enchant(ENCH_SLOW, 0, whose_kill)))
+ {
+ if (!mon->paralysed() && !mon->petrified()
+ && simple_monster_message(mon, " seems to slow down."))
+ {
+ return (true);
+ }
+ }
+
+ return (false);
+}
+
+bool project_noise()
+{
+ bool success = false;
+
+ coord_def pos(1, 0);
+ level_pos lpos;
+
+ mpr("Choose the noise's source (press '.' or delete to select).");
+ more();
+
+ // Might abort with SIG_HUP despite !allow_esc.
+ if (!show_map(lpos, false, false, false))
+ lpos = level_pos::current();
+ pos = lpos.pos;
+
+ redraw_screen();
+
+ dprf("Target square (%d,%d)", pos.x, pos.y);
+
+ if (!in_bounds(pos) || !silenced(pos))
+ {
+ if (in_bounds(pos) && !feat_is_solid(grd(pos)))
+ {
+ noisy(30, pos);
+ success = true;
+ }
+
+ if (!silenced(you.pos()))
+ {
+ if (success)
+ {
+ mprf(MSGCH_SOUND, "You hear a %svoice call your name.",
+ (!you.see_cell(pos) ? "distant " : ""));
+ }
+ else
+ mprf(MSGCH_SOUND, "You hear a dull thud.");
+ }
+ }
+
+ return (success);
+}