Add special saver effect

This commit is contained in:
Kalle 2022-09-11 13:08:29 +03:00
parent 454dc923a4
commit 8065e8a6e5
6 changed files with 86 additions and 35 deletions

View File

@ -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 {};
}

View File

@ -115,6 +115,8 @@ export interface AnalyzedBuild {
};
stats: {
specialPoint: Stat;
/** % of special charge saved when dying */
specialSavedAfterDeath: Stat;
shotsPerInkTank: Partial<Record<InkConsumeShotType, Stat>>;
/** How much action costs (% of ink tank) */
inkCost?: Partial<Record<InkConsumePercentageType, Stat>>;

View File

@ -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 }),
};
}

View File

@ -41,13 +41,15 @@ export default function BuildAnalyzerPage() {
</div>
<div>
<StatCategory title="Special">
<StatCollection
stats={[
{
title: t("stat.specialPoints"),
stat: analyzed.stats.specialPoint,
},
]}
<StatCard
stat={analyzed.stats.specialPoint}
title={t("stat.specialPoints")}
suffix="p"
/>
<StatCard
stat={analyzed.stats.specialSavedAfterDeath}
title={t("stat.specialLost")}
suffix="%"
/>
</StatCategory>
</div>
@ -66,34 +68,38 @@ function StatCategory({
return (
<details>
<summary className="analyzer__summary">{title}</summary>
{children}
<div className="analyzer__stat-collection">{children}</div>
</details>
);
}
function StatCollection({
stats,
function StatCard({
title,
stat,
suffix,
}: {
stats: Array<{ title: string; stat: Stat }>;
title: string;
stat: Stat;
suffix?: string;
}) {
return (
<div className="analyzer__stat-collection">
{stats.map(({ title, stat }) => (
<div key={title} className="analyzer__stat-card">
<h4 className="analyzer__stat-card__title">{title}</h4>
{stat.value !== stat.baseValue && (
<div className="analyzer__stat-card__value">
Current: {stat.value}
</div>
)}
<div className="analyzer__stat-card__value text-lighter">
Base: {stat.baseValue}
</div>
<div className="stack items-center mt-4">
<Ability ability={stat.modifiedBy} size="TINY" />
<div key={title} className="analyzer__stat-card">
<div>
<h4 className="analyzer__stat-card__title">{title}</h4>
{stat.value !== stat.baseValue && (
<div className="analyzer__stat-card__value">
Current: {stat.value}
{suffix}
</div>
)}
<div className="analyzer__stat-card__value text-lighter">
Base: {stat.baseValue}
{suffix}
</div>
))}
</div>
<div className="stack items-center">
<Ability ability={stat.modifiedBy} size="TINY" />
</div>
</div>
);
}

View File

@ -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 {

View File

@ -1,3 +1,4 @@
{
"stat.specialPoints": "Points to special"
"stat.specialPoints": "Points to special",
"stat.specialLost": "Special lost when splatted"
}