From 38d4c3e4b5e66eb1aa5e4fa93e1883a3acdddde0 Mon Sep 17 00:00:00 2001 From: sganggs Date: Thu, 8 Oct 2026 20:34:51 +0800 Subject: [PATCH] =?UTF-8?q?feedback7=20R22-GHSIM:=20=E4=BD=99=20=E3=80=90?= =?UTF-8?q?=E6=96=87=E7=81=AB=E6=85=A2=E7=82=96=E3=80=91=20adds=20no=20lay?= =?UTF-8?q?ers=20to=20a=20bond=20without=20layers=20(noStack:=20=E7=BB=9D?= =?UTF-8?q?=E6=8A=80,=20=E7=8B=AC=E8=A1=8C,=20=E8=B0=83=E5=92=8C,=20?= =?UTF-8?q?=E5=8D=8F=E9=98=B2=E5=B9=B2=E5=91=98)=20=E2=80=94=20with=20one?= =?UTF-8?q?=20such=20bond=20the=20only=20one=20active,=20nothing=20is=20ad?= =?UTF-8?q?ded=20(the=20owner's=20decision=20of=202026-10-08);=20golden:?= =?UTF-8?q?=20unchanged?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The owner's decision (relayed 2026-10-08) overrides PRTS 下半/PRTS盟约记录 「部分盟约不会显示叠加层数,但是叠加层数的特质/策略/ 装备等效果仍然对其生效」 for this strategy. bands/meta.js round_start_bond_check_gain_layer skips every bonds.json noStack bond; the 「仅激活了1个盟约」 count stays the sentence's (every active bond), so: 独行 / 绝技 alone → nothing; 独行 + one layered bond → the layered one +12 (count2), 独行 none. Repro: 独行 alone got 36, 绝技 alone 36, 独行 + 炎 got 12 each. Only 余: 协防 (bonds/addon/meta.js deputShip, 「使所有已激活的盟约层数+N」) and 华法琳 【重点监护】 (prep_finish_char_bond_add_layer, a random operator's bonds, 无需激活) each pick their own bonds and call addLayers; they share no helper with 余 beyond the generic Player.addLayers sink, which every layer gain uses — left unchanged, so both still add to noStack bonds as PRTS says. Docs: PLAYING.md 层数. Golden: unchanged (no corpus 余 at round 8 with such a bond). --- docs/PLAYING.md | 2 +- server/sim/content/bands/meta.js | 16 ++++++++++++---- test/content/bands.test.js | 16 ++++++++++++++++ 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/docs/PLAYING.md b/docs/PLAYING.md index c0a270f1..24e22add 100644 --- a/docs/PLAYING.md +++ b/docs/PLAYING.md @@ -111,7 +111,7 @@ - **本局禁用**:「标准模拟」与官方相同,关闭拉特兰、阿戈尔、卡西米尔、灵巧、奥术、奇迹、投资人、突袭、独行、绝技这 10 个盟约,它们不会激活。你有这些盟约的成员时(奇迹、投资人也算整备区里的成员),盟约栏末尾显示**灰色带 ✕ 的盟约图标和「本局禁用」**,干员卡、盟约标签和盟约详情也这样标注。「远见」「奇迹」「投资人」计入整备区,盟约详情的「成员」人数也一样计入整备区里的成员(临时整备区不算)。 - **调和**:激活时,场上已有成员的核心盟约人数各 +1(只加 1 人,不论有几名调和干员)。盟约详情会写「含调和 +1」,成员列表上方列出带来这 1 人的调和干员(如缪尔赛思)。 - **炎佑**:场上 6 名以上「炎」干员时召唤炎佑(9 名时两只)。它追踪全场仇恨最高的敌人并悬停在其上方,技能「祛恶之焰」锁定 1 个目标**持续喷火**(最长 20 秒,每秒对目标周围的敌人造成法术伤害并附带灼燃,喷火时不普攻,目标死亡或被沉默时结束);场上暂时没有敌人时停在原地等待。它持有官方的「孤立」:医疗干员不会治疗它,友方的增益、光环和天赋也不会选中它(敌人照常可以攻击它)。 -- **层数**:盟约通过各种效果叠加层数,层数越高效果越强(例如「炎」攻击力随层数提升、「远见」每 10 层给资金)。**层数整局保留,但只有盟约激活时才生效**,多数情况下也只有激活的盟约能叠层。每个盟约最多 **999 层**(与官方相同,取自官方客户端的常量):到 999 后再获得的层数直接作废,按层数发放的奖励(如「远见」的资金)也随之停止。作战中获得的层数在盟约栏里**实时**显示,作战结束后一直保留到结算(联防期间也不会退回去)。「调和」「协防干员」「独行」「绝技」与官方一样**不显示层数**(盟约栏、详情和结算卡片都不显示),但叠层的特质 / 策略 / 装备照样给它们加层(PRTS 盟约记录:「部分盟约不会显示叠加层数,但是叠加层数的特质/策略/装备等效果仍然对其生效」),这些层数也计入激活层数总和;它们的效果本身与层数无关。 +- **层数**:盟约通过各种效果叠加层数,层数越高效果越强(例如「炎」攻击力随层数提升、「远见」每 10 层给资金)。**层数整局保留,但只有盟约激活时才生效**,多数情况下也只有激活的盟约能叠层。每个盟约最多 **999 层**(与官方相同,取自官方客户端的常量):到 999 后再获得的层数直接作废,按层数发放的奖励(如「远见」的资金)也随之停止。作战中获得的层数在盟约栏里**实时**显示,作战结束后一直保留到结算(联防期间也不会退回去)。「调和」「协防干员」「独行」「绝技」与官方一样**不显示层数**(盟约栏、详情和结算卡片都不显示),但叠层的特质 / 策略 / 装备照样给它们加层(PRTS 盟约记录:「部分盟约不会显示叠加层数,但是叠加层数的特质/策略/装备等效果仍然对其生效」),这些层数也计入激活层数总和——只有策略「余」的【文火慢炖】不给这四个盟约加层(第 8 回合只激活了其中一个时什么也不加;维护者 2026-10-08 的决定);它们的效果本身与层数无关。 - **特质在哪里生效**:「进入休整期时」「休整期结束时」「刷新时」的特质(详情卡的第一项)只在干员部署在作战区时生效;文字里写着「此干员在整备区时也有效」的拉普兰德、调香师、波登可,以及激活【炎】/【投资人】时的琳琅诗怀雅,在整备区里也生效(临时整备区不算),与官方数据一致;「获得时」「售出时」的特质在获得、售出的那一刻生效,不论干员在哪里。「远见」「奇迹」「投资人」的「整备区的…干员也可用于激活盟约」只是把整备区的成员算进人数,不会让赫默等干员的特质在整备区生效。写着「使已激活的…」的特质要求盟约当时已经激活:例如「叙拉古」只数作战区里不同的叙拉古干员,整备区里的拉普兰德不算在这 3 名里;拉普兰德每回合只在她经历的第一次主动刷新时叠层(免费刷新也算),那次刷新时叙拉古没有激活,这一回合就不会再叠。 - **加成怎么叠**:盟约、策略、装备、机变卡和特质给的「攻击力 / 防御力 / 生命值 +X%」与技能的「攻击力 +X%」**相加**后再乘到属性上(官方:直接乘算),例如精准 +130%、独行 +60%、一件 +40% 的装备合计 +230%,而不是 ×2.3×1.6×1.4。「伤害提升至 X%」「受到的伤害 +X%」(维多利亚、谢拉格、奥术、脆弱等)这类伤害倍率之间仍然相乘;但同名效果只算一个——同一战场两名玩家都开了「奥术」时,敌人身上只挂一层奥术易伤,取两人中较高的那一个(不再相乘);两名「灵知」的坚冰、两名「莱恩哈特」/「缄默德克萨斯」的法抗削减也一样只算最强的一个。「坚守」的反伤计入被打的那名成员(个人对领袖伤害统计里能看到)。 - 每局会随机**禁用**若干盟约(标准模拟较少),它们的干员不会出现在商店;开局的「确认本局信息」会列出,选择策略时(「查看禁用盟约与干员」)和对局中(左上角 🔍)也能再查看。 diff --git a/server/sim/content/bands/meta.js b/server/sim/content/bands/meta.js index cd1fe501..c2f7aa5e 100644 --- a/server/sim/content/bands/meta.js +++ b/server/sim/content/bands/meta.js @@ -19,6 +19,7 @@ // shop: onBuy — a free pick / grant never uses it up) // band_cost_coin_reach_cnt_gain_chess_from_pool 潘格尼尼 once coin_cnt funds spent in total: 1 chess of pool (elite 拉特兰 ≥ T4) // round_start_bond_check_gain_layer 余 round start of `round`: exactly factioncount active bonds → +count1, else each active +count2 +// — never to a bond without layers (noStack; the owner's decision of 2026-10-08) // up_shop_add_special_goods {count,choice,pool} 凯瑟琳 every level-up: pick 1 of `count` items of pool (free) // coin_carry_over {capital,interest,max} 坎诺特 leftover ≥ capital at round start → +min(max, ⌊left/capital⌋×interest) income // round_start_all_player_change_enemy_2 鸭爵 global: every alive player's battle from `round` (own + teammates; @@ -244,15 +245,22 @@ K.band_cost_coin_reach_cnt_gain_chess_from_pool = (ps) => ({ }, }); +/** + * 余 【文火慢炖】 「第8回合开始时,若仅激活了1个盟约,使其增加36层;否则使所有已激活盟约增加12层」. The owner's decision of 2026-10-08 + * overrides PRTS here (下半/PRTS盟约记录: layers of a bond that shows none 「仍然对其生效」): a bond without layers — bonds.json + * `noStack`: 绝技, 独行, 调和, 协防干员 — gets none. The count stays the sentence's (every active bond), so one active bond + * that is such a bond means nothing is added, and with two active bonds a layered one still gets count2. Only this + * strategy: 协防's 「使所有已激活的盟约层数」 (bonds/addon/meta.js) and 华法琳's 【重点监护】 keep adding to every bond they name. + */ K.round_start_bond_check_gain_layer = (ps) => ({ onRoundStart(ctx) { const p = ps[0]; if (ctx.round !== int(p.round, -1)) return; const active = Object.entries(ctx.bonds()).filter(([, b]) => b && b.active).map(([id]) => id); - if (active.length === int(p.factioncount, 1)) { - for (const b of active) ctx.addLayers(b, int(p.count1, 0), { requireActive: true, reason: 'band' }); - } else { - for (const b of active) ctx.addLayers(b, int(p.count2, 0), { requireActive: true, reason: 'band' }); + const n = active.length === int(p.factioncount, 1) ? int(p.count1, 0) : int(p.count2, 0); + for (const b of active) { + if (ctx.gd.bond(b)?.noStack) continue; + ctx.addLayers(b, n, { requireActive: true, reason: 'band' }); } }, }); diff --git a/test/content/bands.test.js b/test/content/bands.test.js index 783604f8..b1e9744a 100644 --- a/test/content/bands.test.js +++ b/test/content/bands.test.js @@ -302,6 +302,22 @@ test('余 文火慢炖: R8 round start — exactly 1 active bond +36 layers, oth cover('band_yu'); }); +test('余 文火慢炖 adds no layers to a bond without layers (noStack: 独行, 绝技 …) — the owner\'s decision of 2026-10-08', () => { + assert.deepEqual(Object.values(DATA.bonds).filter((b) => b.noStack).map((b) => b.name).sort(), ['协防干员', '独行', '绝技', '调和'].sort()); + for (const [bonus, want] of [ + [{ soloShip: 1 }, {}], // the one active bond is 独行: nothing at all + [{ suntShip: 5 }, {}], // … or 绝技 + [{ soloShip: 1, yanShip: 20 }, { yanShip: 12 }], // two active (the sentence's count): the layered one +12, 独行 none + ]) { + const s = setup({ band: 'band_yu' }); + Object.assign(s.ps.bondCountBonus, bonus); s.ps.recompute(); + for (const id of Object.keys(bonus)) assert.ok(s.ps.bonds[id]?.active, `${id} active`); + s.roundStart(8); + const got = Object.fromEntries(Object.entries(s.ps.layers).filter(([, v]) => v > 0)); + assert.deepEqual(got, want, JSON.stringify(bonus)); + } +}); + test('凯瑟琳 定向投放: every shop upgrade offers 3 different shop items (any tier — community report of 2026-10-06), 1 free pick', () => { const { m, ps } = setup({ band: 'band_cathy', seed: 9 }); for (const lvl of [2, 3]) {