From a06777be076d8258b3537591afa40efcebe16351 Mon Sep 17 00:00:00 2001 From: troytt <47798984@qq.com> Date: Mon, 28 Sep 2026 01:27:10 +0000 Subject: [PATCH] fix(ui): remove non-authentic deposit/withdraw buttons over stash bottom keyhole area --- src/ui/world-panels.ts | 93 +------------------ .../challenger-m5-stash-entities-gold.test.ts | 21 ++--- tests/stash.test.ts | 43 +++++++-- 3 files changed, 41 insertions(+), 116 deletions(-) diff --git a/src/ui/world-panels.ts b/src/ui/world-panels.ts index 75afe5e..113f359 100644 --- a/src/ui/world-panels.ts +++ b/src/ui/world-panels.ts @@ -60,8 +60,6 @@ export const STASH_GRID_ORIGIN = { x: 80 + 74, y: 60 + 82, cols: 6, rows: 8, cel export const STASH_GOLD_CAP = 2_500_000 export const PLAYER_GOLD_CAP = 2_500_000 export const STASH_CLOSE_BTN_BOUNDS = { x: 80 + 272, y: 60 + 388, w: 32, h: 32 } as const -export const STASH_DEPOSIT_BTN_BOUNDS = { x: 80 + 68, y: 60 + 386, w: 76, h: 26 } as const -export const STASH_WITHDRAW_BTN_BOUNDS = { x: 80 + 154, y: 60 + 386, w: 76, h: 26 } as const /** * `Panel\TradeStash.dc6` (`public/ui/stash-bg.png`, 320x432 anchored at `ox = 80, oy = 60`) @@ -1675,8 +1673,7 @@ export class WorldPanelsHud { withdrawGold(amount: number, playerInventory: { gold: number; maxGold?: number }): number { if (amount <= 0) return 0 - const maxInvGold = playerInventory.maxGold ?? PLAYER_GOLD_CAP - const available = Math.max(0, Math.min(amount, this.stashGold, maxInvGold - playerInventory.gold)) + const available = Math.max(0, Math.min(amount, this.stashGold, PLAYER_GOLD_CAP - playerInventory.gold)) if (available <= 0) return 0 this.stashGold -= available playerInventory.gold += available @@ -2018,39 +2015,7 @@ export class WorldPanelsHud { return true } } else if (kind === 'stash') { - // 1. Gold deposit button - if ( - logicalX >= STASH_DEPOSIT_BTN_BOUNDS.x && - logicalX <= STASH_DEPOSIT_BTN_BOUNDS.x + STASH_DEPOSIT_BTN_BOUNDS.w && - logicalY >= STASH_DEPOSIT_BTN_BOUNDS.y && - logicalY <= STASH_DEPOSIT_BTN_BOUNDS.y + STASH_DEPOSIT_BTN_BOUNDS.h - ) { - if (!callbacks.isRightClick && callbacks.inventory) { - const depositAmt = Math.min(50_000, callbacks.inventory.gold, STASH_GOLD_CAP - this.stashGold) - if (depositAmt > 0) { - this.depositGold(depositAmt, callbacks.inventory) - } - } - return true - } - - // 2. Gold withdraw button - if ( - logicalX >= STASH_WITHDRAW_BTN_BOUNDS.x && - logicalX <= STASH_WITHDRAW_BTN_BOUNDS.x + STASH_WITHDRAW_BTN_BOUNDS.w && - logicalY >= STASH_WITHDRAW_BTN_BOUNDS.y && - logicalY <= STASH_WITHDRAW_BTN_BOUNDS.y + STASH_WITHDRAW_BTN_BOUNDS.h - ) { - if (!callbacks.isRightClick && callbacks.inventory) { - const withdrawAmt = Math.min(50_000, this.stashGold, PLAYER_GOLD_CAP - callbacks.inventory.gold) - if (withdrawAmt > 0) { - this.withdrawGold(withdrawAmt, callbacks.inventory) - } - } - return true - } - - // 3. Stash 6x8 Grid + // Stash 6x8 Grid if ( logicalX >= STASH_GRID_ORIGIN.x && logicalX < STASH_GRID_ORIGIN.x + STASH_GRID_ORIGIN.cols * STASH_GRID_ORIGIN.cellPx && @@ -2383,60 +2348,6 @@ export class WorldPanelsHud { ctx.fillRect(gx + 2, gy + 2, gw - 4, gh - 4) } } - - // Deposit button - ctx.fillStyle = 'rgba(20, 16, 12, 0.9)' - ctx.fillRect( - STASH_DEPOSIT_BTN_BOUNDS.x, - STASH_DEPOSIT_BTN_BOUNDS.y, - STASH_DEPOSIT_BTN_BOUNDS.w, - STASH_DEPOSIT_BTN_BOUNDS.h, - ) - ctx.strokeStyle = '#8a7248' - ctx.strokeRect( - STASH_DEPOSIT_BTN_BOUNDS.x + 0.5, - STASH_DEPOSIT_BTN_BOUNDS.y + 0.5, - STASH_DEPOSIT_BTN_BOUNDS.w - 1, - STASH_DEPOSIT_BTN_BOUNDS.h - 1, - ) - font.drawText( - ctx, - '存入', - STASH_DEPOSIT_BTN_BOUNDS.x + STASH_DEPOSIT_BTN_BOUNDS.w / 2, - STASH_DEPOSIT_BTN_BOUNDS.y + 16, - { - font: 'font8', - color: 'gold', - align: 'center', - }, - ) - - // Withdraw button - ctx.fillStyle = 'rgba(20, 16, 12, 0.9)' - ctx.fillRect( - STASH_WITHDRAW_BTN_BOUNDS.x, - STASH_WITHDRAW_BTN_BOUNDS.y, - STASH_WITHDRAW_BTN_BOUNDS.w, - STASH_WITHDRAW_BTN_BOUNDS.h, - ) - ctx.strokeStyle = '#8a7248' - ctx.strokeRect( - STASH_WITHDRAW_BTN_BOUNDS.x + 0.5, - STASH_WITHDRAW_BTN_BOUNDS.y + 0.5, - STASH_WITHDRAW_BTN_BOUNDS.w - 1, - STASH_WITHDRAW_BTN_BOUNDS.h - 1, - ) - font.drawText( - ctx, - '取出', - STASH_WITHDRAW_BTN_BOUNDS.x + STASH_WITHDRAW_BTN_BOUNDS.w / 2, - STASH_WITHDRAW_BTN_BOUNDS.y + 16, - { - font: 'font8', - color: 'gold', - align: 'center', - }, - ) } else if (kind === 'cube') { if (assets.cubeBgImg) ctx.drawImage(assets.cubeBgImg, ox, oy) font.drawText(ctx, `赫拉迪克方块 (已合成 ${this.cubeTransmuteCount} 次)`, ox + 160, oy + 32, { diff --git a/tests/challenger-m5-stash-entities-gold.test.ts b/tests/challenger-m5-stash-entities-gold.test.ts index e6154e0..40c11d6 100644 --- a/tests/challenger-m5-stash-entities-gold.test.ts +++ b/tests/challenger-m5-stash-entities-gold.test.ts @@ -9,8 +9,6 @@ import { WorldPanelsHud, STASH_GOLD_CAP, PLAYER_GOLD_CAP, - STASH_DEPOSIT_BTN_BOUNDS, - STASH_WITHDRAW_BTN_BOUNDS, } from '../src/ui/world-panels.ts' import { HudManager } from '../src/ui/hud-manager.ts' import { GameEngine } from '../src/game/engine.ts' @@ -584,7 +582,7 @@ describe('Challenger M5 Empirical Stress Test: Town Stash Entities, Interaction expect(panels.stashGold).toBe(50_000) }) - it('handles simulated UI button clicks for deposit and withdraw', () => { + it('does not intercept bottom keyhole ornament clicks as non-authentic deposit/withdraw buttons', () => { inv.gold = 100_000 panels.stashGold = 200_000 @@ -594,19 +592,12 @@ describe('Challenger M5 Empirical Stress Test: Town Stash Entities, Interaction inventory: inv as any, } - // Click deposit button (center of STASH_DEPOSIT_BTN_BOUNDS) - const depX = STASH_DEPOSIT_BTN_BOUNDS.x + 10 - const depY = STASH_DEPOSIT_BTN_BOUNDS.y + 10 - const handledDep = panels.handleLeftDockClick('stash', depX, depY, clickCallbacks) - expect(handledDep).toBe(true) - expect(panels.stashGold).toBe(250_000) // Default batch is 50,000 - expect(inv.gold).toBe(50_000) + // Click bottom keyhole area where non-authentic deposit/withdraw buttons used to be + panels.handleLeftDockClick('stash', 80 + 84, 60 + 388, clickCallbacks) + expect(panels.stashGold).toBe(200_000) + expect(inv.gold).toBe(100_000) - // Click withdraw button (center of STASH_WITHDRAW_BTN_BOUNDS) - const wX = STASH_WITHDRAW_BTN_BOUNDS.x + 10 - const wY = STASH_WITHDRAW_BTN_BOUNDS.y + 10 - const handledW = panels.handleLeftDockClick('stash', wX, wY, clickCallbacks) - expect(handledW).toBe(true) + panels.handleLeftDockClick('stash', 80 + 168, 60 + 388, clickCallbacks) expect(panels.stashGold).toBe(200_000) expect(inv.gold).toBe(100_000) }) diff --git a/tests/stash.test.ts b/tests/stash.test.ts index 56bd7af..fb7e230 100644 --- a/tests/stash.test.ts +++ b/tests/stash.test.ts @@ -13,8 +13,6 @@ import { STASH_GRID_ORIGIN, STASH_GOLD_CAP, PLAYER_GOLD_CAP, - STASH_DEPOSIT_BTN_BOUNDS, - STASH_WITHDRAW_BTN_BOUNDS, STASH_HEADER_ICON_SOCKET, STASH_HEADER_TOP_RECESS, STASH_HEADER_BOTTOM_RECESS, @@ -155,15 +153,40 @@ describe('Milestone M5 (Issue #150): Camp Town Stash Entities Across 5 Acts & 6x expect(STASH_GRID_ORIGIN.y + STASH_GRID_ORIGIN.rows * STASH_GRID_ORIGIN.cellPx).toBe(374) }) - it('defines deposit and withdraw button bounds inside stash panel', () => { - expect(STASH_DEPOSIT_BTN_BOUNDS.x).toBeGreaterThanOrEqual(STASH_PANEL_ORIGIN.x) - expect(STASH_DEPOSIT_BTN_BOUNDS.x + STASH_DEPOSIT_BTN_BOUNDS.w).toBeLessThanOrEqual( - STASH_PANEL_ORIGIN.x + STASH_PANEL_ORIGIN.w, - ) - expect(STASH_WITHDRAW_BTN_BOUNDS.x).toBeGreaterThanOrEqual(STASH_PANEL_ORIGIN.x) - expect(STASH_WITHDRAW_BTN_BOUNDS.x + STASH_WITHDRAW_BTN_BOUNDS.w).toBeLessThanOrEqual( - STASH_PANEL_ORIGIN.x + STASH_PANEL_ORIGIN.w, + it('does not render non-authentic deposit or withdraw buttons over bottom keyhole area', () => { + const panels = new WorldPanelsHud() + const drawTextCalls: string[] = [] + const mockFont = { + drawText: (_ctx: CanvasRenderingContext2D, text: string) => { + drawTextCalls.push(text) + }, + measureText: (text: string) => text.length * 6.5, + } as unknown as D2FontRenderer + const mockCtx = { + drawImage: () => {}, + fillRect: () => {}, + strokeRect: () => {}, + fillStyle: '', + strokeStyle: '', + } as unknown as CanvasRenderingContext2D + + panels.drawLeftDockPanel( + mockCtx, + 'stash', + { + questBgImg: null, + waypointBgImg: null, + borderLeftImg: null, + stashBgImg: null, + cubeBgImg: null, + vendorBgImg: null, + buySellBtnImg: null, + }, + mockFont, ) + + expect(drawTextCalls).not.toContain('存入') + expect(drawTextCalls).not.toContain('取出') }) it('confirms stash background graphic asset exists in public/ui/stash-bg.png', () => {