summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/docs/crawl_manual.txt5
-rw-r--r--crawl-ref/source/abl-show.cc35
-rw-r--r--crawl-ref/source/acr.cc2
-rw-r--r--crawl-ref/source/beam.cc61
-rw-r--r--crawl-ref/source/cloud.cc2
-rw-r--r--crawl-ref/source/enum.h2
-rw-r--r--crawl-ref/source/externs.h1
-rw-r--r--crawl-ref/source/fight.cc11
-rw-r--r--crawl-ref/source/losparam.cc2
-rw-r--r--crawl-ref/source/losparam.h2
-rw-r--r--crawl-ref/source/monstuff.cc55
-rw-r--r--crawl-ref/source/monstuff.h4
-rw-r--r--crawl-ref/source/ouch.cc2
-rw-r--r--crawl-ref/source/output.cc9
-rw-r--r--crawl-ref/source/player.cc1
-rw-r--r--crawl-ref/source/religion.cc92
-rw-r--r--crawl-ref/source/tags.cc4
-rw-r--r--crawl-ref/source/tags.h3
-rw-r--r--crawl-ref/source/transfor.cc10
19 files changed, 204 insertions, 99 deletions
diff --git a/crawl-ref/docs/crawl_manual.txt b/crawl-ref/docs/crawl_manual.txt
index 91423389c0..b9dbc93e2f 100644
--- a/crawl-ref/docs/crawl_manual.txt
+++ b/crawl-ref/docs/crawl_manual.txt
@@ -1900,7 +1900,8 @@ Berserkers:
Berserkers are hardy warriors who worship Trog the Wrathful, from whom
they get the power to go berserk (as well as a number of other powers,
should they prove worthy), but who forbids the use of spell magic. They
-usually enter the dungeon with an axe and dressed in animal skins.
+usually enter the dungeon with a mace or axe, and dressed in animal
+skins.
Paladins:
---------
@@ -1913,7 +1914,7 @@ Priests:
Priests serve either Zin, the ancient and revered God of Law, or
Yredelemnul, the rather less pleasant God of Death. In addition, Hill
Orcs may choose to follow the Orc god Beogh instead. Priests enter the
-dungeon with a traditional weapon, and a priestly robe. Those who serve
+dungeon with a traditional weapon and a priestly robe. Those who serve
Zin also get a few healing potions.
Healers:
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<talent> 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
@@ -1268,21 +1268,6 @@ const zap_info zap_data[] = {
},
{
- ZAP_SLIME,
- "0",
- 100,
- NULL,
- NULL,
- GREEN,
- true,
- BEAM_SLIME,
- DCHAR_SPACE,
- false,
- false,
- false
- },
-
- {
ZAP_PORKALATOR,
"porkalator",
100,
@@ -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/cloud.cc b/crawl-ref/source/cloud.cc
index 0da8010083..7591920662 100644
--- a/crawl-ref/source/cloud.cc
+++ b/crawl-ref/source/cloud.cc
@@ -195,7 +195,7 @@ void delete_cloud( int cloud )
&& one_chance_in(3))
// Don't drown the player!
feat = DNGN_DEEP_WATER;
- else
+ else
feat = grd(c.pos);
if (grd(c.pos) != feat)
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/losparam.cc b/crawl-ref/source/losparam.cc
index c0a3ed0298..9b83e28b11 100644
--- a/crawl-ref/source/losparam.cc
+++ b/crawl-ref/source/losparam.cc
@@ -1,6 +1,6 @@
/*
* File: losparam.h
- * Summary: Parameters for the LOS algorithm
+ * Summary: Parameters for the LOS algorithm
*/
#include "AppHdr.h"
diff --git a/crawl-ref/source/losparam.h b/crawl-ref/source/losparam.h
index 69e043e5fb..15f12d8d49 100644
--- a/crawl-ref/source/losparam.h
+++ b/crawl-ref/source/losparam.h
@@ -11,7 +11,7 @@ enum opacity_type
OPC_CLEAR,
OPC_HALF, // for opaque clouds; two or more block
OPC_OPAQUE,
-
+
NUM_OPACITIES
};
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/ouch.cc b/crawl-ref/source/ouch.cc
index 27b382fa6c..e52ed53ea6 100644
--- a/crawl-ref/source/ouch.cc
+++ b/crawl-ref/source/ouch.cc
@@ -953,7 +953,7 @@ void ouch(int dam, int death_source, kill_method_type death_type,
dam -= you.magic_points;
dec_mp(you.magic_points);
}
-
+
if (dam >= you.hp)
{
if (harm_protection_type hpt = god_protects_from_harm(you.religion))
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<status_light>& 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<monster_type>(mon),
+ mgen_data::hostile_at(static_cast<monster_type>(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<undead_state_type>(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