From 22c9c1dd3fe93c8ccab01eec647fb002877018f8 Mon Sep 17 00:00:00 2001 From: Darshan Shaligram Date: Tue, 29 Dec 2009 08:26:24 +0530 Subject: Merfolk (water/ice) elementalists join the Shoals guard. --- crawl-ref/source/spl-data.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'crawl-ref/source/spl-data.h') diff --git a/crawl-ref/source/spl-data.h b/crawl-ref/source/spl-data.h index 303306cc83..6a62b9ed09 100644 --- a/crawl-ref/source/spl-data.h +++ b/crawl-ref/source/spl-data.h @@ -2641,6 +2641,20 @@ false }, +{ + SPELL_PRIMAL_WAVE, "Primal Wave", + SPTYP_CONJURATION | SPTYP_ICE, + SPFLAG_DIR_OR_TARGET, + 6, + 200, + 7, 7, + 0, + NULL, + true, + false +}, + + { SPELL_NO_SPELL, "nonexistent spell", 0, -- cgit v1.2.3-54-g00ecf From 9cc1ba155f353a235d38e785c1eefc984f4d42c1 Mon Sep 17 00:00:00 2001 From: Darshan Shaligram Date: Tue, 29 Dec 2009 19:48:21 +0530 Subject: Boost Ilsuiw stats and give her Call Tide, which strongly boosts the tide in Shoals, pegs it towards high tide, and includes a local high tide maximum centered on Ilsuiw, which can be double the height of the normal high tide. --- crawl-ref/source/dgn-shoals.cc | 108 +++++++++++++++++++++++++++++++++++------ crawl-ref/source/dgn-shoals.h | 3 +- crawl-ref/source/enum.h | 2 + crawl-ref/source/main.cc | 2 +- crawl-ref/source/mon-abil.cc | 12 +---- crawl-ref/source/mon-cast.cc | 13 +++++ crawl-ref/source/mon-data.h | 2 +- crawl-ref/source/mon-gear.cc | 12 +++++ crawl-ref/source/mon-spll.h | 5 +- crawl-ref/source/mon-stuff.cc | 3 ++ crawl-ref/source/mon-util.cc | 7 +++ crawl-ref/source/monster.cc | 7 ++- crawl-ref/source/monster.h | 1 + crawl-ref/source/spl-data.h | 12 +++++ crawl-ref/source/view.cc | 13 +++++ crawl-ref/source/view.h | 1 + 16 files changed, 169 insertions(+), 34 deletions(-) (limited to 'crawl-ref/source/spl-data.h') diff --git a/crawl-ref/source/dgn-shoals.cc b/crawl-ref/source/dgn-shoals.cc index b88873d5b5..b91dc3a195 100644 --- a/crawl-ref/source/dgn-shoals.cc +++ b/crawl-ref/source/dgn-shoals.cc @@ -1,6 +1,7 @@ #include "AppHdr.h" #include "branch.h" +#include "colour.h" #include "coord.h" #include "coordit.h" #include "dungeon.h" @@ -10,10 +11,12 @@ #include "items.h" #include "maps.h" #include "mgen_data.h" +#include "mon-iter.h" #include "mon-place.h" #include "mon-util.h" #include "random.h" #include "terrain.h" +#include "view.h" #include #include @@ -42,6 +45,23 @@ const int N_PERTURB_OFFSET_HIGH = 45; const int PERTURB_OFFSET_RADIUS_LOW = 2; const int PERTURB_OFFSET_RADIUS_HIGH = 7; +// The raw tide height / TIDE_MULTIPLIER is the actual tide height. The higher +// the tide multiplier, the slower the tide advances and recedes. A multiplier +// of X implies that the tide will advance visibly about once in X turns. +const int TIDE_MULTIPLIER = 30; + +const int LOW_TIDE = -18 * TIDE_MULTIPLIER; +const int HIGH_TIDE = 25 * TIDE_MULTIPLIER; + +// The highest a tide can be called by a tide caller such as Ilsuiw. +const int HIGH_CALLED_TIDE = 25; +const int TIDE_DECEL_MARGIN = 8; +const int PEAK_TIDE_ACCEL = 2; + +// The area around the user of a call tide spell that is subject to +// local tide elevation. +const int TIDE_CALL_RADIUS = 8; + const int _shoals_margin = 6; enum shoals_height_thresholds @@ -60,6 +80,10 @@ enum tide_direction }; static tide_direction _shoals_tide_direction; +static monsters *tide_caller = NULL; +static coord_def tide_caller_pos; +static long tide_called_turns = 0L; +static int tide_called_peak = 0; static dungeon_feature_type _shoals_feature_by_height(int height) { @@ -816,18 +840,16 @@ void shoals_postprocess_level() } } -// The raw tide height / TIDE_MULTIPLIER is the actual tide height. The higher -// the tide multiplier, the slower the tide advances and recedes. A multiplier -// of X implies that the tide will advance visibly about once in X turns. -const int TIDE_MULTIPLIER = 30; - -const int LOW_TIDE = -18 * TIDE_MULTIPLIER; -const int HIGH_TIDE = 25 * TIDE_MULTIPLIER; -const int TIDE_DECEL_MARGIN = 8; -const int START_TIDE_RISE = 2; - static void _shoals_run_tide(int &tide, int &acc) { + // If someone is calling the tide, the acceleration is clamped high. + if (tide_caller) + acc = 15; + // If there's no tide caller and our acceleration is suspiciously high, + // reset it to a falling tide at peak acceleration. + else if (abs(acc) > PEAK_TIDE_ACCEL) + acc = -PEAK_TIDE_ACCEL; + tide += acc; tide = std::max(std::min(tide, HIGH_TIDE), LOW_TIDE); if ((tide == HIGH_TIDE && acc > 0) @@ -836,7 +858,7 @@ static void _shoals_run_tide(int &tide, int &acc) bool in_decel_margin = (abs(tide - HIGH_TIDE) < TIDE_DECEL_MARGIN) || (abs(tide - LOW_TIDE) < TIDE_DECEL_MARGIN); - if ((abs(acc) == 2) == in_decel_margin) + if ((abs(acc) > 1) == in_decel_margin) acc = in_decel_margin? acc / 2 : acc * 2; } @@ -956,6 +978,23 @@ static void _shoals_apply_tide_at(coord_def c, int tide) _shoals_apply_tide_feature_at(c, newfeat); } +static int _shoals_tide_at(coord_def pos, int base_tide) +{ + if (!tide_caller) + return base_tide; + + const int rl_distance = grid_distance(pos, tide_caller_pos); + if (rl_distance > TIDE_CALL_RADIUS) + return base_tide; + + const int distance = + static_cast(sqrt((pos - tide_caller->pos()).abs())); + if (distance > TIDE_CALL_RADIUS) + return base_tide; + + return (base_tide + std::max(0, tide_called_peak - distance * 3)); +} + static void _shoals_apply_tide(int tide) { std::vector pages[2]; @@ -980,7 +1019,7 @@ static void _shoals_apply_tide(int tide) coord_def c(cpage[i]); const bool was_wet(_shoals_tide_passable_feat(grd(c))); seen_points(c) = true; - _shoals_apply_tide_at(c, tide); + _shoals_apply_tide_at(c, _shoals_tide_at(c, tide)); const bool is_wet(feat_is_water(grd(c))); // Only squares that were wet (before applying tide @@ -1017,13 +1056,22 @@ static void _shoals_init_tide() if (!env.properties.exists(ENVP_SHOALS_TIDE_KEY)) { env.properties[ENVP_SHOALS_TIDE_KEY] = short(0); - env.properties[ENVP_SHOALS_TIDE_VEL] = short(2); + env.properties[ENVP_SHOALS_TIDE_VEL] = short(PEAK_TIDE_ACCEL); } } -void shoals_apply_tides(int turns_elapsed) +static monsters *_shoals_find_tide_caller() +{ + for (monster_iterator mi; mi; ++mi) + if (mi->has_ench(ENCH_TIDE)) + return *mi; + return NULL; +} + +void shoals_apply_tides(int turns_elapsed, bool force) { - if (!player_in_branch(BRANCH_SHOALS) || !turns_elapsed + if (!player_in_branch(BRANCH_SHOALS) + || (!turns_elapsed && !force) || !env.heightmap.get()) { return; @@ -1035,6 +1083,20 @@ void shoals_apply_tides(int turns_elapsed) turns_elapsed = turns_elapsed % TIDE_UNIT + TIDE_UNIT; _shoals_init_tide(); + + unwind_var tide_caller_unwind(tide_caller, + _shoals_find_tide_caller()); + if (tide_caller) + { + tide_called_turns = tide_caller->props[TIDE_CALL_TURN].get_long(); + tide_called_turns = you.num_turns - tide_called_turns; + if (tide_called_turns < 1L) + tide_called_turns = 1L; + tide_called_peak = std::min(HIGH_CALLED_TIDE, + int(tide_called_turns * 5)); + tide_caller_pos = tide_caller->pos(); + } + int tide = env.properties[ENVP_SHOALS_TIDE_KEY].get_short(); int acc = env.properties[ENVP_SHOALS_TIDE_VEL].get_short(); const int old_tide = tide; @@ -1042,10 +1104,24 @@ void shoals_apply_tides(int turns_elapsed) _shoals_run_tide(tide, acc); env.properties[ENVP_SHOALS_TIDE_KEY] = short(tide); env.properties[ENVP_SHOALS_TIDE_VEL] = short(acc); - if (old_tide / TIDE_MULTIPLIER != tide / TIDE_MULTIPLIER) + if (force + || tide_caller + || old_tide / TIDE_MULTIPLIER != tide / TIDE_MULTIPLIER) { _shoals_tide_direction = tide > old_tide ? TIDE_RISING : TIDE_FALLING; _shoals_apply_tide(tide / TIDE_MULTIPLIER); } } + +void shoals_release_tide(monsters *mons) +{ + if (player_in_branch(BRANCH_SHOALS) + && player_can_hear(you.pos())) + { + mprf(MSGCH_SOUND, "The tide is released from %s call.", + mons->name(DESC_NOCAP_YOUR, true).c_str()); + flash_view_delay(ETC_WATER, 150); + shoals_apply_tides(0, true); + } +} diff --git a/crawl-ref/source/dgn-shoals.h b/crawl-ref/source/dgn-shoals.h index f558f6606f..1d14c620f2 100644 --- a/crawl-ref/source/dgn-shoals.h +++ b/crawl-ref/source/dgn-shoals.h @@ -3,6 +3,7 @@ void prepare_shoals(int level_number); void shoals_postprocess_level(); -void shoals_apply_tides(int turns_elapsed); +void shoals_apply_tides(int turns_elapsed, bool force = false); +void shoals_release_tide(monsters *caller); #endif diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h index 08ae63c36e..f770323cfc 100644 --- a/crawl-ref/source/enum.h +++ b/crawl-ref/source/enum.h @@ -1254,6 +1254,7 @@ enum enchant_type ENCH_SPORE_PRODUCTION, // 35 ENCH_SLOUCH, ENCH_SWIFT, + ENCH_TIDE, // Update enchantment names in mon-util.cc when adding or removing // enchantments. @@ -2930,6 +2931,7 @@ enum spell_type SPELL_SUMMON_RAKSHASA, SPELL_SUMMON_PLAYER_GHOST, SPELL_PRIMAL_WAVE, + SPELL_CALL_TIDE, NUM_SPELLS }; diff --git a/crawl-ref/source/main.cc b/crawl-ref/source/main.cc index 7f3ccb2592..1ad6e1af6c 100644 --- a/crawl-ref/source/main.cc +++ b/crawl-ref/source/main.cc @@ -4631,7 +4631,7 @@ static void _compile_time_asserts() COMPILE_CHECK(SP_VAMPIRE == 30 , c3); COMPILE_CHECK(SPELL_DEBUGGING_RAY == 103 , c4); COMPILE_CHECK(SPELL_RETURNING_AMMUNITION == 162 , c5); - COMPILE_CHECK(NUM_SPELLS == 216 , c6); + COMPILE_CHECK(NUM_SPELLS == 217 , c6); //jmf: NEW ASSERTS: we ought to do a *lot* of these COMPILE_CHECK(NUM_SPECIES < SP_UNKNOWN , c7); diff --git a/crawl-ref/source/mon-abil.cc b/crawl-ref/source/mon-abil.cc index 5325d3f27b..781778d6d3 100644 --- a/crawl-ref/source/mon-abil.cc +++ b/crawl-ref/source/mon-abil.cc @@ -303,17 +303,7 @@ static bool _do_merge(monsters *initial_slime, monsters *merge_to) merge_to->name(DESC_NOCAP_A).c_str()); } - flash_view(LIGHTGREEN); - - int flash_delay = 150; - // Scale delay to match change in arena_delay. - if (crawl_state.arena) - { - flash_delay *= Options.arena_delay; - flash_delay /= 600; - } - - delay(flash_delay); + flash_view_delay(LIGHTGREEN, 150); } else if (you.can_see(initial_slime)) mpr("A slime creature suddenly disappears!"); diff --git a/crawl-ref/source/mon-cast.cc b/crawl-ref/source/mon-cast.cc index 42b7b52da5..5190625c61 100644 --- a/crawl-ref/source/mon-cast.cc +++ b/crawl-ref/source/mon-cast.cc @@ -839,6 +839,7 @@ bool setup_mons_cast(monsters *monster, bolt &pbolt, spell_type spell_cast, case SPELL_SUMMON_EYEBALLS: case SPELL_SUMMON_BUTTERFLIES: case SPELL_MISLEAD: + case SPELL_CALL_TIDE: return (true); default: if (check_validity) @@ -1678,6 +1679,18 @@ void mons_cast(monsters *monster, bolt &pbolt, spell_type spell_cast, simple_monster_message(monster, " seems to move somewhat quicker."); return; + case SPELL_CALL_TIDE: + { + const int tide_duration = random_range(18, 50, 2); + monster->add_ench(mon_enchant(ENCH_TIDE, 0, KC_OTHER, + tide_duration * 10)); + monster->props[TIDE_CALL_TURN] = you.num_turns; + simple_monster_message(monster, + " sings a water chant to call the tide!"); + flash_view_delay(ETC_WATER, 300); + return; + } + case SPELL_SUMMON_SMALL_MAMMALS: case SPELL_VAMPIRE_SUMMON: if (spell_cast == SPELL_SUMMON_SMALL_MAMMALS) diff --git a/crawl-ref/source/mon-data.h b/crawl-ref/source/mon-data.h index e5e5fb7b98..6ce2103a22 100644 --- a/crawl-ref/source/mon-data.h +++ b/crawl-ref/source/mon-data.h @@ -4626,7 +4626,7 @@ static monsterentry mondata[] = { MR_RES_POISON | MR_RES_COLD, 500, 10, MONS_MERFOLK, MONS_MERFOLK, MH_NATURAL, -7, { {AT_HIT, AF_PLAIN, 10}, AT_NO_ATK, AT_NO_ATK, AT_NO_ATK }, - { 9, 0, 0, 54 }, + { 16, 0, 0, 150 }, 5, 18, MST_ILSUIW, CE_CONTAMINATED, Z_NOZOMBIE, S_SHOUT, I_NORMAL, HT_AMPHIBIOUS_WATER, FL_NONE, 10, DEFAULT_ENERGY, MONUSE_WEAPONS_ARMOUR, MONEAT_NOTHING, SIZE_MEDIUM diff --git a/crawl-ref/source/mon-gear.cc b/crawl-ref/source/mon-gear.cc index 393d4680b7..8affc9587f 100644 --- a/crawl-ref/source/mon-gear.cc +++ b/crawl-ref/source/mon-gear.cc @@ -12,6 +12,7 @@ #include "mon-gear.h" #include "artefact.h" +#include "colour.h" #include "dungeon.h" #include "env.h" #include "itemprop.h" @@ -582,6 +583,17 @@ static item_make_species_type _give_weapon(monsters *mon, int level, } break; + case MONS_ILSUIW: + item_race = MAKE_ITEM_NO_RACE; + item.base_type = OBJ_WEAPONS; + item.sub_type = WPN_TRIDENT; + item.special = SPWPN_FREEZING; + item.plus = random_range(-1, 6, 2); + item.plus2 = random_range(-1, 6, 2); + item.colour = ETC_ICE; + force_item = true; + break; + case MONS_MERFOLK_IMPALER: item_race = MAKE_ITEM_NO_RACE; item.base_type = OBJ_WEAPONS; diff --git a/crawl-ref/source/mon-spll.h b/crawl-ref/source/mon-spll.h index 2137cbbacb..344ae8e6b8 100644 --- a/crawl-ref/source/mon-spll.h +++ b/crawl-ref/source/mon-spll.h @@ -1043,8 +1043,8 @@ { MST_ILSUIW, { - SPELL_THROW_FROST, // was: SPELL_CONFUSED (jpeg) - SPELL_SLOW, + SPELL_THROW_ICICLE, + SPELL_CALL_TIDE, SPELL_INVISIBILITY, SPELL_BLINK, SPELL_WATER_ELEMENTALS, @@ -1323,7 +1323,6 @@ { SPELL_PRIMAL_WAVE, SPELL_BOLT_OF_COLD, - // Ice form would be neat. SPELL_THROW_ICICLE, SPELL_NO_SPELL, SPELL_NO_SPELL, diff --git a/crawl-ref/source/mon-stuff.cc b/crawl-ref/source/mon-stuff.cc index 3db902c13b..ca7b9cf12c 100644 --- a/crawl-ref/source/mon-stuff.cc +++ b/crawl-ref/source/mon-stuff.cc @@ -1422,6 +1422,9 @@ int monster_die(monsters *monster, killer_type killer, return (-1); } + // If the monster was calling the tide, let go now. + monster->del_ench(ENCH_TIDE); + crawl_state.inc_mon_acting(monster); ASSERT(!( YOU_KILL(killer) && crawl_state.arena )); diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc index 3687e1711c..5895a0c542 100644 --- a/crawl-ref/source/mon-util.cc +++ b/crawl-ref/source/mon-util.cc @@ -2390,6 +2390,13 @@ bool ms_waste_of_time( const monsters *mon, spell_type monspell ) // handled here as well. - bwr switch (monspell) { + case SPELL_CALL_TIDE: + return (!player_in_branch(BRANCH_SHOALS) + || mon->has_ench(ENCH_TIDE) + || !foe + || (grd(mon->pos()) == DNGN_DEEP_WATER + && grd(foe->pos()) == DNGN_DEEP_WATER)); + case SPELL_BRAIN_FEED: ret = (foe != &you); break; diff --git a/crawl-ref/source/monster.cc b/crawl-ref/source/monster.cc index f6003c3b81..2f83c01d6f 100644 --- a/crawl-ref/source/monster.cc +++ b/crawl-ref/source/monster.cc @@ -12,6 +12,7 @@ #include "coordit.h" #include "delay.h" #include "dgnevent.h" +#include "dgn-shoals.h" #include "directn.h" #include "env.h" #include "fight.h" @@ -4305,6 +4306,10 @@ void monsters::remove_enchantment_effect(const mon_enchant &me, bool quiet) { switch (me.ench) { + case ENCH_TIDE: + shoals_release_tide(this); + break; + case ENCH_BERSERK: scale_hp(2, 3); break; @@ -6031,7 +6036,7 @@ static const char *enchant_names[] = "short-lived", "paralysis", "sick", "sleep", "fatigue", "held", "blood-lust", "neutral", "petrifying", "petrified", "magic-vulnerable", "soul-ripe", "decay", "hungry", "flopping", "spore-producing", - "downtrodden", "swift", "bug" + "downtrodden", "swift", "tide", "bug" }; static const char *_mons_enchantment_name(enchant_type ench) diff --git a/crawl-ref/source/monster.h b/crawl-ref/source/monster.h index 16ec367332..b93ed65571 100644 --- a/crawl-ref/source/monster.h +++ b/crawl-ref/source/monster.h @@ -4,6 +4,7 @@ #include "actor.h" const int KRAKEN_TENTACLE_RANGE = 3; +#define TIDE_CALL_TURN "tide-call-turn" class mon_enchant { diff --git a/crawl-ref/source/spl-data.h b/crawl-ref/source/spl-data.h index 6a62b9ed09..db5979a031 100644 --- a/crawl-ref/source/spl-data.h +++ b/crawl-ref/source/spl-data.h @@ -2654,6 +2654,18 @@ false }, +{ + SPELL_CALL_TIDE, "Call Tide", + SPTYP_TRANSLOCATION, + SPFLAG_MONSTER, + 7, + 0, + -1, -1, + 0, + NULL, + false, + false +}, { SPELL_NO_SPELL, "nonexistent spell", diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc index b8e6447a89..94ad2a572c 100644 --- a/crawl-ref/source/view.cc +++ b/crawl-ref/source/view.cc @@ -635,6 +635,19 @@ void flash_view(int colour) viewwindow(false, false); } +void flash_view_delay(int colour, long flash_delay) +{ + flash_view(colour); + // Scale delay to match change in arena_delay. + if (crawl_state.arena) + { + flash_delay *= Options.arena_delay; + flash_delay /= 600; + } + + delay(flash_delay); +} + static void _debug_pane_bounds() { #if DEBUG_PANE_BOUNDS diff --git a/crawl-ref/source/view.h b/crawl-ref/source/view.h index 7a618c182b..70029c000d 100644 --- a/crawl-ref/source/view.h +++ b/crawl-ref/source/view.h @@ -37,6 +37,7 @@ std::string screenshot(bool fullscreen = false); bool view_update(); void view_update_at(const coord_def &pos); void flash_view(int colour = BLACK); // inside #ifndef USE_TILE? +void flash_view_delay(int colour = BLACK, long delay = 150); #ifndef USE_TILE void flash_monster_colour(const monsters *mon, unsigned char fmc_colour, int fmc_delay); -- cgit v1.2.3-54-g00ecf