feedback6: merge R21P — every operator at full potential (潜能 6; GitHub #252, PR #255 by @SpiritedAwayCN, the owner's decision of 2026-10-07)
- tools/build-data.mjs applies every potentialRanks attribute step (COST, RESPAWN_TIME, ATK, MAX_HP, DEF, MAGIC_RESISTANCE, ATTACK_SPEED) to the chess, elites, 补位 and 自选 units and picks talent / trait / module-talent candidates up to requiredPotentialRank 5; summons take the owner's potential for their talents, not its stat steps. data/chess.json, backups.json, tokens.json and the en / ja / ko / zh-TW data translations rebuilt; op-wang.js reads her stock cap (8 at full potential). 刺玫 435 ATK / cost 15, 砾 16 s, 至简 70 s. - No conflicts outside the golden files (regenerated). Golden vs HEAD: roster 49, bonds 46, fields 22, matches 18, diy 133 (standins and diy-012 / diy-135…138 unchanged: no potential ranks or never hit). Union check against the branch and the merge base: every scenario only the branch moved equals the branch, except roster-048 and solo-ABYSS-2: at full potential a 频次 器物 is reached there (roster-048: one more enemy dies instead of leaking, 86 → 87 units), so R21H's hit count (data × hpMul ÷ supplyHpMul) applies where it did not before — with only that rule put back (archetypes.js times as at the merge base) both equal the branch exactly. - Tests: broad node --test 5147 / 5147; lint 0 errors.
This commit is contained in:
commit
b05845f507
178 files changed
+7667
-7317
No files matched your search
+15
-10
@@ -121,9 +121,10 @@ test('chess: every non-DIY chess has stats, range, classification and a resolvab
|
||||
assert.ok(c.assets && c.assets.avatar && c.assets.spine, `${c.chessId}: assets`);
|
||||
if (c.isGolden) assert.equal(c.module ? c.module.active || c.module.id === null : true, true);
|
||||
}
|
||||
// Spot checks against official numbers (隐现 E1 Lv55: HP 1123, ATK 399).
|
||||
// Spot checks against official numbers (隐现 E1 Lv55: HP 1123, ATK 399 + 攻击力+23 at full potential = 422; cost 15 − 3).
|
||||
assert.equal(chess.chess_char_1_01_a.stats.maxHp, 1123);
|
||||
assert.equal(chess.chess_char_1_01_a.stats.atk, 399);
|
||||
assert.equal(chess.chess_char_1_01_a.stats.atk, 422);
|
||||
assert.equal(chess.chess_char_1_01_a.stats.cost, 12);
|
||||
assert.equal(chess.chess_char_1_01_a.targetPriority, 'fly');
|
||||
});
|
||||
|
||||
@@ -577,7 +578,7 @@ test('chess: golden modules[] (+ statsBase/traitBase/talentsBase) compose back t
|
||||
const m = chess.chess_char_6_11_b;
|
||||
assert.deepEqual(m.modules.map((x) => [x.uniEquipId, x.typeName, x.isDefault]), [['uniequip_002_mlyss', 'TAC-X', true], ['uniequip_003_mlyss', 'TAC-Y', false]]);
|
||||
assert.deepEqual(m.modules[1].attr, { maxHp: 170, atk: 28, def: 28 });
|
||||
assert.deepEqual([m.statsBase.maxHp, m.statsBase.atk, m.statsBase.def], [1703, 467, 111]);
|
||||
assert.deepEqual([m.statsBase.maxHp, m.statsBase.atk, m.statsBase.def], [1703, 492, 111]); // ATK 467 + 攻击力+25 (full potential)
|
||||
// module-less goldens: no choices, base = stats
|
||||
assert.deepEqual(chess.chess_char_5_14_b.modules, []);
|
||||
assert.deepEqual(chess.chess_char_5_14_b.statsBase, chess.chess_char_5_14_b.stats);
|
||||
@@ -705,12 +706,13 @@ test('stages: the escaped levels\' maps — one per helper count, never a match
|
||||
});
|
||||
|
||||
test('official spot checks (hard-coded values from the zh_CN client data)', () => {
|
||||
// at full potential (the owner's decision of 2026-10-07): the client's numbers plus each operator's potential steps
|
||||
const st = (id) => { const s = chess[id].stats; return [s.maxHp, s.atk, s.def, s.res, s.blockCnt, s.cost]; };
|
||||
assert.deepEqual(st('chess_char_6_11_b'), [1893, 492, 141, 0, 1, 15]); // 缪尔赛思 精锐 (E2 60 + module Lv3)
|
||||
assert.deepEqual(st('chess_char_6_17_b'), [3593, 1108, 279, 0, 1, 19]); // 耀骑士临光 精锐
|
||||
assert.deepEqual(st('chess_char_3_08_a'), [1594, 629, 170, 15, 1, 25]); // 薄绿 (E2 1)
|
||||
assert.deepEqual(st('chess_char_2_11_a'), [1816, 547, 254, 0, 2, 15]); // 风丸 (E1 60)
|
||||
assert.deepEqual(st('chess_char_4_07_b'), [2383, 604, 359, 0, 1, 13]); // 风笛 精锐
|
||||
assert.deepEqual(st('chess_char_6_11_b'), [1893, 517, 141, 0, 1, 13]); // 缪尔赛思 精锐 (E2 60 + module Lv3): 492 + 25 ATK, 15 − 2 cost
|
||||
assert.deepEqual(st('chess_char_6_17_b'), [3593, 1143, 279, 0, 1, 17]); // 耀骑士临光 精锐: 1108 + 35, 19 − 2
|
||||
assert.deepEqual(st('chess_char_3_08_a'), [1594, 629, 170, 15, 1, 22]); // 薄绿 (E2 1): 25 − 3
|
||||
assert.deepEqual(st('chess_char_2_11_a'), [1816, 574, 254, 0, 2, 13]); // 风丸 (E1 60): 547 + 27, 15 − 2
|
||||
assert.deepEqual(st('chess_char_4_07_b'), [2383, 629, 359, 0, 1, 11]); // 风笛 精锐: 604 + 25, 13 − 2
|
||||
assert.equal(chess.chess_char_6_11_b.module.level, 3);
|
||||
assert.deepEqual([chess.chess_char_4_07_b.skill.skillId, chess.chess_char_4_07_b.skill.level, chess.chess_char_4_07_b.skill.spCost], ['skchr_bpipe_2', 7, 5]);
|
||||
const es = (k) => { const s = enemies[k].stats; return [s.maxHp, s.atk, s.def, s.res]; };
|
||||
@@ -741,8 +743,11 @@ test('independent re-derivation of every chess and enemy stat from the raw offic
|
||||
const k0 = P.attributesKeyFrames[0], k1 = P.attributesKeyFrames[P.attributesKeyFrames.length - 1];
|
||||
const t = (cd.status.charLevel - k0.level) / (k1.level - k0.level || 1);
|
||||
const f = (key) => k0.data[key] + (k1.data[key] - k0.data[key]) * t;
|
||||
const exp = { maxHp: f('maxHp'), atk: f('atk'), def: f('def'), res: f('magicResistance'), aspd: f('attackSpeed'), blockCnt: f('blockCnt'), cost: f('cost') };
|
||||
const map = { max_hp: 'maxHp', atk: 'atk', def: 'def', magic_resistance: 'res', attack_speed: 'aspd', block_cnt: 'blockCnt', cost: 'cost' };
|
||||
const exp = { maxHp: f('maxHp'), atk: f('atk'), def: f('def'), res: f('magicResistance'), aspd: f('attackSpeed'), blockCnt: f('blockCnt'), cost: f('cost'), respawnTime: f('respawnTime') };
|
||||
const map = { max_hp: 'maxHp', atk: 'atk', def: 'def', magic_resistance: 'res', attack_speed: 'aspd', block_cnt: 'blockCnt', cost: 'cost', respawn_time: 'respawnTime' };
|
||||
// full potential (the owner's decision of 2026-10-07): every potentialRanks attribute step (all ADDITION)
|
||||
const POT = { MAX_HP: 'maxHp', ATK: 'atk', DEF: 'def', MAGIC_RESISTANCE: 'res', ATTACK_SPEED: 'aspd', COST: 'cost', RESPAWN_TIME: 'respawnTime' };
|
||||
for (const r of CT[shop.charId].potentialRanks || []) for (const m of r.buff?.attributes?.attributeModifiers || []) exp[POT[m.attributeType]] += m.value;
|
||||
if (cd.status.equipLevel > 0 && shop.defaultUniEquipId) {
|
||||
const mp = BE[shop.defaultUniEquipId]?.phases.find((p) => p.equipLevel === cd.status.equipLevel);
|
||||
for (const b of mp?.attributeBlackboard || []) if (map[b.key]) exp[map[b.key]] += b.value;
|
||||
|
||||
Reference in new issue
Block a user