From 99fa93ad19e9b00b1c150899887e54eef5e47e0c Mon Sep 17 00:00:00 2001 From: sanguinerarogue Date: Sat, 7 Sep 2024 20:38:50 -0600 Subject: [PATCH 1/7] Melee 2Pc Bonus Work --- proto/common.proto | 5 +++-- sim/core/debuffs.go | 18 ++++++++++++++++++ ui/core/components/inputs/buffs_debuffs.ts | 9 +++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/proto/common.proto b/proto/common.proto index 0f66a8b871..718256168d 100644 --- a/proto/common.proto +++ b/proto/common.proto @@ -738,7 +738,7 @@ message Consumes { bool bogling_root = 19 [deprecated=true]; } -// NextIndex: 40 +// NextIndex: 41 message Debuffs { bool judgement_of_wisdom = 1; bool judgement_of_light = 2; @@ -795,7 +795,8 @@ message Debuffs { int32 ancient_corrosive_poison = 24; // between 0 and 100, represents average uptime percentage bool mekkatorque_fist_debuff = 29; bool serpents_striker_fist_debuff = 30; - bool improved_faerie_fire = 36; // Provided by Tier 1 Balance set bonus + bool improved_faerie_fire = 36; // Provided by Tier 1 Feral set bonus + bool melee_hunter_bonus = 40; // Provided by Tier 1 Melee Hunter set bonus TristateEffect curse_of_elements_new = 31 [deprecated=true]; TristateEffect curse_of_shadow_new = 32 [deprecated=true]; diff --git a/sim/core/debuffs.go b/sim/core/debuffs.go index ee7d642f1a..0ccdd7e4ef 100644 --- a/sim/core/debuffs.go +++ b/sim/core/debuffs.go @@ -219,6 +219,10 @@ func applyDebuffEffects(target *Unit, targetIdx int, debuffs *proto.Debuffs, rai MakePermanent(ImprovedFaerieFireAura(target)) } + if debuffs.MeleeHunterBonus { + MakePermanent(MeleeHunterBonusAura(target)) + } + if debuffs.CurseOfWeakness != proto.TristateEffect_TristateEffectMissing { MakePermanent(CurseOfWeaknessAura(target, GetTristateValueInt32(debuffs.CurseOfWeakness, 0, 3), level)) } @@ -1128,6 +1132,20 @@ func ImprovedFaerieFireAura(target *Unit) *Aura { }) } +func MeleeHunterBonusAura(target *Unit) *Aura { + return target.GetOrRegisterAura(Aura{ + Label: "S03 - Item - T1 - Hunter - Melee 2P Bonus", + ActionID: ActionID{SpellID: 456389}, + Duration: time.Second * 30, + OnGain: func(aura *Aura, sim *Simulation) { + aura.Unit.AddStatDynamic(sim, stats.Dodge, -1) + }, + OnExpire: func(aura *Aura, sim *Simulation) { + aura.Unit.AddStatDynamic(sim, stats.Dodge, 1) + }, + }) +} + func CurseOfWeaknessAura(target *Unit, points int32, playerLevel int32) *Aura { spellID := map[int32]int32{ 25: 6205, diff --git a/ui/core/components/inputs/buffs_debuffs.ts b/ui/core/components/inputs/buffs_debuffs.ts index ec6720537a..cc3586ae6d 100644 --- a/ui/core/components/inputs/buffs_debuffs.ts +++ b/ui/core/components/inputs/buffs_debuffs.ts @@ -917,6 +917,10 @@ export const ImprovedFaerieFire = makeBooleanDebuffInput({ actionId: player => player.getMatchingSpellActionId([{ id: 455864, minLevel: 60 }]), fieldName: 'improvedFaerieFire', }); +export const MeleeHunter2pcT1Bonus = makeBooleanDebuffInput({ + actionId: player => player.getMatchingSpellActionId([{ id: 456389, minLevel: 60 }]), + fieldName: 'meleeHunterBonus', +}); export const MekkatorqueFistDebuff = makeBooleanDebuffInput({ actionId: player => player.getMatchingItemActionId([{ id: 213409, minLevel: 40, maxLevel: 45 }]), fieldName: 'mekkatorqueFistDebuff', @@ -1325,6 +1329,11 @@ export const MISC_DEBUFFS_CONFIG = [ picker: IconPicker, stats: [], }, + { + config: MeleeHunter2pcT1Bonus, + picker: IconPicker, + stats: [], + }, { config: MekkatorqueFistDebuff, picker: IconPicker, From 7676c8112d53260781126b5ac144d52764b192d7 Mon Sep 17 00:00:00 2001 From: sanguinerarogue Date: Sun, 8 Sep 2024 18:18:39 -0600 Subject: [PATCH 2/7] . --- sim/core/debuffs.go | 6 ++++-- sim/core/spell_outcome.go | 23 ++++++++++++----------- sim/hunter/item_sets_pve.go | 5 +++-- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/sim/core/debuffs.go b/sim/core/debuffs.go index 0ccdd7e4ef..dc7655580b 100644 --- a/sim/core/debuffs.go +++ b/sim/core/debuffs.go @@ -1138,10 +1138,12 @@ func MeleeHunterBonusAura(target *Unit) *Aura { ActionID: ActionID{SpellID: 456389}, Duration: time.Second * 30, OnGain: func(aura *Aura, sim *Simulation) { - aura.Unit.AddStatDynamic(sim, stats.Dodge, -1) + // target.BaseDodgeChance -= 1 + // target.AttackTables[target.CurrentTarget.UnitIndex][proto.CastType_CastTypeMainHand].BaseDodgeChance -= 1 }, OnExpire: func(aura *Aura, sim *Simulation) { - aura.Unit.AddStatDynamic(sim, stats.Dodge, 1) + // target.BaseDodgeChance += 1 + // target.AttackTables[target.CurrentTarget.UnitIndex][proto.CastType_CastTypeMainHand].BaseDodgeChance += 1 }, }) } diff --git a/sim/core/spell_outcome.go b/sim/core/spell_outcome.go index 9e04596b19..e8e1f3bdcc 100644 --- a/sim/core/spell_outcome.go +++ b/sim/core/spell_outcome.go @@ -252,7 +252,7 @@ func (spell *Spell) outcomeMeleeWhite(sim *Simulation, result *SpellResult, atta if unit.PseudoStats.InFrontOfTarget { if !result.applyAttackTableMiss(spell, attackTable, roll, &chance) && - !result.applyAttackTableDodge(spell, attackTable, roll, &chance) && + !result.applyAttackTableDodge(spell, unit, attackTable, roll, &chance) && !result.applyAttackTableParry(spell, attackTable, roll, &chance) && !result.applyAttackTableGlance(spell, attackTable, roll, &chance, glanceRoll) && !result.applyAttackTableBlock(spell, attackTable, roll, &chance) && @@ -261,7 +261,7 @@ func (spell *Spell) outcomeMeleeWhite(sim *Simulation, result *SpellResult, atta } } else { if !result.applyAttackTableMiss(spell, attackTable, roll, &chance) && - !result.applyAttackTableDodge(spell, attackTable, roll, &chance) && + !result.applyAttackTableDodge(spell, unit, attackTable, roll, &chance) && !result.applyAttackTableGlance(spell, attackTable, roll, &chance, glanceRoll) && !result.applyAttackTableCrit(spell, attackTable, roll, &chance, countHits) { result.applyAttackTableHit(spell, countHits) @@ -282,13 +282,13 @@ func (spell *Spell) outcomeMeleeSpecialHit(sim *Simulation, result *SpellResult, if unit.PseudoStats.InFrontOfTarget { if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance) && - !result.applyAttackTableDodge(spell, attackTable, roll, &chance) && + !result.applyAttackTableDodge(spell, unit, attackTable, roll, &chance) && !result.applyAttackTableParry(spell, attackTable, roll, &chance) { result.applyAttackTableHit(spell, countHits) } } else { if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance) && - !result.applyAttackTableDodge(spell, attackTable, roll, &chance) { + !result.applyAttackTableDodge(spell, unit, attackTable, roll, &chance) { result.applyAttackTableHit(spell, countHits) } } @@ -307,7 +307,7 @@ func (spell *Spell) outcomeMeleeSpecialHitAndCrit(sim *Simulation, result *Spell if unit.PseudoStats.InFrontOfTarget { if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance) && - !result.applyAttackTableDodge(spell, attackTable, roll, &chance) && + !result.applyAttackTableDodge(spell, unit, attackTable, roll, &chance) && !result.applyAttackTableParry(spell, attackTable, roll, &chance) { if result.applyAttackTableCritSeparateRoll(sim, spell, attackTable, countHits) { result.applyAttackTableBlock(spell, attackTable, roll, &chance) @@ -319,7 +319,7 @@ func (spell *Spell) outcomeMeleeSpecialHitAndCrit(sim *Simulation, result *Spell } } else { if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance) && - !result.applyAttackTableDodge(spell, attackTable, roll, &chance) && + !result.applyAttackTableDodge(spell, unit, attackTable, roll, &chance) && !result.applyAttackTableCritSeparateRoll(sim, spell, attackTable, countHits) { result.applyAttackTableHit(spell, countHits) } @@ -338,9 +338,10 @@ func (spell *Spell) outcomeMeleeWeaponSpecialHitAndCrit(sim *Simulation, result if spell.Unit.PseudoStats.InFrontOfTarget { roll := sim.RandomFloat("White Hit Table") chance := 0.0 + unit := spell.Unit if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance) && - !result.applyAttackTableDodge(spell, attackTable, roll, &chance) && + !result.applyAttackTableDodge(spell, unit, attackTable, roll, &chance) && !result.applyAttackTableParry(spell, attackTable, roll, &chance) && !result.applyAttackTableBlock(spell, attackTable, roll, &chance) && !result.applyAttackTableCritSeparateRoll(sim, spell, attackTable, countHits) { @@ -377,14 +378,14 @@ func (spell *Spell) outcomeMeleeWeaponSpecialNoCrit(sim *Simulation, result *Spe if unit.PseudoStats.InFrontOfTarget { if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance) && - !result.applyAttackTableDodge(spell, attackTable, roll, &chance) && + !result.applyAttackTableDodge(spell, unit, attackTable, roll, &chance) && !result.applyAttackTableParry(spell, attackTable, roll, &chance) && !result.applyAttackTableBlock(spell, attackTable, roll, &chance) { result.applyAttackTableHit(spell, countHits) } } else { if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance) && - !result.applyAttackTableDodge(spell, attackTable, roll, &chance) { + !result.applyAttackTableDodge(spell, unit, attackTable, roll, &chance) { result.applyAttackTableHit(spell, countHits) } } @@ -684,8 +685,8 @@ func (result *SpellResult) applyAttackTableBlock(spell *Spell, attackTable *Atta return false } -func (result *SpellResult) applyAttackTableDodge(spell *Spell, attackTable *AttackTable, roll float64, chance *float64) bool { - *chance += max(0, attackTable.BaseDodgeChance) +func (result *SpellResult) applyAttackTableDodge(spell *Spell, unit *Unit, attackTable *AttackTable, roll float64, chance *float64) bool { + *chance += max(0, attackTable.BaseDodgeChance-unit.PseudoStats.DodgeReduction) if roll < *chance { result.Outcome = OutcomeDodge diff --git a/sim/hunter/item_sets_pve.go b/sim/hunter/item_sets_pve.go index 44edf0ff1e..c05a7b19c1 100644 --- a/sim/hunter/item_sets_pve.go +++ b/sim/hunter/item_sets_pve.go @@ -80,6 +80,7 @@ var ItemSetGiantstalkerProwess = core.NewItemSet(core.ItemSet{ // Your Mongoose Bite also reduces its target's chance to Dodge by 1% and increases your chance to hit by 1% for 30 sec. 2: func(agent core.Agent) { hunter := agent.(HunterAgent).GetHunter() + hunter.PseudoStats.DodgeReduction += .01 debuffAuras := hunter.NewEnemyAuraArray(func(target *core.Unit, level int32) *core.Aura { return target.RegisterAura(core.Aura{ @@ -87,12 +88,12 @@ var ItemSetGiantstalkerProwess = core.NewItemSet(core.ItemSet{ ActionID: core.ActionID{SpellID: 456389}, Duration: time.Second * 30, OnGain: func(aura *core.Aura, sim *core.Simulation) { - aura.Unit.AddStatDynamic(sim, stats.Dodge, -1) + aura.Unit.PseudoStats.BonusMeleeHitRatingTaken += 1 * core.MeleeHitRatingPerHitChance aura.Unit.PseudoStats.BonusSpellHitRatingTaken += 1 * core.SpellHitRatingPerHitChance }, OnExpire: func(aura *core.Aura, sim *core.Simulation) { - aura.Unit.AddStatDynamic(sim, stats.Dodge, 1) + aura.Unit.PseudoStats.BonusMeleeHitRatingTaken += 1 * core.MeleeHitRatingPerHitChance aura.Unit.PseudoStats.BonusSpellHitRatingTaken += 1 * core.SpellHitRatingPerHitChance }, From c17656b6e45f736728dff9eb2128a531c0f8335f Mon Sep 17 00:00:00 2001 From: sanguinerarogue Date: Mon, 23 Sep 2024 12:07:19 -0600 Subject: [PATCH 3/7] resolving conflicts with hitcount --- sim/core/spell_outcome.go | 62 +-------------------------------------- 1 file changed, 1 insertion(+), 61 deletions(-) diff --git a/sim/core/spell_outcome.go b/sim/core/spell_outcome.go index 83061d4e0b..3d637fca52 100644 --- a/sim/core/spell_outcome.go +++ b/sim/core/spell_outcome.go @@ -258,32 +258,18 @@ func (spell *Spell) outcomeMeleeWhite(sim *Simulation, result *SpellResult, atta chance := 0.0 if unit.PseudoStats.InFrontOfTarget { -<<<<<<< HEAD - if !result.applyAttackTableMiss(spell, attackTable, roll, &chance) && - !result.applyAttackTableDodge(spell, unit, attackTable, roll, &chance) && - !result.applyAttackTableParry(spell, attackTable, roll, &chance) && - !result.applyAttackTableGlance(spell, attackTable, roll, &chance, glanceRoll) && - !result.applyAttackTableBlock(spell, attackTable, roll, &chance) && -======= if !result.applyAttackTableMiss(spell, attackTable, roll, &chance, countHits) && !result.applyAttackTableDodge(spell, attackTable, roll, &chance, countHits) && !result.applyAttackTableParry(spell, attackTable, roll, &chance, countHits) && !result.applyAttackTableGlance(spell, attackTable, roll, &chance, glanceRoll, countHits) && !result.applyAttackTableBlock(spell, attackTable, roll, &chance, countHits) && ->>>>>>> master !result.applyAttackTableCrit(spell, attackTable, roll, &chance, countHits) { result.applyAttackTableHit(spell, countHits) } } else { -<<<<<<< HEAD - if !result.applyAttackTableMiss(spell, attackTable, roll, &chance) && - !result.applyAttackTableDodge(spell, unit, attackTable, roll, &chance) && - !result.applyAttackTableGlance(spell, attackTable, roll, &chance, glanceRoll) && -======= if !result.applyAttackTableMiss(spell, attackTable, roll, &chance, countHits) && !result.applyAttackTableDodge(spell, attackTable, roll, &chance, countHits) && !result.applyAttackTableGlance(spell, attackTable, roll, &chance, glanceRoll, countHits) && ->>>>>>> master !result.applyAttackTableCrit(spell, attackTable, roll, &chance, countHits) { result.applyAttackTableHit(spell, countHits) } @@ -302,16 +288,6 @@ func (spell *Spell) outcomeMeleeSpecialHit(sim *Simulation, result *SpellResult, chance := 0.0 if unit.PseudoStats.InFrontOfTarget { -<<<<<<< HEAD - if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance) && - !result.applyAttackTableDodge(spell, unit, attackTable, roll, &chance) && - !result.applyAttackTableParry(spell, attackTable, roll, &chance) { - result.applyAttackTableHit(spell, countHits) - } - } else { - if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance) && - !result.applyAttackTableDodge(spell, unit, attackTable, roll, &chance) { -======= if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance, countHits) && !result.applyAttackTableDodge(spell, attackTable, roll, &chance, countHits) && !result.applyAttackTableParry(spell, attackTable, roll, &chance, countHits) { @@ -320,7 +296,6 @@ func (spell *Spell) outcomeMeleeSpecialHit(sim *Simulation, result *SpellResult, } else { if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance, countHits) && !result.applyAttackTableDodge(spell, attackTable, roll, &chance, countHits) { ->>>>>>> master result.applyAttackTableHit(spell, countHits) } } @@ -338,15 +313,9 @@ func (spell *Spell) outcomeMeleeSpecialHitAndCrit(sim *Simulation, result *Spell chance := 0.0 if unit.PseudoStats.InFrontOfTarget { -<<<<<<< HEAD - if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance) && - !result.applyAttackTableDodge(spell, unit, attackTable, roll, &chance) && - !result.applyAttackTableParry(spell, attackTable, roll, &chance) { -======= if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance, countHits) && !result.applyAttackTableDodge(spell, attackTable, roll, &chance, countHits) && !result.applyAttackTableParry(spell, attackTable, roll, &chance, countHits) { ->>>>>>> master if result.applyAttackTableCritSeparateRoll(sim, spell, attackTable, countHits) { result.applyAttackTableBlock(spell, attackTable, roll, &chance, countHits) } else { @@ -356,13 +325,8 @@ func (spell *Spell) outcomeMeleeSpecialHitAndCrit(sim *Simulation, result *Spell } } } else { -<<<<<<< HEAD - if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance) && - !result.applyAttackTableDodge(spell, unit, attackTable, roll, &chance) && -======= if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance, countHits) && !result.applyAttackTableDodge(spell, attackTable, roll, &chance, countHits) && ->>>>>>> master !result.applyAttackTableCritSeparateRoll(sim, spell, attackTable, countHits) { result.applyAttackTableHit(spell, countHits) } @@ -383,17 +347,10 @@ func (spell *Spell) outcomeMeleeWeaponSpecialHitAndCrit(sim *Simulation, result chance := 0.0 unit := spell.Unit -<<<<<<< HEAD - if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance) && - !result.applyAttackTableDodge(spell, unit, attackTable, roll, &chance) && - !result.applyAttackTableParry(spell, attackTable, roll, &chance) && - !result.applyAttackTableBlock(spell, attackTable, roll, &chance) && -======= if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance, countHits) && !result.applyAttackTableDodge(spell, attackTable, roll, &chance, countHits) && !result.applyAttackTableParry(spell, attackTable, roll, &chance, countHits) && !result.applyAttackTableBlock(spell, attackTable, roll, &chance, countHits) && ->>>>>>> master !result.applyAttackTableCritSeparateRoll(sim, spell, attackTable, countHits) { result.applyAttackTableHit(spell, countHits) } @@ -427,17 +384,6 @@ func (spell *Spell) outcomeMeleeWeaponSpecialNoCrit(sim *Simulation, result *Spe chance := 0.0 if unit.PseudoStats.InFrontOfTarget { -<<<<<<< HEAD - if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance) && - !result.applyAttackTableDodge(spell, unit, attackTable, roll, &chance) && - !result.applyAttackTableParry(spell, attackTable, roll, &chance) && - !result.applyAttackTableBlock(spell, attackTable, roll, &chance) { - result.applyAttackTableHit(spell, countHits) - } - } else { - if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance) && - !result.applyAttackTableDodge(spell, unit, attackTable, roll, &chance) { -======= if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance, countHits) && !result.applyAttackTableDodge(spell, attackTable, roll, &chance, countHits) && !result.applyAttackTableParry(spell, attackTable, roll, &chance, countHits) && @@ -447,7 +393,6 @@ func (spell *Spell) outcomeMeleeWeaponSpecialNoCrit(sim *Simulation, result *Spe } else { if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance, countHits) && !result.applyAttackTableDodge(spell, attackTable, roll, &chance, countHits) { ->>>>>>> master result.applyAttackTableHit(spell, countHits) } } @@ -766,13 +711,8 @@ func (result *SpellResult) applyAttackTableBlock(spell *Spell, attackTable *Atta return false } -<<<<<<< HEAD -func (result *SpellResult) applyAttackTableDodge(spell *Spell, unit *Unit, attackTable *AttackTable, roll float64, chance *float64) bool { +func (result *SpellResult) applyAttackTableDodge(spell *Spell, unit *Unit, attackTable *AttackTable, roll float64, chance *float64, countHits bool) bool { *chance += max(0, attackTable.BaseDodgeChance-unit.PseudoStats.DodgeReduction) -======= -func (result *SpellResult) applyAttackTableDodge(spell *Spell, attackTable *AttackTable, roll float64, chance *float64, countHits bool) bool { - *chance += max(0, attackTable.BaseDodgeChance) ->>>>>>> master if roll < *chance { result.Outcome = OutcomeDodge From 71fd429cce25cb1b299bd48409250281b02d9146 Mon Sep 17 00:00:00 2001 From: sanguinerarogue Date: Mon, 23 Sep 2024 12:12:59 -0600 Subject: [PATCH 4/7] updates conflicts with proto --- proto/common.proto | 2 +- sim/core/spell_outcome.go | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/proto/common.proto b/proto/common.proto index 3ef335dba8..d97d267e90 100644 --- a/proto/common.proto +++ b/proto/common.proto @@ -795,7 +795,7 @@ message Debuffs { bool mekkatorque_fist_debuff = 29; bool serpents_striker_fist_debuff = 30; bool improved_faerie_fire = 36; // Provided by Tier 1 Feral set bonus - bool melee_hunter_bonus = 40; // Provided by Tier 1 Melee Hunter set bonus + bool melee_hunter_bonus = 41; // Provided by Tier 1 Melee Hunter set bonus TristateEffect curse_of_elements_new = 31 [deprecated=true]; TristateEffect curse_of_shadow_new = 32 [deprecated=true]; diff --git a/sim/core/spell_outcome.go b/sim/core/spell_outcome.go index 3d637fca52..4b8a082cd1 100644 --- a/sim/core/spell_outcome.go +++ b/sim/core/spell_outcome.go @@ -259,7 +259,7 @@ func (spell *Spell) outcomeMeleeWhite(sim *Simulation, result *SpellResult, atta if unit.PseudoStats.InFrontOfTarget { if !result.applyAttackTableMiss(spell, attackTable, roll, &chance, countHits) && - !result.applyAttackTableDodge(spell, attackTable, roll, &chance, countHits) && + !result.applyAttackTableDodge(spell, unit, attackTable, roll, &chance, countHits) && !result.applyAttackTableParry(spell, attackTable, roll, &chance, countHits) && !result.applyAttackTableGlance(spell, attackTable, roll, &chance, glanceRoll, countHits) && !result.applyAttackTableBlock(spell, attackTable, roll, &chance, countHits) && @@ -268,7 +268,7 @@ func (spell *Spell) outcomeMeleeWhite(sim *Simulation, result *SpellResult, atta } } else { if !result.applyAttackTableMiss(spell, attackTable, roll, &chance, countHits) && - !result.applyAttackTableDodge(spell, attackTable, roll, &chance, countHits) && + !result.applyAttackTableDodge(spell, unit, attackTable, roll, &chance, countHits) && !result.applyAttackTableGlance(spell, attackTable, roll, &chance, glanceRoll, countHits) && !result.applyAttackTableCrit(spell, attackTable, roll, &chance, countHits) { result.applyAttackTableHit(spell, countHits) @@ -289,13 +289,13 @@ func (spell *Spell) outcomeMeleeSpecialHit(sim *Simulation, result *SpellResult, if unit.PseudoStats.InFrontOfTarget { if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance, countHits) && - !result.applyAttackTableDodge(spell, attackTable, roll, &chance, countHits) && + !result.applyAttackTableDodge(spell, unit, attackTable, roll, &chance, countHits) && !result.applyAttackTableParry(spell, attackTable, roll, &chance, countHits) { result.applyAttackTableHit(spell, countHits) } } else { if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance, countHits) && - !result.applyAttackTableDodge(spell, attackTable, roll, &chance, countHits) { + !result.applyAttackTableDodge(spell, unit, attackTable, roll, &chance, countHits) { result.applyAttackTableHit(spell, countHits) } } @@ -314,7 +314,7 @@ func (spell *Spell) outcomeMeleeSpecialHitAndCrit(sim *Simulation, result *Spell if unit.PseudoStats.InFrontOfTarget { if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance, countHits) && - !result.applyAttackTableDodge(spell, attackTable, roll, &chance, countHits) && + !result.applyAttackTableDodge(spell, unit, attackTable, roll, &chance, countHits) && !result.applyAttackTableParry(spell, attackTable, roll, &chance, countHits) { if result.applyAttackTableCritSeparateRoll(sim, spell, attackTable, countHits) { result.applyAttackTableBlock(spell, attackTable, roll, &chance, countHits) @@ -326,7 +326,7 @@ func (spell *Spell) outcomeMeleeSpecialHitAndCrit(sim *Simulation, result *Spell } } else { if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance, countHits) && - !result.applyAttackTableDodge(spell, attackTable, roll, &chance, countHits) && + !result.applyAttackTableDodge(spell, unit, attackTable, roll, &chance, countHits) && !result.applyAttackTableCritSeparateRoll(sim, spell, attackTable, countHits) { result.applyAttackTableHit(spell, countHits) } @@ -348,7 +348,7 @@ func (spell *Spell) outcomeMeleeWeaponSpecialHitAndCrit(sim *Simulation, result unit := spell.Unit if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance, countHits) && - !result.applyAttackTableDodge(spell, attackTable, roll, &chance, countHits) && + !result.applyAttackTableDodge(spell, unit, attackTable, roll, &chance, countHits) && !result.applyAttackTableParry(spell, attackTable, roll, &chance, countHits) && !result.applyAttackTableBlock(spell, attackTable, roll, &chance, countHits) && !result.applyAttackTableCritSeparateRoll(sim, spell, attackTable, countHits) { @@ -385,14 +385,14 @@ func (spell *Spell) outcomeMeleeWeaponSpecialNoCrit(sim *Simulation, result *Spe if unit.PseudoStats.InFrontOfTarget { if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance, countHits) && - !result.applyAttackTableDodge(spell, attackTable, roll, &chance, countHits) && + !result.applyAttackTableDodge(spell, unit, attackTable, roll, &chance, countHits) && !result.applyAttackTableParry(spell, attackTable, roll, &chance, countHits) && !result.applyAttackTableBlock(spell, attackTable, roll, &chance, countHits) { result.applyAttackTableHit(spell, countHits) } } else { if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance, countHits) && - !result.applyAttackTableDodge(spell, attackTable, roll, &chance, countHits) { + !result.applyAttackTableDodge(spell, unit, attackTable, roll, &chance, countHits) { result.applyAttackTableHit(spell, countHits) } } From 27a58251de4686e167bbde0cf436a2fc22ade0ff Mon Sep 17 00:00:00 2001 From: Kayla Glick Date: Wed, 25 Sep 2024 17:45:21 -0400 Subject: [PATCH 5/7] update hunter dodge debuffs --- proto/common.proto | 2 +- sim/core/debuffs.go | 12 ++++------ sim/core/spell_outcome.go | 28 ++++++++++++---------- sim/core/stats/stats.go | 2 +- sim/hunter/item_sets_pve.go | 20 +--------------- ui/core/components/inputs/buffs_debuffs.ts | 14 +++++------ 6 files changed, 31 insertions(+), 47 deletions(-) diff --git a/proto/common.proto b/proto/common.proto index d97d267e90..afae3a616f 100644 --- a/proto/common.proto +++ b/proto/common.proto @@ -795,7 +795,7 @@ message Debuffs { bool mekkatorque_fist_debuff = 29; bool serpents_striker_fist_debuff = 30; bool improved_faerie_fire = 36; // Provided by Tier 1 Feral set bonus - bool melee_hunter_bonus = 41; // Provided by Tier 1 Melee Hunter set bonus + bool melee_hunter_dodge_debuff = 41; // Provided by Tier 1 Melee Hunter set bonus TristateEffect curse_of_elements_new = 31 [deprecated=true]; TristateEffect curse_of_shadow_new = 32 [deprecated=true]; diff --git a/sim/core/debuffs.go b/sim/core/debuffs.go index c89b09d64b..bed32c64c4 100644 --- a/sim/core/debuffs.go +++ b/sim/core/debuffs.go @@ -219,8 +219,8 @@ func applyDebuffEffects(target *Unit, targetIdx int, debuffs *proto.Debuffs, rai MakePermanent(ImprovedFaerieFireAura(target)) } - if debuffs.MeleeHunterBonus { - MakePermanent(MeleeHunterBonusAura(target)) + if debuffs.MeleeHunterDodgeDebuff { + MakePermanent(MeleeHunterDodgeReductionAura(target, level)) } if debuffs.CurseOfWeakness != proto.TristateEffect_TristateEffectMissing { @@ -1140,18 +1140,16 @@ func ImprovedFaerieFireAura(target *Unit) *Aura { }) } -func MeleeHunterBonusAura(target *Unit) *Aura { +func MeleeHunterDodgeReductionAura(target *Unit, _ int32) *Aura { return target.GetOrRegisterAura(Aura{ Label: "S03 - Item - T1 - Hunter - Melee 2P Bonus", ActionID: ActionID{SpellID: 456389}, Duration: time.Second * 30, OnGain: func(aura *Aura, sim *Simulation) { - // target.BaseDodgeChance -= 1 - // target.AttackTables[target.CurrentTarget.UnitIndex][proto.CastType_CastTypeMainHand].BaseDodgeChance -= 1 + aura.Unit.PseudoStats.DodgeReduction += 0.01 }, OnExpire: func(aura *Aura, sim *Simulation) { - // target.BaseDodgeChance += 1 - // target.AttackTables[target.CurrentTarget.UnitIndex][proto.CastType_CastTypeMainHand].BaseDodgeChance += 1 + aura.Unit.PseudoStats.DodgeReduction -= 0.01 }, }) } diff --git a/sim/core/spell_outcome.go b/sim/core/spell_outcome.go index 4b8a082cd1..31c2b9ceaa 100644 --- a/sim/core/spell_outcome.go +++ b/sim/core/spell_outcome.go @@ -253,13 +253,14 @@ func (spell *Spell) OutcomeMeleeWhiteNoHitCounter(sim *Simulation, result *Spell } func (spell *Spell) outcomeMeleeWhite(sim *Simulation, result *SpellResult, attackTable *AttackTable, countHits bool) { unit := spell.Unit + target := result.Target roll := sim.RandomFloat("White Hit Table") glanceRoll := sim.RandomFloat("White Hit Glancing Penalty") chance := 0.0 if unit.PseudoStats.InFrontOfTarget { if !result.applyAttackTableMiss(spell, attackTable, roll, &chance, countHits) && - !result.applyAttackTableDodge(spell, unit, attackTable, roll, &chance, countHits) && + !result.applyAttackTableDodge(spell, target, attackTable, roll, &chance, countHits) && !result.applyAttackTableParry(spell, attackTable, roll, &chance, countHits) && !result.applyAttackTableGlance(spell, attackTable, roll, &chance, glanceRoll, countHits) && !result.applyAttackTableBlock(spell, attackTable, roll, &chance, countHits) && @@ -268,7 +269,7 @@ func (spell *Spell) outcomeMeleeWhite(sim *Simulation, result *SpellResult, atta } } else { if !result.applyAttackTableMiss(spell, attackTable, roll, &chance, countHits) && - !result.applyAttackTableDodge(spell, unit, attackTable, roll, &chance, countHits) && + !result.applyAttackTableDodge(spell, target, attackTable, roll, &chance, countHits) && !result.applyAttackTableGlance(spell, attackTable, roll, &chance, glanceRoll, countHits) && !result.applyAttackTableCrit(spell, attackTable, roll, &chance, countHits) { result.applyAttackTableHit(spell, countHits) @@ -284,18 +285,19 @@ func (spell *Spell) OutcomeMeleeSpecialHitNoHitCounter(sim *Simulation, result * } func (spell *Spell) outcomeMeleeSpecialHit(sim *Simulation, result *SpellResult, attackTable *AttackTable, countHits bool) { unit := spell.Unit + target := result.Target roll := sim.RandomFloat("White Hit Table") chance := 0.0 if unit.PseudoStats.InFrontOfTarget { if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance, countHits) && - !result.applyAttackTableDodge(spell, unit, attackTable, roll, &chance, countHits) && + !result.applyAttackTableDodge(spell, target, attackTable, roll, &chance, countHits) && !result.applyAttackTableParry(spell, attackTable, roll, &chance, countHits) { result.applyAttackTableHit(spell, countHits) } } else { if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance, countHits) && - !result.applyAttackTableDodge(spell, unit, attackTable, roll, &chance, countHits) { + !result.applyAttackTableDodge(spell, target, attackTable, roll, &chance, countHits) { result.applyAttackTableHit(spell, countHits) } } @@ -309,12 +311,13 @@ func (spell *Spell) OutcomeMeleeSpecialHitAndCritNoHitCounter(sim *Simulation, r } func (spell *Spell) outcomeMeleeSpecialHitAndCrit(sim *Simulation, result *SpellResult, attackTable *AttackTable, countHits bool) { unit := spell.Unit + target := result.Target roll := sim.RandomFloat("White Hit Table") chance := 0.0 if unit.PseudoStats.InFrontOfTarget { if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance, countHits) && - !result.applyAttackTableDodge(spell, unit, attackTable, roll, &chance, countHits) && + !result.applyAttackTableDodge(spell, target, attackTable, roll, &chance, countHits) && !result.applyAttackTableParry(spell, attackTable, roll, &chance, countHits) { if result.applyAttackTableCritSeparateRoll(sim, spell, attackTable, countHits) { result.applyAttackTableBlock(spell, attackTable, roll, &chance, countHits) @@ -326,7 +329,7 @@ func (spell *Spell) outcomeMeleeSpecialHitAndCrit(sim *Simulation, result *Spell } } else { if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance, countHits) && - !result.applyAttackTableDodge(spell, unit, attackTable, roll, &chance, countHits) && + !result.applyAttackTableDodge(spell, target, attackTable, roll, &chance, countHits) && !result.applyAttackTableCritSeparateRoll(sim, spell, attackTable, countHits) { result.applyAttackTableHit(spell, countHits) } @@ -343,12 +346,12 @@ func (spell *Spell) OutcomeMeleeWeaponSpecialHitAndCritNoHitCounter(sim *Simulat // Like OutcomeMeleeSpecialHitAndCrit, but blocks prevent crits (all weapon damage based attacks). func (spell *Spell) outcomeMeleeWeaponSpecialHitAndCrit(sim *Simulation, result *SpellResult, attackTable *AttackTable, countHits bool) { if spell.Unit.PseudoStats.InFrontOfTarget { + target := result.Target roll := sim.RandomFloat("White Hit Table") chance := 0.0 - unit := spell.Unit if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance, countHits) && - !result.applyAttackTableDodge(spell, unit, attackTable, roll, &chance, countHits) && + !result.applyAttackTableDodge(spell, target, attackTable, roll, &chance, countHits) && !result.applyAttackTableParry(spell, attackTable, roll, &chance, countHits) && !result.applyAttackTableBlock(spell, attackTable, roll, &chance, countHits) && !result.applyAttackTableCritSeparateRoll(sim, spell, attackTable, countHits) { @@ -380,19 +383,20 @@ func (spell *Spell) OutcomeMeleeWeaponSpecialNoCritNoHitCounter(sim *Simulation, } func (spell *Spell) outcomeMeleeWeaponSpecialNoCrit(sim *Simulation, result *SpellResult, attackTable *AttackTable, countHits bool) { unit := spell.Unit + target := result.Target roll := sim.RandomFloat("White Hit Table") chance := 0.0 if unit.PseudoStats.InFrontOfTarget { if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance, countHits) && - !result.applyAttackTableDodge(spell, unit, attackTable, roll, &chance, countHits) && + !result.applyAttackTableDodge(spell, target, attackTable, roll, &chance, countHits) && !result.applyAttackTableParry(spell, attackTable, roll, &chance, countHits) && !result.applyAttackTableBlock(spell, attackTable, roll, &chance, countHits) { result.applyAttackTableHit(spell, countHits) } } else { if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance, countHits) && - !result.applyAttackTableDodge(spell, unit, attackTable, roll, &chance, countHits) { + !result.applyAttackTableDodge(spell, target, attackTable, roll, &chance, countHits) { result.applyAttackTableHit(spell, countHits) } } @@ -711,8 +715,8 @@ func (result *SpellResult) applyAttackTableBlock(spell *Spell, attackTable *Atta return false } -func (result *SpellResult) applyAttackTableDodge(spell *Spell, unit *Unit, attackTable *AttackTable, roll float64, chance *float64, countHits bool) bool { - *chance += max(0, attackTable.BaseDodgeChance-unit.PseudoStats.DodgeReduction) +func (result *SpellResult) applyAttackTableDodge(spell *Spell, target *Unit, attackTable *AttackTable, roll float64, chance *float64, countHits bool) bool { + *chance += max(0, attackTable.BaseDodgeChance-target.PseudoStats.DodgeReduction) if roll < *chance { result.Outcome = OutcomeDodge diff --git a/sim/core/stats/stats.go b/sim/core/stats/stats.go index 463e0c34fc..4f4dbf8355 100644 --- a/sim/core/stats/stats.go +++ b/sim/core/stats/stats.go @@ -424,7 +424,7 @@ type PseudoStats struct { DisableDWMissPenalty bool // Used by Heroic Strike and Cleave IncreasedMissChance float64 // Insect Swarm and Scorpid Sting - DodgeReduction float64 // Used by Warrior talent 'Weapon Mastery' and SWP boss auras. + DodgeReduction float64 // Target dodge reduction effects e.g. "reduces its target's chance to Dodge by X%" MobTypeAttackPower float64 // Bonus AP against mobs of the current type. MobTypeSpellPower float64 // Bonus SP against mobs of the current type. diff --git a/sim/hunter/item_sets_pve.go b/sim/hunter/item_sets_pve.go index dc258d1215..53b50ea443 100644 --- a/sim/hunter/item_sets_pve.go +++ b/sim/hunter/item_sets_pve.go @@ -80,26 +80,8 @@ var ItemSetGiantstalkerProwess = core.NewItemSet(core.ItemSet{ // Your Mongoose Bite also reduces its target's chance to Dodge by 1% and increases your chance to hit by 1% for 30 sec. 2: func(agent core.Agent) { hunter := agent.(HunterAgent).GetHunter() - hunter.PseudoStats.DodgeReduction += .01 - - debuffAuras := hunter.NewEnemyAuraArray(func(target *core.Unit, level int32) *core.Aura { - return target.RegisterAura(core.Aura{ - Label: "S03 - Item - T1 - Hunter - Melee 2P Bonus", - ActionID: core.ActionID{SpellID: 456389}, - Duration: time.Second * 30, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - - aura.Unit.PseudoStats.BonusMeleeHitRatingTaken += 1 * core.MeleeHitRatingPerHitChance - aura.Unit.PseudoStats.BonusSpellHitRatingTaken += 1 * core.SpellHitRatingPerHitChance - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - - aura.Unit.PseudoStats.BonusMeleeHitRatingTaken += 1 * core.MeleeHitRatingPerHitChance - aura.Unit.PseudoStats.BonusSpellHitRatingTaken += 1 * core.SpellHitRatingPerHitChance - }, - }) - }) + debuffAuras := hunter.NewEnemyAuraArray(core.MeleeHunterDodgeReductionAura) core.MakePermanent(hunter.RegisterAura(core.Aura{ Label: "S03 - Item - T1 - Hunter - Melee 2P Bonus Trigger", OnSpellHitDealt: func(_ *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { diff --git a/ui/core/components/inputs/buffs_debuffs.ts b/ui/core/components/inputs/buffs_debuffs.ts index c3ebb867f8..963af06065 100644 --- a/ui/core/components/inputs/buffs_debuffs.ts +++ b/ui/core/components/inputs/buffs_debuffs.ts @@ -923,7 +923,7 @@ export const ImprovedFaerieFire = makeBooleanDebuffInput({ }); export const MeleeHunter2pcT1Bonus = makeBooleanDebuffInput({ actionId: player => player.getMatchingSpellActionId([{ id: 456389, minLevel: 60 }]), - fieldName: 'meleeHunterBonus', + fieldName: 'meleeHunterDodgeDebuff', }); export const MekkatorqueFistDebuff = makeBooleanDebuffInput({ actionId: player => player.getMatchingItemActionId([{ id: 213409, minLevel: 40, maxLevel: 45 }]), @@ -1016,11 +1016,11 @@ export const RAID_BUFFS_CONFIG = [ picker: IconPicker, stats: [Stat.StatArmor], }, - // { - // config: DamageReductionPercentBuff, - // picker: IconPicker, - // stats: [Stat.StatArmor], - // }, + // { + // config: DamageReductionPercentBuff, + // picker: IconPicker, + // stats: [Stat.StatArmor], + // }, { config: ResistanceBuff, picker: MultiIconPicker, @@ -1336,7 +1336,7 @@ export const MISC_DEBUFFS_CONFIG = [ { config: MeleeHunter2pcT1Bonus, picker: IconPicker, - stats: [], + stats: [Stat.StatMeleeHit], }, { config: MekkatorqueFistDebuff, From 5d57a676d0ce3427c0da3a29084b0ed42b6db18d Mon Sep 17 00:00:00 2001 From: Kayla Glick Date: Wed, 25 Sep 2024 17:56:33 -0400 Subject: [PATCH 6/7] use attacktable.Defender --- sim/core/spell_outcome.go | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/sim/core/spell_outcome.go b/sim/core/spell_outcome.go index 31c2b9ceaa..0c358c234a 100644 --- a/sim/core/spell_outcome.go +++ b/sim/core/spell_outcome.go @@ -253,14 +253,13 @@ func (spell *Spell) OutcomeMeleeWhiteNoHitCounter(sim *Simulation, result *Spell } func (spell *Spell) outcomeMeleeWhite(sim *Simulation, result *SpellResult, attackTable *AttackTable, countHits bool) { unit := spell.Unit - target := result.Target roll := sim.RandomFloat("White Hit Table") glanceRoll := sim.RandomFloat("White Hit Glancing Penalty") chance := 0.0 if unit.PseudoStats.InFrontOfTarget { if !result.applyAttackTableMiss(spell, attackTable, roll, &chance, countHits) && - !result.applyAttackTableDodge(spell, target, attackTable, roll, &chance, countHits) && + !result.applyAttackTableDodge(spell, attackTable, roll, &chance, countHits) && !result.applyAttackTableParry(spell, attackTable, roll, &chance, countHits) && !result.applyAttackTableGlance(spell, attackTable, roll, &chance, glanceRoll, countHits) && !result.applyAttackTableBlock(spell, attackTable, roll, &chance, countHits) && @@ -269,7 +268,7 @@ func (spell *Spell) outcomeMeleeWhite(sim *Simulation, result *SpellResult, atta } } else { if !result.applyAttackTableMiss(spell, attackTable, roll, &chance, countHits) && - !result.applyAttackTableDodge(spell, target, attackTable, roll, &chance, countHits) && + !result.applyAttackTableDodge(spell, attackTable, roll, &chance, countHits) && !result.applyAttackTableGlance(spell, attackTable, roll, &chance, glanceRoll, countHits) && !result.applyAttackTableCrit(spell, attackTable, roll, &chance, countHits) { result.applyAttackTableHit(spell, countHits) @@ -285,19 +284,18 @@ func (spell *Spell) OutcomeMeleeSpecialHitNoHitCounter(sim *Simulation, result * } func (spell *Spell) outcomeMeleeSpecialHit(sim *Simulation, result *SpellResult, attackTable *AttackTable, countHits bool) { unit := spell.Unit - target := result.Target roll := sim.RandomFloat("White Hit Table") chance := 0.0 if unit.PseudoStats.InFrontOfTarget { if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance, countHits) && - !result.applyAttackTableDodge(spell, target, attackTable, roll, &chance, countHits) && + !result.applyAttackTableDodge(spell, attackTable, roll, &chance, countHits) && !result.applyAttackTableParry(spell, attackTable, roll, &chance, countHits) { result.applyAttackTableHit(spell, countHits) } } else { if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance, countHits) && - !result.applyAttackTableDodge(spell, target, attackTable, roll, &chance, countHits) { + !result.applyAttackTableDodge(spell, attackTable, roll, &chance, countHits) { result.applyAttackTableHit(spell, countHits) } } @@ -311,13 +309,12 @@ func (spell *Spell) OutcomeMeleeSpecialHitAndCritNoHitCounter(sim *Simulation, r } func (spell *Spell) outcomeMeleeSpecialHitAndCrit(sim *Simulation, result *SpellResult, attackTable *AttackTable, countHits bool) { unit := spell.Unit - target := result.Target roll := sim.RandomFloat("White Hit Table") chance := 0.0 if unit.PseudoStats.InFrontOfTarget { if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance, countHits) && - !result.applyAttackTableDodge(spell, target, attackTable, roll, &chance, countHits) && + !result.applyAttackTableDodge(spell, attackTable, roll, &chance, countHits) && !result.applyAttackTableParry(spell, attackTable, roll, &chance, countHits) { if result.applyAttackTableCritSeparateRoll(sim, spell, attackTable, countHits) { result.applyAttackTableBlock(spell, attackTable, roll, &chance, countHits) @@ -329,7 +326,7 @@ func (spell *Spell) outcomeMeleeSpecialHitAndCrit(sim *Simulation, result *Spell } } else { if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance, countHits) && - !result.applyAttackTableDodge(spell, target, attackTable, roll, &chance, countHits) && + !result.applyAttackTableDodge(spell, attackTable, roll, &chance, countHits) && !result.applyAttackTableCritSeparateRoll(sim, spell, attackTable, countHits) { result.applyAttackTableHit(spell, countHits) } @@ -346,12 +343,11 @@ func (spell *Spell) OutcomeMeleeWeaponSpecialHitAndCritNoHitCounter(sim *Simulat // Like OutcomeMeleeSpecialHitAndCrit, but blocks prevent crits (all weapon damage based attacks). func (spell *Spell) outcomeMeleeWeaponSpecialHitAndCrit(sim *Simulation, result *SpellResult, attackTable *AttackTable, countHits bool) { if spell.Unit.PseudoStats.InFrontOfTarget { - target := result.Target roll := sim.RandomFloat("White Hit Table") chance := 0.0 if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance, countHits) && - !result.applyAttackTableDodge(spell, target, attackTable, roll, &chance, countHits) && + !result.applyAttackTableDodge(spell, attackTable, roll, &chance, countHits) && !result.applyAttackTableParry(spell, attackTable, roll, &chance, countHits) && !result.applyAttackTableBlock(spell, attackTable, roll, &chance, countHits) && !result.applyAttackTableCritSeparateRoll(sim, spell, attackTable, countHits) { @@ -383,20 +379,19 @@ func (spell *Spell) OutcomeMeleeWeaponSpecialNoCritNoHitCounter(sim *Simulation, } func (spell *Spell) outcomeMeleeWeaponSpecialNoCrit(sim *Simulation, result *SpellResult, attackTable *AttackTable, countHits bool) { unit := spell.Unit - target := result.Target roll := sim.RandomFloat("White Hit Table") chance := 0.0 if unit.PseudoStats.InFrontOfTarget { if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance, countHits) && - !result.applyAttackTableDodge(spell, target, attackTable, roll, &chance, countHits) && + !result.applyAttackTableDodge(spell, attackTable, roll, &chance, countHits) && !result.applyAttackTableParry(spell, attackTable, roll, &chance, countHits) && !result.applyAttackTableBlock(spell, attackTable, roll, &chance, countHits) { result.applyAttackTableHit(spell, countHits) } } else { if !result.applyAttackTableMissNoDWPenalty(spell, attackTable, roll, &chance, countHits) && - !result.applyAttackTableDodge(spell, target, attackTable, roll, &chance, countHits) { + !result.applyAttackTableDodge(spell, attackTable, roll, &chance, countHits) { result.applyAttackTableHit(spell, countHits) } } @@ -715,8 +710,8 @@ func (result *SpellResult) applyAttackTableBlock(spell *Spell, attackTable *Atta return false } -func (result *SpellResult) applyAttackTableDodge(spell *Spell, target *Unit, attackTable *AttackTable, roll float64, chance *float64, countHits bool) bool { - *chance += max(0, attackTable.BaseDodgeChance-target.PseudoStats.DodgeReduction) +func (result *SpellResult) applyAttackTableDodge(spell *Spell, attackTable *AttackTable, roll float64, chance *float64, countHits bool) bool { + *chance += max(0, attackTable.BaseDodgeChance-attackTable.Defender.PseudoStats.DodgeReduction) if roll < *chance { result.Outcome = OutcomeDodge From 79d8105acf911a7fa2acd9180a8aaeb44a758d6f Mon Sep 17 00:00:00 2001 From: sanguinerarogue Date: Wed, 25 Sep 2024 16:58:40 -0600 Subject: [PATCH 7/7] Tooltip clean up + Stalker aura --- sim/core/debuffs.go | 4 ++-- sim/hunter/item_sets_pve.go | 18 ++++++++++++++++++ ui/core/components/inputs/buffs_debuffs.ts | 2 +- ui/core/proto_utils/action_id.ts | 2 ++ 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/sim/core/debuffs.go b/sim/core/debuffs.go index bed32c64c4..f5f8134f27 100644 --- a/sim/core/debuffs.go +++ b/sim/core/debuffs.go @@ -1142,8 +1142,8 @@ func ImprovedFaerieFireAura(target *Unit) *Aura { func MeleeHunterDodgeReductionAura(target *Unit, _ int32) *Aura { return target.GetOrRegisterAura(Aura{ - Label: "S03 - Item - T1 - Hunter - Melee 2P Bonus", - ActionID: ActionID{SpellID: 456389}, + Label: "Stalked", + ActionID: ActionID{SpellID: 456393}, Duration: time.Second * 30, OnGain: func(aura *Aura, sim *Simulation) { aura.Unit.PseudoStats.DodgeReduction += 0.01 diff --git a/sim/hunter/item_sets_pve.go b/sim/hunter/item_sets_pve.go index 53b50ea443..948652513b 100644 --- a/sim/hunter/item_sets_pve.go +++ b/sim/hunter/item_sets_pve.go @@ -80,6 +80,23 @@ var ItemSetGiantstalkerProwess = core.NewItemSet(core.ItemSet{ // Your Mongoose Bite also reduces its target's chance to Dodge by 1% and increases your chance to hit by 1% for 30 sec. 2: func(agent core.Agent) { hunter := agent.(HunterAgent).GetHunter() + + procBonus := stats.Stats{ + stats.SpellHit: 1, + stats.MeleeHit: 1, + } + + stalkerAura := hunter.RegisterAura(core.Aura{ + ActionID: core.ActionID{SpellID: 458403}, + Label: "Stalker", + Duration: time.Second * 30, + OnGain: func(aura *core.Aura, sim *core.Simulation) { + aura.Unit.AddStatsDynamic(sim, procBonus) + }, + OnExpire: func(aura *core.Aura, sim *core.Simulation) { + aura.Unit.AddStatsDynamic(sim, procBonus.Invert()) + }, + }) debuffAuras := hunter.NewEnemyAuraArray(core.MeleeHunterDodgeReductionAura) core.MakePermanent(hunter.RegisterAura(core.Aura{ @@ -87,6 +104,7 @@ var ItemSetGiantstalkerProwess = core.NewItemSet(core.ItemSet{ OnSpellHitDealt: func(_ *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { if spell.SpellCode == SpellCode_HunterMongooseBite && result.Landed() { debuffAuras.Get(result.Target).Activate(sim) + stalkerAura.Activate(sim) } }, })) diff --git a/ui/core/components/inputs/buffs_debuffs.ts b/ui/core/components/inputs/buffs_debuffs.ts index 963af06065..2e85d23c0a 100644 --- a/ui/core/components/inputs/buffs_debuffs.ts +++ b/ui/core/components/inputs/buffs_debuffs.ts @@ -922,7 +922,7 @@ export const ImprovedFaerieFire = makeBooleanDebuffInput({ fieldName: 'improvedFaerieFire', }); export const MeleeHunter2pcT1Bonus = makeBooleanDebuffInput({ - actionId: player => player.getMatchingSpellActionId([{ id: 456389, minLevel: 60 }]), + actionId: player => player.getMatchingSpellActionId([{ id: 456393, minLevel: 60 }]), fieldName: 'meleeHunterDodgeDebuff', }); export const MekkatorqueFistDebuff = makeBooleanDebuffInput({ diff --git a/ui/core/proto_utils/action_id.ts b/ui/core/proto_utils/action_id.ts index 67070b4fa8..5ef4cd1bde 100644 --- a/ui/core/proto_utils/action_id.ts +++ b/ui/core/proto_utils/action_id.ts @@ -720,9 +720,11 @@ const spellIDsToShowBuffs = new Set([ 457816, // https://www.wowhead.com/classic/spell=457816/battle-forecast 457817, // https://www.wowhead.com/classic/spell=457817/berserker-forecast 457819, // https://www.wowhead.com/classic/spell=457819/echoes-of-gladiator-stance + 458403, // https://www.wowhead.com/classic/spell=458403/stalker 461252, // https://www.wowhead.com/classic/spell=461252/shadowflame-fury 461270, // https://www.wowhead.com/classic/spell=461270/magmadars-return 461615, // https://www.wowhead.com/classic/spell=461615/mark-of-chaos + 456393, // https://www.wowhead.com/classic/spell=456393/stalked ]); export const defaultTargetIcon = 'https://wow.zamimg.com/images/wow/icons/large/spell_shadow_metamorphosis.jpg';