feedback5 WE2: no hand card for 予愿安洁莉娜's “一会儿见!” — a summon no owner shows is not placeable (#24)

tools/build-data.mjs summonRecord: placeable also needs an owner that shows the summon
(the variants' display source, the owner's displayTokenDict). The S3 marker is the skill's
own object (PRTS 予愿安洁莉娜 S3 备注: the skill deploys it at her initial tile); every other
undisplayed summon is already HIDDEN. Regenerated offline: one path changed,
backups.tokens.token_10071_aglna2_agairp.placeable true -> false. The kit drops its
placed-marker branch (the skill always summons it). Golden: no scenario moved.
This commit is contained in:
sganggs committed 2026-10-06 15:10:59 +08:00
1 parent ad23320411
commit f50fd50273
7 files changed
+44 -36

No files matched your search

@@ -4,6 +4,8 @@
// hidden "TOKEN数" talent max_deploy_count / max_deck_stack_cnt on top of the attribute frame). Official counts: the owners'
// talents (麦哲伦 / 令 / 电弧 "最多同时部署3个", SUM-Y stage 2+ "最多同时部署4个", 白铁 / 娜斯提 "最多可部署2个", 望 "可以使用6枚
// 棋子", TRP-X +1), PRTS 幻影 备注 "最大可部署数量为3" (夜莺).
// #24: a summon no owner shows (displayTokenDict: the variants' `display` source) is its skill's own object, never a hand
// card — 予愿安洁莉娜 S3's “一会儿见!” (PRTS 予愿安洁莉娜 S3 备注: the skill deploys it at her initial tile).
// Run: node --test test/content/feedback5-we2-summon-hand.test.js
import { test } from 'node:test';
@@ -94,3 +96,26 @@ test('the data: deploy limit / holding = the attribute frame + the token talents
assert.equal(tokens.token_10041_cathy_catsld.variants.chess_char_4_11_a.stats.deployLimit, 2);
assert.equal(tokens.token_10000_silent_healrb.variants.chess_char_2_02_a.stats.deployLimit, 1);
});
test('#24 a summon no owner shows is never a hand card: 予愿安洁莉娜 S3\'s “一会儿见!” is not placeable, every placeable summon is displayed', () => {
const MARKER = 'token_10071_aglna2_agairp';
const AGLNA2 = 'char_1015_aglna2';
assert.equal(BACKUPS.tokens[MARKER].placeable, false);
const shows = (v) => (v.sources ?? []).includes('display') || Object.values(v.bySkill ?? {}).some((a) => (a.sources ?? []).includes('display'));
for (const t of [...Object.values(load('tokens')), ...Object.values(BACKUPS.tokens)]) {
if (t.kind !== 'summon') continue;
if (t.placeable) assert.ok(Object.values(t.variants).some(shows), `${t.tokenId} ${t.name}: placeable and displayed`);
else if (!Object.values(t.variants).some(shows)) assert.ok(t.displayType === 'HIDDEN' || t.tokenId === MARKER, `${t.tokenId} ${t.name}: undisplayed ⇒ HIDDEN (or the marker)`);
}
for (const tier of [5, 6]) {
for (const elite of [false, true]) {
const slot = diySlot(SLOT[tier], DATA);
const id = elite ? slot.goldenId : slot.baseId;
for (const skillIndex of [0, 1, 2]) {
const rec = diyRecord(SLOT[tier], { charId: AGLNA2, skillIndex, uniEquipId: null }, { elite, data: DATA });
const view = diyGameData(gd, new Map([[id, rec]]));
assert.deepEqual(view.placeableTokens(id, { skillIndex, moduleId: null }), [], `T${tier} ${elite ? 'elite' : 'normal'} S${skillIndex + 1}: no hand piece`);
}
}
}
});
+2 -16
View File
@@ -39,12 +39,11 @@ const ANY_ATK = (h, u) => h.hooksOf('damaged').filter((c) => c.source === u && c
const extras = (h, u) => h.hooksOf('damaged').filter((c) => c.source === u && (c.dmg?.tags || []).includes('aglna2:extra'));
/** 予愿安洁莉娜 as uid 1 at (row, col) facing RIGHT, plus `others`. */
function field({ tier = 5, elite = false, skill = 0, row = 10, col = 4, others = [], seed = 5, marker = null } = {}) {
const piece = marker ? [{ uid: 9, kind: 'token', tokenId: MARKER, ownerUid: 1, row: marker[0], col: marker[1] }] : [];
function field({ tier = 5, elite = false, skill = 0, row = 10, col = 4, others = [], seed = 5 } = {}) {
const h = makeBattle({
defs: { enemies: ENEMIES }, timeLimit: 900, autoFinish: false, seed,
flags: { dpPerSec: 0, dpMax: 999 }, hooks: ['damaged', 'skillStart', 'skillEnd', 'statusApplied', 'deploy', 'dodge'], captureNoisy: true,
units: [{ uid: 1, diy: { slot: SLOT[tier], charId: AGL, skillIndex: skill }, elite, row, col }, ...piece, ...others],
units: [{ uid: 1, diy: { slot: SLOT[tier], charId: AGL, skillIndex: skill }, elite, row, col }, ...others],
});
h.step();
return { h, u: h.unit(1) };
@@ -349,19 +348,6 @@ test('S3 move: blocking nothing, she flies (2 tiles/s, 无敌, disarmed) to the
assert.equal(u.extraRangeKeys, null);
done(h);
}
// a placed “一会儿见!” piece never deploys by itself; it is the marker
{
const { h, u } = field({ tier: 6, elite: true, skill: 2, marker: [12, 9] });
const piece = h.b.allyUnits.find((t) => t.kind === 'token' && t.uid === 9);
assert.ok(piece && !piece.alive && piece.deferDeploy, 'not deployed at the start');
u.skill.gainSp(999);
h.spawn('enemy_fly', { pos: [11, 7] });
assert.ok(h.runUntil(() => u.tileR === 11 && u.tileC === 7, 5));
assert.ok(piece.alive && piece.tileR === 10 && piece.tileC === 4, 'the piece marks her deployment tile');
u.skill.end('test');
assert.ok(!piece.alive && !piece.removed, 'withdrawn, kept as a piece');
done(h);
}
// blocking something, she stays
{
const { h, u } = field({ tier: 5, skill: 2 });