Further refactoring
This commit is contained in:
151
src/scenes/systems/ItemManager.ts
Normal file
151
src/scenes/systems/ItemManager.ts
Normal file
@@ -0,0 +1,151 @@
|
||||
import type { World, CombatantActor, Item, ItemDropActor, Vec2 } from "../../core/types";
|
||||
import { EntityManager } from "../../engine/EntityManager";
|
||||
|
||||
/**
|
||||
* Result of attempting to use an item
|
||||
*/
|
||||
export interface ItemUseResult {
|
||||
success: boolean;
|
||||
consumed: boolean;
|
||||
message?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Manages item-related operations including spawning, pickup, and usage.
|
||||
* Extracted from GameScene to centralize item logic and reduce complexity.
|
||||
*/
|
||||
export class ItemManager {
|
||||
private world: World;
|
||||
private entityManager: EntityManager;
|
||||
|
||||
constructor(world: World, entityManager: EntityManager) {
|
||||
this.world = world;
|
||||
this.entityManager = entityManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update references when world changes (e.g., new floor)
|
||||
*/
|
||||
updateWorld(world: World, entityManager: EntityManager): void {
|
||||
this.world = world;
|
||||
this.entityManager = entityManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawn an item drop at the specified position
|
||||
*/
|
||||
spawnItem(item: Item, pos: Vec2): void {
|
||||
if (!this.world || !this.entityManager) return;
|
||||
|
||||
const id = this.entityManager.getNextId();
|
||||
const drop: ItemDropActor = {
|
||||
id,
|
||||
pos: { x: pos.x, y: pos.y },
|
||||
category: "item_drop",
|
||||
item: { ...item } // Clone item
|
||||
};
|
||||
|
||||
this.entityManager.addActor(drop);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to pickup an item at the player's position
|
||||
* @returns The picked up item, or null if nothing to pick up
|
||||
*/
|
||||
tryPickup(player: CombatantActor): Item | null {
|
||||
if (!player || !player.inventory) return null;
|
||||
|
||||
const actors = this.entityManager.getActorsAt(player.pos.x, player.pos.y);
|
||||
const itemActor = actors.find((a): a is ItemDropActor => a.category === "item_drop");
|
||||
|
||||
if (itemActor) {
|
||||
const item = itemActor.item;
|
||||
|
||||
// Add to inventory
|
||||
player.inventory.items.push(item);
|
||||
|
||||
// Remove from world
|
||||
this.entityManager.removeActor(itemActor.id);
|
||||
|
||||
console.log("Picked up:", item.name);
|
||||
return item;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle using an item from inventory
|
||||
* Returns information about what happened
|
||||
*/
|
||||
handleUse(itemId: string, player: CombatantActor): ItemUseResult {
|
||||
if (!player || !player.inventory) {
|
||||
return { success: false, consumed: false, message: "Invalid player state" };
|
||||
}
|
||||
|
||||
const itemIdx = player.inventory.items.findIndex(it => it.id === itemId);
|
||||
if (itemIdx === -1) {
|
||||
return { success: false, consumed: false, message: "Item not found" };
|
||||
}
|
||||
|
||||
const item = player.inventory.items[itemIdx];
|
||||
|
||||
// Check if item is a healing consumable
|
||||
if (item.stats && item.stats.hp && item.stats.hp > 0) {
|
||||
const healAmount = item.stats.hp;
|
||||
|
||||
if (player.stats.hp >= player.stats.maxHp) {
|
||||
return { success: false, consumed: false, message: "Already at full health" };
|
||||
}
|
||||
|
||||
player.stats.hp = Math.min(player.stats.hp + healAmount, player.stats.maxHp);
|
||||
|
||||
// Remove item after use
|
||||
player.inventory.items.splice(itemIdx, 1);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
consumed: true,
|
||||
message: `Healed for ${healAmount} HP`
|
||||
};
|
||||
}
|
||||
|
||||
// Throwable items are handled by TargetingSystem, not here
|
||||
if (item.throwable) {
|
||||
return {
|
||||
success: true,
|
||||
consumed: false,
|
||||
message: "Throwable item - use targeting"
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
success: false,
|
||||
consumed: false,
|
||||
message: "Item has no effect"
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an item from player inventory by ID
|
||||
*/
|
||||
removeFromInventory(player: CombatantActor, itemId: string): boolean {
|
||||
if (!player || !player.inventory) return false;
|
||||
|
||||
const itemIdx = player.inventory.items.findIndex(it => it.id === itemId);
|
||||
if (itemIdx === -1) return false;
|
||||
|
||||
player.inventory.items.splice(itemIdx, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an item from player inventory by ID
|
||||
*/
|
||||
getItem(player: CombatantActor, itemId: string): Item | null {
|
||||
if (!player || !player.inventory) return null;
|
||||
|
||||
const item = player.inventory.items.find(it => it.id === itemId);
|
||||
return item || null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user