diff --git a/docs/DESIGN.md b/docs/DESIGN.md index bd41ae84..9112a7ee 100644 --- a/docs/DESIGN.md +++ b/docs/DESIGN.md @@ -492,6 +492,8 @@ Look & feel: research 06 §11–§12 (near-black green-grey panels, mint `#4ed8a Screens: **Title** (season art backdrop, 开始 → nickname), **Lobby** (独立模拟 / 同盟模拟 → create or join; recent rooms), **Room** (4 seats, invite code + copy link, difficulty picker (host), add/remove AI, ready, start), **Briefing** (INFO_CHECK: stage, factions, disabled bonds, banned chess, boss silhouette, ready x/4), **Band draft** (grid of 40 bands with icon/name/LP/effect; turn order list; skip; 查看禁用盟约与干员 under the order list opens the briefing's bond rows, legend and banned operators again in a read-only dialog — one component, `ui/matchInfo.js`, §21.28), **Game** (Pixi field + DOM HUD: top bar with round/phase capsule/LP (live during the own battle, §17.5)/timer/ready; bond strip + popups; left team panel with LP/status/emote bubbles, click to watch; bottom shop bar (level card, 3–5 chess cards, item card, funds, refresh, freeze, collapse); detail panel on click/hover (header with bonds, then 特质 — the operator's own effect — right under it, 特性, stats (live: the battle's own numbers / the start-of-battle ones in prep, §18.5), skill, module, equipped items, talents: §17.5); enemy preview drawer (next round enemies with counts, factions; its 本局信息 tab lists the briefing's disabled bonds and banned operators, §21.28); 机变 overlay (the official card: framed icon + name, the effect text — data `descRaw` — under it, the taker's round avatar at the top-right; two taps, §18.2, §20.7); merge reward overlay (the promotion reward, or a special offer — 凯瑟琳's 定向投放 … — as item / chess cards under its source's label, with the count of offers queued behind it, §21.2); phase banners; ticker (by broadcast priority, highest first; a leader-damage line plays only in its round and a player's newer one replaces the older, §21.10); toasts; emote wheel; settings (volume, quality, show damage numbers)), **Result** (victory/defeat, rounds, per-player lineup, stats, titles, back to room). +盟约栏支持「收起/展开盟约」(GitHub #142):收起时隐藏完整列表并关闭由列表打开的浮层,让原图标区域的指针事件到达棋盘,只保留至少 44×44 CSS px 的恢复按钮。折叠状态在本局阶段变化、观看队友时保留;展开后仍按当前观看对象显示最新盟约。按钮支持 Enter / Space,聚焦按钮时 Space 不触发准备或暂停。 + A bond the mode never activates (标准: official `inactiveBondIdList`) reads 本局禁用 on shop / reward cards (struck through), detail chips and the popup — no 在场 count, no 当前效果 (§21.7); a strategy built around one carries a 本局禁用 tag and note in the strategy draft and stays selectable (bands.json `bondIds`, §21.26). Interactions (research 09 §1.2 / §5, which supersede the first draft): shop card, upgrade and 机变 card are two-tap (select → confirm, §18.2) — a tap anywhere on the card, its confirm strip included, is the card's tap (shop cards have no ⓘ corner; the armed bar sits above the detail card; a shop card that cannot be bought right now opens its detail on tap, §20.7); a press / drop goes by the tile under the pointer (§18.1); drag bench↔board — a legal board drop (also onto the piece's own tile) opens the 4-direction deploy wheel (swipe UP/RIGHT/DOWN/LEFT with the rotated range striped orange; release in the centre, ✕ 点击取消 or Esc cancels); tap a unit's tile ⇒ underframe with **出售 +N** (and **撤退** on the board; items/Arts in the hand / temp: **销毁** — equipped items are locked, §6.2) plus its rotated range; no drag-to-sell; drag an item onto a unit's tile ⇒ equip that unit (both slots used ⇒ the replace dialog `ui/equipReplace.js` shows the incoming and the two equipped items; the player picks the one to replace — it is destroyed — `g.equip replaceUid`; cancel changes nothing); Arts are dropped on a tile and get the direction step; right-click or long-press ⇒ detail (or a tap on a shop card while the bar is locked); `R` refresh, `F` freeze, `D` level-up, `Space` ready (in a solo battle: pause / resume, §14 Solo pause). All actions optimistic-free: UI waits for server state (latency is small). diff --git a/docs/PLAYING.md b/docs/PLAYING.md index 1235246c..65754748 100644 --- a/docs/PLAYING.md +++ b/docs/PLAYING.md @@ -94,6 +94,8 @@ 干员属于 1–2 个盟约。场上**不同名**的成员达到人数后激活(大多只数棋盘上的,「远见」「奇迹」「投资人」连整备区也算)。 +盟约栏挡住棋盘时,点左侧的「收起」隐藏列表,再点「盟约」展开。收起会关闭从盟约栏打开的详情,原来图标覆盖的位置可以直接点选或拖动棋子;本局切换回合、查看队友时保留收起状态。 + - **核心盟约**(8 个势力:炎、萨尔贡、维多利亚、谢拉格、拉特兰、阿戈尔、叙拉古、卡西米尔):3 名激活,6 名获得强力的额外效果。 - **附加盟约**(精准、迅捷、灵巧、奥术、坚守、助力、远见、奇迹、投资人、突袭、不屈、调和、协防干员、独行、绝技):多为 2 / 3 名激活;「独行」需要场上**恰好 1 名**,「绝技」按场上的精锐数量计算,没有势力盟约的干员算「协防干员」。 - **本局禁用**:「标准模拟」与官方相同,关闭拉特兰、阿戈尔、卡西米尔、灵巧、奥术、奇迹、投资人、突袭、独行、绝技这 10 个盟约,它们不会激活。你有这些盟约的成员时(奇迹、投资人也算整备区里的成员),盟约栏末尾显示**灰色带 ✕ 的盟约图标和「本局禁用」**,干员卡、盟约标签和盟约详情也这样标注。「远见」「奇迹」「投资人」计入整备区,盟约详情的「成员」人数也一样计入整备区里的成员(临时整备区不算)。 diff --git a/public/css/screens/game.css b/public/css/screens/game.css index cb101c1a..8f58f30b 100644 --- a/public/css/screens/game.css +++ b/public/css/screens/game.css @@ -220,12 +220,22 @@ .readybtn.is-busy { opacity: .7; } /* ---- bond strip ---------------------------------------------------------------------------------------- */ -.gm__bonds { position: absolute; left: 1.56rem; top: 1.36rem; right: 5.2rem; pointer-events: none; } +.gm__bonds { position: absolute; left: 1.56rem; top: 1.36rem; right: 5.2rem; pointer-events: none; + display: flex; align-items: flex-start; gap: max(.1rem, 8px); } /* Only the bond discs (and the +N chip) take the pointer: the strip's box spans the width under the top bar, where the top board row's units stand (row 12 at 16:9 / 21:9 / 720p / phones, the boss field's row 5 in a boss prep) — it used to swallow the taps and drags on them (review of user playtest #2 item 8: every own unit reachable). */ .gm__bonds > *, .gm__bonds .bstrip { pointer-events: none; } .gm__bonds .bslot, .gm__bonds .bstrip__more { pointer-events: auto; } +.gm__bond-list { min-width: 0; } +/* The hidden list leaves no hit area over the board; only this compact tab can reopen it (GitHub #142). */ +.gm__bonds .bonds-toggle { pointer-events: auto; flex: none; display: inline-flex; align-items: center; justify-content: center; + gap: max(.03rem, 2px); min-width: 44px; min-height: 44px; padding: .06rem .08rem; + color: var(--text-hi); background: var(--bg-1); border: 1px solid var(--line-2); cursor: pointer; + font-size: max(.14rem, 11px); line-height: 1; } +.bonds-toggle .icon { width: max(.18rem, 14px); height: max(.18rem, 14px); } +.bonds-toggle:hover { color: var(--mint-500); border-color: var(--mint-500); } +.bonds-toggle:focus-visible { outline: 2px solid var(--mint-500); outline-offset: 2px; } .bstrip { display: flex; align-items: flex-start; gap: .1rem; flex-wrap: nowrap; } .bstrip.is-frozen .bslot { opacity: .5; filter: saturate(.4); } .bstrip--empty { display: inline-flex; align-items: center; gap: .12rem; padding: .08rem .16rem; font-size: .15rem; color: var(--text-dim); background: rgba(8, 11, 10, .6); border: 1px dashed var(--line-2); } diff --git a/public/js/screens/game.js b/public/js/screens/game.js index 47a1d602..8a42291a 100644 --- a/public/js/screens/game.js +++ b/public/js/screens/game.js @@ -200,6 +200,7 @@ function MatchScreen() { const [watchWho, setWatchWho] = useState(null); // { fieldId, playerId }: the teammate picked with 前往查看 const [drawer, setDrawer] = useState(null); // 'enemies' | 'info' | null const [bondOpen, setBondOpen] = useState(null); // { id, ownerId, from }: the bond popup and whose bond it shows + const [bondsCollapsed, setBondsCollapsed] = useState(false); const [detail, setDetail] = useState(null); // detail target const [collapsed, setCollapsed] = useState(false); const [rewardMin, setRewardMin] = useState(false); @@ -1244,8 +1245,20 @@ function MatchScreen() { live=${liveLpNow} spectator=${spectator} />