From b9bbf3a0402d76a4c680d9337bd9a48152c24314 Mon Sep 17 00:00:00 2001 From: sganggs Date: Sat, 3 Oct 2026 02:52:38 +0800 Subject: [PATCH] =?UTF-8?q?feedback1c=20WK:=20a=20=E5=90=8C=E6=9E=84=20row?= =?UTF-8?q?=20opens=20the=20wearer's=20card=20with=20its=20pair?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Review follow-up. A teammate's card showed the dashed 同构 chip but not the items behind it, and the card a bond popup's 同构 row opened was the plain record card, without the chip. - gameLogic.bondMembers: a 变形同构体 row carries the wearer's item ids. - BondPopup passes them to onMember; the screen hands them to the card ({ kind: 'chess', id, owner, items }), resolveDetail turns them into unitItems. - ChessDetail: a card without an own piece lists the carried items read-only under 装备 (a teammate's unit, the card a 同构 row opens). - META: the card side, and the operator-talent checks that still read the record's bonds [ASSUMED]. --- docs/META.md | 4 +++- public/js/screens/game.js | 2 +- public/js/ui/bondStrip.js | 11 +++++++---- public/js/ui/detailPanel.js | 20 ++++++++++++++++---- public/js/ui/gameLogic.js | 16 +++++++++------- test/ui/morph-bonds.test.js | 35 +++++++++++++++++++++++++++++++++-- test/ui/watch-bonds.test.js | 3 ++- 7 files changed, 71 insertions(+), 20 deletions(-) diff --git a/docs/META.md b/docs/META.md index 43aee5b2..d86f0656 100644 --- a/docs/META.md +++ b/docs/META.md @@ -439,7 +439,9 @@ Any `choice:` handler whose EffectRef reuses its own key must guard like this (o any member (on the board only: the 14 bonds are BOARD; one member per operator, normal and elite copies alike), and so in the battle input / battle, the views, and on the client: the bond popup lists it among the members (tagged 同构, `gameLogic.bondMembers` / `grantedBonds`, the same rule as `pieceBonds`) and its card shows the granted bond - chip; a teammate's units carry their item ids for that (UnitInfo `items`, `Match.prepFieldMeta`, SIM.md §9). + chip; a teammate's units carry their item ids for that (UnitInfo `items`, `Match.prepFieldMeta`, SIM.md §9), and a + card without an own piece (a teammate's unit, the card a 同构 row opens) lists those items read-only under 装备. + Not covered [ASSUMED]: operator talents that test "【拉特兰】/【卡西米尔】/… 干员" in the kits read the record's bonds. **Layer cap** (research 11 §1; the client's `MAX_GARRISON_STACK` / `AddBondCount` = min(L + n, 999)): each bond's layers stop at `BOND_LAYER_CAP` = 999 (shared/constants.js; 0 / Infinity = off). Every writer clamps with `layerGainRoom` — `PlayerState.addLayers` (all prep-side gains: 特质, items, bands, 机变 cards, bonds; `ctx.addLayers`), diff --git a/public/js/screens/game.js b/public/js/screens/game.js index 55c855a2..45f668d2 100644 --- a/public/js/screens/game.js +++ b/public/js/screens/game.js @@ -1200,7 +1200,7 @@ function MatchScreen() { ${bondPop ? html`<${BondPopup} bondId=${bondPop.bondId} entry=${bondPop.entry} priv=${bondPop.priv} banned=${pub?.bannedChess || []} owner=${bondPop.name} place=${bpPlace} over=${!!resolved && bpPlace === dSide} - onClose=${() => setBondOpen(null)} onMember=${(id) => setDetail({ kind: 'chess', id, owner: bondPop.ownerId })} />` : null} + onClose=${() => setBondOpen(null)} onMember=${(id, items) => setDetail({ kind: 'chess', id, owner: bondPop.ownerId, items: items || null })} />` : null} ${resolved ? html`<${DetailPanel} detail=${resolved} snapHp=${snapHp} onClose=${() => { setDetail(null); setSel(null); }} bonds=${detailBonds} loadout=${detailLoadout} side=${dSide} shopOpen=${shopOpen} live=${liveStats} diff --git a/public/js/ui/bondStrip.js b/public/js/ui/bondStrip.js index 9817d91e..ea9a39ca 100644 --- a/public/js/ui/bondStrip.js +++ b/public/js/ui/bondStrip.js @@ -1,7 +1,8 @@ // Bond strip (active-bond discs under the top bar) and the bond detail popup: the key facts first (user playtest #2 // item 9: name, members in play / next threshold, layers, reached tier and its threshold row, the current effect with // layer-resolved numbers), then the full description and the member list with owned / on-board state — operators that -// are members through 变形同构体 included (tagged 同构, gameLogic bondMembers), so the list's count agrees with 在场. Opened +// are members through 变形同构体 included (tagged 同构, gameLogic bondMembers; such a row opens the wearer's card with its +// items: the pair and the granted chip), so the list's count agrees with 在场. Opened // from the detail panel's bond chips it docks beside that panel (`beside`: the panel's side). // Research 06 §11.1: round mint discs, stack count over the disc, name below, sorted by stacks; grey = // present but inactive; in 联防 / boss rounds the strip is dimmed ("层数叠加已禁用"). @@ -59,10 +60,12 @@ export function BondStrip({ bonds, layersDisabled = false, onOpen, openId = null /** * Bond detail popup. - * @param {{ bondId: string, entry?: any, priv?: any, banned?: string[], onClose: Function, onMember?: (chessId:string)=>void, + * @param {{ bondId: string, entry?: any, priv?: any, banned?: string[], onClose: Function, + * onMember?: (chessId:string, items?:string[]|null)=>void, * place?: 'left'|'beside'|'besideR'|'right'|null, over?: boolean, beside?: 'left'|'right'|null, owner?: string|null }} props — * `place`: where it opens (gameLogic bondPopupPlace; `beside: 'left'` = the older spelling of 'beside'); `over`: above the - * detail card; `owner`: the watched teammate's name (`entry` / `priv` are then theirs: ui/watchBonds.js) + * detail card; `owner`: the watched teammate's name (`entry` / `priv` are then theirs: ui/watchBonds.js); `onMember` + * gets a 变形同构体 row's item ids too (its card shows the pair and the granted chip), null for a plain member */ export function BondPopup({ bondId, entry, priv, banned = [], onClose, onMember, place = null, over = false, beside = null, owner = null }) { const b = data.lookup('bonds', bondId); @@ -108,7 +111,7 @@ export function BondPopup({ bondId, entry, priv, banned = [], onClose, onMember,

成员 ${members.filter((x) => x.onBoard).length}/${members.length}

${members.map((mb) => html`