Skip to content

Commit c9be07a

Browse files
authored
[Warrior] Refactor Avatar (#9858)
1 parent e583462 commit c9be07a

File tree

1 file changed

+168
-106
lines changed

1 file changed

+168
-106
lines changed

engine/class_modules/sc_warrior.cpp

+168-106
Original file line numberDiff line numberDiff line change
@@ -1148,7 +1148,7 @@ struct warrior_action_t : public parse_action_effects_t<Base>
11481148
parse_effects( p()->buff.juggernaut );
11491149
parse_effects( p()->buff.merciless_bonegrinder );
11501150
parse_effects( p()->buff.storm_of_swords );
1151-
parse_effects( p()->buff.recklessness_warlords_torment );
1151+
parse_effects( p()->buff.recklessness_warlords_torment, effect_mask_t( true ).disable( 10, 11, 12 ) );
11521152

11531153
parse_effects( p()->buff.strike_vulnerabilities ); // T29 arms
11541154
parse_effects( p()->buff.crushing_advance ); // T30 Arms 4pc
@@ -1745,6 +1745,147 @@ struct warrior_attack_t : public warrior_action_t<melee_attack_t>
17451745
}
17461746
};
17471747

1748+
// Avatar ===================================================================
1749+
1750+
struct avatar_t : public warrior_spell_t
1751+
{
1752+
timespan_t warlords_torment_duration;
1753+
timespan_t berserkers_torment_duration;
1754+
timespan_t titans_torment_duration;
1755+
timespan_t avatar_of_the_storm_duration;
1756+
timespan_t immovable_object_duration;
1757+
bool from_torment;
1758+
bool from_avatar_of_the_storm;
1759+
bool from_immovable_object;
1760+
avatar_t( warrior_t* p, util::string_view options_str, util::string_view n, const spell_data_t* spell )
1761+
: warrior_spell_t( n, p, spell ),
1762+
warlords_torment_duration( 0_s ),
1763+
berserkers_torment_duration( 0_s ),
1764+
titans_torment_duration( 0_s ),
1765+
avatar_of_the_storm_duration( 0_s ),
1766+
immovable_object_duration( 0_s ),
1767+
from_torment( false ),
1768+
from_avatar_of_the_storm( false ),
1769+
from_immovable_object( false )
1770+
{
1771+
1772+
parse_options( options_str );
1773+
harmful = false;
1774+
target = p;
1775+
}
1776+
1777+
avatar_t( util::string_view name, warrior_t* p )
1778+
: warrior_spell_t( name, p, p->talents.warrior.avatar ),
1779+
warlords_torment_duration( 0_s ),
1780+
berserkers_torment_duration( 0_s ),
1781+
titans_torment_duration( 0_s ),
1782+
avatar_of_the_storm_duration( 0_s ),
1783+
immovable_object_duration( 0_s ),
1784+
from_torment( false ),
1785+
from_avatar_of_the_storm( false ),
1786+
from_immovable_object( false )
1787+
{
1788+
background = true;
1789+
trigger_gcd = timespan_t::zero();
1790+
harmful = false;
1791+
target = p;
1792+
1793+
if ( p->talents.warrior.warlords_torment->ok() )
1794+
warlords_torment_duration = p->talents.warrior.warlords_torment->effectN( 1 ).time_value();
1795+
1796+
if ( p->talents.warrior.berserkers_torment->ok() )
1797+
berserkers_torment_duration = p->talents.warrior.berserkers_torment->effectN( 2 ).time_value();
1798+
1799+
if ( p->talents.warrior.titans_torment->ok() )
1800+
titans_torment_duration = p->talents.warrior.titans_torment->effectN( 1 ).time_value();
1801+
1802+
if ( p->talents.warrior.immovable_object->ok() )
1803+
immovable_object_duration = p->talents.warrior.immovable_object->effectN( 2 ).time_value();
1804+
1805+
if ( p->talents.mountain_thane.avatar_of_the_storm->ok() )
1806+
avatar_of_the_storm_duration = timespan_t::from_seconds( p->talents.mountain_thane.avatar_of_the_storm->effectN( 3 ).base_value() );
1807+
}
1808+
1809+
struct state_t : public action_state_t
1810+
{
1811+
using action_state_t::action_state_t;
1812+
1813+
proc_types2 cast_proc_type2() const override
1814+
{
1815+
// This spell can trigger on-cast procs even if it is backgrounded
1816+
return PROC2_CAST_GENERIC;
1817+
}
1818+
};
1819+
1820+
action_state_t* new_state() override
1821+
{
1822+
return new state_t( this, target );
1823+
}
1824+
1825+
void execute() override
1826+
{
1827+
warrior_spell_t::execute();
1828+
1829+
if ( !background ) // For Hard Cast Avatar
1830+
{
1831+
// Trigger main buff
1832+
p()->buff.avatar->extend_duration_or_trigger();
1833+
1834+
// Arms
1835+
if ( p()->talents.warrior.blademasters_torment.ok() )
1836+
p()->buff.sweeping_strikes->extend_duration_or_trigger( p()->talents.warrior.blademasters_torment->effectN( 1 ).time_value() );
1837+
1838+
if ( p()->talents.warrior.warlords_torment->ok() )
1839+
p()->buff.recklessness_warlords_torment->extend_duration_or_trigger( warlords_torment_duration );
1840+
1841+
// Fury
1842+
if ( p()->talents.warrior.berserkers_torment.ok() )
1843+
p()->active.torment_recklessness->schedule_execute();
1844+
1845+
if ( !p()->is_ptr() && p()->talents.warrior.titans_torment->ok() )
1846+
p()->active.torment_odyns_fury->schedule_execute();
1847+
1848+
// Protection
1849+
if ( p()->talents.warrior.immovable_object->ok() )
1850+
p()->buff.shield_wall->extend_duration_or_trigger( immovable_object_duration );
1851+
1852+
// Hero Talents
1853+
// Mountain Thane
1854+
if ( p()->talents.mountain_thane.avatar_of_the_storm->ok() )
1855+
{
1856+
p()->buff.thunder_blast->trigger( as<int> ( p()->talents.mountain_thane.avatar_of_the_storm->effectN( 1 ).base_value() ) );
1857+
p()->cooldown.thunder_clap->reset( true );
1858+
}
1859+
}
1860+
else // For background triggered avatar procs
1861+
{
1862+
// Fury
1863+
if ( p()->talents.warrior.berserkers_torment->ok() && from_torment )
1864+
p()->buff.avatar->extend_duration_or_trigger( berserkers_torment_duration );
1865+
1866+
if ( !p()->is_ptr() && p()->talents.warrior.titans_torment->ok() && from_torment )
1867+
p()->buff.avatar->extend_duration_or_trigger( titans_torment_duration );
1868+
1869+
// Protection
1870+
if ( p()->talents.warrior.immovable_object->ok() && from_immovable_object )
1871+
p()->buff.avatar->extend_duration_or_trigger( immovable_object_duration );
1872+
1873+
// Mountain Thane
1874+
if ( from_avatar_of_the_storm )
1875+
p()->buff.avatar->extend_duration_or_trigger( avatar_of_the_storm_duration );
1876+
}
1877+
}
1878+
1879+
bool verify_actor_spec() const override // no longer needed ?
1880+
{
1881+
// Do not check spec if Arms talent avatar is available, so that spec check on the spell (required: protection) does not fail.
1882+
if ( p()->talents.warrior.avatar->ok() && p()->specialization() == WARRIOR_ARMS )
1883+
return true;
1884+
1885+
return warrior_spell_t::verify_actor_spec();
1886+
}
1887+
};
1888+
17481889
// Reap the Storm ===========================================================
17491890

