Object damage hitpoints initial

This commit is contained in:
Kalle
2022-10-22 11:43:19 +03:00
parent bc892dc2fb
commit 63a80c8ecd
9 changed files with 156 additions and 12 deletions

View File

@@ -5,6 +5,7 @@ export type {
Stat,
AnalyzedBuild,
SpecialEffectType,
HitPoints,
} from "./types";
export { useAnalyzeBuild } from "./useAnalyzeBuild";

View File

@@ -0,0 +1,53 @@
import invariant from "tiny-invariant";
import { BIG_BUBBLER_ID, CRAB_TANK_ID, SPLASH_WALL_ID } from "../in-game-lists";
import { specialDeviceHp, specialFieldHp, subStats } from "./stats";
import type {
AbilityPoints,
HitPoints,
SpecialWeaponParams,
SubWeaponParams,
} from "./types";
import weaponParams from "./weapon-params.json";
const PLACEHOLDER_HP = 1000;
export const objectHitPoints = (abilityPoints: AbilityPoints): HitPoints => {
const Wsb_Shield = subStats({
abilityPoints,
subWeaponParams: weaponParams.subWeapons[SPLASH_WALL_ID] as SubWeaponParams,
}).subHp?.value;
const GreatBarrier_Barrier = specialFieldHp({
abilityPoints,
specialWeaponParams: weaponParams.specialWeapons[
BIG_BUBBLER_ID
] as SpecialWeaponParams,
})?.value;
const GreatBarrier_WeakPoint = specialDeviceHp({
abilityPoints,
specialWeaponParams: weaponParams.specialWeapons[
BIG_BUBBLER_ID
] as SpecialWeaponParams,
})?.value;
invariant(Wsb_Shield);
invariant(GreatBarrier_Barrier);
invariant(GreatBarrier_WeakPoint);
return {
BulletUmbrellaCanopyNormal: PLACEHOLDER_HP, // ?? needs defaults
BulletUmbrellaCanopyWide: weaponParams.mainWeapons[6010].CanopyHP,
BulletUmbrellaCanopyCompact: weaponParams.mainWeapons[6020].CanopyHP,
Wsb_Shield,
Bomb_TorpedoBullet: PLACEHOLDER_HP, // ??
Chariot: weaponParams.specialWeapons[CRAB_TANK_ID].ArmorHP,
Gachihoko_Barrier: PLACEHOLDER_HP, // ??
GreatBarrier_Barrier,
GreatBarrier_WeakPoint,
InkRail: PLACEHOLDER_HP, // ??
NiceBall_Armor: PLACEHOLDER_HP, // ??
ShockSonar: PLACEHOLDER_HP, // ??
Sponge_Versus: PLACEHOLDER_HP, // ??
Wsb_Flag: PLACEHOLDER_HP, // ??
Wsb_Sprinkler: PLACEHOLDER_HP, // ??
};
};

View File

