feedback7 R22-LOADOUT: the data carries every potential (潜能 1–6), not only full potential; golden: unchanged
Potential becomes a per-player setting (the owner's decision of 2026-10-08: 「调配干员里自己设置吧,默认满潜满加成」;
official: 调度手册 「卫戍协议中干员潜能由自身已持有干员潜能决定」). 0.2.1 baked full potential into the data (§26.14).
- tools/build-data.mjs runs the chess / backups / tokens builders once per potential rank (ctx.potRank, 0–5) and keeps
the full-potential build annotated with what each lower rank changes: `potDown` { rank: { dotted.path: value } } on
chess records, backups.json forms and token variants (stats, statsBase; 望's 棋子 deployLimit / deckStack, 多萝西's
共振装置 count), and chained talent entries (`potMin` / `potBelow`: the candidates by requiredPotentialRank, the
fields a lower rank changes) in talents / talentsBase / modules[].talentChanges / variant talents. A self-check proves
shared/potential.js atRank rebuilds every rank exactly; the unit-form parity runs at every rank.
- shared/potential.js (new): atPotential / atRank, talentAtRank, stripPotential, and the 练度 helpers used next
(cultivateMul from the effects.json CHAR_MAP records aceffect_char_1…4, cultivationOf, cultivatedStats).
- composeTalents / composeUnitRecord return potential-resolved lists (no chains): a composed record is built at one
potential (its form resolved first).
- JSON compare: the new chess / backups / tokens minus the annotations equal the old files byte for byte; every other
data file identical; data/i18n/* rebuilt (the chained talent texts translated at the old rates: en 95.4 %, ja 95.2 %,
ko 95.2 %, zh-TW 90 %). Data 5.21 → 5.51 MB.
- Docs: DATA.md §2.3 (new), §2, §7, §14, §16, §18; research/03-operators.md; kits/README.md.
- Tests: test/potential.test.js (new, 7): every chess and 自选 form at every potential = the raw keyframes plus the
potential steps up to it, every talent = the last candidate with requiredPotentialRank ≤ the rank, 刺玫 at each
potential, summons at the owner's potential (Mon3tr 3 s / 1200, 望's 棋子 6 / 7, “小自在” 15), the 练度 table =
cultivateEffectList; data.test.js compares the composed talents without annotations.
This commit is contained in:
1 parent
ae22335cfe
commit
7e09c63da8
17 files changed
+614
-69
No files matched your search
+36
-10
@@ -161,7 +161,7 @@ Top level: `{ season, seasonName, modes, economy, lpCapPerRound, bossOvertimeAft
|
||||
| `price`, `sellPrice` | `2`, `1` | |
|
||||
| `upgradeNum`, `upgradeChessId` | `3`, `"chess_char_1_01_b"` | copies needed to merge (风丸 2; golden 0) |
|
||||
| `status` | `{"phase":2,"level":50,"skillLevel":7,"equipLevel":1}` | training status used for all numbers |
|
||||
| `stats` | `{"maxHp":1421,"atk":531,"def":167,"res":0,"cost":12,"blockCnt":1,"bat":1,"aspd":100,"respawnTime":70,"spRecovery":1,"hpRecoveryPerSec":0,"moveSpeed":1,"tauntLevel":0,"massLevel":0,"deployLimit":1,"deckStack":0}` | keyframes linearly interpolated at `status` **plus every potential attribute modifier** (full potential, 潜能 6: character_table `potentialRanks` 1–5 — 「攻击力+N」, 「部署费用-1」, 「再部署时间-N秒」, 生命 / 防御 / 法抗 / 攻速 — added to the raw values; the owner's decision of 2026-10-07, GitHub #252 / PR #255: the official records carry no potential, a tournament video shows 刺玫 at ATK 435 / cost 15 = her E1 Lv55 413 / 17 + 攻击力+22 and two 部署费用-1; `tools/build-data.mjs OPERATOR_POTENTIAL`), hp/atk/def/cost/block/respawn rounded; **golden includes the module attribute bonus**. `aspd` 100 = base (module attack_speed added). Talent stat boosts are NOT folded in. |
|
||||
| `stats` | `{"maxHp":1421,"atk":531,"def":167,"res":0,"cost":12,"blockCnt":1,"bat":1,"aspd":100,"respawnTime":70,"spRecovery":1,"hpRecoveryPerSec":0,"moveSpeed":1,"tauntLevel":0,"massLevel":0,"deployLimit":1,"deckStack":0}` | keyframes linearly interpolated at `status` **plus every potential attribute modifier** (full potential, 潜能 6 — the default; character_table `potentialRanks` 1–5 — 「攻击力+N」, 「部署费用-1」, 「再部署时间-N秒」, 生命 / 防御 / 法抗 / 攻速 — added to the raw values: the official records carry no potential, a tournament video shows 刺玫 at ATK 435 / cost 15 = her E1 Lv55 413 / 17 + 攻击力+22 and two 部署费用-1; a lower potential — the player's 干员调配 setting since 0.2.2 — reads `potDown`, §2.3), hp/atk/def/cost/block/respawn rounded; **golden includes the module attribute bonus**. `aspd` 100 = base (module attack_speed added). Talent stat boosts are NOT folded in. |
|
||||
| `immunities` | `{"stun":false,"silence":false,"sleep":false,"frozen":false,"levitate":false}` | |
|
||||
| `rangeId`, `rangeGrid` | `"3-3"`, `[[1,0],[1,1],…]` | attack range at `status` |
|
||||
| `dmgType` | `"phys"` | `phys` / `arts` / `heal` (derived, see §2.1) |
|
||||
@@ -173,11 +173,12 @@ Top level: `{ season, seasonName, modes, economy, lpCapPerRound, bossOvertimeAft
|
||||
| `skill` | see below | default skill at `status.skillLevel` (normal 4, golden 7) |
|
||||
| `skills[]` | `[{…skill record…, "index":0, "isDefault":false}, {…, "index":1, "isDefault":true}]` | **loadout choices** (DESIGN §16): every skill unlocked at `status` (E1 ⇒ S1–S2, E2 ⇒ S1–S3; the default is always listed), same shape as `skill` + `isDefault`, at the chess skill level, `trigger` resolved **for that skill index** (§2.2). The `isDefault` entry equals `skill` |
|
||||
| `modules[]`, `statsBase`, `traitBase`, `talentsBase` | see §2.2 | golden chess with `equipLevel > 0` only: selectable modules + the no-module base they apply to |
|
||||
| `talents[]` | `{"index":0,"name":"火力支援","desc":"…","descRaw":"…","bb":{"self_ammo":3,"duration":20,"ally_ammo":1},"bbStr":{},"rangeGrid":null,"tokenKey":null,"hidden":false,"fromModule":false}` | best unlocked candidate at `status` at full potential (candidates up to `requiredPotentialRank` 5: the 「天赋效果增强」 steps; module talent candidates the same); golden: module talent upgrades applied (`fromModule`); module data-only talents have `name:null, hidden:true`. A module upgrade of an existing talent **merges** blackboards (module keys win, base keys it does not restate are kept — e.g. 宴 keeps `min_attack_speed`; 仇白's upgrade adds `atk_scale_t` next to the old `atk_scale`: prefer the key the text uses). Module parts flagged `isToken` are **not** applied to the operator; they upgrade its summons (tokens.json variants). `containerTokenKey`: the official talent token id when it is a container missing from character_table (凛御银灰), `tokenKey` then holds the default skill's token |
|
||||
| `talents[]` | `{"index":0,"name":"火力支援","desc":"…","descRaw":"…","bb":{"self_ammo":3,"duration":20,"ally_ammo":1},"bbStr":{},"rangeGrid":null,"tokenKey":null,"hidden":false,"fromModule":false}` | best unlocked candidate at `status` at full potential (candidates up to `requiredPotentialRank` 5: the 「天赋效果增强」 steps; module talent candidates the same — an entry a lower potential changes chains its lower candidates, `potMin` / `potBelow`, §2.3); golden: module talent upgrades applied (`fromModule`); module data-only talents have `name:null, hidden:true`. A module upgrade of an existing talent **merges** blackboards (module keys win, base keys it does not restate are kept — e.g. 宴 keeps `min_attack_speed`; 仇白's upgrade adds `atk_scale_t` next to the old `atk_scale`: prefer the key the text uses). Module parts flagged `isToken` are **not** applied to the operator; they upgrade its summons (tokens.json variants). `containerTokenKey`: the official talent token id when it is a container missing from character_table (凛御银灰), `tokenKey` then holds the default skill's token |
|
||||
| `tokens[]` | `["token_10028_vigil_wolf"]` | summons (→ `tokens.json`): displayTokenDict + default-skill `overrideTokenKey` + talent `tokenKey`; `tokens.json → variants[chessId].sources` tells which (a `display`-only token is not produced by this chess's default skill or talents) |
|
||||
| `module` | `{"id":"uniequip_002_inside","name":"“最初的惊喜”","type":"MAR-X","level":1,"active":true}` | active only on golden chess |
|
||||
| `assets` | `{"avatar":"char_498_inside_2","portrait":"char_498_inside_2","spine":"char_498_inside","skillIcon":"skchr_inside_2","subProfIcon":"sub_fastshot_icon"}` | asset **ids** (URLs in `data/assets.json`); golden uses the E2 art when it exists |
|
||||
| `diyRequirement` | `"TIER_6"` | DIY only |
|
||||
| `potDown` | `{"0":{"stats.cost":17},"1":{"stats.respawnTime":70},"2":{"stats.atk":413},"4":{"stats.cost":16}}` (`chess_char_1_06_a`, 刺玫) | what a lower potential changes (§2.3; absent when nothing does: the DIY slots, 盟约·辅助干员) |
|
||||
|
||||
`skill`:
|
||||
|
||||
@@ -242,6 +243,30 @@ everything needed to resolve a unit for `(chessId, skillIndex, moduleId)` (`simd
|
||||
variants[owner].byModule` (§14). Module choices never change the combat classification (`dmgType`…; the build warns
|
||||
if one ever would).
|
||||
|
||||
### 2.3 Potential below full potential: `potDown` and chained talents (0.2.2)
|
||||
|
||||
Potential (潜能 1–6) is the player's per-operator setting (干员调配, the owner's decision of 2026-10-08 — default 潜能 6;
|
||||
official: 调度手册 「卫戍协议中干员潜能由自身已持有干员潜能决定」). Every record is built at **full potential** and carries
|
||||
what each lower one changes; `shared/potential.js atPotential(rec, potential)` composes the record at a potential
|
||||
(data rank r = potential − 1, character_table's `potentialRanks[r]` being the step from rank r to r + 1). The same
|
||||
annotation is on chess records, `backups.json` unit forms (§18) and token variants (`tokens.json` and `backups.json`
|
||||
`tokens` variants, §14 — the owner's potential; a token record's top-level defaults stay full):
|
||||
|
||||
- `potDown`: `{ "<rank>": { "<dotted.path>": value } }` — for each rank 0–4, the exact value at that rank of every leaf
|
||||
that differs from the rank above (`stats.*` / `statsBase.*` of a record, `stats.*` of a form; a variant's
|
||||
`stats.deployLimit`, `stats.deckStack`, `count`, `bySkill.<i>.count`, `byModule.<id>.stats.*`). Applied from rank 4
|
||||
down to the wanted rank, each value overwriting, so every leaf ends at its value for that rank.
|
||||
- a talent entry (`talents`, `talentsBase`, `modules[].talentChanges`; a variant's `talents` and `byModule[*].talents`)
|
||||
that a lower rank changes: `potMin` = the lowest rank it holds for, `potBelow` = the fields the entry below it
|
||||
changes (`desc`, `descRaw`, `bb` …), itself chained the same way — the candidates by `requiredPotentialRank`
|
||||
(刺玫's 土壤基肥改良 `potMin` 4: 11% → 8%; Mon3tr's 不毁重构 below its owner's rank 4: 3 s / 1200).
|
||||
|
||||
`tools/build-data.mjs` runs the chess / backups / tokens builders at every rank (`ctx.potRank`) and annotates the
|
||||
full-rank build from the others; the build fails unless `atRank` rebuilds every rank exactly, and the unit-form parity
|
||||
(§18) holds at every rank. Nothing else depends on potential (no skill, trait or list length). The data translations
|
||||
(`data/i18n/*.json`) translate the chained texts too. 练度 (the 自持有 bonus) is no record field: it is the
|
||||
`char_attribute_mul` of the effects.json CHAR_MAP records `aceffect_char_1…4` (§7), applied to the unit.
|
||||
|
||||
---
|
||||
|
||||
## 3. `bonds.json` — `{ [bondId]: Bond }` (23 bonds, 8 core)
|
||||
@@ -317,7 +342,7 @@ everything needed to resolve a unit for `(chessId, skillIndex, moduleId)` (`simd
|
||||
|
||||
## 7. `effects.json` — `{ [effectId]: Effect }` (361: every effect of the season)
|
||||
|
||||
Types: `BAND_INITIAL` 41, `BOND` 23, `EQUIP` 115, `ENEMY_GAIN` 129 (悬赏), `BUFF_GAIN` 43 (战术决策), `ENEMY` 6 (`aceffect_enemy_*` global modifiers), `CHAR_MAP` 4.
|
||||
Types: `BAND_INITIAL` 41, `BOND` 23, `EQUIP` 115, `ENEMY_GAIN` 129 (悬赏), `BUFF_GAIN` 43 (战术决策), `ENEMY` 6 (`aceffect_enemy_*` global modifiers), `CHAR_MAP` 4 (角色练度映射 — the 自持有 练度 tiers `aceffect_char_1…4`, 未精英化 / 精英阶段1 / 精英阶段2 / 精英阶段2-60级, in `autoChessData.cultivateEffectList` order: their `char_attribute_mul` buff — `atk` / `def` / `max_hp` 1, 1.05, 1.1 — is the unit's 练度 multiplier, `shared/potential.js cultivateMul`, 0.2.2).
|
||||
|
||||
| Field | Example | Meaning |
|
||||
|---|---|---|
|
||||
@@ -494,7 +519,7 @@ Glyph legend (`rows`):
|
||||
| `skill` | `{"skillId":"sktok_vigil_wolf_3","bb":{…}}` | default token skill (same slot as the owner's skill) |
|
||||
| `deployLimit`, `count` | `1`, `1` | `deployLimit` = the first owner's `stats.deployLimit`. `count` = copies sent to the hand / spawned (talent/skill `cnt`); `null` ⇒ use `deployLimit` |
|
||||
| `abnormal[]` | `["healFree"]` | abnormal effects the summon holds from the start, no official table carries them — `tools/build-data.mjs TOKEN_ABNORMAL` from the PRTS summon pages (user playtest #6 item 18): `healFree` = 禁疗 (“小自在”, “耀阳”, 斯卡蒂的海嗣, 沙之碑, 流形, 狼群, 迷迭香的战术装备, 黄金盟誓, 保护目标(冻结状态)), `isolated` = 孤立 "无法被同阵营选中" (“炎佑”, 从不混淆的方向); `[]` otherwise. The sim sets `noHeal` / `isolated` (docs/SIM.md §3) |
|
||||
| `variants[ownerChessId]` | `{"phase":2,"level":1,"stats":{…},"immunities":{…},"rangeGrid":…,"trait":{…},"dmgType":…,"skill":{full skill record},"talents":[…],"count":1,"sources":["talent","display"]}` | stats at the owner's phase/level (clamped to the token's max level) — **none of the owner's potential attribute modifiers** (a token has no potential ranks) — + golden module `tokenAttributeBlackboard` + the token's own talent additions to `deployLimit` / `deckStack` (blackboard `max_deploy_count` / `max_deck_stack_cnt` — the hidden "TOKEN数" talent of 麦哲伦's / 令's summons and 白铁's devices, 夜莺's 幻影; a module token part of the same talent replaces it: `tools/build-data.mjs tokenTalentDeckBonus`, 0.2.0 — no tokens.json summon has one; PRTS 幻影 备注 "最大可部署数量为3", the owners' "最多同时部署3个"); its `talents` / `trait` candidates are picked at the **owner's potential** (full: their `requiredPotentialRank` mirrors the owner's 「天赋效果增强」 — 夕's “小自在” 18 层, 凯尔希's Mon3tr, 望's 棋子 +1 持有 / 部署; `tools/build-data.mjs OPERATOR_POTENTIAL`); the owner's module parts flagged `isToken` upgrade the variant's `trait` (+`moduleDesc`) and `talents` (伺夜's wolves, 缪尔赛思's 流形 `scale` 1, 浊心斯卡蒂's 海嗣 30 s, “耀阳” `atk_scale` 1.15). `sources` ⊆ `talent`/`skill`/`display`: how the owner produces it (`display` only = listed on the character but unused by its default skill/talents, e.g. 迷迭香 S2, 凛御银灰 eagle1/3). `count` = copies from a talent `cnt` or the default skill's `cnt` when that skill overrides this token; `null` ⇒ use `deployLimit` |
|
||||
| `variants[ownerChessId]` | `{"phase":2,"level":1,"stats":{…},"immunities":{…},"rangeGrid":…,"trait":{…},"dmgType":…,"skill":{full skill record},"talents":[…],"count":1,"sources":["talent","display"]}` | stats at the owner's phase/level (clamped to the token's max level) — **none of the owner's potential attribute modifiers** (a token has no potential ranks) — + golden module `tokenAttributeBlackboard` + the token's own talent additions to `deployLimit` / `deckStack` (blackboard `max_deploy_count` / `max_deck_stack_cnt` — the hidden "TOKEN数" talent of 麦哲伦's / 令's summons and 白铁's devices, 夜莺's 幻影; a module token part of the same talent replaces it: `tools/build-data.mjs tokenTalentDeckBonus`, 0.2.0 — no tokens.json summon has one; PRTS 幻影 备注 "最大可部署数量为3", the owners' "最多同时部署3个"); its `talents` / `trait` candidates are picked at the **owner's potential** (full; their `requiredPotentialRank` mirrors the owner's 「天赋效果增强」 — 夕's “小自在” 18 层, 凯尔希's Mon3tr, 望's 棋子 +1 持有 / 部署 — and the variant chains the lower ones, §2.3: `atPotential(variant, ownerPotential)`); the owner's module parts flagged `isToken` upgrade the variant's `trait` (+`moduleDesc`) and `talents` (伺夜's wolves, 缪尔赛思's 流形 `scale` 1, 浊心斯卡蒂's 海嗣 30 s, “耀阳” `atk_scale` 1.15). `sources` ⊆ `talent`/`skill`/`display`: how the owner produces it (`display` only = listed on the character but unused by its default skill/talents, e.g. 迷迭香 S2, 凛御银灰 eagle1/3). `count` = copies from a talent `cnt` or the default skill's `cnt` when that skill overrides this token; `null` ⇒ use `deployLimit` |
|
||||
| `variants[o].bySkill[i]` | `{"skill":{…},"count":1,"sources":["talent","display"]}` | owner loadout with the non-default skill index `i` (one entry per other selectable owner skill): the token skill of that slot (伺夜's wolves, 缪尔赛思's 流形, 凛御银灰's eagles…), the count and how the chess then produces it (`sources` may be `[]`: 风丸 S1 makes no 纸偶; 赫默 / 巫恋 S1 only `display` ⇒ no hand piece). The sim resolves them for an owner loadout: `simdata getToken(id, ownerChessId, loadout)` → `def.sources` / `def.count` |
|
||||
| `variants[o].byModule[m]` | `{"stats":{…},"immunities":{…},"trait":{…},"talents":[…]}` | golden owner with another module `m` or `'none'`: the token as that module makes it (module `tokenAttributeBlackboard`, `isToken` trait/talent parts) |
|
||||
| `assets` | `{"avatar":"token_10028_vigil_wolf","spine":"token_10028_vigil_wolf"}` | |
|
||||
@@ -574,7 +599,7 @@ Glyph legend (`rows`):
|
||||
|
||||
`chess 266 (112 visible; 283 selectable skills over the visible chess, 184 module choices over 129 goldens; 74 PRESET / 55 NORMAL / 4 DIY base chess)`, `bonds 23`, `garrisons 249 (43 effect keys)`, `items 115`, `bands 40`, `effects 361`,
|
||||
`enemies 249`, `factions 67 entries`, `waves 38`, `stages 11 (8 active)`, `bosses 10`, `tokens 22`, `choice events 109`,
|
||||
`bounty cards 129`, `tactic cards 43`, `backups: 88 units (17 stand-ins, 71 owned-6★ picks; 256 forms), 38 自选 summons, 4 DIY slots, 15 / 9 prototype picks (tier 5 / 6), 71 owned-6★ picks (7 collab operators excluded)`.
|
||||
`bounty cards 129`, `tactic cards 43`, `backups: 88 units (17 stand-ins, 71 owned-6★ picks; 256 forms), 38 自选 summons, 4 DIY slots, 15 / 9 prototype picks (tier 5 / 6), 71 owned-6★ picks (7 collab operators excluded)`, potential (§2.3): `256 chess records, 219 forms / variants with potDown; 442 + 401 + 19 chained talent entries (chess, backups, tokens)`.
|
||||
|
||||
## 17. Integrity guarantees (checked by the builder and `test/data.test.js`)
|
||||
|
||||
@@ -623,8 +648,8 @@ server/match/player/diy.js, docs/META.md §3). The rules in the data (activity_t
|
||||
- A stand-in keeps the chess's bonds, 特质, tier, price, merge and status (the elite form uses the same backup at the
|
||||
elite row) and fights as `backup.charId` at that status with skill `backup.skillIndex` (fixed by the chess: the same
|
||||
character takes S2 on one chess and S3 on another), module `backup.uniEquipId` (null at tiers 3–4 and for every 4★, so
|
||||
even their elite form has none) and the row's potential (`potRank` 0 on all 55) — moot: every unit form is built at
|
||||
full potential like a chess (the owner's decision of 2026-10-07), and the 17 原型干员 have no potential ranks.
|
||||
even their elite form has none) and the row's potential (`potRank` 0 on all 55) — moot: the 17 原型干员 have no
|
||||
potential ranks, and a stand-in takes neither the player's potential nor the 自持有 练度 (0.2.2).
|
||||
|
||||
`units[charId]` — first the 17 stand-ins, then the 71 owned-6★ 自选 picks (`diy.ownedPool`); no unit for a PRESET or DIY
|
||||
chess:
|
||||
@@ -638,7 +663,7 @@ chess:
|
||||
| `forms[statusKey]` | keys `"2/1/4/0"`, `"2/60/7/1"`, `"2/60/7/3"` | the character at every status it fights at — of the chess it stands in for and of the DIY slots it may fill (`statusKey(status)` = `phase/level/skillLevel/equipLevel`): 3 forms per 6★ (an owned pick: exactly the three DIY slot statuses — E2 Lv1 skill rank 4 without a module, E2 Lv60 rank 7 with every module at stage 1 and at stage 3), 2 per 4★ |
|
||||
|
||||
A **form** holds the operator fields of a chess record with **nothing selected**: `status`; `stats`, `trait`, `talents`
|
||||
**without** a module, at full potential as on a chess; `immunities`, `rangeId`, `rangeGrid`, `dmgType`, `attackKind`, `projectile`, `canHitFly`,
|
||||
**without** a module, at full potential as on a chess (`potDown` / chained talents for the lower ones, §2.3); `immunities`, `rangeId`, `rangeGrid`, `dmgType`, `attackKind`, `projectile`, `canHitFly`,
|
||||
`targetPriority`; `skills[]` — every skill unlocked at the status, at its skill level, `trigger` resolved per skill, no
|
||||
`isDefault`; `displayTokens` / `tokens` (summons — none of the 17 stand-ins has one; 27 of the owned picks do, their
|
||||
records in `tokens` below); at `equipLevel > 0` `modules[]` (§2.2 shape without `isDefault`). `buildUnitForm` uses buildChess's helpers and rules, and the build fails when `buildUnitForm` +
|
||||
@@ -705,5 +730,6 @@ loadout. No id is also a tokens.json record.
|
||||
|
||||
Not in this data: a player's ownership roster and 自选 picks (browser settings sent with `room.ownership` / `room.diy`),
|
||||
the DIY stock (per player in the match, `PlayerState.diyStock`: `config.economy.poolCopies` of the slot's tier — no excel
|
||||
field), 助战 borrows (`borrowCount` 20), the owned-operator training bonus (`prepareStateDict`), a per-player potential (every
|
||||
form is built at full potential, as every chess: the owner's decision of 2026-10-07).
|
||||
field), 助战 borrows (`borrowCount` 20), and a player's potential / 练度 per operator (the 干员调配 settings sent with
|
||||
`room.loadout`; the forms are built at full potential and carry the lower ranks, §2.3; 练度 = effects.json
|
||||
`aceffect_char_1…4`).
|
||||
Reference in new issue
Block a user