Skip to content

Commit

Permalink
fix LvB, LB, FS all working
Browse files Browse the repository at this point in the history
  • Loading branch information
kayla-glick committed Feb 1, 2024
1 parent 40b0670 commit 5ac6ce3
Show file tree
Hide file tree
Showing 9 changed files with 153 additions and 123 deletions.
87 changes: 87 additions & 0 deletions sim/shaman/flame_shock.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package shaman

import (
"time"

"github.com/wowsims/sod/sim/core"
)

const FlameShockRanks = 6

// First entry is the base spell ID, second entry is the overload's spell ID
var FlameShockSpellId = [FlameShockRanks + 1]int32{0, 8050, 8052, 8053, 10447, 10448, 29228}
var FlameShockBaseDamage = [FlameShockRanks + 1]float64{0, 25, 51, 95, 164, 245, 292}
var FlameShockBaseDotDamage = [FlameShockRanks + 1]float64{0, 28, 48, 96, 168, 256, 320}
var FlameShockBaseSpellCoef = [FlameShockRanks + 1]float64{0, .134, .198, .214, .214, .214, .214}
var FlameShockDotSpellCoef = [FlameShockRanks + 1]float64{0, .134, .198, .214, .214, .214, .214}
var FlameShockManaCost = [FlameShockRanks + 1]float64{0, 55, 95, 160, 250, 345, 410}
var FlameShockLevel = [FlameShockRanks + 1]int{0, 10, 18, 28, 40, 52, 60}

func (shaman *Shaman) registerFlameShockSpell(shockTimer *core.Timer) {
for i := 1; i <= FlameShockRanks; i++ {
config := shaman.newFlameShockSpellConfig(shockTimer, i)

if config.RequiredLevel <= int(shaman.Level) {
shaman.FlameShock = shaman.RegisterSpell(config)
}
}
}

func (shaman *Shaman) newFlameShockSpellConfig(shockTimer *core.Timer, rank int) core.SpellConfig {
spellId := FlameShockSpellId[rank]
baseDamage := FlameShockBaseDamage[rank]
baseDotDamage := FlameShockBaseDotDamage[rank]
baseSpellCoeff := FlameShockBaseSpellCoef[rank]
dotSpellCoeff := FlameShockDotSpellCoef[rank]
manaCost := FlameShockManaCost[rank]
level := FlameShockLevel[rank]

numTicks := 4
tickDuration := time.Second * 3

spell := shaman.newShockSpellConfig(
core.ActionID{SpellID: spellId},
core.SpellSchoolFire,
manaCost,
shockTimer,
)

spell.RequiredLevel = level
spell.Rank = rank

spell.CritMultiplier = shaman.ElementalCritMultiplier(0)
spell.ApplyEffects = func(sim *core.Simulation, target *core.Unit, spell *core.Spell) {
damage := baseDamage + baseSpellCoeff*spell.SpellPower()
result := spell.CalcDamage(sim, target, damage, spell.OutcomeMagicHitAndCrit)
if result.Landed() {
spell.Dot(target).NumberOfTicks = int32(numTicks)
spell.Dot(target).Apply(sim)
}
spell.DealDamage(sim, result)
}

spell.Dot = core.DotConfig{
Aura: core.Aura{
Label: "FlameShock",
OnGain: func(aura *core.Aura, sim *core.Simulation) {
shaman.LavaBurst.BonusCritRating += 100 * core.CritRatingPerCritChance
},
OnExpire: func(aura *core.Aura, sim *core.Simulation) {
shaman.LavaBurst.BonusCritRating -= 100 * core.CritRatingPerCritChance
},
},
NumberOfTicks: int32(numTicks),
TickLength: tickDuration,

OnSnapshot: func(sim *core.Simulation, target *core.Unit, dot *core.Dot, _ bool) {
dot.SnapshotBaseDamage = (baseDotDamage / float64(numTicks)) + dotSpellCoeff*dot.Spell.SpellPower()
dot.SnapshotCritChance = dot.Spell.SpellCritChance(target)
dot.SnapshotAttackerMultiplier = dot.Spell.AttackerDamageMultiplier(dot.Spell.Unit.AttackTables[target.UnitIndex])
},
OnTick: func(sim *core.Simulation, target *core.Unit, dot *core.Dot) {
dot.CalcAndDealPeriodicSnapshotDamage(sim, target, dot.OutcomeSnapshotCrit)
},
}

return spell
}
4 changes: 2 additions & 2 deletions sim/shaman/lava_burst.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func (shaman *Shaman) applyLavaBurst() {
}