@@ -765,7 +765,9 @@ const SUB_WEAPON_STATS = [
},
{ analyzedBuildKey: "subHp", abilityValuesKey: "MaxHP", type: "HP" },
] as const;
function subStats(args: StatFunctionInput) {
export function subStats(
args: Pick<StatFunctionInput, "subWeaponParams" | "abilityPoints">
) {
const result: Partial<AnalyzedBuild["stats"]> = {};
const SUB_STATS_KEY = "BRU";
@@ -1126,8 +1128,8 @@ function specialPaintRadius(
};
}
function specialFieldHp(
args: StatFunctionInput
export function specialFieldHp(
args: Pick<StatFunctionInput, "specialWeaponParams" | "abilityPoints">
): AnalyzedBuild["stats"]["specialFieldHp"] {
if (!hasEffect({ key: "MaxFieldHP", weapon: args.specialWeaponParams })) {
return;
@@ -1150,8 +1152,8 @@ function specialFieldHp(
};
}
function specialDeviceHp(
args: StatFunctionInput
export function specialDeviceHp(
args: Pick<StatFunctionInput, "specialWeaponParams" | "abilityPoints">
): AnalyzedBuild["stats"]["specialDeviceHp"] {
if (!hasEffect({ key: "MaxHP", weapon: args.specialWeaponParams })) {
return;

View File

@@ -164,6 +164,8 @@ export type DamageType = typeof DAMAGE_TYPE[number];
export type DamageReceiver = typeof DAMAGE_RECEIVERS[number];
export type HitPoints = Record<DamageReceiver, number>;
export interface Damage {
value: number;
type: DamageType;

View File

@@ -2,6 +2,7 @@ import { useSearchParams } from "@remix-run/react";
import { type MainWeaponId } from "../in-game-lists";
import { damageTypeToWeaponType } from "./constants";
import { damageTypeToMultipliers, fallbackRates } from "./damageMultipliers";
import { objectHitPoints } from "./objectHitPoints";
import { buildStats } from "./stats";
import { validatedWeaponIdFromSearchParams } from "./utils";
@@ -53,5 +54,7 @@ export function useObjectDamage() {
mainWeaponId,
handleChange,
multipliers,
damages: analyzed.stats.damages,
hitPoints: objectHitPoints(new Map()),
};
}

View File

@@ -1246,6 +1246,7 @@
}
},
"12": {
"ArmorHP": 5000,
"overwrites": {
"SpecialDurationFrame": {
"High": 660,

View File

@@ -1,22 +1,54 @@
import { WeaponCombobox } from "~/components/Combobox";
import { Image } from "~/components/Image";
import { Main } from "~/components/Main";
import { useObjectDamage } from "~/modules/analyzer";
import type { MainWeaponId } from "~/modules/in-game-lists";
import { type SendouRouteHandle } from "~/utils/remix";
import {
DAMAGE_RECEIVERS,
useObjectDamage,
type HitPoints,
} from "~/modules/analyzer";
import {
type MainWeaponId,
BIG_BUBBLER_ID,
BOOYAH_BOMB_ID,
CRAB_TANK_ID,
SPLASH_WALL_ID,
SQUID_BEAKON_ID,
TORPEDO_ID,
WAVE_BREAKER_ID,
SPRINKLER_ID,
} from "~/modules/in-game-lists";
import {
mainWeaponImageUrl,
modeImageUrl,
specialWeaponImageUrl,
subWeaponImageUrl,
} from "~/utils/urls";
import styles from "~/styles/object-damage.css";
import type { LinksFunction } from "@remix-run/node";
import type { SendouRouteHandle } from "~/utils/remix";
import type { DamageReceiver } from "~/modules/analyzer/types";
export const links: LinksFunction = () => {
return [{ rel: "stylesheet", href: styles }];
};
export const handle: SendouRouteHandle = {
i18n: ["weapons"],
};
export default function ObjectDamagePage() {
const { mainWeaponId, handleChange, multipliers } = useObjectDamage();
const { mainWeaponId, handleChange, multipliers, damages, hitPoints } =
useObjectDamage();
if (process.env.NODE_ENV !== "development") {
return <Main>WIP :)</Main>;
}
console.log(JSON.stringify(multipliers, null, 2));
console.log(JSON.stringify(damages, null, 2));
return (
<Main>
<Main className="stack lg">
<WeaponCombobox
inputName="weapon"
initialWeaponId={mainWeaponId}
@@ -29,7 +61,48 @@ export default function ObjectDamagePage() {
className="w-full-important"
clearsInputOnFocus
/>
<pre>{JSON.stringify(multipliers, null, 2)}</pre>
<div
className="object-damage__grid"
style={{ "--columns-count": "2" } as any}
>
<DamageReceiversHeader hitPoints={hitPoints} />
</div>
</Main>
);
}
const damageReceiverImages: Record<DamageReceiver, string> = {
Bomb_TorpedoBullet: subWeaponImageUrl(TORPEDO_ID),
Chariot: specialWeaponImageUrl(CRAB_TANK_ID),
Gachihoko_Barrier: modeImageUrl("RM"),
GreatBarrier_Barrier: specialWeaponImageUrl(BIG_BUBBLER_ID),
GreatBarrier_WeakPoint: specialWeaponImageUrl(BIG_BUBBLER_ID),
InkRail: modeImageUrl("CB"),
NiceBall_Armor: specialWeaponImageUrl(BOOYAH_BOMB_ID),
ShockSonar: specialWeaponImageUrl(WAVE_BREAKER_ID),
Sponge_Versus: modeImageUrl("CB"),
Wsb_Flag: subWeaponImageUrl(SQUID_BEAKON_ID),
Wsb_Shield: subWeaponImageUrl(SPLASH_WALL_ID),
Wsb_Sprinkler: subWeaponImageUrl(SPRINKLER_ID),
BulletUmbrellaCanopyNormal: mainWeaponImageUrl(6000),
BulletUmbrellaCanopyWide: mainWeaponImageUrl(6010),
BulletUmbrellaCanopyCompact: mainWeaponImageUrl(6020),
};
function DamageReceiversHeader({ hitPoints }: { hitPoints: HitPoints }) {
return (
<>
{DAMAGE_RECEIVERS.map((receiver, i) => (
<>
<Image
key={i}
alt=""
path={damageReceiverImages[receiver]}
width={40}
height={40}
/>
<div>{hitPoints[receiver]}</div>
</>
))}
</>
);
}

View File

@@ -0,0 +1,6 @@
.object-damage__grid {
display: grid;
width: 100%;
gap: var(--s-3);
grid-template-columns: repeat(var(--columns-count), 1fr);
}

View File

@@ -314,7 +314,10 @@ function parametersToSpecialWeaponResult(params: any) {
resultUnwrapped["SplashAroundPaintRadius"] = undefined;
}
return { overwrites: resultUnwrapped };
return {
ArmorHP: params["WeaponSpChariotParam"]?.["ArmorHP"],
overwrites: resultUnwrapped,
};
}
function unwrapSubSpecialSpecUpList(result: any) {