270 lines
6.4 KiB
TypeScript
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;
|