Add quick slot and consumables (health and mana potions)

This commit is contained in:
Peter Stockings
2026-01-06 18:23:34 +11:00
parent 57fb85f62e
commit 3b29180a00
8 changed files with 281 additions and 4 deletions

View File

@@ -0,0 +1,124 @@
import Phaser from "phaser";
import type { CombatantActor, Item } from "../../core/types";
export class QuickSlotComponent {
private scene: Phaser.Scene;
private container!: Phaser.GameObjects.Container;
private slots: Phaser.GameObjects.Container[] = [];
private itemMap: (Item | null)[] = [null, null, null, null]; // 4 slots
private assignedIds: string[] = ["health_potion", "", "", ""]; // Default slot 1 to HP pot
constructor(scene: Phaser.Scene) {
this.scene = scene;
}
create() {
const { width, height } = this.scene.scale;
// Position bottom center-ish
this.container = this.scene.add.container(width / 2 - 100, height - 50);
this.container.setScrollFactor(0).setDepth(1500);
for (let i = 0; i < 4; i++) {
const x = i * 50;
const g = this.scene.add.graphics();
// Slot bg
g.fillStyle(0x1a1a1a, 0.8);
g.fillRect(0, 0, 40, 40);
g.lineStyle(1, 0x555555);
g.strokeRect(0, 0, 40, 40);
// Hotkey label
const key = this.scene.add.text(2, 2, `${i + 1}`, {
fontSize: "10px",
color: "#aaaaaa"
});
const slotContainer = this.scene.add.container(x, 0, [g, key]);
this.slots.push(slotContainer);
this.container.add(slotContainer);
// Input
const hitArea = new Phaser.Geom.Rectangle(0, 0, 40, 40);
slotContainer.setInteractive(hitArea, Phaser.Geom.Rectangle.Contains);
slotContainer.on("pointerdown", () => {
this.activateSlot(i);
});
}
// Keyboard inputs
this.scene.input.keyboard?.on("keydown-ONE", () => this.activateSlot(0));
this.scene.input.keyboard?.on("keydown-TWO", () => this.activateSlot(1));
this.scene.input.keyboard?.on("keydown-THREE", () => this.activateSlot(2));
this.scene.input.keyboard?.on("keydown-FOUR", () => this.activateSlot(3));
}
update(player: CombatantActor) {
if (!player.inventory) return;
// Update slots based on inventory availability
for (let i = 0; i < 4; i++) {
const desiredId = this.assignedIds[i];
const slot = this.slots[i];
// Clear previous item icon if any (children > 2, since 0=bg, 1=text)
// Clear previous item icon if any (children > 2, since 0=bg, 1=text)
if (slot.list.length > 2) {
slot.removeBetween(2, undefined, true);
}
if (desiredId) {
const foundItem = player.inventory.items.find(it => it.id === desiredId);
this.itemMap[i] = foundItem || null;
if (foundItem) {
// Determine color based on item ID for now since we don't have real assets loaded for everything yet
let color = 0xffffff;
let label = "?";
if (foundItem.id === "health_potion") {
color = 0xff3333;
label = "HP";
}
// Draw simple icon representation
const icon = this.scene.add.text(20, 20, label, {
fontSize: "14px",
color: "#ffffff",
fontStyle: "bold"
}).setOrigin(0.5);
// Add bg circle for color
const circle = this.scene.add.graphics();
circle.fillStyle(color, 1);
circle.fillCircle(20, 20, 10);
// Move text to front
slot.add(circle);
slot.add(icon);
// Add count if stackable (future)
const count = player.inventory.items.filter(it => it.id === desiredId).length;
const countText = this.scene.add.text(38, 38, `${count}`, {
fontSize: "10px",
color: "#ffffff"
}).setOrigin(1, 1);
slot.add(countText);
}
} else {
this.itemMap[i] = null;
}
}
}
private activateSlot(index: number) {
const item = this.itemMap[index];
if (item) {
console.log(`Activating slot ${index + 1}: ${item.name}`);
// Emit event to GameScene to handle item usage
const gameScene = this.scene.scene.get("GameScene");
gameScene.events.emit("use-item", { itemId: item.id });
} else {
console.log(`Slot ${index + 1} is empty`);
}
}
}