Skip to content
Open
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
78 changes: 31 additions & 47 deletions engine/action/action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ action_t::action_t( action_e ty, util::string_view token, player_t* p, const spe
may_dodge(),
may_parry(),
may_glance(),
may_block(),
may_block( true ),
may_crit(),
tick_may_crit(),
tick_zero(),
Expand Down Expand Up @@ -676,6 +676,8 @@ void action_t::parse_spell_data( const spell_data_t& spell_data )
treat_as_periodic = spell_data.flags( spell_attribute::SX_TREAT_AS_PERIODIC );
ignores_armor = spell_data.flags( spell_attribute::SX_TREAT_AS_PERIODIC ); // TODO: better way to parse this?
may_miss = !spell_data.flags( spell_attribute::SX_ALWAYS_HIT );
may_block = !spell_data.flags( spell_attribute::SX_NO_BLOCK ) &&
!spell_data.flags( spell_attribute::SX_NO_D_P_B );
not_a_proc = spell_data.flags( spell_attribute::SX_NOT_A_PROC );

if ( spell_data.flags( spell_attribute::SX_REFRESH_EXTENDS_DURATION ) )
Expand Down Expand Up @@ -1671,9 +1673,12 @@ double action_t::composite_total_spell_power() const
return spell_power;
}

double action_t::composite_target_armor( player_t* t ) const
double action_t::composite_target_armor( const action_state_t* s ) const
{
return player->composite_player_target_armor( t );
if ( get_school() == SCHOOL_PHYSICAL )
return player->composite_player_target_armor( s->target );
else
return 0.0;
}

double action_t::composite_target_crit_chance( player_t* t ) const
Expand Down Expand Up @@ -1782,46 +1787,23 @@ player_t* action_t::find_target_by_number( int number ) const
}

// action_t::calculate_block_result =========================================
// moved here now that we found out that spells can be blocked (Holy Shield)
// block_chance() and crit_block_chance() govern whether any given attack can
// be blocked or not (zero return if not)

block_result_e action_t::calculate_block_result( action_state_t* s ) const
{
block_result_e block_result = BLOCK_RESULT_UNBLOCKED;

// 2019-06-02: Looking at logs from Uldir, Battle of Dazar'alor and Crucible of Storms,
// It appears that non players can't block attacks or abilities anymore
// Non-player Parry and Miss seem unchanged
if ( s -> target -> is_enemy() )
// target_block_value is only set by enemy actions that damage players
if ( may_block && s->target_block_value && result_is_hit( s->result ) && player->position() == POSITION_FRONT &&
s->result != RESULT_NONE )
{
return BLOCK_RESULT_UNBLOCKED;
}

// Blocks also get a their own roll, and glances/crits can be blocked.
if ( result_is_hit( s->result ) && may_block && ( player->position() == POSITION_FRONT ) &&
!( s->result == RESULT_NONE ) )
{
double block_total = block_chance( s );
// Blocks also get a their own roll, and glances/crits can be blocked.
auto block_result = s->target->target_block_resolution( s );

if ( block_total > 0 )
{
double crit_block = crit_block_chance( s );
if ( sim->debug )
sim->print_debug( "{} block result for {} is {}", *player, *this, block_result );

// Roll once for block, then again for crit block if the block succeeds
if ( rng().roll( block_total ) )
{
if ( rng().roll( crit_block ) )
block_result = BLOCK_RESULT_CRIT_BLOCKED;
else
block_result = BLOCK_RESULT_BLOCKED;
}
}
return block_result;
}

sim->print_debug("{} result for {} is {}", *player, *this, block_result );

return block_result;
return BLOCK_RESULT_UNBLOCKED;
}

// action_t::execute ========================================================
Expand Down Expand Up @@ -2739,12 +2721,16 @@ void action_t::init()

if ( does_periodic_damage() )
{
snapshot_flags |= STATE_MUL_TA | STATE_TGT_MUL_TA | STATE_MUL_PERSISTENT | STATE_VERSATILITY;
snapshot_flags |= STATE_MUL_TA | STATE_TGT_MUL_TA | STATE_TGT_MITG_TA | STATE_MUL_PERSISTENT | STATE_VERSATILITY;
}

