feedback5 O5: 自选 operator kits for 左乐, 重岳 and 煌 — every skill at ranks 4 / 7, both talents, the trait and both modules at stages 1 / 3, from the data, PRTS 备注, the client's buff templates and the battle skeletons' clip events
- 左乐 (op-zuole.js): S1 next attack + 1 / 2 extra strikes below 80 / 50 % HP (each a damage instance and a trait heal); S2 流失 50 % current HP (never below 1), a barrier of scale × max HP stacking to 2×, ATK / block +1 / every blocked enemy, −200 per second once over; S3 7 slashes on ≤ 3 enemies of 3-2, the last ×2 + stun, the trait's heal turned into a barrier (70 × 2.5 / 3 per damage instance, ≤ 2× max HP, 15 s); 坚忍 ASPD / SP recovery; 守正自明 per damage instance (SBL-Y Lv3 ×1.2 on a success); SBL-X 庇护 (behind the barrier once 行险 resets it — PRTS S2 备注 — through the hpDamage hook); SBL-Y revive at 30 % once per deployment. - 重岳 (op-chyue.js): 止戈 marks (normal-attack instances, ×1.65 / ×1.75 on all his damage); 万象为宾 SP at each skill / segment end, 阻回 ignored (FGT-X Lv3 4, else 1); S1 charges with the full-stack burst of 3; S2 x-4 ≤ 4 enemies (air too) + 浮空 2 s on the marked, the second segment 0.5 s later (skeleton events) on every 浮空 enemy; S3 strike + 0.8 splash, the 5th cast transforms him (x-6, double hits, +1 SP per attack, self-cast, the strike twice); FGT-X dodge, FGT-Y ASPD. - 煌 (op-huang.js): CEN-X ×1.1 vs blocked enemies on every damage; CEN-Y −20 % physical above 50 %; 紧急除颤 不死 + heal + the 50 % HP floor through the hpDamage hook (CEN-Y Lv3: 50 % then 25 %, 8 s, DEF −150 above 50 %); 严酷训练 抵抗 after 15 s (CEN-X Lv3 ATK +6 % / ASPD +12 after 30 / 45 s); S1 next attack; S2 SP_FULL toggle with 2-2; S3 a 10 s 维持技能状态: cuts each second for 8 s, ramp to full at 8.95 s, at 9 s 流失 25 % max HP and the 3-6 burst (air too). - kits/index.js OPERATOR_KIT_FILES lists the three files; test/content/diy.test.js's "owned 6★ without a kit" case takes the first kitless operator of diy.ownedPool (it named 煌). - Golden: only test/golden/diy.json moved — the diy family packs the new kits: diy-003 / 004 field 左乐, diy-005 / 006 重岳, diy-007 / 008 煌 (tiers 5 / 6, every form × module × skill, no battle error); the prototypes and reserves moved from diy-003 … 006 to diy-009 … 012 (new ids, same packing); diy-001 / 002 (推进之王) and every other family unchanged. - Tests: test/content/op_zuole.test.js (10), op_chyue.test.js (8), op_huang.test.js (10).
This commit is contained in:
1 parent
89d17d8e08
commit
29fa988604
9 files changed
+2071
-102
No files matched your search
@@ -13,10 +13,13 @@ import { getDefaultSource, DataSource } from '../../server/sim/simdata.js';
|
||||
import { buildBattleSpec, createBattleFromSpec } from '../../server/sim/spec.js';
|
||||
import { unitInfo } from '../../server/sim/snapshot.js';
|
||||
import { isDiyDef, kitOf } from '../../server/sim/content/index.js';
|
||||
import { KITTED_CHARS } from '../../server/sim/content/kits/index.js';
|
||||
|
||||
const load = (f) => JSON.parse(readFileSync(new URL(`../../data/${f}.json`, import.meta.url), 'utf8'));
|
||||
const BACKUPS = load('backups');
|
||||
const SIEGE = 'char_112_siege';
|
||||
/** An owned 6★ without an operator kit yet (the generic kit's case) — the first of diy.ownedPool, null once all have one. */
|
||||
const KITLESS = BACKUPS.diy.ownedPool.find((id) => !KITTED_CHARS.includes(id)) ?? null;
|
||||
const T5 = 'chess_char_5_diy1_a', T6 = 'chess_char_6_diy1_a';
|
||||
const dummy = (key, o = {}) => enemyRec({ key, hp: 1e9, speed: 0, mass: 0, ...o });
|
||||
const ENEMIES = { enemy_dummy: dummy('enemy_dummy') };
|
||||
@@ -54,18 +57,21 @@ test('a battle fields 自选 pieces by their kit: an owned 6★\'s operator kit
|
||||
{ diy: { slot: 5, charId: SIEGE, skillIndex: 1 }, row: 10, col: 3 },
|
||||
{ diy: { slot: 'chess_char_5_diy2_a', charId: 'char_609_acguad' }, elite: true, row: 10, col: 5 },
|
||||
{ diy: { slot: T6, charId: 'char_617_sharp2' }, elite: true, row: 10, col: 7 },
|
||||
{ diy: { slot: 'chess_char_6_diy2_a', charId: 'char_017_huang', skillIndex: 2 }, row: 11, col: 3 },
|
||||
...(KITLESS ? [{ diy: { slot: 'chess_char_6_diy2_a', charId: KITLESS, skillIndex: 2 }, row: 11, col: 3 }] : []),
|
||||
{ diy: { slot: 'chess_char_6_diy2_a', charId: 'char_601_cguard' }, row: 11, col: 5 }, // illegal at tier 6: never fielded
|
||||
], { kits: { [SIEGE]: siegeKit, chess_char_5_diy1_a: () => { throw new Error('a 自选 piece never runs a kit of its slot id'); } } });
|
||||
h.step();
|
||||
const [siege, sharp, sharp2, huang] = [1, 2, 3, 4].map((uid) => h.unit(uid));
|
||||
assert.equal(h.unit(5), null, 'an illegal pick fields nothing');
|
||||
const [siege, sharp, sharp2, kitless] = [1, 2, 3, 4].map((uid) => h.unit(uid));
|
||||
assert.equal(h.unit(KITLESS ? 5 : 4), null, 'an illegal pick fields nothing');
|
||||
assert.deepEqual([siege.defId, siege.def.charId, siege.skill.id, siege.kit.diyProbe, siege.kit.skillSource], [T5, SIEGE, 'skchr_siege_2', true, 'skills']);
|
||||
assert.equal(kitOf(siege.def, { [T5]: 'slot', chess_char_5_diy1: 'bare', [SIEGE]: 'mine' }), 'mine', 'kitOf: by charId only');
|
||||
assert.equal(kitOf(siege.def, { [T5]: 'slot' }), undefined);
|
||||
assert.deepEqual([sharp.defId, sharp.def.charId, sharp.skill.id, !!sharp.kit.generic, sharp.kit.skillSource, sharp.def.raw.module.level], ['chess_char_5_diy2_b', 'char_609_acguad', 'skchr_acguad_3', false, 'skills', 1]);
|
||||
assert.deepEqual([sharp2.skill.id, !!sharp2.kit.generic, sharp2.def.raw.module.level, sharp2.def.raw.module.active], ['skchr_sharp2_1', false, 3, true], '领主·Sharp at tier 6: S1 + LOR-X stage 3');
|
||||
assert.deepEqual([huang.def.charId, huang.skill.id, !!huang.kit.generic, huang.def.bonds], ['char_017_huang', 'skchr_huang_3', true, ['yanShip', 'victoriaShip']], '煌 has no kit yet: the generic kit');
|
||||
if (KITLESS) {
|
||||
assert.deepEqual([kitless.def.charId, kitless.skill.id, !!kitless.kit.generic, kitless.def.bonds],
|
||||
[KITLESS, BACKUPS.units[KITLESS].forms['2/1/4/0'].skills[2].skillId, true, BACKUPS.diy.operators[KITLESS].bonds], `${KITLESS} has no kit yet: the generic kit`);
|
||||
}
|
||||
// the elite reserve uses the generic kit with its exact stat talents (as a 补位 stand-in does)
|
||||
const h2 = battle([{ diy: { slot: 5, charId: 'char_601_cguard' }, elite: true, row: 10, col: 3 }]);
|
||||
h2.step();
|
||||
|
||||
Reference in new issue
Block a user