summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/source/acr.cc40
-rw-r--r--crawl-ref/source/beam.cc61
-rw-r--r--crawl-ref/source/directn.cc13
-rw-r--r--crawl-ref/source/enum.h26
-rw-r--r--crawl-ref/source/externs.h9
-rw-r--r--crawl-ref/source/fight.cc14
-rw-r--r--crawl-ref/source/ghost.cc12
-rw-r--r--crawl-ref/source/mon-util.cc92
-rw-r--r--crawl-ref/source/mon-util.h4
-rw-r--r--crawl-ref/source/monstuff.cc15
-rw-r--r--crawl-ref/source/mstuff2.cc2
-rw-r--r--crawl-ref/source/player.cc45
-rw-r--r--crawl-ref/source/religion.cc12
-rw-r--r--crawl-ref/source/spells1.cc9
-rw-r--r--crawl-ref/source/spl-book.cc4
-rw-r--r--crawl-ref/source/spl-cast.cc5
-rw-r--r--crawl-ref/source/spl-data.h10
17 files changed, 290 insertions, 83 deletions
diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc
index 2ec9fb0cce..fdbd08193e 100644
--- a/crawl-ref/source/acr.cc
+++ b/crawl-ref/source/acr.cc
@@ -2462,14 +2462,14 @@ static bool _decrement_a_duration(duration_type dur, const char* endmsg = NULL,
you.duration[dur]--;
if (you.duration[dur] == midpoint)
{
- if ( midmsg )
+ if (midmsg)
mpr(midmsg, chan);
you.duration[dur] -= midloss;
}
}
else if (you.duration[dur] == 1)
{
- if ( endmsg )
+ if (endmsg)
mpr(endmsg, chan);
rc = true;
@@ -2593,7 +2593,7 @@ static void _decrement_durations()
}
}
- //jmf: more flexible weapon branding code
+ //jmf: More flexible weapon branding code.
if (you.duration[DUR_WEAPON_BRAND] > 1)
you.duration[DUR_WEAPON_BRAND]--;
else if (you.duration[DUR_WEAPON_BRAND] == 1)
@@ -2656,7 +2656,7 @@ static void _decrement_durations()
}
}
- // must come after transformation duration
+ // Must come after transformation duration.
_decrement_a_duration(DUR_BREATH_WEAPON, "You have got your breath back.",
-1, 0, NULL, MSGCH_RECOVERY);
@@ -2717,7 +2717,7 @@ static void _decrement_durations()
if ( _decrement_a_duration(DUR_TELEPORT) )
{
- // only to a new area of the abyss sometimes (for abyss teleports)
+ // Only to a new area of the abyss sometimes (for abyss teleports).
you_teleport_now( true, one_chance_in(5) );
untag_followers();
}
@@ -2748,8 +2748,17 @@ static void _decrement_durations()
_decrement_a_duration(DUR_BARGAIN, "You feel less charismatic.");
_decrement_a_duration(DUR_CONF, "You feel less confused.");
- if (_decrement_a_duration(DUR_PARALYSIS, "You can move again."))
- you.redraw_evasion = true;
+ if (you.duration[DUR_PARALYSIS] || you.duration[DUR_PETRIFIED])
+ {
+ _decrement_a_duration(DUR_PARALYSIS);
+ _decrement_a_duration(DUR_PETRIFIED);
+
+ if (!you.duration[DUR_PARALYSIS] && !you.duration[DUR_PETRIFIED])
+ {
+ mpr("You can move again.", MSGCH_DURATION);
+ you.redraw_evasion = true;
+ }
+ }
_decrement_a_duration(DUR_EXHAUSTED, "You feel less fatigued.");
@@ -2774,7 +2783,7 @@ static void _decrement_durations()
if (_decrement_a_duration(DUR_BERSERKER, "You are no longer berserk."))
{
- //jmf: guilty for berserking /after/ berserk
+ //jmf: Guilty for berserking /after/ berserk.
did_god_conduct( DID_STIMULANTS, 6 + random2(6) );
// Sometimes berserk leaves us physically drained.
@@ -2804,23 +2813,26 @@ static void _decrement_durations()
{
mpr("Trog's vigour flows through your veins.");
}
- else if ( one_chance_in(chance) )
+ else if (one_chance_in(chance))
{
mpr("You pass out from exhaustion.", MSGCH_WARN);
you.duration[DUR_PARALYSIS] += roll_dice( 1, 4 );
}
}
- if ( you.duration[DUR_PARALYSIS] == 0 )
+ if (you.duration[DUR_PARALYSIS] == 0
+ && you.duration[DUR_PETRIFIED] == 0)
+ {
mpr("You are exhausted.", MSGCH_WARN);
+ }
- // this resets from an actual penalty or from NO_BERSERK_PENALTY
+ // This resets from an actual penalty or from NO_BERSERK_PENALTY.
you.berserk_penalty = 0;
int dur = 12 + roll_dice( 2, 12 );
you.duration[DUR_EXHAUSTED] += dur;
- // Don't trigger too many tutorial messages
+ // Don't trigger too many tutorial messages.
const bool tut_slow = Options.tutorial_events[TUT_YOU_ENCHANTED];
Options.tutorial_events[TUT_YOU_ENCHANTED] = false;
@@ -3148,7 +3160,7 @@ static void _world_reacts()
if (you.duration[DUR_FIRE_SHIELD] > 0)
manage_fire_shield();
- // food death check:
+ // Food death check.
if (you.is_undead != US_UNDEAD && you.hunger <= 500)
{
if (!you.cannot_act() && one_chance_in(40))
@@ -4624,7 +4636,7 @@ static void _compile_time_asserts()
COMPILE_CHECK(SP_VAMPIRE == 34 , c3);
COMPILE_CHECK(SPELL_BOLT_OF_MAGMA == 18 , c4);
COMPILE_CHECK(SPELL_POISON_ARROW == 94 , c5);
- COMPILE_CHECK(SPELL_SUMMON_MUSHROOMS == 222 , c6);
+ COMPILE_CHECK(SPELL_SUMMON_MUSHROOMS == 223 , c6);
//jmf: NEW ASSERTS: we ought to do a *lot* of these
COMPILE_CHECK(NUM_SPELLS < SPELL_NO_SPELL , c7);
diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc
index 50b7af8611..bd7e702624 100644
--- a/crawl-ref/source/beam.cc
+++ b/crawl-ref/source/beam.cc
@@ -96,6 +96,7 @@ static int _affect_player(bolt &beam, item_def *item = NULL);
static int _affect_monster(bolt &beam, monsters *mon, item_def *item = NULL);
static int _affect_monster_enchantment(bolt &beam, monsters *mon);
static void _beam_paralyses_monster( bolt &pbolt, monsters *monster );
+static void _beam_petrifies_monster( bolt &pbolt, monsters *monster );
static int _range_used_on_hit(bolt &beam);
static void _explosion1(bolt &pbolt);
static void _explosion_map(bolt &beam, int x, int y,
@@ -571,6 +572,12 @@ static void _get_max_range( zap_type z_type, int power, bolt &pbolt )
pbolt.flavour = BEAM_PARALYSIS;
break;
+ case ZAP_PETRIFY:
+ pbolt.name = "0";
+ pbolt.rangeMax = 12;
+ pbolt.flavour = BEAM_PETRIFY;
+ break;
+
case ZAP_CONFUSION:
pbolt.name = "0";
pbolt.rangeMax = 12;
@@ -953,6 +960,7 @@ static void _zappy( zap_type z_type, int power, bolt &pbolt )
case ZAP_SLOWING:
case ZAP_HASTING:
case ZAP_PARALYSIS:
+ case ZAP_PETRIFY:
case ZAP_BACKLIGHT:
case ZAP_SLEEP:
case ZAP_CONFUSION:
@@ -1540,6 +1548,12 @@ static void _zappy( zap_type z_type, int power, bolt &pbolt )
// pbolt.is_beam = true;
break;
+ case ZAP_PETRIFY:
+ pbolt.name = "0";
+ pbolt.flavour = BEAM_PETRIFY;
+ // pbolt.is_beam = true;
+ break;
+
case ZAP_CONFUSION:
pbolt.name = "0";
pbolt.flavour = BEAM_CONFUSION;
@@ -2495,7 +2509,7 @@ int mons_ench_f2(monsters *monster, bolt &pbolt)
&& !mons_is_stationary(monster)
&& monster->add_ench(mon_enchant(ENCH_SLOW, 0, _whose_kill(pbolt))))
{
- if (!mons_is_paralysed(monster)
+ if (!mons_is_paralysed(monster) && !mons_is_petrified(monster)
&& simple_monster_message(monster, " seems to slow down."))
{
pbolt.obvious_effect = true;
@@ -2517,7 +2531,7 @@ int mons_ench_f2(monsters *monster, bolt &pbolt)
&& !mons_is_stationary(monster)
&& monster->add_ench(ENCH_HASTE))
{
- if (!mons_is_paralysed(monster)
+ if (!mons_is_paralysed(monster) && !mons_is_petrified(monster)
&& simple_monster_message(monster, " seems to speed up."))
{
pbolt.obvious_effect = true;
@@ -2554,6 +2568,10 @@ int mons_ench_f2(monsters *monster, bolt &pbolt)
_beam_paralyses_monster(pbolt, monster);
return (MON_AFFECTED);
+ case BEAM_PETRIFY:
+ _beam_petrifies_monster(pbolt, monster);
+ return (MON_AFFECTED);
+
case BEAM_CONFUSION:
if (!mons_class_is_confusable(monster->type))
return (MON_UNAFFECTED);
@@ -2635,7 +2653,9 @@ static void _slow_monster(monsters *mon, int /* degree */)
static void _beam_paralyses_monster(bolt &pbolt, monsters *monster)
{
if (!monster->has_ench(ENCH_PARALYSIS)
- && monster->add_ench(ENCH_PARALYSIS))
+ && monster->add_ench(ENCH_PARALYSIS)
+ && (!monster->has_ench(ENCH_PETRIFIED)
+ || monster->has_ench(ENCH_PETRIFYING)))
{
if (simple_monster_message(monster, " suddenly stops moving!"))
pbolt.obvious_effect = true;
@@ -2644,6 +2664,32 @@ static void _beam_paralyses_monster(bolt &pbolt, monsters *monster)
}
}
+static void _beam_petrifies_monster(bolt &pbolt, monsters *monster)
+{
+ int petrifying = monster->has_ench(ENCH_PETRIFYING);
+ if (monster->has_ench(ENCH_PETRIFIED))
+ {
+ if (petrifying > 0)
+ {
+ monster->del_ench(ENCH_PETRIFYING, true);
+ if (!monster->has_ench(ENCH_PARALYSIS)
+ && simple_monster_message(monster, " stops moving altogether!"))
+ {
+ pbolt.obvious_effect = true;
+ }
+ }
+ }
+ else if (monster->add_ench(ENCH_PETRIFIED)
+ && !monster->has_ench(ENCH_PARALYSIS))
+ {
+ monster->add_ench(ENCH_PETRIFYING);
+ if (simple_monster_message(monster, " is moving more slowly."))
+ pbolt.obvious_effect = true;
+
+ mons_check_pool(monster, pbolt.killer(), pbolt.beam_source);
+ }
+}
+
// Returns true if the curare killed the monster.
bool curare_hits_monster( const bolt &beam,
monsters *monster,
@@ -3786,6 +3832,11 @@ static int _affect_player( bolt &beam, item_def *item )
beam.obvious_effect = true;
break; // paralysis
+ case BEAM_PETRIFY:
+ you.petrify( beam.ench_power );
+ beam.obvious_effect = true;
+ break;
+
case BEAM_CONFUSION:
potion_effect( POT_CONFUSION, beam.ench_power );
beam.obvious_effect = true;
@@ -4986,6 +5037,7 @@ static int _range_used_on_hit(bolt &beam)
case BEAM_HASTE:
case BEAM_HEALING:
case BEAM_PARALYSIS:
+ case BEAM_PETRIFY:
case BEAM_CONFUSION:
case BEAM_INVISIBILITY:
case BEAM_TELEPORT:
@@ -5557,7 +5609,8 @@ killer_type bolt::killer() const
{
case KILL_YOU:
case KILL_YOU_MISSILE:
- return (flavour == BEAM_PARALYSIS? KILL_YOU : KILL_YOU_MISSILE);
+ return (flavour == BEAM_PARALYSIS
+ || flavour == BEAM_PETRIFY) ? KILL_YOU : KILL_YOU_MISSILE;
case KILL_MON:
case KILL_MON_MISSILE:
diff --git a/crawl-ref/source/directn.cc b/crawl-ref/source/directn.cc
index 0c2b554d62..cd5901145f 100644
--- a/crawl-ref/source/directn.cc
+++ b/crawl-ref/source/directn.cc
@@ -1997,8 +1997,12 @@ static std::string _describe_mons_enchantment(const monsters &mons,
{
// Suppress silly-looking combinations, even if they're
// internally valid.
- if (paralysed && (ench.ench == ENCH_SLOW || ench.ench == ENCH_HASTE))
+ if (paralysed && (ench.ench == ENCH_SLOW || ench.ench == ENCH_HASTE
+ || ench.ench == ENCH_PETRIFIED
+ || ench.ench == ENCH_PETRIFYING))
+ {
return "";
+ }
if ((ench.ench == ENCH_HASTE || ench.ench == ENCH_BATTLE_FRENZY)
&& mons.has_ench(ENCH_BERSERK))
@@ -2006,6 +2010,9 @@ static std::string _describe_mons_enchantment(const monsters &mons,
return "";
}
+ if (ench.ench == ENCH_PETRIFIED && mons.has_ench(ENCH_PETRIFYING))
+ return "";
+
switch (ench.ench)
{
case ENCH_POISON:
@@ -2034,6 +2041,10 @@ static std::string _describe_mons_enchantment(const monsters &mons,
return "covered in liquid flames";
case ENCH_HELD:
return "entangled in a net";
+ case ENCH_PETRIFIED:
+ return "petrified";
+ case ENCH_PETRIFYING:
+ return "slowly petrifying";
default:
return "";
}
diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h
index 186bccdccc..32d5efbd46 100644
--- a/crawl-ref/source/enum.h
+++ b/crawl-ref/source/enum.h
@@ -1053,7 +1053,8 @@ enum floor_property_type
FPROP_NONE, // 0
FPROP_SANCTUARY_1,
FPROP_SANCTUARY_2,
- FPROP_BLOODY // bloody floor and sanctuary are exclusive, so that's okay
+ FPROP_BLOODY
+ // Bloody floor and sanctuary are exclusive, so that's okay.
};
enum duration_type
@@ -1116,6 +1117,8 @@ enum duration_type
DUR_SAGE,
DUR_TELEPATHY,
DUR_VITALISATION_CHAIN,
+ DUR_PETRIFIED,
+
NUM_DURATIONS
};
@@ -1147,9 +1150,11 @@ enum enchant_type
ENCH_SICK,
ENCH_SLEEPY, // Monster can't wake until this wears off.
ENCH_FATIGUE, // Post-berserk fatigue.
- ENCH_HELD, // caught in a net
- ENCH_BATTLE_FRENZY, // Monster is in a battle frenzy
+ ENCH_HELD, // Caught in a net.
+ ENCH_BATTLE_FRENZY, // 25 -- Monster is in a battle frenzy
ENCH_NEUTRAL,
+ ENCH_PETRIFYING,
+ ENCH_PETRIFIED,
// Update enchantment names in mon-util.cc when adding or removing
// enchantments.
@@ -2585,28 +2590,29 @@ enum spell_type
SPELL_EXCRUCIATING_WOUNDS,
SPELL_PORTAL_PROJECTILE,
SPELL_SUMMON_UGLY_THING, // 205
+ SPELL_PETRIFY,
// Mostly monster-only spells after this point:
SPELL_HELLFIRE_BURST,
SPELL_VAMPIRE_SUMMON,
SPELL_BRAIN_FEED,
- SPELL_FAKE_RAKSHASA_SUMMON,
- SPELL_STEAM_BALL, // 210
+ SPELL_FAKE_RAKSHASA_SUMMON, // 210
+ SPELL_STEAM_BALL,
SPELL_SUMMON_UFETUBUS,
SPELL_SUMMON_BEAST,
SPELL_ENERGY_BOLT,
- SPELL_POISON_SPLASH,
- SPELL_SUMMON_UNDEAD, // 215
+ SPELL_POISON_SPLASH, // 215
+ SPELL_SUMMON_UNDEAD,
SPELL_CANTRIP,
SPELL_QUICKSILVER_BOLT,
SPELL_METAL_SPLINTERS,
- SPELL_MIASMA,
- SPELL_SUMMON_DRAKES, // 220
+ SPELL_MIASMA, // 220
+ SPELL_SUMMON_DRAKES,
SPELL_BLINK_OTHER,
SPELL_SUMMON_MUSHROOMS,
NUM_SPELLS,
- SPELL_NO_SPELL = 250 // 255 - added 22jan2000 {dlb}
+ SPELL_NO_SPELL = 250
};
enum slot_select_mode
diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h
index dc30418f83..3cbf438d20 100644
--- a/crawl-ref/source/externs.h
+++ b/crawl-ref/source/externs.h
@@ -158,6 +158,7 @@ public:
virtual void poison(actor *attacker, int amount = 1) = 0;
virtual bool sicken(int amount) = 0;
virtual void paralyse(int strength) = 0;
+ virtual void petrify(int strength) = 0;
virtual void slow_down(int strength) = 0;
virtual void confuse(int strength) = 0;
virtual void rot(actor *attacker, int rotlevel, int immediate_rot) = 0;
@@ -199,6 +200,7 @@ public:
virtual bool airborne() const;
virtual bool paralysed() const = 0;
+ virtual bool cannot_move() const = 0;
virtual bool confused() const = 0;
virtual bool caught() const = 0;
virtual bool asleep() const { return (false); }
@@ -209,7 +211,7 @@ public:
virtual bool incapacitated() const
{
- return paralysed() || asleep() || confused() || caught();
+ return cannot_move() || asleep() || confused() || caught();
}
virtual int holy_aura() const
@@ -855,6 +857,7 @@ public:
void poison(actor *agent, int amount = 1);
bool sicken(int amount);
void paralyse(int str);
+ void petrify(int str);
void slow_down(int str);
void confuse(int strength);
void rot(actor *agent, int rotlevel, int immed_rot);
@@ -883,6 +886,7 @@ public:
bool permanent_flight() const;
bool paralysed() const;
+ bool cannot_move() const;
bool confused() const;
bool caught() const;
bool backlit(bool check_haloed = true) const;
@@ -1215,6 +1219,8 @@ public:
bool can_see(const actor *target) const;
bool is_icy() const;
bool paralysed() const;
+ bool cannot_move() const;
+ bool cannot_act() const;
bool confused() const;
bool caught() const;
bool asleep() const;
@@ -1231,6 +1237,7 @@ public:
void poison(actor *agent, int amount = 1);
bool sicken(int strength);
void paralyse(int str);
+ void petrify(int str);
void slow_down(int str);
void confuse(int strength);
void rot(actor *agent, int rotlevel, int immed_rot);
diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc
index d420986590..be37c09cfb 100644
--- a/crawl-ref/source/fight.cc
+++ b/crawl-ref/source/fight.cc
@@ -316,11 +316,11 @@ unchivalric_attack_type is_unchivalric_attack(const actor *attacker,
unchivalric = UCAT_INVISIBLE;
// held in a net
- if (def->has_ench(ENCH_HELD))
+ if (def->has_ench(ENCH_HELD) || def->has_ench(ENCH_PETRIFYING))
unchivalric = UCAT_HELD_IN_NET;
// paralysed
- if (def->has_ench(ENCH_PARALYSIS))
+ if (def->cannot_act())
unchivalric = UCAT_PARALYSED;
// sleeping
@@ -1305,8 +1305,10 @@ bool melee_attack::player_hits_monster()
return (to_hit >= def->ev
|| one_chance_in(20)
- || ((mons_is_paralysed(def) || def->behaviour == BEH_SLEEP)
- && !one_chance_in(10 + you.skills[SK_STABBING])));
+ || ((mons_cannot_act(def) || def->behaviour == BEH_SLEEP)
+ && !one_chance_in(10 + you.skills[SK_STABBING]))
+ || mons_is_petrifying(def)
+ && !one_chance_in(2 + you.skills[SK_STABBING]));
}
int melee_attack::player_stat_modify_damage(int damage)
@@ -1517,7 +1519,7 @@ int melee_attack::player_stab(int damage)
if (def->behaviour == BEH_SLEEP)
{
- // Sleeping moster wakes up when stabbed but may be groggy
+ // Sleeping moster wakes up when stabbed but may be groggy.
if (random2(200) <= you.skills[SK_STABBING] + you.dex)
{
int stun = random2( you.dex + 1 );
@@ -1530,6 +1532,8 @@ int melee_attack::player_stab(int damage)
}
damage = player_stab_weapon_bonus(damage);
+ if (mons_is_petrified(def))
+ damage /= 3;
}
return (damage);
diff --git a/crawl-ref/source/ghost.cc b/crawl-ref/source/ghost.cc
index 0cafd86dbe..b4f2788ab7 100644
--- a/crawl-ref/source/ghost.cc
+++ b/crawl-ref/source/ghost.cc
@@ -190,19 +190,19 @@ void ghost_demon::init_random_demon()
|| brand == SPWPN_FROST);
}
- // is demon a spellcaster?
- // upped from one_chance_in(3)... spellcasters are more interesting
+ // Is demon a spellcaster?
+ // Upped from one_chance_in(3)... spellcasters are more interesting
// and I expect named demons to typically have a trick or two -- bwr
spellcaster = !one_chance_in(10);
- // does demon fly?
+ // Does demon fly?
fly = (one_chance_in(3)? FL_NONE :
one_chance_in(5)? FL_LEVITATE : FL_FLY);
// hit dice:
xl = 10 + roll_dice(2, 10);
- // does demon cycle colours?
+ // Does demon cycle colours?
cycle_colours = one_chance_in(10);
spells.init(SPELL_NO_SPELL);
@@ -225,7 +225,7 @@ void ghost_demon::init_random_demon()
if (coinflip())
{
spells[3] = RANDOM_ELEMENT(search_order_misc);
- if ( spells[3] == SPELL_DIG )
+ if (spells[3] == SPELL_DIG)
spells[3] = SPELL_NO_SPELL;
}
@@ -457,6 +457,8 @@ spell_type ghost_demon::translate_spell(spell_type spel) const
return (SPELL_SYMBOL_OF_TORMENT);
case SPELL_DELAYED_FIREBALL:
return (SPELL_FIREBALL);
+ case SPELL_PETRIFY:
+ return (SPELL_PARALYSE);
default:
break;
}
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index faec32cacc..15ba6e9e30 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -2140,6 +2140,27 @@ bool mons_is_paralysed(const monsters *m)
return (m->has_ench(ENCH_PARALYSIS));
}
+bool mons_is_petrified(const monsters *m)
+{
+ return (m->has_ench(ENCH_PETRIFIED));
+}
+
+bool mons_is_petrifying(const monsters *m)
+{
+ return (m->has_ench(ENCH_PETRIFYING));
+}
+
+bool mons_cannot_act(const monsters *m)
+{
+ return (mons_is_paralysed(m)
+ || mons_is_petrified(m) && !mons_is_petrifying(m));
+}
+
+bool mons_cannot_move(const monsters *m)
+{
+ return (mons_cannot_act(m) || mons_is_petrifying(m));
+}
+
bool mons_is_confused(const monsters *m)
{
return (m->has_ench(ENCH_CONFUSION)
@@ -2181,8 +2202,7 @@ bool mons_looks_stabbable(const monsters *m)
return (mons_behaviour_perceptible(m)
&& !mons_friendly(m)
&& (mons_is_sleeping(m)
- || mons_is_paralysed(m)
- || mons_is_caught(m)));
+ || mons_cannot_act(m)));
}
bool mons_looks_distracted(const monsters *m)
@@ -2192,7 +2212,8 @@ bool mons_looks_distracted(const monsters *m)
&& (m->foe != MHITYOU && !mons_is_batty(m) && !mons_neutral(m)
|| mons_is_confused(m)
|| mons_is_fleeing(m)
- || mons_is_caught(m)));
+ || mons_is_caught(m)
+ || mons_is_petrifying(m)));
}
bool mons_should_fire(struct bolt &beam)
@@ -4242,8 +4263,8 @@ bool monsters::fumbles_attack(bool verbose)
bool monsters::cannot_fight() const
{
- return mons_class_flag(type, M_NO_EXP_GAIN)
- || mons_is_statue(type);
+ return (mons_class_flag(type, M_NO_EXP_GAIN)
+ || mons_is_statue(type));
}
void monsters::attacking(actor * /* other */)
@@ -4310,6 +4331,16 @@ bool monsters::paralysed() const
return (mons_is_paralysed(this));
}
+bool monsters::cannot_act() const
+{
+ return (mons_cannot_act(this));
+}
+
+bool monsters::cannot_move() const
+{
+ return (mons_cannot_move(this));
+}
+
bool monsters::asleep() const
{
return (mons_is_sleeping(this));
@@ -4550,6 +4581,16 @@ void monsters::paralyse(int strength)
mons_ench_f2(this, paralysis);
}
+void monsters::petrify(int strength)
+{
+ if (mons_is_insubstantial(type))
+ return;
+
+ bolt petrif;
+ petrif.flavour = BEAM_PETRIFY;
+ mons_ench_f2(this, petrif);
+}
+
void monsters::slow_down(int strength)
{
bolt slow;
@@ -5066,6 +5107,23 @@ void monsters::remove_enchantment_effect(const mon_enchant &me, bool quiet)
behaviour_event(this, ME_EVAL);
break;
+ case ENCH_PETRIFIED:
+ if (!quiet)
+ simple_monster_message(this, " is no longer petrified.");
+ del_ench(ENCH_PETRIFYING);
+
+ behaviour_event(this, ME_EVAL);
+ break;
+
+ case ENCH_PETRIFYING:
+ if (!has_ench(ENCH_PETRIFIED))
+ break;
+
+ if (!quiet)
+ simple_monster_message(this, " stops moving altogether!");
+ behaviour_event(this, ME_EVAL);
+ break;
+
case ENCH_FEAR:
snprintf( info, INFO_SIZE, " seems to regain %s courage.",
mons_pronoun(static_cast<monster_type>(this->type),
@@ -5308,6 +5366,7 @@ void monsters::timeout_enchantments(int levels)
case ENCH_SLOW: case ENCH_HASTE: case ENCH_FEAR:
case ENCH_INVIS: case ENCH_CHARM: case ENCH_SLEEP_WARY:
case ENCH_SICK: case ENCH_SLEEPY: case ENCH_PARALYSIS:
+ case ENCH_PETRIFYING: case ENCH_PETRIFIED:
case ENCH_BATTLE_FRENZY: case ENCH_NEUTRAL:
lose_ench_levels(i->second, levels);
break;
@@ -5433,6 +5492,8 @@ void monsters::apply_enchantment(const mon_enchant &me)
case ENCH_HASTE:
case ENCH_FEAR:
case ENCH_PARALYSIS:
+ case ENCH_PETRIFYING:
+ case ENCH_PETRIFIED:
case ENCH_SICK:
case ENCH_BACKLIGHT:
case ENCH_ABJ:
@@ -5447,7 +5508,7 @@ void monsters::apply_enchantment(const mon_enchant &me)
case ENCH_HELD:
{
- if (mons_is_stationary(this) || mons_is_paralysed(this)
+ if (mons_is_stationary(this) || mons_cannot_act(this)
|| this->behaviour == BEH_SLEEP)
{
break;
@@ -6173,7 +6234,14 @@ int monsters::action_energy(energy_use_type et) const
void monsters::lose_energy(energy_use_type et, int div, int mult)
{
- speed_increment -= div_round_up(mult * action_energy(et), div);
+ int energy_loss = div_round_up(mult * action_energy(et), div);
+ if (has_ench(ENCH_PETRIFYING))
+ {
+ energy_loss *= 3;
+ energy_loss /= 2;
+ }
+
+ speed_increment -= energy_loss;
}
static inline monster_type _royal_jelly_ejectable_monster()
@@ -6250,7 +6318,7 @@ static const char *enchant_names[] =
"rot", "summon", "abj", "backlit", "charm", "fire",
"gloshifter", "shifter", "tp", "wary", "submerged",
"short lived", "paralysis", "sick", "sleep", "fatigue", "held",
- "blood-lust", "neutral", "bug"
+ "blood-lust", "neutral", "petrifying", "petrified", "bug"
};
static const char *_mons_enchantment_name(enchant_type ench)
@@ -6347,7 +6415,7 @@ int mon_enchant::calc_duration(const monsters *mons,
const int deg = newdegree? newdegree : 1;
// Beneficial enchantments (like Haste) should not be throttled by
- // monster HD!
+ // monster HD via modded_speed(). Use mod_speed instead!
switch (ench)
{
case ENCH_HASTE:
@@ -6365,6 +6433,12 @@ int mon_enchant::calc_duration(const monsters *mons,
case ENCH_PARALYSIS:
cturn = std::max(90 / modded_speed(mons, 5), 3);
break;
+ case ENCH_PETRIFIED:
+ cturn = std::max(8, 150 / (1 + modded_speed(mons, 5)));
+ break;
+ case ENCH_PETRIFYING:
+ cturn = 50 / _mod_speed(10, mons->speed);
+ break;
case ENCH_CONFUSION:
cturn = std::max(100 / modded_speed(mons, 5), 3);
break;
diff --git a/crawl-ref/source/mon-util.h b/crawl-ref/source/mon-util.h
index 8da8afacbc..cc7e364d37 100644
--- a/crawl-ref/source/mon-util.h
+++ b/crawl-ref/source/mon-util.h
@@ -679,6 +679,10 @@ bool invalid_monster_index(int i);
bool monster_shover(const monsters *m);
bool mons_is_paralysed(const monsters *m);
+bool mons_is_petrified(const monsters *m);
+bool mons_is_petrifying(const monsters *m);
+bool mons_cannot_act(const monsters *m);
+bool mons_cannot_move(const monsters *m);
bool monster_senior(const monsters *first, const monsters *second);
monster_type draco_subspecies( const monsters *mon );
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index 313444e743..1d046afcf8 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -5603,7 +5603,7 @@ static void _handle_monster_move(int i, monsters *monster)
_monster_regenerate(monster);
- if (mons_is_paralysed(monster))
+ if (mons_cannot_act(monster))
{
monster->speed_increment -= non_move_energy;
continue;
@@ -5690,7 +5690,7 @@ static void _handle_monster_move(int i, monsters *monster)
// Struggling against the net takes time.
_swim_or_move_energy(monster);
}
- else
+ else if (!mons_is_petrified(monster))
{
// Calculates mmov_x, mmov_y based on monster target.
_handle_movement(monster);
@@ -5877,7 +5877,6 @@ static void _handle_monster_move(int i, monsters *monster)
|| monster->type == MONS_BALL_LIGHTNING)
&& monster->hit_points < 1)
{
-
// Detach monster from the grid first, so it
// doesn't get hit by its own explosion. (GDL)
mgrd[monster->x][monster->y] = NON_MONSTER;
@@ -5902,7 +5901,7 @@ static void _handle_monster_move(int i, monsters *monster)
continue;
}
- if (!_monster_move(monster))
+ if (mons_cannot_move(monster) || !_monster_move(monster))
monster->speed_increment -= non_move_energy;
}
update_beholders(monster);
@@ -6178,10 +6177,10 @@ static bool _mons_can_displace(const monsters *mpusher, const monsters *mpushee)
// can't push. Note that sleeping monsters can't be pushed
// past, either, but they may be woken up by a crowd trying to
// elbow past them, and the wake-up check happens downstream.
- if (mons_is_confused(mpusher) || mons_is_confused(mpushee)
- || mons_is_paralysed(mpusher) || mons_is_paralysed(mpushee)
- || mons_is_sleeping(mpusher) || mons_is_stationary(mpusher)
- || mons_is_stationary(mpushee))
+ if (mons_is_confused(mpusher) || mons_is_confused(mpushee)
+ || mons_cannot_move(mpusher) || mons_cannot_move(mpushee)
+ || mons_is_stationary(mpusher) || mons_is_stationary(mpushee)
+ || mons_is_sleeping(mpusher))
{
return (false);
}
diff --git a/crawl-ref/source/mstuff2.cc b/crawl-ref/source/mstuff2.cc
index 47872d502d..b80db9bbba 100644
--- a/crawl-ref/source/mstuff2.cc
+++ b/crawl-ref/source/mstuff2.cc
@@ -2390,7 +2390,7 @@ bool orc_battle_cry(monsters *chief)
&& mons_aligned(boss_index, i)
&& mon->hit_dice < chief->hit_dice
&& !mon->has_ench(ENCH_BERSERK)
- && !mon->paralysed()
+ && !mon->cannot_move()
&& !mon->confused()
&& chief->can_see(mon))
{
diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc
index 5bd01e2ff6..5434768742 100644
--- a/crawl-ref/source/player.cc
+++ b/crawl-ref/source/player.cc
@@ -2234,7 +2234,7 @@ int player_evasion()
int ev = 10 + 2 * size_factor;
// Repulsion fields and size are all that matters when paralysed.
- if (you.paralysed())
+ if (you.cannot_move())
{
ev = 2 + size_factor;
if (player_mutation_level(MUT_REPULSION_FIELD) > 0)
@@ -2611,18 +2611,18 @@ bool player_beheld_by( const monsters *mon )
return false;
}
-// removes a monster from the list of beholders
-// if force == true (e.g. monster dead) or one of
-// several cases is met
+// Removes a monster from the list of beholders if force == true
+// (e.g. monster dead) or one of several cases is met.
void update_beholders(const monsters *mon, bool force)
{
- if (!player_beheld_by(mon)) // not in list?
+ if (!player_beheld_by(mon)) // Not in list?
return;
- // is an update even necessary?
+ // Is an update even necessary?
if (force || !mons_near(mon) || mons_friendly(mon) || mon->submerged()
- || mon->has_ench(ENCH_CONFUSION) || mons_is_paralysed(mon) || mon->asleep()
- || silenced(you.x_pos, you.y_pos) || silenced(mon->x, mon->y))
+ || mon->has_ench(ENCH_CONFUSION) || mons_cannot_move(mon)
+ || mon->asleep() || silenced(you.x_pos, you.y_pos)
+ || silenced(mon->x, mon->y))
{
const std::vector<int> help = you.beheld_by;
you.beheld_by.clear();
@@ -3875,9 +3875,11 @@ void display_char_status()
if (you.duration[DUR_BEHELD])
mpr( "You are beheld." );
- // how exactly did you get to show the status?
+ // How exactly did you get to show the status?
if (you.duration[DUR_PARALYSIS])
mpr( "You are paralysed." );
+ if (you.duration[DUR_PETRIFIED])
+ mpr( "You are petrified." );
if (you.duration[DUR_SLEEP])
mpr( "You are asleep." );
@@ -5346,7 +5348,7 @@ level_id actor::shaft_dest() const
bool actor::airborne() const
{
- return (is_levitating() || (flight_mode() == FL_FLY && !paralysed()));
+ return (is_levitating() || (flight_mode() == FL_FLY && !cannot_move()));
}
bool actor::can_pass_through(int x, int y) const
@@ -5770,7 +5772,7 @@ bool player::cannot_speak() const
if (silenced(x_pos, y_pos))
return (true);
- if (you.duration[DUR_PARALYSIS]) // we allow talking during sleep ;)
+ if (you.cannot_move()) // we allow talking during sleep ;)
return (true);
// No transform that prevents the player from speaking yet.
@@ -6090,6 +6092,11 @@ bool player::paralysed() const
return (duration[DUR_PARALYSIS]);
}
+bool player::cannot_move() const
+{
+ return (duration[DUR_PARALYSIS] || duration[DUR_PETRIFIED]);
+}
+
bool player::confused() const
{
return (duration[DUR_CONF]);
@@ -6409,6 +6416,20 @@ void player::paralyse(int str)
paralysis = 13;
}
+void player::petrify(int str)
+{
+ int &petrif(duration[DUR_PETRIFIED]);
+
+ mprf( "You %s the ability to move!",
+ petrif ? "still haven't" : "suddenly lose" );
+
+ if (str > petrif && (petrif < 3 || one_chance_in(petrif)))
+ petrif = str;
+
+ if (petrif > 13)
+ petrif = 13;
+}
+
void player::slow_down(int str)
{
::slow_player( str );
@@ -6587,7 +6608,7 @@ bool player::asleep() const
bool player::cannot_act() const
{
- return (asleep() || paralysed());
+ return (asleep() || cannot_move());
}
bool player::can_throw_rocks() const
diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc
index 337ccd6999..3dcd2930fb 100644
--- a/crawl-ref/source/religion.cc
+++ b/crawl-ref/source/religion.cc
@@ -4198,9 +4198,8 @@ static bool _beogh_followers_abandon_you()
const int xend = MIN(GXM - 1, you.x_pos + 9);
// monster check
- for ( int y = ystart; y <= yend; ++y )
- {
- for ( int x = xstart; x <= xend; ++x )
+ for (int y = ystart; y <= yend; ++y)
+ for (int x = xstart; x <= xend; ++x)
{
const unsigned short targ_monst = mgrd[x][y];
if ( targ_monst != NON_MONSTER )
@@ -4213,11 +4212,11 @@ static bool _beogh_followers_abandon_you()
if (mons_player_visible(monster)
&& !mons_is_sleeping(monster)
&& !mons_is_confused(monster)
- && !mons_is_paralysed(monster))
+ && !mons_cannot_act(monster))
{
const int hd = monster->hit_dice;
- // during penance followers get a saving throw
+ // During penance followers get a saving throw.
if (random2((you.piety-you.penance[GOD_BEOGH])/18) +
random2(you.skills[SK_INVOCATIONS]-6)
> random2(hd) + hd + random2(5))
@@ -4227,7 +4226,7 @@ static bool _beogh_followers_abandon_you()
monster->attitude = ATT_HOSTILE;
behaviour_event(monster, ME_ALERT, MHITYOU);
- // for now CREATED_FRIENDLY stays
+ // For now CREATED_FRIENDLY stays.
if (player_monster_visible(monster))
num_reconvert++; // only visible ones
@@ -4237,7 +4236,6 @@ static bool _beogh_followers_abandon_you()
}
}
}
- }
}
if (reconvert) // maybe all of them are invisible
diff --git a/crawl-ref/source/spells1.cc b/crawl-ref/source/spells1.cc
index 5f3295db81..3a804ce805 100644
--- a/crawl-ref/source/spells1.cc
+++ b/crawl-ref/source/spells1.cc
@@ -1171,7 +1171,7 @@ bool cast_revivification(int pow)
}
return (success);
-} // end cast_revivification()
+}
void cast_cure_poison(int mabil)
{
@@ -1181,7 +1181,7 @@ void cast_cure_poison(int mabil)
reduce_poison_player( 2 + random2(mabil) + random2(3) );
return;
-} // end cast_cure_poison()
+}
void purification(void)
{
@@ -1193,7 +1193,8 @@ void purification(void)
you.duration[DUR_SLOW] = 0;
you.disease = 0;
you.duration[DUR_PARALYSIS] = 0; // can't currently happen -- bwr
-} // end purification()
+ you.duration[DUR_PETRIFIED] = 0;
+}
int allowed_deaths_door_hp(void)
{
@@ -1275,7 +1276,7 @@ void antimagic()
DUR_FORESCRY, DUR_SEE_INVISIBLE, DUR_WEAPON_BRAND, DUR_SILENCE,
DUR_CONDENSATION_SHIELD, DUR_STONESKIN, DUR_BARGAIN,
DUR_INSULATION, DUR_RESIST_POISON, DUR_RESIST_FIRE, DUR_RESIST_COLD,
- DUR_SLAYING, DUR_STEALTH, DUR_MAGIC_SHIELD, DUR_SAGE
+ DUR_SLAYING, DUR_STEALTH, DUR_MAGIC_SHIELD, DUR_SAGE, DUR_PETRIFIED
};
if (!you.permanent_levitation() && !you.permanent_flight()
diff --git a/crawl-ref/source/spl-book.cc b/crawl-ref/source/spl-book.cc
index d644675641..74c20c092c 100644
--- a/crawl-ref/source/spl-book.cc
+++ b/crawl-ref/source/spl-book.cc
@@ -213,7 +213,7 @@ static spell_type spellbook_template_array[NUMBER_SPELLBOOKS][SPELLBOOK_SIZE] =
{SPELL_CONFUSING_TOUCH,
SPELL_SLOW,
SPELL_CONFUSE,
- SPELL_PARALYSE,
+ SPELL_PETRIFY,
SPELL_NO_SPELL,
SPELL_NO_SPELL,
SPELL_NO_SPELL,
@@ -550,7 +550,7 @@ static spell_type spellbook_template_array[NUMBER_SPELLBOOKS][SPELLBOOK_SIZE] =
SPELL_PROJECTED_NOISE,
SPELL_MEPHITIC_CLOUD,
SPELL_POISON_WEAPON,
- SPELL_PARALYSE,
+ SPELL_PETRIFY,
SPELL_INVISIBILITY,
SPELL_NO_SPELL,
},
diff --git a/crawl-ref/source/spl-cast.cc b/crawl-ref/source/spl-cast.cc
index 5f84cf81cc..0b989d42de 100644
--- a/crawl-ref/source/spl-cast.cc
+++ b/crawl-ref/source/spl-cast.cc
@@ -1583,6 +1583,11 @@ spret_type your_spells(spell_type spell, int powc, bool allow_fail)
return (SPRET_ABORT);
break;
+ case SPELL_PETRIFY:
+ if (!zapping(ZAP_PETRIFY, powc, beam, true))
+ return (SPRET_ABORT);
+ break;
+
case SPELL_POLYMORPH_OTHER:
// Trying is already enough, even if it fails.
did_god_conduct(DID_DELIBERATE_MUTATING, 10);
diff --git a/crawl-ref/source/spl-data.h b/crawl-ref/source/spl-data.h
index 453cb7154c..c2405ca375 100644
--- a/crawl-ref/source/spl-data.h
+++ b/crawl-ref/source/spl-data.h
@@ -375,6 +375,16 @@
},
{
+ SPELL_PETRIFY, "Petrify",
+ SPTYP_ENCHANTMENT | SPTYP_TRANSMIGRATION,
+ SPFLAG_DIR_OR_TARGET,
+ 4,
+ 200,
+ NULL,
+ true
+},
+
+{
SPELL_CONFUSE, "Confuse",
SPTYP_ENCHANTMENT,
SPFLAG_DIR_OR_TARGET,