feedback3 WH: an item gained as prep ends waits in hand and merges at the next prep start

This commit is contained in:
sganggs committed 2026-10-04 20:34:03 +08:00
1 parent c0cc1d6118
commit 9aaba7708c
7 files changed
+182 -5

No files matched your search

+5
View File
@@ -1658,6 +1658,11 @@ export class Match {
const alive = this.alivePlayers();
for (const ps of alive) {
ps.ready = false;
// Items gained as the previous prep ended waited unmerged (acquireItem deferMerge). Merge them now, before
// this prep's onPrepStart grants and before the player acts — not in endPrep, which runs in the same prep
// that granted them and would take an equipped copy off for the fight about to start.
ps.checkItemMerges();
ps.recompute();
this.dispatch(ps, 'onPrepStart', { round: this.round });
ps.recompute();
}
+6 -2
View File
@@ -712,12 +712,16 @@ export class PlayerState {
/**
* Acquire an item (buy, supply card, grant). Merges with an identical normal copy (hand/temp/equipped) into the
* golden item (to the hand). Returns the owned piece or null.
* `deferMerge` (effectsMeta, while onPrepEnd is on the stack): stow it — hand, else temp — and do not merge in this
* call, even when an identical normal copy is already owned. The next prep's start runs checkItemMerges. Nothing
* already equipped is taken off for the fight about to start. Hand and temp both full keeps the 「整备区已满,获得的装备已销毁」
* outcome. [ASSUMED] every item granted at 休整期结束, not only 维多利亚's 战栗维式重锤 (owner's decision 2026-10-04).
*/
acquireItem(itemId, { source = 'grant', toTemp = false, silent = false } = {}) {
acquireItem(itemId, { source = 'grant', toTemp = false, silent = false, deferMerge = false } = {}) {
const rec = this.gd.item(itemId);
if (!rec) return null;
let piece = this.newPiece('item', itemId);
if (this.completesItemMerge(itemId)) {
if (!deferMerge && this.completesItemMerge(itemId)) {
piece = this._mergeItem(itemId, piece);
if (!piece) return null;
} else if (!this.stow(piece, { allowTemp: true, toTemp })) {
+11 -1
View File
@@ -196,6 +196,11 @@ export class EffectDispatcher {
return ev;
}
this.depth++;
// An item granted while 休整期结束 is on the stack (this hook, or onGain re-entering it — 维多利亚 pays the next
// milestone from the grant's onGain) is stowed and not merged until the next prep start. [ASSUMED] every such
// item, not only the 战栗维式重锤 (owner's decision 2026-10-04: "an item that arrives at 休整期结束").
const deferItems = hook === 'onPrepEnd';
if (deferItems) ps._deferItemMerge = (ps._deferItemMerge || 0) + 1;
try {
const reg = this.registry;
// 0. onPrice: the priced chess's own 特质 first — 购买价格为N defines the price every other modifier acts on
@@ -236,6 +241,7 @@ export class EffectDispatcher {
if (h) this._call(ps, ref.key, h, hook, { kind: 'effect', key: ref.key, ref }, ev);
}
} finally {
if (deferItems) ps._deferItemMerge--;
this.depth--;
}
return ev;
@@ -511,7 +517,11 @@ export function makeCtx(m, ps, source, hook, ev = null) {
},
grantItem: (itemId, opts = {}) => {
if (!ps.alive || !gd.item(itemId)) return null;
const p = ps.acquireItem(itemId, { source: opts.source || source.key || 'effect', toTemp: !!opts.toTemp });
const p = ps.acquireItem(itemId, {
source: opts.source || source.key || 'effect',
toTemp: !!opts.toTemp,
deferMerge: ps._deferItemMerge > 0,
});
return p ? view(p) : null;
},
/** Random chess id from the shared pool (copy-weighted). opts: { maxTier, tier, bond, filter(id) } */
+2
View File
@@ -607,6 +607,8 @@ export function payHammers(ctx) {
ctx.setCounter(VICTORIA_COUNTER, paid + 1);
for (let i = 0; i < count; i++) {
const id = ctx.rollItem({ pool: p.pool });
// onPrepEnd: grantItem stows this and does not merge until the next prep start, so a second copy does not
// take an equipped hammer off for the fight (effectsMeta _deferItemMerge). [ASSUMED] every item that hook grants.
if (id && ctx.grantItem(id, { source: 'bond:victoriaShip' })) granted++;
}
}