Highlight active item slot and activate when shortcut key is pressed

This commit is contained in:
Peter Stockings
2026-01-06 22:33:51 +11:00
parent 309ab19e8c
commit 505f62ac97
6 changed files with 275 additions and 23 deletions

View File

@@ -8,14 +8,15 @@ import {
type World,
type CombatantActor,
type Item,
type ItemDropActor
type ItemDropActor,
type UIUpdatePayload
} from "../core/types";
import { TILE_SIZE } from "../core/constants";
import { inBounds, isBlocked, isPlayerOnExit, tryDestructTile } from "../engine/world/world-logic";
import { findPathAStar } from "../engine/world/pathfinding";
import { applyAction, stepUntilPlayerTurn } from "../engine/simulation/simulation";
import { generateWorld } from "../engine/world/generator";
import { traceProjectile } from "../engine/gameplay/CombatLogic";
import { traceProjectile, getClosestVisibleEnemy } from "../engine/gameplay/CombatLogic";
@@ -53,6 +54,7 @@ export class GameScene extends Phaser.Scene {
// Targeting Mode
private isTargeting = false;
private targetingItem: string | null = null;
private targetCursor: { x: number, y: number } | null = null;
private targetingGraphics!: Phaser.GameObjects.Graphics;
private turnCount = 0; // Track turns for mana regen
@@ -188,9 +190,38 @@ export class GameScene extends Phaser.Scene {
this.emitUIUpdate();
}
} else if (item.throwable) {
// Check if already targeting this item -> verify intent to throw
if (this.isTargeting && this.targetingItem === item.id) {
if (this.targetCursor) {
this.executeThrow(this.targetCursor.x, this.targetCursor.y);
}
return;
}
this.targetingItem = item.id;
this.isTargeting = true;
// Auto-target closest visible enemy
const closest = getClosestVisibleEnemy(
this.world,
player.pos,
this.dungeonRenderer.seenArray,
this.world.width
);
if (closest) {
this.targetCursor = closest;
} else {
// Default to player pos or null?
// If we default to mouse pos, we need current mouse pos.
// Let's default to null and wait for mouse move, OR default to player pos forward?
// Let's just default to null until mouse moves.
this.targetCursor = null;
}
this.drawTargetingLine();
console.log("Targeting Mode: ON");
this.emitUIUpdate();
}
});
@@ -230,7 +261,11 @@ export class GameScene extends Phaser.Scene {
this.input.on("pointermove", (p: Phaser.Input.Pointer) => {
if (!p.isDown) { // Even if not down, we might need to update targeting line
if (this.isTargeting) {
this.updateTargetingLine(p);
const tx = Math.floor(p.worldX / TILE_SIZE);
const ty = Math.floor(p.worldY / TILE_SIZE);
// Only update if changed to avoid jitter if needed, but simple assignment is fine
this.targetCursor = { x: tx, y: ty };
this.drawTargetingLine();
}
return;
}
@@ -255,7 +290,10 @@ export class GameScene extends Phaser.Scene {
}
if (this.isTargeting) {
this.updateTargetingLine(p);
const tx = Math.floor(p.worldX / TILE_SIZE);
const ty = Math.floor(p.worldY / TILE_SIZE);
this.targetCursor = { x: tx, y: ty };
this.drawTargetingLine();
}
});
@@ -265,9 +303,9 @@ export class GameScene extends Phaser.Scene {
if (this.isTargeting) {
// Only Left Click throws
if (p.button === 0) {
const tx = Math.floor(p.worldX / TILE_SIZE);
const ty = Math.floor(p.worldY / TILE_SIZE);
this.executeThrow(tx, ty);
if (this.targetCursor) {
this.executeThrow(this.targetCursor.x, this.targetCursor.y);
}
}
return;
}
@@ -397,11 +435,15 @@ export class GameScene extends Phaser.Scene {
}
private emitUIUpdate() {
this.events.emit("update-ui", {
const payload: UIUpdatePayload = {
world: this.world,
playerId: this.playerId,
floorIndex: this.floorIndex
});
floorIndex: this.floorIndex,
uiState: {
targetingItemId: this.targetingItem
}
};
this.events.emit("update-ui", payload);
}
private commitPlayerAction(action: Action) {
@@ -547,8 +589,12 @@ export class GameScene extends Phaser.Scene {
);
}
private updateTargetingLine(p: Phaser.Input.Pointer) {
if (!this.world) return;
private drawTargetingLine() {
if (!this.world || !this.targetCursor) {
this.targetingGraphics.clear();
return;
}
this.targetingGraphics.clear();
const player = this.world.actors.get(this.playerId) as CombatantActor;
@@ -557,22 +603,22 @@ export class GameScene extends Phaser.Scene {
const startX = player.pos.x * TILE_SIZE + TILE_SIZE / 2;
const startY = player.pos.y * TILE_SIZE + TILE_SIZE / 2;
const endX = p.worldX;
const endY = p.worldY;
const endX = this.targetCursor.x * TILE_SIZE + TILE_SIZE / 2;
const endY = this.targetCursor.y * TILE_SIZE + TILE_SIZE / 2;
this.targetingGraphics.lineStyle(2, 0xff0000, 0.7);
this.targetingGraphics.lineBetween(startX, startY, endX, endY);
const tx = Math.floor(endX / TILE_SIZE);
const ty = Math.floor(endY / TILE_SIZE);
this.targetingGraphics.strokeRect(tx * TILE_SIZE, ty * TILE_SIZE, TILE_SIZE, TILE_SIZE);
this.targetingGraphics.strokeRect(this.targetCursor.x * TILE_SIZE, this.targetCursor.y * TILE_SIZE, TILE_SIZE, TILE_SIZE);
}
private cancelTargeting() {
this.isTargeting = false;
this.targetingItem = null;
this.targetCursor = null;
this.targetingGraphics.clear();
console.log("Targeting cancelled");
this.emitUIUpdate();
}
private executeThrow(targetX: number, targetY: number) {