fix(ui): remove non-authentic deposit/withdraw buttons over stash bottom keyhole area
This commit is contained in:
parent
b6fc2512d4
commit
a06777be07
|
|
@ -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 STASH_GOLD_CAP = 2_500_000
|
||||||
export const PLAYER_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_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`)
|
* `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 {
|
withdrawGold(amount: number, playerInventory: { gold: number; maxGold?: number }): number {
|
||||||
if (amount <= 0) return 0
|
if (amount <= 0) return 0
|
||||||
const maxInvGold = playerInventory.maxGold ?? PLAYER_GOLD_CAP
|
const available = Math.max(0, Math.min(amount, this.stashGold, PLAYER_GOLD_CAP - playerInventory.gold))
|
||||||
const available = Math.max(0, Math.min(amount, this.stashGold, maxInvGold - playerInventory.gold))
|
|
||||||
if (available <= 0) return 0
|
if (available <= 0) return 0
|
||||||
this.stashGold -= available
|
this.stashGold -= available
|
||||||
playerInventory.gold += available
|
playerInventory.gold += available
|
||||||
|
|
@ -2018,39 +2015,7 @@ export class WorldPanelsHud {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
} else if (kind === 'stash') {
|
} else if (kind === 'stash') {
|
||||||
// 1. Gold deposit button
|
// Stash 6x8 Grid
|
||||||
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
|
|
||||||
if (
|
if (
|
||||||
logicalX >= STASH_GRID_ORIGIN.x &&
|
logicalX >= STASH_GRID_ORIGIN.x &&
|
||||||
logicalX < STASH_GRID_ORIGIN.x + STASH_GRID_ORIGIN.cols * STASH_GRID_ORIGIN.cellPx &&
|
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)
|
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') {
|
} else if (kind === 'cube') {
|
||||||
if (assets.cubeBgImg) ctx.drawImage(assets.cubeBgImg, ox, oy)
|
if (assets.cubeBgImg) ctx.drawImage(assets.cubeBgImg, ox, oy)
|
||||||
font.drawText(ctx, `赫拉迪克方块 (已合成 ${this.cubeTransmuteCount} 次)`, ox + 160, oy + 32, {
|
font.drawText(ctx, `赫拉迪克方块 (已合成 ${this.cubeTransmuteCount} 次)`, ox + 160, oy + 32, {
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,6 @@ import {
|
||||||
WorldPanelsHud,
|
WorldPanelsHud,
|
||||||
STASH_GOLD_CAP,
|
STASH_GOLD_CAP,
|
||||||
PLAYER_GOLD_CAP,
|
PLAYER_GOLD_CAP,
|
||||||
STASH_DEPOSIT_BTN_BOUNDS,
|
|
||||||
STASH_WITHDRAW_BTN_BOUNDS,
|
|
||||||
} from '../src/ui/world-panels.ts'
|
} from '../src/ui/world-panels.ts'
|
||||||
import { HudManager } from '../src/ui/hud-manager.ts'
|
import { HudManager } from '../src/ui/hud-manager.ts'
|
||||||
import { GameEngine } from '../src/game/engine.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)
|
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
|
inv.gold = 100_000
|
||||||
panels.stashGold = 200_000
|
panels.stashGold = 200_000
|
||||||
|
|
||||||
|
|
@ -594,19 +592,12 @@ describe('Challenger M5 Empirical Stress Test: Town Stash Entities, Interaction
|
||||||
inventory: inv as any,
|
inventory: inv as any,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Click deposit button (center of STASH_DEPOSIT_BTN_BOUNDS)
|
// Click bottom keyhole area where non-authentic deposit/withdraw buttons used to be
|
||||||
const depX = STASH_DEPOSIT_BTN_BOUNDS.x + 10
|
panels.handleLeftDockClick('stash', 80 + 84, 60 + 388, clickCallbacks)
|
||||||
const depY = STASH_DEPOSIT_BTN_BOUNDS.y + 10
|
expect(panels.stashGold).toBe(200_000)
|
||||||
const handledDep = panels.handleLeftDockClick('stash', depX, depY, clickCallbacks)
|
expect(inv.gold).toBe(100_000)
|
||||||
expect(handledDep).toBe(true)
|
|
||||||
expect(panels.stashGold).toBe(250_000) // Default batch is 50,000
|
|
||||||
expect(inv.gold).toBe(50_000)
|
|
||||||
|
|
||||||
// Click withdraw button (center of STASH_WITHDRAW_BTN_BOUNDS)
|
panels.handleLeftDockClick('stash', 80 + 168, 60 + 388, clickCallbacks)
|
||||||
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)
|
|
||||||
expect(panels.stashGold).toBe(200_000)
|
expect(panels.stashGold).toBe(200_000)
|
||||||
expect(inv.gold).toBe(100_000)
|
expect(inv.gold).toBe(100_000)
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,6 @@ import {
|
||||||
STASH_GRID_ORIGIN,
|
STASH_GRID_ORIGIN,
|
||||||
STASH_GOLD_CAP,
|
STASH_GOLD_CAP,
|
||||||
PLAYER_GOLD_CAP,
|
PLAYER_GOLD_CAP,
|
||||||
STASH_DEPOSIT_BTN_BOUNDS,
|
|
||||||
STASH_WITHDRAW_BTN_BOUNDS,
|
|
||||||
STASH_HEADER_ICON_SOCKET,
|
STASH_HEADER_ICON_SOCKET,
|
||||||
STASH_HEADER_TOP_RECESS,
|
STASH_HEADER_TOP_RECESS,
|
||||||
STASH_HEADER_BOTTOM_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)
|
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', () => {
|
it('does not render non-authentic deposit or withdraw buttons over bottom keyhole area', () => {
|
||||||
expect(STASH_DEPOSIT_BTN_BOUNDS.x).toBeGreaterThanOrEqual(STASH_PANEL_ORIGIN.x)
|
const panels = new WorldPanelsHud()
|
||||||
expect(STASH_DEPOSIT_BTN_BOUNDS.x + STASH_DEPOSIT_BTN_BOUNDS.w).toBeLessThanOrEqual(
|
const drawTextCalls: string[] = []
|
||||||
STASH_PANEL_ORIGIN.x + STASH_PANEL_ORIGIN.w,
|
const mockFont = {
|
||||||
)
|
drawText: (_ctx: CanvasRenderingContext2D, text: string) => {
|
||||||
expect(STASH_WITHDRAW_BTN_BOUNDS.x).toBeGreaterThanOrEqual(STASH_PANEL_ORIGIN.x)
|
drawTextCalls.push(text)
|
||||||
expect(STASH_WITHDRAW_BTN_BOUNDS.x + STASH_WITHDRAW_BTN_BOUNDS.w).toBeLessThanOrEqual(
|
},
|
||||||
STASH_PANEL_ORIGIN.x + STASH_PANEL_ORIGIN.w,
|
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', () => {
|
it('confirms stash background graphic asset exists in public/ui/stash-bg.png', () => {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue