feedback6: merge fb6-small-fixes (see its commits)
This commit is contained in:
commit
3f918c9f03
21 files changed
+398
-91
No files matched your search
@@ -0,0 +1,65 @@
|
||||
// PR #262 (#261 its closed duplicate): an operator's 凋亡 burst — PRTS 元素 "立即获得等时长的阻回、静默,该阻回、静默持续期间
|
||||
// 每秒损失1点技力并受到100点无来源法术持续伤害" — drains the official 技力, stored charges included: PRTS 技能 可充能 "当持有者
|
||||
// 的技力流失时,充能次数也会实时降低". The drain took only the SP towards the next charge, so a full skill (sp = cost with
|
||||
// every charge stored) kept all its charges — a one-charge skill stayed ready through the whole burst. An active timed
|
||||
// skill is left alone (its SP was spent at the cast; Skill.setSpTotal leaves it too).
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { makeBattle, chessRec, checkInvariants } from '../helpers/battleHarness.js';
|
||||
import { hasGeneratedData } from '../../server/sim/simdata.js';
|
||||
|
||||
const REAL = { skip: !hasGeneratedData() };
|
||||
const SNOW = 'chess_char_3_11_b'; // 精锐 雪猎: S2 风雪连弩, MANUAL, 可充能2次, 14 SP per charge
|
||||
|
||||
function arena(units, defs = {}) {
|
||||
const h = makeBattle({ defs, units, autoFinish: false, timeLimit: 120, hooks: ['spGain', 'damaged'] });
|
||||
h.step();
|
||||
return h;
|
||||
}
|
||||
const burst = (h, u) => {
|
||||
h.b.dealDamage(null, u, { type: 'element', element: 'apoptosis', amount: u.gaugeMax });
|
||||
assert.ok(u.findBuff('apoptosisBurst'), '凋亡 bursts');
|
||||
};
|
||||
|
||||
test('PR #262: 凋亡 drains a charge skill\'s stored charges — 精锐 雪猎 with both charges loses one at the first second and is empty after 15', REAL, () => {
|
||||
const h = arena([{ chessId: SNOW, row: 10, col: 4 }]);
|
||||
const u = h.unit(SNOW), sk = u.skill;
|
||||
assert.equal(sk.maxCharges, 2);
|
||||
const cost = sk.spCost;
|
||||
sk.setSpTotal(2 * cost);
|
||||
assert.deepEqual([sk.charges, sk.sp, sk.spTotal], [2, cost, 2 * cost], 'both charges stored');
|
||||
burst(h, u);
|
||||
h.run(1.01);
|
||||
assert.deepEqual([sk.charges, sk.sp, sk.spTotal], [1, cost - 1, 2 * cost - 1], 'one second: −1 技力, the second charge goes');
|
||||
assert.equal(sk.ready, true, 'one charge left');
|
||||
h.run(14);
|
||||
// (the burst ends with its 15th second: the time SP of the ticks since then is back)
|
||||
assert.equal(sk.charges, 0, '15 seconds: −15 技力 — the last charge gone too');
|
||||
assert.ok(Math.abs(sk.spTotal - (2 * cost - 15)) < 0.1, `${sk.spTotal} ≈ ${2 * cost - 15}`);
|
||||
assert.equal(sk.ready, false);
|
||||
assert.equal(sk.activations, 0, '静默: no cast through the burst');
|
||||
assert.ok(!u.findBuff('apoptosisBurst'), 'the burst is over');
|
||||
checkInvariants(h.b);
|
||||
});
|
||||
|
||||
test('PR #262: a full one-charge skill is no longer ready after the first second of 凋亡; an active timed skill keeps its state', () => {
|
||||
const op = chessRec({ id: 't_apo', stats: { maxHp: 1e5, spRecovery: 0 }, skill: { spCost: 20, initSp: 0, duration: 30, durationType: 'NONE' } });
|
||||
const h = arena([{ chessId: 't_apo', row: 10, col: 4, uid: 1 }, { chessId: 't_apo', row: 10, col: 6, uid: 2 }], { chess: { t_apo: op } });
|
||||
const a = h.unit(1), b = h.unit(2);
|
||||
a.skill.setSpTotal(20);
|
||||
assert.equal(a.skill.ready, true);
|
||||
burst(h, a);
|
||||
h.run(1.01);
|
||||
assert.deepEqual([a.skill.charges, a.skill.sp, a.skill.ready], [0, 19, false], 'the ready charge is part of the 技力 it loses');
|
||||
h.run(14);
|
||||
assert.equal(a.skill.spTotal, 5, '−15 技力 in all');
|
||||
assert.equal(h.hooksOf('spGain').length, 0, 'the drain is no SP gain (no spGain hook)');
|
||||
// a running timed skill: its SP was spent at the cast — nothing to drain, and it runs on (the burst silences new casts only)
|
||||
b.skill.setSpTotal(20);
|
||||
assert.ok(b.skill.activate('test'));
|
||||
const before = [b.skill.active, b.skill.charges, b.skill.sp];
|
||||
burst(h, b);
|
||||
h.run(3);
|
||||
assert.deepEqual([b.skill.active, b.skill.charges, b.skill.sp], before);
|
||||
checkInvariants(h.b);
|
||||
});
|
||||
@@ -1124,6 +1124,28 @@ test('Touch talents: 攫升 +3 SP to the healed unit, 超脱 +5 SP when an opera
|
||||
checkInvariants(h.b);
|
||||
});
|
||||
|
||||
test('GitHub #260: the 外勤医疗 Touch casts 恳切福音 on an injured ally only inside the skill\'s 5-2 (ACTIVE_RANGE, as the 补位 Touch); a full-HP or unhealable one does not', REAL, () => {
|
||||
// Touch stands on (10,2) facing right: her 3-3 reaches column 5, the skill's 5-2 column 7
|
||||
const h = makeBattle({ stageId: 'act2autochess_m01', defs: { chess: { test_guard: guard({ stats: { maxHp: 10000, atk: 0 } }) } },
|
||||
units: [{ chessId: 'test_guard', row: 10, col: 7 }], autoFinish: false, timeLimit: 60 });
|
||||
h.step();
|
||||
const touch = spawnMapChar(h.b, 'p1', TOKEN_IDS.touch);
|
||||
assert.deepEqual([touch.tileR, touch.tileC], [10, 2]);
|
||||
assert.equal(touch.skill.rule, 'ACTIVE_RANGE');
|
||||
const ally = h.unit('test_guard');
|
||||
touch.skill.gainSp(1000);
|
||||
h.run(3);
|
||||
assert.equal(touch.skill.activations, 0, 'every ally at full HP: no cast');
|
||||
ally.hp = 4000;
|
||||
const buff = h.b.addBuff(ally, { key: 'test:noHeal', flags: { noHeal: true } });
|
||||
h.run(2);
|
||||
assert.equal(touch.skill.activations, 0, 'an ally no heal can pick: no cast');
|
||||
h.b.removeBuff(ally, buff);
|
||||
assert.ok(h.runUntil(() => touch.skill.activations === 1, 2), 'the injured ally five tiles ahead (outside her 3-3) casts the skill');
|
||||
assert.ok(h.runUntil(() => ally.hp > 4000, 5), 'and she heals it from the larger range');
|
||||
checkInvariants(h.b);
|
||||
});
|
||||
|
||||
test('spawnMapChar: per-player slots — unite: p1 #1 (10,2), p2 its multi-only slot (10,10); boss: L (3,2), R (3,18); solo never multi-only', REAL, () => {
|
||||
const players = [
|
||||
{ playerId: 'p1', seat: 0, side: 'L', colOffset: 0, units: [], bonds: {} },
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
// .gitignore keeps per-machine state out of the repository (and so out of the release packages, which ship tracked
|
||||
// files only: tools/package.mjs). GitHub #258: a local npm cache (`npm_config_cache=./.npm-cache`, `npm ci --cache
|
||||
// .npm-cache`) must never be committed by any contributor.
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { execFileSync } from 'node:child_process';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
||||
const lines = readFileSync(path.join(ROOT, '.gitignore'), 'utf8').split(/\r?\n/).map((l) => l.trim());
|
||||
|
||||
/** git's own verdict on a path (null when git or the repository is not available). */
|
||||
function ignored(rel) {
|
||||
try {
|
||||
execFileSync('git', ['check-ignore', '-q', '--no-index', rel], { cwd: ROOT, stdio: 'ignore' });
|
||||
return true;
|
||||
} catch (e) {
|
||||
return e && e.status === 1 ? false : null;
|
||||
}
|
||||
}
|
||||
|
||||
test('GitHub #258: the local npm cache (.npm-cache/) is ignored, like node_modules/ and .cache/', () => {
|
||||
for (const entry of ['.npm-cache/', 'node_modules/', '.cache/']) assert.ok(lines.includes(entry), `.gitignore lists ${entry}`);
|
||||
for (const rel of ['.npm-cache/_cacache/index-v5/00/aa', '.npm-cache/_logs/debug-0.log']) {
|
||||
const v = ignored(rel);
|
||||
if (v !== null) assert.equal(v, true, `${rel} is ignored`);
|
||||
}
|
||||
assert.notEqual(ignored('package.json'), true, 'a tracked file is not');
|
||||
});
|
||||
+20
-20
@@ -2382,7 +2382,7 @@
|
||||
"hooks": [1,129,6242,303,303,643,724,1632,21,124,15,15,0,5917,2,46,105,103,1,21,0,13,0],
|
||||
"events": {"atk":309,"deploy":21,"die":21,"dmg":681,"engage":10,"fx":124,"heal":41,"leak":103,"skill":30,"spawn":120,"status":46},
|
||||
"fx": {"aoe":24,"beam":20,"burst":13,"crit":2,"explode":1,"healField":10,"shield":9,"thorns":45},
|
||||
"snaps": "8af17d6a 024bce8c e0452b2c 5af87abd 42a1f8a9 0b71523e 3fd3e515 fa3770c9 2ca7b522 c32eaf65 dffbf1b7 224a00a2 994934f9 5bc28beb 05894548 582c0f90 dd02f272 cbdb633c 2fb767c6 ad6a50e0 205812fb"
|
||||
"snaps": "8af17d6a c4ee14aa b0c6352a 4663534b ad4f6c57 79103640 6a18ed37 6ce034df 01e7e370 1a22aca7 2ab6744d 07e795ec 55eb2147 66c813ad 16426e3e 9e7597da 454aaf0c ba882526 bb829c2c 99b4e6c6 a4e6b5a1"
|
||||
},
|
||||
"diy-059": {
|
||||
"about": "5_diy1_b=shu/S1/002_shu 5_diy2_b=shu/S2/002_shu 5_diy1_b=shu/S3/002_shu 6_diy1_a=shu/S1 6_diy2_a=shu/S2 6_diy1_a=shu/S3 6_diy2_b=shu/S1 6_diy1_b=shu/S2 6_diy2_b=shu/S3 6_diy1_b=shu/S1/002_shu 6_diy2_b=shu/S2/002_shu 6_diy1_b=shu/S3/002_shu",
|
||||
@@ -2396,35 +2396,35 @@
|
||||
"time": 230,
|
||||
"ticks": 6900,
|
||||
"reason": "timeout",
|
||||
"killed": 39,
|
||||
"killed": 47,
|
||||
"total": 96,
|
||||
"unspawned": 0,
|
||||
"bossHpLeft": null,
|
||||
"rngDraws": 0,
|
||||
"errors": {"count":0,"kinds":[]},
|
||||
"players": {"p1":{"killed":39,"total":96,"perfect":false,"leaks":57,"leaksUncounted":0,"coins":0,"dmg":234243,"bossDmg":0,"heal":203629,"deaths":18,"layerGains":{}}},
|
||||
"players": {"p1":{"killed":47,"total":96,"perfect":false,"leaks":49,"leaksUncounted":0,"coins":0,"dmg":231786,"bossDmg":0,"heal":217108,"deaths":15,"layerGains":{}}},
|
||||
"units": [
|
||||
["p1",1,"op","chess_char_5_diy1_b",0,"uniequip_002_shu",0,0,103,2,14695,21669,15436,64,11],
|
||||
["p1",2,"op","chess_char_5_diy2_b",1,"uniequip_002_shu",0,0,119,0,7297,21517,15906,36,1],
|
||||
["p1",3,"op","chess_char_5_diy1_b",2,"uniequip_002_shu",3070,1,120,6,14925,16583,5503,77,1],
|
||||
["p1",4,"op","chess_char_6_diy1_a",0,null,0,0,99,1,7880,21342,8555,56,6],
|
||||
["p1",5,"op","chess_char_6_diy2_a",1,null,0,0,101,0,5224,32777,48418,50,2],
|
||||
["p1",6,"op","chess_char_6_diy1_a",2,null,0,0,77,2,11366,9710,12836,42,1],
|
||||
["p1",7,"op","chess_char_6_diy2_b",0,"none",2791.49,1,107,5,36418,40843,15790,135,9],
|
||||
["p1",8,"op","chess_char_6_diy1_b",1,"none",0,0,102,2,16600,20626,10010,73,1],
|
||||
["p1",9,"op","chess_char_6_diy2_b",2,"none",0,0,5,5,15654,5050,26206,69,2],
|
||||
["p1",10,"op","chess_char_6_diy1_b",0,"uniequip_002_shu",0,0,8,0,14640,10510,10285,43,6],
|
||||
["p1",11,"op","chess_char_6_diy2_b",1,"uniequip_002_shu",0,0,10,6,39992,33225,14891,106,1],
|
||||
["p1",12,"op","chess_char_6_diy1_b",2,"uniequip_002_shu",3180,1,116,7,49553,20305,19793,109,2],
|
||||
["p1",1,"op","chess_char_5_diy1_b",0,"uniequip_002_shu",0,0,106,1,16402,16000,9569,59,5],
|
||||
["p1",2,"op","chess_char_5_diy2_b",1,"uniequip_002_shu",2945.74,1,119,0,5494,19342,17088,32,2],
|
||||
["p1",3,"op","chess_char_5_diy1_b",2,"uniequip_002_shu",3070,1,120,5,16030,16314,5378,80,1],
|
||||
["p1",4,"op","chess_char_6_diy1_a",0,null,2313,1,100,2,12751,26007,6577,66,2],
|
||||
["p1",5,"op","chess_char_6_diy2_a",1,null,2057.85,1,103,1,13344,39122,47357,75,2],
|
||||
["p1",6,"op","chess_char_6_diy1_a",2,null,0,0,77,2,11366,9681,12807,42,1],
|
||||
["p1",7,"op","chess_char_6_diy2_b",0,"none",2183.12,1,102,6,34558,41766,13074,133,5],
|
||||
["p1",8,"op","chess_char_6_diy1_b",1,"none",0,0,99,2,16300,33752,26299,85,2],
|
||||
["p1",9,"op","chess_char_6_diy2_b",2,"none",0,0,5,5,16102,3554,24484,71,2],
|
||||
["p1",10,"op","chess_char_6_diy1_b",0,"uniequip_002_shu",0,0,8,1,6712,7983,4179,20,1],
|
||||
["p1",11,"op","chess_char_6_diy2_b",1,"uniequip_002_shu",0,0,10,5,35380,29094,14012,94,1],
|
||||
["p1",12,"op","chess_char_6_diy1_b",2,"uniequip_002_shu",3180,1,115,9,47347,18313,36285,106,2],
|
||||
["-","~1","device","trap_1105_accrate",null,null,100,1,1,0,0,0,0,0,null],
|
||||
["-","~2","device","trap_1105_accrate",null,null,100,1,2,0,0,0,0,0,null],
|
||||
["-","~3","device","trap_1105_accrate",null,null,100,1,3,0,0,0,0,0,null]
|
||||
],
|
||||
"enemies": {"enemy_1229_darmy":[27,13,14,45139,72535],"enemy_1229_darmy_2":[57,26,31,120688,198119],"enemy_9007_acelem":[12,0,11,69460,101381]},
|
||||
"hooks": [1,120,6900,1449,1449,4412,4696,22580,57,113,43,42,0,15690,0,93,96,56,1,57,0,39,0],
|
||||
"events": {"atk":1500,"deploy":21,"die":57,"dmg":4696,"engage":12,"fx":181,"heal":328,"leak":56,"skill":85,"spawn":111,"status":105},
|
||||
"fx": {"beam":18,"burst":39,"healField":47,"teleport":77},
|
||||
"snaps": "8dc1b37a b5460f3d 3555fcc6 db56014a a0553a57 f4dca0ac f05a71e9 77e33494 98645a14 e2eefd2d bd5020fc d9664555 4c789e18 d251cfc2 3e54ab89 a00b133e 02012e0d 11dc3504 389257ff 0e7213e4 96b7c324 1b69e292 0f8b3ea2"
|
||||
"enemies": {"enemy_1229_darmy":[27,15,12,48739,79249],"enemy_1229_darmy_2":[57,32,23,133695,210887],"enemy_9007_acelem":[12,0,10,58192,72262]},
|
||||
"hooks": [1,120,6900,1513,1513,4343,4631,22639,62,107,26,25,0,15564,0,93,96,45,1,62,0,37,0],
|
||||
"events": {"atk":1572,"deploy":21,"die":62,"dmg":4631,"engage":12,"fx":189,"heal":335,"leak":45,"skill":51,"spawn":111,"status":101},
|
||||
"fx": {"beam":18,"burst":37,"healField":49,"teleport":85},
|
||||
"snaps": "8dc1b37a b5460f3d 3ef6a531 1b763d75 2ca58274 c2fef8fd afccd50e 9e6a1580 6921be5e a89eb8c3 950cf27b 18a4160c e6764ecc cf15dcc9 dbfe2e1c fd2de4b2 aaaf0692 702a1a56 289559cc 2f1168ca 69dba497 ce110259 f0b47a01"
|
||||
},
|
||||
"diy-060": {
|
||||
"about": "5_diy1_a=pallas/S1 5_diy2_a=pallas/S2 5_diy1_a=pallas/S3 5_diy2_b=pallas/S1 5_diy1_b=pallas/S2 5_diy2_b=pallas/S3 5_diy1_b=pallas/S1/002_pallas 5_diy2_b=pallas/S2/002_pallas 5_diy1_b=pallas/S3/002_pallas 5_diy2_b=pallas/S1/003_pallas 5_diy1_b=pallas/S2/003_pallas 5_diy2_b=pallas/S3/003_pallas",
|
||||
|
||||
+17
-17
@@ -375,7 +375,7 @@
|
||||
"hooks": [1,42,6000,387,387,643,1580,796,20,24,80,78,20,17921,1173,2,19,0,1,139,0,1,0],
|
||||
"events": {"atk":405,"deploy":17,"die":24,"dmg":733,"engage":8,"fx":203,"heal":59,"skill":158,"spawn":36,"status":179},
|
||||
"fx": {"anchor":1,"aoe":3,"beam":6,"burst":1,"candle":3,"ember":3,"explode":104,"healAoe":34,"overload":4,"phase":12,"revive":1,"splash":20,"substitute":1,"summon":6,"swap":1,"telegraph":1,"teleport":2},
|
||||
"snaps": "87076623 3c36dd04 03a89072 745a7c6b 24a96213 0ed332a6 26e97a3b 2b49b7d6 376df693 78dab18f 1b931756 f174873b d4541524 71b41d30 2da111bb 5c2d56c1 fa32d0c4 f6866cb6 7c0b0632 9a7cccfc"
|
||||
"snaps": "87076623 3c36dd04 03a89072 745a7c6b 24a96213 0ed332a6 26e97a3b 2b49b7d6 4deb0556 087cdcb6 79fbf5f7 dfe3d106 fdaa7bd5 af470bb9 c87c0fc2 ed37f880 df193341 1e30dddf 21a08fc7 5270e9dd"
|
||||
},
|
||||
"boss-boss_4-pair": {
|
||||
"about": "盐风主教昆图斯 pair pool 8400000: chess_char_5_19_b chess_char_4_01_b chess_char_5_14_b chess_char_5_17_b chess_char_5_15_b chess_char_5_20_b chess_char_5_21_b chess_char_5_22_b chess_char_5_23_b chess_char_4_02_b | chess_char_4_11_b chess_char_4_04_b chess_char_4_07_b chess_char_4_16_b chess_char_4_09_b chess_char_4_06_b chess_char_4_10_b chess_char_4_12_b chess_char_4_13_b chess_char_4_14_b token_10041_cathy_catsld token_10041_cathy_catsld",
|
||||
@@ -1283,8 +1283,8 @@
|
||||
"enemy_9022_acdumm": [1,0,0,478,0],
|
||||
"enemy_9023_acdums": [12,12,0,25367,120]
|
||||
},
|
||||
"hooks": [1,53,6000,1112,1250,2538,2725,6368,26,28,66,63,0,29865,1406,6,18,0,1,28,0,10,0],
|
||||
"events": {"atk":1217,"deploy":33,"die":28,"dmg":2714,"engage":14,"fx":1020,"heal":66,"skill":129,"spawn":42,"status":675},
|
||||
"hooks": [1,53,6000,1112,1250,2538,2725,6368,26,28,66,63,0,29862,1406,6,18,0,1,28,0,10,0],
|
||||
"events": {"atk":1217,"deploy":33,"die":28,"dmg":2714,"engage":14,"fx":1020,"heal":66,"skill":129,"spawn":42,"status":683},
|
||||
"fx": {
|
||||
"beam": 13,
|
||||
"blink": 2,
|
||||
@@ -1321,7 +1321,7 @@
|
||||
"weightless": 5,
|
||||
"zone": 76
|
||||
},
|
||||
"snaps": "a3593c93 05df9199 329883cc 83065c46 6d189e2d d27e20b7 d0119d66 53c297b8 408cec99 65434e27 1d704b57 5517a58b dc7344d6 58d4ad2b b8585956 3bb8237c 89be2434 4474d986 12d9ba25 a4ab8999"
|
||||
"snaps": "a3593c93 05df9199 329883cc 83065c46 6d189e2d d27e20b7 d0119d66 53c297b8 408cec99 65434e27 1d704b57 5517a58b dc7344d6 58d4ad2b b8585956 eedd57cd 2c69cc89 3e330a00 d5d56836 2efc2732"
|
||||
},
|
||||
"hidden-boss_10-solo": {
|
||||
"about": "假想敌:管 solo pool 7600000: chess_char_4_17_b chess_char_4_18_b chess_char_4_23_b chess_char_4_19_b chess_char_4_22_b chess_char_4_20_b chess_char_4_21_b chess_char_4_24_b chess_char_4_25_b chess_char_4_26_b",
|
||||
@@ -1339,32 +1339,32 @@
|
||||
"total": 13,
|
||||
"unspawned": 0,
|
||||
"bossHpLeft": 7156236,
|
||||
"rngDraws": 28,
|
||||
"rngDraws": 27,
|
||||
"errors": {"count":0,"kinds":[]},
|
||||
"players": {"p1":{"killed":12,"total":13,"perfect":false,"leaks":1,"leaksUncounted":0,"coins":0,"dmg":595215,"bossDmg":443764,"heal":73194,"deaths":0,"layerGains":{}}},
|
||||
"players": {"p1":{"killed":12,"total":13,"perfect":false,"leaks":1,"leaksUncounted":0,"coins":0,"dmg":595215,"bossDmg":443764,"heal":72505,"deaths":0,"layerGains":{}}},
|
||||
"units": [
|
||||
["p1",1,"op","chess_char_4_17_b",1,"uniequip_002_hsguma",3513,1,4,1,1,0,0,1,0],
|
||||
["p1",2,"op","chess_char_4_18_b",1,"uniequip_002_mudrok",7440.8,1,6,0,5,3861,4102,5,1],
|
||||
["p1",3,"op","chess_char_4_23_b",2,"uniequip_002_gvial2",4147.8,1,7,4,193323,7944,2803,230,5],
|
||||
["p1",2,"op","chess_char_4_18_b",1,"uniequip_002_mudrok",7440.8,1,6,0,5,3861,4169,5,0],
|
||||
["p1",3,"op","chess_char_4_23_b",2,"uniequip_002_gvial2",4147.8,1,7,4,193323,7934,2790,230,5],
|
||||
["p1",4,"op","chess_char_4_19_b",2,"uniequip_002_flamtl",3600.6,1,5,0,0,2336,0,0,0],
|
||||
["p1",5,"op","chess_char_4_22_b",2,"uniequip_002_svrash",3905.8,1,8,7,206512,35880,6134,154,3],
|
||||
["p1",5,"op","chess_char_4_22_b",2,"uniequip_002_svrash",3905.8,1,8,7,206512,35241,6004,154,3],
|
||||
["p1",6,"op","chess_char_4_20_b",2,"uniequip_002_fartth",1419,1,1,0,170086,0,0,70,7],
|
||||
["p1",7,"op","chess_char_4_21_b",1,"uniequip_002_plosis",2920.8,1,9,0,0,4595,39389,67,2],
|
||||
["p1",7,"op","chess_char_4_21_b",1,"uniequip_002_plosis",2920.8,1,9,0,0,4595,39464,67,2],
|
||||
["p1",8,"op","chess_char_4_24_b",1,"uniequip_002_billro",2178,1,2,0,25288,0,0,20,1],
|
||||
["p1",9,"op","chess_char_4_25_b",2,"uniequip_002_cetsyr",1671,1,10,0,0,16053,3215,0,3],
|
||||
["p1",10,"op","chess_char_4_26_b",0,"uniequip_002_bldsk",1522,1,3,0,0,2241,17551,29,6]
|
||||
["p1",9,"op","chess_char_4_25_b",2,"uniequip_002_cetsyr",1671,1,10,0,0,15953,3078,0,3],
|
||||
["p1",10,"op","chess_char_4_26_b",0,"uniequip_002_bldsk",1522,1,3,0,0,2241,17000,28,6]
|
||||
],
|
||||
"enemies": {
|
||||
"enemy_1005_yokai_3": [1,0,1,13187,65325],
|
||||
"enemy_9010_acpupp": [2,2,0,25403,86026],
|
||||
"enemy_9021_acduml_2": [1,0,0,0,443764],
|
||||
"enemy_9022_acdumm": [1,0,0,1006,0],
|
||||
"enemy_9023_acdums": [10,10,0,29635,100]
|
||||
"enemy_9023_acdums": [10,10,0,28891,100]
|
||||
},
|
||||
"hooks": [1,25,6000,614,614,1220,1745,4474,12,13,28,26,0,15177,45,8,15,1,1,18,0,7,0],
|
||||
"events": {"atk":746,"deploy":10,"die":12,"dmg":1740,"engage":6,"fx":464,"heal":136,"leak":1,"skill":56,"spawn":25,"status":248},
|
||||
"fx": {"bandage":6,"beam":15,"burst":7,"ember":2,"explode":188,"featherArrow":7,"garrisonGrant":1,"healField":2,"jungleSoul":5,"mote":68,"phase":29,"redistribute":40,"reweave":3,"rockslide":1,"sandChainsCharged":1,"shieldBreak":7,"slash":60,"spGift":9,"summon":8,"telegraph":2,"truesilver":3},
|
||||
"snaps": "e9089456 d56595f6 94862b5d c7e389c2 97042251 346900c6 d3f1fdf3 ee72f858 3559a133 032bf766 7d5d0f98 ab1e397a ca88665f 19e0cc43 4f90670f aa7bdb4e f43775ca a84c46d1 705ff5fd 5b7831a7"
|
||||
"hooks": [1,25,6000,613,613,1210,1727,4456,12,13,27,25,0,15178,45,7,15,1,1,18,0,7,0],
|
||||
"events": {"atk":746,"deploy":10,"die":12,"dmg":1722,"engage":6,"fx":460,"heal":135,"leak":1,"skill":54,"spawn":25,"status":248},
|
||||
"fx": {"bandage":6,"beam":15,"burst":7,"ember":2,"explode":185,"featherArrow":7,"garrisonGrant":1,"healField":2,"jungleSoul":5,"mote":68,"phase":29,"redistribute":40,"reweave":3,"sandChainsCharged":1,"shieldBreak":7,"slash":60,"spGift":9,"summon":8,"telegraph":2,"truesilver":3},
|
||||
"snaps": "e9089456 d56595f6 94862b5d c7e389c2 97042251 346900c6 d3f1fdf3 ee72f858 76fb6eac 826bd52d 00497c63 de189efc 37b5cbcd ab1762e2 8644257f 4db1c850 efe502ae b7764884 f14f9be1 89f56bcc"
|
||||
},
|
||||
"unite-1": {
|
||||
"about": "联防 1 helper(s), 11 leaked: chess_char_6_03_b chess_char_6_06_b chess_char_6_07_b chess_char_6_01_b chess_char_6_02_b chess_char_6_04_b chess_char_6_05_b chess_char_6_08_b token_10017_skadi2_dedant",
|
||||
|
||||
+12
-12
@@ -1493,7 +1493,7 @@
|
||||
"boost": null,
|
||||
"setup": {"stageId":"act1autochess_m01","bossId":"boss_5","hiddenBossId":"boss_10","factions":["DOT","INVISIBLE","REFLECTION"]},
|
||||
"end": {"victory":true,"roundsPassed":14,"hiddenReached":false,"hiddenCleared":false,"reason":"victory","teamLp":28,"bossPoolLeft":0,"virtualMs":119900},
|
||||
"rng": {"setup":25,"shop":525,"waves":0,"draft":34,"bots":18074,"meta":23},
|
||||
"rng": {"setup":25,"shop":525,"waves":0,"draft":34,"bots":18080,"meta":23},
|
||||
"errors": {"engine":0,"logged":0,"sim":0,"dispatcher":0},
|
||||
"rounds": [
|
||||
{
|
||||
@@ -1548,18 +1548,18 @@
|
||||
},
|
||||
{
|
||||
"round": 11,
|
||||
"h_0": [1,26,12,0,2,5,8,"a1840a82",60,"arcaneShip 0/7, kazimierzShip 0/8, miraShip 1/4, preciShip 0/19, siracusaShip 1/18, skillfulShip 1/0, soloShip 1/0, suntShip 1/0, swiftShip 1/38, yanShip 0/13",20,25,5,102],
|
||||
"ai_0": [1,23,13,0,0,5,8,"e76ee4ed",224,"arcaneShip 0/2, deputShip 1/30, kazimierzShip 0/8, lateranoShip 1/39, miraShip 1/4, preciShip 0/2, raidShip 0/2, sargonShip 0/2, siracusaShip 1/40, skillfulShip 1/52, suntShip 1/12, swiftShip 1/47",25,25,0,98]
|
||||
"h_0": [1,25,12,0,2,5,8,"a1840a82",60,"arcaneShip 0/7, kazimierzShip 0/8, miraShip 1/4, preciShip 0/19, siracusaShip 1/18, skillfulShip 1/0, soloShip 1/0, suntShip 1/0, swiftShip 1/38, yanShip 0/13",20,25,5,102],
|
||||
"ai_0": [1,23,13,0,0,5,8,"e76ee4ed",226,"arcaneShip 0/2, deputShip 1/30, kazimierzShip 0/8, lateranoShip 1/41, miraShip 1/4, preciShip 0/2, raidShip 0/2, sargonShip 0/2, siracusaShip 1/40, skillfulShip 1/52, suntShip 1/12, swiftShip 1/47",25,25,0,98]
|
||||
},
|
||||
{
|
||||
"round": 12,
|
||||
"h_0": [1,26,14,0,0,6,8,"efcfaab5",123,"arcaneShip 0/7, kazimierzShip 0/8, miraShip 1/18, preciShip 1/24, siracusaShip 1/34, soloShip 1/0, suntShip 1/0, swiftShip 1/47, yanShip 0/13",15,31,16,116],
|
||||
"ai_0": [1,23,12,0,1,6,8,"3f2e303b",264,"arcaneShip 0/2, deputShip 1/32, kazimierzShip 0/8, lateranoShip 1/59, miraShip 1/6, preciShip 0/2, raidShip 0/2, sargonShip 0/2, siracusaShip 1/42, skillfulShip 1/62, suntShip 1/14, swiftShip 1/49",31,31,0,112]
|
||||
"h_0": [1,25,14,0,0,6,8,"2d442d6d",115,"arcaneShip 0/7, kazimierzShip 0/8, miraShip 1/14, preciShip 1/24, siracusaShip 1/30, soloShip 1/0, suntShip 1/0, swiftShip 1/47, yanShip 0/13",21,31,10,116],
|
||||
"ai_0": [1,23,12,0,1,6,8,"fcca8b16",266,"arcaneShip 0/2, deputShip 1/32, kazimierzShip 0/8, lateranoShip 1/61, miraShip 1/6, preciShip 0/2, raidShip 0/2, sargonShip 0/2, siracusaShip 1/42, skillfulShip 1/62, suntShip 1/14, swiftShip 1/49",31,31,0,112]
|
||||
},
|
||||
{
|
||||
"round": 13,
|
||||
"h_0": [1,16,12,0,2,6,8,"31530f99",169,"arcaneShip 0/7, kazimierzShip 0/8, miraShip 1/30, preciShip 1/33, raidShip 1/0, sargonShip 1/9, siracusaShip 1/46, suntShip 1/0, swiftShip 1/51, yanShip 0/13",8,57,49,130],
|
||||
"ai_0": [1,13,13,0,2,6,8,"38248b3d",204,"arcaneShip 0/2, deputShip 0/32, kazimierzShip 0/8, lateranoShip 1/73, miraShip 1/6, preciShip 1/2, raidShip 0/2, sargonShip 0/2, siracusaShip 1/54, skillfulShip 0/68, suntShip 1/14, swiftShip 1/55",7,57,50,127]
|
||||
"h_0": [1,15,12,0,2,6,8,"bd084a10",173,"arcaneShip 0/7, kazimierzShip 0/8, miraShip 1/20, preciShip 1/46, raidShip 1/0, sargonShip 1/22, siracusaShip 1/34, suntShip 1/0, swiftShip 1/51, yanShip 0/13",10,57,47,130],
|
||||
"ai_0": [1,13,13,0,2,6,8,"e6104ee6",194,"arcaneShip 0/2, deputShip 0/38, kazimierzShip 0/8, lateranoShip 1/69, miraShip 1/6, preciShip 1/2, raidShip 0/2, sargonShip 0/2, siracusaShip 1/54, skillfulShip 0/68, suntShip 1/14, swiftShip 1/49",12,57,45,127]
|
||||
}
|
||||
],
|
||||
"players": {
|
||||
@@ -1573,9 +1573,9 @@
|
||||
"title": {"id":"comment_4","name":"精英云集","picId":"comment_icon_4","text":"晋升精锐次数最多"},
|
||||
"trophies": 4,
|
||||
"reward": 400,
|
||||
"stats": {"activatedLayers":189,"bossDamage":277141,"dmgDealt":2376575,"gold":144,"itemsEquipped":20,"kills":238,"leaks":76,"lpLost":12,"merges":6,"perfectRounds":9,"refreshes":24},
|
||||
"stats": {"activatedLayers":193,"bossDamage":239043,"dmgDealt":2465246,"gold":144,"itemsEquipped":20,"kills":246,"leaks":68,"lpLost":13,"merges":6,"perfectRounds":9,"refreshes":24},
|
||||
"lineup": ["5_10_a@12,3[1_02_e_b]","5_15_a@11,3[3_11_e_a]","3_13_b@11,8[1_01_e_a]","3_19_b@10,3[4_07_e_a+3_01_e_a]","4_16_a@10,7[4_03_e_b+3_07_e_a]","1_08_b@10,8[4_11_e_b+4_02_e_a]","6_05_a@9,8[6_09_e_a+6_01_e_b]","5_02_a@9,9"],
|
||||
"bonds": ["arcaneShip 0/11","kazimierzShip 0/16","kjeragShip 0/8","miraShip 1/34","preciShip 1/37","sargonShip 1/9","siracusaShip 1/46","soloShip 1/0","suntShip 1/0","swiftShip 1/63","yanShip 0/13"]
|
||||
"bonds": ["arcaneShip 0/11","kazimierzShip 0/16","kjeragShip 0/8","miraShip 1/24","preciShip 1/50","sargonShip 1/22","siracusaShip 1/34","soloShip 1/0","suntShip 1/0","swiftShip 1/63","yanShip 0/13"]
|
||||
},
|
||||
"ai_0": {
|
||||
"alive": true,
|
||||
@@ -1587,9 +1587,9 @@
|
||||
"title": {"id":"comment_1","name":"卫戍之星","picId":"comment_icon_1","text":"对敌方领袖造成伤害最高(仅胜利时)"},
|
||||
"trophies": 4,
|
||||
"reward": 400,
|
||||
"stats": {"activatedLayers":290,"bossDamage":502859,"dmgDealt":3633322,"gold":140,"itemsEquipped":22,"kills":269,"leaks":50,"lpLost":10,"merges":6,"perfectRounds":12,"refreshes":21},
|
||||
"lineup": ["1_01_b@12,3[2_01_e_a+3_07_e_b]","4_21_a@12,7","3_21_b@11,3[1_05_e_b+4_08_e_b]","5_20_a@11,8","3_01_b@10,3[5_09_e_a+6_05_e_a]","3_18_a@10,7","4_16_a@10,8[4_11_e_a+4_02_e_a]","6_01_a@9,8[3_07_e_a+3_08_e_b]"],
|
||||
"bonds": ["arcaneShip 0/2","deputShip 0/32","kazimierzShip 0/8","lateranoShip 1/81","miraShip 1/6","preciShip 0/2","raidShip 0/2","sargonShip 0/2","siracusaShip 1/66","skillfulShip 1/68","suntShip 1/14","swiftShip 1/55"]
|
||||
"stats": {"activatedLayers":292,"bossDamage":540957,"dmgDealt":3504212,"gold":140,"itemsEquipped":22,"kills":267,"leaks":45,"lpLost":10,"merges":6,"perfectRounds":12,"refreshes":21},
|
||||
"lineup": ["1_01_b@12,3[2_01_e_a+3_07_e_b]","3_21_b@11,3[1_05_e_b+4_08_e_b]","5_20_a@11,8","3_01_b@10,3[5_09_e_a+6_05_e_a]","3_18_a@10,7","4_16_a@10,8[4_11_e_a+4_02_e_a]","6_01_a@9,8[3_07_e_a+3_08_e_b]","4_21_a@9,9"],
|
||||
"bonds": ["arcaneShip 0/2","deputShip 0/38","kazimierzShip 0/8","lateranoShip 1/83","miraShip 1/6","preciShip 0/2","raidShip 0/2","sargonShip 0/2","siracusaShip 1/66","skillfulShip 1/68","suntShip 1/14","swiftShip 1/55"]
|
||||
}
|
||||
},
|
||||
"standIns": {
|
||||
|
||||
+22
-24
@@ -2512,40 +2512,38 @@
|
||||
"bossHpLeft": null,
|
||||
"rngDraws": 43,
|
||||
"errors": {"count":0,"kinds":[]},
|
||||
"players": {
|
||||
"p1": {"killed":46,"total":47,"perfect":false,"leaks":1,"leaksUncounted":0,"coins":8,"dmg":564702,"bossDmg":0,"heal":8941,"deaths":7,"layerGains":{"visiShip":5}}
|
||||
},
|
||||
"players": {"p1":{"killed":46,"total":47,"perfect":false,"leaks":1,"leaksUncounted":0,"coins":8,"dmg":535533,"bossDmg":0,"heal":17173,"deaths":4,"layerGains":{}}},
|
||||
"units": [
|
||||
["p1",1,"op","chess_char_4_23_a",1,null,0,0,63,7,28573,4358,0,47,1],
|
||||
["p1",2,"op","chess_char_4_01_b",1,"none",2872.7,1,9,1,7066,2118,0,105,2],
|
||||
["p1",3,"op","chess_char_4_19_a",1,null,0,0,53,0,1771,3120,0,38,2],
|
||||
["p1",4,"op","chess_char_4_22_a",1,null,2022,1,7,0,1416,3450,502,43,1],
|
||||
["p1",5,"op","chess_char_4_04_b",2,"uniequip_002_ines",2149,1,66,6,63599,10027,0,61,4],
|
||||
["p1",6,"op","chess_char_4_07_b",2,"none",2233,1,8,1,2150,400,1,1,1],
|
||||
["p1",7,"op","chess_char_4_09_b",2,"uniequip_004_mizuki",1756,1,12,18,321808,1511,0,52,2],
|
||||
["p1",8,"op","chess_char_4_20_a",1,null,1217,1,2,2,22436,0,0,82,3],
|
||||
["p1",9,"op","chess_char_4_24_a",2,null,1726,1,3,10,77993,0,0,31,4],
|
||||
["p1",10,"op","chess_char_4_25_a",1,null,1221,1,4,1,13938,0,0,0,3],
|
||||
["p1",1,"op","chess_char_4_23_a",1,null,2179,1,64,2,26142,2179,0,47,2],
|
||||
["p1",2,"op","chess_char_4_01_b",1,"none",3199.72,1,9,0,7648,1791,0,82,1],
|
||||
["p1",3,"op","chess_char_4_19_a",1,null,0,0,59,0,2327,5998,0,51,3],
|
||||
["p1",4,"op","chess_char_4_22_a",1,null,2022,1,7,0,623,2216,101,18,1],
|
||||
["p1",5,"op","chess_char_4_04_b",2,"uniequip_002_ines",465,1,55,4,71128,14681,0,103,2],
|
||||
["p1",6,"op","chess_char_4_07_b",2,"none",2233,1,8,0,0,0,0,0,0],
|
||||
["p1",7,"op","chess_char_4_09_b",2,"uniequip_004_mizuki",1492.6,1,12,26,296442,1494,0,52,2],
|
||||
["p1",8,"op","chess_char_4_20_a",1,null,1217,1,2,1,20712,0,0,82,3],
|
||||
["p1",9,"op","chess_char_4_24_a",2,null,1726,1,3,12,71831,0,0,21,4],
|
||||
["p1",10,"op","chess_char_4_25_a",1,null,1221,1,4,1,11911,0,0,0,3],
|
||||
["p1",11,"op","chess_char_4_02_b",1,"none",2966.25,1,1,0,0,0,0,0,0],
|
||||
["p1",12,"op","chess_char_4_12_b",1,"none",4562.3,1,5,0,23952,0,0,69,4],
|
||||
["p1","~1","token","char_613_acmedc",null,null,1314,1,13,0,0,0,8438,19,2]
|
||||
["p1",12,"op","chess_char_4_12_b",1,"none",4562.3,1,5,0,26769,0,0,70,4],
|
||||
["p1","~1","token","char_613_acmedc",null,null,1314,1,13,0,0,0,17072,27,2]
|
||||
],
|
||||
"enemies": {
|
||||
"enemy_1001_bigbo": [1,1,0,2027,17600],
|
||||
"enemy_1001_bigbo": [1,1,0,2124,17600],
|
||||
"enemy_10097_crshd": [1,1,0,0,8000],
|
||||
"enemy_1045_hammer": [1,1,0,40,8000],
|
||||
"enemy_1045_hammer_2": [6,5,0,16433,92110],
|
||||
"enemy_1061_zomshd": [33,33,0,4573,410182],
|
||||
"enemy_1045_hammer": [1,1,0,487,8000],
|
||||
"enemy_1045_hammer_2": [6,5,0,19532,89637],
|
||||
"enemy_1061_zomshd": [33,33,0,3921,383485],
|
||||
"enemy_1166_dusbr": [1,1,0,0,2400],
|
||||
"enemy_1204_msfhu_2": [1,1,0,0,6],
|
||||
"enemy_1288_duskls_2": [1,1,0,0,4805],
|
||||
"enemy_1427_lrnazg": [1,1,0,688,12000],
|
||||
"enemy_2010_csdcr": [1,1,0,960,9600]
|
||||
"enemy_2010_csdcr": [1,1,0,1080,9600]
|
||||
},
|
||||
"hooks": [1,66,5700,698,698,1192,1191,22137,53,54,29,23,63,27315,96,51,47,0,1,54,1,0,10],
|
||||
"events": {"atk":1071,"bounty":4,"deploy":19,"die":54,"dmg":1134,"engage":10,"fx":194,"heal":24,"layer":1,"skill":52,"spawn":60,"status":330},
|
||||
"fx": {"aoe":2,"beam":4,"buff":1,"devour":4,"displace":45,"dodge":10,"ember":1,"garrison":1,"garrisonGrant":1,"link":3,"mote":72,"overload":3,"reweave":3,"riposte":7,"ripple":2,"sentry":5,"shadowWeave":20,"shield":4,"snow":1,"summon":1,"wake":4},
|
||||
"snaps": "10b0fc57 0b25ce77 4b6dd831 dfcc878d ea02c153 8f9524b2 a967f6bd 5b979090 1c1bc0ac a3a6e47e 27b92546 3018c6fd ff67392c 97352b97 dd49f777 68cea056 3b6f2f3a c0c82ec8 f88614a7"
|
||||
"hooks": [1,64,5700,662,662,1105,1100,18020,50,51,27,23,45,27645,98,54,47,0,1,51,0,0,13],
|
||||
"events": {"atk":997,"bounty":4,"deploy":17,"die":51,"dmg":1060,"engage":9,"fx":193,"heal":47,"skill":50,"spawn":60,"status":351},
|
||||
"fx": {"aoe":3,"beam":2,"devour":4,"displace":51,"dodge":13,"ember":1,"garrisonGrant":1,"link":3,"mote":69,"overload":3,"reweave":3,"riposte":7,"ripple":2,"sentry":3,"shadowWeave":19,"shield":3,"snow":1,"summon":1,"wake":4},
|
||||
"snaps": "10b0fc57 0b25ce77 2eb004e3 34bc73ed 2ae3d4fc 952fb4c4 fbed5c98 4dacadad a902ca6b d97ae173 1b59ad14 ba4ffa6d 9b7e70f2 318c9aa8 c804aa7e 79f72845 7a1a0e9d 96548306 9230b759"
|
||||
},
|
||||
"roster-042": {
|
||||
"about": "pass 2 band 5: chess_char_4_17_b chess_char_4_18_b chess_char_4_23_b chess_char_4_19_b chess_char_4_22_b chess_char_5_01_a chess_char_4_16_b chess_char_4_13_b chess_char_4_20_b chess_char_4_24_b chess_char_4_25_b chess_char_5_02_a",
|
||||
|
||||
@@ -184,6 +184,41 @@ test('#1 only manual refreshes count: a re-triggered "刷新时" trait (ctx.trig
|
||||
m.dispose();
|
||||
});
|
||||
|
||||
// PR #196 (the part 0.2.0 lacks): 贾维 【团伙行动】 grants a 叙拉古 operator on every 6th manual refresh from that refresh's
|
||||
// own dispatch (band step, before the garrisons). The 拉普兰德 it grants — or the elite its copy completes — is gained
|
||||
// after the refresh happened: her "本回合首次主动刷新" is the next manual one. The dispatcher walks the board and hand as
|
||||
// they stood when the refresh happened (EffectDispatcher.dispatch onRefresh snapshot); it walked them live, so she fired
|
||||
// (and spent her first refresh) in the refresh that granted her. Round counters are not copied on a merge (§25.13.3).
|
||||
for (const variant of ['a new copy', 'a copy that completes the elite']) {
|
||||
test(`#1 贾维 refresh gift (${variant}, PR #196): the 拉普兰德 waits for the next manual refresh`, () => {
|
||||
const s = setup();
|
||||
const { m, ps } = s;
|
||||
ps.bandId = 'band_chiave';
|
||||
ps.shop.level = 2;
|
||||
// 贾维's draw (ctx.rollChess on the meta RNG) gives 拉普兰德; the shop rolls stay as they are
|
||||
const roll = m.pool.roll.bind(m.pool);
|
||||
m.pool.roll = (rng, opts = {}) => (rng === m.rngMeta && typeof opts.filter === 'function' && opts.filter(LAP) ? LAP : roll(rng, opts));
|
||||
s.activate();
|
||||
const elite = variant !== 'a new copy';
|
||||
if (elite) { give(m, ps, LAP, 'hand'); give(m, ps, LAP, 'hand'); }
|
||||
for (let i = 0; i < 5; i++) s.refresh();
|
||||
const before = s.L();
|
||||
assert.equal(before, elite ? 8 : 0, 'the copies already owned fire on the round\'s first refresh');
|
||||
assert.ok(!ps.allChess().some((p) => p.id === LAP_B) && ps.allChess().filter((p) => p.id === LAP).length === (elite ? 2 : 0));
|
||||
s.refresh(); // the 6th: 贾维's gift
|
||||
const lap = ps.allChess().find((p) => p.id === (elite ? LAP_B : LAP));
|
||||
assert.ok(lap, elite ? 'the gift completed the elite' : 'the gift is owned');
|
||||
assert.equal(s.L(), before, 'not in the refresh that granted her');
|
||||
s.refresh();
|
||||
assert.equal(s.L(), before + (elite ? 8 : 4), 'her first manual refresh is the next one');
|
||||
s.refresh();
|
||||
assert.equal(s.L(), before + (elite ? 8 : 4), 'once a round');
|
||||
assert.equal(m.dispatcher.errors, 0);
|
||||
checkInvariants(m);
|
||||
m.dispose();
|
||||
});
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------------------
|
||||
// #4 突变细胞
|
||||
|
||||
|
||||
@@ -115,3 +115,37 @@ test('a golden owner\'s summon card shows the golden variant: 精锐 巫恋\'s d
|
||||
assert.equal(unit.type, 'token');
|
||||
assert.equal(unit.ownerId, 'chess_char_3_15_b');
|
||||
});
|
||||
|
||||
// GitHub #260 (PR #278): the 外勤医疗 strategy's map characters are operators of the mode — the card read them as summons
|
||||
// (召唤物, an owner variant they do not have: base stats only)
|
||||
const allText = (v) => {
|
||||
if (v == null || typeof v === 'boolean') return '';
|
||||
if (typeof v === 'string' || typeof v === 'number') return String(v);
|
||||
if (Array.isArray(v)) return v.map(allText).join('');
|
||||
if (typeof v === 'object' && typeof v.type === 'function' && ['Section', 'Stat', 'LiveTag'].includes(v.type.name)) return allText(v.type(v.props));
|
||||
if (typeof v === 'object' && typeof v.props?.text === 'string') return v.props.text;
|
||||
return typeof v === 'object' ? allText(v.props?.children) : '';
|
||||
};
|
||||
|
||||
test('GitHub #260: Touch / 预备干员-医疗 cards say 干员 · 医疗 and show the skill, talents and 特性 of their record; 恳切福音 says what the sim does (低于一半)', async () => {
|
||||
await data.loadAll('tokens', 'assets');
|
||||
for (const [id, want] of [
|
||||
['char_613_acmedc', ['恳切福音', '攻击距离<@ba.vup>+2</>', '攫升', '治疗目标时使其获得3点技力', '超脱', '获得5点技力', '恢复友方单位生命', '初始', '持续']],
|
||||
['char_605_cmedic', ['治疗强化·β型', '攻击力<@ba.vup>+50%</>', '攻击提升', '攻击力+4%', '恢复友方单位生命']],
|
||||
]) {
|
||||
// a battle click resolves the unit as its token record
|
||||
const detail = resolveDetail({ kind: 'unit', unit: { id: 91, side: 'ally', defId: id } }, new Map());
|
||||
assert.equal(detail.type, 'token');
|
||||
const text = allText(TokenDetail(detail));
|
||||
assert.match(text, /干员/);
|
||||
assert.match(text, /医疗/);
|
||||
assert.doesNotMatch(text, /召唤物/);
|
||||
for (const w of want) assert.ok(text.includes(w), `${id}: ${w}`);
|
||||
assert.equal(/PRTS 修正/.test(text), id === 'char_613_acmedc', `${id}: the 低于一半 line only under 恳切福音`);
|
||||
}
|
||||
// the record keeps the official sentence; the line under it is what touchGospel does (strictly below hp_ratio)
|
||||
assert.match(TOKENS.char_613_acmedc.skill.desc, /不高于一半/);
|
||||
assert.match(allText(TokenDetail({ token: TOKENS.char_613_acmedc })), /实际为生命值低于一半/);
|
||||
// a summon keeps its summon card
|
||||
assert.match(allText(TokenDetail({ token: TOKENS.token_10006_vodfox_doll, ownerId: 'chess_char_3_15_a' })), /召唤物/);
|
||||
});
|
||||
Reference in new issue
Block a user