17501891
struct reap_the_storm_t : public warrior_attack_t
@@ -2360,10 +2501,12 @@ struct ground_current_t : public warrior_attack_t
23602501
struct lightning_strike_t : public warrior_attack_t
23612502
{
23622503
action_t* ground_current;
2504+
action_t* avatar;
23632505
double rage_from_thorims_might;
23642506
lightning_strike_t( util::string_view name, warrior_t* p )
23652507
: warrior_attack_t( name, p, p->spell.lightning_strike ),
23662508
ground_current( nullptr ),
2509+
avatar( nullptr ),
23672510
rage_from_thorims_might( 0 )
23682511
{
23692512
background = true;
@@ -2379,6 +2522,12 @@ struct lightning_strike_t : public warrior_attack_t
23792522
{
23802523
rage_from_thorims_might = p->talents.mountain_thane.thorims_might->effectN( 1 ).resource( RESOURCE_RAGE );
23812524
}
2525+
2526+
if ( p->talents.mountain_thane.avatar_of_the_storm->ok() )
2527+
{
2528+
avatar = new avatar_t( "avatar_avatar_of_the_storm", p );
2529+
debug_cast<avatar_t*>(avatar)->from_avatar_of_the_storm = true;
2530+
}
23822531
}
23832532

23842533
void impact( action_state_t* s ) override
@@ -2405,7 +2554,7 @@ struct lightning_strike_t : public warrior_attack_t
24052554
if ( p()->talents.mountain_thane.avatar_of_the_storm->ok() && !p()->buff.avatar->check() )
24062555
{
24072556
if ( rng().roll( p()->talents.mountain_thane.avatar_of_the_storm->effectN( 2 ).percent() ) )
2408-
p()->buff.avatar->extend_duration_or_trigger( timespan_t::from_seconds( p()->talents.mountain_thane.avatar_of_the_storm->effectN( 3 ).base_value() ) );
2557+
avatar->schedule_execute();
24092558
}
24102559
}
24112560
};
@@ -5867,10 +6016,7 @@ struct odyns_fury_t : warrior_attack_t
58676016
oh_attack2->execute();
58686017

