Files
rogue/src/core/config/Items.ts

270 lines
6.4 KiB
TypeScript

import type {
ConsumableItem,
MeleeWeaponItem,
RangedWeaponItem,
ArmourItem,
AmmoItem,
FlamethrowerItem
} from "../types";
import { GAME_CONFIG } from "../config/GameConfig";
// =============================================================================
// Per-Type Template Lists (Immutable)
// =============================================================================
export const CONSUMABLES = {
health_potion: {
name: "Health Potion",
textureKey: "items",
spriteIndex: 57,
healAmount: 5,
stackable: true,
},
throwing_dagger: {
name: "Throwing Dagger",
textureKey: "items",
spriteIndex: 15,
attack: 4,
throwable: true,
stackable: true,
},
upgrade_scroll: {
name: "Upgrade Scroll",
textureKey: "items",
spriteIndex: 79,
stackable: true,
},
} as const;
export const RANGED_WEAPONS = {
pistol: {
name: "Pistol",
textureKey: "weapons",
spriteIndex: 1,
attack: 10,
range: 8,
magazineSize: 6,
ammoType: "9mm",
projectileSpeed: 15,
fireSound: "shoot",
},
} as const;
export const MELEE_WEAPONS = {
iron_sword: {
name: "Iron Sword",
textureKey: "items",
spriteIndex: 2,
attack: 2,
},
} as const;
export const AMMO = {
ammo_9mm: {
name: "9mm Ammo",
textureKey: "weapons",
spriteIndex: 23,
ammoType: "9mm",
stackable: true,
},
} as const;
export const ARMOUR = {
leather_armor: {
name: "Leather Armor",
textureKey: "items",
spriteIndex: 25,
defense: 2,
},
} as const;
// Combined lookup for rendering (e.g., projectile sprites)
export const ALL_TEMPLATES = {
...CONSUMABLES,
...RANGED_WEAPONS,
...MELEE_WEAPONS,
...AMMO,
...ARMOUR,
} as const;
// =============================================================================
// Type-Safe IDs (derived from templates)
// =============================================================================
export type ConsumableId = keyof typeof CONSUMABLES;
export type RangedWeaponId = keyof typeof RANGED_WEAPONS;
export type MeleeWeaponId = keyof typeof MELEE_WEAPONS;
export type AmmoId = keyof typeof AMMO;
export type ArmourId = keyof typeof ARMOUR;
export type ItemTemplateId = keyof typeof ALL_TEMPLATES;
// =============================================================================
// Factory Functions
// =============================================================================
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,
type: "Consumable",
textureKey: t.textureKey,
spriteIndex: t.spriteIndex,
stackable: t.stackable ?? false,
quantity,
variant,
stats: {
hp: finalHealAmount,
attack: "attack" in t ? t.attack : undefined,
},
throwable: "throwable" in t ? t.throwable : undefined,
};
}
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,
type: "Weapon",
weaponType: "ranged",
textureKey: t.textureKey,
spriteIndex: t.spriteIndex,
currentAmmo: t.magazineSize,
reloadingTurnsLeft: 0,
variant,
stats: {
attack: t.attack + attackBonus,
range: t.range,
magazineSize: t.magazineSize,
ammoType: t.ammoType,
projectileSpeed: t.projectileSpeed,
fireSound: t.fireSound,
},
};
}
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,
type: "Weapon",
weaponType: "melee",
textureKey: t.textureKey,
spriteIndex: t.spriteIndex,
variant,
stats: {
attack: t.attack + attackBonus,
},
};
}
export function createAmmo(id: AmmoId, quantity = 10): AmmoItem {
const t = AMMO[id];
return {
id,
name: t.name,
type: "Ammo",
textureKey: t.textureKey,
spriteIndex: t.spriteIndex,
ammoType: t.ammoType,
stackable: true,
quantity,
};
}
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,
type: "BodyArmour",
textureKey: t.textureKey,
spriteIndex: t.spriteIndex,
variant,
stats: {
defense: t.defense + defenseBonus,
},
};
}
export function createUpgradeScroll(quantity = 1): ConsumableItem {
const t = CONSUMABLES["upgrade_scroll"];
return {
id: "upgrade_scroll",
name: t.name,
type: "Consumable",
textureKey: t.textureKey,
spriteIndex: t.spriteIndex,
stackable: true,
quantity,
};
}
export function createFlamethrower(): FlamethrowerItem {
const config = GAME_CONFIG.gameplay.flamethrower;
return {
id: "flamethrower",
name: "Flamethrower",
type: "Weapon",
weaponType: "flamethrower",
textureKey: "weapons",
spriteIndex: 5,
charges: config.maxCharges,
maxCharges: config.maxCharges,
lastRechargeTurn: 0,
stats: {
attack: config.initialDamage,
range: config.range,
},
};
}
// Legacy export for backward compatibility during migration
export const ITEMS = ALL_TEMPLATES;