func (shaman *Shaman) newLavaBurstSpellConfig(isOverload bool) core.SpellConfig {
level := float64(shaman.GetCharacter().Level)
level := float64(shaman.Level)
spellId := core.TernaryInt32(isOverload, 408491, 408490)
baseCalc := 7.583798 + 0.471881*level + 0.036599*level*level
baseLowDamage := baseCalc * 4.69
Expand Down Expand Up @@ -60,13 +60,13 @@ func (shaman *Shaman) newLavaBurstSpellConfig(isOverload bool) core.SpellConfig

// Concussion does not currently apply to Lava Burst in SoD
// DamageMultiplier: 1 + 0.01*float64(shaman.Talents.Concussion)
DamageMultiplier: 1,
CritMultiplier: shaman.ElementalCritMultiplier(0),
ThreatMultiplier: 1,

ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) {
baseDamage := sim.Roll(baseLowDamage, baseHighDamage) + spellCoeff*spell.SpellPower()
result := spell.CalcDamage(sim, target, baseDamage, spell.OutcomeMagicHitAndCrit)

if canOverload && result.Landed() && sim.RandomFloat("LvB Overload") < shaman.OverloadChance {
shaman.LavaBurstOverload.Cast(sim, target)
}
Expand Down
10 changes: 4 additions & 6 deletions sim/shaman/lightning_bolt.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ func (shaman *Shaman) registerLightningBoltSpell() {
}

func (shaman *Shaman) newLightningBoltSpellConfig(rank int, isOverload bool) core.SpellConfig {
// First entry is the base spell ID, second entry is the overload's spell ID
spellId := LightningBoltSpellId[rank][core.TernaryInt32(isOverload, 1, 0)]
baseDamageLow := LightningBoltBaseDamage[rank][0]
baseDamageHigh := LightningBoltBaseDamage[rank][1]
Expand All @@ -43,23 +42,22 @@ func (shaman *Shaman) newLightningBoltSpellConfig(rank int, isOverload bool) cor
manaCost := LightningBoltManaCost[rank]
level := LightningBoltLevel[rank]

dmgBonus := shaman.electricSpellBonusDamage(spellCoeff)
canOverload := !isOverload && shaman.OverloadAura != nil

spell := shaman.newElectricSpellConfig(
core.ActionID{SpellID: spellId},
manaCost,
time.Millisecond*time.Duration(castTime),
isOverload,
)

dmgBonus := shaman.electricSpellBonusDamage(spellCoeff)

canOverload := !isOverload && shaman.OverloadAura != nil

spell.RequiredLevel = level
spell.Rank = rank

spell.ApplyEffects = func(sim *core.Simulation, target *core.Unit, spell *core.Spell) {
baseDamage := dmgBonus + sim.Roll(baseDamageLow, baseDamageHigh) + spellCoeff*spell.SpellPower()
result := spell.CalcDamage(sim, target, baseDamage, spell.OutcomeMagicHitAndCrit)

if canOverload && result.Landed() && sim.RandomFloat("LB Overload") < shaman.OverloadChance {
shaman.LightningBoltOverload.Cast(sim, target)
}
Expand Down
2 changes: 1 addition & 1 deletion sim/shaman/shaman.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ func (shaman *Shaman) Initialize() {
// shaman.registerManaSpringTotemSpell()
// shaman.registerHealingStreamTotemSpell()
// shaman.registerSearingTotemSpell()
// shaman.registerShocks()
shaman.registerShocks()
// shaman.registerStormstrikeSpell()
// shaman.registerStrengthOfEarthTotemSpell()
// shaman.registerThunderstormSpell()
Expand Down
147 changes: 42 additions & 105 deletions sim/shaman/shocks.go
Original file line number Diff line number Diff line change
@@ -1,51 +1,41 @@
package shaman

// import (
// "time"

// "github.com/wowsims/sod/sim/core"
// )

// func (shaman *Shaman) ShockCD() time.Duration {
// return time.Second*6 - time.Millisecond*200*time.Duration(shaman.Talents.Reverberation)
// }

// // Shared logic for all shocks.
// func (shaman *Shaman) newShockSpellConfig(spellID int32, spellSchool core.SpellSchool, baseCost float64, shockTimer *core.Timer) core.SpellConfig {
// actionID := core.ActionID{SpellID: spellID}

// return core.SpellConfig{
// ActionID: actionID,
// SpellSchool: spellSchool,
// ProcMask: core.ProcMaskSpellDamage,
// Flags: SpellFlagShock | core.SpellFlagAPL,

// ManaCost: core.ManaCostOptions{
// BaseCost: baseCost,
// Multiplier: 1 -
// core.TernaryFloat64(shaman.Talents.ShamanisticFocus, 0.45, 0) -
// 0.02*float64(shaman.Talents.Convection) -
// 0.02*float64(shaman.Talents.MentalQuickness) -
// core.TernaryFloat64(shaman.HasSetBonus(ItemSetSkyshatterHarness, 2), 0.1, 0),
// },
// Cast: core.CastConfig{
// DefaultCast: core.Cast{
// GCD: core.GCDDefault,
// },
// CD: core.Cooldown{
// Timer: shockTimer,
// Duration: shaman.ShockCD(),
// },
// },

// BonusHitRating: float64(shaman.Talents.ElementalPrecision) * core.SpellHitRatingPerHitChance,
// DamageMultiplier: 1 +
// 0.01*float64(shaman.Talents.Concussion) +
// core.TernaryFloat64(shaman.HasSetBonus(ItemSetThrallsBattlegear, 4), 0.25, 0),
// CritMultiplier: shaman.ElementalCritMultiplier(0),
// ThreatMultiplier: shaman.spellThreatMultiplier(),
// }
// }
import (
"time"

"github.com/wowsims/sod/sim/core"
)

func (shaman *Shaman) ShockCD() time.Duration {
return time.Second*6 - time.Millisecond*200*time.Duration(shaman.Talents.Reverberation)
}

// Shared logic for all shocks.
func (shaman *Shaman) newShockSpellConfig(actionId core.ActionID, spellSchool core.SpellSchool, baseCost float64, shockTimer *core.Timer) core.SpellConfig {
return core.SpellConfig{
ActionID: actionId,
SpellSchool: spellSchool,
ProcMask: core.ProcMaskSpellDamage,
Flags: SpellFlagShock | core.SpellFlagAPL,

ManaCost: core.ManaCostOptions{
FlatCost: baseCost,
Multiplier: 1 - 0.02*float64(shaman.Talents.Convection),
},
Cast: core.CastConfig{
DefaultCast: core.Cast{
GCD: core.GCDDefault,
},
CD: core.Cooldown{
Timer: shockTimer,
Duration: shaman.ShockCD(),
},
},

DamageMultiplier: 1 + 0.01*float64(shaman.Talents.Concussion),
CritMultiplier: shaman.ElementalCritMultiplier(0),
}
}

// func (shaman *Shaman) registerEarthShockSpell(shockTimer *core.Timer) {
// config := shaman.newShockSpellConfig(49231, core.SpellSchoolNature, 0.18, shockTimer)
Expand All @@ -57,59 +47,6 @@ package shaman
// shaman.EarthShock = shaman.RegisterSpell(config)
// }

// func (shaman *Shaman) registerFlameShockSpell(shockTimer *core.Timer) {
// config := shaman.newShockSpellConfig(49233, core.SpellSchoolFire, 0.17, shockTimer)

// config.Cast.CD.Duration -= time.Duration(shaman.Talents.BoomingEchoes) * time.Second
// config.CritMultiplier = shaman.ElementalCritMultiplier(0)
// config.DamageMultiplier += 0.1 * float64(shaman.Talents.BoomingEchoes)

// flameShockBaseNumberOfTicks := 6 + core.TernaryInt32(shaman.HasSetBonus(ItemSetThrallsRegalia, 2), 3, 0)
// config.ApplyEffects = func(sim *core.Simulation, target *core.Unit, spell *core.Spell) {
// baseDamage := 500 + 0.214*spell.SpellPower()
// result := spell.CalcDamage(sim, target, baseDamage, spell.OutcomeMagicHitAndCrit)
// if result.Landed() {
// spell.Dot(target).NumberOfTicks = flameShockBaseNumberOfTicks
// spell.Dot(target).Apply(sim)
// }
// spell.DealDamage(sim, result)
// }

// bonusPeriodicDamageMultiplier := 0 +
// 0.2*float64(shaman.Talents.StormEarthAndFire) +
// core.TernaryFloat64(shaman.HasSetBonus(ItemSetWorldbreakerGarb, 2), 0.2, 0) -
// 0.1*float64(shaman.Talents.BoomingEchoes)

// config.Dot = core.DotConfig{
// Aura: core.Aura{
// Label: "FlameShock",
// OnGain: func(aura *core.Aura, sim *core.Simulation) {
// shaman.LavaBurst.BonusCritRating += 100 * core.CritRatingPerCritChance
// },
// OnExpire: func(aura *core.Aura, sim *core.Simulation) {
// shaman.LavaBurst.BonusCritRating -= 100 * core.CritRatingPerCritChance
// },
// },
// NumberOfTicks: flameShockBaseNumberOfTicks,
// TickLength: time.Second * 3,
// AffectedByCastSpeed: true,

// OnSnapshot: func(sim *core.Simulation, target *core.Unit, dot *core.Dot, _ bool) {
// dot.SnapshotBaseDamage = 834/6 + 0.1*dot.Spell.SpellPower()
// dot.SnapshotCritChance = dot.Spell.SpellCritChance(target)

// dot.Spell.DamageMultiplierAdditive += bonusPeriodicDamageMultiplier
// dot.SnapshotAttackerMultiplier = dot.Spell.AttackerDamageMultiplier(dot.Spell.Unit.AttackTables[target.UnitIndex])
// dot.Spell.DamageMultiplierAdditive -= bonusPeriodicDamageMultiplier
// },
// OnTick: func(sim *core.Simulation, target *core.Unit, dot *core.Dot) {
// dot.CalcAndDealPeriodicSnapshotDamage(sim, target, dot.OutcomeSnapshotCrit)
// },
// }

// shaman.FlameShock = shaman.RegisterSpell(config)
// }

// func (shaman *Shaman) registerFrostShockSpell(shockTimer *core.Timer) {
// config := shaman.newShockSpellConfig(49236, core.SpellSchoolFrost, 0.18, shockTimer)
// config.Cast.CD.Duration -= time.Duration(shaman.Talents.BoomingEchoes) * time.Second
Expand All @@ -123,9 +60,9 @@ package shaman
// shaman.FrostShock = shaman.RegisterSpell(config)
// }

// func (shaman *Shaman) registerShocks() {
// shockTimer := shaman.NewTimer()
// shaman.registerEarthShockSpell(shockTimer)
// shaman.registerFlameShockSpell(shockTimer)
// shaman.registerFrostShockSpell(shockTimer)
// }
func (shaman *Shaman) registerShocks() {
shockTimer := shaman.NewTimer()
// shaman.registerEarthShockSpell(shockTimer)
shaman.registerFlameShockSpell(shockTimer)
// shaman.registerFrostShockSpell(shockTimer)
}
5 changes: 0 additions & 5 deletions ui/elemental_shaman/apls/default.apl.json

This file was deleted.

11 changes: 11 additions & 0 deletions ui/elemental_shaman/apls/phase_1.apl.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"type": "TypeAPL",
"prepullActions": [
{"action":{"castSpell":{"spellId":{"spellId":915,"rank":4}}},"doAtValue":{"const":{"val":"3.05"}}}
],
"priorityList": [
{"action":{"condition":{"cmp":{"op":"OpLe","lhs":{"dotRemainingTime":{"spellId":{"spellId":8052,"rank":2}}},"rhs":{"const":{"val":"2"}}}},"castSpell":{"spellId":{"spellId":8052,"rank":2}}}},
{"action":{"castSpell":{"spellId":{"spellId":408490}}}},
{"action":{"condition":{"cmp":{"op":"OpGt","lhs":{"dotRemainingTime":{"spellId":{"spellId":8052,"rank":2}}},"rhs":{"spellCastTime":{"spellId":{"spellId":915,"rank":4}}}}},"castSpell":{"spellId":{"spellId":915,"rank":4}}}}
]
}
6 changes: 4 additions & 2 deletions ui/elemental_shaman/presets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import * as PresetUtils from '../core/preset_utils.js';
import BlankGear from './gear_sets/blank.gear.json';
import Phase1Gear from './gear_sets/phase_1.gear.json';

import DefaultApl from './apls/default.apl.json';
import Phase1APL from './apls/phase_1.apl.json';

// Preset options for this spec.
// Eventually we will import these values for the raid sim too, so its good to
Expand All @@ -32,7 +32,9 @@ export const Phase1PresetGear = PresetUtils.makePresetGear('Phase 1', Phase1Gear

export const DefaultGear = Phase1PresetGear;

export const ROTATION_PRESET_DEFAULT = PresetUtils.makePresetAPLRotation('Default', DefaultApl);
export const Phase1PresetAPL = PresetUtils.makePresetAPLRotation('Phase 1', Phase1APL);

export const DefaultAPL = Phase1PresetAPL

// Default talents. Uses the wowhead calculator format, make the talents on
// https://wowhead.com/classic/talent-calc and copy the numbers in the url.
Expand Down
4 changes: 2 additions & 2 deletions ui/elemental_shaman/sim.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecElementalShaman, {
],
// Preset rotations that the user can quickly select.
rotations: [
Presets.ROTATION_PRESET_DEFAULT,
Presets.Phase1PresetAPL,
],
// Preset gear configurations that the user can quickly select.
gear: [
Expand All @@ -148,7 +148,7 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecElementalShaman, {
},

autoRotation: (_: Player<Spec.SpecElementalShaman>): APLRotation => {
return Presets.ROTATION_PRESET_DEFAULT.rotation.rotation!;
return Presets.DefaultAPL.rotation.rotation!;
},

raidSimPresets: [
Expand Down

0 comments on commit 5ac6ce3

Please sign in to comment.