feedback7 R22-LOADOUT: the battle takes each operator's potential and 练度 from its spec entry; golden: unchanged
A PlayerBattleInput operator entry may carry `potential` (潜能 1–6) and `cultivate` (练度 0–3, the 自持有 bonus) —
the player's 干员调配 settings (the owner's decision of 2026-10-08). Specs without them field what 0.2.1 fielded, so
no golden scenario moves here; the match states both next.
- shared/loadoutRecord.js: a resolved loadout carries `potential`; loadoutRecord composes the record at it first
(shared/potential.js atPotential), then the skill / module as before.
- server/sim/simdata.js: getChess(id, { …, potential }), getDiy(slot, pick, potential) (an owned 自选 pick's form at it;
a prototype has none — `diyProto` on its record, shared/diy.js), getToken / getDiyToken compose the owner variant at
the owner's potential (talents; a 自选 summon's deploy limit / holding / count); the per-battle loadout view keeps it
per unit; DataSource.cultivateMul reads the effects.json CHAR_MAP record's char_attribute_mul.
- battle/players.js: `potential` composes the def (never a stand-in's); `cultivate` sets unit.cultMul — ×ATK / ×DEF /
×max HP in the unit's Πmul (units.js), a multiplier of its own, never summed with the 直接乘算 percentages (PRTS
盟约记录 「…与自持有干员的属性加成独立」); a stand-in, a prototype 自选 pick and a summon take none [ASSUMED for summons].
- spec.js keeps both only when well-formed (never on a stand-in or a summon); content/index.js passes the potential to
the loadout sync; the kits that read a summon variant raw (content/tokens.js ownVariant, summoner.js tokenStat,
多萝西, 麦克尼斯特) compose it at the owner's potential; UnitInfo carries `potential` (below 6) / `cultivate`;
unitStatsEntry counts the 练度 in the unit's own numbers (no green delta for it on the card).
- Docs: SIM.md §2 (Πmul), §9 (UnitInfo), §12.
- Tests: test/sim/potential-battle.test.js (new, 6): a unit at each potential (刺玫 413 / 17 / 70 s and 8 % at 潜能1;
the elite on 不装备), the four 练度 tiers and their product with a +20 % ATK bonus, HP at deployment and the card's
numbers, stand-in / prototype take neither and an owned 自选 pick both, Mon3tr / 望's 棋子 / “小自在” at the owner's
potential, the spec round trip (kept, dropped, the JSON spec gives the same result digest), two players with the same
chess at different settings on one field; test/sim/loadout.test.js expects the resolved loadout's new fields.
This commit is contained in:
1 parent
7e09c63da8
commit
ec0a2fc669
16 files changed
+324
-62
No files matched your search
@@ -9,6 +9,7 @@ import { normDir, mirrorDir } from '../dir.js';
|
||||
import { SkillRuntime } from '../skills.js';
|
||||
import { resolveProfile } from '../professions.js';
|
||||
import { normalizeToken } from '../simdata.js';
|
||||
import { isPotential, isCultivate } from '../../../shared/potential.js';
|
||||
import { setupUnitKit } from '../content/index.js';
|
||||
import { clone } from './util.js';
|
||||
|
||||
@@ -141,10 +142,12 @@ export class BattlePlayers {
|
||||
// the unit's own loadout (DESIGN §16): an entry without loadout fields is the DEFAULT — never another player's
|
||||
// choice for the same chess id in a multi-player field (the per-battle data view maps id-only lookups); `standIn:
|
||||
// true` fields the chess as its 补位 stand-in (simdata getStandIn: the stand-in's body, the chess's identity); `diy`
|
||||
// fills a 自选 slot with its pick (simdata getDiy: the slot's identity, the operator's body, skill and module)
|
||||
// fills a 自选 slot with its pick (simdata getDiy: the slot's identity, the operator's body, skill and module);
|
||||
// `potential` (潜能 1–6, 0.2.2) composes the def at it (never a stand-in's)
|
||||
const lo = { skillIndex: inp.skillIndex ?? null, moduleId: inp.moduleId ?? null };
|
||||
if (inp.standIn === true) lo.standIn = true;
|
||||
if (inp.diy && typeof inp.diy === 'object') lo.diy = inp.diy;
|
||||
if (inp.standIn !== true && isPotential(inp.potential)) lo.potential = inp.potential;
|
||||
const def = this.data.getChess(inp.chessId, lo);
|
||||
if (!def) { this.log(`unknown chess ${inp.chessId}${lo.diy ? ' (illegal 自选 pick)' : ''}`); return null; }
|
||||
// a DIY slot has no body of its own (甄选干员): it fights only as a 自选 piece (its `diy` pick)
|
||||
@@ -152,6 +155,12 @@ export class BattlePlayers {
|
||||
const u = this._makeAlly(ps, def, 'op', r, c, { uid: inp.uid, dir });
|
||||
u.items = [...(inp.items ?? [])];
|
||||
u.carry = inp.carryState ?? null;
|
||||
// 练度 (自持有, 0.2.2): the owned operator's ×ATK / ×DEF / ×max HP (units.js Πmul) — never a 补位 stand-in's nor a
|
||||
// prototype 自选 pick's (another character than the one the player owns)
|
||||
if (isCultivate(inp.cultivate) && !def.standInFor && !def.raw?.diyProto) {
|
||||
const mul = typeof this.data.cultivateMul === 'function' ? this.data.cultivateMul(inp.cultivate) : null;
|
||||
if (mul) { u.cultivate = inp.cultivate; u.cultMul = Object.freeze({ ...mul }); u.markDirty(); }
|
||||
}
|
||||
return u;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user