From 9cc9c1350516b56581c8bf86aafa695677d819f9 Mon Sep 17 00:00:00 2001 From: David Lawrence Ramsey Date: Mon, 12 Oct 2009 20:14:49 -0500 Subject: Apply n78291's patch in [2877049], with a few tweaks, to expand Jiyva's wrath, allow uncancelable transformations as part of it, and adjust his Slimify power. --- crawl-ref/source/abl-show.cc | 35 ++++++++++------- crawl-ref/source/acr.cc | 2 + crawl-ref/source/beam.cc | 61 ----------------------------- crawl-ref/source/enum.h | 2 +- crawl-ref/source/externs.h | 1 + crawl-ref/source/fight.cc | 11 ++++++ crawl-ref/source/monstuff.cc | 55 ++++++++++++++++++++++++-- crawl-ref/source/monstuff.h | 4 ++ crawl-ref/source/output.cc | 9 +++++ crawl-ref/source/player.cc | 1 + crawl-ref/source/religion.cc | 92 +++++++++++++++++++++++++++++++++++++------- crawl-ref/source/tags.cc | 4 ++ crawl-ref/source/tags.h | 3 +- crawl-ref/source/transfor.cc | 10 +++++ 14 files changed, 197 insertions(+), 93 deletions(-) diff --git a/crawl-ref/source/abl-show.cc b/crawl-ref/source/abl-show.cc index 005e83db52..be34c67611 100644 --- a/crawl-ref/source/abl-show.cc +++ b/crawl-ref/source/abl-show.cc @@ -322,7 +322,7 @@ static const ability_def Ability_List[] = // Jiyva { ABIL_JIYVA_CALL_JELLY, "Request Jelly", 2, 0, 20, 1, ABFLAG_NONE }, { ABIL_JIYVA_JELLY_SHIELD, "Jelly Shield", 0, 0, 0, 0, ABFLAG_PIETY }, - { ABIL_JIYVA_SLIMIFY, "Slimify", 4, 0, 100, 3, ABFLAG_NONE }, + { ABIL_JIYVA_SLIMIFY, "Slimify", 4, 0, 100, 8, ABFLAG_NONE }, { ABIL_JIYVA_CURE_BAD_MUTATION, "Cure Bad Mutation", 8, 0, 200, 15, ABFLAG_NONE }, @@ -2042,22 +2042,27 @@ static bool _do_ability(const ability_def& abil) break; case ABIL_JIYVA_SLIMIFY: - beam.range = LOS_RADIUS; - if (!spell_direction(spd, beam)) - return (false); + { + std::string msg; + int has_weapon = you.equip[EQ_WEAPON]; - if (beam.target == you.pos()) - { - mpr("You cannot slimify yourself!"); - return (false); - } - if (!zapping(ZAP_SLIME, 16 + you.skills[SK_INVOCATIONS] * 8, beam, - true)) + if (has_weapon == -1) + msg = "your " + you.hand_name(true); + else { - return (false); + item_def& weapon = *you.weapon(); + msg = weapon.name(DESC_NOCAP_YOUR); } + + mprf(MSGCH_DURATION, "A thick mucus forms on %s.", msg.c_str()); + you.duration[DUR_SLIMIFY] += you.skills[SK_INVOCATIONS] * 3 / 2 + 3; + + if (you.duration[DUR_SLIMIFY] > 100) + you.duration[DUR_SLIMIFY] = 100; + exercise(SK_INVOCATIONS, 3 + random2(5)); break; + } case ABIL_JIYVA_CURE_BAD_MUTATION: if (jiyva_remove_bad_mutation()) @@ -2349,8 +2354,12 @@ std::vector your_talents(bool check_confused) if (player_mutation_level(MUT_SMITE)) _add_talent(talents, ABIL_BOLT_OF_DRAINING, check_confused); - if (you.duration[DUR_TRANSFORMATION] && you.attribute[ATTR_TRANSFORMATION]!=TRAN_PIG) + if (you.duration[DUR_TRANSFORMATION] + && you.attribute[ATTR_TRANSFORMATION] != TRAN_PIG + && you.transform_cancellable) + { _add_talent(talents, ABIL_END_TRANSFORMATION, check_confused); + } if (player_mutation_level(MUT_BLINK)) _add_talent(talents, ABIL_BLINK, check_confused); diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc index 988da0c579..b20c9794f1 100644 --- a/crawl-ref/source/acr.cc +++ b/crawl-ref/source/acr.cc @@ -2273,6 +2273,8 @@ static void _decrement_durations() _decrement_a_duration(DUR_BARGAIN, "You feel less charismatic."); _decrement_a_duration(DUR_CONF, "You feel less confused."); _decrement_a_duration(DUR_LOWERED_MR, "You feel more resistant to magic."); + _decrement_a_duration(DUR_SLIMIFY, "You feel less slimy.", + coinflip(), "Your slime is starting to congeal."); if (you.duration[DUR_PARALYSIS] || you.duration[DUR_PETRIFIED]) { diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc index 50cf568e9a..ae882b0c9e 100644 --- a/crawl-ref/source/beam.cc +++ b/crawl-ref/source/beam.cc @@ -1267,21 +1267,6 @@ const zap_info zap_data[] = { false }, - { - ZAP_SLIME, - "0", - 100, - NULL, - NULL, - GREEN, - true, - BEAM_SLIME, - DCHAR_SPACE, - false, - false, - false - }, - { ZAP_PORKALATOR, "porkalator", @@ -4889,11 +4874,6 @@ bool _ench_flavour_affects_monster(beam_type flavour, const monsters* mon) || (mons_holiness(mon) == MH_NATURAL && mon->type != MONS_HOG); break; - case BEAM_SLIME: - rc = (mons_holiness(mon) == MH_NATURAL - || mons_holiness(mon) == MH_UNDEAD); - break; - default: break; } @@ -5074,46 +5054,6 @@ mon_resist_type bolt::apply_enchantment_to_monster(monsters* mon) behaviour_event(mon, ME_ALERT, MHITNOT); return (MON_AFFECTED); - case BEAM_SLIME: - if (mon->hit_dice * 8 / 2 >= random2(ench_power)) - return (MON_RESIST); - - obvious_effect = true; - - if (mons_holiness(mon) == MH_UNDEAD) - monster_polymorph(mon, MONS_DEATH_OOZE); - else - { - const int x = mon->hit_dice + (coinflip() ? 1 : -1) * random2(5); - - if (x < 3) - monster_polymorph(mon, MONS_OOZE); - else if (x >= 3 && x < 5) - monster_polymorph(mon, MONS_JELLY); - else if (x >= 5 && x < 7) - monster_polymorph(mon, MONS_BROWN_OOZE); - else if (x >= 7 && x <= 11) - { - if (coinflip()) - monster_polymorph(mon, MONS_SLIME_CREATURE); - else - monster_polymorph(mon, MONS_GIANT_AMOEBA); - } - else - { - if (coinflip()) - monster_polymorph(mon, MONS_ACID_BLOB); - else - monster_polymorph(mon, MONS_AZURE_JELLY); - } - } - - if (!mons_eats_items(mon)) - mon->add_ench(ENCH_EAT_ITEMS); - - mon->attitude = ATT_STRICT_NEUTRAL; - return (MON_AFFECTED); - case BEAM_PAIN: // pain/agony if (simple_monster_message(mon, " convulses in agony!")) obvious_effect = true; @@ -6017,7 +5957,6 @@ std::string beam_type_name(beam_type type) case BEAM_PETRIFY: return ("petrify"); case BEAM_BACKLIGHT: return ("backlight"); case BEAM_PORKALATOR: return ("porkalator"); - case BEAM_SLIME: return ("slime"); case BEAM_SLEEP: return ("sleep"); case BEAM_BERSERK: return ("berserk"); case BEAM_POTION_BLACK_SMOKE: return ("black smoke"); diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h index 6a602a2c8f..4d186f9e91 100644 --- a/crawl-ref/source/enum.h +++ b/crawl-ref/source/enum.h @@ -245,7 +245,6 @@ enum beam_type // beam[].flavour BEAM_PETRIFY, BEAM_BACKLIGHT, // 45 BEAM_PORKALATOR, - BEAM_SLIME, BEAM_SLEEP, BEAM_BERSERK, BEAM_LAST_ENCHANTMENT = BEAM_BERSERK, @@ -1253,6 +1252,7 @@ enum duration_type DUR_LOWERED_MR, DUR_REPEL_STAIRS_MOVE, DUR_REPEL_STAIRS_CLIMB, + DUR_SLIMIFY, NUM_DURATIONS }; diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h index c675520e37..1c4d291f8c 100644 --- a/crawl-ref/source/externs.h +++ b/crawl-ref/source/externs.h @@ -836,6 +836,7 @@ public: game_direction_type char_direction; bool opened_zot; bool royal_jelly_dead; + bool transform_cancellable; unsigned short pet_target; diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc index 1426d83ad6..2f3d899835 100644 --- a/crawl-ref/source/fight.cc +++ b/crawl-ref/source/fight.cc @@ -858,6 +858,17 @@ bool melee_attack::player_attack() player_calc_hit_damage(); } + if (you.duration[DUR_SLIMIFY] + && mon_can_be_slimified(defender_as_monster())) + { + // Bail out after sliming so we don't get aux unarmed and + // attack a fellow slime. + damage_done = 0; + slimify_monster(defender_as_monster()); + you.duration[DUR_SLIMIFY] = 0; + return (true); + } + bool hit_woke_orc = false; if (you.religion == GOD_BEOGH && defender->mons_species() == MONS_ORC diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc index 8df057e503..daf446fb0a 100644 --- a/crawl-ref/source/monstuff.cc +++ b/crawl-ref/source/monstuff.cc @@ -2531,6 +2531,54 @@ bool monster_blink(monsters *monster, bool quiet) return (true); } +bool mon_can_be_slimified(monsters *monster) +{ + return (mons_holiness(monster) == MH_UNDEAD + || mons_holiness(monster) == MH_NATURAL + && !mons_is_slime(monster)); +} + +void slimify_monster(monsters *mon, bool hostile) +{ + if (mons_holiness(mon) == MH_UNDEAD) + monster_polymorph(mon, MONS_DEATH_OOZE); + else + { + const int x = mon->hit_dice + (coinflip() ? 1 : -1) * random2(5); + + if (x < 3) + monster_polymorph(mon, MONS_OOZE); + else if (x >= 3 && x < 5) + monster_polymorph(mon, MONS_JELLY); + else if (x >= 5 && x < 7) + monster_polymorph(mon, MONS_BROWN_OOZE); + else if (x >= 7 && x <= 11) + { + if (coinflip()) + monster_polymorph(mon, MONS_SLIME_CREATURE); + else + monster_polymorph(mon, MONS_GIANT_AMOEBA); + } + else + { + if (coinflip()) + monster_polymorph(mon, MONS_ACID_BLOB); + else + monster_polymorph(mon, MONS_AZURE_JELLY); + } + } + + if (!mons_eats_items(mon)) + mon->add_ench(ENCH_EAT_ITEMS); + + if (!hostile) + mon->attitude = ATT_STRICT_NEUTRAL; + else + mon->attitude = ATT_HOSTILE; + + mons_make_god_gift(mon, GOD_JIYVA); +} + static void _set_random_target(monsters* mon) { mon->target = random_in_bounds(); // If we don't find anything better @@ -5533,12 +5581,12 @@ bool mons_avoids_cloud(const monsters *monster, cloud_struct cloud, if (monster->flight_mode() != FL_NONE) return (false); - // These don't care about deep water. + // These don't care about deep water. if (monster_habitable_grid(monster, DNGN_DEEP_WATER)) return (false); // This position could become deep water, and they might drown. - if (grd(cloud.pos) == DNGN_SHALLOW_WATER) + if (grd(cloud.pos) == DNGN_SHALLOW_WATER) return (true); // Otherwise, it's safe for everyone else. @@ -9458,8 +9506,7 @@ static void _mons_in_cloud(monsters *monster) hurted += ((4 * random2(3)) - random2(monster->ac)); wake = true; } - - break; + break; case CLOUD_MUTAGENIC: simple_monster_message(monster, " is engulfed in a mutagenic fog!"); diff --git a/crawl-ref/source/monstuff.h b/crawl-ref/source/monstuff.h index 22b7c3bbdd..b4995ab97e 100644 --- a/crawl-ref/source/monstuff.h +++ b/crawl-ref/source/monstuff.h @@ -96,6 +96,10 @@ int place_monster_corpse(const monsters *monster, bool silent, void slime_vault_change(bool glass); +void slimify_monster(monsters *monster, bool hostile = false); + +bool mon_can_be_slimified(monsters *monster); + void mons_check_pool(monsters *monster, const coord_def &oldpos, killer_type killer = KILL_NONE, int killnum = -1); diff --git a/crawl-ref/source/output.cc b/crawl-ref/source/output.cc index 7ec43683b7..6779e355c7 100644 --- a/crawl-ref/source/output.cc +++ b/crawl-ref/source/output.cc @@ -711,6 +711,12 @@ static void _get_status_lights(std::vector& out) out.push_back(status_light(color, "RoF")); } + if (you.duration[DUR_SLIMIFY]) + { + int color = _dur_colour(GREEN, dur_expiring(DUR_SLIMIFY)); + out.push_back(status_light(color, "Slime")); + } + if (you.duration[DUR_SURE_BLADE]) out.push_back(status_light(BLUE, "Blade")); @@ -2523,6 +2529,9 @@ std::string _status_mut_abilities() "confusing touch")); } + if (you.duration[DUR_SLIMIFY]) + status.push_back(_get_expiration_string(DUR_SLIMIFY, "slimy")); + if (you.duration[DUR_SURE_BLADE]) status.push_back("bonded with blade"); diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index f86d010662..d5591ef803 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -3925,6 +3925,7 @@ int get_expiration_threshold(duration_type dur) case DUR_LEVITATION: case DUR_TRANSFORMATION: // not on status case DUR_DEATHS_DOOR: // not on status + case DUR_SLIMIFY: return (10); // These get no messages when they "flicker". diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index 270a4ca04b..1efd7f2d49 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -74,6 +74,7 @@ REVISION("$Rev$"); #include "state.h" #include "stuff.h" #include "terrain.h" +#include "transfor.h" #include "tutorial.h" #include "view.h" #include "xom.h" @@ -1088,6 +1089,11 @@ static void _inc_penance(god_type god, int val) if (you.duration[DUR_DIVINE_VIGOUR]) remove_divine_vigour(); } + else if (god == GOD_JIYVA) + { + if (you.duration[DUR_SLIMIFY]) + you.duration[DUR_SLIMIFY] = 0; + } if (you.religion == god) { @@ -5376,7 +5382,73 @@ static bool _jiyva_retribution() { const god_type god = GOD_JIYVA; - if (!you.can_safely_mutate() || one_chance_in(4)) + if (you.can_safely_mutate() && one_chance_in(7)) + { + const int mutat = 1 + random2(3); + + god_speaks(god, "You feel Jiyva alter your body."); + + for (int i = 0; i < mutat; ++i) + mutate(RANDOM_BAD_MUTATION, true, false, true); + } + else if (there_are_monsters_nearby() && coinflip()) + { + int tries = 0; + bool found_one = false; + monsters *mon; + + while (tries < 10) + { + mon = choose_random_nearby_monster(0); + + if (!mon || !mon_can_be_slimified(mon) + || mon->attitude != ATT_HOSTILE) + { + tries++; + continue; + } + else + { + found_one = true; + break; + } + } + + if (found_one) + { + mprf(MSGCH_GOD, "Jiyva's putrescence saturates the %s!", + mon->name(DESC_NOCAP_THE).c_str()); + + slimify_monster(mon, true); + } + } + else if (!one_chance_in(3)) + { + god_speaks(god, "Mutagenic energy floods into your body!"); + contaminate_player(random2(you.penance[GOD_JIYVA]) / 2); + + if (coinflip()) + { + transformation_type form = TRAN_NONE; + + switch (random2(3)) + { + case 0: + form = TRAN_BAT; + break; + case 1: + form = TRAN_STATUE; + break; + case 2: + form = TRAN_SPIDER; + break; + } + + if (transform(random2(you.penance[GOD_JIYVA]) * 2, form, true)) + you.transform_cancellable = false; + } + } + else { const monster_type slimes[] = { MONS_GIANT_EYEBALL, MONS_EYE_OF_DRAINING, @@ -5391,10 +5463,10 @@ static bool _jiyva_retribution() bool success = false; for (int i = 0; i < how_many; ++i) { - const monster_type mon = RANDOM_ELEMENT(slimes); + const monster_type slime = RANDOM_ELEMENT(slimes); if (create_monster( - mgen_data::hostile_at(static_cast(mon), + mgen_data::hostile_at(static_cast(slime), you.pos(), 0, 0, true, god)) != -1) { success = true; @@ -5404,15 +5476,6 @@ static bool _jiyva_retribution() god_speaks(god, success ? "Some slimes ooze up out of the ground!" : "The ground quivers slightly."); } - else - { - const int mutat = 1 + random2(4); - - god_speaks(god, "You feel Jiyva alter your body."); - - for (int i = 0; i < mutat; ++i) - mutate(RANDOM_BAD_MUTATION, true, false, true); - } return (true); } @@ -6834,11 +6897,14 @@ void excommunication(god_type new_god) case GOD_JIYVA: _jiyva_slimes_abandon_you(); + if (you.duration[DUR_SLIMIFY]) + you.duration[DUR_SLIMIFY] = 0; + if (you.can_safely_mutate()) { god_speaks(old_god, "You feel Jiyva alter your body."); - for (int i = 0; i < 4; ++i) + for (int i = 0; i < 2; ++i) mutate(RANDOM_BAD_MUTATION, true, false, true); } diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc index 4729730a1f..da5980878b 100644 --- a/crawl-ref/source/tags.cc +++ b/crawl-ref/source/tags.cc @@ -837,6 +837,7 @@ static void tag_construct_you(writer &th) marshallByte(th, you.char_direction); marshallByte(th, you.opened_zot); marshallByte(th, you.royal_jelly_dead); + marshallByte(th, you.transform_cancellable); marshallByte(th, you.your_level); marshallByte(th, you.is_undead); marshallShort(th, you.unrand_reacts); @@ -1261,6 +1262,9 @@ static void tag_read_you(reader &th, char minorVersion) if (minorVersion >= TAG_MINOR_JELLY) you.royal_jelly_dead = (bool) unmarshallByte(th); + if (minorVersion >= TAG_MINOR_TRANS) + you.transform_cancellable = (bool) unmarshallByte(th); + you.your_level = unmarshallByte(th); you.is_undead = static_cast(unmarshallByte(th)); you.unrand_reacts = unmarshallShort(th); diff --git a/crawl-ref/source/tags.h b/crawl-ref/source/tags.h index 8bce7f4c81..f303cf5b69 100644 --- a/crawl-ref/source/tags.h +++ b/crawl-ref/source/tags.h @@ -70,7 +70,8 @@ enum tag_minor_version TAG_ANNOTATE_EXCL = 20, // Store exclusion information for annotations. TAG_MINOR_UGLY = 21, // More ghost bits for (very) ugly things. TAG_MINOR_ROTTING = 22, // Added monster-specific rotting resistance. - TAG_MINOR_VERSION = 22 // Current version. (Keep equal to max.) + TAG_MINOR_TRANS = 23, // Keep track of cancellable transformations. + TAG_MINOR_VERSION = 23 // Current version. (Keep equal to max.) }; diff --git a/crawl-ref/source/transfor.cc b/crawl-ref/source/transfor.cc index fcadaef4dd..3330fe472b 100644 --- a/crawl-ref/source/transfor.cc +++ b/crawl-ref/source/transfor.cc @@ -524,6 +524,14 @@ bool transform(int pow, transformation_type which_trans, bool force, if (!force && crawl_state.is_god_acting()) force = true; + if (!force && !you.transform_cancellable) + { + // Jiyva's wrath-induced transformation is blocking the attempt. + // May need to be updated if transform_cancellable is used for + // other uses. + return (false); + } + if (you.species == SP_MERFOLK && player_is_swimming() && which_trans != TRAN_DRAGON && which_trans != TRAN_BAT) { @@ -961,6 +969,8 @@ void untransform(bool skip_wielding) handle_interrupted_swap(true, false, true); you.turn_is_over = true; + if (!you.transform_cancellable) + you.transform_cancellable = true; } // XXX: This whole system is a mess as it still relies on special -- cgit v1.2.3-54-g00ecf