-
Notifications
You must be signed in to change notification settings - Fork 30
/
aimed_shot.go
100 lines (84 loc) · 2.88 KB
/
aimed_shot.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package hunter
import (
"time"
"github.com/wowsims/sod/sim/core"
"github.com/wowsims/sod/sim/core/proto"
)
func (hunter *Hunter) getAimedShotConfig(rank int, timer *core.Timer) core.SpellConfig {
spellId := [7]int32{0, 19434, 20900, 20901, 20902, 20903, 20904}[rank]
baseDamage := [7]float64{0, 70, 125, 200, 330, 460, 600}[rank]
manaCost := [7]float64{0, 75, 115, 160, 210, 260, 310}[rank]
level := [7]int{0, 0, 28, 36, 44, 52, 60}[rank]
hasCobraStrikes := hunter.pet != nil && hunter.HasRune(proto.HunterRune_RuneChestCobraStrikes)
manaCostMultiplier := 1 - 0.02*float64(hunter.Talents.Efficiency)
if hunter.HasRune(proto.HunterRune_RuneChestMasterMarksman) {
manaCostMultiplier -= 0.25
}
return core.SpellConfig{
ActionID: core.ActionID{SpellID: spellId},
SpellSchool: core.SpellSchoolPhysical,
DefenseType: core.DefenseTypeRanged,
ProcMask: core.ProcMaskRangedSpecial,
Flags: core.SpellFlagMeleeMetrics | core.SpellFlagAPL,
CastType: proto.CastType_CastTypeRanged,
Rank: rank,
RequiredLevel: level,
MissileSpeed: 24,
ManaCost: core.ManaCostOptions{
FlatCost: manaCost,
Multiplier: manaCostMultiplier,
},
Cast: core.CastConfig{
DefaultCast: core.Cast{
GCD: core.GCDDefault,
CastTime: time.Millisecond * 3500,
},
CD: core.Cooldown{
Timer: timer,
Duration: time.Second * 6,
},
ModifyCast: func(_ *core.Simulation, spell *core.Spell, cast *core.Cast) {
cast.CastTime = spell.CastTime()
},
IgnoreHaste: true, // Hunter GCD is locked at 1.5s
CastTime: func(spell *core.Spell) time.Duration {
if hunter.SniperTrainingAura.GetStacks() == 5 {
return 0
}
return time.Duration(float64(spell.DefaultCast.CastTime) / hunter.RangedSwingSpeed())
},
},
ExtraCastCondition: func(sim *core.Simulation, target *core.Unit) bool {
return hunter.DistanceFromTarget >= 8
},
CritDamageBonus: hunter.mortalShots(),
DamageMultiplier: 1,
ThreatMultiplier: 1,
BonusCoefficient: 1,
ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) {
baseDamage := hunter.AutoAttacks.Ranged().CalculateNormalizedWeaponDamage(sim, spell.RangedAttackPower(target)) +
hunter.NormalizedAmmoDamageBonus +
baseDamage
result := spell.CalcDamage(sim, target, baseDamage, spell.OutcomeRangedHitAndCrit)
spell.WaitTravelTime(sim, func(s *core.Simulation) {
spell.DealDamage(sim, result)
if hasCobraStrikes && result.DidCrit() {
hunter.CobraStrikesAura.Activate(sim)
hunter.CobraStrikesAura.SetStacks(sim, 2)
}
})
},
}
}
func (hunter *Hunter) registerAimedShotSpell(timer *core.Timer) {
if !hunter.Talents.AimedShot {
return
}
maxRank := 6
for i := 1; i <= maxRank; i++ {
config := hunter.getAimedShotConfig(i, timer)
if config.RequiredLevel <= int(hunter.Level) {
hunter.ArcaneShot = hunter.GetOrRegisterSpell(config)
}
}
}