Object damage calculator to feature folder

This commit is contained in:
Kalle 2022-12-22 20:48:24 +02:00
parent d98e8af619
commit cfa2e556d2
12 changed files with 234 additions and 200 deletions

View File

@ -1,27 +1,9 @@
import type { DamageType } from "./types";
import type objectDamages from "./object-dmg.json";
import { type MainWeaponId, mainWeaponIds } from "~/modules/in-game-lists";
import invariant from "tiny-invariant";
import { type MainWeaponId } from "~/modules/in-game-lists";
export const MAX_LDE_INTENSITY = 21;
export const MAX_AP = 57;
export const DAMAGE_RECEIVERS = [
"Chariot", // Crab Tank
"NiceBall_Armor", // Booyah Bomb Armor
"ShockSonar", // Wave Breaker
"GreatBarrier_Barrier", // Big Bubbler Shield
"GreatBarrier_WeakPoint", // Big Bubbler Weak Point
"Gachihoko_Barrier", // Rainmaker Shield
"Wsb_Flag", // Squid Beakon
"Wsb_Shield", // Splash Wall
"Wsb_Sprinkler", // Sprinkler
"Bomb_TorpedoBullet", // Torpedo
"BulletUmbrellaCanopyCompact", // Undercover Brella Canopy
"BulletUmbrellaCanopyNormal", // Splat Brella Canopy
"BulletUmbrellaCanopyWide", // Tenta Brella Canopy
] as const;
export const DAMAGE_TYPE = [
"NORMAL_MIN",
"NORMAL_MAX",
@ -65,155 +47,6 @@ export const damageTypeToWeaponType: Record<
SPLATANA_HORIZONTAL_DIRECT: "MAIN",
};
export const objectDamageJsonKeyPriority: Record<
keyof typeof objectDamages,
Array<DamageType> | null
> = {
Blaster_BlasterMiddle: null,
Blaster_BlasterShort: null,
Blaster_KillOneShot: ["DIRECT"],
Blaster: null,
BlowerExhale_BombCore: null,
BlowerInhale: null,
BombFlower: null,
Bomb_CurlingBullet: null,
Bomb_DirectHit: ["BOMB_DIRECT"],
Bomb_Fizzy: null,
Bomb_Suction: null,
Bomb_TorpedoBullet: null,
Bomb_TorpedoSplashBurst: null,
Bomb_Trap: null,
Bomb: null,
BrushCore: null,
BrushSplash: null,
CannonMissile: null,
ChargerFull_Light: ["FULL_CHARGE"],
ChargerFull_Long: ["FULL_CHARGE"],
ChargerFull: ["FULL_CHARGE"],
Charger_Light: ["MAX_CHARGE", "TAP_SHOT"],
Charger_Long: ["MAX_CHARGE", "TAP_SHOT"],
Charger: ["MAX_CHARGE", "TAP_SHOT"],
Chariot_Body: null,
Chariot_Cannon: null,
Default: null,
EnemyFlyingHohei_BombCore: null,
GachihokoTimeUpBurst: null,
Gachihoko_BombCore: null,
Gachihoko_Bullet: null,
Geyser: null,
GoldenIkuraAttack: null,
InkStormRain: null,
InkStorm: null,
Jetpack_BombCore: null,
Jetpack_Bullet: null,
Jetpack_Coop: null,
Jetpack_Jet: null,
Maneuver_Short: null,
Maneuver: null,
MicroLaser: null,
MissionSalmonBuddy: null,
MovePainter_Burst: null,
MovePainter_Direct: null,
MultiMissile_BombCore: null,
MultiMissile_Bullet: null,
NiceBall: null,
ObjectEffect_Up: null,
RollerCore: null,
RollerSplash_Compact: null,
RollerSplash_Heavy: null,
RollerSplash_Hunter: null,
RollerSplash: null,
Saber_ChargeShot: ["SPLATANA_VERTICAL"],
Saber_ChargeSlash: ["SPLATANA_VERTICAL_DIRECT"],
Saber_Shot: ["SPLATANA_HORIZONTAL"],
Saber_Slash: ["SPLATANA_HORIZONTAL_DIRECT"],
Saber_ChargeSlash_Penetrate: null,
SakerocketBullet: null,
ShelterCanopy_Compact: null,
ShelterCanopy_Wide: null,
ShelterCanopy: null,
ShelterShot_Compact: null,
ShelterShot_Wide: null,
ShelterShot: null,
Shield: null,
ShockSonar_Wave: null,
Shooter_Blaze: ["NORMAL_MAX", "NORMAL_MIN"],
Shooter_Expert: ["NORMAL_MAX", "NORMAL_MIN"],
Shooter_First: ["NORMAL_MAX", "NORMAL_MIN"],
Shooter_FlashRepeat: ["NORMAL_MAX", "NORMAL_MIN"],
Shooter_Flash: ["NORMAL_MAX", "NORMAL_MIN"],
Shooter_Gravity: ["NORMAL_MAX", "NORMAL_MIN"],
Shooter_Heavy: ["NORMAL_MAX", "NORMAL_MIN"],
Shooter_Long: ["NORMAL_MAX", "NORMAL_MIN"],
Shooter_Precision: ["NORMAL_MAX", "NORMAL_MIN"],
Shooter_Short: ["NORMAL_MAX", "NORMAL_MIN"],
Shooter_TripleMiddle: ["NORMAL_MAX", "NORMAL_MIN"],
Shooter_TripleQuick: ["NORMAL_MAX", "NORMAL_MIN"],
Shooter: null,
Skewer_Body: null,
Skewer: null,
Slosher_Bathtub: ["DIRECT", "DIRECT_MAX", "DIRECT_MIN", "DISTANCE", "SPLASH"],
Slosher_Bear: ["DIRECT", "DIRECT_MAX", "DIRECT_MIN", "DISTANCE", "SPLASH"],
Slosher_WashtubBombCore: ["DIRECT", "DIRECT_MAX", "DIRECT_MIN"],
Slosher_Washtub: ["DISTANCE", "SPLASH"],
Slosher: ["DIRECT", "DIRECT_MAX", "DIRECT_MIN", "DISTANCE", "SPLASH"],
Spinner: ["NORMAL_MAX", "NORMAL_MIN", "NORMAL_MAX_FULL_CHARGE", "SPLASH"],
Sprinkler: null,
Stringer_Short: ["NORMAL_MAX", "NORMAL_MIN", "DISTANCE"],
Stringer: ["NORMAL_MAX", "NORMAL_MIN", "DISTANCE"],
SuperHook: null,
SuperLanding: null,
TripleTornado: null,
UltraShot: null,
UltraStamp_Swing: null,
UltraStamp_Throw_BombCore: null,
UltraStamp_Throw: null,
};
export const damageTypesToCombine: Partial<
Record<
MainWeaponId,
Array<{
when: DamageType;
combineWith: DamageType;
/** for this weapon "when" damage already includes "combineWith" damage, so calculating multiplier only */
multiplierOnly?: boolean;
}>
>
> = {
// Explosher
3040: [{ when: "DIRECT", combineWith: "DISTANCE" }],
// Tri-Stringer
7010: [{ when: "NORMAL_MAX", combineWith: "DISTANCE" }],
// Splatana Stamper
8000: [
{ when: "SPLATANA_VERTICAL_DIRECT", combineWith: "SPLATANA_VERTICAL" },
{
when: "SPLATANA_HORIZONTAL_DIRECT",
combineWith: "SPLATANA_HORIZONTAL",
multiplierOnly: true,
},
],
// Splatana Wiper
8010: [
{ when: "SPLATANA_VERTICAL_DIRECT", combineWith: "SPLATANA_VERTICAL" },
{
when: "SPLATANA_HORIZONTAL_DIRECT",
combineWith: "SPLATANA_HORIZONTAL",
multiplierOnly: true,
},
],
};
invariant(
mainWeaponIds.every((id) => {
// not Splatana
if (id < 8000 || id >= 9000) return true;
return Boolean(damageTypesToCombine[id]);
}),
"Splatana weapon missing from damageTypesToCombine"
);
export const multiShot: Partial<Record<MainWeaponId, number>> = {
// L-3
300: 3,

View File

@ -7,7 +7,7 @@ import type {
import type { SPECIAL_EFFECTS } from "./specialEffects";
import type weaponParams from "./weapon-params.json";
import type abilityValues from "./ability-values.json";
import type { DAMAGE_RECEIVERS, DAMAGE_TYPE } from "./constants";
import type { DAMAGE_TYPE } from "./constants";
import type { AbilityWithUnknown } from "~/modules/in-game-lists/types";
type Overwrites = Record<
@ -173,10 +173,6 @@ export interface FullInkTankOption {
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

@ -1,2 +1,20 @@
export { possibleApValues } from "./core/utils";
export type { DamageReceiver, DamageType } from "./core/types";
export {
possibleApValues,
validatedWeaponIdFromSearchParams,
hpDivided,
} from "./core/utils";
export type {
DamageType,
AbilityPoints,
AnalyzedBuild,
SpecialWeaponParams,
SubWeaponParams,
} from "./core/types";
export {
buildStats,
specialDeviceHp,
specialFieldHp,
subStats,
} from "./core/stats";
export { DAMAGE_TYPE, damageTypeToWeaponType } from "./core/constants";
export { default as weaponParams } from "./core/weapon-params.json";

View File

@ -0,0 +1,169 @@
import { type MainWeaponId, mainWeaponIds } from "~/modules/in-game-lists";
import type { DamageType } from "~/features/build-analyzer";
import type objectDamages from "./core/object-dmg.json";
import invariant from "tiny-invariant";
export const DAMAGE_RECEIVERS = [
"Chariot", // Crab Tank
"NiceBall_Armor", // Booyah Bomb Armor
"ShockSonar", // Wave Breaker
"GreatBarrier_Barrier", // Big Bubbler Shield
"GreatBarrier_WeakPoint", // Big Bubbler Weak Point
"Gachihoko_Barrier", // Rainmaker Shield
"Wsb_Flag", // Squid Beakon
"Wsb_Shield", // Splash Wall
"Wsb_Sprinkler", // Sprinkler
"Bomb_TorpedoBullet", // Torpedo
"BulletUmbrellaCanopyCompact", // Undercover Brella Canopy
"BulletUmbrellaCanopyNormal", // Splat Brella Canopy
"BulletUmbrellaCanopyWide", // Tenta Brella Canopy
] as const;
export const objectDamageJsonKeyPriority: Record<
keyof typeof objectDamages,
Array<DamageType> | null
> = {
Blaster_BlasterMiddle: null,
Blaster_BlasterShort: null,
Blaster_KillOneShot: ["DIRECT"],
Blaster: null,
BlowerExhale_BombCore: null,
BlowerInhale: null,
BombFlower: null,
Bomb_CurlingBullet: null,
Bomb_DirectHit: ["BOMB_DIRECT"],
Bomb_Fizzy: null,
Bomb_Suction: null,
Bomb_TorpedoBullet: null,
Bomb_TorpedoSplashBurst: null,
Bomb_Trap: null,
Bomb: null,
BrushCore: null,
BrushSplash: null,
CannonMissile: null,
ChargerFull_Light: ["FULL_CHARGE"],
ChargerFull_Long: ["FULL_CHARGE"],
ChargerFull: ["FULL_CHARGE"],
Charger_Light: ["MAX_CHARGE", "TAP_SHOT"],
Charger_Long: ["MAX_CHARGE", "TAP_SHOT"],
Charger: ["MAX_CHARGE", "TAP_SHOT"],
Chariot_Body: null,
Chariot_Cannon: null,
Default: null,
EnemyFlyingHohei_BombCore: null,
GachihokoTimeUpBurst: null,
Gachihoko_BombCore: null,
Gachihoko_Bullet: null,
Geyser: null,
GoldenIkuraAttack: null,
InkStormRain: null,
InkStorm: null,
Jetpack_BombCore: null,
Jetpack_Bullet: null,
Jetpack_Coop: null,
Jetpack_Jet: null,
Maneuver_Short: null,
Maneuver: null,
MicroLaser: null,
MissionSalmonBuddy: null,
MovePainter_Burst: null,
MovePainter_Direct: null,
MultiMissile_BombCore: null,
MultiMissile_Bullet: null,
NiceBall: null,
ObjectEffect_Up: null,
RollerCore: null,
RollerSplash_Compact: null,
RollerSplash_Heavy: null,
RollerSplash_Hunter: null,
RollerSplash: null,
Saber_ChargeShot: ["SPLATANA_VERTICAL"],
Saber_ChargeSlash: ["SPLATANA_VERTICAL_DIRECT"],
Saber_Shot: ["SPLATANA_HORIZONTAL"],
Saber_Slash: ["SPLATANA_HORIZONTAL_DIRECT"],
Saber_ChargeSlash_Penetrate: null,
SakerocketBullet: null,
ShelterCanopy_Compact: null,
ShelterCanopy_Wide: null,
ShelterCanopy: null,
ShelterShot_Compact: null,
ShelterShot_Wide: null,
ShelterShot: null,
Shield: null,
ShockSonar_Wave: null,
Shooter_Blaze: ["NORMAL_MAX", "NORMAL_MIN"],
Shooter_Expert: ["NORMAL_MAX", "NORMAL_MIN"],
Shooter_First: ["NORMAL_MAX", "NORMAL_MIN"],
Shooter_FlashRepeat: ["NORMAL_MAX", "NORMAL_MIN"],
Shooter_Flash: ["NORMAL_MAX", "NORMAL_MIN"],
Shooter_Gravity: ["NORMAL_MAX", "NORMAL_MIN"],
Shooter_Heavy: ["NORMAL_MAX", "NORMAL_MIN"],
Shooter_Long: ["NORMAL_MAX", "NORMAL_MIN"],
Shooter_Precision: ["NORMAL_MAX", "NORMAL_MIN"],
Shooter_Short: ["NORMAL_MAX", "NORMAL_MIN"],
Shooter_TripleMiddle: ["NORMAL_MAX", "NORMAL_MIN"],
Shooter_TripleQuick: ["NORMAL_MAX", "NORMAL_MIN"],
Shooter: null,
Skewer_Body: null,
Skewer: null,
Slosher_Bathtub: ["DIRECT", "DIRECT_MAX", "DIRECT_MIN", "DISTANCE", "SPLASH"],
Slosher_Bear: ["DIRECT", "DIRECT_MAX", "DIRECT_MIN", "DISTANCE", "SPLASH"],
Slosher_WashtubBombCore: ["DIRECT", "DIRECT_MAX", "DIRECT_MIN"],
Slosher_Washtub: ["DISTANCE", "SPLASH"],
Slosher: ["DIRECT", "DIRECT_MAX", "DIRECT_MIN", "DISTANCE", "SPLASH"],
Spinner: ["NORMAL_MAX", "NORMAL_MIN", "NORMAL_MAX_FULL_CHARGE", "SPLASH"],
Sprinkler: null,
Stringer_Short: ["NORMAL_MAX", "NORMAL_MIN", "DISTANCE"],
Stringer: ["NORMAL_MAX", "NORMAL_MIN", "DISTANCE"],
SuperHook: null,
SuperLanding: null,
TripleTornado: null,
UltraShot: null,
UltraStamp_Swing: null,
UltraStamp_Throw_BombCore: null,
UltraStamp_Throw: null,
};
export const damageTypesToCombine: Partial<
Record<
MainWeaponId,
Array<{
when: DamageType;
combineWith: DamageType;
/** for this weapon "when" damage already includes "combineWith" damage, so calculating multiplier only */
multiplierOnly?: boolean;
}>
>
> = {
// Explosher
3040: [{ when: "DIRECT", combineWith: "DISTANCE" }],
// Tri-Stringer
7010: [{ when: "NORMAL_MAX", combineWith: "DISTANCE" }],
// Splatana Stamper
8000: [
{ when: "SPLATANA_VERTICAL_DIRECT", combineWith: "SPLATANA_VERTICAL" },
{
when: "SPLATANA_HORIZONTAL_DIRECT",
combineWith: "SPLATANA_HORIZONTAL",
multiplierOnly: true,
},
],
// Splatana Wiper
8010: [
{ when: "SPLATANA_VERTICAL_DIRECT", combineWith: "SPLATANA_VERTICAL" },
{
when: "SPLATANA_HORIZONTAL_DIRECT",
combineWith: "SPLATANA_HORIZONTAL",
multiplierOnly: true,
},
],
};
invariant(
mainWeaponIds.every((id) => {
// not Splatana
if (id < 8000 || id >= 9000) return true;
return Boolean(damageTypesToCombine[id]);
}),
"Splatana weapon missing from damageTypesToCombine"
);

View File

@ -1,11 +1,15 @@
import { useSearchParams } from "@remix-run/react";
import { assertType } from "~/utils/types";
import { type MainWeaponId } from "~/modules/in-game-lists";
import type { DAMAGE_TYPE } from "./constants";
import { calculateDamage } from "./objectDamage";
import { buildStats } from "./stats";
import type { AnalyzedBuild, DamageType } from "./types";
import { possibleApValues, validatedWeaponIdFromSearchParams } from "./utils";
import {
type DAMAGE_TYPE,
buildStats,
possibleApValues,
validatedWeaponIdFromSearchParams,
type AnalyzedBuild,
type DamageType,
} from "~/features/build-analyzer";
import { calculateDamage } from "./core/objectDamage";
const ABILITY_POINTS_SP_KEY = "ap";
const DAMAGE_TYPE_SP_KEY = "dmg";

View File

@ -0,0 +1,5 @@
import type { DAMAGE_RECEIVERS } from "./calculator-constants";
export type DamageReceiver = typeof DAMAGE_RECEIVERS[number];
export type HitPoints = Record<DamageReceiver, number>;

View File

@ -2,8 +2,11 @@ import { suite } from "uvu";
import * as assert from "uvu/assert";
import type { MainWeaponId } from "~/modules/in-game-lists";
import { calculateDamage } from "./objectDamage";
import { buildStats } from "./stats";
import type { AbilityPoints, DamageType } from "./types";
import {
buildStats,
type DamageType,
type AbilityPoints,
} from "~/features/build-analyzer";
function calculate({
mainWeaponId = 10,

View File

@ -1,24 +1,24 @@
import type {
AbilityPoints,
AnalyzedBuild,
DamageReceiver,
DamageType,
} from "./types";
} from "~/features/build-analyzer";
import { damageTypeToWeaponType } from "~/features/build-analyzer";
import objectDamages from "./object-dmg.json";
import type {
MainWeaponId,
SpecialWeaponId,
SubWeaponId,
} from "~/modules/in-game-lists";
import { roundToNDecimalPlaces } from "~/utils/number";
import invariant from "tiny-invariant";
import { objectHitPoints } from "./objectHitPoints";
import {
damageTypesToCombine,
damageTypeToWeaponType,
DAMAGE_RECEIVERS,
objectDamageJsonKeyPriority,
} from "./constants";
import { roundToNDecimalPlaces } from "~/utils/number";
import { objectHitPoints } from "./objectHitPoints";
import invariant from "tiny-invariant";
} from "../calculator-constants";
import type { DamageReceiver } from "../calculator-types";
export function damageTypeToMultipliers({
type,

View File

@ -4,15 +4,17 @@ import {
CRAB_TANK_ID,
SPLASH_WALL_ID,
} from "~/modules/in-game-lists";
import { specialDeviceHp, specialFieldHp, subStats } from "./stats";
import type {
AbilityPoints,
HitPoints,
SpecialWeaponParams,
SubWeaponParams,
} from "./types";
import { hpDivided } from "./utils";
import weaponParams from "./weapon-params.json";
import {
specialDeviceHp,
specialFieldHp,
subStats,
hpDivided,
weaponParams,
type AbilityPoints,
type SpecialWeaponParams,
type SubWeaponParams,
} from "~/features/build-analyzer";
import type { HitPoints } from "../calculator-types";
const WAVE_BREAKER_HP = 400;
const SPRINKER_HP = 100;

View File

@ -32,9 +32,9 @@ import { damageTypeTranslationString } from "~/utils/i18next";
import { useSetTitle } from "~/hooks/useSetTitle";
import type { ShouldReloadFunction } from "@remix-run/react";
import { Toggle } from "~/components/Toggle";
import { useObjectDamage } from "~/features/build-analyzer/core/useObjectDamage";
import type { DamageReceiver } from "~/features/build-analyzer";
import { useObjectDamage } from "../calculator-hooks";
import { type DamageType, possibleApValues } from "~/features/build-analyzer";
import type { DamageReceiver } from "../calculator-types";
export const CURRENT_PATCH = "2.0";

View File

@ -7,6 +7,10 @@ module.exports = {
routes: async (defineRoutes) => {
return defineRoutes((route) => {
route("/analyzer", "features/build-analyzer/routes/analyzer.tsx");
route(
"/object-damage-calculator",
"features/object-damage-calculator/routes/object-damage-calculator.tsx"
);
route("/to/:id", "features/tournament/routes/to.$id.tsx", () => {
route("/to/:id", "features/tournament/routes/to.$id.index.tsx");
route(