Skip to content

Commit

Permalink
Allow Trog to berserk all species
Browse files Browse the repository at this point in the history
Currently formicids and the undead cannot go berserk (except Full+
vampires) from any means. This commit allows Trog's divine rage to
stir anger into the heart of even these species.

Most god abilities override species restrictions, for example Trog's
Hand, Bend Space, and Potion Petition working where the player might not
expect them to. There are cases where god abilities do not override
species restrictions, for example Jiyva not mutation the undead, and
Nemelex cards respecting various species restrictions.

In future, it might be worth looking at these two approaches to the
species restriction vs divine ability priority and deciding if there
should be more consistency in how they are resolved (either changing all
cases to one or the other approach, or defining an inutitive test to
tell whether an ability should override restrictions or not).
  • Loading branch information
alexjurkiewicz committed Aug 29, 2018
1 parent ef0ad6d commit 521304b
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 23 deletions.
19 changes: 6 additions & 13 deletions crawl-ref/source/ability.cc
Expand Up @@ -941,7 +941,6 @@ ability_type fixup_ability(ability_type ability)
return ability;

case ABIL_EVOKE_BERSERK:
case ABIL_TROG_BERSERK:
if (you.is_lifeless_undead(false)
|| you.species == SP_FORMICID)
{
Expand Down Expand Up @@ -1294,12 +1293,11 @@ static bool _check_ability_possible(const ability_def& abil, bool quiet = false)
}
}

if ((abil.ability == ABIL_EVOKE_BERSERK
|| abil.ability == ABIL_TROG_BERSERK)
&& !you.can_go_berserk(true, false, quiet))
{
return false;
}
if (abil.ability == ABIL_EVOKE_BERSERK)
return you.can_go_berserk(true, false, quiet);

if (abil.ability == ABIL_TROG_BERSERK)
return you.can_go_berserk(true, false, quiet, nullptr, true, true);

if ((abil.ability == ABIL_EVOKE_FLIGHT
|| abil.ability == ABIL_TRAN_BAT
Expand Down Expand Up @@ -1567,11 +1565,6 @@ static bool _check_ability_possible(const ability_def& abil, bool quiet = false)
return false;
}

case ABIL_EVOKE_BERSERK:
case ABIL_TROG_BERSERK:
return you.can_go_berserk(true, false, true)
&& (quiet || berserk_check_wielded_weapon());

case ABIL_EVOKE_FOG:
if (cloud_at(you.pos()))
{
Expand Down Expand Up @@ -2444,7 +2437,7 @@ static spret_type _do_ability(const ability_def& abil, bool fail)
case ABIL_TROG_BERSERK:
fail_check();
// Trog abilities don't use or train invocations.
you.go_berserk(true);
you.go_berserk(true, false, true);
break;

case ABIL_TROG_REGEN_MR:
Expand Down
3 changes: 2 additions & 1 deletion crawl-ref/source/actor.h
Expand Up @@ -168,7 +168,8 @@ class actor
}
virtual void attacking(actor *other, bool ranged = false) = 0;
virtual bool can_go_berserk() const = 0;
virtual bool go_berserk(bool intentional, bool potion = false) = 0;
virtual bool go_berserk(bool intentional, bool potion = false,
bool divine = false) = 0;
virtual bool berserk() const = 0;
virtual bool can_see_invisible(bool calc_unid = true) const = 0;
virtual bool invisible() const = 0;
Expand Down
2 changes: 1 addition & 1 deletion crawl-ref/source/monster.cc
Expand Up @@ -2763,7 +2763,7 @@ bool monster::go_frenzy(actor *source)
return true;
}

bool monster::go_berserk(bool intentional, bool /* potion */)
bool monster::go_berserk(bool intentional, bool /* potion */, bool /* divine */)
{
if (!can_go_berserk())
return false;
Expand Down
3 changes: 2 additions & 1 deletion crawl-ref/source/monster.h
Expand Up @@ -343,7 +343,8 @@ class monster : public actor
void attacking(actor *other, bool ranged) override;
bool can_go_frenzy() const;
bool can_go_berserk() const override;
bool go_berserk(bool intentional, bool potion = false) override;
bool go_berserk(bool intentional, bool potion = false,
bool divine = false) override;
bool go_frenzy(actor *source);
bool berserk() const override;
bool berserk_or_insane() const;
Expand Down
27 changes: 22 additions & 5 deletions crawl-ref/source/player-act.cc
Expand Up @@ -710,13 +710,15 @@ static bool _god_prevents_berserk_haste(bool intentional)
* @param potion If true, this was caused by the player quaffing !berserk;
* and we get the same additional messages as when
* intentional is true.
* @param divine If true, this was caused by divine action, and works even
* for species that can't usually go berserk.
* @return True if we went berserk, false otherwise.
*/
bool player::go_berserk(bool intentional, bool potion)
bool player::go_berserk(bool intentional, bool potion, bool divine)
{
ASSERT(!crawl_state.game_is_arena());

if (!you.can_go_berserk(intentional, potion))
if (!you.can_go_berserk(intentional, potion, false, nullptr, true, divine))
return false;

if (crawl_state.game_is_hints())
Expand Down Expand Up @@ -764,8 +766,23 @@ bool player::can_go_berserk() const
return can_go_berserk(false);
}

/*
* Check the player can go berserk, and possibly print an explanation why not.
*
* @param intentional Did the player deliberately try to go berserk? If true,
* failure will be messaged to the player.
* @param potion Did the player quaff a potion of berserk rage? If true,
* failure will be messaged to the player.
* @param quiet Suppress any player messaging.
* @param reason If the player cannot go berserk, get any failure reason as
* this string.
* @param temp Check temporary reasons why berserk could fail (already
* berserk, etc)
* @param divine Is the source of berserk a divine power?
* @returns If the player can go berserk or not.
*/
bool player::can_go_berserk(bool intentional, bool potion, bool quiet,
string *reason, bool temp) const
string *reason, bool temp, bool divine) const
{
const bool verbose = (intentional || potion) && !quiet;
string msg;
Expand All @@ -783,9 +800,9 @@ bool player::can_go_berserk(bool intentional, bool potion, bool quiet,
msg = "You are too terrified to rage.";
else if (!intentional && !potion && clarity() && temp)
msg = "You're too calm and focused to rage.";
else if (is_lifeless_undead(temp))
else if (is_lifeless_undead(temp) && !divine)
msg = "You cannot raise a blood rage in your lifeless body.";
else if (stasis())
else if (stasis() && !divine)
msg = "Your stasis prevents you from going berserk.";
else
success = true;
Expand Down
5 changes: 3 additions & 2 deletions crawl-ref/source/player.h
Expand Up @@ -675,8 +675,9 @@ class player : public actor
bool can_go_berserk() const override;
bool can_go_berserk(bool intentional, bool potion = false,
bool quiet = false, string *reason = nullptr,
bool temp = true) const;
bool go_berserk(bool intentional, bool potion = false) override;
bool temp = true, bool divine = false) const;
bool go_berserk(bool intentional, bool potion = false,
bool divine = false) override;
bool berserk() const override;
bool can_mutate() const override;
bool can_safely_mutate(bool temp = true) const override;
Expand Down

0 comments on commit 521304b

Please sign in to comment.