Skip to content
Merged
Show file tree
Hide file tree
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
18 changes: 18 additions & 0 deletions engine/class_modules/warlock/sc_warlock.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1208,6 +1208,24 @@ struct warlock_t : public parse_player_effects_t
return td;
}

template <typename T>
bool dot_or_debuff_active( T d, warlock_td_t* t )
{
if constexpr ( std::is_invocable_v<T, warlock_td_t::debuffs_t> )
{
return std::invoke( d, t->debuffs )->check() > 0;
}
else if constexpr ( std::is_invocable_v<T, warlock_td_t::dots_t> )
{
return std::invoke( d, t->dots )->is_ticking();
}
else
{
sim->error( SEVERE, "%s dot_or_debuff_active: Unsupported type passed.\n", name() );
return false;
}
}

action_t* create_action_warlock( util::string_view, util::string_view );

action_t* create_action_affliction( util::string_view, util::string_view );
Expand Down
98 changes: 60 additions & 38 deletions engine/class_modules/warlock/sc_warlock_actions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,43 @@ using namespace helpers;
const warlock_td_t* td( player_t* t ) const
{ return p()->get_target_data( t ); }

template <typename T>
target_filter_callback_t dot_or_debuff_only( T d )
{
return [ this, d ]( const action_t*, player_t* t ) {
return p()->dot_or_debuff_active( d, p()->get_target_data( t ) );
};
}

target_filter_callback_t primary_target_or( target_filter_callback_t secondary_filter )
{
return [ secondary_filter = std::move( secondary_filter ) ]( const action_t* a, player_t* t ) {
return t == a->target || secondary_filter( a, t );
};
}

target_filter_callback_t immolate_or_wither_only()
{
return [ this ]( const action_t*, player_t* t ) {
return td( t )->dots.immolate->is_ticking() || td( t )->dots.wither->is_ticking();
};
}

target_filter_callback_t corruption_or_wither_only()
{
return [ this ]( const action_t*, player_t* t ) {
return td( t )->dots.corruption->is_ticking() || td( t )->dots.wither->is_ticking();
};
}

target_filter_callback_t affliction_core_dots_only()
{
return [ this ]( const action_t*, player_t* t ) {
return td( t )->dots.corruption->is_ticking() || td( t )->dots.wither->is_ticking()
|| td( t )->dots.agony->is_ticking() || td( t )->dots.unstable_affliction->is_ticking();
};
}

void reset() override
{ action_base_t::reset(); }

Expand Down Expand Up @@ -2342,24 +2379,9 @@ using namespace helpers;
{
channeled = true;

add_child( dark_harvest_dmg );
}

std::vector<player_t*>& target_list() const override
{
target_cache.list = warlock_spell_t::target_list();

size_t i = target_cache.list.size();
while ( i > 0 )
{
i--;

if ( !td( target_cache.list[ i ] )->dots.corruption->is_ticking() && !td( target_cache.list[ i ] )->dots.wither->is_ticking()
&& !td( target_cache.list[ i ] )->dots.agony->is_ticking() && !td( target_cache.list[ i ] )->dots.unstable_affliction->is_ticking() )
target_cache.list.erase( target_cache.list.begin() + i );
}
target_filter_callback = affliction_core_dots_only();

return target_cache.list;
add_child( dark_harvest_dmg );
}

bool ready() override
Expand All @@ -2368,11 +2390,13 @@ using namespace helpers;
return false;

target_cache.is_valid = false;
return target_list().size() > 0;
return !target_list().empty();
}

void tick( dot_t* d ) override
{
target_cache.is_valid = false;

warlock_spell_t::tick( d );

const auto& tl = target_list();
Expand All @@ -2398,6 +2422,7 @@ using namespace helpers;
void execute() override
{
target_cache.is_valid = false;

warlock_spell_t::execute();
}
};
Expand All @@ -2422,9 +2447,18 @@ using namespace helpers;
struct shadow_of_nathreza_dmg_t : public warlock_spell_t
{
shadow_of_nathreza_dmg_t( warlock_t* p )
: warlock_spell_t( "shadow_of_nathreza", p, p->talents.shadow_of_nathreza_dot )
: warlock_spell_t( "Shadow of Nathreza", p, p->talents.shadow_of_nathreza_dot )
{
background = dual = true;

target_filter_callback = primary_target_or( corruption_or_wither_only() );
}

void execute() override
{
target_cache.is_valid = false;

warlock_spell_t::execute();
}
};

Expand Down Expand Up @@ -3591,9 +3625,10 @@ using namespace helpers;
add_child( fnb_action );
}

// Custom init() to combine Havoc+FnB coefficients instead of using the generic warlock_spell_t::init() Havoc multiplier
void init() override
{
spell_t::init();
action_base_t::init();

if ( affected_by.havoc )
{
Expand Down Expand Up @@ -4584,6 +4619,8 @@ using namespace helpers;
may_crit = false;
cooldown->hasted = true;

target_filter_callback = immolate_or_wither_only();

if ( !p->talents.demonfire_infusion.ok() || p->talents.channel_demonfire.ok() )
add_child( channel_demonfire_tick );

Expand All @@ -4594,22 +4631,6 @@ using namespace helpers;
}
}

std::vector<player_t*>& target_list() const override
{
target_cache.list = warlock_spell_t::target_list();

size_t i = target_cache.list.size();
while ( i > 0 )
{
i--;

if ( !td( target_cache.list[ i ] )->dots.immolate->is_ticking() && !td( target_cache.list[ i ] )->dots.wither->is_ticking() )
target_cache.list.erase( target_cache.list.begin() + i );
}

return target_cache.list;
}

void tick( dot_t* d ) override
{
target_cache.is_valid = false;
Expand All @@ -4627,10 +4648,11 @@ using namespace helpers;

bool ready() override
{
if ( p()->get_active_dots( td( target )->dots.immolate ) == 0 && p()->get_active_dots( td( target )->dots.wither ) == 0 )
if ( !warlock_spell_t::ready() )
return false;

return warlock_spell_t::ready();
target_cache.is_valid = false;
return !target_list().empty();
}
};

Expand Down