hensei-web/src/lib/utils/gridHelpers.ts

99 lines
2.8 KiB
TypeScript

/**
* Grid slot finding and helper utilities
* Handles finding available positions in weapon, summon, and character grids
*/
import type { Party } from '$lib/types/api/party'
import { GridType } from '$lib/types/enums'
/** Sentinel value indicating no empty slot was found */
export const SLOT_NOT_FOUND = -999
export interface SlotRange {
start: number
end: number
specialSlots?: number[] // e.g., mainhand (-1), friend summon (6)
}
/** Grid slot configuration for each grid type */
const GRID_CONFIGS: Record<GridType, SlotRange> = {
[GridType.Weapon]: { start: 0, end: 8, specialSlots: [-1] }, // mainhand + 9 grid slots
[GridType.Summon]: { start: 0, end: 5, specialSlots: [-1, 6] }, // main + 6 grid + friend
[GridType.Character]: { start: 0, end: 4, specialSlots: [] } // 5 character slots (0-4)
}
/**
* Finds the next empty slot in a grid
*
* @param party - Current party state
* @param gridType - Type of grid to search (weapon, summon, or character)
* @returns Position number of next empty slot, or SLOT_NOT_FOUND if grid is full
*
* @example
* ```typescript
* const nextSlot = findNextEmptySlot(party, GridType.Weapon)
* if (nextSlot !== SLOT_NOT_FOUND) {
* selectedSlot = nextSlot
* }
* ```
*/
export function findNextEmptySlot(party: Party, gridType: GridType): number {
const config = GRID_CONFIGS[gridType]
const collection = getCollectionForType(party, gridType)
// Check special slots first (e.g., mainhand, main summon)
for (const specialSlot of config.specialSlots || []) {
if (!isSlotOccupied(collection, specialSlot, gridType)) {
return specialSlot
}
}
// Check regular grid slots
for (let i = config.start; i <= config.end; i++) {
if (!isSlotOccupied(collection, i, gridType)) {
return i
}
}
return SLOT_NOT_FOUND
}
/**
* Gets the appropriate collection array for a grid type
*/
function getCollectionForType(party: Party, gridType: GridType) {
switch (gridType) {
case GridType.Weapon:
return party.weapons
case GridType.Summon:
return party.summons
case GridType.Character:
return party.characters
}
}
/**
* Checks if a specific slot position is occupied
* Handles special cases for mainhand weapons, main/friend summons
*/
function isSlotOccupied(collection: any[], position: number, gridType: GridType): boolean {
// For weapons, check both position and mainhand flag
if (gridType === GridType.Weapon) {
return collection.some(
(item) => item.position === position || (position === -1 && item.mainhand)
)
}
// For summons, check position, main, and friend flags
if (gridType === GridType.Summon) {
return collection.some(
(item) =>
item.position === position ||
(position === -1 && item.main) ||
(position === 6 && item.friend)
)
}
// For characters, simple position check
return collection.some((item) => item.position === position)
}