fbcbfdffbc7294a8d7dcfb5113e7ebe67876e808
4
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
ddf8c39ed0 |
feedback7 R22-VOICES: the Japanese voice dub as a second tree beside the Chinese one — audio.voiceJp (the same slots and file names from ArknightsAssets2 voice/: 2674 files, 89.4 MB, for the 191 voiced operators), 设置 → 语音语言 中文 / 日本語 (default 中文, not tied to the interface language), a JP line the manifest or the host lacks plays the Chinese one; the full zip ships both dubs (one switch, tools/package.mjs FULL_ZIP_JP_VOICE), the lite zip stays art-free (the owner's request of 2026-10-08 「全套的日配语音」); golden: unchanged
- tools/assets/plan.mjs: one voiceTree() per dub — audio.voice (--voice-lang, cn by default) and audio.voiceJp (VOICE_JP_LANG, always the JP dub, audio/voice/jp/<charId>/cn_nnn.mp3); fetch-assets plans and downloads both (stats.voiceJpChars), so setup (checkAssets walks every listed URL) fetches both too. - data/assets.json regenerated with the project's tool (node tools/fetch-assets.mjs --add-only, raw.githubusercontent.com, 107 s): the only change is audio.voiceJp + stats (+2674 files, +89,388,041 bytes, voiceJpChars 191) + hash — the rest is byte-identical; the JP tree is the Chinese one with the folder swapped (191 × 14 files, every file a valid MP3). The audio files are not committed (public/assets/ is git-ignored). - public/js/audio.js voiceLine(): 'jp' draws from voiceJp and falls back to the Chinese line per slot (a JP entry the manifest lacks) and per line at play time (the Chinese file of the same name when the host lacks the JP one — same token, same gate); operators without voice (stand-ins, 盟约·辅助干员, summons) stay silent. setVoiceLang(). - settings: voiceLang 'cn' | 'jp' (VOICE_LANGS, sanitizeSettings), the 语音语言 row under 干员语音 (each dub named in its own language, like the language switch), 语音语言 in the en / ja / ko / zh-TW packs. - tools/package.mjs FULL_ZIP_JP_VOICE (true): false holds the JP files out of the full zip (and its update zip) — not missing, not orphans, never in an update's `removed`; setup then downloads them. - Sizes measured: art download 548 MiB (was 463), full zip ≈ 505 MB (0.2.1: 428 MiB + 76 MiB of zipped JP voice), unzipped 711 MB (package --dry-run); lite zip unchanged. README, DEPLOY, ASSETS, setup's fallback size updated; PLAYING voice paragraph; §21.30 "Changed in 0.2.2" note. Tests: test/feedback7-voices.test.js (new: plan, manifest, settings, package switch), test/ui/audio.test.js (voiceLine, the manager's dub choice and fallback), test/ui/gameLogic.test.js, test/docs-consistency.test.js — all fail on the parent. |
||
|
|
f2bec76176 |
feedback5 WAC: players rebind the in-match shortcuts in 设置 → 快捷键 (community request 「快捷键可不可以自己设置」, the owner's decision of 2026-10-07)
- The settings (sp.pref.settings) hold a key map, action → KeyboardEvent.code, for refresh / freeze / level-up / retreat / sell / ready (the ready key also pauses a solo battle); the defaults are the 0.1.4 keys R F D Q X Space, so nothing changes for a player who never opens the section. sanitizeSettings keeps each saved key that may be a shortcut and gives any other its default; not a map, or two actions on one key, gives the defaults. - One lookup, actionForKey (the character typed first, then the physical key: the 0.1.4 code-or-key match, identical for the defaults), serves shortcutFor(e, keys) in game.js and the facing wheel; the modifier, text-field, repeat and overlay guards are unchanged. The shop bar, ready / pause and underframe key hints read the map. - 设置 → 快捷键 (the one SettingsModal, in a match and on the title screen): each action with its key; click or Enter waits, the next key binds; Esc cancels (the dialog stays open), Tab leaves; Ctrl / Alt / ⌘ combinations and the interface keys (Esc, Tab, Enter, arrows, F1–F12) are refused; a key in use is swapped and the line under the list names both; 恢复默认. Esc stays fixed. Touch-only devices: a keyboard note and a folded list; one column under 768 px. - Tests: test/ui/feedback5-hotkeys.test.js (map, sanitising, conflicts, lookup, capture, handlers and hints with a rebound key), test/ui/gameLogic.test.js (sanitizeSettings now returns keys), test/ui/hotkeys.e2e.test.js (SP_E2E=1: 撤退 rebound to W with the keyboard only in the mock match; phone width). Golden unchanged (client UI only). |
||
|
|
c5e8d13636 |
feedback5: merge feedback4 (beb0296) — PR #73 (operator battle voices) ported to the split layout (the voice setting into ui/gameLogic/settings.js, the gameLogic.js shim unchanged; onResult and DetailPanel voice stay in screens/game.js, which needed its store import back; the sim's 'engage' in server/sim/ai.js performAttack, still the one battle/combat.js and devices.js call; plan.mjs / fetch-assets.mjs merged with --add-only, extraOperators and moduleTypes; the 干员语音 slider through t() with English); golden: roster / bonds / fields / standins / diy differ only in events.engage, matches unchanged
Ported by hand: - public/js/ui/gameLogic.js is a re-export shim on feedback5: #73's DEFAULT_SETTINGS / sanitizeSettings `voice` hunk went into public/js/ui/gameLogic/settings.js. - public/js/screens/game.js: MatchScreen still lives there, so #73's onResult (battleRunner 'result' → resultSpeaker / resultVoiceSlot) and `voice=${combat}` on the DetailPanel auto-merged in place. feedback5's game.js no longer imported `store` (the split moved its other users), so onResult's store.get() would have thrown into its try/catch and the 结算 line would never have played: `store` is imported again. `localAsset` stays dropped. - public/js/ui/settings.js (i18n phase 1): the slider is `label=${t('干员语音')}`, public/i18n/en.json "干员语音": "Operator Voices" (next to Music / Sound Effects). - tools/assets/plan.mjs: buildPlan takes #73's charword / voiceLang / voiceSlots and feedback5's extraOperators / moduleTypes; the template has `modules` and audio { bgm, bossBgm, voice, sfx }. `chars` now includes the 自选 picks, so the voice loop's comment says so (the next `npm run assets` plans their lines too). - tools/fetch-assets.mjs: parseArgs keeps --add-only beside --voice-lang / --voice-all. - data/assets.json: feedback5's manifest plus #73's audio.voice (120 operators, after bossBgm, the plan order); stats files +1680 and bytes +42 041 118 as measured on feedback4, voiceChars 120; the hash is recomputed with the generator's contentHash. No other entry changed. - docs/ASSETS.md: the stats line lists modules and voiceChars. DESIGN §21.30 stays where feedback4 put it; SIM.md's 'engage' line and docs-consistency's §21.30 test auto-merged (game.js / detailPanel.js still hold the pinned code). - Auto-merged and checked: audio.js, battle/runner.js emit('result'), components.js mic icon, detailPanel.js voice prop, shared/protocol.js EV.ENGAGE, server/sim/ai.js, tools/assets/audio.mjs / cache.mjs, #73's tests. Where #73 met feedback5 work: - 补位: a chess fielded as its stand-in shows the stand-in in the detail card, and audio.js keys battle lines by UnitInfo spine (the stand-in's model). The 选中干员 line now takes detail.standIn.charId first, so the stand-in speaks, not the operator it replaces (test/ui/standin-ui.test.js pins it). A 自选 record is already the pick's. - The sim's 'engage': stand-in and 自选 units attack through the same performAttack, so it fires for them as well. Golden regenerated: every moved scenario differs only in events.engage (the new event's count; no gameplay change), proven by a field-path diff against feedback5: - roster: all 49; bonds: all 46; fields: all 22; standins: all 10 (the stand-ins engage). - diy: 101 of 109. Unmoved: diy-010/011/012/092/093 (闪灵, 夜莺, 凯尔希 squads: they only heal, and a heal never engages) and diy-077 (薇薇安娜), diy-080/081 (赫德雷), whose picks make no attack in those battles (already so on feedback5). - matches: unchanged. |
||
|
|
eb04f5dfa4 |
feedback5 R5: split the in-match UI logic into modules
public/js/ui/gameLogic.js becomes a re-export barrel. The bodies move verbatim into public/js/ui/gameLogic/*.js (shared, phases, camera, watch, bonds, shop, placement, draft, enemies, format, shortcuts, settings, result, loadout, panel). The barrel re-exports the same 96 names in the same order. isObj and int gain export on shared.js so sibling modules can import them; they stay off the barrel. No importer changes. |