Compare commits
2 Commits
9196c49976
...
ff6b6bfb73
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ff6b6bfb73 | ||
|
|
a11f86d23b |
@@ -52,7 +52,12 @@ export function generateWorld(floor: number, runState: RunState): { world: World
|
|||||||
items: [
|
items: [
|
||||||
...runState.inventory.items,
|
...runState.inventory.items,
|
||||||
// Add starting items for testing if empty
|
// Add starting items for testing if empty
|
||||||
...(runState.inventory.items.length === 0 ? [ITEMS["health_potion"], ITEMS["health_potion"], ITEMS["iron_sword"], ITEMS["throwing_dagger"], ITEMS["throwing_dagger"], ITEMS["throwing_dagger"], ITEMS["pistol"]] : [])
|
...(runState.inventory.items.length === 0 ? [
|
||||||
|
{ ...ITEMS["health_potion"], quantity: 2 },
|
||||||
|
ITEMS["iron_sword"],
|
||||||
|
{ ...ITEMS["throwing_dagger"], quantity: 3 },
|
||||||
|
ITEMS["pistol"]
|
||||||
|
] : [])
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
energy: 0
|
energy: 0
|
||||||
|
|||||||
@@ -272,8 +272,21 @@ export class GameScene extends Phaser.Scene {
|
|||||||
const item = this.itemManager.getItem(player, data.itemId);
|
const item = this.itemManager.getItem(player, data.itemId);
|
||||||
if (!item) return;
|
if (!item) return;
|
||||||
|
|
||||||
// Drop position is simply on the player's current tile
|
// Determine drop position based on pointer or player pos
|
||||||
const dropPos = { x: player.pos.x, y: player.pos.y };
|
let dropPos = { x: player.pos.x, y: player.pos.y };
|
||||||
|
if (data.pointerX !== undefined && data.pointerY !== undefined) {
|
||||||
|
const tilePos = this.getPointerTilePos({ x: data.pointerX, y: data.pointerY } as Phaser.Input.Pointer);
|
||||||
|
|
||||||
|
// Limit drop distance to 1 tile from player for balance/fairness
|
||||||
|
const dx = Math.sign(tilePos.x - player.pos.x);
|
||||||
|
const dy = Math.sign(tilePos.y - player.pos.y);
|
||||||
|
const targetX = player.pos.x + dx;
|
||||||
|
const targetY = player.pos.y + dy;
|
||||||
|
|
||||||
|
if (inBounds(this.world, targetX, targetY) && !isBlocked(this.world, targetX, targetY, this.entityManager)) {
|
||||||
|
dropPos = { x: targetX, y: targetY };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Remove from inventory and spawn in world
|
// Remove from inventory and spawn in world
|
||||||
if (this.itemManager.removeFromInventory(player, data.itemId)) {
|
if (this.itemManager.removeFromInventory(player, data.itemId)) {
|
||||||
|
|||||||
@@ -66,33 +66,47 @@ export class ItemManager {
|
|||||||
|
|
||||||
if (itemActor) {
|
if (itemActor) {
|
||||||
const item = itemActor.item;
|
const item = itemActor.item;
|
||||||
|
const result = this.addItem(player, item);
|
||||||
// Stacking Logic
|
|
||||||
if (item.stackable) {
|
|
||||||
const existingItem = player.inventory.items.find(it => it.id === item.id);
|
|
||||||
if (existingItem) {
|
|
||||||
existingItem.quantity = (existingItem.quantity || 1) + (item.quantity || 1);
|
|
||||||
console.log(`Stacked ${item.name}. New quantity: ${existingItem.quantity}`);
|
|
||||||
|
|
||||||
this.entityManager.removeActor(itemActor.id);
|
|
||||||
return existingItem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add to inventory
|
|
||||||
item.quantity = item.quantity || 1;
|
|
||||||
player.inventory.items.push(item);
|
|
||||||
|
|
||||||
// Remove from world
|
// Remove from world
|
||||||
this.entityManager.removeActor(itemActor.id);
|
this.entityManager.removeActor(itemActor.id);
|
||||||
|
|
||||||
console.log("Picked up:", item.name);
|
console.log("Picked up:", item.name);
|
||||||
return item;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an item to player inventory, handling stacking if applicable
|
||||||
|
* @returns The added or modified item
|
||||||
|
*/
|
||||||
|
addItem(player: CombatantActor, item: Item): Item {
|
||||||
|
if (!player.inventory) throw new Error("Player has no inventory");
|
||||||
|
|
||||||
|
// Deep clone item (crucial for items with mutable stats like ammo or when picking up from ground)
|
||||||
|
const itemToAdd = { ...item } as Item;
|
||||||
|
if ('stats' in itemToAdd && itemToAdd.stats) {
|
||||||
|
(itemToAdd as any).stats = { ...itemToAdd.stats };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stacking Logic
|
||||||
|
if (itemToAdd.stackable) {
|
||||||
|
const existingItem = player.inventory.items.find(it => it.id === itemToAdd.id);
|
||||||
|
if (existingItem) {
|
||||||
|
existingItem.quantity = (existingItem.quantity || 1) + (itemToAdd.quantity || 1);
|
||||||
|
console.log(`Stacked ${itemToAdd.name}. New quantity: ${existingItem.quantity}`);
|
||||||
|
return existingItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add to inventory
|
||||||
|
itemToAdd.quantity = itemToAdd.quantity || 1;
|
||||||
|
player.inventory.items.push(itemToAdd);
|
||||||
|
return itemToAdd;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle using an item from inventory
|
* Handle using an item from inventory
|
||||||
* Returns information about what happened
|
* Returns information about what happened
|
||||||
|
|||||||
@@ -9,13 +9,13 @@ import { QuickSlotComponent } from "./components/QuickSlotComponent";
|
|||||||
import { ActionButtonComponent } from "./components/ActionButtonComponent";
|
import { ActionButtonComponent } from "./components/ActionButtonComponent";
|
||||||
|
|
||||||
export default class GameUI extends Phaser.Scene {
|
export default class GameUI extends Phaser.Scene {
|
||||||
private hud: HudComponent;
|
public hud: HudComponent;
|
||||||
private menu: MenuComponent;
|
public menu: MenuComponent;
|
||||||
private inventory: InventoryOverlay;
|
public inventory: InventoryOverlay;
|
||||||
private character: CharacterOverlay;
|
public character: CharacterOverlay;
|
||||||
private death: DeathOverlay;
|
public death: DeathOverlay;
|
||||||
private quickSlots: QuickSlotComponent;
|
public quickSlots: QuickSlotComponent;
|
||||||
private actionButtons: ActionButtonComponent;
|
public actionButtons: ActionButtonComponent;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super({ key: "GameUI" });
|
super({ key: "GameUI" });
|
||||||
|
|||||||
@@ -5,6 +5,9 @@ import { type CombatantActor } from "../../core/types";
|
|||||||
export class InventoryOverlay extends OverlayComponent {
|
export class InventoryOverlay extends OverlayComponent {
|
||||||
private equipmentSlots: Map<string, Phaser.GameObjects.Container> = new Map();
|
private equipmentSlots: Map<string, Phaser.GameObjects.Container> = new Map();
|
||||||
private backpackSlots: Phaser.GameObjects.Container[] = [];
|
private backpackSlots: Phaser.GameObjects.Container[] = [];
|
||||||
|
private dragIcon: Phaser.GameObjects.Sprite | null = null;
|
||||||
|
private draggedItemIndex: number | null = null;
|
||||||
|
private draggedEquipmentKey: string | null = null;
|
||||||
|
|
||||||
protected setupContent() {
|
protected setupContent() {
|
||||||
// Base overlay is 700x500, so we need to fit within those bounds
|
// Base overlay is 700x500, so we need to fit within those bounds
|
||||||
@@ -216,13 +219,20 @@ export class InventoryOverlay extends OverlayComponent {
|
|||||||
update(player: CombatantActor) {
|
update(player: CombatantActor) {
|
||||||
if (!player.inventory) return;
|
if (!player.inventory) return;
|
||||||
|
|
||||||
// Clear existing items from slots
|
// Clear existing items from backpack slots
|
||||||
this.backpackSlots.forEach(slot => {
|
this.backpackSlots.forEach(slot => {
|
||||||
if (slot.list.length > 1) {
|
if (slot.list.length > 1) {
|
||||||
slot.removeBetween(1, undefined, true);
|
slot.removeBetween(1, undefined, true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Clear existing items from equipment slots
|
||||||
|
this.equipmentSlots.forEach(slot => {
|
||||||
|
if (slot.list.length > 1) {
|
||||||
|
slot.removeBetween(1, undefined, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Populate items
|
// Populate items
|
||||||
player.inventory.items.forEach((item, index) => {
|
player.inventory.items.forEach((item, index) => {
|
||||||
if (index >= this.backpackSlots.length) return;
|
if (index >= this.backpackSlots.length) return;
|
||||||
@@ -236,12 +246,183 @@ export class InventoryOverlay extends OverlayComponent {
|
|||||||
sprite.setScale(2.2); // Scale to fit nicely in 44px slots
|
sprite.setScale(2.2); // Scale to fit nicely in 44px slots
|
||||||
|
|
||||||
slot.add(sprite);
|
slot.add(sprite);
|
||||||
|
|
||||||
|
// Add Count Label (Bottom-Right)
|
||||||
|
let labelText = "";
|
||||||
|
if (item.stackable) {
|
||||||
|
labelText = `x${item.quantity || 1}`;
|
||||||
|
} else if (item.type === "Weapon" && item.weaponType === "ranged" && item.stats) {
|
||||||
|
labelText = `${item.stats.currentAmmo}/${item.stats.magazineSize}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (labelText) {
|
||||||
|
const slotSize = 44;
|
||||||
|
const display = this.scene.add.text(slotSize / 2 - 3, slotSize / 2 - 3, labelText, {
|
||||||
|
fontSize: "11px",
|
||||||
|
color: "#ffffff",
|
||||||
|
fontStyle: "bold",
|
||||||
|
stroke: "#000000",
|
||||||
|
strokeThickness: 2
|
||||||
|
}).setOrigin(1, 1);
|
||||||
|
slot.add(display);
|
||||||
|
}
|
||||||
|
|
||||||
// Add interactivity
|
// Add interactivity for backpack items
|
||||||
slot.setInteractive(new Phaser.Geom.Rectangle(-22, -22, 44, 44), Phaser.Geom.Rectangle.Contains);
|
slot.setInteractive(new Phaser.Geom.Rectangle(-22, -22, 44, 44), Phaser.Geom.Rectangle.Contains);
|
||||||
|
slot.setData("index", index);
|
||||||
|
slot.setData("equipmentKey", undefined); // Explicitly clear to avoid confusion
|
||||||
|
this.scene.input.setDraggable(slot);
|
||||||
|
|
||||||
slot.on("pointerdown", () => {
|
slot.on("pointerdown", () => {
|
||||||
console.log("Clicked item:", item);
|
console.log("Clicked item:", item);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Populate equipment slots
|
||||||
|
if (player.equipment) {
|
||||||
|
Object.entries(player.equipment).forEach(([key, item]) => {
|
||||||
|
if (!item) return;
|
||||||
|
const slot = this.equipmentSlots.get(key);
|
||||||
|
if (!slot) return;
|
||||||
|
|
||||||
|
const sprite = this.scene.add.sprite(0, 0, item.textureKey, item.spriteIndex);
|
||||||
|
sprite.setScale(2.2);
|
||||||
|
slot.add(sprite);
|
||||||
|
|
||||||
|
// Add interactivity
|
||||||
|
const size = (key === "bodyArmour") ? 58 : (key === "belt") ? 32 : (key === "boots") ? 46 : (key.startsWith("ring")) ? 38 : 46;
|
||||||
|
slot.setInteractive(new Phaser.Geom.Rectangle(-size/2, -size/2, size, size), Phaser.Geom.Rectangle.Contains);
|
||||||
|
slot.setData("equipmentKey", key);
|
||||||
|
this.scene.input.setDraggable(slot);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setupDragEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
private setupDragEvents() {
|
||||||
|
this.scene.input.on("dragstart", (pointer: Phaser.Input.Pointer, gameObject: any) => {
|
||||||
|
const gameScene = this.scene.scene.get("GameScene") as any;
|
||||||
|
const player = gameScene.world.actors.get(gameScene.playerId);
|
||||||
|
if (!player) return;
|
||||||
|
|
||||||
|
let item: any = null;
|
||||||
|
|
||||||
|
// Check if it's a backpack slot or equipment slot
|
||||||
|
const index = gameObject.getData("index");
|
||||||
|
const eqKey = gameObject.getData("equipmentKey");
|
||||||
|
|
||||||
|
if (index !== undefined && this.backpackSlots.includes(gameObject)) {
|
||||||
|
item = player.inventory?.items[index];
|
||||||
|
this.draggedItemIndex = index;
|
||||||
|
this.draggedEquipmentKey = null;
|
||||||
|
} else if (eqKey !== undefined && this.equipmentSlots.get(eqKey) === gameObject) {
|
||||||
|
item = player.equipment?.[eqKey];
|
||||||
|
this.draggedItemIndex = null;
|
||||||
|
this.draggedEquipmentKey = eqKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!item) return;
|
||||||
|
|
||||||
|
// Setup drag icon
|
||||||
|
if (!this.dragIcon) {
|
||||||
|
this.dragIcon = this.scene.add.sprite(0, 0, item.textureKey ?? "items", item.spriteIndex);
|
||||||
|
this.dragIcon.setDepth(2500).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 original
|
||||||
|
const sprite = gameObject.list.find((child: any) => child instanceof Phaser.GameObjects.Sprite);
|
||||||
|
if (sprite) sprite.setAlpha(0.3);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.scene.input.on("drag", (pointer: Phaser.Input.Pointer) => {
|
||||||
|
if (this.dragIcon && this.dragIcon.visible) {
|
||||||
|
this.dragIcon.setPosition(pointer.x, pointer.y);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.scene.input.on("dragend", (pointer: Phaser.Input.Pointer, gameObject: any) => {
|
||||||
|
if (this.draggedItemIndex === null && this.draggedEquipmentKey === null) return;
|
||||||
|
|
||||||
|
const isFromBackpack = this.draggedItemIndex !== null;
|
||||||
|
if (isFromBackpack && !this.backpackSlots.includes(gameObject)) return;
|
||||||
|
if (!isFromBackpack && this.equipmentSlots.get(this.draggedEquipmentKey!) !== gameObject) return;
|
||||||
|
|
||||||
|
const startIndex = this.draggedItemIndex;
|
||||||
|
const startEqKey = this.draggedEquipmentKey;
|
||||||
|
|
||||||
|
this.draggedItemIndex = null;
|
||||||
|
this.draggedEquipmentKey = null;
|
||||||
|
|
||||||
|
if (this.dragIcon) this.dragIcon.setVisible(false);
|
||||||
|
|
||||||
|
// Reset alpha
|
||||||
|
const sprite = gameObject.list.find((child: any) => child instanceof Phaser.GameObjects.Sprite);
|
||||||
|
if (sprite) sprite.setAlpha(1.0);
|
||||||
|
|
||||||
|
const gameUI = this.scene as any;
|
||||||
|
const gameScene = this.scene.scene.get("GameScene") as any;
|
||||||
|
const player = gameScene.world.actors.get(gameScene.playerId);
|
||||||
|
|
||||||
|
const item = isFromBackpack ? player.inventory.items[startIndex!] : (player.equipment as any)[startEqKey!];
|
||||||
|
|
||||||
|
// Check Quick Slots
|
||||||
|
if (gameUI.quickSlots && gameUI.quickSlots.isPointerOver(pointer.x, pointer.y)) {
|
||||||
|
const targetSlot = gameUI.quickSlots.getSlotIndexAt(pointer.x, pointer.y);
|
||||||
|
if (targetSlot !== null) {
|
||||||
|
gameUI.quickSlots.assignItem(targetSlot, item.id);
|
||||||
|
console.log(`Assigned backpack item ${item.name} to quick slot ${targetSlot}`);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check Backpack (for swapping/reordering) - ONLY if dragged from backpack
|
||||||
|
if (isFromBackpack && this.isPointerOver(pointer.x, pointer.y)) {
|
||||||
|
const targetIndex = this.getBackpackSlotAt(pointer.x, pointer.y);
|
||||||
|
if (targetIndex !== null && targetIndex !== startIndex) {
|
||||||
|
const items = player.inventory.items;
|
||||||
|
const itemToMove = items[startIndex!];
|
||||||
|
|
||||||
|
// Remove from old position
|
||||||
|
items.splice(startIndex!, 1);
|
||||||
|
|
||||||
|
// Insert at new position (clamped to end of list)
|
||||||
|
const finalTargetIndex = Math.min(targetIndex, items.length);
|
||||||
|
items.splice(finalTargetIndex, 0, itemToMove);
|
||||||
|
|
||||||
|
gameScene.events.emit("request-ui-update");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Drop on ground
|
||||||
|
gameScene.events.emit("drop-item", {
|
||||||
|
itemId: item.id,
|
||||||
|
pointerX: pointer.x,
|
||||||
|
pointerY: pointer.y
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private getBackpackSlotAt(x: number, y: number): number | null {
|
||||||
|
// Relative to container
|
||||||
|
const localX = x - this.container.x;
|
||||||
|
const localY = y - this.container.y;
|
||||||
|
|
||||||
|
for (let i = 0; i < this.backpackSlots.length; i++) {
|
||||||
|
const slot = this.backpackSlots[i];
|
||||||
|
const halfSize = 22; // slotSize 44 / 2
|
||||||
|
const dx = localX - slot.x;
|
||||||
|
const dy = localY - slot.y;
|
||||||
|
|
||||||
|
if (dx >= -halfSize && dx <= halfSize && dy >= -halfSize && dy <= halfSize) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,4 +37,22 @@ export abstract class OverlayComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected onOpen() {}
|
protected onOpen() {}
|
||||||
|
|
||||||
|
public isPointerOver(x: number, y: number): boolean {
|
||||||
|
if (!this.isOpen || !this.container.visible) return false;
|
||||||
|
|
||||||
|
// Get world bounds of the first child (the background rectangle)
|
||||||
|
const bg = this.container.list[0] as Phaser.GameObjects.Rectangle;
|
||||||
|
if (!bg) return false;
|
||||||
|
|
||||||
|
// Local coordinates in container are centered at 0,0
|
||||||
|
const halfW = bg.width / 2;
|
||||||
|
const halfH = bg.height / 2;
|
||||||
|
|
||||||
|
// Container position is fixed on screen (scrollFactor 0)
|
||||||
|
const localX = x - this.container.x;
|
||||||
|
const localY = y - this.container.y;
|
||||||
|
|
||||||
|
return localX >= -halfW && localX <= halfW && localY >= -halfH && localY <= halfH;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,7 +71,10 @@ export class QuickSlotComponent {
|
|||||||
|
|
||||||
// Drag and Drop Events
|
// Drag and Drop Events
|
||||||
this.scene.input.on("dragstart", (pointer: Phaser.Input.Pointer, gameObject: Phaser.GameObjects.Container) => {
|
this.scene.input.on("dragstart", (pointer: Phaser.Input.Pointer, gameObject: Phaser.GameObjects.Container) => {
|
||||||
const index = gameObject.getData("index") as number;
|
// Only handle if it's one of our slots
|
||||||
|
const index = gameObject.getData("index");
|
||||||
|
if (index === undefined || !this.slots.includes(gameObject)) return;
|
||||||
|
|
||||||
const item = this.itemMap[index];
|
const item = this.itemMap[index];
|
||||||
if (!item) return;
|
if (!item) return;
|
||||||
|
|
||||||
@@ -99,7 +102,7 @@ export class QuickSlotComponent {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.scene.input.on("dragend", (pointer: Phaser.Input.Pointer, gameObject: Phaser.GameObjects.Container) => {
|
this.scene.input.on("dragend", (pointer: Phaser.Input.Pointer, gameObject: Phaser.GameObjects.Container) => {
|
||||||
if (this.draggedSlotIndex === null) return;
|
if (this.draggedSlotIndex === null || !this.slots.includes(gameObject)) return;
|
||||||
|
|
||||||
const startIndex = this.draggedSlotIndex;
|
const startIndex = this.draggedSlotIndex;
|
||||||
this.draggedSlotIndex = null;
|
this.draggedSlotIndex = null;
|
||||||
@@ -138,18 +141,26 @@ export class QuickSlotComponent {
|
|||||||
this.assignedIds[targetIndex] = temp;
|
this.assignedIds[targetIndex] = temp;
|
||||||
console.log(`Moved/Swapped slot ${startIndex} to ${targetIndex}`);
|
console.log(`Moved/Swapped slot ${startIndex} to ${targetIndex}`);
|
||||||
} else if (targetIndex === null) {
|
} else if (targetIndex === null) {
|
||||||
// Dropped outside - drop on ground
|
// Check if dropped over inventory backpack
|
||||||
const item = this.itemMap[startIndex];
|
const gameUI = this.scene as any;
|
||||||
if (item) {
|
if (gameUI.inventory && gameUI.inventory.isPointerOver(pointer.x, pointer.y)) {
|
||||||
const gameScene = this.scene.scene.get("GameScene") as any;
|
// Clear the quick slot (returning to backpack)
|
||||||
gameScene.events.emit("drop-item", {
|
|
||||||
itemId: item.id,
|
|
||||||
pointerX: pointer.x,
|
|
||||||
pointerY: pointer.y
|
|
||||||
});
|
|
||||||
|
|
||||||
// Clear the slot
|
|
||||||
this.assignedIds[startIndex] = "";
|
this.assignedIds[startIndex] = "";
|
||||||
|
console.log(`Cleared quick slot ${startIndex} (returned to backpack)`);
|
||||||
|
} else {
|
||||||
|
// 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] = "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,4 +273,50 @@ export class QuickSlotComponent {
|
|||||||
console.log(`Slot ${index + 1} is empty`);
|
console.log(`Slot ${index + 1} is empty`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public isPointerOver(x: number, y: number): boolean {
|
||||||
|
const slotSize = 48;
|
||||||
|
const slotSpacing = 4;
|
||||||
|
const totalWidth = (slotSize + slotSpacing) * 10 - slotSpacing;
|
||||||
|
|
||||||
|
const localX = x - this.container.x;
|
||||||
|
const localY = y - this.container.y;
|
||||||
|
|
||||||
|
return localX >= 0 && localX <= totalWidth && localY >= 0 && localY <= slotSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getSlotIndexAt(x: number, y: number): number | null {
|
||||||
|
const slotSize = 48;
|
||||||
|
const slotSpacing = 4;
|
||||||
|
|
||||||
|
const localX = x - this.container.x;
|
||||||
|
const localY = y - this.container.y;
|
||||||
|
|
||||||
|
if (localY >= 0 && localY <= slotSize) {
|
||||||
|
const index = Math.floor(localX / (slotSize + slotSpacing));
|
||||||
|
const remainder = localX % (slotSize + slotSpacing);
|
||||||
|
|
||||||
|
if (index >= 0 && index < 10 && remainder <= slotSize) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public assignItem(index: number, itemId: string) {
|
||||||
|
if (index >= 0 && index < 10) {
|
||||||
|
// Prevent duplicate assignments
|
||||||
|
const existingIndex = this.assignedIds.indexOf(itemId);
|
||||||
|
if (existingIndex !== -1 && existingIndex !== index) {
|
||||||
|
this.assignedIds[existingIndex] = "";
|
||||||
|
console.log(`Cleared duplicate assignment of ${itemId} from slot ${existingIndex}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.assignedIds[index] = itemId;
|
||||||
|
|
||||||
|
// Refresh UI
|
||||||
|
const gameScene = this.scene.scene.get("GameScene");
|
||||||
|
gameScene.events.emit("request-ui-update");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user