Q / X hotkeys retreat and sell the selected operator in prep (#114)
Q retreats and X sells the selected operator during prep, through the same buttons (never an item, never while typing in a field); the buttons show [Q] / [X]. Contributed by @SpiritedAwayCN.
This commit is contained in:
1 parent
a0a5419eb8
commit
3f05c65dec
9 files changed
+82
-12
No files matched your search
@@ -1528,11 +1528,11 @@ export function rangeGridBox(grid, mirror = false) {
|
||||
// ---- keyboard ---------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Map a keydown to a game shortcut (R refresh, F freeze, D level-up, Space ready, Esc close).
|
||||
* Map a keydown to a game shortcut (R refresh, F freeze, D level-up, Q retreat, X sell, Space ready, Esc close).
|
||||
* Space means ready even while a HUD button has focus (a mouse click leaves the shop card / 刷新 focused, and
|
||||
* Space must not re-trigger it); the caller prevents the button's own activation. Enter still activates buttons.
|
||||
* @param {{ key?: string, code?: string, ctrlKey?: boolean, metaKey?: boolean, altKey?: boolean, repeat?: boolean, target?: any }} e
|
||||
* @returns {'refresh'|'freeze'|'levelUp'|'ready'|'escape'|null}
|
||||
* @returns {'refresh'|'freeze'|'levelUp'|'retreat'|'sell'|'ready'|'escape'|null}
|
||||
*/
|
||||
export function shortcutFor(e) {
|
||||
if (!e || e.ctrlKey || e.metaKey || e.altKey) return null;
|
||||
@@ -1546,6 +1546,8 @@ export function shortcutFor(e) {
|
||||
if (code === 'KeyR' || key === 'r') return 'refresh';
|
||||
if (code === 'KeyF' || key === 'f') return 'freeze';
|
||||
if (code === 'KeyD' || key === 'd') return 'levelUp';
|
||||
if (code === 'KeyQ' || key === 'q') return 'retreat';
|
||||
if (code === 'KeyX' || key === 'x') return 'sell';
|
||||
if (code === 'Space' || key === ' ') return 'ready';
|
||||
return null;
|
||||
}
|
||||
@@ -1561,7 +1563,7 @@ export const closesOnFieldPress = (detail) => detail?.kind === 'piece' || detail
|
||||
* Whether an open overlay swallows a game shortcut: a modal / the guide own the keyboard (Esc included — they close
|
||||
* themselves); the 本局信息 / 敌方情报 drawer is a dialog too — only Esc (it closes the drawer) passes, R / F / D / Space
|
||||
* never act behind it.
|
||||
* @param {'refresh'|'freeze'|'levelUp'|'ready'|'escape'|null} act shortcutFor
|
||||
* @param {'refresh'|'freeze'|'levelUp'|'retreat'|'sell'|'ready'|'escape'|null} act shortcutFor
|
||||
* @param {{ modal?: boolean, drawer?: boolean }} open
|
||||
*/
|
||||
export function shortcutBlocked(act, { modal = false, drawer = false } = {}) {
|
||||
|
||||
@@ -73,7 +73,7 @@ export function SettingsModal({ open, onClose }) {
|
||||
</div>
|
||||
${touchUi
|
||||
? html`<p class="set-hint">触屏操作:点击单位选中(撤退 / 出售)· 长按单位或卡牌查看详情 · 拖动部署后滑动选择朝向</p>`
|
||||
: html`<p class="set-hint">快捷键:<kbd>R</kbd> 刷新 · <kbd>F</kbd> 冻结 · <kbd>D</kbd> 升级 · <kbd>Space</kbd> 准备就绪 · <kbd>Esc</kbd> 关闭弹窗 · 右键查看详情</p>`}
|
||||
: html`<p class="set-hint">快捷键:<kbd>R</kbd> 刷新 · <kbd>F</kbd> 冻结 · <kbd>D</kbd> 升级 · <kbd>Q</kbd> 撤退选中干员 · <kbd>X</kbd> 出售选中干员 · <kbd>Space</kbd> 准备就绪 · <kbd>Esc</kbd> 关闭弹窗 · 右键查看详情</p>`}
|
||||
</div>
|
||||
<//>`;
|
||||
}
|
||||
@@ -91,13 +91,13 @@ export function Underframe({ view, uid = null, row, col, actions, name = '', bus
|
||||
<path class="uframe__corner" d="M-100 0 L-86 -14 M-100 0 L-86 14 M100 0 L86 -14 M100 0 L86 14 M0 -100 L-14 -86 M0 -100 L14 -86 M0 100 L-14 86 M0 100 L14 86" />
|
||||
</svg>
|
||||
${actions.retreat ? html`<button type="button" class="uframe__btn uframe__btn--retreat" disabled=${busy} onPointerDown=${stop}
|
||||
onClick=${(e) => { stop(e); onRetreat?.(); }} title="撤退至整备区" aria-label="撤退">
|
||||
<${RetreatGlyph} /><span class="uframe__label">撤退</span>
|
||||
onClick=${(e) => { stop(e); onRetreat?.(); }} title=${actions.sell != null ? '撤退至整备区(Q)' : '撤退至整备区'} aria-label="撤退" aria-keyshortcuts=${actions.sell != null ? 'Q' : undefined}>
|
||||
<${RetreatGlyph} /><span class="uframe__label">${actions.sell != null ? '撤退[Q]' : '撤退'}</span>
|
||||
</button>` : null}
|
||||
${actions.sell != null ? html`<button type="button" class="uframe__btn uframe__btn--sell" disabled=${busy} onPointerDown=${stop}
|
||||
onClick=${(e) => { stop(e); onSell?.(); }} title=${`出售(+${actions.sell} 资金)`} aria-label=${`出售,获得 ${actions.sell} 资金`}>
|
||||
onClick=${(e) => { stop(e); onSell?.(); }} title=${`出售(+${actions.sell} 资金,X)`} aria-label=${`出售,获得 ${actions.sell} 资金`} aria-keyshortcuts="X">
|
||||
<${PlateIcon} sprite="icon_sell" glyph="sell" tone="sell" />
|
||||
<span class="uframe__label">出售</span>
|
||||
<span class="uframe__label">出售[X]</span>
|
||||
<${HexBadge} value=${`+${actions.sell}`} tone="gold" size="sm" class="uframe__price" />
|
||||
</button>` : null}
|
||||
${actions.destroy ? html`<button type="button" class=${cx('uframe__btn', 'uframe__btn--destroy')} disabled=${busy} onPointerDown=${stop}
|
||||
|
||||
Reference in new issue
Block a user