summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2008-06-12 14:39:38 +0000
committerj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2008-06-12 14:39:38 +0000
commit1bff3c05ddd42eda0d5310b4d1f2671aae52815d (patch)
treef368dee0160428d811be9f91e403a5cdec83c3c8
parenta6faebe0c260af46518fa09ed6fce3992ce478a2 (diff)
downloadcrawl-ref-1bff3c05ddd42eda0d5310b4d1f2671aae52815d.tar.gz
crawl-ref-1bff3c05ddd42eda0d5310b4d1f2671aae52815d.zip
Implement the Petrify spell in a rather basic variant, and replace the
player spell "Paralyse" with it, i.e. not the wand/potion/misc. effects. Petrify is a 4th level spell of the Enchantment/Transmigrations school (a unique combination, I believe), all other values (incl. the level) were shamelessly stolen from Paralysis. Anyway, it consists of two elements (so I actually added TWO new enchantments), Petrifying and Petrified. A monster that is petrifying cannot move around but can perform actions like hitting adjacent monsters or casting spells at a slowed rate (1.5 of the normal cost). Once this sub-enchantment runs out (happens faster) the monster cannot move or act anymore, so it works like Paralysis. The damage you do during stabbing is one third of what you'd do otherwise, for both states of enchantment, and for both stabbing counts as unchivalric behaviour. It has not been implemented as a monster spell, and ghosts of characters that had it will use Paralyse instead. Consequently, the effect on the player (in self targetting) only handles the Petrified part. Numbers, esp. enchantment timeout, will need tweaking. They're currently Petrifying: cturn = 50 / _mod_speed(10, mons->speed); Petrified: cturn = std::max(8, 150 / (1 + modded_speed(mons, 5))) because I wanted the first to always run out faster than the second, but at the same time make the ratio of Petrifying/Petrified tilt in favour of the first for powerful monsters. The numbers are more or less made up, and tested with different monsters in wizard mode. Still, could be anything between too weak and overpowered, though the latter is more likely. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@5761 c06c8d41-db1a-0410-9941-cceddc491573
-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,