diff --git a/proto/api.proto b/proto/api.proto index bca887f4f6..b04504c891 100644 --- a/proto/api.proto +++ b/proto/api.proto @@ -180,76 +180,82 @@ message ActionMetrics { // Metrics for a specific action, when cast at a particular target. message TargetedActionMetrics { // Raid/Target Index of the unit these metrics are targeted at. - int32 unit_index = 12; + int32 unit_index = 1; // # of times this action was used by the agent. - int32 casts = 1; + int32 casts = 2; // # of times this action hit a target. For cleave spells this can be larger than casts. - int32 hits = 2; + int32 hits = 3; // # of times this action was a critical strike. - int32 crits = 3; + int32 crits = 4; // # of times this action ticked on a target. - int32 ticks = 21; + int32 ticks = 5; // # of times this action was a critical tick on a target. - int32 crit_ticks = 22; + int32 crit_ticks = 6; // # of times this action was a Miss or Resist. - int32 misses = 4; + int32 misses = 7; // # of times this action was a Dodge. - int32 dodges = 5; + int32 dodges = 8; // # of times this action was a Parry. - int32 parries = 6; + int32 parries = 9; // # of times this action was a Block. - int32 blocks = 7; + int32 blocks = 10; // # of times this action was a Critical Block. - int32 crit_blocks = 20; + int32 crit_blocks = 11; // # of times this action was a Glance. - int32 glances = 8; + int32 glances = 12; + + // # of times this action was a Glancing Block. + int32 glance_blocks = 13; // Total damage done to this target by this action. - double damage = 9; + double damage = 14; // Total critical damage done to this target by this action. double crit_damage = 15; // Total tick damage done to this target by this action. - double tick_damage = 23; + double tick_damage = 16; // Total critical tick damage done to this target by this action. - double crit_tick_damage = 24; + double crit_tick_damage = 17; + + // Total glancing damage done to this target by this action. + double glance_damage = 18; // Total glancing damage done to this target by this action. - double glance_damage = 17; + double glance_block_damage = 19; // Total block damage done to this target by this action. - double block_damage = 18; + double block_damage = 20; // Total critical block damage done to this target by this action. - double crit_block_damage = 19; + double crit_block_damage = 21; // Total threat done to this target by this action. - double threat = 10; + double threat = 22; // Total healing done to this target by this action. - double healing = 11; + double healing = 23; // Total critical healing done to this target by this action. - double crit_healing = 16; + double crit_healing = 24; // Total shielding done to this target by this action. - double shielding = 13; + double shielding = 25; // Total time spent casting this action, in milliseconds, either from hard casts, GCD, or channeling. - double cast_time_ms = 14; + double cast_time_ms = 26; } message AggregatorData { diff --git a/sim/core/flags.go b/sim/core/flags.go index 07e6c7f18c..450858e136 100644 --- a/sim/core/flags.go +++ b/sim/core/flags.go @@ -136,14 +136,16 @@ func (ho HitOutcome) String() string { return "Dodge" } else if ho.Matches(OutcomeParry) { return "Parry" - } else if ho.Matches(OutcomeGlance) { - return "Glance" } else if ho.Matches(OutcomeBlock) { if ho.Matches(OutcomeCrit) { return "CriticalBlock" + } else if ho.Matches(OutcomeGlance) { + return "GlanceBlock" } else { return "Block" } + } else if ho.Matches(OutcomeGlance) { + return "Glance" } else if ho.Matches(OutcomeCrit) { return "Crit" + ho.PartialResistString() } else if ho.Matches(OutcomeHit) { diff --git a/sim/core/metrics_aggregator.go b/sim/core/metrics_aggregator.go index 39dddbd53a..cba19f0d2e 100644 --- a/sim/core/metrics_aggregator.go +++ b/sim/core/metrics_aggregator.go @@ -148,89 +148,95 @@ func (actionMetrics *ActionMetrics) ToProto(actionID ActionID) *proto.ActionMetr // Metric totals for a spell against a specific target, for the current iteration. type SpellMetrics struct { - Casts int32 - Misses int32 - Hits int32 - Crits int32 - Ticks int32 - CritTicks int32 - Crushes int32 - Dodges int32 - Glances int32 - Parries int32 - Blocks int32 - CritBlocks int32 - - TotalDamage float64 // Damage done by all casts of this spell. - TotalCritDamage float64 // Damage done by all critical casts of this spell. - TotalTickDamage float64 // Damage done by all dots of this spell. - TotalCritTickDamage float64 // Damage done by all critical dots of this spell. - TotalGlanceDamage float64 // Damage done by all glance casts of this spell. - TotalBlockDamage float64 // Damage done by all block casts of this spell. - TotalCritBlockDamage float64 // Damage done by all critical block casts of this spell. - TotalThreat float64 // Threat generated by all casts of this spell. - TotalHealing float64 // Healing done by all casts of this spell. - TotalCritHealing float64 // Healing done by all critical casts of this spell. - TotalShielding float64 // Shielding done by all casts of this spell. - TotalCastTime time.Duration + Casts int32 + Misses int32 + Hits int32 + Crits int32 + Ticks int32 + CritTicks int32 + Crushes int32 + Dodges int32 + Parries int32 + Blocks int32 + CritBlocks int32 + Glances int32 + GlanceBlocks int32 + + TotalDamage float64 // Damage done by all casts of this spell. + TotalCritDamage float64 // Damage done by all critical casts of this spell. + TotalTickDamage float64 // Damage done by all dots of this spell. + TotalCritTickDamage float64 // Damage done by all critical dots of this spell. + TotalGlanceDamage float64 // Damage done by all glance casts of this spell. + TotalGlanceBlockDamage float64 // Damage done by all glance block casts of this spell. + TotalBlockDamage float64 // Damage done by all block casts of this spell. + TotalCritBlockDamage float64 // Damage done by all critical block casts of this spell. + TotalThreat float64 // Threat generated by all casts of this spell. + TotalHealing float64 // Healing done by all casts of this spell. + TotalCritHealing float64 // Healing done by all critical casts of this spell. + TotalShielding float64 // Shielding done by all casts of this spell. + TotalCastTime time.Duration } type TargetedActionMetrics struct { UnitIndex int32 - Casts int32 - Hits int32 - Crits int32 - Ticks int32 - CritTicks int32 - Misses int32 - Dodges int32 - Parries int32 - Blocks int32 - CritBlocks int32 - Glances int32 - - Damage float64 - CritDamage float64 - TickDamage float64 - CritTickDamage float64 - GlanceDamage float64 - BlockDamage float64 - CritBlockDamage float64 - Threat float64 - Healing float64 - CritHealing float64 - Shielding float64 - CastTime time.Duration + Casts int32 + Hits int32 + Crits int32 + Ticks int32 + CritTicks int32 + Misses int32 + Dodges int32 + Parries int32 + Blocks int32 + CritBlocks int32 + Glances int32 + GlanceBlocks int32 + + Damage float64 + CritDamage float64 + TickDamage float64 + CritTickDamage float64 + GlanceDamage float64 + GlanceBlockDamage float64 + BlockDamage float64 + CritBlockDamage float64 + Threat float64 + Healing float64 + CritHealing float64 + Shielding float64 + CastTime time.Duration } func (tam *TargetedActionMetrics) ToProto() *proto.TargetedActionMetrics { return &proto.TargetedActionMetrics{ UnitIndex: tam.UnitIndex, - Casts: tam.Casts, - Hits: tam.Hits, - Crits: tam.Crits, - Ticks: tam.Ticks, - CritTicks: tam.CritTicks, - Misses: tam.Misses, - Dodges: tam.Dodges, - Parries: tam.Parries, - Blocks: tam.Blocks, - CritBlocks: tam.CritBlocks, - Glances: tam.Glances, - Damage: tam.Damage, - CritDamage: tam.CritDamage, - TickDamage: tam.TickDamage, - CritTickDamage: tam.CritTickDamage, - GlanceDamage: tam.GlanceDamage, - BlockDamage: tam.BlockDamage, - CritBlockDamage: tam.CritBlockDamage, - Threat: tam.Threat, - Healing: tam.Healing, - CritHealing: tam.CritHealing, - Shielding: tam.Shielding, - CastTimeMs: float64(tam.CastTime.Milliseconds()), + Casts: tam.Casts, + Hits: tam.Hits, + Crits: tam.Crits, + Ticks: tam.Ticks, + CritTicks: tam.CritTicks, + Misses: tam.Misses, + Dodges: tam.Dodges, + Parries: tam.Parries, + Blocks: tam.Blocks, + CritBlocks: tam.CritBlocks, + Glances: tam.Glances, + GlanceBlocks: tam.GlanceBlocks, + Damage: tam.Damage, + CritDamage: tam.CritDamage, + TickDamage: tam.TickDamage, + CritTickDamage: tam.CritTickDamage, + GlanceDamage: tam.GlanceDamage, + GlanceBlockDamage: tam.GlanceBlockDamage, + BlockDamage: tam.BlockDamage, + CritBlockDamage: tam.CritBlockDamage, + Threat: tam.Threat, + Healing: tam.Healing, + CritHealing: tam.CritHealing, + Shielding: tam.Shielding, + CastTimeMs: float64(tam.CastTime.Milliseconds()), } } @@ -378,11 +384,13 @@ func (unitMetrics *UnitMetrics) addSpellMetrics(spell *Spell, actionID ActionID, tam.Blocks += spellTargetMetrics.Blocks tam.CritBlocks += spellTargetMetrics.CritBlocks tam.Glances += spellTargetMetrics.Glances + tam.GlanceBlocks += spellTargetMetrics.GlanceBlocks tam.Damage += spellTargetMetrics.TotalDamage tam.CritDamage += spellTargetMetrics.TotalCritDamage tam.TickDamage += spellTargetMetrics.TotalTickDamage tam.CritTickDamage += spellTargetMetrics.TotalCritTickDamage tam.GlanceDamage += spellTargetMetrics.TotalGlanceDamage + tam.GlanceBlockDamage += spellTargetMetrics.TotalGlanceBlockDamage tam.BlockDamage += spellTargetMetrics.TotalBlockDamage tam.CritBlockDamage += spellTargetMetrics.TotalCritBlockDamage tam.Threat += spellTargetMetrics.TotalThreat diff --git a/sim/core/sim_concurrent.go b/sim/core/sim_concurrent.go index 8814f72c88..59ebbf4cc1 100644 --- a/sim/core/sim_concurrent.go +++ b/sim/core/sim_concurrent.go @@ -181,11 +181,13 @@ func (rsrc *raidSimResultCombiner) addActionMetrics(unit *proto.UnitMetrics, add baseTgt.Blocks += addTgt.Blocks baseTgt.CritBlocks += addTgt.CritBlocks baseTgt.Glances += addTgt.Glances + baseTgt.GlanceBlocks += addTgt.GlanceBlocks baseTgt.Damage += addTgt.Damage baseTgt.CritDamage += addTgt.CritDamage baseTgt.TickDamage += addTgt.TickDamage baseTgt.CritTickDamage += addTgt.CritTickDamage baseTgt.GlanceDamage += addTgt.GlanceDamage + baseTgt.GlanceBlockDamage += addTgt.GlanceBlockDamage baseTgt.BlockDamage += addTgt.BlockDamage baseTgt.CritBlockDamage += addTgt.CritBlockDamage baseTgt.Threat += addTgt.Threat diff --git a/sim/core/spell_outcome.go b/sim/core/spell_outcome.go index 214f0a4186..e7ed20fff1 100644 --- a/sim/core/spell_outcome.go +++ b/sim/core/spell_outcome.go @@ -10,7 +10,7 @@ import ( // 3. Modify the damage if necessary. type OutcomeApplier func(sim *Simulation, result *SpellResult, attackTable *AttackTable) -func (spell *Spell) OutcomeAlwaysHit(_ *Simulation, result *SpellResult, _ *AttackTable) { +func (spell *Spell) OutcomeAlwaysHit(sim *Simulation, result *SpellResult, _ *AttackTable) { result.Outcome = OutcomeHit spell.SpellMetrics[result.Target.UnitIndex].Hits++ } @@ -227,7 +227,6 @@ func (spell *Spell) outcomeMeleeWhite(sim *Simulation, result *SpellResult, atta unit := spell.Unit roll := sim.RandomFloat("White Hit Table") chance := 0.0 - if unit.PseudoStats.InFrontOfTarget { if !result.applyAttackTableMiss(spell, attackTable, roll, &chance) && !result.applyAttackTableDodge(spell, attackTable, roll, &chance) && @@ -253,7 +252,6 @@ func (spell *Spell) OutcomeMeleeWhiteNoGlance(sim *Simulation, result *SpellResu unit := spell.Unit roll := sim.RandomFloat("White Hit Table") chance := 0.0 - if unit.PseudoStats.InFrontOfTarget { if !result.applyAttackTableMiss(spell, attackTable, roll, &chance) && !result.applyAttackTableDodge(spell, attackTable, roll, &chance) && @@ -418,6 +416,7 @@ func (spell *Spell) OutcomeMeleeSpecialCritOnlyNoHitCounter(sim *Simulation, res spell.outcomeMeleeSpecialCritOnly(sim, result, attackTable, false) } func (spell *Spell) outcomeMeleeSpecialCritOnly(sim *Simulation, result *SpellResult, attackTable *AttackTable, countHits bool) { + if !result.applyAttackTableCritSeparateRoll(sim, spell, attackTable, countHits) { result.applyAttackTableHit(spell, countHits) } @@ -430,6 +429,7 @@ func (spell *Spell) OutcomeMeleeSpecialBlockAndCritNoHitCounter(sim *Simulation, spell.outcomeMeleeSpecialBlockAndCrit(sim, result, attackTable, false) } func (spell *Spell) outcomeMeleeSpecialBlockAndCrit(sim *Simulation, result *SpellResult, attackTable *AttackTable, countHits bool) { + if spell.Unit.PseudoStats.InFrontOfTarget { if result.applyAttackTableCritSeparateRoll(sim, spell, attackTable, countHits) { result.applyAttackTableBlock(sim, spell, attackTable) @@ -589,7 +589,14 @@ func (result *SpellResult) applyAttackTableBlock(sim *Simulation, spell *Spell, if sim.RandomFloat("Block Roll") < chance { result.Outcome |= OutcomeBlock if result.DidCrit() { + // Subtract Crits because they happen before Blocks + spell.SpellMetrics[result.Target.UnitIndex].Crits-- spell.SpellMetrics[result.Target.UnitIndex].CritBlocks++ + } else if result.DidGlance() { + // Subtract Glances because they happen before Blocks + spell.SpellMetrics[result.Target.UnitIndex].Glances-- + spell.SpellMetrics[result.Target.UnitIndex].GlanceBlocks++ + } else { spell.SpellMetrics[result.Target.UnitIndex].Blocks++ } @@ -719,7 +726,13 @@ func (result *SpellResult) applyEnemyAttackTableBlock(sim *Simulation, spell *Sp if sim.RandomFloat("Player Block") < chance { result.Outcome |= OutcomeBlock if result.DidCrit() { + // Subtract Crits because they happen before Blocks + spell.SpellMetrics[result.Target.UnitIndex].Crits-- spell.SpellMetrics[result.Target.UnitIndex].CritBlocks++ + } else if result.DidGlance() { + // Subtract Glances because they happen before Blocks + spell.SpellMetrics[result.Target.UnitIndex].Glances-- + spell.SpellMetrics[result.Target.UnitIndex].GlanceBlocks++ } else { spell.SpellMetrics[result.Target.UnitIndex].Blocks++ } diff --git a/sim/core/spell_result.go b/sim/core/spell_result.go index e58d977caa..f8fec25544 100644 --- a/sim/core/spell_result.go +++ b/sim/core/spell_result.go @@ -289,7 +289,11 @@ func (spell *Spell) dealDamageInternal(sim *Simulation, isPeriodic bool, result } } } else if result.DidGlance() { - spell.SpellMetrics[result.Target.UnitIndex].TotalGlanceDamage += result.Damage + if result.DidBlock() { + spell.SpellMetrics[result.Target.UnitIndex].TotalGlanceBlockDamage += result.Damage + } else { + spell.SpellMetrics[result.Target.UnitIndex].TotalGlanceDamage += result.Damage + } } else if result.DidBlock() { spell.SpellMetrics[result.Target.UnitIndex].TotalBlockDamage += result.Damage } diff --git a/ui/core/components/detailed_results/damage_metrics.tsx b/ui/core/components/detailed_results/damage_metrics.tsx index 57d5356fb8..7f197241b9 100644 --- a/ui/core/components/detailed_results/damage_metrics.tsx +++ b/ui/core/components/detailed_results/damage_metrics.tsx @@ -47,6 +47,7 @@ export class DamageMetricsTable extends MetricsTable { const tickValues = metric.damageDone.tick; const critTickValues = metric.damageDone.critTick; const glanceValues = metric.damageDone.glance; + const glanceBlockValues = metric.damageDone.glanceBlock; const blockValues = metric.damageDone.block; const critBlockValues = metric.damageDone.critBlock; @@ -80,6 +81,10 @@ export class DamageMetricsTable extends MetricsTable { name: 'Glancing Blow', ...glanceValues, }, + { + name: 'Blocked Glancing Blow', + ...glanceBlockValues, + }, { name: 'Blocked Hit', ...blockValues, @@ -210,6 +215,7 @@ export class DamageMetricsTable extends MetricsTable { const relativeTickPercent = (metric.ticks / metric.landedTicks) * 100; const relativeCritTickPercent = (metric.critTicks / metric.landedTicks) * 100; const relativeGlancePercent = (metric.glances / metric.landedHits) * 100; + const relativeGlanceBlockPercent = (metric.glanceBlocks / metric.landedHits) * 100; const relativeBlockPercent = (metric.blocks / metric.landedHits) * 100; const relativeCritBlockPercent = (metric.critBlocks / metric.landedHits) * 100; @@ -237,6 +243,11 @@ export class DamageMetricsTable extends MetricsTable { value: metric.glances, percentage: relativeGlancePercent, }, + { + name: 'Blocked Glancing Blow', + value: metric.glanceBlocks, + percentage: relativeGlanceBlockPercent, + }, { name: 'Blocked Hit', value: metric.blocks, @@ -314,10 +325,10 @@ export class DamageMetricsTable extends MetricsTable { }, { name: 'Crit %', - getValue: (metric: ActionMetrics) => metric.critPercent || metric.critTickPercent, + getValue: (metric: ActionMetrics) => (metric.critPercent + metric.critBlockPercent) || metric.critTickPercent, getDisplayString: (metric: ActionMetrics) => - `${formatToPercent(metric.critPercent || metric.critTickPercent, { fallbackString: '-' })}${ - metric.critPercent && metric.critTickPercent ? ` (${formatToPercent(metric.critTickPercent, { fallbackString: '-' })})` : '' + `${formatToPercent(metric.critPercent + metric.critBlockPercent || metric.critTickPercent, { fallbackString: '-' })}${ + metric.critPercent + metric.critBlockPercent && metric.critTickPercent ? ` (${formatToPercent(metric.critTickPercent, { fallbackString: '-' })})` : '' }`, }, { diff --git a/ui/core/components/detailed_results/dtps_metrics.tsx b/ui/core/components/detailed_results/dtps_metrics.tsx index b13cc85d55..8f07742716 100644 --- a/ui/core/components/detailed_results/dtps_metrics.tsx +++ b/ui/core/components/detailed_results/dtps_metrics.tsx @@ -47,6 +47,7 @@ export class DtpsMetricsTable extends MetricsTable { const tickValues = metric.damageDone.tick; const critTickValues = metric.damageDone.critTick; const glanceValues = metric.damageDone.glance; + const glanceBlockValues = metric.damageDone.glanceBlock; const blockValues = metric.damageDone.block; const critBlockValues = metric.damageDone.critBlock; @@ -80,6 +81,10 @@ export class DtpsMetricsTable extends MetricsTable { name: 'Glancing Blow', ...glanceValues, }, + { + name: 'Blocked Glancing Blow', + ...glanceBlockValues, + }, { name: 'Blocked Hit', ...blockValues, @@ -172,6 +177,7 @@ export class DtpsMetricsTable extends MetricsTable { const relativeTickPercent = (metric.ticks / metric.landedTicks) * 100; const relativeCritTickPercent = (metric.critTicks / metric.landedTicks) * 100; const relativeGlancePercent = (metric.glances / metric.landedHits) * 100; + const relativeGlanceBlockPercent = (metric.glanceBlocks / metric.landedHits) * 100; const relativeBlockPercent = (metric.blocks / metric.landedHits) * 100; const relativeCritBlockPercent = (metric.critBlocks / metric.landedHits) * 100; @@ -199,6 +205,11 @@ export class DtpsMetricsTable extends MetricsTable { value: metric.glances, percentage: relativeGlancePercent, }, + { + name: 'Blocked Glancing Blow', + value: metric.glanceBlocks, + percentage: relativeGlanceBlockPercent, + }, { name: 'Blocked Hit', value: metric.blocks, @@ -286,10 +297,10 @@ export class DtpsMetricsTable extends MetricsTable { }, { name: 'Crit %', - getValue: (metric: ActionMetrics) => metric.critPercent || metric.critTickPercent, + getValue: (metric: ActionMetrics) => metric.critPercent + metric.critBlockPercent || metric.critTickPercent, getDisplayString: (metric: ActionMetrics) => - `${formatToPercent(metric.critPercent || metric.critTickPercent, { fallbackString: '-' })}${ - metric.critPercent && metric.critTickPercent ? ` (${formatToPercent(metric.critTickPercent, { fallbackString: '-' })})` : '' + `${formatToPercent(metric.critPercent + metric.critBlockPercent || metric.critTickPercent, { fallbackString: '-' })}${ + metric.critPercent + metric.critBlockPercent && metric.critTickPercent ? ` (${formatToPercent(metric.critTickPercent, { fallbackString: '-' })})` : '' }`, }, { diff --git a/ui/core/proto_utils/logs_parser.tsx b/ui/core/proto_utils/logs_parser.tsx index c544e52427..c5e26cfa28 100644 --- a/ui/core/proto_utils/logs_parser.tsx +++ b/ui/core/proto_utils/logs_parser.tsx @@ -395,12 +395,14 @@ export class DamageDealtLog extends SimLog { ? 'Dodge' : this.parry ? 'Parry' - : this.glance - ? 'Glance' : this.block ? this.crit ? 'Critical Block' + : this.glance + ? 'Blocked Glance' : 'Block' + : this.glance + ? 'Glance' : this.crit ? 'Crit' : this.crush @@ -456,7 +458,7 @@ export class DamageDealtLog extends SimLog { static parse(params: SimLogParams): Promise | null { const match = params.raw.match( - /] (.*?) (tick )?((Miss)|(Hit)|(CriticalBlock)|(Crit)|(Crush)|(Glance)|(Dodge)|(Parry)|(Block))( \((\d+)% Resist\))?( for (\d+\.\d+) ((damage)|(healing)|(shielding)))?/, + /] (.*?) (tick )?((Miss)|(Hit)|(CriticalBlock)|(Crit)|(Crush)|(GlanceBlock)|(Glance)|(Dodge)|(Parry)|(Block))( \((\d+)% Resist\))?( for (\d+\.\d+) ((damage)|(healing)|(shielding)))?/, ); if (match) { return ActionId.fromLogString(match[1]) @@ -464,8 +466,8 @@ export class DamageDealtLog extends SimLog { .then(cause => { params.actionId = cause; - const amount = match[16] ? parseFloat(match[16]) : 0; - const type = match[17] || ''; + const amount = match[17] ? parseFloat(match[17]) : 0; + const type = match[18] || ''; return new DamageDealtLog( params, @@ -474,14 +476,14 @@ export class DamageDealtLog extends SimLog { match[3] == 'Miss', match[3] == 'Crit' || match[3] == 'CriticalBlock', match[3] == 'Crush', - match[3] == 'Glance', + match[3] == 'Glance' || match[3] == 'GlanceBlock', match[3] == 'Dodge', match[3] == 'Parry', - match[3] == 'Block' || match[3] == 'CriticalBlock', + match[3] == 'Block' || match[3] == 'CriticalBlock' || match[3] == 'GlanceBlock', Boolean(match[2]) && match[2].includes('tick'), - match[14] == '10', - match[14] == '20', - match[14] == '30', + match[15] == '10', + match[15] == '20', + match[15] == '30', ); }); } else { @@ -782,7 +784,15 @@ export class ResourceChangedLog extends SimLog { readonly total: number; readonly secondaryResourceType?: SecondaryResourceType; - constructor(params: SimLogParams, resourceType: ResourceType, valueBefore: number, valueAfter: number, isSpend: boolean, total: number, secondaryType?: SecondaryResourceType) { + constructor( + params: SimLogParams, + resourceType: ResourceType, + valueBefore: number, + valueAfter: number, + isSpend: boolean, + total: number, + secondaryType?: SecondaryResourceType, + ) { super(params); this.resourceType = resourceType; this.valueBefore = valueBefore; @@ -797,7 +807,8 @@ export class ResourceChangedLog extends SimLog { const signedDiff = (this.valueAfter - this.valueBefore) * (this.isSpend ? -1 : 1); const isHealth = this.resourceType == ResourceType.ResourceTypeHealth; const verb = isHealth ? (this.isSpend ? 'Lost' : 'Recovered') : this.isSpend ? 'Spent' : 'Gained'; - const resourceName = this.secondaryResourceType !== undefined ? SECONDARY_RESOURCES.get(this.secondaryResourceType)!.name : resourceNames.get(this.resourceType)!; + const resourceName = + this.secondaryResourceType !== undefined ? SECONDARY_RESOURCES.get(this.secondaryResourceType)!.name : resourceNames.get(this.resourceType)!; const resourceClass = `resource-${resourceName.replace(/\s/g, '-').toLowerCase()}`; return ( @@ -823,9 +834,7 @@ export class ResourceChangedLog extends SimLog { } static parse(params: SimLogParams): Promise | null { - const match = params.raw.match( - /(Gained|Spent) (\d+\.?\d*) (\S.+?\S) from (.*?) \((\d+\.?\d*) --> (\d+\.?\d*)\)( of (\d+\.?\d*) total)?/, - ); + const match = params.raw.match(/(Gained|Spent) (\d+\.?\d*) (\S.+?\S) from (.*?) \((\d+\.?\d*) --> (\d+\.?\d*)\)( of (\d+\.?\d*) total)?/); if (match) { const [resourceType, secondaryType] = stringToResourceType(match[3]); const total = match[8] !== undefined ? parseFloat(match[8]) : 0; diff --git a/ui/core/proto_utils/sim_result.ts b/ui/core/proto_utils/sim_result.ts index 70abff3517..8c6b376115 100644 --- a/ui/core/proto_utils/sim_result.ts +++ b/ui/core/proto_utils/sim_result.ts @@ -838,6 +838,7 @@ export class ActionMetrics { this.avgCritDamage + this.avgCritTickDamage - this.avgGlanceDamage - + this.avgGlanceBlockDamage - this.avgBlockDamage - this.avgCritBlockDamage ); @@ -875,6 +876,14 @@ export class ActionMetrics { return this.combinedMetrics.avgGlanceDamage; } + get glanceBlockDamage() { + return this.combinedMetrics.glanceBlockDamage; + } + + get avgGlanceBlockDamage() { + return this.combinedMetrics.avgGlanceBlockDamage; + } + get blockDamage() { return this.combinedMetrics.blockDamage; } @@ -1092,6 +1101,14 @@ export class ActionMetrics { return this.combinedMetrics.glancePercent; } + get glanceBlocks() { + return this.combinedMetrics.glanceBlocks; + } + + get glanceBlocksPercent() { + return this.combinedMetrics.glanceBlocksPercent; + } + get crits() { return this.combinedMetrics.crits; } @@ -1115,6 +1132,7 @@ export class ActionMetrics { this.avgCritDamage + this.avgCritTickDamage - this.avgGlanceDamage - + this.avgGlanceBlockDamage - this.avgBlockDamage - this.avgCritBlockDamage; @@ -1145,7 +1163,12 @@ export class ActionMetrics { glance: { value: this.avgGlanceDamage, percentage: (this.avgGlanceDamage / this.avgDamage) * 100, - average: this.avgGlanceDamage / this.glances, + average: this.avgGlanceDamage / this.glanceBlocks, + }, + glanceBlock: { + value: this.avgGlanceBlockDamage, + percentage: (this.avgGlanceBlockDamage / this.avgDamage) * 100, + average: this.avgGlanceBlockDamage / this.glanceBlocks, }, block: { value: this.avgBlockDamage, @@ -1243,11 +1266,18 @@ export class TargetedActionMetrics { this.duration = duration; this.data = data; - this.landedHitsRaw = this.data.hits + this.data.crits + this.data.blocks + this.data.critBlocks + this.data.glances; + this.landedHitsRaw = this.data.hits + this.data.crits + this.data.blocks + this.data.critBlocks + this.data.glances + this.data.glanceBlocks; this.landedTicksRaw = this.data.ticks + this.data.critTicks; this.hitAttempts = - this.data.misses + this.data.dodges + this.data.parries + this.data.critBlocks + this.data.blocks + this.data.glances + this.data.crits; + this.data.misses + + this.data.dodges + + this.data.parries + + this.data.critBlocks + + this.data.blocks + + this.data.glances + + this.data.glanceBlocks + + this.data.crits; if (this.data.hits !== 0) { this.hitAttempts += this.data.hits; @@ -1296,6 +1326,14 @@ export class TargetedActionMetrics { return this.data.glanceDamage / this.iterations; } + get glanceBlockDamage() { + return this.data.glanceBlockDamage; + } + + get avgGlanceBlockDamage() { + return this.data.glanceBlockDamage / this.iterations; + } + get blockDamage() { return this.data.blockDamage; } @@ -1496,6 +1534,14 @@ export class TargetedActionMetrics { return (this.data.glances / this.hitAttempts) * 100; } + get glanceBlocks() { + return this.data.glanceBlocks / this.iterations; + } + + get glanceBlocksPercent() { + return (this.data.glanceBlocks / this.hitAttempts) * 100; + } + get crits() { return this.data.crits / this.iterations; } @@ -1529,11 +1575,13 @@ export class TargetedActionMetrics { blocks: sum(actions.map(a => a.data.blocks)), critBlocks: sum(actions.map(a => a.data.critBlocks)), glances: sum(actions.map(a => a.data.glances)), + glanceBlocks: sum(actions.map(a => a.data.glanceBlocks)), damage: sum(actions.map(a => a.data.damage)), critDamage: sum(actions.map(a => a.data.critDamage)), tickDamage: sum(actions.map(a => a.data.tickDamage)), critTickDamage: sum(actions.map(a => a.data.critTickDamage)), glanceDamage: sum(actions.map(a => a.data.glanceDamage)), + glanceBlockDamage: sum(actions.map(a => a.data.glanceBlockDamage)), blockDamage: sum(actions.map(a => a.data.blockDamage)), critBlockDamage: sum(actions.map(a => a.data.critBlockDamage)), threat: sum(actions.map(a => a.data.threat)),