Objective damage table change SPU/BRU

This commit is contained in:
Kalle
2022-10-23 11:59:03 +03:00
parent 3fe59c1a88
commit 86a5e9ee2a
6 changed files with 105 additions and 18 deletions

View File

@@ -13,6 +13,7 @@ type LabelProps = Pick<
};
required?: boolean;
className?: string;
labelClassName?: string;
};
export function Label({
@@ -21,10 +22,11 @@ export function Label({
children,
htmlFor,
className,
labelClassName,
}: LabelProps) {
return (
<div className={clsx("label__container", className)}>
<label htmlFor={htmlFor}>
<label htmlFor={htmlFor} className={labelClassName}>
{children} {required && <span className="text-error">*</span>}
</label>
{valueLimits ? (

View File

@@ -15,3 +15,5 @@ export { useObjectDamage } from "./useObjectDamage";
export { MAX_LDE_INTENSITY, DAMAGE_RECEIVERS, DAMAGE_TYPE } from "./constants";
export { lastDitchEffortIntensityToAp } from "./specialEffects";
export { possibleApValues } from "./utils";

View File

@@ -2,21 +2,27 @@ import { useSearchParams } from "@remix-run/react";
import { type MainWeaponId } from "../in-game-lists";
import { calculateDamage } from "./objectDamage";
import { buildStats } from "./stats";
import { validatedWeaponIdFromSearchParams } from "./utils";
import { possibleApValues, validatedWeaponIdFromSearchParams } from "./utils";
const ABILITY_POINTS_SP_KEY = "ap";
export function useObjectDamage() {
const [searchParams, setSearchParams] = useSearchParams();
const mainWeaponId = validatedWeaponIdFromSearchParams(searchParams);
const abilityPoints = validatedAbilityPointsFromSearchParams(searchParams);
const handleChange = ({
newMainWeaponId = mainWeaponId,
abilityPoints = 0,
}: {
newMainWeaponId?: MainWeaponId;
abilityPoints?: number;
}) => {
setSearchParams(
{
weapon: String(newMainWeaponId),
[ABILITY_POINTS_SP_KEY]: String(abilityPoints),
},
{ replace: true, state: { scroll: false } }
);
@@ -31,9 +37,23 @@ export function useObjectDamage() {
subWeaponId: analyzed.weapon.subWeaponSplId,
handleChange,
damagesToReceivers: calculateDamage({
abilityPoints: new Map(),
abilityPoints: new Map([
["BRU", { ap: abilityPoints, apBeforeTacticooler: abilityPoints }],
["SPU", { ap: abilityPoints, apBeforeTacticooler: abilityPoints }],
]),
analyzed,
mainWeaponId,
}),
abilityPoints: String(abilityPoints),
};
}
export function validatedAbilityPointsFromSearchParams(
searchParams: URLSearchParams
) {
const abilityPoints = Number(searchParams.get(ABILITY_POINTS_SP_KEY));
return (
possibleApValues().find((possibleAp) => possibleAp === abilityPoints) ?? 0
);
}

View File

@@ -167,3 +167,15 @@ export function validatedWeaponIdFromSearchParams(
}
export const hpDivided = (hp: number) => hp / 10;
export function possibleApValues() {
const uniqueValues = new Set<number>();
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 10; j++) {
uniqueValues.add(i * 10 + j * 3);
}
}
return Array.from(uniqueValues).sort((a, b) => a - b);
}

View File

@@ -1,7 +1,7 @@
import { WeaponCombobox } from "~/components/Combobox";
import { Image } from "~/components/Image";
import { Main } from "~/components/Main";
import { useObjectDamage } from "~/modules/analyzer";
import { possibleApValues, useObjectDamage } from "~/modules/analyzer";
import {
type MainWeaponId,
BIG_BUBBLER_ID,
@@ -26,6 +26,8 @@ import type { DamageReceiver } from "~/modules/analyzer/types";
import React from "react";
import { useTranslation } from "react-i18next";
import clsx from "clsx";
import { Label } from "~/components/Label";
import { Ability } from "~/components/Ability";
export const links: LinksFunction = () => {
return [{ rel: "stylesheet", href: styles }];
@@ -36,8 +38,14 @@ export const handle: SendouRouteHandle = {
};
export default function ObjectDamagePage() {
const { mainWeaponId, subWeaponId, handleChange, damagesToReceivers } =
useObjectDamage();
const { t } = useTranslation(["analyzer"]);
const {
mainWeaponId,
subWeaponId,
handleChange,
damagesToReceivers,
abilityPoints,
} = useObjectDamage();
if (process.env.NODE_ENV !== "development") {
return <Main>WIP :)</Main>;
@@ -45,18 +53,50 @@ export default function ObjectDamagePage() {
return (
<Main className="stack lg">
<WeaponCombobox
inputName="weapon"
initialWeaponId={mainWeaponId}
onChange={(opt) =>
opt &&
handleChange({
newMainWeaponId: Number(opt.value) as MainWeaponId,
})
}
className="w-full-important"
clearsInputOnFocus
/>
<div className="object-damage__controls">
<div>
<Label htmlFor="weapon">Weapon</Label>
<WeaponCombobox
id="weapon"
inputName="weapon"
initialWeaponId={mainWeaponId}
onChange={(opt) =>
opt &&
handleChange({
newMainWeaponId: Number(opt.value) as MainWeaponId,
})
}
className="w-full-important"
clearsInputOnFocus
/>
</div>
<div>
<Label htmlFor="damage">Damage type</Label>
<select id="damage">
<option value="0">0</option>
</select>
</div>
<div>
<Label htmlFor="ap" labelClassName="object-damage__ap-label">
Amount of <Ability ability="BRU" size="TINY" />{" "}
<Ability ability="SPU" size="TINY" />
</Label>
<select
id="ap"
value={abilityPoints}
onChange={(e) =>
handleChange({ abilityPoints: Number(e.target.value) })
}
>
{possibleApValues().map((ap) => (
<option key={ap} value={ap}>
{ap}
{t("analyzer:abilityPoints.short")}
</option>
))}
</select>
</div>
</div>
<DamageReceiversGrid
subWeaponId={subWeaponId}
damagesToReceivers={damagesToReceivers}

View File

@@ -1,3 +1,14 @@
.object-damage__controls {
display: flex;
justify-content: space-between;
}
.object-damage__ap-label {
display: flex;
align-items: center;
gap: var(--s-1-5);
}
.object-damage__grid {
display: grid;
width: 100%;