Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 136 additions & 5 deletions engine/class_modules/sc_mage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -276,11 +276,13 @@ struct mage_t final : public player_t
buff_t* arcane_salvo;
buff_t* arcane_surge;
buff_t* clearcasting;
buff_t* cumulative_power;
buff_t* enlightened;
buff_t* evocation;
buff_t* intuition;
buff_t* overpowered_missiles;
buff_t* presence_of_mind;
buff_t* prismatic_bolt;


// Fire
Expand Down Expand Up @@ -581,6 +583,7 @@ struct mage_t final : public player_t

// Row 8
player_talent_t touch_of_the_archmage_1;
player_talent_t prismatic_bolt_1;
player_talent_t evocation;
player_talent_t mana_adept;
player_talent_t enlightened;
Expand All @@ -589,12 +592,14 @@ struct mage_t final : public player_t

// Row 9
player_talent_t touch_of_the_archmage_2;
player_talent_t prismatic_bolt_2;
player_talent_t prodigious_savant;
player_talent_t eureka;
player_talent_t arcane_singularity;

// Row 10
player_talent_t touch_of_the_archmage_3;
player_talent_t prismatic_bolt_3;
player_talent_t charged_missiles;
player_talent_t high_voltage;
player_talent_t overflowing_insight;
Expand Down Expand Up @@ -2811,6 +2816,14 @@ struct arcane_barrage_t final : public arcane_mage_spell_t
p()->buffs.intuition->expire();

int salvo = p()->buffs.arcane_salvo->check();

if ( p()->talents.prismatic_bolt_1.ok() && salvo > 0 )
{
double chance = salvo * p()->talents.prismatic_bolt_1->effectN( 1 ).percent();
if ( rng().roll( chance ) )
p()->buffs.prismatic_bolt->trigger();
}

if ( p()->buffs.arcane_soul->check() )
{
p()->trigger_clearcasting( 1.0, true, true );
Expand Down Expand Up @@ -2927,13 +2940,16 @@ struct arcane_blast_t final : public arcane_mage_spell_t

if ( p()->buffs.presence_of_mind->up() )
p()->buffs.presence_of_mind->decrement();

p()->buffs.cumulative_power->expire();
}

double action_multiplier() const override
{
double am = arcane_mage_spell_t::action_multiplier();

am *= arcane_charge_multiplier();
am *= 1.0 + p()->buffs.cumulative_power->check_stack_value();

return am;
}
Expand All @@ -2945,6 +2961,73 @@ struct arcane_blast_t final : public arcane_mage_spell_t

return arcane_mage_spell_t::execute_time();
}

bool ready() override
{
// Arcane Blast is upgraded into Prismatic Bolt while the buff is up.
if ( p()->buffs.prismatic_bolt->check() )
return false;

return arcane_mage_spell_t::ready();
}
};

// The aoe part of Prismatic Bolt is its own spell (1295939)
struct prismatic_bolt_aoe_t final : public arcane_mage_spell_t
{
prismatic_bolt_aoe_t( std::string_view n, mage_t* p ) :
arcane_mage_spell_t( n, p, p->find_spell( 1295939 ) )
{
background = true;
aoe = -1;
radius = 8;
reduced_aoe_targets = p->find_spell( 1295924 )->effectN( 4 ).base_value();
target_filter_callback = secondary_targets_only();
}
};

struct prismatic_bolt_t final : public arcane_mage_spell_t
{
prismatic_bolt_t( std::string_view n, mage_t* p, std::string_view options_str ) :
arcane_mage_spell_t( n, p, p->find_spell( 1295924 ) )
{
parse_options( options_str );
triggers.clearcasting = triggers.spellfire_sphere = triggers.mana_cascade = true;

impact_action = get_action<prismatic_bolt_aoe_t>( "prismatic_bolt_aoe", p );
add_child( impact_action );
}

bool ready() override
{
if ( !p()->buffs.prismatic_bolt->check() )
return false;

return arcane_mage_spell_t::ready();
}

void execute() override
{
arcane_mage_spell_t::execute();

p()->buffs.prismatic_bolt->expire();
p()->buffs.cumulative_power->expire();

p()->trigger_arcane_charge( as<int>( data().effectN( 3 ).base_value() ) );
p()->trigger_arcane_salvo( salvo_source, as<int>( p()->talents.expanded_mind->effectN( 3 ).base_value() ) );

if ( p()->talents.prismatic_bolt_2.ok() )
p()->trigger_clearcasting( p()->talents.prismatic_bolt_2->effectN( 1 ).percent() );
}

double action_multiplier() const override
{
double am = arcane_mage_spell_t::action_multiplier();

am *= 1.0 + p()->buffs.cumulative_power->check_stack_value();

return am;
}
};

