127 lines
4.7 KiB
TypeScript
127 lines
4.7 KiB
TypeScript
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", "throwing_dagger", "", ""]; // Default slot 1 to HP pot, 2 to Dagger
|
|
|
|
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, activeItemId?: string | null) {
|
|
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];
|
|
const bgGraphics = slot.list[0] as Phaser.GameObjects.Graphics;
|
|
|
|
// 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;
|
|
|
|
const isActive = foundItem && foundItem.id === activeItemId;
|
|
|
|
// Redraw background based on active state
|
|
bgGraphics.clear();
|
|
bgGraphics.fillStyle(0x1a1a1a, 0.8);
|
|
bgGraphics.fillRect(0, 0, 40, 40);
|
|
|
|
if (isActive) {
|
|
bgGraphics.lineStyle(2, 0xffff00); // Gold highlight
|
|
} else {
|
|
bgGraphics.lineStyle(1, 0x555555); // Default gray
|
|
}
|
|
bgGraphics.strokeRect(0, 0, 40, 40);
|
|
|
|
if (foundItem) {
|
|
const texture = foundItem.textureKey ?? "items";
|
|
const sprite = this.scene.add.sprite(20, 20, texture, foundItem.spriteIndex);
|
|
// PD items are 16x16, slot is 40x40. Scale it up?
|
|
sprite.setScale(2);
|
|
slot.add(sprite);
|
|
|
|
// 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;
|
|
// Reset bg
|
|
bgGraphics.clear();
|
|
bgGraphics.fillStyle(0x1a1a1a, 0.8);
|
|
bgGraphics.fillRect(0, 0, 40, 40);
|
|
bgGraphics.lineStyle(1, 0x555555);
|
|
bgGraphics.strokeRect(0, 0, 40, 40);
|
|
}
|
|
}
|
|
}
|
|
|
|
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`);
|
|
}
|
|
}
|
|
}
|