diff --git a/elesim/README b/elesim/README
deleted file mode 100644
index 57ee905..0000000
--- a/elesim/README
+++ /dev/null
@@ -1,2 +0,0 @@
-Partially implemented classic simulator.
-Probably never going to finish because TBC is coming.
diff --git a/elesim/auras.go b/elesim/auras.go
deleted file mode 100644
index 0953eaa..0000000
--- a/elesim/auras.go
+++ /dev/null
@@ -1,109 +0,0 @@
-package elesim
-
-type Aura struct {
- ID string
- Duration int // ticks aura will apply
- OnCast func(c *Cast)
- OnSpellHit func(c *Cast)
- OnStruck func(c *Cast)
-}
-
-type Cast struct {
- Spell *Spell
- // Caster ... // Needed for onstruck effects?
-
- // Mutatable State
- ManaCost float64
- Hit float64
- Crit float64
- Spellpower float64
-}
-
-type Spell struct {
- ID string
- CastTime float64
- Cooldown int
- Mana float64
- MinDmg float64
- MaxDmg float64
- DamageType DamageType
- Coeff float64
-}
-
-type DamageType int
-
-const (
- DamageTypeUnknown DamageType = iota
- DamageTypeFire
- DamageTypeNature
- DamageTypeFrost
-
- // who cares
- DamageTypeShadow
- DamageTypeHoly
- DamageTypeArcane
-)
-
-func clearcasting() Aura {
- return Aura{
- Duration: 15 * tickPerSecond,
- OnCast: func(c *Cast) {
- debug("clearcasting...")
- c.ManaCost = 0
- },
- }
-}
-
-func zhc() Aura {
- dmgbonus := 204.0
-
- return Aura{
- Duration: 20 * tickPerSecond,
- OnCast: func(c *Cast) {
- debug("zhc(%.0f)...", dmgbonus)
- c.Spellpower += dmgbonus
- dmgbonus -= 17
- },
- }
-}
-
-func elemastery() Aura {
- return Aura{
- Duration: 99999999999999999,
- OnCast: func(c *Cast) {
- debug("ele mastery...")
- c.Crit = 1.01 // 101% chance of crit
- c.ManaCost = 0
- },
- }
-}
-
-func stormcaller() Aura {
- return Aura{
- Duration: 8 * tickPerSecond,
- OnCast: func(c *Cast) {
- debug("stormcaller...")
- c.Spellpower += 50
- },
- }
-}
-
-// spells
-var spells = []Spell{
- {ID: "LB4", CastTime: 2.0, MinDmg: 88, MaxDmg: 100, Mana: 50, DamageType: DamageTypeNature},
- {ID: "LB10", CastTime: 3.0, MinDmg: 428, MaxDmg: 477, Mana: 265, DamageType: DamageTypeNature},
- {ID: "CL4", CastTime: 2.5, Cooldown: 6, MinDmg: 505, MaxDmg: 564, Mana: 605, DamageType: DamageTypeNature},
-}
-
-var spellmap = map[string]*Spell{}
-
-func init() {
- for _, sp := range spells {
- sp2 := sp //wtf go?
- spp := &sp2
- if spp.Coeff == 0 {
- spp.Coeff = spp.CastTime / 3.5
- }
- spellmap[sp.ID] = spp
- }
-}
diff --git a/elesim/buffs.go b/elesim/buffs.go
deleted file mode 100644
index 4b7ce85..0000000
--- a/elesim/buffs.go
+++ /dev/null
@@ -1 +0,0 @@
-package elesim
diff --git a/elesim/sim.go b/elesim/sim.go
deleted file mode 100644
index f3d90b5..0000000
--- a/elesim/sim.go
+++ /dev/null
@@ -1,204 +0,0 @@
-package elesim
-
-import (
- "fmt"
- "math/rand"
- "strings"
-)
-
-var IsDebug = false
-
-func debug(s string, vals ...interface{}) {
- if IsDebug {
- fmt.Printf(s, vals...)
- }
-}
-
-func Sim(seconds int, stats Stats, spellOrder []string) (float64, int) {
- ticks := seconds * tickPerSecond
-
- // ticks until cast is complete
- currentMana := stats[StatMana]
- casting := 0
- // timeToRegen := 0
- castingSpell := ""
-
- spellIdx := 0
- cds := map[string]int{}
- auras := map[string]Aura{}
-
- totalDmg := 0.0
- castStats := map[string]struct {
- Num int
- Total float64
- }{}
- oomAt := 0
-
- for i := 0; i < ticks; i++ {
- casting--
-
- // MP5 regen
- currentMana += (stats[StatMP5] / 5.0) / float64(tickPerSecond)
- if currentMana > stats[StatMana] {
- currentMana = stats[StatMana]
- }
-
- if stats[StatMana]-currentMana >= 2250 && cds["potion"] < 1 {
- // Restores 1350 to 2250 mana. (2 Min Cooldown)
- currentMana += float64(1350 + rand.Intn(2250-1350))
- cds["potion"] = 120 * tickPerSecond
- debug("[%d] Used Mana Potion\n", i/tickPerSecond)
- }
- if stats[StatMana]-currentMana >= 1500 && cds["darkrune"] < 1 {
- // Restores 900 to 1500 mana. (2 Min Cooldown)
- currentMana += float64(900 + rand.Intn(1500-900))
- cds["darkrune"] = 120 * tickPerSecond
- debug("[%d] Used Mana Potion\n", i/tickPerSecond)
- }
-
- if castingSpell == "" && oomAt == 0 {
- // debug("(%0.0f/%0.0f mana)\n", currentMana, stats[StatMana])
- }
-
- if casting <= 0 {
- if castingSpell != "" {
- sp := spellmap[castingSpell]
- cast := &Cast{
- Spell: sp,
- ManaCost: float64(sp.Mana),
- Spellpower: stats[StatSpellDmg], // TODO: type specific bonuses...
- }
- if strings.HasPrefix(sp.ID, "LB") || strings.HasPrefix(sp.ID, "CL") {
- // totem of the storm
- cast.Spellpower += 33
- // Talent Convection
- cast.ManaCost *= 0.9
- }
-
- cast.Hit = 0.83 + stats[StatSpellHit]
- cast.Crit = stats[StatSpellCrit]
-
- for _, aur := range auras {
- if aur.OnCast != nil {
- aur.OnCast(cast)
- }
- }
-
- // TODO: generalize aura removal.
- if _, ok := auras["elemastery"]; ok {
- delete(auras, "elemastery")
- } else if _, ok := auras["cc"]; ok {
- delete(auras, "cc")
- }
-
- if rand.Float64() < cast.Hit {
- dmg := (float64(rand.Intn(int(sp.MaxDmg-sp.MinDmg))) + sp.MinDmg) + (stats[StatSpellDmg] * sp.Coeff)
-
- if rand.Float64() < cast.Crit {
- dmg *= 2
- debug("crit")
- } else {
- debug("hit")
- }
-
- if strings.HasPrefix(sp.ID, "LB") || strings.HasPrefix(sp.ID, "CL") {
- // Talent Concussion
- dmg *= 1.05
- }
-
- // Average Resistance = (Target's Resistance / (Caster's Level * 5)) * 0.75 "AR"
- // P(x) = 50% - 250%*|x - AR| <- where X is chance of resist
- // For now hardcode the 25% chance resist at 2.5% (this assumes bosses have 0 nature resist)
- if rand.Float64() < 0.025 { // chance of 25% resist
- dmg *= .75
- debug("(partial resist)")
- }
- debug(": %0.0f\n", dmg)
-
- totalDmg += dmg
- stat := castStats[sp.ID]
- stat.Num += 1
- stat.Total += dmg
- castStats[sp.ID] = stat
- } else {
- debug("miss.\n")
- }
-
- currentMana -= cast.ManaCost
-
- castingSpell = ""
- if sp.Cooldown > 0 {
- cds[sp.ID] = sp.Cooldown * tickPerSecond
- }
- if rand.Float64() < 0.1 {
- // TODO: make Elemental Focus an aura that applies an aura.
- // talent for clearcast chance on cast
- auras["cc"] = clearcasting()
- debug("\tGained Clearcasting.\n")
- }
- if rand.Float64() < 0.2 {
- auras["stc"] = stormcaller()
- debug("\tGained Stormcaller.\n")
- }
- continue
- } else {
- // Choose next spell
- so := spellOrder[spellIdx]
-
- isclearcasting := auras["cc"].Duration > 0 || auras["elemastery"].Duration > 0
-
- // anytime ZHC AND Ele Mastery are up, pop!
- if cds["zhc"] <= 0 && cds["elemastery"] <= 0 {
- // Apply auras
- auras["zhc"] = zhc()
- auras["elemastery"] = elemastery()
-
- cds["zhc"] = 120 * tickPerSecond
- cds["elemastery"] = 180 * tickPerSecond
- }
-
- sp := spellmap[so]
- cost := sp.Mana
- if strings.HasPrefix(sp.ID, "LB") || strings.HasPrefix(sp.ID, "CL") {
- // Talent to reduce mana cost by 10%
- cost *= 0.9
- }
- if cds[so] == 0 && (currentMana >= sp.Mana || isclearcasting) {
- castTime := spellmap[so].CastTime
- if strings.HasPrefix(sp.ID, "LB") || strings.HasPrefix(sp.ID, "CL") {
- // Talent to reduce cast time.
- castTime -= 1
- }
- casting = int(castTime * float64(tickPerSecond))
- castingSpell = sp.ID
- spellIdx++
- if spellIdx == len(spellOrder) {
- spellIdx = 0
- }
- debug("[%d] Casting %s ...", i/tickPerSecond, sp.ID)
- } else if !isclearcasting && currentMana < 200 && oomAt == 0 {
- oomAt = i / tickPerSecond
- }
-
- }
- }
- // CDS
- for k := range cds {
- cds[k]--
- if cds[k] <= 0 {
- delete(cds, k)
- }
- }
- for k, v := range auras {
- nv := v
- nv.Duration--
- if nv.Duration > 0 {
- auras[k] = nv
- } else {
- delete(auras, k)
- }
- }
- }
-
- return totalDmg, oomAt
-}
diff --git a/elesim/stats.go b/elesim/stats.go
deleted file mode 100644
index 9f29715..0000000
--- a/elesim/stats.go
+++ /dev/null
@@ -1,53 +0,0 @@
-package elesim
-
-import "fmt"
-
-var tickPerSecond = 30
-
-type Stats []float64
-
-type Stat int
-
-const (
- StatInt Stat = iota
- StatSpellCrit
- StatSpellHit
- StatSpellDmg
- StatMP5
- StatMana
- StatSpellPen
-)
-
-func (s Stat) StatName() string {
- switch s {
- case StatInt:
- return "StatInt"
- case StatSpellCrit:
- return "StatSpellCrit"
- case StatSpellHit:
- return "StatSpellHit"
- case StatSpellDmg:
- return "StatSpellDmg"
- case StatMP5:
- return "StatMP5"
- case StatMana:
- return "StatMana"
- case StatSpellPen:
- return "StatSpellPen"
- }
-
- return "none"
-}
-
-func (st Stats) Print() {
- fmt.Printf("Stats:\n")
-
- for k, v := range st {
- if v < 50 {
- fmt.Printf("\t%s: %0.3f\n", Stat(k).StatName(), v)
- } else {
- fmt.Printf("\t%s: %0.0f\n", Stat(k).StatName(), v)
- }
-
- }
-}
diff --git a/elesim/ui/index.html b/elesim/ui/index.html
deleted file mode 100644
index 2cbccae..0000000
--- a/elesim/ui/index.html
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
Assumptions:
- Standard Elemental Build
- Elemental: Convection, Concussion, Call of Thunder, Elemental Focus, Elemental Fury, Lightning Mastery, Elemental Mastery
- Resto: Natures Guidance, Tidal Mastery
- Buffs:
- World: DMT, Ony, Songflower, ZG
- Raid: Arcane Brilliance, Gift of the Wild
- Hardcoded Gear:
- ZHC + T2.5 3p + Totem of the Storm
- TODO: Make these configurable
- Casting Rules:
- No network latency and perfect reaction times.
- Pop ZHC + Ele Mastery when both are off CD.
-
- Stats:
-
-
-
\ No newline at end of file
diff --git a/go.mod b/go.mod
index fc1a4ff..dd2663d 100644
--- a/go.mod
+++ b/go.mod
@@ -1,3 +1,3 @@
-module gitlab.com/lologarithm/wowsim
+module github.com/lologarithm/wowsim
go 1.15
diff --git a/itemparser/main.go b/itemparser/main.go
index 7e8cb0e..21735b8 100644
--- a/itemparser/main.go
+++ b/itemparser/main.go
@@ -9,7 +9,7 @@ import (
"strconv"
"strings"
- "gitlab.com/lologarithm/wowsim/tbc"
+ "github.com/lologarithm/wowsim/tbc"
)
// This was used to parse a CSV from an item spreadsheet.
diff --git a/main.go b/main.go
index 7d75465..2a157cf 100644
--- a/main.go
+++ b/main.go
@@ -11,8 +11,8 @@ import (
"strings"
"time"
- "gitlab.com/lologarithm/wowsim/elesim"
- "gitlab.com/lologarithm/wowsim/tbc"
+ "github.com/lologarithm/wowsim/elesim"
+ "github.com/lologarithm/wowsim/tbc"
)
// /script print(GetSpellBonusDamage(4))
@@ -40,7 +40,6 @@ import (
func main() {
var isDebug = flag.Bool("debug", false, "Include --debug to spew the entire simulation log.")
var runWebUI = flag.Bool("web", false, "Use to run sim in web interface instead of in terminal")
- var useTBC = flag.Bool("tbc", false, "Use to run sim using TBC stats / effects")
flag.Parse()
elesim.IsDebug = *isDebug
@@ -50,187 +49,70 @@ func main() {
log.Printf("Closing: %s", http.ListenAndServe(":3333", nil))
}
- if *useTBC {
- gear := tbc.NewEquipmentSet(
- "Shamanistic Helmet of Second Sight",
- "Brooch of Heightened Potential",
- "Pauldrons of Wild Magic",
- "Ogre Slayer's Cover",
- "Tidefury Chestpiece",
- "World's End Bracers",
- "Earth Mantle Handwraps",
- "Wave-Song Girdle",
- "Stormsong Kilt",
- "Magma Plume Boots",
- "Cobalt Band of Tyrigosa",
- "Scintillating Coral Band",
- "Totem of the Void",
- "Khadgar's Knapsack",
- "Bleeding Hollow Warhammer",
- )
-
- gearStats := gear.Stats()
- fmt.Printf("Gear Stats:\n")
- gearStats.Print()
-
- stats := tbc.Stats{
- tbc.StatInt: 104, // Base
- tbc.StatSpellCrit: 48.62 + 243, // Base + Talents + Totem
- tbc.StatSpellHit: 151.2, // Totem + Talents
- tbc.StatSpellDmg: 101, // Totem
- tbc.StatMP5: 50 + 25, // Water Shield + Mana Stream
- tbc.StatMana: 2958, // level 70 shaman
- tbc.StatHaste: 0,
- tbc.StatSpellPen: 0,
- }
-
- buffs := tbc.Stats{
- tbc.StatInt: 40, //arcane int
- tbc.StatSpellCrit: 0,
- tbc.StatSpellHit: 0,
- tbc.StatSpellDmg: 42, // sup wiz oil
- tbc.StatMP5: 0,
- tbc.StatMana: 0,
- tbc.StatHaste: 0,
- tbc.StatSpellPen: 0,
- }
-
- for i, v := range buffs {
- stats[i] += v
- stats[i] += gearStats[i]
- }
-
- stats[tbc.StatInt] *= 1.1 // blessing of kings
-
- stats[tbc.StatSpellCrit] += (stats[tbc.StatInt] / 80) / 100 // 1% crit per 59.5 int
- stats[tbc.StatMana] += stats[tbc.StatInt] * 15
-
- fmt.Printf("Final Stats:\n")
- stats.Print()
- sims := 10000
- if *isDebug {
- sims = 1
- }
- results := runTBCSim(stats, 120, sims)
- for _, res := range results {
- fmt.Printf("\n%s\n", res)
- }
- } else {
- stats := elesim.Stats{
- elesim.StatInt: 86 + 191, // base + gear
- elesim.StatSpellCrit: 0.022 + 0.04 + .11, // base crit + gear + talents
- elesim.StatSpellHit: 0.03 + 0.03, // talents + gear
- elesim.StatSpellDmg: 474, // gear
- elesim.StatMP5: 33, //
- elesim.StatMana: 1240,
- elesim.StatSpellPen: 0,
- }
-
- buffs := elesim.Stats{
- elesim.StatSpellCrit: 0.18, // world buffs DMT+Ony+Songflower
- elesim.StatInt: 15, // songflower
- }
- buffs[elesim.StatInt] += 31 // arcane brill
- buffs[elesim.StatInt] += 12 // GOTW
- // buffs[elesim.StatInt] += 10 // runn tum tuber
-
- for i, v := range buffs {
- // ZG Buff
- if elesim.Stat(i) == elesim.StatInt {
- stats[i] = stats[i] * 1.15
- }
-
- // I believe ZG buff applies before other buffs
- stats[i] += v
- }
- stats[elesim.StatSpellCrit] += (stats[elesim.StatInt] / 59.5) / 100 // 1% crit per 59.5 int
- stats[elesim.StatMana] += stats[elesim.StatInt] * 15
- stats.Print()
-
- // hardcode 120s 200 sims
- results := runSim(stats, 120, 500)
- for _, res := range results {
- fmt.Printf("\n%s\n", res)
- }
+ gear := tbc.NewEquipmentSet(
+ "Shamanistic Helmet of Second Sight",
+ "Brooch of Heightened Potential",
+ "Pauldrons of Wild Magic",
+ "Ogre Slayer's Cover",
+ "Tidefury Chestpiece",
+ "World's End Bracers",
+ "Earth Mantle Handwraps",
+ "Wave-Song Girdle",
+ "Stormsong Kilt",
+ "Magma Plume Boots",
+ "Cobalt Band of Tyrigosa",
+ "Scintillating Coral Band",
+ "Totem of the Void",
+ "Khadgar's Knapsack",
+ "Bleeding Hollow Warhammer",
+ )
+
+ gearStats := gear.Stats()
+ fmt.Printf("Gear Stats:\n")
+ gearStats.Print()
+
+ stats := tbc.Stats{
+ tbc.StatInt: 104, // Base
+ tbc.StatSpellCrit: 48.62 + 243, // Base + Talents + Totem
+ tbc.StatSpellHit: 151.2, // Totem + Talents
+ tbc.StatSpellDmg: 101, // Totem
+ tbc.StatMP5: 50 + 25, // Water Shield + Mana Stream
+ tbc.StatMana: 2958, // level 70 shaman
+ tbc.StatHaste: 0,
+ tbc.StatSpellPen: 0,
}
-}
-
-func runSim(stats elesim.Stats, seconds int, numSims int) []string {
- fmt.Printf("\nSim Duration: %d sec\nNum Simulations: %d\n", seconds, numSims)
- spellOrders := [][]string{
- // {"CL4", "LB10", "LB10", "LB10"},
- {"LB10"},
- // {"LB10", "LB4"},
+ buffs := tbc.Stats{
+ tbc.StatInt: 40, //arcane int
+ tbc.StatSpellCrit: 0,
+ tbc.StatSpellHit: 0,
+ tbc.StatSpellDmg: 42, // sup wiz oil
+ tbc.StatMP5: 0,
+ tbc.StatMana: 0,
+ tbc.StatHaste: 0,
+ tbc.StatSpellPen: 0,
}
- statchan := make(chan string, 3)
- for _, spells := range spellOrders {
- go func(spo []string) {
- simDmgs := []float64{}
- simOOMs := []int{}
-
- for ns := 0; ns < numSims; ns++ {
- dmg, oomat := elesim.Sim(seconds, stats, spo)
- simDmgs = append(simDmgs, dmg)
- simOOMs = append(simOOMs, oomat)
- }
-
- totalDmg := 0.0
- tdSq := totalDmg
- max := 0.0
- for _, dmg := range simDmgs {
- totalDmg += dmg
- tdSq += dmg * dmg
-
- if dmg > max {
- max = dmg
- }
- }
+ for i, v := range buffs {
+ stats[i] += v
+ stats[i] += gearStats[i]
+ }
- meanSq := tdSq / float64(numSims)
- mean := totalDmg / float64(numSims)
- stdev := math.Sqrt(meanSq - mean*mean)
+ stats[tbc.StatInt] *= 1.1 // blessing of kings
- output := ""
- output += fmt.Sprintf("Spell Order: %v\n", spo)
- output += fmt.Sprintf("DPS:")
- output += fmt.Sprintf("\tMean: %0.1f\n", (mean / float64(seconds)))
- output += fmt.Sprintf("\tMax: %0.1f\n", (max / float64(seconds)))
- output += fmt.Sprintf("\tStd.Dev: %0.1f\n", stdev/float64(seconds))
+ stats[tbc.StatSpellCrit] += (stats[tbc.StatInt] / 80) / 100 // 1% crit per 59.5 int
+ stats[tbc.StatMana] += stats[tbc.StatInt] * 15
- ooms := 0
- numOoms := 0
- for _, oa := range simOOMs {
- ooms += oa
- if oa > 0 {
- numOoms++
- }
- }
-
- avg := 0
- if numOoms > 0 {
- avg = ooms / numOoms
- }
- output += fmt.Sprintf("Went OOM: %d/%d sims\n", numOoms, numSims)
- if numOoms > 0 {
- output += fmt.Sprintf("Avg OOM Time: %d seconds\n", avg)
- }
- statchan <- output
- }(spells)
+ fmt.Printf("Final Stats:\n")
+ stats.Print()
+ sims := 10000
+ if *isDebug {
+ sims = 1
}
-
- results := []string{}
- for i := 0; i < len(spellOrders); i++ {
- results = append(results, <-statchan)
+ results := runTBCSim(stats, 120, sims)
+ for _, res := range results {
+ fmt.Printf("\n%s\n", res)
}
-
- return results
-
- // fmt.Printf("Casts: \n")
- // for k, v := range castStats {
- // fmt.Printf("\t%s: %d\n", k, v.Num)
- // }
}
func runTBCSim(stats tbc.Stats, seconds int, numSims int) []string {
@@ -260,6 +142,7 @@ func runTBCSim(stats tbc.Stats, seconds int, numSims int) []string {
histogram[rv] += 1
}
+ // TODO: do this better... for now just dumping histograph data to disk lol.
out := ""
for k, v := range histogram {
out += strconv.Itoa(k) + "," + strconv.Itoa(v) + "\n"
@@ -329,9 +212,4 @@ func runTBCSim(stats tbc.Stats, seconds int, numSims int) []string {
}
return results
-
- // fmt.Printf("Casts: \n")
- // for k, v := range castStats {
- // fmt.Printf("\t%s: %d\n", k, v.Num)
- // }
}
diff --git a/ui/main.go b/ui/main.go
index 3589ed9..e897dcf 100644
--- a/ui/main.go
+++ b/ui/main.go
@@ -8,7 +8,7 @@ import (
"syscall/js"
"time"
- "gitlab.com/lologarithm/wowsim/tbc"
+ "github.com/lologarithm/wowsim/tbc"
)
func main() {
diff --git a/web.go b/web.go
index 2e136be..ed2c211 100644
--- a/web.go
+++ b/web.go
@@ -7,8 +7,7 @@ import (
"strconv"
"strings"
- "gitlab.com/lologarithm/wowsim/elesim"
- "gitlab.com/lologarithm/wowsim/tbc"
+ "github.com/lologarithm/wowsim/tbc"
)
func init() {
@@ -21,87 +20,9 @@ func init() {
log.Printf("Serving: %s", req.URL.String())
fs.ServeHTTP(resp, req)
})
- http.HandleFunc("/tui/", func(resp http.ResponseWriter, req *http.Request) {
- resp.Header().Add("Cache-Control", "no-cache")
- if strings.HasSuffix(req.URL.Path, ".wasm") {
- resp.Header().Set("content-type", "application/wasm")
- }
- log.Printf("Serving: %s", req.URL.String())
- fs.ServeHTTP(resp, req)
- })
- http.HandleFunc("/sim", simPage)
http.HandleFunc("/simtbc", simTBCPage)
}
-func simPage(w http.ResponseWriter, r *http.Request) {
- fileData, err := ioutil.ReadFile("elesim/ui/index.html")
- if err != nil {
- log.Fatalf("Failed to read file: %s", err)
- }
-
- if r.ContentLength > 0 {
- // parse form.
- r.ParseForm()
- intv, _ := strconv.Atoi(r.FormValue("int"))
- sph, _ := strconv.ParseFloat(r.FormValue("spellhit"), 64)
- spc, _ := strconv.ParseFloat(r.FormValue("spellcrit"), 64)
- spd, _ := strconv.ParseFloat(r.FormValue("spelldmg"), 64)
- mp5, _ := strconv.ParseFloat(r.FormValue("mp5"), 64)
- spp, _ := strconv.ParseFloat(r.FormValue("spellpen"), 64)
-
- stats := elesim.Stats{
- elesim.StatInt: float64(intv) + 86, // Add base stats
- elesim.StatSpellCrit: spc/100 + 0.022 + .11, // Add base+talents to gear
- elesim.StatSpellHit: sph/100 + 0.03, // Add talent hit
- elesim.StatSpellDmg: spd, // gear
- elesim.StatMP5: mp5, // gear
- elesim.StatMana: 1240, // Base Mana L60 Troll Shaman
- elesim.StatSpellPen: spp, //
- }
-
- // stats := elesim.Stats{
- // elesim.StatInt: 86 + 191, // base + gear
- // elesim.StatSpellCrit: 0.022 + 0.04 + .11, // base crit + gear + talents
- // elesim.StatSpellHit: 0.03 + 0.03, // talents + gear
- // elesim.StatSpellDmg: 474, // gear
- // elesim.StatMP5: 31 + 4 + 110, //
- // elesim.StatMana: 1240,
- // elesim.StatSpellPen: 0,
- // }
-
- buffs := elesim.Stats{
- // elesim.StatSpellCrit: 0.18, // world buffs DMT+Ony+Songflower
- // elesim.StatInt: 15, // songflower
- }
- // buffs[elesim.StatInt] += 31 // arcane brill
- // buffs[elesim.StatInt] += 12 // GOTW
- // buffs[elesim.StatInt] += 10 // runn tum tuber
-
- for i, v := range buffs {
- // ZG Buff
- // if elesim.Stat(i) == elesim.StatInt {
- // stats[i] = stats[i] * 1.15
- // }
- // I believe ZG buff applies before other buffs
- stats[i] += v
- }
- stats[elesim.StatSpellCrit] += (stats[elesim.StatInt] / 59.5) / 100 // 1% crit per 59.5 int
- stats[elesim.StatMana] += stats[elesim.StatInt] * 15
-
- stats.Print()
-
- results := runSim(stats, 60, 5000)
- fileData = append(fileData, ""...)
- for _, res := range results {
- fileData = append(fileData, res...)
- fileData = append(fileData, "\n"...)
- }
- fileData = append(fileData, "
"...)
- }
-
- w.Write(fileData)
-}
-
func simTBCPage(w http.ResponseWriter, r *http.Request) {
fileData, err := ioutil.ReadFile("tbc/ui/index.html")
if err != nil {