Files
i-want-to-heal-2/src/claudeCraftEquipmentRules.ts
T

60 lines
2.8 KiB
TypeScript

import type { ItemDef, PlayerClass } from './claudeCraftTypes'
export type ArmorType = 'cloth' | 'leather' | 'mail'
type WeaponArchetype = 'warrior' | 'caster' | 'rogue'
const MAIL_CLASSES = new Set<PlayerClass>(['warrior', 'paladin', 'shaman'])
const LEATHER_CLASSES = new Set<PlayerClass>(['druid', 'rogue', 'hunter'])
const CLOTH_CLASSES = new Set<PlayerClass>(['mage', 'priest', 'warlock'])
const CASTER_ARCHETYPE_CLASSES = new Set<PlayerClass>(['mage', 'priest', 'warlock', 'druid'])
const WARRIOR_WEAPON_CLASSES = new Set<PlayerClass>(['warrior', 'rogue', 'hunter', 'shaman', 'paladin'])
const CASTER_WEAPON_CLASSES = new Set<PlayerClass>(['mage', 'priest', 'warlock', 'shaman', 'paladin', 'druid'])
const ROGUE_WEAPON_CLASSES = new Set<PlayerClass>(['rogue', 'hunter'])
const OLD_WARRIOR_WEAPON_ARCHETYPE = new Set<PlayerClass>(['warrior', 'paladin', 'shaman'])
const OLD_CASTER_WEAPON_ARCHETYPE = new Set<PlayerClass>(['mage', 'priest', 'warlock', 'druid'])
const ARMOR_RANK: Record<ArmorType, number> = {
cloth: 0,
leather: 1,
mail: 2,
}
function subsetOf(classes: readonly PlayerClass[], allowed: ReadonlySet<PlayerClass>): boolean {
return classes.length > 0 && classes.every((cls) => allowed.has(cls))
}
export function armorTypeForItem(item: ItemDef): ArmorType | null {
if (item.kind !== 'armor') return null
if (item.armorType) return item.armorType
if (!item.requiredClass) return null
if (subsetOf(item.requiredClass, MAIL_CLASSES)) return 'mail'
if (subsetOf(item.requiredClass, LEATHER_CLASSES)) return 'leather'
if (subsetOf(item.requiredClass, CLOTH_CLASSES) || subsetOf(item.requiredClass, CASTER_ARCHETYPE_CLASSES)) return 'cloth'
return null
}
export function maxArmorTypeForClass(cls: PlayerClass): ArmorType {
if (MAIL_CLASSES.has(cls)) return 'mail'
if (LEATHER_CLASSES.has(cls)) return 'leather'
return 'cloth'
}
export function weaponArchetypeForItem(item: ItemDef): WeaponArchetype | null {
if (item.kind !== 'weapon' || !item.requiredClass) return null
if (subsetOf(item.requiredClass, OLD_WARRIOR_WEAPON_ARCHETYPE)) return 'warrior'
if (subsetOf(item.requiredClass, OLD_CASTER_WEAPON_ARCHETYPE)) return 'caster'
if (subsetOf(item.requiredClass, ROGUE_WEAPON_CLASSES)) return 'rogue'
return null
}
export function canEquipItem(cls: PlayerClass, item: ItemDef): boolean {
const armorType = armorTypeForItem(item)
if (armorType) return ARMOR_RANK[armorType] <= ARMOR_RANK[maxArmorTypeForClass(cls)]
const weaponArchetype = weaponArchetypeForItem(item)
if (weaponArchetype === 'warrior') return WARRIOR_WEAPON_CLASSES.has(cls)
if (weaponArchetype === 'caster') return CASTER_WEAPON_CLASSES.has(cls)
if (weaponArchetype === 'rogue') return ROGUE_WEAPON_CLASSES.has(cls)
if (item.requiredClass) return item.requiredClass.includes(cls)
return true
}