58696018
if ( !p()->is_ptr() && p()->talents.warrior.titans_torment->ok() )
5870-
{
5871-
action_t* torment_ability = p()->active.torment_avatar;
5872-
torment_ability->schedule_execute();
5873-
}
6019+
p()->active.torment_avatar->schedule_execute();
58746020

58756021
if ( p()->tier_set.t31_fury_2pc->ok() )
58766022
{
@@ -7521,96 +7667,6 @@ struct champions_spear_t : public warrior_attack_t
75217667
// Warrior Spells
75227668
// ==========================================================================
75237669

7524-
// Avatar ===================================================================
7525-
7526-
struct avatar_t : public warrior_spell_t
7527-
{
7528-
avatar_t( warrior_t* p, util::string_view options_str, util::string_view n, const spell_data_t* spell )
7529-
: warrior_spell_t( n, p, spell )
7530-
{
7531-
7532-
parse_options( options_str );
7533-
callbacks = false;
7534-
harmful = false;
7535-
target = p;
7536-
}
7537-
7538-
void execute() override
7539-
{
7540-
warrior_spell_t::execute();
7541-
7542-
if ( p()->talents.warrior.immovable_object->ok() )
7543-
p()->buff.shield_wall->trigger( p()->talents.warrior.immovable_object->effectN( 2 ).time_value() );
7544-
7545-
p()->buff.avatar->extend_duration_or_trigger();
7546-
7547-
if ( p()->talents.warrior.berserkers_torment.ok() )
7548-
{
7549-
action_t* torment_ability = p()->active.torment_recklessness;
7550-
torment_ability->schedule_execute();
7551-
}
7552-
if ( p()->talents.warrior.blademasters_torment.ok() )
7553-
{
7554-
p()->buff.sweeping_strikes->extend_duration_or_trigger( p()->talents.warrior.blademasters_torment->effectN( 1 ).time_value() );
7555-
}
7556-
if ( !p()->is_ptr() && p()->talents.warrior.titans_torment->ok() )
7557-
{
7558-
action_t* torment_ability = p()->active.torment_odyns_fury;
7559-
torment_ability->schedule_execute();
7560-
}
7561-
7562-
if ( p()->talents.warrior.warlords_torment->ok() )
7563-
{
7564-
const timespan_t trigger_duration = p()->talents.warrior.warlords_torment->effectN( 1 ).time_value();
7565-
p()->buff.recklessness_warlords_torment->extend_duration_or_trigger( trigger_duration );
7566-
}
7567-
7568-
if ( p()->talents.mountain_thane.avatar_of_the_storm->ok() )
7569-
{
7570-
p()->buff.thunder_blast->trigger( as<int> ( p()->talents.mountain_thane.avatar_of_the_storm->effectN( 1 ).base_value() ) );
7571-
p()->cooldown.thunder_clap->reset( true );
7572-
}
7573-
}
7574-
7575-
bool verify_actor_spec() const override // no longer needed ?
7576-
{
7577-
// Do not check spec if Arms talent avatar is available, so that spec check on the spell (required: protection) does not fail.
7578-
if ( p()->talents.warrior.avatar->ok() && p()->specialization() == WARRIOR_ARMS )
7579-
return true;
7580-
7581-
return warrior_spell_t::verify_actor_spec();
7582-
}
7583-
};
7584-
7585-
// Torment Avatar ===================================================================
7586-
7587-
struct torment_avatar_t : public warrior_spell_t
7588-
{
7589-
torment_avatar_t( warrior_t* p, util::string_view options_str, util::string_view n, const spell_data_t* spell )
7590-
: warrior_spell_t( n, p, spell )
7591-
{
7592-
parse_options( options_str );
7593-
callbacks = false;
7594-
target = p;
7595-
}
7596-
7597-
void execute() override
7598-
{
7599-
warrior_spell_t::execute();
7600-
7601-
if ( p()->talents.warrior.berserkers_torment->ok() )
7602-
{
7603-
const timespan_t trigger_duration = p()->talents.warrior.berserkers_torment->effectN( 2 ).time_value();
7604-
p()->buff.avatar->extend_duration_or_trigger( trigger_duration );
7605-
}
7606-
if ( !p()->is_ptr() && p()->talents.warrior.titans_torment->ok() )
7607-
{
7608-
const timespan_t trigger_duration = p()->talents.warrior.titans_torment->effectN( 1 ).time_value();
7609-
p()->buff.avatar->extend_duration_or_trigger( trigger_duration );
7610-
}
7611-
}
7612-
};
7613-
76147670
// Battle Shout ===================================================================
76157671

76167672
struct battle_shout_t : public warrior_spell_t
@@ -7983,15 +8039,10 @@ struct recklessness_t : public warrior_spell_t
79838039
p()->buff.recklessness->extend_duration_or_trigger();
79848040

79858041
if ( p()->talents.warrior.berserkers_torment.ok() )
7986-
{
7987-
action_t* torment_ability = p()->active.torment_avatar;
7988-
torment_ability->schedule_execute();
7989-
}
8042+
p()->active.torment_avatar->schedule_execute();
79908043

79918044
if ( p()->talents.mountain_thane.snap_induction->ok() )
7992-
{
79938045
p()->buff.thunder_blast->trigger();
7994-
}
79958046
}
79968047

