diff options
author | Johanna Ploog <j-p-e-g@users.sourceforge.net> | 2010-08-22 12:28:44 +0200 |
---|---|---|
committer | Johanna Ploog <j-p-e-g@users.sourceforge.net> | 2010-08-22 13:59:57 +0200 |
commit | 2d5f3c5367ec0d4dce1a0e9403ed50a58766e13d (patch) | |
tree | f75826a47445ced7b2ca9b2eb61189c8e1c05321 /crawl-ref/source/spl-monench.cc | |
parent | 2af507a7653a0a2da55c7a0e2ed75bcfe402e475 (diff) | |
download | crawl-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.cc | 221 |
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); +} |