diff --git a/app/modules/analyzer/stats.ts b/app/modules/analyzer/stats.ts index caed822c1..4827464a6 100644 --- a/app/modules/analyzer/stats.ts +++ b/app/modules/analyzer/stats.ts @@ -5,7 +5,7 @@ import type { import type { AnalyzedBuild, StatFunctionInput } from "./types"; import invariant from "tiny-invariant"; import { - abilityPointsToEffect, + abilityPointsToEffects, apFromMap, buildToAbilityPoints, weaponParams, @@ -43,6 +43,7 @@ export function buildStats({ shotsPerInkTank: shotsPerInkTank(input), inkCost: inkCost(input), specialPoint: specialPoint(input), + specialSavedAfterDeath: specialSavedAfterDeath(input), subWeaponWhiteInkFrames: subWeaponParams.InkRecoverStop, }, }; @@ -60,7 +61,7 @@ function specialPoint({ }: StatFunctionInput): AnalyzedBuild["stats"]["specialPoint"] { const SPECIAL_POINT_ABILITY = "SCU"; - const effect = abilityPointsToEffect({ + const { effect } = abilityPointsToEffects({ abilityPoints: apFromMap({ abilityPoints: abilityPoints, ability: SPECIAL_POINT_ABILITY, @@ -76,6 +77,30 @@ function specialPoint({ }; } +function specialSavedAfterDeath({ + abilityPoints, + mainWeaponParams, +}: StatFunctionInput): AnalyzedBuild["stats"]["specialPoint"] { + const SPECIAL_SAVED_AFTER_DEATH_ABILITY = "SS"; + const specialSavedAfterDeathForDisplay = (effect: number) => + Number(((1.0 - effect) * 100).toFixed(2)); + + const { baseEffect, effect } = abilityPointsToEffects({ + abilityPoints: apFromMap({ + abilityPoints: abilityPoints, + ability: SPECIAL_SAVED_AFTER_DEATH_ABILITY, + }), + key: "SpecialGaugeRt_Restart", + weapon: mainWeaponParams, + }); + + return { + baseValue: specialSavedAfterDeathForDisplay(baseEffect), + value: specialSavedAfterDeathForDisplay(effect), + modifiedBy: SPECIAL_SAVED_AFTER_DEATH_ABILITY, + }; +} + function inkCost(args: StatFunctionInput): AnalyzedBuild["stats"]["inkCost"] { return {}; } diff --git a/app/modules/analyzer/types.ts b/app/modules/analyzer/types.ts index 0e544ca00..b9a91a530 100644 --- a/app/modules/analyzer/types.ts +++ b/app/modules/analyzer/types.ts @@ -115,6 +115,8 @@ export interface AnalyzedBuild { }; stats: { specialPoint: Stat; + /** % of special charge saved when dying */ + specialSavedAfterDeath: Stat; shotsPerInkTank: Partial>; /** How much action costs (% of ink tank) */ inkCost?: Partial>; diff --git a/app/modules/analyzer/utils.ts b/app/modules/analyzer/utils.ts index a08ade23c..4dab84476 100644 --- a/app/modules/analyzer/utils.ts +++ b/app/modules/analyzer/utils.ts @@ -80,7 +80,7 @@ function lerpN(p: number, s: number) { return Math.pow(Math.E, -1 * ((Math.log(p) * Math.log(s)) / Math.log(2))); } -export function abilityPointsToEffect({ +function abilityPointsToEffect({ key, abilityPoints, weapon, @@ -99,3 +99,18 @@ export function abilityPointsToEffect({ //return [result, lerpN(slope, percentage) * 100]; return result; } + +export function abilityPointsToEffects({ + key, + abilityPoints, + weapon, +}: { + key: keyof typeof abilityValuesJson; + abilityPoints: number; + weapon: MainWeaponParams; +}) { + return { + baseEffect: abilityPointsToEffect({ key, abilityPoints: 0, weapon }), + effect: abilityPointsToEffect({ key, abilityPoints, weapon }), + }; +} diff --git a/app/routes/analyzer.tsx b/app/routes/analyzer.tsx index b420d8447..50eee9f70 100644 --- a/app/routes/analyzer.tsx +++ b/app/routes/analyzer.tsx @@ -41,13 +41,15 @@ export default function BuildAnalyzerPage() {
- +
@@ -66,34 +68,38 @@ function StatCategory({ return (
{title} - {children} +
{children}
); } -function StatCollection({ - stats, +function StatCard({ + title, + stat, + suffix, }: { - stats: Array<{ title: string; stat: Stat }>; + title: string; + stat: Stat; + suffix?: string; }) { return ( -
- {stats.map(({ title, stat }) => ( -
-

{title}

- {stat.value !== stat.baseValue && ( -
- Current: {stat.value} -
- )} -
- Base: {stat.baseValue} -
-
- +
+
+

{title}

+ {stat.value !== stat.baseValue && ( +
+ Current: {stat.value} + {suffix}
+ )} +
+ Base: {stat.baseValue} + {suffix}
- ))} +
+
+ +
); } diff --git a/app/styles/analyzer.css b/app/styles/analyzer.css index 7bdf033b7..924cd78e8 100644 --- a/app/styles/analyzer.css +++ b/app/styles/analyzer.css @@ -14,22 +14,24 @@ } .analyzer__stat-collection { - display: flex; - flex-wrap: wrap; + display: grid; gap: var(--s-2); + grid-template-columns: repeat(auto-fill, minmax(7.5rem, 1fr)); margin-block-start: var(--s-4); } .analyzer__stat-card { - width: max-content; - height: max-content; + display: flex; + flex-direction: column; + justify-content: space-between; padding: var(--s-2); background-color: var(--bg-darker); border-radius: var(--rounded); + gap: var(--s-4); } .analyzer__stat-card__title { - font-size: var(--fonts-sm); + font-size: var(--fonts-xs); } .analyzer__stat-card__value { diff --git a/public/locales/en/analyzer.json b/public/locales/en/analyzer.json index 5e7f0d31a..d2df5aad2 100644 --- a/public/locales/en/analyzer.json +++ b/public/locales/en/analyzer.json @@ -1,3 +1,4 @@ { - "stat.specialPoints": "Points to special" + "stat.specialPoints": "Points to special", + "stat.specialLost": "Special lost when splatted" }