diff --git a/app/features/build-analyzer/analyzer-types.ts b/app/features/build-analyzer/analyzer-types.ts index 0ef835731..2f8d4b350 100644 --- a/app/features/build-analyzer/analyzer-types.ts +++ b/app/features/build-analyzer/analyzer-types.ts @@ -72,6 +72,8 @@ export interface BaseWeaponStats { CanopyHP?: number; /** Amount of frames white ink (=no ink recovery during this time) takes */ InkRecoverStop?: number; + InkRecoverStop_WeaponVerticalSwingParam?: number; + InkRecoverStop_WeaponWideSwingParam?: number; /** How much ink one shot consumes? InkConsume = 0.5 means 2 shots per full tank */ InkConsume?: number; /** Squeezer rapid fire (secondary mode) consumption per shot */ @@ -297,6 +299,8 @@ export interface AnalyzedBuild { /** Seconds for Tenacity to fill the special gauge, keyed by how many players the team is down. */ tenacitySecondsToSpecial?: Record; mainWeaponWhiteInkSeconds?: number; + mainWeaponWhiteInkSecondsHorizontalSwing?: number; + mainWeaponWhiteInkSecondsVerticalSwing?: number; subWeaponWhiteInkSeconds: number; subWeaponInkConsumptionPercentage: Stat; /** Seconds a full ink tank lasts rolling at full speed (rollers and brushes) */ diff --git a/app/features/build-analyzer/core/stats.test.ts b/app/features/build-analyzer/core/stats.test.ts index df770c3a3..8e22586ac 100644 --- a/app/features/build-analyzer/core/stats.test.ts +++ b/app/features/build-analyzer/core/stats.test.ts @@ -169,6 +169,27 @@ describe("Analyze build", () => { ).toBeUndefined(); }); + test.each([ + { why: "Painbrush", weaponSplId: 1120, expected: 0.833 }, + { why: "Splatana Stamper", weaponSplId: 8000, expected: 0.667 }, + { why: "Tenta Brella", weaponSplId: 6010, expected: 1.167 }, + ] as const)( + "Main weapon no ink recovery time comes from the weapon's action params ($why)", + ({ weaponSplId, expected }) => { + const analyzed = buildStats({ weaponSplId, hasTacticooler: false }); + + expect(analyzed.stats.mainWeaponWhiteInkSeconds).toBe(expected); + }, + ); + + test("Roller no ink recovery time is split by swing direction", () => { + const analyzed = buildStats({ weaponSplId: 1010, hasTacticooler: false }); + + expect(analyzed.stats.mainWeaponWhiteInkSeconds).toBeUndefined(); + expect(analyzed.stats.mainWeaponWhiteInkSecondsHorizontalSwing).toBe(0.717); + expect(analyzed.stats.mainWeaponWhiteInkSecondsVerticalSwing).toBe(0.967); + }); + test("Squeezer rapid fire has its own ink consumption and run speed", () => { const analyzed = buildStats({ weaponSplId: 400, diff --git a/app/features/build-analyzer/core/stats.ts b/app/features/build-analyzer/core/stats.ts index aea51697c..7baece05d 100644 --- a/app/features/build-analyzer/core/stats.ts +++ b/app/features/build-analyzer/core/stats.ts @@ -117,10 +117,15 @@ export function buildStats({ damages: damages(input), specialWeaponDamages: specialWeaponDamages(input), subWeaponDefenseDamages: subWeaponDefenseDamages(input), - mainWeaponWhiteInkSeconds: - typeof mainWeaponParams.InkRecoverStop === "number" - ? framesToSeconds(mainWeaponParams.InkRecoverStop) - : undefined, + mainWeaponWhiteInkSeconds: optionalFramesToSeconds( + mainWeaponParams.InkRecoverStop, + ), + mainWeaponWhiteInkSecondsHorizontalSwing: optionalFramesToSeconds( + mainWeaponParams.InkRecoverStop_WeaponWideSwingParam, + ), + mainWeaponWhiteInkSecondsVerticalSwing: optionalFramesToSeconds( + mainWeaponParams.InkRecoverStop_WeaponVerticalSwingParam, + ), subWeaponWhiteInkSeconds: framesToSeconds(subWeaponParams.InkRecoverStop), subWeaponInkConsumptionPercentage: subWeaponInkConsumptionPercentage(input), @@ -846,6 +851,8 @@ export function subWeaponDamageValue({ const framesToSeconds = (frames: number) => effectToRounded(Math.ceil(frames) / 60); +const optionalFramesToSeconds = (frames: number | undefined) => + typeof frames === "number" ? framesToSeconds(frames) : undefined; function squidFormInkRecoverySeconds( args: StatFunctionInput, ): AnalyzedBuild["stats"]["squidFormInkRecoverySeconds"] { diff --git a/app/features/build-analyzer/data/weapon-params.ts b/app/features/build-analyzer/data/weapon-params.ts index c232a49a6..73780491e 100644 --- a/app/features/build-analyzer/data/weapon-params.ts +++ b/app/features/build-analyzer/data/weapon-params.ts @@ -431,6 +431,8 @@ export const weaponParams = { VerticalSwingUnitGroupParam_DamageParam_DamageMaxValue: 1200, WideSwingUnitGroupParam_DamageParam_DamageMinValue: 250, WideSwingUnitGroupParam_DamageParam_DamageMaxValue: 1000, + InkRecoverStop_WeaponVerticalSwingParam: 45, + InkRecoverStop_WeaponWideSwingParam: 40, InkConsume_WeaponSwingParam: 0.0396, InkConsumeMaxPerFrame_WeaponRollParam: 0.001, }, @@ -445,6 +447,8 @@ export const weaponParams = { VerticalSwingUnitGroupParam_DamageParam_DamageMaxValue: 1500, WideSwingUnitGroupParam_DamageParam_DamageMinValue: 350, WideSwingUnitGroupParam_DamageParam_DamageMaxValue: 1500, + InkRecoverStop_WeaponVerticalSwingParam: 58, + InkRecoverStop_WeaponWideSwingParam: 43, InkConsume_WeaponSwingParam: 0.085, InkConsumeMaxPerFrame_WeaponRollParam: 0.001, }, @@ -460,6 +464,8 @@ export const weaponParams = { VerticalSwingUnitGroupParam_DamageParam_DamageMaxValue: 1800, WideSwingUnitGroupParam_DamageParam_DamageMinValue: 400, WideSwingUnitGroupParam_DamageParam_DamageMaxValue: 1800, + InkRecoverStop_WeaponVerticalSwingParam: 70, + InkRecoverStop_WeaponWideSwingParam: 55, InkConsume_WeaponSwingParam: 0.21, InkConsumeMaxPerFrame_WeaponRollParam: 0.001, }, @@ -474,6 +480,8 @@ export const weaponParams = { VerticalSwingUnitGroupParam_DamageParam_DamageMaxValue: 1500, WideSwingUnitGroupParam_DamageParam_DamageMinValue: 300, WideSwingUnitGroupParam_DamageParam_DamageMaxValue: 1500, + InkRecoverStop_WeaponVerticalSwingParam: 65, + InkRecoverStop_WeaponWideSwingParam: 45, InkConsume_WeaponVerticalSwingParam: 0.12, InkConsume_WeaponWideSwingParam: 0.08, InkConsumeMaxPerFrame_WeaponRollParam: 0.001, @@ -489,6 +497,8 @@ export const weaponParams = { VerticalSwingUnitGroupParam_DamageParam_DamageMaxValue: 1200, WideSwingUnitGroupParam_DamageParam_DamageMinValue: 400, WideSwingUnitGroupParam_DamageParam_DamageMaxValue: 700, + InkRecoverStop_WeaponVerticalSwingParam: 50, + InkRecoverStop_WeaponWideSwingParam: 45, InkConsume_WeaponSwingParam: 0.09, InkConsumeMaxPerFrame_WeaponRollParam: 0.0005, }, @@ -500,6 +510,7 @@ export const weaponParams = { BodyParam_Damage: 200, SwingUnitGroupParam_DamageParam_DamageMinValue: 150, SwingUnitGroupParam_DamageParam_DamageMaxValue: 300, + InkRecoverStop: 30, InkConsume_WeaponSwingParam: 0.02, InkConsumeMaxPerFrame_WeaponRollParam: 0.00125, }, @@ -510,6 +521,7 @@ export const weaponParams = { BodyParam_Damage: 250, SwingUnitGroupParam_DamageParam_DamageMinValue: 200, SwingUnitGroupParam_DamageParam_DamageMaxValue: 400, + InkRecoverStop: 30, InkConsume_WeaponSwingParam: 0.027, InkConsumeMaxPerFrame_WeaponRollParam: 0.0015, }, @@ -520,6 +532,7 @@ export const weaponParams = { BodyParam_Damage: 300, SwingUnitGroupParam_DamageParam_DamageMinValue: 310, SwingUnitGroupParam_DamageParam_DamageMaxValue: 600, + InkRecoverStop: 50, InkConsume_WeaponSwingParam: 0.048, InkConsumeMaxPerFrame_WeaponRollParam: 0.0018, }, @@ -973,6 +986,7 @@ export const weaponParams = { MoveSpeed: 0.05, DamageParam_ValueMax: 1190, CanopyHP: 7000, + InkRecoverStop: 70, InkConsumeUmbrella_WeaponShelterCanopyParam: 0.23, InkConsume_WeaponShelterShotgunParam: 0.11, }, @@ -985,6 +999,7 @@ export const weaponParams = { MoveSpeed: 0.072, DamageParam_ValueMax: 400, CanopyHP: 2000, + InkRecoverStop: 40, InkConsume_WeaponShelterShotgunParam: 0.037, }, "6030": { @@ -995,6 +1010,7 @@ export const weaponParams = { MoveSpeed: 0.058, DamageParam_ValueMax: 900, CanopyHP: 1500, + InkRecoverStop: 50, InkConsumeUmbrella_WeaponShelterCanopyParam: 0.15, InkConsume_WeaponShelterShotgunParam: 0.06, }, @@ -1073,6 +1089,7 @@ export const weaponParams = { DamageParam_SplatanaVertical: 700, DamageParam_SplatanaHorizontalDirect: 550, DamageParam_SplatanaHorizontal: 350, + InkRecoverStop: 40, InkConsume_SwingParam: 0.052, InkConsumeFullCharge_ChargeParam: 0.117, }, @@ -1090,6 +1107,7 @@ export const weaponParams = { DamageParam_SplatanaVertical: 600, DamageParam_SplatanaHorizontalDirect: 450, DamageParam_SplatanaHorizontal: 300, + InkRecoverStop: 30, InkConsume_SwingParam: 0.03, InkConsumeFullCharge_ChargeParam: 0.06, }, @@ -1106,6 +1124,7 @@ export const weaponParams = { DamageParam_SplatanaVertical: 800, DamageParam_SplatanaHorizontalDirect: 700, DamageParam_SplatanaHorizontal: 400, + InkRecoverStop: 50, InkConsume_SwingParam: 0.065, InkConsumeFullCharge_ChargeParam: 0.13, }, diff --git a/app/features/build-analyzer/routes/analyzer.tsx b/app/features/build-analyzer/routes/analyzer.tsx index 4a8d2900f..72be52ff4 100644 --- a/app/features/build-analyzer/routes/analyzer.tsx +++ b/app/features/build-analyzer/routes/analyzer.tsx @@ -235,6 +235,26 @@ function BuildAnalyzerPage() { suffix={t("analyzer:suffix.seconds")} /> ) : null, + typeof analyzed.stats.mainWeaponWhiteInkSecondsHorizontalSwing === + "number" ? ( + + ) : null, + typeof analyzed.stats.mainWeaponWhiteInkSecondsVerticalSwing === + "number" ? ( + + ) : null, typeof analyzed.weapon.brellaCanopyHp === "number" ? (