struct arcane_explosion_t final : public arcane_mage_spell_t
Expand Down Expand Up @@ -2976,7 +3059,10 @@ struct arcane_pulse_t final : public arcane_mage_spell_t
parse_options( options_str );
aoe = -1;
triggers.clearcasting = triggers.spellfire_sphere = triggers.mana_cascade = !echo;
reduced_aoe_targets = data().effectN( 3 ).base_value();
// With the 12.1 PTR, pulse went from having 3 effects to 2, removing 'energize (1240466)'
// The reduced-AoE-targets threshold effect went from effect #3 (live 12.0.7) to effect #2 (12.1 PTR)
// TODO: Remove check when 12.1 goes live
reduced_aoe_targets = data().effectN( p->dbc->wowv() >= wowv_t{ 12, 1, 0 } ? 2 : 3 ).base_value();

if ( echo )
{
Expand All @@ -2997,19 +3083,31 @@ struct arcane_pulse_t final : public arcane_mage_spell_t
{
double c = arcane_mage_spell_t::cost_pct_multiplier();

c *= 1.0 + p()->buffs.arcane_charge->check() * p()->buffs.arcane_charge->data().effectN( 5 ).percent();
// TODO: Remove when 12.1 goes live
if ( p()->dbc->wowv() < wowv_t{ 12, 1, 0 } )
{
c *= 1.0 + p()->buffs.arcane_charge->check() * p()->buffs.arcane_charge->data().effectN( 5 ).percent();
}

return c;
}

void execute() override
{
p()->benefits.arcane_charge.arcane_pulse->update();
// TODO: Remove check when 12.1 goes live
if ( p()->dbc->wowv() < wowv_t{ 12, 1, 0 } )
{
p()->benefits.arcane_charge.arcane_pulse->update();
}

// TODO: radius increase?
arcane_mage_spell_t::execute();

p()->trigger_arcane_charge( as<int>( data().effectN( 2 ).base_value() ) );
// TODO: Remove check when 12.1 goes live -- in 12.1, pulse generates charges per enemy hit in impact() instead.
if ( p()->dbc->wowv() < wowv_t{ 12, 1, 0 } )
{
p()->trigger_arcane_charge( as<int>( data().effectN( 2 ).base_value() ) );
}

// In-game, Arcane Pulse internally sets a target it hits as a "Background Target",
// resulting in all of Pulse's background effects to be directed towards them.
Expand All @@ -3020,18 +3118,39 @@ struct arcane_pulse_t final : public arcane_mage_spell_t
p()->trigger_arcane_salvo( salvo_source, as<int>( p()->talents.expanded_mind->effectN( 1 ).base_value() ) );
effect_target = rng().range( target_list() );
p()->trigger_splinter( effect_target );
p()->buffs.cumulative_power->expire(); // does not affect the reverb
}

if ( arcane_pulse_echo && rng().roll( p()->talents.reverberate->effectN( 1 ).percent() ) )
make_event( *sim, 500_ms, [ this, t = effect_target ] { arcane_pulse_echo->execute_on_target( t ); } );
}

void impact( action_state_t* s ) override
{
arcane_mage_spell_t::impact( s );

// 12.1: Arcane Pulse now generates 1 arcane charge per enemy hit
// TODO: Remove check when 12.1 goes live
if ( p()->dbc->wowv() >= wowv_t{ 12, 1, 0 } && result_is_hit( s->result ) )
p()->trigger_arcane_charge( 1 );
}

