From 4ef2d5df5ed15c7e66b6f7d25c0ebcd2db849335 Mon Sep 17 00:00:00 2001 From: James Tanner Date: Thu, 15 Dec 2022 17:56:39 -0500 Subject: [PATCH] Expose BlockValueMultiplier pseudostat in the UI to fix stat display issue --- proto/common.proto | 1 + sim/core/attack.go | 8 ++++++ sim/core/character.go | 7 ++++- ui/core/components/character_stats.ts | 31 +++++++++++++---------- ui/core/components/exporters.ts | 2 -- ui/core/components/stat_weights_action.ts | 15 +++++++++-- ui/core/proto_utils/names.ts | 2 ++ 7 files changed, 48 insertions(+), 18 deletions(-) diff --git a/proto/common.proto b/proto/common.proto index fad3f8e2fa..f035c890b5 100644 --- a/proto/common.proto +++ b/proto/common.proto @@ -121,6 +121,7 @@ enum PseudoStat { PseudoStatMainHandDps = 0; PseudoStatOffHandDps = 1; PseudoStatRangedDps = 2; + PseudoStatBlockValueMultiplier = 3; } message UnitStats { diff --git a/sim/core/attack.go b/sim/core/attack.go index 9090b6ccb4..d19bc4c4e9 100644 --- a/sim/core/attack.go +++ b/sim/core/attack.go @@ -27,6 +27,14 @@ type Weapon struct { SpellSchool SpellSchool } +func (w Weapon) DPS() float64 { + if w.SwingSpeed == 0 { + return 0 + } else { + return (w.BaseDamageMin + w.BaseDamageMax) / 2.0 / w.SwingSpeed + } +} + func (w Weapon) WithBonusDPS(bonusDps float64) Weapon { newWeapon := w bonusSwingDamage := bonusDps * w.SwingSpeed diff --git a/sim/core/character.go b/sim/core/character.go index 6842af76a7..50a7d45ab5 100644 --- a/sim/core/character.go +++ b/sim/core/character.go @@ -538,7 +538,12 @@ func (character *Character) doneIteration(sim *Simulation) { } func (character *Character) GetPseudoStatsProto() []float64 { - return nil + vals := make([]float64, stats.PseudoStatsLen) + vals[proto.PseudoStat_PseudoStatMainHandDps] = character.WeaponFromMainHand(0).DPS() + vals[proto.PseudoStat_PseudoStatOffHandDps] = character.WeaponFromOffHand(0).DPS() + vals[proto.PseudoStat_PseudoStatRangedDps] = character.WeaponFromRanged(0).DPS() + vals[proto.PseudoStat_PseudoStatBlockValueMultiplier] = character.PseudoStats.BlockValueMultiplier + return vals } func (character *Character) GetMetricsProto() *proto.UnitMetrics { diff --git a/ui/core/components/character_stats.ts b/ui/core/components/character_stats.ts index 5db251e91a..761cdd3bd6 100644 --- a/ui/core/components/character_stats.ts +++ b/ui/core/components/character_stats.ts @@ -1,4 +1,4 @@ -import { Stat, Class } from '..//proto/common.js'; +import { Stat, Class, PseudoStat } from '..//proto/common.js'; import { TristateEffect } from '..//proto/common.js' import { getClassStatName, statOrder } from '..//proto_utils/names.js'; import { Stats } from '..//proto_utils/stats.js'; @@ -87,13 +87,13 @@ export class CharacterStats extends Component { this.stats.forEach((stat, idx) => { let fragment = document.createElement('fragment'); fragment.innerHTML = ` - ${this.statDisplayString(finalStats, stat)} + ${this.statDisplayString(finalStats, finalStats, stat)} ` let valueElem = fragment.children[0] as HTMLElement; this.valueElems[idx].querySelector('.stat-value-link')?.remove() this.valueElems[idx].prepend(valueElem); - let bonusStatValue = player.getBonusStats().getStat(stat); + let bonusStatValue = bonusStats.getStat(stat); if (bonusStatValue == 0) { valueElem.classList.remove('text-success', 'text-danger'); @@ -109,39 +109,39 @@ export class CharacterStats extends Component { valueElem.setAttribute('data-bs-title', `
Base: - ${this.statDisplayString(baseDelta, stat)} + ${this.statDisplayString(baseStats, baseDelta, stat)}
Gear: - ${this.statDisplayString(gearDelta, stat)} + ${this.statDisplayString(gearStats, gearDelta, stat)}
Talents: - ${this.statDisplayString(talentsDelta, stat)} + ${this.statDisplayString(talentsStats, talentsDelta, stat)}
Buffs: - ${this.statDisplayString(buffsDelta, stat)} + ${this.statDisplayString(buffsStats, buffsDelta, stat)}
Consumes: - ${this.statDisplayString(consumesDelta, stat)} + ${this.statDisplayString(consumesStats, consumesDelta, stat)}
${debuffStats.getStat(stat) == 0 ? '' : `
Debuffs: - ${this.statDisplayString(debuffStats, stat)} + ${this.statDisplayString(debuffStats, debuffStats, stat)}
`} ${bonusStatValue == 0 ? '' : `
Bonus: - ${this.statDisplayString(this.player.getBonusStats(), stat)} + ${this.statDisplayString(bonusStats, bonusStats, stat)}
`}
Total: - ${this.statDisplayString(finalStats, stat)} + ${this.statDisplayString(finalStats, finalStats, stat)}
`); @@ -149,8 +149,13 @@ export class CharacterStats extends Component { }); } - private statDisplayString(stats: Stats, stat: Stat): string { - const rawValue = stats.getStat(stat); + private statDisplayString(stats: Stats, deltaStats: Stats, stat: Stat): string { + let rawValue = deltaStats.getStat(stat); + + if (stat == Stat.StatBlockValue) { + rawValue *= stats.getPseudoStat(PseudoStat.PseudoStatBlockValueMultiplier) || 1; + } + let displayStr = String(Math.round(rawValue)); if (stat == Stat.StatMeleeHit) { diff --git a/ui/core/components/exporters.ts b/ui/core/components/exporters.ts index 2b7be8cff8..00ec1416b1 100644 --- a/ui/core/components/exporters.ts +++ b/ui/core/components/exporters.ts @@ -181,7 +181,6 @@ export class Individual80UEPExporter extends Exporter { } static pseudoStatNames: Partial> = { [PseudoStat.PseudoStatMainHandDps]: 'dps', - [PseudoStat.PseudoStatOffHandDps]: '', [PseudoStat.PseudoStatRangedDps]: 'rangedDps', } } @@ -270,7 +269,6 @@ export class IndividualPawnEPExporter extends Exporter { } static pseudoStatNames: Partial> = { [PseudoStat.PseudoStatMainHandDps]: 'MeleeDps', - [PseudoStat.PseudoStatOffHandDps]: '', [PseudoStat.PseudoStatRangedDps]: 'RangedDps', } } diff --git a/ui/core/components/stat_weights_action.ts b/ui/core/components/stat_weights_action.ts index 975c0ccc90..f3cc7336e5 100644 --- a/ui/core/components/stat_weights_action.ts +++ b/ui/core/components/stat_weights_action.ts @@ -203,8 +203,7 @@ class EpWeightsMenu extends Popup { this.tableBody.innerHTML = ''; this.tableBody.appendChild(this.tableHeader); - const allUnitStats = UnitStat.getAll(); - allUnitStats.forEach(stat => { + EpWeightsMenu.epUnitStats.forEach(stat => { const row = this.makeTableRow(stat, iterations, result); if ((stat.isStat() && !this.epStats.includes(stat.getStat())) || (stat.isPseudoStat() && !this.epPseudoStats.includes(stat.getPseudoStat()))) { row.classList.add('non-ep-stat'); @@ -538,6 +537,18 @@ class EpWeightsMenu extends Popup { bestGemEP: bestGemEP, }; } + + private static epUnitStats: Array = UnitStat.getAll().filter(stat => { + if (stat.isStat()) { + return true; + } else { + return [ + PseudoStat.PseudoStatMainHandDps, + PseudoStat.PseudoStatOffHandDps, + PseudoStat.PseudoStatRangedDps, + ].includes(stat.getPseudoStat()); + } + }); } interface BestGemsResult { diff --git a/ui/core/proto_utils/names.ts b/ui/core/proto_utils/names.ts index 131adf12e0..f91ef9a392 100644 --- a/ui/core/proto_utils/names.ts +++ b/ui/core/proto_utils/names.ts @@ -186,11 +186,13 @@ export const pseudoStatOrder: Array = [ PseudoStat.PseudoStatMainHandDps, PseudoStat.PseudoStatOffHandDps, PseudoStat.PseudoStatRangedDps, + PseudoStat.PseudoStatBlockValueMultiplier, ]; export const pseudoStatNames: Record = { [PseudoStat.PseudoStatMainHandDps]: 'Main Hand DPS', [PseudoStat.PseudoStatOffHandDps]: 'Off Hand DPS', [PseudoStat.PseudoStatRangedDps]: 'Ranged DPS', + [PseudoStat.PseudoStatBlockValueMultiplier]: 'Block Value Multiplier', }; export function getClassStatName(stat: Stat, playerClass: Class): string {