diff --git a/docs/DATA.md b/docs/DATA.md index afa99b0b..1f0d0abb 100644 --- a/docs/DATA.md +++ b/docs/DATA.md @@ -25,7 +25,7 @@ Unknown options or a missing option value are errors (exit code 2); `--refresh` Integrity errors (see §17) make the exit code 1 **and leave the previous output untouched** (unless `--force`); warnings never do. Each output file is written atomically (temp file + rename). - **Determinism.** Same inputs ⇒ byte-identical outputs (stable key order, no timestamps, no randomness). -- **Size.** ≈3.5 MB total (limit 6 MB; `chess.json` ≈1.65 MB with the loadout choices), compact JSON (no indentation). +- **Size.** ≈3.7 MB total (limit 6 MB; `chess.json` ≈1.69 MB with the loadout choices, `backups.json` ≈0.17 MB), compact JSON (no indentation). - **Derived paths.** `stages.json groundPaths*` come from the sim's own `server/sim/grid.js` pathing: a change there needs a rebuild (the offline-rebuild test catches a stale `data/`). @@ -146,6 +146,7 @@ Top level: `{ season, seasonName, modes, economy, lpCapPerRound, bossOvertimeAft | `identifier`, `shopSortId` | `133`, `1` | official ordering | | `isHidden`, `isDiy`, `visible` | | `visible = !isHidden && !isDiy` (only visible chess enter the shop pool) | | `chessType` | `"PRESET"` | `PRESET` / `NORMAL` / `DIY` | +| `backup` | `{"charId":"char_611_acnipe","tmplId":null,"skillIndex":2,"uniEquipId":"uniequip_002_acnipe","potRank":0}` (`chess_char_5_22_a/_b`, 妮芙) | the shop row's official stand-in fields, verbatim (`backupCharId`, `backupTmplId`, `backupCharSkillIndex`, `backupCharUniEquipId`, `backupCharPotRank`), the same on both forms: PRESET (特许) = itself, NORMAL = the 补位 stand-in fielded when the player does not own the operator (§18), DIY = none (`charId` null). The current match ignores it (every chess fields its real operator) | | `charId` | `"char_498_inside"` | operator (null for DIY) | | `name`, `appellation` | `"隐现"`, `"Insider"` | | | `rarity` | `5` | stars 1–6 | @@ -239,7 +240,7 @@ everything needed to resolve a unit for `(chessId, skillIndex, moduleId)` (`simd | Field | Example (`deputShip`) | Meaning | |---|---|---| | `bondId`, `name`, `identifier` | `"deputShip"`, `"助力"`, `14` | | -| `isCore`, `bondType`, `bondOrder`, `powerIdList` | `false`, `"REGULAR"`, `2`, `[]` | core = `isPower` (SEASON); `powerIdList` = nation/group ids for DIY bond derivation | +| `isCore`, `bondType`, `bondOrder`, `powerIdList` | `false`, `"REGULAR"`, `2`, `[]` | core = `isPower` (SEASON); `powerIdList` = nation/group/team ids for DIY bond derivation (`backups.json diy.operators[*].bonds`, §18) | | `iconId` | `"icon_deputShip"` | | | `activeCount` | `2` | official activation count | | `thresholds` | `[2,3]` | ascending member counts that raise the tier (tier = number of thresholds reached). yan `[3,6,9]`, egir `[3,5]`, sunt `[2,5]`, solo `[1]` | @@ -487,7 +488,8 @@ Glyph legend (`rows`): `…_eagle1/3` stay listed (`sources:["display"]`, belong to S1/S3). With another skill selected (DESIGN §16) the talent follows that skill's eagle (`simdata loadoutRecord`; `variants[o].bySkill[i].sources`). 2. **DIY chess** (`chess_char_5_diy1/2`, `chess_char_6_diy1/2`, `_a` and `_b` = 8 records): no `charId`, no stats/skill; `visible:false`, - name placeholder `甄选干员`. Out of scope for v1. + name placeholder `甄选干员`, not in the shop. Their picks and bond rule are in `backups.json diy` (§18); the gameplay + is not implemented yet. 3. **Module-less chess**: 蒂比 (`chess_char_2_13`) and 凛御银灰 (`chess_char_5_14`) have no module; their golden record has `module:{id:null,active:false}` and no module stat bonus. 4. **Hidden chess (17)** are kept with `visible:false`; several operators exist in two tiers with one hidden @@ -542,12 +544,16 @@ Glyph legend (`rows`): ## 16. Counts (current build) -`chess 266 (112 visible; 283 selectable skills over the visible chess, 184 module choices over 129 goldens)`, `bonds 23`, `garrisons 249 (43 effect keys)`, `items 115`, `bands 40`, `effects 361`, +`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`. +`bounty cards 129`, `tactic cards 43`, `backups: 17 stand-in units (43 forms), 4 DIY slots, 15 / 9 prototype picks (tier 5 / 6), 78 owned-6★ picks`. ## 17. Integrity guarantees (checked by the builder and `test/data.test.js`) +Every PRESET chess is its own backup and the stand-in builder gives it back field for field (§18); every NORMAL chess +(both forms) composes into its stand-in with an unlocked backup skill and, on the elite form, its module at that level; +every DIY prototype pick has a form for both slot statuses; derived DIY bonds exist (`test/backups.test.js` also +re-derives the backup fields, the stand-in numbers and the faction ids from the raw tables). Chess bonds/garrisons/tokens/base/golden ids resolve; talent tokens are in `chess.tokens`; every non-DIY chess has `skills[]` with exactly one default equal to `skill` (and every skill token listed in `chess.tokens`); golden module choices are consistent (one default iff `module.active`, base fields present; composing the default reproduces the @@ -566,3 +572,61 @@ generator and preview zones on the raw level files for every mode × round × te included) × allowed entry, and `test/sim/pathing-crosscheck.test.js` re-implements the client SPFA + smoothing over the whole map for every walkable tile of the normal / 联防 / boss fields of the 8 stages (extended by the road-over-floor preference; against the pure official algorithm: identical route lengths, never more non-blockable tiles crossed). + +## 18. `backups.json` — 补位 stand-ins and 自选 (DIY) data — `{ units, diy }` + +The data of two official features whose gameplay is not implemented yet (DESIGN 0.2.0 draft): **补位** — a NORMAL chess +whose operator the player does not own is fielded as its official stand-in (原型干员) — and **自选编队** — two tier-5 and +two tier-6 DIY slots, each filled with a 6★ the player owns or a prototype. Built by `tools/build-data.mjs buildBackups`; +`shared/standIn.js` composes it into chess-shaped records. The rules in the data (activity_table act2autochess +`charShopChessDatas`; PRTS 卫戍协议, 卫戍协议:盟约 下半/PRTS盟约记录): + +- PRESET (74, 特许干员) always fields the real operator (`backup.charId` = itself); NORMAL (55) names one of 17 stand-ins — + the 4★ 预备干员 `char_600–607`, the 6★ `char_608–615` and 领主·Sharp `char_617` (the "其它分支"); DIY (4) has none. +- 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 potential 0 (`potRank` 0 on all 55). + +`units[charId]` — the 17 stand-ins (no unit for a PRESET or DIY chess): + +| Field | Example (`char_611_acnipe`) | Meaning | +|---|---|---| +| `charId`, `name`, `appellation`, `rarity`, `profession`, `subProfessionId`, `subProfessionName`, `position`, `nationId`, `isNotObtainable` | `"char_611_acnipe"`, `"Stormeye"`, `"Stormeye"`, `6`, `"SNIPER"`, `"fastshot"`, `"速射手"`, `"RANGED"`, `null`, `true` | as on a chess record | +| `assets` | `{"avatar":"char_611_acnipe","avatarGolden":"char_611_acnipe","portrait":"char_611_acnipe_1","portraitGolden":"char_611_acnipe_1","spine":"char_611_acnipe","subProfIcon":"sub_fastshot_icon"}` | art ids (URLs in `data/assets.json`, which already carries all 17); the elite form takes the E2 art when it exists — only 领主·Sharp has it | +| `moduleNames` | `{"uniequip_001_acnipe":{"name":"Stormeye证章","typeName":"ORIGINAL"},"uniequip_002_acnipe":{"name":"Stormeye证章","typeName":"MAR-X"}}` | every module of the character (a composed record names its module on the normal form too) | +| `standsIn[]` | `["chess_char_3_21_a","chess_char_4_02_a","chess_char_5_18_a","chess_char_5_22_a","chess_char_6_01_a","chess_char_6_05_a"]` | the NORMAL base chess it replaces | +| `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★, 2 per 4★ | + +A **form** holds the operator fields of a chess record with **nothing selected**: `status`; `stats`, `trait`, `talents` +**without** a module; `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 has one); at `equipLevel > 0` `modules[]` (§2.2 shape +without `isDefault`). `buildUnitForm` uses buildChess's helpers and rules, and the build fails when `buildUnitForm` + +`composeUnitRecord` do not give back every PRESET chess field for field (each is its own backup), so a later change to +buildChess that the stand-ins would miss stops the build. No trigger deviation (§2.2, DESIGN §21.29) applies to a form — +the deviations name chess, so the 重装 stand-ins (预备干员-重装, Mechanist) keep the official `TAKE_DAMAGE` row. + +**Composition** (`shared/standIn.js`, pure ESM for the server, the sim and the client): `standInRecord(chess, backups)` is +the NORMAL chess as its stand-in — `IDENTITY_FIELDS` (ids, tier, `isHidden` / `visible`, `chessType`, `backup`, `bonds`, +`garrisonIds`, prices, merge, `status`) from the chess, every other field from the unit's form at the chess's status +with `backup.skillIndex` / `backup.uniEquipId` as the defaults, plus `standInFor` (the replaced charId: the official 补位 +mark on the avatar). The result is shaped exactly like a chess record (`skill` = the `isDefault` entry of `skills[]`; +elite `statsBase` / `traitBase` / `talentsBase` / `modules[]`), so `normalizeChess`, `resolveLoadout` (no loadout ⇒ the +backup selection) and `loadoutRecord` read it unchanged; null for a PRESET or DIY chess. **Kits are keyed by base chess +id** (`server/sim/content/index.js setupUnitKit`): a stand-in keeps the chess's ids, so its kit must be found by its +`charId`. `diyRecord(slot, charId, backups, { skillIndex, moduleId })` fills a DIY slot with a prototype (the slot's +tier and price, no 特质, the pick's derived bonds); which skill a prototype carries in a slot is not in the data. + +`diy`: + +| Field | Example | Meaning | +|---|---|---| +| `slots[slotId]` | `{"tier":5,"goldenId":"chess_char_5_diy1_b","shopLevel":5,"requirement":"TIER_6"}` | the four DIY chess `chess_char_5_diy1/2_a`, `chess_char_6_diy1/2_a` (chess.json: price 4, sell 1, `diyRequirement`, empty `bonds` / `garrisonIds`); `shopLevel` = the 调度中心 level whose `shopLevelDisplayDataDict.charChessDiySlotIdList` lists the slot | +| `prototypes[tier]` | `{"5":[…15],"6":[…9]}` | the legal prototype picks: the nine 6★ at both tiers, at tier 5 also the six 4★ that are not 先锋 / 特种 ("第5阶可额外从6名四星原型干员(先锋、特种职业除外)中选取"; `DIY_EXTRA_PROTOTYPES`). A prototype may fill a tier-5 and a tier-6 slot ("原型干员可于5、6阶之间重复选取") | +| `ownedPool[]` | 78 charIds | the owned 6★ a player may slot: obtainable, rarity = the requirement, and no chess names it — hidden chess included ("不可甄选加入已在名单中的固定干员"); each at most once per roster ("玩家已拥有干员不可重复选取"). The data does not exclude collab operators | +| `operators[charId]` | `{"name":"煌","rarity":6,"profession":"WARRIOR","subProfessionId":"centurion","obtainable":true,"powers":["rhodes","elite","yan","victoria"],"bonds":["yanShip","victoriaShip"]}` | every pick (owned pool + prototypes): `powers` = the `nationId` / `groupId` / `teamId` of `mainPower` and of every `subPower` (隐藏势力); `bonds` = the core bonds whose `powerIdList` meets them — one or several — else `economy.fallbackBondId` 协防干员 ("甄选加入的干员会根据其实际阵营所属分配核心盟约,若没有可匹配的则改为分配协防干员盟约"); every prototype gets `["emptyShip"]` | + +Not in this data (the gameplay workstreams): a player's ownership roster, 助战 borrows (`borrowCount` 20), DIY stock, the +owned-operator training bonus (`prepareStateDict`), forms and kits of owned 6★ picks (the same `buildUnitForm` builds +them once kits exist). diff --git a/docs/research/02-bonds.md b/docs/research/02-bonds.md index f0307c0d..2b2cb0fb 100644 --- a/docs/research/02-bonds.md +++ b/docs/research/02-bonds.md @@ -48,7 +48,7 @@ Core (isPower, bondType SEASON): 炎 萨尔贡 维多利亚 谢拉格 拉特兰 - "不同" (distinct): operators are identified by their normal chess id (chessNormalIdLookupDict maps *_b -> *_a), so a normal and an elite copy of the same operator count once. Exception: 助力 3-member tier counts operators that differ in name OR elite state (PRTS 修正). 独行 is only broken by 2+ DIFFERENT 独行 operators (PRTS 修正). - 调和 (maniShip): while active (>=1 调和 operator on board) every core bond (isPower=true) gets member count +1 (a single +1, not per 调和 operator), and 调和 operators receive the effects of every active core bond as if members. [ASSUMED: the +1 applies only to core bonds that already have >=1 real member on the board.] "炎佑" does not include 调和 operators' stats unless they are also 炎 (PRTS). - Item 变形同构体 (chess_item_6_09_e, canGiveBond) worn together with a bond item (trapChessData.giveBondId) makes the wearer an extra member of that bond. 14 bonds have such items; 灵巧/远见/奇迹/投资人/助力/调和/协防干员/独行/绝技 do not. -- DIY (自选) chess slots chess_char_5_diy1/2 and chess_char_6_diy1/2 have bondIds [] and are filled with a 6-star operator the player owns (diyChessDict = TIER_6). Their bond is derived from the chosen operator's nationId/groupId/teamId matched against autoChessData.bondInfoDict[*].powerIdList (e.g. yan: yan,sui,lungmen,lee,lgd; victoria: victoria,glasgow; kjerag: kjerag,karlan; egir: egir,abyssal; siracusa: siracusa,chiave; kazimierz: kazimierz,pinus; sargon; laterano). No match -> constData.fallbackBondId = emptyShip (协防干员). (bwiki: operators from those nations get the nation alliance, "others receive the 协防 designation".) +- DIY (自选) chess slots chess_char_5_diy1/2 and chess_char_6_diy1/2 have bondIds [] and are filled with a 6-star operator the player owns (diyChessDict = TIER_6). Their bond is derived from the chosen operator's nationId/groupId/teamId — of `mainPower` and of every `subPower` (PRTS 盟约 下半 record: 所属势力 and 隐藏势力; one or several core bonds; built in data/backups.json `diy.operators`, DATA.md §18) — matched against autoChessData.bondInfoDict[*].powerIdList (e.g. yan: yan,sui,lungmen,lee,lgd; victoria: victoria,glasgow; kjerag: kjerag,karlan; egir: egir,abyssal; siracusa: siracusa,chiave; kazimierz: kazimierz,pinus; sargon; laterano). No match -> constData.fallbackBondId = emptyShip (协防干员). (bwiki: operators from those nations get the nation alliance, "others receive the 协防 designation".) - Prototype substitution: a NORMAL chess whose operator the player does not own is fielded as its backupCharId (预备干员 / 原型干员) but keeps the chess's bonds and traits (PRTS: "烛煌(或对应的原型干员)"). - Mode filter: 标准模拟 (mode_single_funny / mode_multi_funny) enables only 13 bonds (炎 萨尔贡 维多利亚 谢拉格 叙拉古 精准 迅捷 坚守 助力 远见 不屈 调和 协防干员); 拉特兰 阿戈尔 卡西米尔 灵巧 奥术 奇迹 投资人 突袭 独行 绝技 are inactive there. Training/险境/绝境/终极 enable all 23. - Stat math: attribute bonuses from 盟约, strategies and equipment are "直接乘算" (PRTS 盟约记录 "盟约效果,策略效果,装备效果提供的属性加成均为直接乘算,与自持有干员的属性加成独立"). **Corrected 2026-10-01 (DESIGN §20.10):** 直接乘算 is PRTS's technical modifier class (游戏数据基础 属性基本公式: "直接乘算结果 D_t = t₁ + t₂ + … + tₙ", A = (A₀ + D_p)(1 + D_t); 作战机制: X₂ = X₁(1 + b₁% + b₂%), a skill's "攻击力+180%" being the example) — the values are SUMMED with each other and with the skills' "+X%"; "与自持有干员的属性加成独立" means they are separate from the **自持有加成** (PRTS 卫戍协议:盟约 下半, its own table: an operator the player really owns gets +5–10 % ATK / DEF / max HP by its real promotion — 精英1 Lv.1 +5/+5/–, 精英2 Lv.1 +10/+5/+5, 精英2 Lv.60 +10/+10/+10, the highest met applies), which the remake does not model. E.g. 炎 +50% ATK and an item +30% ATK -> final = base_atk x (1 + 0.5 + 0.3) (+ any skill %), not x 1.5 x 1.3 (the reading used until v2.5). diff --git a/docs/research/03-operators.md b/docs/research/03-operators.md index ab5f7b9e..802a6b81 100644 --- a/docs/research/03-operators.md +++ b/docs/research/03-operators.md @@ -26,8 +26,8 @@ Rich-text tags (`<@ba.vup>…`, `<$ba.inspire>…`) are stripped in this d ### 1.2 chessType, isHidden, backup (原型/替补) and DIY (甄选) - `PRESET` (74): 特许干员 — all 4★ (19) / 5★ (48) and 7 non-gacha 6★ (伺夜, 信仰搅拌机, 歌蕾蒂娅, 魔王 x2, 流明, 溯光星源); usable even if the player does not own them. -- `NORMAL` (55): all 6★ gacha operators. If the player owns the operator, their own copy is used; otherwise a friend-support copy (up to `borrowCount`=20) or the **backup** operator: `backupCharId` is a special non-obtainable stand-in (预备干员 4★ `char_600..607` or 6★ "罗德岛特派高级干员" `char_608..617` = 郁金香/Sharp/Mechanist/Stormeye/Pith/Touch/Raidian/Misery/领主·Sharp) with `backupCharSkillIndex`. Backups keep the chess's bonds and 特质. **For the fan remake: always use the real operator** (no ownership system); backup data is kept in JSON (`backup`). -- `DIY` (4): `chess_char_5_diy1/2_a`, `chess_char_6_diy1/2_a` — 甄选 slots (2 in tier 5, 2 in tier 6). `diyChessDict` = `TIER_6` means the player may put in **one of their own 6★ operators** not already in the pool; bondIds = [] and garrisonIds = null, so it gets the fallback bond `emptyShip` (协防干员) and no 特质. Status same as tier 5/6 chess. Remake suggestion [ASSUMED]: either drop DIY slots or let each player pick any 6★ from a curated list before the match. +- `NORMAL` (55): all 6★ gacha operators. If the player owns the operator, their own copy is used; otherwise a friend-support copy (up to `borrowCount`=20) or the **backup** operator: `backupCharId` is a special non-obtainable stand-in (预备干员 4★ `char_600..607` or 6★ "罗德岛特派高级干员" `char_608..617` = 郁金香/Sharp/Mechanist/Stormeye/Pith/Touch/Raidian/Misery/领主·Sharp) with `backupCharSkillIndex`. Backups keep the chess's bonds and 特质. **For the fan remake: always use the real operator** (no ownership system); backup data is kept in JSON (`backup`) — since 0.2.0 also in the built data/chess.json (`backup`), with the 17 stand-ins built in data/backups.json (docs/DATA.md §18). +- `DIY` (4): `chess_char_5_diy1/2_a`, `chess_char_6_diy1/2_a` — 甄选 slots (2 in tier 5, 2 in tier 6). `diyChessDict` = `TIER_6` means the player may put in **one of their own 6★ operators** not already in the pool; bondIds = [] and garrisonIds = null: no 特质, and the bonds come from the chosen operator's factions — `mainPower` and every `subPower` against the core bonds' `powerIdList`, one or several — else the fallback bond `emptyShip` (协防干员) (PRTS 卫戍协议; data/backups.json `diy.operators`, DATA.md §18). Status same as tier 5/6 chess. Remake suggestion [ASSUMED]: either drop DIY slots or let each player pick any 6★ from a curated list before the match. - `isHidden = true` (17 chess): not offered in the current shop pool. Best explained as **上半期 entries retired in the 下半期 rebalance** (official news 5114: "调整部分上半期预设干员的等阶、特质及所属盟约"): 8 of them are operators that now have a different visible tier entry; `chess_char_1_15_a` 盟约·辅助干员 (char_616_pithst, bonds 调和+协防干员) is a special piece granted only by strategy band effect `aceffect_band_42` 优等生 (round 1: gain 1 special operator); the other 8 (红豆, 地灵, 崖心, 协律, 见行者, 巫恋, 蜜蜡, 瑰盐) were dropped from the pool. For the remake, **exclude hidden chess from the shop pool** (keep them in data only; a few effects may still reference them - verify in shop/garrison research). Operators appearing in two tiers: 锡人 (char_4151_tinman): chess_char_1_16 hidden, chess_char_2_19; 耶拉 (char_4013_kjera): chess_char_3_20, chess_char_4_03 hidden; 录武官 (char_4196_reckpr): chess_char_4_15 hidden, chess_char_5_23; 白面鸮 (char_128_plosis): chess_char_4_21, chess_char_5_16 hidden; 百炼嘉维尔 (char_1026_gvial2): chess_char_4_23, chess_char_5_18 hidden; 魔王 (char_4134_cetsyr): chess_char_4_25, chess_char_5_09 hidden; 华法琳 (char_171_bldsk): chess_char_4_26, chess_char_5_04 hidden; 妮芙 (char_4146_nymph): chess_char_5_22, chess_char_6_10 hidden. Hidden list: 1_05 红豆, 1_11 地灵, 1_15 盟约·辅助干员, 1_16 锡人, 2_03 崖心, 2_15 协律, 3_07 见行者, 3_15 巫恋, 4_03 耶拉, 4_05 蜜蜡, 4_08 瑰盐, 4_15 录武官, 5_04 华法琳, 5_09 魔王, 5_16 白面鸮, 5_18 百炼嘉维尔, 6_10 妮芙. - Owned-operator bonus (`autoChessData.prepareStateDict`, applies in the real game only when the player owns the operator; **not needed for the remake**): aceffect_char_1 ATK×1.05; _2 ATK×1.05 DEF×1.05; _3 ATK×1.10 DEF×1.05 HP×1.05; _4 ATK/DEF/HP×1.10 (by the player's own training level; community: E1 / E2 Lv1 / E2 Lv60+). @@ -1987,4 +1987,4 @@ Consequences for the current pool: The per-match ban removes every visible chess whose bonds are **all** in the disabled set. The rule is verified; see 01 Addendum A2. Elites of banned chess are also unobtainable. Hidden chess (17) stay out of the shop as §1.2 says. ### C4. DIY (甄选) recommendation -The 2024 rule text reads "对于五六阶干员,除了目标干员外,还各共开放了2个甄选干员名额,博士可以选择等阶加入精英干员或自己在活动外已有的六星干员". The remake has no account roster. **Recommendation:** v1 disables the 4 DIY chess, so they are not in the pool or the copy tables. v2 lets each player pre-pick up to 2 T5 and 2 T6 from a curated 6★ list. Stats come from `character_table` at the tier's status. The bond is derived from nation/group/team through `powerIdList`, else 协防干员. There is no 特质. +The 2024 rule text reads "对于五六阶干员,除了目标干员外,还各共开放了2个甄选干员名额,博士可以选择等阶加入精英干员或自己在活动外已有的六星干员". The remake has no account roster. **Recommendation:** v1 disables the 4 DIY chess, so they are not in the pool or the copy tables. v2 lets each player pre-pick up to 2 T5 and 2 T6 from a curated 6★ list. Stats come from `character_table` at the tier's status. The bond is derived from the nation/group/team of `mainPower` and every `subPower` through `powerIdList` (several core bonds possible), else 协防干员 (data/backups.json `diy.operators`, DATA.md §18). There is no 特质.