double action_multiplier() const override
{
double am = arcane_mage_spell_t::action_multiplier();

am *= arcane_charge_multiplier();
// TODO: Remove check when 12.1 goes live
if ( p()->dbc->wowv() < wowv_t{ 12, 1, 0 } )
{
am *= arcane_charge_multiplier();
}

// TODO: Remove check when 12.1 goes live
if ( p()->dbc->wowv() >= wowv_t{ 12, 1, 0 } )
{
am *= 1.0 + p()->buffs.cumulative_power->check_stack_value();
}

return am;
}
};
Expand Down Expand Up @@ -3146,6 +3265,9 @@ struct arcane_missiles_tick_t final : public custom_state_spell_t<arcane_mage_sp
{
custom_state_spell_t::execute();

if ( p()->sets->has_set_bonus( MAGE_ARCANE, MID2, B4 ) )
p()->buffs.cumulative_power->trigger();

p()->trigger_arcane_salvo( salvo_source );
p()->trigger_arcane_salvo( crystal_source, as<int>( p()->talents.focusing_crystal->effectN( 2 ).base_value() ),
p()->talents.focusing_crystal->effectN( 1 ).percent() );
Expand Down Expand Up @@ -5653,6 +5775,7 @@ action_t* mage_t::create_action( std::string_view name, std::string_view options
if ( name == "arcane_surge" ) return new arcane_surge_t( name, this, options_str );
if ( name == "evocation" ) return new evocation_t( name, this, options_str );
if ( name == "presence_of_mind" ) return new presence_of_mind_t( name, this, options_str );
if ( name == "prismatic_bolt" ) return new prismatic_bolt_t( name, this, options_str );
if ( name == "touch_of_the_magi" ) return new touch_of_the_magi_t( name, this, options_str );

// Fire
Expand Down Expand Up @@ -6020,18 +6143,21 @@ void mage_t::init_spells()
talents.impetus = find_talent_spell( talent_tree::SPECIALIZATION, "Impetus" );
// Row 8
talents.touch_of_the_archmage_1 = find_talent_spell( talent_tree::SPECIALIZATION, 1257942 );
talents.prismatic_bolt_1 = find_talent_spell( talent_tree::SPECIALIZATION, 1295923 );
talents.evocation = find_talent_spell( talent_tree::SPECIALIZATION, "Evocation" );
talents.mana_adept = find_talent_spell( talent_tree::SPECIALIZATION, "Mana Adept" );
talents.enlightened = find_talent_spell( talent_tree::SPECIALIZATION, "Enlightened" );
talents.focusing_crystal = find_talent_spell( talent_tree::SPECIALIZATION, "Focusing Crystal" );
talents.illuminated_thoughts = find_talent_spell( talent_tree::SPECIALIZATION, "Illuminated Thoughts" );
// Row 9
talents.touch_of_the_archmage_2 = find_talent_spell( talent_tree::SPECIALIZATION, 1257947 );
talents.prismatic_bolt_2 = find_talent_spell( talent_tree::SPECIALIZATION, 1295944 );
talents.prodigious_savant = find_talent_spell( talent_tree::SPECIALIZATION, "Prodigious Savant" );
talents.eureka = find_talent_spell( talent_tree::SPECIALIZATION, "Eureka" );
talents.arcane_singularity = find_talent_spell( talent_tree::SPECIALIZATION, "Arcane Singularity" );
// Row 10
talents.touch_of_the_archmage_3 = find_talent_spell( talent_tree::SPECIALIZATION, 1257950 );
talents.prismatic_bolt_3 = find_talent_spell( talent_tree::SPECIALIZATION, 1295946 );
talents.charged_missiles = find_talent_spell( talent_tree::SPECIALIZATION, "Charged Missiles" );
talents.high_voltage = find_talent_spell( talent_tree::SPECIALIZATION, "High Voltage" );
talents.overflowing_insight = find_talent_spell( talent_tree::SPECIALIZATION, "Overflowing Insight" );
Expand Down Expand Up @@ -6316,6 +6442,9 @@ void mage_t::create_buffs()
buffs.clearcasting = make_buff( this, "clearcasting", find_spell( 263725 ) )
->set_default_value_from_effect( 1 )
->set_chance( spec.clearcasting->ok() ) ;
buffs.cumulative_power = make_buff( this, "cumulative_power", find_spell( 1296930 ) )
->set_default_value_from_effect( 1 )
->set_chance( sets->has_set_bonus( MAGE_ARCANE, MID2, B4 ) );
buffs.enlightened = make_buff( this, "enlightened", find_spell( 1217242 ) )
->set_schools_from_effect( 4 )
->add_invalidate( CACHE_PLAYER_DAMAGE_MULTIPLIER )
Expand All @@ -6338,6 +6467,8 @@ void mage_t::create_buffs()
->set_cooldown( 0_ms )
->set_stack_change_callback( [ this ] ( buff_t*, int, int cur )
{ if ( cur == 0 ) cooldowns.presence_of_mind->start( cooldowns.presence_of_mind->action ); } );
buffs.prismatic_bolt = make_buff( this, "prismatic_bolt", find_spell( 1295942 ) )
->set_chance( talents.prismatic_bolt_1.ok() );


// Fire
Expand Down
Loading