From 5dc80027dc6603a8def26d21df29b8bbeaa42514 Mon Sep 17 00:00:00 2001 From: sungdark Date: Fri, 27 Mar 2026 13:02:32 +0000 Subject: [PATCH 1/2] fix: skip hover on touch to fix double-tap issue on Android Issue: Touching hexagons on Android triggers hover behavior first, requiring users to tap twice to perform an action. Fix: Detect touch input via pointer.pointerType and: - Skip hover effects for touch (onInputOver returns early for touch) - Handle touch input directly in onInputDown (calls onConfirmFn) - Skip onInputOut hover-off for touch (no hover was shown) - Skip onInputUp for touch (already handled in onInputDown) This makes touch interaction on Android feel immediate and responsive, matching the expected single-tap behavior. --- src/utility/hex.ts | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/utility/hex.ts b/src/utility/hex.ts index 1e3d3bd29..2cbabe838 100644 --- a/src/utility/hex.ts +++ b/src/utility/hex.ts @@ -180,10 +180,23 @@ export class Hex { this.overlay = grid.overlayHexesGroup.create(x, y, 'hex'); this.overlay.alpha = 0; + // Track if last interaction was from touch to avoid double-firing + let lastInteractionTouch = false; + // Binding Events - this.hitBox.events.onInputOver.add(() => { + this.hitBox.events.onInputOver.add((_, pointer) => { if (game.freezedInput || game.UI.dashopen) return; + // Skip hover effect for touch input - on Android, touch triggers + // onInputOver before onInputUp, making users tap twice to act. + // Touch input is handled directly in onInputDown instead. + if (pointer && pointer.pointerType === 'touch') { + lastInteractionTouch = true; + return; + } + + lastInteractionTouch = false; + // Show dashed overlay on current hexes of active creature if (this.reachable && game.activeCreature) { game.activeCreature.highlightCurrentHexesAsDashed(); @@ -194,9 +207,27 @@ export class Hex { this.onSelectFn(this); }, this); + // onInputDown: handle touch directly to avoid double-tap issue on Android + this.hitBox.events.onInputDown.add((_, pointer) => { + if (game.freezedInput || game.UI.dashopen) return; + + // For touch input, immediately trigger the confirm action. + // This bypasses the hover-first behavior that requires double-tapping on Android. + if (pointer && pointer.pointerType === 'touch') { + lastInteractionTouch = true; + this.onConfirmFn(this); + } + }, this); + this.hitBox.events.onInputOut.add((_, pointer) => { if (game.freezedInput || game.UI.dashopen || !pointer.withinGame) return; + // Skip hover-off for touch since we skip hover-on for touch + if (lastInteractionTouch) { + lastInteractionTouch = false; + return; + } + // Clear dashed overlay when leaving a reachable hex if (this.reachable && game.activeCreature) { game.activeCreature.clearDashedOverlayOnHexes(); @@ -212,6 +243,11 @@ export class Hex { return; } + // Skip onInputUp for touch since we already handled it in onInputDown + if (Pointer.pointerType === 'touch') { + return; + } + switch (Pointer.button) { case 0: // Left mouse button pressed From 607b90e9733c384a41e31095373e9ab255ef9dd6 Mon Sep 17 00:00:00 2001 From: sungdark Date: Fri, 27 Mar 2026 13:10:40 +0000 Subject: [PATCH 2/2] fix: make card update function less draconian when ability costs are undefined (#1996) --- src/ui/interface.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ui/interface.ts b/src/ui/interface.ts index 14453859e..7783947bf 100644 --- a/src/ui/interface.ts +++ b/src/ui/interface.ts @@ -1071,12 +1071,12 @@ export class UI { .children('#upgrade') .text('Upgrade: ' + stats.ability_info[key].upgrade); - if (stats.ability_info[key].costs !== undefined && key !== 0) { + if (typeof stats.ability_info[key].costs?.energy === 'number' && key !== 0) { $ability .children('.wrapper') .children('.info') .children('#cost') - .text(' - costs ' + stats.ability_info[key].costs.energy + ' energy pts.'); + .text(' - costs ' + stats.ability_info[key].costs!.energy + ' energy pts.'); } else { $ability .children('.wrapper') @@ -1260,12 +1260,12 @@ export class UI { $ability.children('.wrapper').children('.info').children('#upgrade').text(' '); } - if (stats.ability_info[key].costs !== undefined && key !== 0) { + if (typeof stats.ability_info[key].costs?.energy === 'number' && key !== 0) { $ability .children('.wrapper') .children('.info') .children('#cost') - .text(' - costs ' + stats.ability_info[key].costs.energy + ' energy pts.'); + .text(' - costs ' + stats.ability_info[key].costs!.energy + ' energy pts.'); } else { $ability .children('.wrapper')