From ed1aa8e7d5a857274458213d33d37b68c22fdd3f Mon Sep 17 00:00:00 2001 From: Ben Echols Date: Tue, 30 Mar 2021 22:25:14 -0600 Subject: [PATCH] Removed old sim --- elesim/README | 2 - elesim/auras.go | 109 -------------------- elesim/buffs.go | 1 - elesim/sim.go | 204 ------------------------------------- elesim/stats.go | 53 ---------- elesim/ui/index.html | 36 ------- go.mod | 2 +- itemparser/main.go | 2 +- main.go | 238 +++++++++++-------------------------------- ui/main.go | 2 +- web.go | 81 +-------------- 11 files changed, 62 insertions(+), 668 deletions(-) delete mode 100644 elesim/README delete mode 100644 elesim/auras.go delete mode 100644 elesim/buffs.go delete mode 100644 elesim/sim.go delete mode 100644 elesim/stats.go delete mode 100644 elesim/ui/index.html 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 {