sendou.ink/app/features/object-damage-calculator/calculator-hooks.ts
Kalle cfbd18b4fe Object Damage Calc: Separate subs in the combobox Closes #1220
Also due to a bug the subs were not accessible at all before.
This was a bug introduced in c014ba5e18
2023-04-15 12:06:07 +03:00

138 lines
3.6 KiB
TypeScript

import { useSearchParams } from "@remix-run/react";
import { assertType } from "~/utils/types";
import {
type DAMAGE_TYPE,
buildStats,
possibleApValues,
validatedAnyWeaponFromSearchParams,
type AnalyzedBuild,
type DamageType,
} from "~/features/build-analyzer";
import {
calculateDamage,
resolveAllUniqueDamageTypes,
} from "./core/objectDamage";
import type { AnyWeapon } from "../build-analyzer/analyzer-types";
const ABILITY_POINTS_SP_KEY = "ap";
const DAMAGE_TYPE_SP_KEY = "dmg";
const MULTI_SHOT_SP_KEY = "multi";
export function useObjectDamage() {
const [searchParams, setSearchParams] = useSearchParams();
const anyWeapon = validatedAnyWeaponFromSearchParams(searchParams);
const abilityPoints = validatedAbilityPointsFromSearchParams(searchParams);
const isMultiShot = validatedMultiShotFromSearchParams(searchParams);
const analyzed = buildStats({
weaponSplId: anyWeapon.type === "MAIN" ? anyWeapon.id : 0,
hasTacticooler: false,
});
const damageType = validatedDamageTypeFromSearchParams({
searchParams,
analyzed,
});
const handleChange = ({
newAnyWeapon = anyWeapon,
newAbilityPoints = abilityPoints,
newDamageType = damageType,
newIsMultiShot = isMultiShot,
}: {
newAnyWeapon?: AnyWeapon;
newAbilityPoints?: number;
newDamageType?: DamageType;
newIsMultiShot?: boolean;
}) => {
setSearchParams(
{
weapon: `${newAnyWeapon.type}_${newAnyWeapon.id}`,
[ABILITY_POINTS_SP_KEY]: String(newAbilityPoints),
[DAMAGE_TYPE_SP_KEY]: newDamageType ?? "",
[MULTI_SHOT_SP_KEY]: String(newIsMultiShot),
},
{ replace: true, state: { scroll: false } }
);
};
return {
weapon: anyWeapon,
isMultiShot,
multiShotCount: analyzed.stats.damages.find((d) => d.type === damageType)
?.multiShots,
handleChange,
damagesToReceivers: damageType
? calculateDamage({
abilityPoints: new Map([
["BRU", abilityPoints],
["SPU", abilityPoints],
]),
analyzed,
anyWeapon,
damageType,
isMultiShot,
})
: null,
abilityPoints: String(abilityPoints),
damageType,
allDamageTypes: resolveAllUniqueDamageTypes({ analyzed, anyWeapon }),
};
}
function validatedAbilityPointsFromSearchParams(searchParams: URLSearchParams) {
const abilityPoints = Number(searchParams.get(ABILITY_POINTS_SP_KEY));
return (
possibleApValues().find((possibleAp) => possibleAp === abilityPoints) ?? 0
);
}
function validatedMultiShotFromSearchParams(searchParams: URLSearchParams) {
return searchParams.get(MULTI_SHOT_SP_KEY) === "false" ? false : true;
}
export const damageTypePriorityList = [
"DIRECT_MAX",
"DIRECT",
"DIRECT_MIN",
"FULL_CHARGE",
"MAX_CHARGE",
"NORMAL_MAX_FULL_CHARGE",
"NORMAL_MAX",
"NORMAL_MIN",
"SPLASH",
"TAP_SHOT",
"DISTANCE",
"BOMB_DIRECT",
"BOMB_NORMAL",
"SPLATANA_VERTICAL_DIRECT",
"SPLATANA_VERTICAL",
"SPLATANA_HORIZONTAL_DIRECT",
"SPLATANA_HORIZONTAL",
] as const;
assertType<
(typeof damageTypePriorityList)[number],
(typeof DAMAGE_TYPE)[number]
>();
function validatedDamageTypeFromSearchParams({
searchParams,
analyzed,
}: {
searchParams: URLSearchParams;
analyzed: AnalyzedBuild;
}) {
const damageType = searchParams.get(DAMAGE_TYPE_SP_KEY);
const found = analyzed.stats.damages.find((d) => d.type === damageType);
if (found) return found.type;
const fallbackFound = damageTypePriorityList.find((type) =>
analyzed.stats.damages.some((d) => d.type === type)
);
return fallbackFound;
}