diff --git a/engine/action/action.cpp b/engine/action/action.cpp index aab06809b0e..5cbacc2f1d2 100644 --- a/engine/action/action.cpp +++ b/engine/action/action.cpp @@ -2730,19 +2730,19 @@ void action_t::init() if ( does_periodic_damage() ) { - snapshot_flags |= STATE_MUL_TA | STATE_TGT_MUL_TA | STATE_TGT_MITG_TA | STATE_MUL_PERSISTENT | STATE_VERSATILITY; + snapshot_flags |= STATE_MUL_TA | STATE_MUL_VERSUS | 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_TGT_MITG_DA | STATE_MUL_PERSISTENT | STATE_VERSATILITY; + snapshot_flags |= STATE_MUL_DA | STATE_MUL_VERSUS | 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 | + if ( player->is_pet() && ( snapshot_flags & ( STATE_MUL_DA | STATE_MUL_TA | STATE_MUL_VERSUS | STATE_TGT_MUL_DA | STATE_TGT_MUL_TA | STATE_MUL_PERSISTENT | STATE_VERSATILITY ) ) ) { snapshot_flags |= STATE_MUL_PET | STATE_TGT_MUL_PET; @@ -2751,7 +2751,7 @@ void action_t::init() if ( data().flags( spell_attribute::SX_DISABLE_PLAYER_MULT ) || data().flags( spell_attribute::SX_DISABLE_PLAYER_HEALING_MULT ) ) { - snapshot_flags &= ~( STATE_VERSATILITY | STATE_MUL_PLAYER_DAM | STATE_MUL_PET ); + snapshot_flags &= ~( STATE_VERSATILITY | STATE_MUL_PLAYER_DAM | STATE_MUL_VERSUS | STATE_MUL_PET ); } if ( data().flags( spell_attribute::SX_DISABLE_TARGET_MULT ) ) @@ -2802,7 +2802,7 @@ void action_t::init() { if ( is_periodic_damage_effect( eff ) && eff.flags( spelleffect_attribute::EX_COMPUTE_ON_CAST ) ) { - update_flags &= ~( STATE_AP | STATE_SP | STATE_MUL_TA | STATE_VERSATILITY ); + update_flags &= ~( STATE_AP | STATE_SP | STATE_MUL_TA | STATE_MUL_VERSUS | STATE_VERSATILITY ); break; } } @@ -4341,6 +4341,9 @@ void action_t::snapshot_internal( action_state_t* state, unsigned flags, result_ if ( flags & STATE_MUL_PLAYER_DAM ) state->player_multiplier = composite_player_multiplier( state ); + if ( flags & STATE_MUL_VERSUS ) + state->versus_multiplier = composite_versus_multiplier( state->target ); + if ( flags & STATE_MUL_PERSISTENT ) state->persistent_multiplier = composite_persistent_multiplier( state ); @@ -5002,6 +5005,11 @@ double action_t::composite_rolling_ta_multiplier( const action_state_t* s ) cons return m; } +double action_t::composite_versus_multiplier( player_t* t ) const +{ + return player->composite_versus_multiplier( t ); +} + /// Persistent modifiers that are snapshot at the start of the spell cast double action_t::composite_persistent_multiplier( const action_state_t* ) const diff --git a/engine/action/action.hpp b/engine/action/action.hpp index 8e4f3e7570a..19f1e8d31d6 100644 --- a/engine/action/action.hpp +++ b/engine/action/action.hpp @@ -961,6 +961,9 @@ struct action_t : private noncopyable // Multiplier for Rolling Periodic DoTs virtual double composite_rolling_ta_multiplier( const action_state_t* ) const; + /// Multiplier for "versus" effects (e.g. extra damage vs creature type) + virtual double composite_versus_multiplier( player_t* ) const; + /// Persistent modifiers that are snapshot at the start of the spell cast virtual double composite_persistent_multiplier( const action_state_t* ) const; diff --git a/engine/action/action_state.cpp b/engine/action/action_state.cpp index 9d96f2814ee..289b7b84736 100644 --- a/engine/action/action_state.cpp +++ b/engine/action/action_state.cpp @@ -102,6 +102,7 @@ void action_state_t::copy_state( const action_state_t* o ) ta_multiplier = o->ta_multiplier; rolling_ta_multiplier = o->rolling_ta_multiplier; player_multiplier = o->player_multiplier; + versus_multiplier = o->versus_multiplier; persistent_multiplier = o->persistent_multiplier; pet_multiplier = o->pet_multiplier; @@ -142,6 +143,7 @@ action_state_t::action_state_t( action_t* a, player_t* t ) ta_multiplier( 1.0 ), rolling_ta_multiplier( 1.0 ), player_multiplier( 1.0 ), + versus_multiplier( 1.0 ), persistent_multiplier( 1.0 ), pet_multiplier( 1.0 ), target_da_multiplier( 1.0 ), @@ -220,6 +222,7 @@ std::ostringstream& action_state_t::debug_str( std::ostringstream& s ) s << " ta_mul=" << ta_multiplier; s << " rolling_ta_mul=" << rolling_ta_multiplier; s << " ply_mul=" << player_multiplier; + s << " vs_mul=" << versus_multiplier; s << " per_mul=" << persistent_multiplier; if ( action->player->is_pet() ) { @@ -307,6 +310,7 @@ std::string action_state_t::flags_to_str( unsigned flags ) concat_flag_str( str, "MUL_DA", STATE_MUL_SPELL_DA ); concat_flag_str( str, "MUL_TA", STATE_MUL_SPELL_TA ); concat_flag_str( str, "MUL_PLY", STATE_MUL_PLAYER_DAM ); + concat_flag_str( str, "MUL_VS", STATE_MUL_VERSUS ); concat_flag_str( str, "MUL_PER", STATE_MUL_PERSISTENT ); concat_flag_str( str, "MUL_PET", STATE_MUL_PET ); diff --git a/engine/action/action_state.hpp b/engine/action/action_state.hpp index a5b1f7fdab0..b4d4004ca6e 100644 --- a/engine/action/action_state.hpp +++ b/engine/action/action_state.hpp @@ -51,6 +51,7 @@ struct action_state_t : private noncopyable double ta_multiplier; double rolling_ta_multiplier; double player_multiplier; + double versus_multiplier; double persistent_multiplier; double pet_multiplier; // Owner -> pet multiplier double target_da_multiplier; @@ -88,14 +89,14 @@ struct action_state_t : private noncopyable virtual double composite_da_multiplier() const { - return da_multiplier * player_multiplier * persistent_multiplier * target_da_multiplier * versatility * - pet_multiplier * target_pet_multiplier; + return da_multiplier * player_multiplier * versus_multiplier * persistent_multiplier * target_da_multiplier * + versatility * pet_multiplier * target_pet_multiplier; } virtual double composite_ta_multiplier() const { - return ta_multiplier * player_multiplier * persistent_multiplier * target_ta_multiplier * versatility * - pet_multiplier * target_pet_multiplier; + return ta_multiplier * player_multiplier * versus_multiplier * persistent_multiplier * target_ta_multiplier * + versatility * pet_multiplier * target_pet_multiplier; } virtual double composite_rolling_ta_multiplier() const diff --git a/engine/class_modules/sc_mage.cpp b/engine/class_modules/sc_mage.cpp index 71d6656de96..4201b2b5846 100644 --- a/engine/class_modules/sc_mage.cpp +++ b/engine/class_modules/sc_mage.cpp @@ -862,6 +862,7 @@ struct mage_t final : public player_t double composite_player_critical_damage_multiplier( const action_state_t*, school_e school ) const override; double composite_player_multiplier( school_e ) const override; double composite_player_target_multiplier( player_t*, school_e ) const override; + double composite_versus_multiplier( player_t* ) const override; double composite_spell_crit_chance() const override; double composite_player_pet_damage_multiplier( const action_state_t*, bool ) const override; double composite_attribute_multiplier( attribute_e ) const override; @@ -6736,6 +6737,13 @@ double mage_t::composite_player_target_multiplier( player_t* target, school_e sc m *= 1.0 + totm->data().effectN( 2 ).percent(); } + return m; +} + +double mage_t::composite_versus_multiplier( player_t* target ) const +{ + double m = player_t::composite_versus_multiplier( target ); + // TODO: this still technically points to 458910's value (but the debuff is likely no longer used) if ( talents.molten_fury.ok() && target->health_percentage() <= talents.molten_fury->effectN( 1 ).base_value() ) m *= 1.0 + talents.molten_fury->effectN( 2 ).percent(); diff --git a/engine/player/player.cpp b/engine/player/player.cpp index fc3a9e56847..7706045d200 100644 --- a/engine/player/player.cpp +++ b/engine/player/player.cpp @@ -5563,7 +5563,7 @@ double player_t::composite_player_multiplier( school_e school ) const return m; } -double player_t::composite_player_target_multiplier( player_t* t, school_e /* school */ ) const +double player_t::composite_versus_multiplier( player_t* t ) const { double m = 1.0; @@ -5580,6 +5580,13 @@ double player_t::composite_player_target_multiplier( player_t* t, school_e /* sc } } + return m; +} + +double player_t::composite_player_target_multiplier( player_t* t, school_e /* school */ ) const +{ + double m = 1.0; + auto td = find_target_data( t ); if ( td ) { diff --git a/engine/player/player.hpp b/engine/player/player.hpp index e6c80489e47..8f7d3ba3b26 100644 --- a/engine/player/player.hpp +++ b/engine/player/player.hpp @@ -1211,6 +1211,7 @@ struct player_t : public actor_t virtual double matching_gear_multiplier( attribute_e /* attr */ ) const; /// Player-wide school based multipliers virtual double composite_player_multiplier( school_e ) const; + virtual double composite_versus_multiplier( player_t* ) const; /// Persistent multipliers that are snapshot at the beginning of the spell application/execution virtual double composite_persistent_multiplier( school_e ) const { return 1.0; } virtual double composite_player_target_multiplier( player_t*, school_e school ) const; diff --git a/engine/sc_enums.hpp b/engine/sc_enums.hpp index 78eb5761171..ffc02f1cf2b 100644 --- a/engine/sc_enums.hpp +++ b/engine/sc_enums.hpp @@ -1284,40 +1284,38 @@ enum power_e // New stuff enum snapshot_state_e { - STATE_HASTE = 0x000001, - STATE_CRIT = 0x000002, - STATE_AP = 0x000004, - STATE_SP = 0x000008, + STATE_HASTE = 0x00000001, + STATE_CRIT = 0x00000002, + STATE_AP = 0x00000004, + STATE_SP = 0x00000008, - STATE_MUL_SPELL_DA = 0x000010, // Add Percent Modifier (108): Spell Direct Amount (0) list-based multiplier - STATE_MUL_SPELL_TA = 0x000020, // Add Percent Modifier (108): Spell Periodic Amount (22) list-based multiplier - STATE_VERSATILITY = 0x000040, - STATE_MUL_PERSISTENT = 0x000080, // Persistent modifier for the few abilities that snapshot + STATE_MUL_SPELL_DA = 0x00000010, // Add Percent Modifier (108): Spell Direct Amount (0) list-based multiplier + STATE_MUL_SPELL_TA = 0x00000020, // Add Percent Modifier (108): Spell Periodic Amount (22) list-based multiplier + STATE_VERSATILITY = 0x00000040, + STATE_MUL_PERSISTENT = 0x00000080, // Persistent modifier for the few abilities that snapshot - STATE_TGT_CRIT = 0x000100, - STATE_TGT_MUL_DA = 0x000200, - STATE_TGT_MUL_TA = 0x000400, + STATE_TGT_CRIT = 0x00000100, + STATE_TGT_MUL_DA = 0x00000200, + STATE_TGT_MUL_TA = 0x00000400, - STATE_MUL_PLAYER_DAM = 0x000800, // Modify Damage Done% (79) school-based player-wide multiplier - - STATE_MUL_DA = STATE_MUL_SPELL_DA | STATE_MUL_PLAYER_DAM, - STATE_MUL_TA = STATE_MUL_SPELL_TA | STATE_MUL_PLAYER_DAM, + STATE_MUL_PLAYER_DAM = 0x00000800, // Modify Damage Done% (79) school-based player-wide multiplier // User-defined state flags - STATE_USER_1 = 0x001000, - STATE_USER_2 = 0x002000, - STATE_USER_3 = 0x004000, - STATE_USER_4 = 0x008000, + STATE_USER_1 = 0x00001000, + STATE_USER_2 = 0x00002000, + STATE_USER_3 = 0x00004000, + STATE_USER_4 = 0x00008000, - STATE_TGT_MITG_DA = 0x010000, - STATE_TGT_MITG_TA = 0x020000, - STATE_TGT_ARMOR = 0x040000, + STATE_TGT_MITG_DA = 0x00010000, + STATE_TGT_MITG_TA = 0x00020000, + STATE_TGT_ARMOR = 0x00040000, /// Multiplier from the owner to pet damage - STATE_MUL_PET = 0x100000, - STATE_TGT_MUL_PET = 0x200000, + STATE_MUL_PET = 0x00100000, + STATE_TGT_MUL_PET = 0x00200000, - STATE_ROLLING_TA = 0x400000, + STATE_ROLLING_TA = 0x00400000, + STATE_MUL_VERSUS = 0x00800000, // Modify Damage Done% vs Race (168) and Modify Damage Done Against Target With Aura (303) // User-defined target-specific state flags STATE_TGT_USER_1 = 0x10000000, @@ -1325,16 +1323,20 @@ enum snapshot_state_e STATE_TGT_USER_3 = 0x40000000, STATE_TGT_USER_4 = 0x80000000, + STATE_MUL_DA = STATE_MUL_SPELL_DA | STATE_MUL_PLAYER_DAM, + STATE_MUL_TA = STATE_MUL_SPELL_TA | STATE_MUL_PLAYER_DAM, + /** * No multiplier helper, use in action_t::init() (after parent init) by issuing snapshot_flags &= STATE_NO_MULTIPLIER * (and/or update_flags &= STATE_NO_MULTIPLIER if a dot). This disables all multipliers, including versatility, and * any/all persistent multipliers the action would use. */ STATE_NO_MULTIPLIER = ~( STATE_MUL_DA | STATE_MUL_TA | STATE_VERSATILITY | STATE_MUL_PERSISTENT | STATE_TGT_MUL_DA | - STATE_TGT_MUL_TA | STATE_TGT_ARMOR | STATE_MUL_PET | STATE_TGT_MUL_PET ), + STATE_TGT_MUL_TA | STATE_TGT_ARMOR | STATE_MUL_PET | STATE_TGT_MUL_PET | STATE_MUL_VERSUS ), /// Target-specific state variables, excluding the pet damage multiplier STATE_TARGET_NO_PET = ( STATE_TGT_CRIT | STATE_TGT_MUL_DA | STATE_TGT_MUL_TA | STATE_TGT_ARMOR | STATE_TGT_MITG_DA | - STATE_TGT_MITG_TA | STATE_TGT_USER_1 | STATE_TGT_USER_2 | STATE_TGT_USER_3 | STATE_TGT_USER_4 ), + STATE_TGT_MITG_TA | STATE_TGT_USER_1 | STATE_TGT_USER_2 | STATE_TGT_USER_3 | STATE_TGT_USER_4 | + STATE_MUL_VERSUS ), /// Target-specific state variables STATE_TARGET = STATE_TARGET_NO_PET | STATE_TGT_MUL_PET