diff options
-rw-r--r-- | crawl-ref/source/acr.cc | 40 | ||||
-rw-r--r-- | crawl-ref/source/beam.cc | 61 | ||||
-rw-r--r-- | crawl-ref/source/directn.cc | 13 | ||||
-rw-r--r-- | crawl-ref/source/enum.h | 26 | ||||
-rw-r--r-- | crawl-ref/source/externs.h | 9 | ||||
-rw-r--r-- | crawl-ref/source/fight.cc | 14 | ||||
-rw-r--r-- | crawl-ref/source/ghost.cc | 12 | ||||
-rw-r--r-- | crawl-ref/source/mon-util.cc | 92 | ||||
-rw-r--r-- | crawl-ref/source/mon-util.h | 4 | ||||
-rw-r--r-- | crawl-ref/source/monstuff.cc | 15 | ||||
-rw-r--r-- | crawl-ref/source/mstuff2.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/player.cc | 45 | ||||
-rw-r--r-- | crawl-ref/source/religion.cc | 12 | ||||
-rw-r--r-- | crawl-ref/source/spells1.cc | 9 | ||||
-rw-r--r-- | crawl-ref/source/spl-book.cc | 4 | ||||
-rw-r--r-- | crawl-ref/source/spl-cast.cc | 5 | ||||
-rw-r--r-- | crawl-ref/source/spl-data.h | 10 |
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, |