feedback5 R19C: the official 「作战结束」 result box and the three battle-over sounds at settlement (GitHub #235; PR #112 by @Convey123, approved and never merged, ported by hand onto the 0.2.0 modules) — the box says only the viewer's own LP, 「全员无伤!」 or 「生命值减少 −N」; after a 联防 the number is the server's own per-player charge (m.public.uniteResult in the SETTLE view) and 「全员无伤!」 only when nothing got through; no box for spectator seats, eliminated players or the boss rounds; golden: unchanged
This commit is contained in:
1 parent
0b306baa49
commit
f661a47773
21 files changed
+706
-14
No files matched your search
@@ -368,6 +368,8 @@ export class Match {
|
||||
this.watchPref = new Map();
|
||||
this.lastResults = new Map();
|
||||
this.unitePlan = null;
|
||||
/** 联防 outcome for the SETTLE view: { through, helpers, leakers, losses } (settle()), null when no 联防 resolved */
|
||||
this.uniteResultView = null;
|
||||
/** server-run 联防: the leakers' counts last published (_uniteTick) */
|
||||
this._uniteLeftKey = null;
|
||||
/** 联防: { plan, bounds } — per leaker the most survivors settlement can bill (_uniteLeft's clamp) */
|
||||
|
||||
@@ -229,6 +229,7 @@ export class MatchPhases {
|
||||
this.fields = [];
|
||||
this.watchers.clear();
|
||||
this.unitePlan = null;
|
||||
this.uniteResultView = null;
|
||||
this.sp = null;
|
||||
this.wave = null;
|
||||
this.bossWaves = null;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// server/match/match/settle.js — Match methods: SETTLE (the LP loss — a leaker's 联防 survivors —, stats, bounty coins,
|
||||
// the IN_BATTLE layer gains clamped by layerGainRoom, CHAR_DAMAGE tickers, eliminations) and RESULT (finish: m.result
|
||||
// to every human still here, onEnd).
|
||||
// the IN_BATTLE layer gains clamped by layerGainRoom, CHAR_DAMAGE tickers, eliminations, the 联防 outcome the SETTLE
|
||||
// view carries) and RESULT (finish: m.result to every human still here, onEnd).
|
||||
// Installed on Match.prototype by server/match/Match.js (a method container: never instantiated; `this` is the match).
|
||||
|
||||
import { PHASE, layerGainRoom } from '../../../shared/constants.js';
|
||||
@@ -20,11 +20,24 @@ export class MatchSettle {
|
||||
// a 联防 battle that could not run at all (synthetic result) must not wipe the leakers' losses: charge their own leaks
|
||||
const uniteRan = !!(plan && uniteResult && !uniteResult.synthetic);
|
||||
const survivors = uniteRan ? uniteSurvivors(plan, uniteResult) : null;
|
||||
// The 联防's outcome as data for the SETTLE view (m.public.uniteResult, views.js; GitHub #235, PR #112 by @Convey123):
|
||||
// each client pops the official result box from it (ui/gameLogic/phases.js uniteResultBox) — `through` = the leakers'
|
||||
// enemies that still got through (uncapped; only decides whether 「全员无伤!」 is true), `losses` = every alive
|
||||
// player's own LP charge of this round, the same `loss` deducted below, so the box and the LP bar never disagree. A
|
||||
// leaker's own battle leaks are not its charge in a 联防 round, which is why the client cannot work the number out
|
||||
// itself. No ticker line: the official reports the outcome in the one dialog. null when no 联防 resolved.
|
||||
this.uniteResultView = uniteRan && plan.leakers.length ? {
|
||||
through: plan.leakers.reduce((n, lk) => n + Math.max(0, survivors.get(lk.playerId) || 0), 0),
|
||||
helpers: plan.helpers.map((p) => p.playerId),
|
||||
leakers: plan.leakers.map((p) => p.playerId),
|
||||
losses: {},
|
||||
} : null;
|
||||
const alive = this.alivePlayers();
|
||||
for (const ps of alive) {
|
||||
const r = this.lastResults.get(ps.playerId) || { leaked: [], perfect: true, coins: 0, layerGains: {}, killed: 0, damageDealt: 0 };
|
||||
const counted = (r.leaked || []).filter((l) => l && l.counted !== false).length;
|
||||
const loss = uniteRan && plan.leakers.includes(ps) ? Math.min(cap, survivors.get(ps.playerId) || 0) : Math.min(cap, counted);
|
||||
if (this.uniteResultView) this.uniteResultView.losses[ps.playerId] = loss;
|
||||
ps.lp -= loss;
|
||||
ps.stats.lpLost += loss;
|
||||
ps.stats.leaks += counted;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// server/match/match/views.js — Match methods: the state builders — m.public (publicView with statusOf / fieldOf, the
|
||||
// fields' progress and the teammates' live pendingLp / uniteLeft), the nextEnemies preview of m.private and the prep
|
||||
// scout's m.field (prepFieldMeta: board, hand and temp as units, the scouted player's effects and coming enemies; in a
|
||||
// boss round's prep on the player's half of the boss field).
|
||||
// fields' progress, the teammates' live pendingLp / uniteLeft, the SETTLE uniteResult), the nextEnemies preview of
|
||||
// m.private and the prep scout's m.field (prepFieldMeta: board, hand and temp as units, the scouted player's effects and
|
||||
// coming enemies; in a boss round's prep on the player's half of the boss field).
|
||||
// Installed on Match.prototype by server/match/Match.js (a method container: never instantiated; `this` is the match).
|
||||
|
||||
import { PHASE, GEO } from '../../../shared/constants.js';
|
||||
@@ -117,6 +117,13 @@ export class MatchViews {
|
||||
};
|
||||
}
|
||||
if (this.phase === PHASE.UNITE && this.unitePlan) v.unite = { helpers: this.unitePlan.helpers.map((p) => p.playerId), leakers: this.unitePlan.leakers.map((p) => p.playerId) };
|
||||
// SETTLE after a 联防: its outcome as data (settle.js uniteResultView; GitHub #235, PR #112) — { through, helpers,
|
||||
// leakers, losses: { playerId: the LP settlement charged this round } } — the client's result box reads the viewer's
|
||||
// own charge from it; absent when no 联防 resolved (the client then shows the round's own battle result)
|
||||
if (this.phase === PHASE.SETTLE && this.uniteResultView) {
|
||||
const ur = this.uniteResultView;
|
||||
v.uniteResult = { through: ur.through, helpers: ur.helpers.slice(), leakers: ur.leakers.slice(), losses: { ...ur.losses } };
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user