if ( does_direct_damage() )
{
snapshot_flags |= STATE_MUL_DA | STATE_TGT_MUL_DA | STATE_MUL_PERSISTENT | STATE_VERSATILITY;
snapshot_flags |= STATE_MUL_DA | STATE_TGT_MUL_DA | STATE_TGT_MITG_DA | STATE_MUL_PERSISTENT | STATE_VERSATILITY;

// Because schools can change during runtime, armor is flagged and not snapshot if determined to be non-physical
if ( !ignores_armor )
snapshot_flags |= STATE_TGT_ARMOR;
}

if ( player->is_pet() && ( snapshot_flags & ( STATE_MUL_DA | STATE_MUL_TA | STATE_TGT_MUL_DA | STATE_TGT_MUL_TA |
Expand All @@ -2753,9 +2739,6 @@ void action_t::init()
snapshot_flags |= STATE_MUL_PET | STATE_TGT_MUL_PET;
}

if ( school == SCHOOL_PHYSICAL )
snapshot_flags |= STATE_TGT_ARMOR;

if ( data().flags( spell_attribute::SX_DISABLE_PLAYER_MULT ) ||
data().flags( spell_attribute::SX_DISABLE_PLAYER_HEALING_MULT ) )
{
Expand Down Expand Up @@ -4368,13 +4351,13 @@ void action_t::snapshot_internal( action_state_t* state, unsigned flags, result_
state->target_crit_chance = composite_target_crit_chance( state->target ) * composite_crit_chance_multiplier();

if ( flags & STATE_TGT_MITG_DA )
state->target_mitigation_da_multiplier = composite_target_mitigation( state->target, get_school() );
state->target_mitigation_da_multiplier = composite_target_mitigation( state, true );

if ( flags & STATE_TGT_MITG_TA )
state->target_mitigation_ta_multiplier = composite_target_mitigation( state->target, get_school() );
state->target_mitigation_ta_multiplier = composite_target_mitigation( state, false );

if ( flags & STATE_TGT_ARMOR )
state->target_armor = composite_target_armor( state->target );
state->target_armor = composite_target_armor( state );
}

// action_t::composite_dot_duration =========================================
Expand Down Expand Up @@ -5012,14 +4995,15 @@ double action_t::composite_rolling_ta_multiplier( const action_state_t* s ) cons

/// Persistent modifiers that are snapshot at the start of the spell cast

double action_t::composite_persistent_multiplier(const action_state_t*) const
double action_t::composite_persistent_multiplier( const action_state_t* ) const
{
return player->composite_persistent_multiplier(get_school());
return player->composite_persistent_multiplier( get_school() );
}

double action_t::composite_target_mitigation(player_t* t, school_e s) const
double action_t::composite_target_mitigation( const action_state_t* s, bool direct ) const
{
return t->composite_mitigation_multiplier(s);
return s->target->composite_mitigation_multiplier( s, get_school(), direct ) *
s->target->composite_mitigation_from_player_multiplier( s->action->player, s, get_school(), direct );
}

double action_t::composite_player_critical_multiplier( const action_state_t* s ) const
Expand Down
12 changes: 3 additions & 9 deletions engine/action/action.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -817,12 +817,6 @@ struct action_t : private noncopyable
virtual double glance_chance( int /* delta_level */ ) const
{ return 0; }

virtual double block_chance( action_state_t* /* state */ ) const
{ return 0; }

virtual double crit_block_chance( action_state_t* /* state */ ) const
{ return 0; }

virtual double total_crit_bonus( const action_state_t* /* state */ ) const; // Check if we want to move this into the stateless system.

virtual int num_targets() const;
Expand Down Expand Up @@ -918,7 +912,7 @@ struct action_t : private noncopyable

virtual double composite_total_spell_power() const;

virtual double composite_target_armor( player_t* ) const;
virtual double composite_target_armor( const action_state_t* ) const;

virtual double composite_target_crit_chance( player_t* ) const;

Expand Down Expand Up @@ -976,9 +970,9 @@ struct action_t : private noncopyable
virtual double composite_aoe_multiplier( const action_state_t* ) const
{ return 1.0; }

virtual double composite_target_mitigation( player_t* t, school_e s ) const;
virtual double composite_target_mitigation( const action_state_t*, bool direct ) const;

virtual double composite_player_critical_multiplier( const action_state_t* s ) const;
virtual double composite_player_critical_multiplier( const action_state_t* ) const;

/// Action proc type, needed for dynamic aoe stuff and such.
virtual proc_types proc_type() const
Expand Down
18 changes: 11 additions & 7 deletions engine/action/action_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,7 @@ void action_state_t::initialize()
result = RESULT_NONE;
result_type = result_amount_type::NONE;
block_result = BLOCK_RESULT_UNBLOCKED;
result_raw = result_total = result_mitigated = result_absorbed =
result_amount = blocked_amount = self_absorb_amount = 0;
result_raw = result_total = result_mitigated = result_absorbed = result_amount = self_absorb_amount = 0;
}
/*
void action_state_t::copy_state( const action_state_t* o )
Expand Down Expand Up @@ -91,7 +90,6 @@ void action_state_t::copy_state( const action_state_t* o )
result_absorbed = o->result_absorbed;
result_crit_bonus = o->result_crit_bonus;
result_amount = o->result_amount;
blocked_amount = o->blocked_amount;
self_absorb_amount = o->self_absorb_amount;
haste = o->haste;
crit_chance = o->crit_chance;
Expand Down Expand Up @@ -133,7 +131,6 @@ action_state_t::action_state_t( action_t* a, player_t* t )
result_absorbed( 0 ),
result_crit_bonus( 0 ),
result_amount( 0 ),
blocked_amount( 0 ),
self_absorb_amount( 0 ),
haste( 1.0 ),
crit_chance( 0 ),
Expand All @@ -152,7 +149,8 @@ action_state_t::action_state_t( action_t* a, player_t* t )
target_pet_multiplier( 1.0 ),
target_mitigation_da_multiplier( 1.0 ),
target_mitigation_ta_multiplier( 1.0 ),
target_armor( 0 )
target_armor( 0 ),
target_block_value( 0 )
{
assert( target );
}
Expand Down Expand Up @@ -210,7 +208,6 @@ std::ostringstream& action_state_t::debug_str( std::ostringstream& s )
s << " absorbed_amount=" << result_absorbed;
s << " crit_bonus=" << result_crit_bonus;
s << " actual_amount=" << result_amount;
s << " only_blocked_damage=" << blocked_amount;
s << " self_absorbed_damage=" << self_absorb_amount;
s << " ap=" << attack_power;
s << " sp=" << spell_power;
Expand All @@ -234,7 +231,14 @@ std::ostringstream& action_state_t::debug_str( std::ostringstream& s )

s << " tgt_mitg_da_mul=" << target_mitigation_da_multiplier;
s << " tgt_mitg_ta_mul=" << target_mitigation_ta_multiplier;
s << " target_armor=" << target_armor;
if ( target_armor )
{
s << " target_armor=" << target_armor;
}
if ( target_block_value )
{
s << " target_block_value=" << target_block_value;
}

s.precision( ss );

Expand Down
4 changes: 2 additions & 2 deletions engine/action/action_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,10 @@ struct action_state_t : private noncopyable
block_result_e block_result;
double result_raw; // Base result value, without crit/glance etc.
double result_total; // Total unmitigated result, including crit bonus, glance penalty, etc.
double result_mitigated; // Result after mitigation / resist. *NOTENOTENOTE* Only filled after action_t::impact() call
double result_mitigated; // Result after mitigation / resist.
double result_absorbed; // Result after absorption. *NOTENOTENOTE* Only filled after action_t::impact() call
double result_crit_bonus; // Crit bonus multiplier used in the final calculation
double result_amount; // Final (actual) result
double blocked_amount; // The amount of damage reduced via block or critical block
double self_absorb_amount; // The amount of damage reduced via personal absorbs such as shield_barrier.
// Snapshotted stats during execution
double haste;
Expand All @@ -61,6 +60,7 @@ struct action_state_t : private noncopyable
double target_mitigation_da_multiplier;
double target_mitigation_ta_multiplier;
double target_armor;
double target_block_value; // Only players can block, so this is only set in enemy_action_t::snapshot_internal()

static void release( action_state_t*& s );
static std::string flags_to_str( unsigned flags );
Expand Down
32 changes: 3 additions & 29 deletions engine/action/attack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ attack_t::attack_t( util::string_view n, player_t* p, const spell_data_t* s )
{
may_dodge = !data().flags( spell_attribute::SX_NO_DODGE );
may_parry = !data().flags( spell_attribute::SX_NO_PARRY );
may_block = !data().flags( spell_attribute::SX_NO_BLOCK );
}
}

Expand Down Expand Up @@ -123,34 +122,6 @@ double attack_t::dodge_chance( double expertise, player_t* t ) const
return dodge;
}

double attack_t::block_chance( action_state_t* s ) const
{
if ( s->target->is_enemy() && sim->auto_attacks_always_land && !special )
{
return 0.0;
}

// cache.block() contains the target's block chance (3.0 base for bosses, more for shield tanks)
double block = s->target->cache.block();

// add or subtract 1.5% per level difference -- Level difference does not seem to matter anymore.
// block += ( s->target->level() - player->level() ) * 0.015;

return block;
}

double attack_t::crit_block_chance( action_state_t* s ) const
{
// This function is probably unnecessary, as we could just query
// cache.crit_block() directly.
// I'm leaving it for consistency with *_chance() and in case future changes
// modify crit block mechanics

// Crit Block does not suffer from level-based suppression, return cached
// value directly
return s->target->cache.crit_block();
}

double attack_t::bonus_da( const action_state_t* s ) const
{
double da = action_t::bonus_da( s );
Expand Down Expand Up @@ -343,6 +314,9 @@ result_e attack_t::calculate_result( action_state_t* s ) const
result = RESULT_CRIT;
}

if ( sim->debug )
sim->print_debug( "{} result for attack {} is {}.", *player, *this, result );

return result;
}

Expand Down
2 changes: 0 additions & 2 deletions engine/action/attack.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ struct attack_t : public action_t

double miss_chance( double hit, player_t* t ) const override;
double dodge_chance( double /* expertise */, player_t* t ) const override;
double block_chance( action_state_t* s ) const override;
double crit_block_chance( action_state_t* s ) const override;

double bonus_da( const action_state_t* ) const override;
double action_multiplier() const override;
Expand Down
8 changes: 8 additions & 0 deletions engine/action/heal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ void heal_t::init()
{
base_t::init();

snapshot_flags &= ~( STATE_TGT_MITG_DA | STATE_TGT_MITG_TA );
update_flags &= ~( STATE_TGT_MITG_DA | STATE_TGT_MITG_TA );

record_healing = player->record_healing();
}

Expand All @@ -96,6 +99,11 @@ double heal_t::composite_ta_multiplier( const action_state_t* s ) const
return m;
}

double heal_t::composite_target_multiplier( player_t* t ) const
{
return t->composite_player_healing_received_multiplier();
}

double heal_t::composite_player_critical_multiplier( const action_state_t* ) const
{
return player->composite_player_critical_healing_multiplier();
Expand Down
1 change: 1 addition & 0 deletions engine/action/heal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ struct heal_t : public spell_base_t
int num_targets() const override;
double composite_da_multiplier( const action_state_t* s ) const override;
double composite_ta_multiplier( const action_state_t* s ) const override;
double composite_target_multiplier( player_t* ) const override;
double composite_player_critical_multiplier( const action_state_t* /* s */ ) const override;
double composite_versatility( const action_state_t* state ) const override;
double total_crit_bonus( const action_state_t* ) const override;
Expand Down
Loading