Feat: Add swap, move, & drop items in quick slots
This commit is contained in:
@@ -263,6 +263,29 @@ export class GameScene extends Phaser.Scene {
|
||||
}
|
||||
});
|
||||
|
||||
this.events.on("drop-item", (data: { itemId: string, pointerX: number, pointerY: number }) => {
|
||||
if (!this.awaitingPlayer) return;
|
||||
|
||||
const player = this.world.actors.get(this.playerId) as CombatantActor;
|
||||
if (!player || !player.inventory) return;
|
||||
|
||||
const item = this.itemManager.getItem(player, data.itemId);
|
||||
if (!item) return;
|
||||
|
||||
// Drop position is simply on the player's current tile
|
||||
const dropPos = { x: player.pos.x, y: player.pos.y };
|
||||
|
||||
// Remove from inventory and spawn in world
|
||||
if (this.itemManager.removeFromInventory(player, data.itemId)) {
|
||||
this.itemManager.spawnItem(item, dropPos);
|
||||
|
||||
const quantityText = (item.quantity && item.quantity > 1) ? ` x${item.quantity}` : "";
|
||||
this.dungeonRenderer.showFloatingText(player.pos.x, player.pos.y, `Dropped ${item.name}${quantityText}`, "#aaaaaa");
|
||||
|
||||
this.emitUIUpdate();
|
||||
}
|
||||
});
|
||||
|
||||
// Right Clicks to cancel targeting
|
||||
this.input.on('pointerdown', (p: Phaser.Input.Pointer) => {
|
||||
if (p.rightButtonDown() && this.targetingSystem.isActive) {
|
||||
|
||||
@@ -7,6 +7,8 @@ export class QuickSlotComponent {
|
||||
private slots: Phaser.GameObjects.Container[] = [];
|
||||
private itemMap: (Item | null)[] = new Array(10).fill(null);
|
||||
private assignedIds: string[] = ["health_potion", "pistol", "throwing_dagger", ...new Array(7).fill("")];
|
||||
private draggedSlotIndex: number | null = null;
|
||||
private dragIcon: Phaser.GameObjects.Sprite | null = null;
|
||||
|
||||
constructor(scene: Phaser.Scene) {
|
||||
this.scene = scene;
|
||||
@@ -47,17 +49,115 @@ export class QuickSlotComponent {
|
||||
}).setOrigin(0, 1);
|
||||
|
||||
const slotContainer = this.scene.add.container(x, 0, [g, key]);
|
||||
slotContainer.setData("index", i);
|
||||
this.slots.push(slotContainer);
|
||||
this.container.add(slotContainer);
|
||||
|
||||
// Input
|
||||
const hitArea = new Phaser.Geom.Rectangle(0, 0, slotSize, slotSize);
|
||||
slotContainer.setInteractive(hitArea, Phaser.Geom.Rectangle.Contains);
|
||||
this.scene.input.setDraggable(slotContainer);
|
||||
|
||||
slotContainer.on("pointerdown", () => {
|
||||
this.activateSlot(i);
|
||||
});
|
||||
|
||||
slotContainer.on("pointerup", (pointer: Phaser.Input.Pointer) => {
|
||||
// If we didn't drag, then activate
|
||||
if (this.draggedSlotIndex === null && pointer.getDistance() < 10) {
|
||||
this.activateSlot(i);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Drag and Drop Events
|
||||
this.scene.input.on("dragstart", (pointer: Phaser.Input.Pointer, gameObject: Phaser.GameObjects.Container) => {
|
||||
const index = gameObject.getData("index") as number;
|
||||
const item = this.itemMap[index];
|
||||
if (!item) return;
|
||||
|
||||
this.draggedSlotIndex = index;
|
||||
|
||||
// Setup drag icon
|
||||
if (!this.dragIcon) {
|
||||
this.dragIcon = this.scene.add.sprite(0, 0, item.textureKey ?? "items", item.spriteIndex);
|
||||
this.dragIcon.setDepth(2000).setScale(2.5).setAlpha(0.7);
|
||||
} else {
|
||||
this.dragIcon.setTexture(item.textureKey ?? "items", item.spriteIndex);
|
||||
this.dragIcon.setVisible(true);
|
||||
}
|
||||
this.dragIcon.setPosition(pointer.x, pointer.y);
|
||||
|
||||
// Ghost the original slot's item
|
||||
const sprite = gameObject.list.find(child => child instanceof Phaser.GameObjects.Sprite) as Phaser.GameObjects.Sprite;
|
||||
if (sprite) sprite.setAlpha(0.3);
|
||||
});
|
||||
|
||||
this.scene.input.on("drag", (pointer: Phaser.Input.Pointer) => {
|
||||
if (this.dragIcon) {
|
||||
this.dragIcon.setPosition(pointer.x, pointer.y);
|
||||
}
|
||||
});
|
||||
|
||||
this.scene.input.on("dragend", (pointer: Phaser.Input.Pointer, gameObject: Phaser.GameObjects.Container) => {
|
||||
if (this.draggedSlotIndex === null) return;
|
||||
|
||||
const startIndex = this.draggedSlotIndex;
|
||||
this.draggedSlotIndex = null;
|
||||
if (this.dragIcon) this.dragIcon.setVisible(false);
|
||||
|
||||
// Reset alpha of original sprite
|
||||
const sprite = gameObject.list.find(child => child instanceof Phaser.GameObjects.Sprite) as Phaser.GameObjects.Sprite;
|
||||
if (sprite) sprite.setAlpha(1.0);
|
||||
|
||||
// Determine if we dropped on another slot
|
||||
let targetIndex: number | null = null;
|
||||
const slotSize = 48;
|
||||
const slotSpacing = 4;
|
||||
|
||||
// Calculate pointer position relative to the quick-slot container
|
||||
// Since container has scrollFactor(0), its screen position is fixed
|
||||
const localX = pointer.x - this.container.x;
|
||||
const localY = pointer.y - this.container.y;
|
||||
|
||||
// Check if pointer is within the vertical bounds of the slots
|
||||
if (localY >= 0 && localY <= slotSize) {
|
||||
// Calculate which slot index the pointer is over
|
||||
const index = Math.floor(localX / (slotSize + slotSpacing));
|
||||
const remainder = localX % (slotSize + slotSpacing);
|
||||
|
||||
// Ensure index is valid and pointer is within the slot's actual area (not spacing)
|
||||
if (index >= 0 && index < 10 && remainder <= slotSize) {
|
||||
targetIndex = index;
|
||||
}
|
||||
}
|
||||
|
||||
if (targetIndex !== null && targetIndex !== startIndex) {
|
||||
// Swap or Move
|
||||
const temp = this.assignedIds[startIndex];
|
||||
this.assignedIds[startIndex] = this.assignedIds[targetIndex];
|
||||
this.assignedIds[targetIndex] = temp;
|
||||
console.log(`Moved/Swapped slot ${startIndex} to ${targetIndex}`);
|
||||
} else if (targetIndex === null) {
|
||||
// Dropped outside - drop on ground
|
||||
const item = this.itemMap[startIndex];
|
||||
if (item) {
|
||||
const gameScene = this.scene.scene.get("GameScene") as any;
|
||||
gameScene.events.emit("drop-item", {
|
||||
itemId: item.id,
|
||||
pointerX: pointer.x,
|
||||
pointerY: pointer.y
|
||||
});
|
||||
|
||||
// Clear the slot
|
||||
this.assignedIds[startIndex] = "";
|
||||
}
|
||||
}
|
||||
|
||||
// Trigger UI refresh to reflect changes on the correct event bus
|
||||
const gameScene = this.scene.scene.get("GameScene");
|
||||
gameScene.events.emit("request-ui-update");
|
||||
});
|
||||
|
||||
// Keyboard inputs
|
||||
this.scene.input.keyboard?.on("keydown-ONE", () => this.activateSlot(0));
|
||||
this.scene.input.keyboard?.on("keydown-TWO", () => this.activateSlot(1));
|
||||
|
||||
Reference in New Issue
Block a user