mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-06-03 06:35:42 -05:00
Add special saver effect
This commit is contained in:
parent
454dc923a4
commit
8065e8a6e5
|
|
@ -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 {};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>>;
|
||||
|
|
|
|||
|
|
@ -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 }),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
{
|
||||
"stat.specialPoints": "Points to special"
|
||||
"stat.specialPoints": "Points to special",
|
||||
"stat.specialLost": "Special lost when splatted"
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user