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

129 lines
No EOL
3.7 KiB
TypeScript

/**
* Utility functions for weapon and character modifiers (awakenings, weapon keys, AX skills)
*/
import type { Awakening, WeaponKey } from '$lib/types/api/entities'
import type { SimpleAxSkill } from '$lib/types/SimpleAxSkill'
import { isWeaponSeriesRef, type WeaponSeriesRef } from '$lib/types/api/weaponSeries'
import { getBasePath } from '$lib/utils/images'
/**
* Get the image URL for an awakening type
*/
export function getAwakeningImage(awakening?: { type?: Awakening; level?: number }): string | null {
if (!awakening?.type?.slug) return null
const slug = awakening.type.slug
// No image for Balanced awakening type (character only)
if (slug === 'character-balanced') return null
// Character awakenings are JPG, weapon awakenings are PNG
const isCharacterAwakening = slug.startsWith('character-')
const extension = isCharacterAwakening ? 'jpg' : 'png'
return `${getBasePath()}/awakening/${slug}.${extension}`
}
/**
* Helper to get series slug from WeaponSeriesRef
*/
function getSeriesSlug(series?: WeaponSeriesRef | null): string | undefined {
if (!isWeaponSeriesRef(series)) {
return undefined
}
return series.slug
}
/**
* Get the image URL for a weapon key with proper element/proficiency/mod variants
*/
export function getWeaponKeyImage(
key: WeaponKey,
weaponElement?: number,
weaponProficiency?: number,
weaponSeries?: WeaponSeriesRef | null,
weaponName?: { en?: string }
): string {
if (!key.slug) return ''
const baseUrl = `${getBasePath()}/weapon-keys/`
let filename = key.slug
// Get series slug for comparison
const seriesSlug = getSeriesSlug(weaponSeries)
// Handle element-specific telumas (Draconic weapons)
const elementalTelumas = [15008, 16001, 16002]
const granblueId = key.granblue_id ?? 0
if (elementalTelumas.includes(granblueId) && weaponElement) {
filename += `-${weaponElement}`
}
// Handle proficiency-specific ultima keys (slot 0)
if (key.slot === 0 && seriesSlug === 'ultima' && weaponProficiency) {
filename += `-${weaponProficiency}`
}
// Handle element-specific opus pendulums (slot 1)
if (seriesSlug === 'dark-opus' && key.slot === 1 && weaponElement) {
const mod = weaponName?.en?.includes('Repudiation') ? 'primal' : 'magna'
const suffixes = [
'pendulum-strength',
'pendulum-zeal',
'pendulum-strife',
'chain-temperament',
'chain-restoration',
'chain-glorification'
]
if (suffixes.includes(key.slug)) {
filename += `-${mod}-${weaponElement}`
}
}
return `${baseUrl}${filename}.png`
}
/**
* Get all weapon key images for a weapon
*/
export function getWeaponKeyImages(
keys?: WeaponKey[],
weaponElement?: number,
weaponProficiency?: number | number[],
weaponSeries?: WeaponSeriesRef | null,
weaponName?: { en?: string }
): Array<{ url: string; alt: string }> {
if (!keys || keys.length === 0) return []
// Handle proficiency being an array (take first element)
const proficiency = Array.isArray(weaponProficiency) ? weaponProficiency[0] : weaponProficiency
return keys
.filter(key => key.slug)
.map(key => ({
url: getWeaponKeyImage(key, weaponElement, proficiency, weaponSeries, weaponName),
alt: key.name?.en || key.slug || 'Weapon Key'
}))
}
/**
* Get the image URL for an AX skill
* Note: Requires ax data reference implementation
*/
export function getAxSkillImage(axSkill?: { slug?: string }): string | null {
if (!axSkill?.slug) return null
return `${getBasePath()}/ax/${axSkill.slug}.png`
}
/**
* Get all AX skill images for a weapon
* Note: This is a placeholder until ax data structure is fully implemented
*/
export function getAxSkillImages(ax?: SimpleAxSkill[]): Array<{ url: string; alt: string }> {
// TODO: Implement when ax data reference is available
// This would need to map ax modifiers to actual ax skill data
return []
}