feedback4: merge master — PR #129 (watching a teammate shows hand, temp, equipment, strategy, effects)

This commit is contained in:
sganggs committed 2026-10-05 16:47:54 +08:00
commit f2440d4fd7
15 files changed
+521 -20

No files matched your search

+11 -4
View File
@@ -96,7 +96,7 @@ import {
snapHud, activeBubbles, shortcutFor, shortcutBlocked, closesOnFieldPress, phaseTotalSeconds, homeFieldId, ownFieldId, normalizeSp, sortedPlayers,
countdownState, shopBlockReason, stageOverrides, effectiveStage, watchTarget, dropFailureReason,
previewEnemyKey, prepCamera, prepCameraFor, foldCamera, deployFieldOf, panelSide, panelSlots, bondPopupPlace, chessLoadout, unitLoadout,
mergeTarget, modeOffBonds, readyFundsPrompt,
mergeTarget, modeOffBonds, readyFundsPrompt, ownerBandId,
} from '../ui/gameLogic.js';
import { toast } from '../ui/toasts.js';
import { BriefingScreen } from './briefing.js';
@@ -234,6 +234,10 @@ function MatchScreen() {
const alive = spectator ? false : priv ? priv.alive !== false : meP?.alive !== false;
const home = homeFieldId(pub, myId);
const watchingOther = !!watching && watching !== home && watching !== ownFieldId(myId);
// watching a teammate's prep board: the 本局信息 drawer shows THEIR 策略 in place of one's own (user playtest #2 item 2)
const scoutPid = watchingOther && field?.prep && typeof field.fieldId === 'string' && field.fieldId.startsWith('n:') ? field.fieldId.slice(2) : null;
const scoutBandId = scoutPid ? ownerBandId(pub, scoutPid) : null;
const scoutBandOwner = scoutPid ? (players.find((p) => p.playerId === scoutPid)?.name || null) : null;
const editable = phase === PHASE.PREP && !!priv && alive && !priv.ready && !watchingOther;
const showShop = !!priv && alive && (phase === PHASE.PREP || phase === PHASE.SP_DRAFT || phase === PHASE.ROUND_START) && !watchingOther;
const layersDisabled = phase === PHASE.UNITE || isBossPhase(phase);
@@ -404,7 +408,9 @@ function MatchScreen() {
evBufRef.current.delete(field.fieldId);
const earlySnap = snapBufRef.current.get(field.fieldId);
snapBufRef.current.delete(field.fieldId);
const kind = field.kind === 'hidden' ? 'boss' : field.kind || 'normal';
// a scouted prep board frames like the own prep with the shop folded (the bench row included, app.js camRect);
// 'prep' expands the rect's top to the hand row
const kind = field.prep ? 'prep' : (field.kind === 'hidden' ? 'boss' : field.kind || 'normal');
const pf = (Array.isArray(pub?.fields) ? pub.fields : []).find((f) => f && f.fieldId === field.fieldId);
const members = Array.isArray(pf?.players) ? pf.players : Array.isArray(field.players) ? field.players : [];
const sides = field.sides && typeof field.sides === 'object' ? field.sides : null;
@@ -415,7 +421,7 @@ function MatchScreen() {
// a lone player's boss field (solo modes, the odd player of a co-op Final Assault: the `_s` templates route every
// enemy to the left objective) is framed on its own half like the ‹ › half view; pairs start on 全景
const lone = kind === 'boss' && members.length === 1;
setCam(kind, lone ? { rect: field.rect, side, half: true } : { rect: field.rect, side });
setCam(kind, lone ? { rect: field.rect, side, half: true } : { rect: field.rect, side, ...(field.prep ? { shop: false } : {}) });
audio.setFieldUnits(field.units);
if (early && early.length) {
// replay state-bearing events only (a burst of stale hit sparks / damage numbers would look wrong)
@@ -1246,7 +1252,7 @@ function MatchScreen() {
self=${Number.isFinite(priv?.lp) ? { lp: priv.lp, pending: liveLpNow.pending, unite: liveLpNow.unite, left: liveLpNow.left } : null}
observe=${cc ? { canObserve: (p) => observeTarget(p, pub, myId, { observing: watchingOther, ownDone: localDone }), observing: watchingOther, onBack: backHome } : null} />
<div class="gm__effects"><${EffectsList} effects=${priv?.effects} /></div>
<div class="gm__effects"><${EffectsList} effects=${watchingOther && field ? (field.effects ?? null) : priv?.effects} /></div>
${watchingOther && !combat ? html`<div class="gm__watching" role="status">
<${GIcon} name="eye" /><span>正在查看 <b>${watchedName}</b> 的阵地(只读)</span>
@@ -1283,6 +1289,7 @@ function MatchScreen() {
</div>
${drawer ? html`<${EnemyDrawer} tab=${drawer} onTab=${setDrawer} pub=${pub} priv=${priv} onClose=${() => setDrawer(null)}
bandId=${scoutBandId} bandOwner=${scoutBandOwner}
onEnemy=${(k, n) => setDetail({ kind: 'enemy', id: k, count: n })} onChess=${(id) => setDetail({ kind: 'chess', id })} />` : null}
${bondPop ? html`<${BondPopup} bondId=${bondPop.bondId} entry=${bondPop.entry} priv=${bondPop.priv} banned=${pub?.bannedChess || []} owner=${bondPop.name}