feedback5: merge feedback4 (3af5b84) — PRs #186 / #134 / #185 / #24 / #183 ported to the split layout (terrainInfo / TERRAIN_TIPS into a new ui/gameLogic/terrain.js re-exported by the gameLogic.js barrel, closesOnFieldPress into ui/gameLogic/shortcuts.js, the rest in place; 42 strings through t(), #183's 设置 too); golden unchanged
Ported by hand: - public/js/ui/gameLogic.js is a re-export shim on feedback5: #185's TERRAIN_TIPS / terrainInfo went into the new public/js/ui/gameLogic/terrain.js (the barrel gains one re-export line); closesOnFieldPress 'terrain' into ui/gameLogic/shortcuts.js. - i18n (docs/I18N.md): every new user-visible string goes through t() with an English entry in public/i18n/en.json (42, after the 补位 strings): the terrain names / tags / fact table are N_() and translated where terrainInfo hands them out, the mechanism lines are msgids with their numbers as params (a line with an optional half is two whole msgids, the list joins use an array param), the card's 地形机制 / 这一格 titles in ui/detailPanel.js. Official EN terms where the EN client has them (stage_table tileInfo: Active Originium, Mire, Exhaust Grille, Deep Water Zone, Incursion Point, Protection Objective, Tunnel Entry / Exit, High Ground; Camouflage). The Chinese output is byte-identical to feedback4's terrainInfo on all 5187 tiles of the 13 stages and on synthetic stages. - public/js/screens/game.js (MatchScreen still lives there): the import keeps feedback5's names plus terrainInfo / fieldTile; the terrain stage is the one view.setStage gets, so it includes feedback5's fieldStage — a 联防 field is played on its own map (GitHub #41), and a tap there explains that map's tile, not the round stage's. The tileClick handler and render/app.js emitTileClick / ui/fallbackField.js auto-merged in place. terrainInfo reads the stage only, so a 补位 / 自选 board explains its tiles the same way (their pieces only change a piece's art and name). - public/js/ui/detailPanel.js: the terrain branch of resolveDetail before feedback5's stand-in / 自选 helpers. - public/js/screens/title.js (#183): feedback5's LangToggle / t() imports plus GIcon / SettingsModal; the gear button's aria-label / title are t('设置') (en.json already has "Settings"). - tools/fetch-assets.mjs / tools/assets/downloader.mjs: --add-only (keepExisting, the font skip) beside #24's --asset-source / SP_ASSET_SOURCE and the shared MirrorPolicy; feedback5's extraOperators / moduleTypes and the voice plan unchanged. - data/assets.json: feedback5's manifest plus #134's audio.sfx.battle.leak (after heal, the plan order); stats files 6993 → 6994 and bytes +23 240 as measured on feedback4; the hash recomputed with the generator's contentHash (c01aa739a2d3 → 6a547fc5c937). A field-wise JSON diff against feedback5 shows only those four fields. - docs: DESIGN §24 intro and §24.5 / §24.6 as on feedback4 (the rest of DESIGN.md is feedback5's); ASSETS.md, DEPLOY.md, PLAYING.md auto-merged. - Auto-merged and checked: audio.js (the sim still emits ['leak', id], server/sim/battle/deploy.js), render/style.js, textures.js, tiles.js, board3d/materials.js, boardArt.js, tools/assets/*, tools/setup.mjs, extract.py, the tests. Checks: the PRs' unit tests (audio 22, gameLogic 44, terrain-detail 1, originium-art 4, boardart 15, board3d-extract 9, asset-network 21, fetch-assets-shrink 4), i18n 9 / i18n-data 8 / i18n-server 4, client-static 313, docs-consistency 24, kits_layout 6 pass; lint 0 errors (no new warnings), check:imports, typecheck; golden: all 283 scenarios match, nothing regenerated.
This commit is contained in:
commit
7059528c47
40 files changed
+1944
-97
No files matched your search
+2
-2
@@ -131,7 +131,7 @@ The `stem` of a Spine model is the upstream file name. Two examples: `char_107_l
|
||||
- **Fonts:** OTF/TTF files are converted to WOFF2 by a built-in encoder (`tools/assets/woff2.mjs`: Brotli with null transforms).
|
||||
- Its output was verified lossless against Google's reference `woff2` decoder.
|
||||
- `fonts.css` lists WOFF2 first and falls back to the original file.
|
||||
- Images stay PNG. WebP conversion is not done: it would need a native dependency.
|
||||
- Images stay PNG. WebP conversion is not done: it would need a native dependency. The local-client board textures are the exception: `tools/local-extract/extract.py` (Python, where Pillow is already a dependency) writes WebP copies of the 12 textures the 3D board downloads (`WEBP`: colour maps lossy at quality 95 with the alpha and the RGB under transparent texels kept, normal and data maps lossless) and `data/local-assets.json` lists the copies; the PNGs stay beside them for `tools/crop-board-atlas.mjs`. `extract.py --webp` adds the copies to an existing extraction without the client.
|
||||
|
||||
## Manifest schema (`data/assets.json`)
|
||||
|
||||
@@ -186,7 +186,7 @@ All paths are URL paths relative to the site root, for example `/assets/char/ava
|
||||
defenceStart, defenceUnite, battleOverReduce, battleOverNoReduce, battleOverNormal, goFirst,
|
||||
disconnect, settlementSucceed, settlementFail, settlementTeam, settlementBossSign,
|
||||
goodEvaluation, load, start, matchSucceed, matchFail, matchCancel, joinRoom },
|
||||
battle: { deploy, tokenDeploy, charDie, enemyDie, enemyDieHeavy, enemyHit, heal, win, lose, killCoin },
|
||||
battle: { deploy, tokenDeploy, charDie, enemyDie, enemyDieHeavy, enemyHit, heal, leak, win, lose, killCoin },
|
||||
units: { [charId|tokenId|enemyId]: { attack?, hit?, skill?, skills?: {[skillIndex]: url}, die?, born?,
|
||||
mix?: { [attack|hit|die|born]: { p?, vol? } } } }
|
||||
}
|
||||
|
||||
+27
-1
@@ -36,6 +36,30 @@
|
||||
|
||||
等价的手动命令:`npm ci`、`node tools/setup.mjs`、`npm start`。
|
||||
|
||||
#### 国内镜像下载
|
||||
|
||||
Setup 默认使用「GitHub 原始源 → jsDelivr」,不查询公网 IP,也不请求 gh-proxy.com。GitHub 下载失败时会提示如何手动开启镜像;仅添加提示,不自动切换到第三方代理。
|
||||
|
||||
镜像方法是在完整 GitHub 链接前加 `https://gh-proxy.com/`,例如:
|
||||
|
||||
```text
|
||||
https://gh-proxy.com/https://raw.githubusercontent.com/OWNER/REPO/BRANCH/file.png
|
||||
```
|
||||
|
||||
手动开启后顺序为「前缀镜像 → 原始源 → jsDelivr」。索引、图片、Spine、音频和字体都使用此规则(音频 voice 分支跳过 jsDelivr)。镜像是第三方代理;当前只校验格式和大小,没有内容哈希校验,请自行决定是否信任并启用。npm / pip 依赖不使用 GitHub 前缀。
|
||||
|
||||
```powershell
|
||||
node tools/setup.mjs --asset-source=mirror # 手动优先国内镜像
|
||||
node tools/setup.mjs --asset-source=direct # 默认:仅原始源和 jsDelivr,不使用前缀代理
|
||||
$env:SP_ASSET_SOURCE = 'mirror' # 也可用环境变量显式启用
|
||||
```
|
||||
|
||||
`node tools/fetch-assets.mjs` 同样支持 `--asset-source=direct|mirror`。命令行优先于 `SP_ASSET_SOURCE`。默认镜像前缀为 `https://gh-proxy.com/`,可通过 `SP_GITHUB_PROXY` 指定其他 HTTPS 前缀;仅配置前缀不会启用镜像。将 `SP_GITHUB_PROXY` 设为空字符串(或全空格)可彻底禁用前缀代理,即使选择了 `mirror` 模式;未设置此变量与显式设空不同,前者使用默认前缀。Windows PowerShell 的某些版本会将空值视为删除变量,可设置 `$env:SP_GITHUB_PROXY = ' '` 或使用 `--asset-source=direct` 来明确禁用。前缀只处理 GitHub 下载链接,不重复添加。
|
||||
|
||||
镜像请求每个 URL 只尝试一次,响应头超时 8 秒,响应体有独立的空闲超时,失败即尝试原始源。连续 3 次网络错误、HTTP 错误或无效内容会在本次运行中关闭镜像,后续索引、素材和字体共享该状态;正在进行的镜像请求也会中止并回退。成功会清零连续失败次数;404 / 410 是资源不存在,不触发熔断。再次运行脚本会重新尝试手动启用的镜像。原始源的重试、已有文件跳过和 0.1.1 的清单缩减保护保持不变。
|
||||
|
||||
从历史下载记录派生的 Spine 补充贴图也按本次设置重新选择来源,禁用后不会沿用旧代理地址。
|
||||
|
||||
### 1.2 防火墙
|
||||
|
||||
- 第一次启动时 Windows 会弹出「Windows 安全中心警报」:勾选**专用网络**并点「允许访问」。
|
||||
@@ -237,7 +261,7 @@ services:
|
||||
| 任何问题 | `node tools/doctor.mjs`:Node 版本、依赖、素材完整性、端口、局域网地址、防火墙、网络类型 |
|
||||
| `端口已被占用 / EADDRINUSE` | 已经有一个服务器在运行(自启任务?)或其他程序占用 3000:换端口 `scripts\start-windows.bat --port 3001` |
|
||||
| 朋友打不开页面 | 防火墙规则 / 网络类型(1.2);确认用的是 `LAN` 地址而不是 `localhost`;访客 Wi-Fi 常开启「AP 隔离」;不在同一网络请看第 2 节 |
|
||||
| 画面是占位图、没有声音 | 素材没下完:重新运行 `node tools/setup.mjs`(会续传);缺失明细在 `.cache/assets-report.json`。GitHub 原始地址访问失败时会自动改用 jsDelivr 镜像 |
|
||||
| 画面是占位图、没有声音 | 素材没下完:重新运行 `node tools/setup.mjs`(会续传);缺失明细在 `.cache/assets-report.json`。默认仅原始源和 jsDelivr;可用 `--asset-source=mirror` 手动开启前缀镜像(见上文) |
|
||||
| 素材下载很慢 / 失败 | 网络问题可随时中断,重新运行会跳过已完成的文件;`node tools/fetch-assets.mjs --concurrency=4` 降低并发。有文件没下载成功时,素材清单 `data/assets.json` 保持不变(脚本列出缺少的条目并以非零状态结束;游戏里缺的图片用占位图,缺的声音不播放),重新运行即可补齐 |
|
||||
| 表情显示成默认图标、「玩法说明」只有文字要点 | 素材没下载完整:重新运行 `node tools/setup.mjs`(表情和教程图随其他素材一起从公开镜像下载,不需要客户端);缺失明细在 `.cache/assets-report.json` |
|
||||
| 本地提取失败 | 游戏照常运行,只是第 6 节表格里的几样换成替代样式。确认客户端已下载全部资源;Python 版本太新导致依赖安装失败时,安装 Python 3.12 后删除 `.venv-extract` 再运行 `node tools/setup.mjs --local` |
|
||||
@@ -259,3 +283,5 @@ services:
|
||||
表情(6 套 × 6 个)和「玩法说明」的 19 页教程图公开镜像也有:`node tools/setup.mjs` 会和其他素材一起下载(约 21 MB),不需要客户端;有本地素材时优先显示本地的。
|
||||
|
||||
**没有客户端的服务器**想要上表中的官方素材:从**同一版本**的完整包([Releases](https://github.com/sganggs/Stronghold-Protocol/releases))里,把 `public/assets/local/` 文件夹和 `data/local-assets.json` 复制到服务器项目目录下的相同位置。服务器每次请求都会重新读取这两处,不必重启,玩家刷新页面即可。一定要用与服务器代码相同版本的完整包:各版本提取的内容和清单可能不同(例如灼热 / 炽焰源石虫的模型是 0.1.0 之后才加入的),混用其他版本的文件会缺图或用错图。复制后 `node tools/doctor.mjs` 会显示本地素材的条目数和「3D 棋盘可用」。
|
||||
|
||||
**3D 棋盘贴图的下载量**:每位玩家进入对局时都要从开服的电脑下载 3D 棋盘的 12 张贴图。提取时会给这 12 张各写一份 WebP(颜色贴图有损、质量 95,法线和数据贴图无损),清单里列的是 WebP,同名 PNG 留在旁边给裁切工具和 setup 用。这部分下载量从约 6.7 MB 降到约 2 MB,网速慢的远程联机最明显。只有 PNG 的本地素材(例如在这一改动之前提取的)可以用提取时的 Python 环境运行 `tools/local-extract/extract.py --webp` 就地补上,只需要 Pillow,不需要客户端。
|
||||
+21
-1
@@ -2172,7 +2172,7 @@ Decisions of the owner, 2026-10-04: a 联防 devour counts members who enter alr
|
||||
|
||||
## 24. Community reports after 0.1.3
|
||||
|
||||
Reports after the 0.1.3 release. Each was checked against the official data and PRTS; anything with no source is marked [ASSUMED]. Where each is handled: a skill clip with no Begin and no own Idle plays once (德克萨斯 S2 剑雨) → §24.1; 高台 for every melee chess whose trait reads 「可以放置于远程位」 (GitHub #153, PR #69) → §24.2; the 5-阿戈尔 revives go to the first 3 members knocked out (GitHub #105, #140) → §24.3; 联防 阿戈尔 devours the operator in front whoever owns it (GitHub #140) → §24.4. Merged pull requests keep their own notes where they changed the rules: deploy-timed skills as duration skills (PR #109, §5 skill contract), the teammate's hand / temp / equipment in prep scouting (PR #129), 灵巧's knocked-out aura and the hidden-layer bonds (PR #66, research 02).
|
||||
Reports after the 0.1.3 release. Each was checked against the official data and PRTS; anything with no source is marked [ASSUMED]. Where each is handled: a skill clip with no Begin and no own Idle plays once (德克萨斯 S2 剑雨) → §24.1; 高台 for every melee chess whose trait reads 「可以放置于远程位」 (GitHub #153, PR #69) → §24.2; the 5-阿戈尔 revives go to the first 3 members knocked out (GitHub #105, #140) → §24.3; 联防 阿戈尔 devours the operator in front whoever owns it (GitHub #140) → §24.4; a special terrain tile explains itself on a tap (GitHub #184, PR #185) → §24.5; 活性源石 was two different materials on the two boards (GitHub #184, PR #185) → §24.6. Merged pull requests keep their own notes where they changed the rules: deploy-timed skills as duration skills (PR #109, §5 skill contract), the teammate's hand / temp / equipment in prep scouting (PR #129), 灵巧's knocked-out aura and the hidden-layer bonds (PR #66, research 02).
|
||||
|
||||
### 24.1 A skill clip with no Begin and no own Idle plays once — 德克萨斯 S2 剑雨 (player report) — `render/spine.js SpineActor.setSkill / update` (`SKILL_CLIP_MIN`, `skillClipOnce`, `skillEndPending`)
|
||||
|
||||
@@ -2342,3 +2342,23 @@ Reports after the 0.1.3 release. Each was checked against the official data and
|
||||
through a teammate's 幽灵鲨 equals the own chain, and her knock-out takes her owner's 5-tier slot; the own-board case
|
||||
through `uniteBattleOpts` (carry.down from a real own combat, the own combat's gains). The first three fail on the
|
||||
previous code. `feedback3-egir-down`, `bonds_core`, `unitedown`, `feedback3-unitecarry` pass unchanged.
|
||||
|
||||
### 24.5 A special terrain tile explains itself on a tap (GitHub #184, player request 「建议加入对于特殊地形的单击信息提示」) — `render/app.js` (`tileClick`, `emitTileClick`), `ui/fallbackField.js` (the board tile), `ui/screens/game.js` (`tileClick` → `terrainInfo`, `live.terrainStage` / `terrainTile`), `ui/gameLogic.js` (`terrainInfo`, `TERRAIN_TIPS`), `ui/detailPanel.js` (`TerrainDetail`, `resolveDetail`)
|
||||
|
||||
- **Asked** (GitHub #184, after 0.1.3): a tap on a special terrain tile should say what it is. The mode draws 活性源石, 沼泽, 排气格栅, 深水区, the gates and the teleports, but nothing in the client names them — the legend lived in `docs/DATA.md` and the data only.
|
||||
- **Why the ground was free**: a press on a tile that had nothing on it only closed what was open (a piece / unit card, the selection). `render/app.js` now emits `tileClick { row, col }` when neither a battle unit, a prep piece (the drag controller), a pen enemy nor the boss leader took the press, and `ui/fallbackField.js` emits the same from its own tile divs, so both field implementations behave alike.
|
||||
- **What the card says**: `gameLogic.terrainInfo(stage, row, col)` reads the glyph from `stage.rows`, its legend entry from `stage.tiles` (tileKey / height / buildable / passability) and **that stage's own terrain parameters** from `stage.special[<terrain>]` — the values `sim/content/devices.js` runs on: 活性源石 `damage 70 / atk 0.2 / attack_speed 20 / duration 300` (PRTS 特殊地形 "部署于其上的我军和经过的敌军在{duration}s内每秒受到{damage}真实伤害…"), 沼泽's stack rule (`intervalSec` 1, `aspdPerStack` −0.05, `moveMulPerStack` −0.05, `maxStacks` 10, `heavyWeight` 3, cleared on leaving — PRTS 沼泽控制), 深水区's drowning (`damage 40`, aspd −0.6, move ×0.6) plus 拒绝部署 (PRTS 深水区 地形信息; `grid.js DEPLOY_REFUSED_TILES`), 排气格栅's "operators on it cannot be targeted by enemy ranged attacks" — completed in review with the two halves that matter in play: the operator it blocks still gets attacked (the tile's buff is a 隐匿-like `stealth` flag, `devices.js enterTerrain`), and 深水区's drowning damage is sourceless damage that no 干员's 增伤 / 穿透 / 装备 applies to and is *not* 环境伤害 (`tickDeepsea`'s tags are `dot` / `periodic` / `deepsea`, deliberately not `terrain`). The gates and teleports carry no `special`, so they key on `tileKey` — 红门 (enemy gate) / 蓝门 (protection objective) / 传送入口 / 传送出口, in the words `docs/PLAYING.md` already uses. The card is a normal `ResultDialog`-less `DetailPanel` card: read-only, no protocol frame, closed by the next field press (`closesOnFieldPress` now lists `terrain`) or its own ✕.
|
||||
- **An ordinary tile still says nothing** (road / floor / wall / fence / bench → null): the press keeps its other meanings there — deselecting a piece, closing a card — and a drag still starts only on a piece.
|
||||
- **Coordinate spaces (corrected in review)**: a tap reports BOARD coordinates — `emitTileClick` picks with `pickBoardTile`, so the boss-prep transform (`prepXf.toBoard`) is applied once, in the renderer. (The first version reported the DRAWN tile from `groundTile` and the screen mapped it again, so on a Final Assault / Hidden Core prep the tap was converted twice and explained another tile.) Everywhere but that prep board the two spaces are the same: a 最终攻势 / 隐秘核心 battle renders the stage's own rows (`GEO.BOSS_RECT`), the normal and 联防 rects are stage rows. A boss PREP draws the player's half — stage rows 2–5 — as board rows 9–12, and the screen turns the board tile into the stage tile with `gameLogic.fieldTile` before the lookup (and reads the stage the board on screen is built from: the own one with the player's 机变 tile overrides, `effectiveStage`, or the plain stage while watching a teammate).
|
||||
- **[ASSUMED]**: that a player wants the official's 地形信息 here (the official shows terrain descriptions in its own level / terrain UI, not in-match — research 09 records none) and the wording of the mechanism lines: the numbers are the data's, the prose is ours (marked as ours in `TERRAIN_TIPS`). A 机变 card that switches a terrain off (模拟战场演变 · 沙尘暴停止) is not reflected — the tip explains the TILE, not the round's modifier.
|
||||
- **Tests**: `test/ui/gameLogic.test.js` (every terrain of the real stages with its own numbers: 活性源石 in 战场#04, 沼泽 in 战场#06, 排气格栅 in 战场#07, 深水区 in 战场#05; the four gate / teleport tiles; an ordinary glyph → null; out-of-range, fractional and legend-less input; the fact lines from the legend entry; a stage missing its parameters still explains the mechanism), `test/ui/terrain-detail.test.js` (the tap's target resolves into the card; a tip-less or malformed one does not), `test/ui/terrain-tip.e2e.test.js` (headless Chrome on the mock harness: a tap on 蓝门 / 红门 opens the card with its own line on BOTH field implementations — the engine canvas at the tile's own screen position and the DOM fallback's tile — while a tap on a floor tile opens nothing; and on a Final Assault PREP the tapped tile is the one the board tile maps to on the boss field, the regression the review asked for).
|
||||
|
||||
### 24.6 活性源石 is ONE material on both boards (GitHub #184, same report's second half) — `render/style.js` (`ORIGINIUM`, `linearToSrgb255` / `linearToHex`), `render/textures.js` (`originiumCanvas` / `originiumOverlay`, `MAT_DRAW.infection` / `infection2`, `PROC_LAYERS.originium` / `originium2`, `DEFAULT_ART_LAYERS.infection` / `infection2`), `render/tiles.js` (`variantMat`, the pulse tint), `render/board3d/materials.js` (`infectionMaterial`)
|
||||
|
||||
- **Reported** (GitHub #184): 「感觉源石地板的图片有点奇怪(有点简陋,另外两个源石地板的贴图不一致)」 — two originium floors that do not match. They were two different materials: with the board art installed (or `?board=2d`) the tile came from the 2D atlas cell — a beveled brick with seven randomly placed orange crystal clusters — while the 3D board drew a world-space crust with pulsing veins over the official concrete. And that 3D crust was multiplied by a per-tile fade (`edge = smoothstep(0, 0.1, min(vUv, 1 − vUv))`), so every tile of a 活性源石 area faded out at its own border and the area read as separate patches rather than one floor.
|
||||
- **One palette**: `style.js ORIGINIUM` holds the crust's dark and lit sides, the vein and the crystal grains. The values are the 3D shader's own working colours (its fragment ends in `#include <colorspace_fragment>`, so they are linear); the canvas converts them with `linearToSrgb255` — without that the 2D tile came out darker than the 3D one, which is what the first version of this change did.
|
||||
- **One recipe**: two octaves of noise make the crust mask (`smoothstep(0.38, 0.62, n·0.7 + n2·0.45)`), the ridge of the fine octave its veins (`smoothstep(0.86, 0.98, 1 − |2·n2 − 1|)`, brightened where the crust is), the rare top of a third octave the grains — the shader runs it over world-space noise, `textures.js originiumCanvas` over a *toroidal* field (the noise wraps, so a cell that is repeated over the board lines up with itself: the veins run through the tile's edge instead of stopping at it).
|
||||
- **Both reach the tile's edges**: the 3D material no longer has the per-tile fade, and the 2D cell has no frame any more (the old `bevelTile` is gone). The mire / water / smog materials keep their own fades — this section is about 活性源石, the tile that was reported.
|
||||
- **With the board art installed** the 2D tile is composed exactly like the 3D one: `DEFAULT_ART_LAYERS.infection` draws the official concrete slab (`board3d/atlas.js concrete`, the same atlas rect) and then the crust as a procedural layer; without the art the cell falls back to `MAT_DRAW.infection` (the procedural ground + the same crust). A second variant (`infection2`, the same art mirrored; `PROC_LAYERS.originium2` for the art path) is picked by tile (`tiles.js variantMat`), so a field of 活性源石 does not repeat one pattern.
|
||||
- **Not [ASSUMED]** — this is our own art: the palette and the recipe are ours, the tile it dresses and its numbers are the data's (a 机变 card can switch the terrain off, §24.5).
|
||||
- **Tests**: `test/render/originium-art.test.js` (the couplings: both renderers take the palette from `ORIGINIUM`, the canvas converts it, the recipe's thresholds agree, the 2D base slab is the same atlas rect the 3D board lays its crust on, the infection shader has no per-tile fade while the mire keeps its own, two variants are registered and picked, the pulse tint is the shared one), `test/render/originium-cell.e2e.test.js` (headless Chrome: the cell's veins hit the palette's displayed colour (`linearToHex(ORIGINIUM.vein)`), veins reach the border like the middle (no frame), the veins at opposite edges are alike (the cell joins itself), and the second variant is a different pattern).
|
||||
@@ -20,6 +20,7 @@
|
||||
| 选择策略 | 40 名策略(分队长)决定**初始目标生命值(20–45)**和一条永久规则。同盟:随机顺序轮流选,**每人 30 秒**,右上角和「决策中」显示同一个倒计时;AI 队友立即选完;队友已选的不能重复,每人可**跳过一次**(排到最后);超时自动选你**当前选中**的策略(已被队友选走则选华法琳)。独立:自由选择、不限时;同盟模拟只有你一名玩家时也不限时。选的时候可以点左侧决策顺序下方的「查看禁用盟约与干员」,再看一遍「确认本局信息」里的盟约(置灰、禁用人数)和本局禁用干员:只能查看,倒计时照常走,底部也显示轮到谁和剩余秒数;点「关闭」、点窗口外面或按 Esc 关闭,轮到下一位时会自动关闭。 |
|
||||
| 机变 | 部分回合开始前出现:同盟共 6 张卡轮流各取 1 张(首位 30 秒,其余 16 秒;只有你一名玩家时不限时),独立 3 选 1。卡片包括装备、资金、干员、盟约层数、悬赏等;**悬赏决策**为你的作战添加悬赏敌人,卡上用蓝字标出持续多久:「下场作战」/「接下来两场作战」的只出现一场或两场,之后不再出现;官方的「多轮悬赏」(原文写「之后的每场作战」)在这里也按「接下来两场作战」处理,只出现两场(如教鞭的法术大师A2·多轮战术特训)。各回合的悬赏决策按官方对局截图来出:第 3 回合是 6 张「接下来两场作战」的悬赏(3 张 1 资金、2 张 2 资金、1 张 3 资金);第 9 回合是各首领的「下场作战」悬赏和「源石虫·特训」;绝境 / 终极的第 11 回合多半是悬赏决策(也可能是机密商店或战术决策),其中的悬赏通常有 1 只特异巨兽,其余是各阵营的「下场战斗」悬赏。击倒悬赏敌人的人(联防中的队友也算)获得资金;右侧效果栏会写「还剩 N 场作战」。**机密商店**的 6 件装备都免费,和官方一样可能出现两件相同的装备(各算一张卡,可以分别被选走);第 11 回合(绝境 / 终极)的机密商店按官方:2 件 VI 阶、至少 1 件 V 阶和 1 枚盟约之币,标准 / 险境较早回合的机密商店各阶装备都可能出现。**战术决策**也和官方一样可能出现两张相同的卡(官方截图里出现过两张「补给」;各算一张卡,可以分别被选走,每张只生效一次,两人各选一张全队卡则效果叠加);第 11 回合(绝境 / 终极)的战术决策按官方截图只出盟誓、驰援、列装 / 财富 / 补给 / 整备 / 升华等增益卡,不出削弱敌人的卡和战场演变卡。每张卡左上是图标和名称,下面写着完整效果(与详情卡相同的官方描述,手机上也显示);已被选走的卡变暗,右上角显示选走它的玩家头像(悬停可看名字)。选卡要**点两次**:第一次只选中(金框 +「确认选择 · 再次点击」),再点同一张或点右上的「确认选择」才生效;点别的卡换选,按 Esc 或点空白处取消。 |
|
||||
| 休整期 | 购买、摆阵、配装备、冻结 / 刷新、升级调度中心;同盟有倒计时(65–215 秒,随回合增加);独立模拟、以及只有你一名玩家(只带 AI 队友)的同盟模拟不限时。所有人「准备就绪」即提前开战,全员就绪前可取消。 |
|
||||
- **特殊地形点一下就有说明**:战场上的**活性源石**、**沼泽**、**排气格栅**、**深水区**,以及**红门 / 蓝门 / 传送点**,点一下就会弹出它自己的说明卡——名称、机制,以及**这一关自己的数值**(比如战场#04 的活性源石:每秒 70 点真实伤害、攻击力 +20%、攻击速度 +20、持续 300 秒)。休整期和作战期都能点。普通地板 / 道路 / 高台点了不会弹东西,所以点一下仍然只是「取消选中、关掉卡片」。
|
||||
| 作战 | 每人在自己的战场各自作战(战斗在你的浏览器里模拟,2 倍速)。干员按**逐列从左到右、每列从上到下**的顺序(官方「从上到下>从左到右」:最左一列最先)自动部署并消耗部署费用(初始 10,+1/秒)。时限 45–115 秒(实际秒数,即屏幕上的倒计时),时间到仍存活的敌人算漏怪。有敌人进入蓝门时,顶栏的目标生命值会**立即**显示扣除后的数值(红字 + 「−N」,每回合至多 10 点),结算时确定;联防阶段标注「联防中」,队友拦下的部分最后不扣。左侧队伍栏同样显示队友的待扣生命值。被击倒的干员**留在倒下的格子上**(倒地姿势、略微变灰),之后也在这一格再部署(与官方一样;倒在其他干员或召唤物初始位置上的,会回到自己的初始位置躺下,召唤物已经消失也一样);因自身效果强制退场的干员(史尔特尔「余烬」结束、耀骑士临光 2 技能结束等)同样倒在原地、在原地再部署;倒地干员所在的格子**不会被占用**,突袭盟约的再部署、援军、召唤物都会避开它。头上的圆圈是再部署倒计时:绿色圆环 + 秒数;变成黄色「DP」表示部署费用不够。血条下方的一行是**元素损伤**(与原版一致:元素图标 + 白条):干员为带图标的彩色圆盘,敌人为小号纯色圆盘,右侧白条是剩余元素值,像血条一样从右往左减少,白条耗尽的那一下就是爆条(被大额元素损伤一次打掉一截时白条也会一次少一截,例如掠海漂移体每击约为 25%–50%);爆条后进入爆发冷却(灼燃 / 神经 / 侵蚀 10 秒,敌方侵蚀 8 秒,凋亡 15 秒),这时白条变成**元素颜色**(神经青绿、侵蚀蓝、灼燃橙红、凋亡灰紫)并在冷却期间慢慢回满、图标闪烁——彩色条表示已经爆条、正在承受爆发效果,不是还剩的元素值;期间所有元素都不会累积也无法被治疗,结束后清零。元素爆发造成的是**无来源伤害**,不吃干员的增伤、穿透和装备加成(例如深巡打海嗣时灼燃爆发固定 7000),击杀仍记在爆条的干员名下;元素脆弱只提高元素伤害,不加快元素条;脆弱不影响元素伤害。已被击杀的敌人不会再被附加元素损伤。 |
|
||||
| 联防 | 见第 5 节。 |
|
||||
| 结算 | 扣 LP、发放悬赏资金、结算层数;LP ≤ 0 的玩家淘汰(其干员回到公共卡池)。 |
|
||||
@@ -94,6 +95,7 @@
|
||||
- 联防中击杀悬赏敌人,资金归击杀者。
|
||||
- 联防后仍然存活的敌人,按原主人扣 LP;没人完美作战时直接扣。
|
||||
- 漏怪的玩家在顶栏中间(击倒数旁)看到橙色的「×N」标签:你漏过、仍在联防战场上的敌人数(含还没出场的,**不设上限**),队友每击倒一个就减一(会分裂或召唤的敌人被击倒时,分裂出的敌人也算你的,数字会相应增加);目标生命值同时显示为扣除 min(N, 10) 后的数值。左侧队伍栏里漏怪队友的行也显示 ×N(与战场上的击倒同步更新;鼠标悬停可看到是谁漏过的敌人)。
|
||||
- **有敌人走进蓝门就会响一声**:不等它真的扣到目标生命值——一回合里超过 10 点上限的那部分、数据里标明不计数目的敌人(BOSS 部件之类),以及联防里漏过去、随后被队友清掉的那几只,目标生命值都不会再扣,但这一声照样会响。播的是**原版关卡里怪进蓝门那一声**(官方音效表里的 `ON_ENEMY_REACHED_EXIT`,任何一关都是它)。你正在看哪个战场就听哪个战场的,所以看队友的战场、以及漏怪后观看联防时同样听得到。这一声 1.44 秒,我们按官方的「同时只允许一个」做成 **1.5 秒内共用一声**:一波打穿防线只响一遍(不会叠成一片),过一会儿再漏会再响。
|
||||
- 每个普通回合每人**最多扣 10 点 LP**。
|
||||
|
||||
## 6. 盟约
|
||||
|
||||
Reference in new issue
Block a user