mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-05-25 13:03:59 -05:00
321 lines
7.7 KiB
TypeScript
321 lines
7.7 KiB
TypeScript
import { assertUnreachable } from "~/utils/types";
|
|
import type { MainWeaponId, SpecialWeaponId, SubWeaponId } from "./types";
|
|
|
|
export const weaponCategories = [
|
|
{
|
|
name: "SHOOTERS",
|
|
weaponIds: [
|
|
0, 1, 10, 11, 20, 21, 22, 30, 31, 32, 40, 41, 42, 45, 46, 47, 50, 51, 60,
|
|
61, 70, 71, 72, 80, 81, 82, 90, 91, 92, 100, 101, 300, 301, 302, 310, 311,
|
|
312, 400, 401,
|
|
],
|
|
},
|
|
{
|
|
name: "BLASTERS",
|
|
weaponIds: [
|
|
200, 201, 205, 210, 211, 212, 220, 221, 230, 231, 240, 241, 250, 251, 252,
|
|
260, 261,
|
|
],
|
|
},
|
|
{
|
|
name: "ROLLERS",
|
|
weaponIds: [
|
|
1000, 1001, 1002, 1010, 1011, 1015, 1020, 1021, 1022, 1030, 1031, 1040,
|
|
1041, 1042,
|
|
],
|
|
},
|
|
{
|
|
name: "BRUSHES",
|
|
weaponIds: [1100, 1101, 1110, 1111, 1112, 1115, 1120, 1121, 1122],
|
|
},
|
|
{
|
|
name: "CHARGERS",
|
|
weaponIds: [
|
|
2000, 2001, 2010, 2011, 2012, 2015, 2020, 2021, 2022, 2030, 2031, 2040,
|
|
2041, 2050, 2051, 2060, 2061, 2070, 2071,
|
|
],
|
|
},
|
|
{
|
|
name: "SLOSHERS",
|
|
weaponIds: [
|
|
3000, 3001, 3005, 3010, 3011, 3012, 3020, 3021, 3030, 3031, 3040, 3041,
|
|
3050, 3051, 3052,
|
|
],
|
|
},
|
|
{
|
|
name: "SPLATLINGS",
|
|
weaponIds: [
|
|
4000, 4001, 4002, 4010, 4011, 4015, 4020, 4021, 4022, 4030, 4031, 4040,
|
|
4041, 4050, 4051,
|
|
],
|
|
},
|
|
{
|
|
name: "DUALIES",
|
|
weaponIds: [
|
|
5000, 5001, 5002, 5010, 5015, 5011, 5012, 5020, 5021, 5030, 5031, 5032,
|
|
5040, 5041, 5050, 5051,
|
|
],
|
|
},
|
|
{
|
|
name: "BRELLAS",
|
|
weaponIds: [
|
|
6000, 6001, 6005, 6010, 6011, 6012, 6020, 6021, 6022, 6030, 6031,
|
|
],
|
|
},
|
|
{
|
|
name: "STRINGERS",
|
|
weaponIds: [7010, 7011, 7012, 7015, 7020, 7021, 7022, 7030, 7031],
|
|
},
|
|
{
|
|
name: "SPLATANAS",
|
|
weaponIds: [8000, 8001, 8002, 8005, 8010, 8011, 8012, 8020, 8021],
|
|
},
|
|
] as const;
|
|
|
|
export const mainWeaponIds = weaponCategories
|
|
.flatMap((category) => category.weaponIds)
|
|
.sort((a, b) => a - b);
|
|
|
|
const weaponIdToAltId = new Map<MainWeaponId, MainWeaponId | MainWeaponId[]>([
|
|
[40, [45, 47]],
|
|
[41, 46],
|
|
[200, 205],
|
|
[1010, 1015],
|
|
[1110, 1115],
|
|
[2010, 2015],
|
|
[3000, 3005],
|
|
[4010, 4015],
|
|
[5010, 5015],
|
|
[6000, 6005],
|
|
[7010, 7015],
|
|
[8000, 8005],
|
|
]);
|
|
const altWeaponIdToId = new Map<MainWeaponId, MainWeaponId>([
|
|
[45, 40],
|
|
[47, 40],
|
|
[46, 41],
|
|
[205, 200],
|
|
[1015, 1010],
|
|
[1115, 1110],
|
|
[2015, 2010],
|
|
[3005, 3000],
|
|
[4015, 4010],
|
|
[5015, 5010],
|
|
[6005, 6000],
|
|
[7015, 7010],
|
|
[8005, 8000],
|
|
]);
|
|
|
|
/**
|
|
* Folds an alt-skin weapon id to its base id, leaving non-alt ids untouched.
|
|
*
|
|
* Unlike {@link weaponIdToBaseWeaponId}, alt kits are preserved (e.g. Tentatek
|
|
* Splattershot stays 41) — only cosmetic alt skins collapse to their base.
|
|
*
|
|
* Mirrors the `BuildWeapon.canonicalWeaponSplId` column so TypeScript callers
|
|
* and SQL queries agree on what a weapon's canonical id is.
|
|
*
|
|
* @example
|
|
* // Splattershot — base weapon, returned unchanged
|
|
* canonicalWeaponSplId(40); // -> 40
|
|
*
|
|
* // Tentatek Splattershot — alt kit, returned unchanged
|
|
* canonicalWeaponSplId(41); // -> 41
|
|
*
|
|
* // Hero Shot Replica — alt skin, folded to Splattershot
|
|
* canonicalWeaponSplId(45); // -> 40
|
|
*/
|
|
export function canonicalWeaponSplId(weaponSplId: MainWeaponId): MainWeaponId {
|
|
return altWeaponIdToId.get(weaponSplId) ?? weaponSplId;
|
|
}
|
|
|
|
/**
|
|
* Converts a given weapon ID to an array containing the weapon ID and its alternate IDs. For example if you enter the ID 40 (Splattershot) it will return [40, 45, 47] (Splattershot, Hero Shot Replica, Order Shot Replica)
|
|
*/
|
|
export function weaponIdToArrayWithAlts(weaponId: MainWeaponId) {
|
|
const altId = weaponIdToAltId.get(weaponId);
|
|
if (altId !== undefined) {
|
|
return [weaponId, ...(Array.isArray(altId) ? altId : [altId])];
|
|
}
|
|
|
|
const regularId = altWeaponIdToId.get(weaponId);
|
|
if (regularId !== undefined) {
|
|
const altId = weaponIdToAltId.get(regularId);
|
|
if (altId !== undefined) {
|
|
return [regularId, ...(Array.isArray(altId) ? altId : [altId])];
|
|
}
|
|
}
|
|
|
|
return [weaponId];
|
|
}
|
|
|
|
/**
|
|
* Determines the type of weapon based on its ID
|
|
*
|
|
* @returns "ALT_SKIN" if the weapon is an alternate skin, "BASE" if it's a base weapon, or "ALT_KIT" if it's an alternate kit
|
|
*
|
|
* @example
|
|
* // Splattershot is a base weapon
|
|
* weaponIdToType(40); // -> "BASE"
|
|
*
|
|
* // Tentatek Splattershot is an alternate kit
|
|
* weaponIdToType(41); // -> "ALT_KIT"
|
|
*
|
|
* // Hero Shot Replica is an alternate skin
|
|
* weaponIdToType(45); // -> "ALT_SKIN"
|
|
*/
|
|
export const weaponIdToType = (weaponId: MainWeaponId) => {
|
|
if (altWeaponIdToId.has(weaponId)) return "ALT_SKIN";
|
|
if (weaponId === weaponIdToBaseWeaponId(weaponId)) return "BASE";
|
|
|
|
return "ALT_KIT";
|
|
};
|
|
|
|
export const SPLAT_BOMB_ID = 0;
|
|
export const SUCTION_BOMB_ID = 1;
|
|
export const BURST_BOMB_ID = 2;
|
|
export const SPRINKLER_ID = 3;
|
|
export const SPLASH_WALL_ID = 4;
|
|
export const FIZZY_BOMB_ID = 5;
|
|
export const CURLING_BOMB_ID = 6;
|
|
export const AUTO_BOMB_ID = 7;
|
|
export const SQUID_BEAKON_ID = 8;
|
|
export const POINT_SENSOR_ID = 9;
|
|
export const INK_MINE_ID = 10;
|
|
export const TOXIC_MIST_ID = 11;
|
|
export const ANGLE_SHOOTER_ID = 12;
|
|
export const TORPEDO_ID = 13;
|
|
|
|
export const subWeaponIds = [
|
|
SPLAT_BOMB_ID,
|
|
SUCTION_BOMB_ID,
|
|
BURST_BOMB_ID,
|
|
SPRINKLER_ID,
|
|
SPLASH_WALL_ID,
|
|
FIZZY_BOMB_ID,
|
|
CURLING_BOMB_ID,
|
|
AUTO_BOMB_ID,
|
|
SQUID_BEAKON_ID,
|
|
POINT_SENSOR_ID,
|
|
INK_MINE_ID,
|
|
TOXIC_MIST_ID,
|
|
ANGLE_SHOOTER_ID,
|
|
TORPEDO_ID,
|
|
] as const;
|
|
|
|
export const nonBombSubWeaponIds = [
|
|
SPRINKLER_ID,
|
|
SPLASH_WALL_ID,
|
|
SQUID_BEAKON_ID,
|
|
POINT_SENSOR_ID,
|
|
TOXIC_MIST_ID,
|
|
] as SubWeaponId[];
|
|
|
|
export const TRIZOOKA_ID = 1;
|
|
export const BIG_BUBBLER_ID = 2;
|
|
export const ZIPCASTER_ID = 3;
|
|
const TENTA_MISSILES_ID = 4;
|
|
export const INK_STORM_ID = 5;
|
|
export const BOOYAH_BOMB_ID = 6;
|
|
export const WAVE_BREAKER_ID = 7;
|
|
export const INK_VAC_ID = 8;
|
|
export const KILLER_WAIL_ID = 9;
|
|
const INKJET_ID = 10;
|
|
const ULTRA_STAMP_ID = 11;
|
|
export const CRAB_TANK_ID = 12;
|
|
const REEF_SLIDER_ID = 13;
|
|
const TRIPLE_INKSTRIKE_ID = 14;
|
|
const TACTICOOLER_ID = 15;
|
|
export const SUPER_CHUMP_ID = 16;
|
|
const KRAKEN_ROYALE_ID = 17;
|
|
export const TRIPLE_SPLASHDOWN_ID = 18;
|
|
export const SPLATTERCOLOR_SCREEN_ID = 19;
|
|
|
|
export const specialWeaponIds = [
|
|
TRIZOOKA_ID,
|
|
BIG_BUBBLER_ID,
|
|
ZIPCASTER_ID,
|
|
TENTA_MISSILES_ID,
|
|
INK_STORM_ID,
|
|
BOOYAH_BOMB_ID,
|
|
WAVE_BREAKER_ID,
|
|
INK_VAC_ID,
|
|
KILLER_WAIL_ID,
|
|
INKJET_ID,
|
|
ULTRA_STAMP_ID,
|
|
CRAB_TANK_ID,
|
|
REEF_SLIDER_ID,
|
|
TRIPLE_INKSTRIKE_ID,
|
|
TACTICOOLER_ID,
|
|
SUPER_CHUMP_ID,
|
|
KRAKEN_ROYALE_ID,
|
|
TRIPLE_SPLASHDOWN_ID,
|
|
SPLATTERCOLOR_SCREEN_ID,
|
|
] as const;
|
|
|
|
export const nonDamagingSpecialWeaponIds = [BIG_BUBBLER_ID, TACTICOOLER_ID];
|
|
|
|
export const exampleMainWeaponIdWithSpecialWeaponId = (
|
|
specialWeaponId: SpecialWeaponId,
|
|
): MainWeaponId => {
|
|
switch (specialWeaponId) {
|
|
case TRIZOOKA_ID:
|
|
return 40;
|
|
case BIG_BUBBLER_ID:
|
|
return 10;
|
|
case ZIPCASTER_ID:
|
|
return 8000;
|
|
case TENTA_MISSILES_ID:
|
|
return 1030;
|
|
case INK_STORM_ID:
|
|
return 3040;
|
|
case BOOYAH_BOMB_ID:
|
|
return 3020;
|
|
case WAVE_BREAKER_ID:
|
|
return 220;
|
|
case INK_VAC_ID:
|
|
return 2010;
|
|
case KILLER_WAIL_ID:
|
|
return 50;
|
|
case INKJET_ID:
|
|
return 3010;
|
|
case ULTRA_STAMP_ID:
|
|
return 4000;
|
|
case CRAB_TANK_ID:
|
|
return 20;
|
|
case REEF_SLIDER_ID:
|
|
return 5040;
|
|
case TRIPLE_INKSTRIKE_ID:
|
|
return 41;
|
|
case TACTICOOLER_ID:
|
|
return 60;
|
|
case SUPER_CHUMP_ID:
|
|
return 61;
|
|
case KRAKEN_ROYALE_ID:
|
|
return 4011;
|
|
case TRIPLE_SPLASHDOWN_ID:
|
|
return 211;
|
|
case SPLATTERCOLOR_SCREEN_ID:
|
|
return 401;
|
|
default: {
|
|
assertUnreachable(specialWeaponId);
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Calculates the base weapon ID from a main weapon ID.
|
|
*
|
|
* @example
|
|
* // Returns 40 (because Splattershot is the base weapon for its kit)
|
|
* weaponIdToBaseWeaponId(40); // -> 40
|
|
*
|
|
* // (41 is Tentatek Splattershot, which is an alt kit of Splattershot)
|
|
* weaponIdToBaseWeaponId(41); // -> 40
|
|
*
|
|
* // (45 is Hero Shot Replica, which is an alt skin of Splattershot)
|
|
* weaponIdToBaseWeaponId(45); // -> 40
|
|
*/
|
|
export const weaponIdToBaseWeaponId = (id: MainWeaponId) =>
|
|
(id - (id % 10)) as MainWeaponId;
|