feedback5 CB5: a 调度中心 upgrade opens the new level's extra slot at once with a new card, the cards shown stay in place (community report of 2026-10-06, item 19; the official tutorial's 休整期 page: 「升级后将出现更多的商品栏位」)
Until 0.2.0 the shop kept its old slot count until the next roll (a refresh or the round start), so a level-up 1→2 (险境: 3→4 operator slots) or 3→4 (4→5; 标准: 5→6) showed no new card. PlayerState._openLevelSlots (player/economy.js): the extra slots of the new level are appended to the chess slots (the item slot stays after them), each drawn at the new level; [ASSUMED] the new card follows the freeze toggle as a manual refresh's cards do. audit.js checks the slot count and that every card shown before stays in place. Docs: META.md §3 / §7, PLAYING.md. Golden: matches — all 18 scenarios moved (solo-FUNNY-1/2, solo-NORMAL-1/2, solo-HARD-1/2, solo-ABYSS-1/2, coop2-NORMAL-3, coop2-HARD-4, coop3-ABYSS-5, coop4-FUNNY-6, coop4-ABYSS-7, coop2-NORMAL-8-serverrun, solo-HARD-9-boosted, coop2-ABYSS-10-boosted, coop2-NORMAL-14-standins, coop2-NORMAL-70-diy): every bot levels its shop and now sees (and draws the shop RNG for) the new card at once, so purchases and boards part from there. roster / bonds / fields / standins / diy unchanged; no engine error stored. Tests: test/match/feedback5-shop-levelslots.test.js (new).
This commit is contained in:
1 parent
02353e13f8
commit
464a823bc5
6 files changed
+635
-507
No files matched your search
@@ -221,12 +221,23 @@ export function attachAudit(m, { invariants = true, limit = 200 } = {}) {
|
||||
const price = ps.shop.upgradePrice;
|
||||
const f0 = ps.funds;
|
||||
const fx = hasSpendEffects(m, ps);
|
||||
const slots0 = ps.shop.slots.slice();
|
||||
const layout0 = ps.shop.layout || { chess: slots0.length, item: 0 };
|
||||
const res = orig();
|
||||
if (res && res.ok) check('levelUp', () => {
|
||||
if (ps.shop.level !== lv + 1) fail(`${ps.playerId}: level ${lv} → ${ps.shop.level}`);
|
||||
if (f0 - ps.funds !== price && !fx && !hasSpendEffects(m, ps)) fail(`${ps.playerId}: level-up paid ${f0 - ps.funds}, price ${price}`);
|
||||
const next = gd.upgradeBase(ps.shop.level) ?? 0;
|
||||
if (ps.shop.upgradePrice !== next) fail(`${ps.playerId}: upgrade price after level-up ${ps.shop.upgradePrice}, expected ${next}`);
|
||||
// the new level's extra slots open at once (item 19 of 2026-10-06); the cards shown before stay in place
|
||||
const { chess, item } = gd.shopSlots(ps.shop.level);
|
||||
const want = Math.max(chess, layout0.chess) + Math.max(item, layout0.item);
|
||||
if (ps.shop.slots.length !== want) fail(`${ps.playerId}: ${ps.shop.slots.length} shop slots after the level-up to ${ps.shop.level}, expected ${want}`);
|
||||
const layout = ps.shop.layout || layout0;
|
||||
slots0.forEach((s, i) => {
|
||||
const at = i < layout0.chess ? i : layout.chess + (i - layout0.chess);
|
||||
if (ps.shop.slots[at] !== s) fail(`${ps.playerId}: shop slot ${i} changed by the level-up`);
|
||||
});
|
||||
});
|
||||
return res;
|
||||
});
|
||||
|
||||
@@ -92,6 +92,27 @@ export class PlayerEconomy {
|
||||
this.dirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* The 调度中心's upgrade opens the new level's extra slots at once, each with a new card drawn at the new level; the
|
||||
* cards already shown stay where they are (chess slots keep their index, the item slot stays after them). Official: the
|
||||
* tutorial's 休整期 page 「升级:…升级后将出现更多的商品栏位、可调度干员以及新装备」; the community report of 2026-10-06
|
||||
* (item 19) 「升级商店获得新的商店位时用新卡补上,而不是空着」. Until 0.2.0 the extra slots waited for the next roll (a
|
||||
* refresh or the round start). [ASSUMED] the new card follows the freeze toggle, as a manual refresh's cards do.
|
||||
*/
|
||||
_openLevelSlots() {
|
||||
const { chess: nChess, item: nItem } = this.gd.shopSlots(this.shop.level);
|
||||
const old = this.shop.slots;
|
||||
const layout = this.shop.layout || { chess: old.length, item: 0 };
|
||||
if (nChess <= layout.chess && nItem <= layout.item) return;
|
||||
const chess = old.slice(0, layout.chess);
|
||||
const items = old.slice(layout.chess);
|
||||
const fresh = (s) => { if (s) s.frozen = this.shop.frozen; return s; };
|
||||
while (chess.length < nChess) chess.push(fresh(this._rollChessSlot()));
|
||||
while (items.length < nItem) items.push(fresh(this._rollItemSlot()));
|
||||
this.shop.slots = [...chess, ...items];
|
||||
this.shop.layout = { chess: chess.length, item: items.length };
|
||||
}
|
||||
|
||||
/** Combat start: unfrozen slots are emptied (research 01 A1). */
|
||||
clearUnfrozenShop() {
|
||||
this.shop.slots = this.shop.slots.map((s) => (s && s.frozen && !s.sold ? s : null));
|
||||
@@ -173,6 +194,7 @@ export class PlayerEconomy {
|
||||
this.spend(price);
|
||||
this.shop.level++;
|
||||
this.shop.upgradePrice = this.gd.upgradeBase(this.shop.level) ?? 0;
|
||||
this._openLevelSlots();
|
||||
this.m.tickerFor('SHOP_LEVEL', [this.name, String(this.shop.level)], { playerId: this.playerId, param: String(this.shop.level) });
|
||||
this.m.dispatch(this, 'onLevelUp', { level: this.shop.level, price });
|
||||
this._afterSpend(price, 'levelUp');
|
||||
|
||||
Reference in new issue
Block a user