feat: expand ISAC content modeling
Validate and deploy production / validate (push) Canceled after 0s
Validate and deploy production / deploy (push) Canceled after 0s
Validate and deploy staging / validate (push) Successful in 28s
Validate and deploy staging / deploy (push) Successful in 1m3s

This commit is contained in:
jb
2026-08-03 01:23:20 -04:00
parent d9924a95b9
commit 57068b61cd
90 changed files with 9635 additions and 1270 deletions
+59 -9
View File
@@ -1,19 +1,42 @@
export const WEAPON_MOD_SLOT_TYPES = [
'Optics',
'Muzzle',
'Underbarrel',
'Magazine',
'Barrel',
'Upper Receiver',
'Lower Receiver',
'Trigger',
export const WEAPON_MOD_SLOT_DEFINITIONS = [
{ id: '28ffc3b1-5d98-4273-a9af-67dbff3e5c76', name: 'Optics' },
{ id: 'c4598f51-2cb0-4a20-a3a7-6d8983a26598', name: 'Muzzle' },
{ id: '85ca3493-1871-4d22-950a-ed718fd547e0', name: 'Underbarrel' },
{ id: '4d809a35-8285-4bff-be98-a0effe1d257e', name: 'Magazine' },
{ id: '0e157cfe-975c-441d-8f49-72983161e7b1', name: 'Barrel' },
{ id: '551fd7c8-3e5b-4c89-8437-9b901e89e8aa', name: 'Upper Receiver' },
{ id: '72573367-6e91-4312-9cc3-710ede4f078e', name: 'Lower Receiver' },
{ id: '8dda5edb-6079-4a23-a556-cd9be4521c70', name: 'Trigger' },
] as const;
export type WeaponModSlotType =
(typeof WEAPON_MOD_SLOT_DEFINITIONS)[number]['name'];
export const WEAPON_MOD_SLOT_TYPES = WEAPON_MOD_SLOT_DEFINITIONS.map(
(definition) => definition.name,
) as WeaponModSlotType[];
export function weaponModSlotDefinitionById(id: string) {
return WEAPON_MOD_SLOT_DEFINITIONS.find((definition) => definition.id === id);
}
export function weaponModSlotDefinitionByName(name: string) {
return WEAPON_MOD_SLOT_DEFINITIONS.find(
(definition) => definition.name === name,
);
}
export type WeaponModSlotConfig = {
tier: number;
slots: string[];
};
export type PublicWeaponModSlot = {
slot: string;
unlockedAtTierOne: boolean;
iconUrl?: string;
};
export function normalizeWeaponModSlotPayload(
payload: unknown,
): WeaponModSlotConfig[] {
@@ -52,6 +75,33 @@ export function sharedWeaponModSlots(
];
}
export function publicWeaponModSlots(
nativeTier: number,
configurations: WeaponModSlotConfig[],
): PublicWeaponModSlot[] {
const nativeSlots =
configurations.find((row) => Number(row.tier) === nativeTier)?.slots ?? [];
const displayedSlots =
nativeTier === 0
? sharedWeaponModSlots(configurations).length
? sharedWeaponModSlots(configurations)
: nativeSlots
: nativeSlots;
const ordered = [...new Set(displayedSlots)].sort(
(left, right) =>
WEAPON_MOD_SLOT_TYPES.indexOf(
left as (typeof WEAPON_MOD_SLOT_TYPES)[number],
) -
WEAPON_MOD_SLOT_TYPES.indexOf(
right as (typeof WEAPON_MOD_SLOT_TYPES)[number],
),
);
return ordered.map((slot) => ({
slot,
unlockedAtTierOne: nativeTier === 0 && !nativeSlots.includes(slot),
}));
}
export function excludedTierZeroWeaponModSlot(
sharedSlots: string[],
configurations: WeaponModSlotConfig[],