feat: create item variants

This commit is contained in:
Peter Stockings
2026-01-23 08:29:39 +11:00
parent d2039df8c8
commit e130e6d174
8 changed files with 384 additions and 39 deletions

View File

@@ -94,36 +94,66 @@ export type ItemTemplateId = keyof typeof ALL_TEMPLATES;
// Factory Functions
// =============================================================================
export function createConsumable(id: ConsumableId, quantity = 1): ConsumableItem {
import {
ALL_VARIANTS,
type ArmourVariantId,
type WeaponVariantId,
type ConsumableVariantId
} from "./ItemVariants";
export function createConsumable(
id: ConsumableId,
quantity = 1,
variant?: ConsumableVariantId
): ConsumableItem {
const t = CONSUMABLES[id];
const v = variant ? ALL_VARIANTS[variant] : null;
// Apply effect multiplier for consumables
const effectMult = v?.statModifiers.effectMultiplier ?? 1;
const baseHealAmount = "healAmount" in t ? t.healAmount : undefined;
const finalHealAmount = baseHealAmount ? Math.floor(baseHealAmount * effectMult) : undefined;
const name = v ? `${v.prefix} ${t.name}` : t.name;
return {
id,
name: t.name,
name,
type: "Consumable",
textureKey: t.textureKey,
spriteIndex: t.spriteIndex,
stackable: t.stackable ?? false,
quantity,
variant,
stats: {
hp: "healAmount" in t ? t.healAmount : undefined,
hp: finalHealAmount,
attack: "attack" in t ? t.attack : undefined,
},
throwable: "throwable" in t ? t.throwable : undefined,
};
}
export function createRangedWeapon(id: RangedWeaponId): RangedWeaponItem {
export function createRangedWeapon(
id: RangedWeaponId,
variant?: WeaponVariantId
): RangedWeaponItem {
const t = RANGED_WEAPONS[id];
const v = variant ? ALL_VARIANTS[variant] : null;
const name = v ? `${v.prefix} ${t.name}` : t.name;
const attackBonus = (v?.statModifiers as { attack?: number })?.attack ?? 0;
return {
id,
name: t.name,
name,
type: "Weapon",
weaponType: "ranged",
textureKey: t.textureKey,
spriteIndex: t.spriteIndex,
currentAmmo: t.magazineSize,
variant,
stats: {
attack: t.attack,
attack: t.attack + attackBonus,
range: t.range,
magazineSize: t.magazineSize,
ammoType: t.ammoType,
@@ -133,17 +163,26 @@ export function createRangedWeapon(id: RangedWeaponId): RangedWeaponItem {
};
}
export function createMeleeWeapon(id: MeleeWeaponId): MeleeWeaponItem {
export function createMeleeWeapon(
id: MeleeWeaponId,
variant?: WeaponVariantId
): MeleeWeaponItem {
const t = MELEE_WEAPONS[id];
const v = variant ? ALL_VARIANTS[variant] : null;
const name = v ? `${v.prefix} ${t.name}` : t.name;
const attackBonus = (v?.statModifiers as { attack?: number })?.attack ?? 0;
return {
id,
name: t.name,
name,
type: "Weapon",
weaponType: "melee",
textureKey: t.textureKey,
spriteIndex: t.spriteIndex,
variant,
stats: {
attack: t.attack,
attack: t.attack + attackBonus,
},
};
}
@@ -162,19 +201,29 @@ export function createAmmo(id: AmmoId, quantity = 10): AmmoItem {
};
}
export function createArmour(id: ArmourId): ArmourItem {
export function createArmour(
id: ArmourId,
variant?: ArmourVariantId
): ArmourItem {
const t = ARMOUR[id];
const v = variant ? ALL_VARIANTS[variant] : null;
const name = v ? `${v.prefix} ${t.name}` : t.name;
const defenseBonus = v?.statModifiers.defense ?? 0;
return {
id,
name: t.name,
name,
type: "BodyArmour",
textureKey: t.textureKey,
spriteIndex: t.spriteIndex,
variant,
stats: {
defense: t.defense,
defense: t.defense + defenseBonus,
},
};
}
// Legacy export for backward compatibility during migration
export const ITEMS = ALL_TEMPLATES;