79978048
bool verify_actor_spec() const override
@@ -8151,12 +8202,21 @@ struct shield_block_t : public warrior_spell_t
81518202

81528203
struct shield_wall_t : public warrior_spell_t
81538204
{
8205+
action_t* avatar;
81548206
shield_wall_t( warrior_t* p, util::string_view options_str )
8155-
: warrior_spell_t( "shield_wall", p, p->talents.protection.shield_wall )
8207+
: warrior_spell_t( "shield_wall", p, p->talents.protection.shield_wall ),
8208+
avatar( nullptr )
81568209
{
81578210
parse_options( options_str );
81588211
harmful = false;
81598212
range = -1;
8213+
8214+
if ( p->talents.warrior.immovable_object->ok() )
8215+
{
8216+
avatar = new avatar_t( "avatar_immovable_object", p );
8217+
debug_cast<avatar_t*>(avatar)->from_immovable_object = true;
8218+
}
8219+
81608220
}
81618221

81628222
void execute() override
@@ -8166,7 +8226,7 @@ struct shield_wall_t : public warrior_spell_t
81668226
p()->buff.shield_wall->trigger( 1, p()->buff.shield_wall->data().effectN( 1 ).percent() );
81678227

81688228
if ( p()->talents.warrior.immovable_object->ok() )
8169-
p()->buff.avatar->trigger( p()->talents.warrior.immovable_object->effectN( 2 ).time_value() );
8229+
avatar->schedule_execute();
81708230
}
81718231
};
81728232

@@ -10105,7 +10165,8 @@ void warrior_t::create_actions()
1010510165
if ( talents.warrior.berserkers_torment->ok() )
1010610166
{
1010710167
active.torment_recklessness = new torment_recklessness_t( this, "", "recklessness_torment", find_spell( 1719 ) );
10108-
active.torment_avatar = new torment_avatar_t( this, "", "avatar_torment", find_spell( 107574 ) );
10168+
active.torment_avatar = new avatar_t( "avatar_torment", this );
10169+
debug_cast<avatar_t*>(active.torment_avatar)->from_torment = true;
1010910170
for ( action_t* action : { active.torment_recklessness, active.torment_avatar } )
1011010171
{
1011110172
action->background = true;
@@ -10114,7 +10175,8 @@ void warrior_t::create_actions()
1011410175
}
1011510176
if ( !is_ptr() && talents.warrior.titans_torment->ok() )
1011610177
{
10117-
active.torment_avatar = new torment_avatar_t( this, "", "avatar_torment", find_spell( 107574 ) );
10178+
active.torment_avatar = new avatar_t( "avatar_torment", this );
10179+
debug_cast<avatar_t*>(active.torment_avatar)->from_torment = true;
1011810180
active.torment_odyns_fury = new torment_odyns_fury_t( this, "", "odyns_fury_torment", find_spell( 385059 ) );
1011910181
for ( action_t* action : { active.torment_avatar, active.torment_odyns_fury } )
1012010182
{

0 commit comments

Comments
 (0)