fix(ui): 复用 HEAD、启用 i18n 并校准设置页配色与内容
This commit is contained in:
1 parent
1d09481ec1
commit
09bc41362d
9 files changed
+435
-255
No files matched your search
@@ -0,0 +1,66 @@
|
||||
# Color Palette(原版配色表)
|
||||
|
||||
> 来源:`module_82347` 的 `C9i`(`E9i()` 单例)构造器。
|
||||
> 这些值直接来自原版主题对象,不是从截图取色。
|
||||
> Kotlin 侧对应:`TankiOffline/app/src/jsMain/kotlin/App/Browser/Ui/Palette.kt`
|
||||
|
||||
## 基础
|
||||
|
||||
| 原字段 | 值 | 用途 |
|
||||
|---|---|---|
|
||||
| `z1hz_1` | `rgb(255,255,255)` | 主文字 |
|
||||
| `a1i0_1` | `rgb(0,0,0)` | 黑色 |
|
||||
| `b1i0_1` | `rgba(255,255,255,0.05)` | 极淡面板 |
|
||||
| `c1i0_1` | `rgba(255,255,255,0.1)` | 面板背景 |
|
||||
| `d1i0_1` | `rgba(255,255,255,0.15)` | 分隔线 |
|
||||
| `e1i0_1` | `rgba(255,255,255,0.2)` | 控件边框 |
|
||||
| `f1i0_1` | `rgba(255,255,255,0.25)` | HEAD 分隔线 |
|
||||
| `g1i0_1` | `rgba(255,255,255,0.3)` | 次级文字/边框 |
|
||||
| `h1i0_1` | `rgba(255,255,255,0.4)` | 弱文字 |
|
||||
| `i1i0_1` | `rgba(255,255,255,0.5)` | 说明文字 |
|
||||
| `j1i0_1` | `rgba(255,255,255,0.6)` | 菜单未激活 |
|
||||
| `k1i0_1` | `rgba(255,255,255,0.7)` | 较强文字 |
|
||||
| `l1i0_1` | `rgba(255,255,255,0.9)` | 标签文字 |
|
||||
| `m1i0_1` | `rgba(255,255,255,0.95)` | 高亮文字 |
|
||||
|
||||
## 主色
|
||||
|
||||
| 原字段 | 值 | 用途 |
|
||||
|---|---|---|
|
||||
| `b1i1_1` | `rgb(255,188,9)` | 主黄色 / 菜单激活线 |
|
||||
| `d1i1_1` | `rgb(255,214,48)` | 黄色高亮 |
|
||||
| `e1i1_1` | `rgb(0,215,255)` | 青色 |
|
||||
| `f1i1_1` | `rgb(0,212,255)` | 青色(主) |
|
||||
| `i1i1_1` | `rgb(116,186,61)` | 绿色 |
|
||||
| `j1i1_1` | `rgb(232,139,0)` | 橙色 |
|
||||
| `h1i1_1` | `rgb(191,213,255)` | 浅蓝 |
|
||||
| `v1i0_1` | `rgb(255,124,124)` | 红色 |
|
||||
| `z1i0_1` | `rgb(235,87,87)` | 深红 |
|
||||
| `l1i1_1` | `rgb(197,197,197)` | 灰色 |
|
||||
| `x1i0_1` | `rgb(78,80,95)` | 深灰 |
|
||||
| `y1i0_1` | `rgb(54,58,66)` | 更深灰 |
|
||||
|
||||
## 渐变
|
||||
|
||||
| 原字段 | 值 | 用途 |
|
||||
|---|---|---|
|
||||
| `d1i2_1` | `radial-gradient(#203040 0%, #03080D 100%)` | 子页面根背景 |
|
||||
| `e1i2_1` | `linear-gradient(to top right, #4A4A5B 0%, #32363E 100%)` | 顶部渐变 |
|
||||
| `f1i2_1` | `linear-gradient(to bottom, #2E3235 0%, #2E3235 0.01%, rgba(46,50,53,0.1) 83.57%, rgba(46,50,53,0) 100%)` | 菜单纵向渐变 |
|
||||
| `q1i1_1` | `linear-gradient(135deg, #FF5309 0%, rgba(255,83,9,0) 71.43%)` | 橙红渐变 |
|
||||
| `r1i1_1` | `linear-gradient(135deg, #FFBC09 0%, rgba(255,188,9,0) 66.67%)` | 黄色渐变 |
|
||||
| `s1i1_1` | `linear-gradient(135deg, #AD87FF 0%, rgba(173,135,255,0) 68.75%)` | 紫色渐变 |
|
||||
| `t1i1_1` | `linear-gradient(135deg, #16B9FF 0%, rgba(22,185,255,0) 84.37%)` | 蓝色渐变 |
|
||||
| `u1i1_1` | `linear-gradient(225deg, #BFFF56 0%, rgba(191,255,86,0) 59.26%)` | 绿色渐变 |
|
||||
|
||||
## 使用规则
|
||||
|
||||
- 子页面根背景:`Palette.PageGradient`
|
||||
- 面板:`Palette.Panel`(`rgba(255,255,255,0.1)`)
|
||||
- 面板边框:`Palette.PanelBorder`(`rgba(255,255,255,0.2)`)
|
||||
- 分隔线:`Palette.Divider`(`rgba(255,255,255,0.25)`)
|
||||
- 主文字:`Palette.White`
|
||||
- 说明文字:`Palette.White50`
|
||||
- 菜单未激活:`Palette.White60`
|
||||
- 菜单激活线/主强调:`Palette.Yellow`
|
||||
- HEAD 背景:`Palette.TopGradient`
|
||||
@@ -2,6 +2,14 @@
|
||||
|
||||
> 来源:`3dtank.com/play/static/js/unpacked/module_82347.js` 的 `SettingsComponentStyle` / `SettingsMenuComponentStyle` / `SettingsButtonsComponentStyle` / `GameSettingsStyle` / `DropDownStyle` / `CheckBoxComponentStyle` / `InputRangeComponentStyle`。
|
||||
> 方法:在无头页面中加载原包模块,patch `module_37036` 的 `ld` 捕获样式类,实例化样式类后逐个执行 `duv_1[0]` 样式函数,并用 recording style object 记录 `rpf` / `gp8` 调用。
|
||||
> 配色:`ColorPalette.md` / `Palette.kt`,直接来自 `C9i`(`E9i()`)构造器。
|
||||
|
||||
## 0. 页面外壳
|
||||
|
||||
- 子页面**复用主页 HEAD**,只把左侧 VIP 区域替换成退出键;组队、等级、昵称/经验、Logo、货币、F11、退出都不变。
|
||||
- 不再使用独立 Breadcrumbs 顶栏。
|
||||
- 设置菜单顺序:游戏显示 / 战斗 / 画面 / 音效 / 操控 / 账户 / 安全。
|
||||
- 文案全部走 `Translations` i18n,语言下拉切换 `Translations.LoadLocale` 并重绘。
|
||||
|
||||
## 1. 页面骨架
|
||||
|
||||
|
||||
@@ -7,15 +7,15 @@
|
||||
|
||||
| 屏幕 / 组件 | 文件 | 说明 |
|
||||
|---|---|---|
|
||||
| HEAD 顶栏 | `app/src/jsMain/kotlin/App/Browser/Ui/HeadScreen.kt` | Emotion;VIP→子页面退出键、组队两段、内部分隔线、货币/F11/退出 |
|
||||
| 子页面 Breadcrumbs | `LobbyScreens.kt` | 6em 高;返回 / 标题 / 红宝石+水晶 / F11 / 退出 |
|
||||
| HEAD 顶栏 | `app/src/jsMain/kotlin/App/Browser/Ui/HeadScreen.kt` | Emotion;所有页面复用;子页面只把 VIP 替换为退出键,其余组队/等级/昵称/货币/F11/退出不变 |
|
||||
| 子页面外壳 | `LobbyView.kt` + `lobby3.css` | `ms-top` 始终显示;`#lobby-content` 从 6em 开始;不再使用独立 Breadcrumbs 顶栏 |
|
||||
| 大厅首页 | `app/src/jsMain/kotlin/App/Browser/Ui/HomeScreen.kt` | Emotion;Play / 主菜单 / Footer / BattlePass / 公告 |
|
||||
| 车库 | `app/src/jsMain/kotlin/App/Browser/Ui/GarageScreen.kt` | React;默认「总览」+ 右侧 4 个已装配件;分类栏、底盘/炮塔选择条、迷彩网格、左右面板、底部选择条 |
|
||||
| 商店 | `app/src/jsMain/kotlin/App/Browser/Ui/LobbyScreens.kt` | 分类页签 + 物品卡片(分类/名称图标、稀有度、VIP、货币价格)+ 右侧详情/购买确认 |
|
||||
| 幸运礼盒 | 同上 | 4 种礼盒美术、钥匙图标/数量、可能奖励稀有度、右侧详情/开启确认 |
|
||||
| 战斗选择 | 同上 | 模式筛选(DM/TDM/CTF/CP/AS/JGR/SGE/RUGBY 图标)+ 战场列表 + 右侧详情/加入/创建入口 |
|
||||
| 任务 | 同上 | 分类侧栏(主要/每日/每周/星级挑战/合约)+ 任务卡(进度、奖励图标、领取/去完成)+ 星级挑战横幅 + 离线示例 |
|
||||
| 设置 | 同上 | 8 个分类侧栏;开关/滑杆/下拉/按键表;账户、安全、支持分组;全部重置。**已按原包 `SettingsComponentStyle` 展开值校准**(72.25em 内容区、18em 菜单、46.875em 面板、1.875em 内边距、黄色滑动条/左侧线),详见 `3DTank/docs/SettingsStyleTable.md` |
|
||||
| 设置 | 同上 | 7 个分类:游戏显示/战斗/画面/音效/操控/账户/安全;开关/滑杆/下拉/按键表;文案走 i18n;样式与配色按原包校准 |
|
||||
| 聊天 | 同上 | 频道侧栏(公共/战斗/军团/私聊)+ 消息行(头像/作者/时间)+ 发送;军团频道读 `ClanChatState` |
|
||||
| 新闻 | 同上 | 左列表 + 右详情;真实图片/日期/正文;无数据时显示带标记的离线示例 |
|
||||
| 军团 | 同上 | 未加入:军团美术、创建/搜索、许可证;已加入:军团头图、信息/成员/请求/邀请页签与成员表 |
|
||||
@@ -32,6 +32,8 @@
|
||||
| 文件 | 内容 |
|
||||
|---|---|
|
||||
| `UiTheme.kt` | 颜色/字体/间距 token、Panel/Button/Tab/Card/Grid/Empty 等通用 Emotion 样式 |
|
||||
| `Palette.kt` | 原版 `C9i` 配色表;所有颜色从 `Palette` 取值,见 `3DTank/docs/ColorPalette.md` |
|
||||
| `Translations.kt` | 原版翻译加载;支持 zh-CN/en-US/ru/de/fr/es/pl/pt-BR/tr/ja 切换 |
|
||||
| `HeadScreen.kt` | `HeadContext` / `HeadMount` |
|
||||
| `HomeScreen.kt` | `HomeContext` / `HomeMount` |
|
||||
| `LobbyScreens.kt` | `ScreenContext` / `ScreenMount` / 子页面路由 |
|
||||
|
||||
@@ -105,7 +105,7 @@ class LobbyView(private val Client: LobbyClient) {
|
||||
LDoc.getElementById("lobby-content").classList.toggle("garage", Nav == "garage")
|
||||
LDoc.getElementById("ms-home").classList.toggle("hidden", Nav != "home")
|
||||
// 车库复用主页顶栏(HEAD);其余子页面暂时隐藏,保留返回按钮。
|
||||
LDoc.getElementById("ms-top").classList.toggle("hidden", Nav != "home" && Nav != "garage")
|
||||
LDoc.getElementById("ms-top").classList.toggle("hidden", false)
|
||||
LDoc.getElementById("ms-back").classList.add("hidden")
|
||||
|
||||
if (Nav == "home") {
|
||||
|
||||
@@ -1,16 +1,48 @@
|
||||
// Translations.kt —— 真实 UI 文案(运行时拉取游戏自带的 zh-CN 翻译)
|
||||
// Translations.kt —— 真实 UI 文案(运行时拉取游戏自带的翻译)
|
||||
//
|
||||
// 资源路径来自 3DTank/src/resources.json 的 resourceMap(id 19144)。
|
||||
// 拉取失败时回退到调用点给的默认文案,UI 不会因网络问题变空白。
|
||||
// 支持运行时切换语言;拉取失败时保留当前语言,调用点可给默认文案。
|
||||
package App.Browser
|
||||
|
||||
object Translations {
|
||||
|
||||
private var Root: dynamic = null
|
||||
private var Loading = false
|
||||
private val Cache = mutableMapOf<String, dynamic>()
|
||||
|
||||
var Current: String = "zh-CN"
|
||||
private set
|
||||
|
||||
val Loaded: Boolean get() = Root != null
|
||||
|
||||
/** 原版可用的语言文件;键为 BCP-47,值为本地资源路径。 */
|
||||
val Languages: List<Pair<String, String>> = listOf(
|
||||
"zh-CN" to "简体中文",
|
||||
"en-US" to "English",
|
||||
"ru" to "Русский",
|
||||
"de" to "Deutsch",
|
||||
"fr" to "Français",
|
||||
"es-ES" to "Español",
|
||||
"pl" to "Polski",
|
||||
"pt-BR" to "Português",
|
||||
"tr" to "Türkçe",
|
||||
"ja" to "日本語",
|
||||
)
|
||||
|
||||
private fun PathOf(Code: String): String = when (Code) {
|
||||
"zh-CN" -> "/play/static/translations/zh-CN.61d6ab60.json"
|
||||
"en-US" -> "/play/static/translations/en-US.0f876fd1.json"
|
||||
"ru" -> "/play/static/translations/ru.d6b949df.json"
|
||||
"de" -> "/play/static/translations/de.6e129d94.json"
|
||||
"fr" -> "/play/static/translations/fr.58d6d8d9.json"
|
||||
"es-ES" -> "/play/static/translations/es-ES.93f63d79.json"
|
||||
"pl" -> "/play/static/translations/pl.7aeeed9f.json"
|
||||
"pt-BR" -> "/play/static/translations/pt-BR.053ff7af.json"
|
||||
"tr" -> "/play/static/translations/tr.16473698.json"
|
||||
"ja" -> "/play/static/translations/ja.1948901a.json"
|
||||
else -> "/play/static/translations/zh-CN.61d6ab60.json"
|
||||
}
|
||||
|
||||
private val FetchJson: (String, (dynamic) -> Unit) -> Unit = js(
|
||||
"""
|
||||
(function (Url, Cb) {
|
||||
@@ -23,16 +55,32 @@ object Translations {
|
||||
"""
|
||||
)
|
||||
|
||||
/** 拉取 zh-CN 翻译;完成后调用 OnReady(用于重绘)。 */
|
||||
/** 拉取当前语言;完成后调用 OnReady(用于重绘)。 */
|
||||
fun Load(OnReady: () -> Unit) {
|
||||
if (Loaded || Loading) {
|
||||
LoadLocale(Current, OnReady)
|
||||
}
|
||||
|
||||
/** 切换语言并拉取翻译;失败时保留当前语言。 */
|
||||
fun LoadLocale(Code: String, OnReady: () -> Unit) {
|
||||
val Cached = Cache[Code]
|
||||
if (Cached != null) {
|
||||
Root = Cached
|
||||
Current = Code
|
||||
OnReady()
|
||||
return
|
||||
}
|
||||
if (Loading) {
|
||||
OnReady()
|
||||
return
|
||||
}
|
||||
Loading = true
|
||||
FetchJson("/play/static/translations/zh-CN.61d6ab60.json") { Json ->
|
||||
Root = Json
|
||||
FetchJson(PathOf(Code)) { Json ->
|
||||
Loading = false
|
||||
if (Json != null) {
|
||||
Cache[Code] = Json
|
||||
Root = Json
|
||||
Current = Code
|
||||
}
|
||||
OnReady()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
package App.Browser.Ui
|
||||
|
||||
import App.Browser.LobbyClient
|
||||
import App.Browser.Translations
|
||||
import App.State.MainQuestInfo
|
||||
import App.State.NewsItemData
|
||||
import App.State.RootState
|
||||
@@ -152,61 +153,6 @@ private fun ChildrenBuilder.ScreenShell(
|
||||
div {
|
||||
css(ScreenRoot)
|
||||
Ui("screen." + Title)
|
||||
div {
|
||||
css(BreadcrumbsHeader)
|
||||
button {
|
||||
css(BreadcrumbsBack)
|
||||
Ui("screen.back")
|
||||
onClick = { ScreenContext.OnBack() }
|
||||
+"←"
|
||||
}
|
||||
h2 {
|
||||
css(BreadcrumbsTitle)
|
||||
+Title
|
||||
if (Subtitle.isNotEmpty()) {
|
||||
span { css(ScreenSubtitle); +Subtitle }
|
||||
}
|
||||
}
|
||||
div {
|
||||
css(BreadcrumbsRight)
|
||||
span {
|
||||
css(BreadcrumbsCurrency)
|
||||
img {
|
||||
src = Asset("static/images/ruby.ce62efbc.svg")
|
||||
css { Style("width", "1em"); Style("height", "1em") }
|
||||
}
|
||||
+"${HeadContext.Rubies}"
|
||||
img {
|
||||
src = Asset("static/images/addRuby.ff47c8be.svg")
|
||||
css { Style("width", "1em"); Style("height", "1em"); Style("margin-left", "0.3em"); Style("opacity", "0.85") }
|
||||
}
|
||||
}
|
||||
span {
|
||||
css(BreadcrumbsCurrency)
|
||||
img {
|
||||
src = Asset("static/images/crystalSmall.242e6c15.svg")
|
||||
css { Style("width", "1em"); Style("height", "1em") }
|
||||
}
|
||||
+"${HeadContext.Crystals}"
|
||||
img {
|
||||
src = Asset("static/images/addCrystal.af9a397c.svg")
|
||||
css { Style("width", "1em"); Style("height", "1em"); Style("margin-left", "0.3em"); Style("opacity", "0.85") }
|
||||
}
|
||||
}
|
||||
div {
|
||||
css(BreadcrumbsFullscreen)
|
||||
onClick = { HeadContext.OnFullscreen() }
|
||||
i { css(BreadcrumbsFullscreenIcon) }
|
||||
b { css(BreadcrumbsFullscreenText); +"F11" }
|
||||
}
|
||||
button {
|
||||
css(BreadcrumbsExit)
|
||||
Ui("screen.exit")
|
||||
onClick = { HeadContext.OnLogout() }
|
||||
+"⏻"
|
||||
}
|
||||
}
|
||||
}
|
||||
div {
|
||||
if (FullBleed) css(ScreenBodyFull) else css(ScreenBody)
|
||||
Body()
|
||||
@@ -1891,8 +1837,6 @@ private val QuestsScreen = FC<Props> {
|
||||
|
||||
// ---------------------------------------------------------------- 设置
|
||||
|
||||
private val SettingsTabs = listOf("游戏显示", "画面", "音效", "操控", "账户", "战斗", "安全", "支持")
|
||||
|
||||
private sealed class SettingEntry {
|
||||
data class Header(val Text: String) : SettingEntry()
|
||||
data class Toggle(
|
||||
@@ -1928,200 +1872,227 @@ private sealed class SettingEntry {
|
||||
data class Keys(val Rows: List<Pair<String, String>>) : SettingEntry()
|
||||
}
|
||||
|
||||
private val SettingsTabKeys = listOf("GAME", "BATTLE", "GRAPHIC", "SOUND", "CONTROL", "ACCOUNT", "SECURITY")
|
||||
private val SettingsTabFallbacks = listOf("游戏显示", "战斗", "画面", "音效", "操控", "账户", "安全")
|
||||
|
||||
private fun SettingsTabLabels(): List<String> =
|
||||
SettingsTabKeys.mapIndexed { Index, Key ->
|
||||
Translations.T("lobby.settings.menu.$Key", SettingsTabFallbacks[Index])
|
||||
}
|
||||
|
||||
private fun ST(Key: String, Default: String): String = Translations.T("lobby.settings.$Key", Default)
|
||||
|
||||
private fun SettingsEntries(Tab: Int, UserName: String): List<SettingEntry> = when (Tab) {
|
||||
0 -> listOf(
|
||||
SettingEntry.Header("常规"),
|
||||
SettingEntry.Choice(
|
||||
"language", "语言", "允许您将游戏语言更改为可用选项之一。",
|
||||
listOf("简体中文", "English", "Русский", "Deutsch", "Français", "Español"), 0,
|
||||
"language",
|
||||
ST("game.LANGUAGE", "语言"),
|
||||
ST("game.LANGUAGE_DESCRIPTION", "允许您将游戏语言更改为可用选项之一。"),
|
||||
Translations.Languages.map { it.second },
|
||||
Translations.Languages.indexOfFirst { it.first == Translations.Current }.coerceAtLeast(0),
|
||||
),
|
||||
SettingEntry.Toggle("showDropZones", "显示空投区", "显示道具箱在地图掉落的位置", true),
|
||||
SettingEntry.Toggle("alternateCamera", "备用视角", "开启备用视角功能", false),
|
||||
SettingEntry.Toggle("showYourDrone", "显示您的无人机", "在屏幕上显示您的无人机", true),
|
||||
SettingEntry.Toggle("showOtherDrone", "显示其他无人机", "显示其他无人机", true),
|
||||
SettingEntry.Toggle("showChat", "显示聊天窗口", "显示聊天窗口", true),
|
||||
SettingEntry.Toggle("showNotifications", "显示通知", "在屏幕上显示您的通知", true),
|
||||
SettingEntry.Toggle("receivePresents", "接收礼物", "允许您接收其他玩家的礼物", true),
|
||||
SettingEntry.Header("音频与通知"),
|
||||
SettingEntry.Toggle("backgroundSound", "背景声音", "启用背景音效", true),
|
||||
SettingEntry.Toggle("blurMute", "后台自动静音", "标签页失焦时静音战斗", true),
|
||||
SettingEntry.Toggle("disableBattleInvites", "屏蔽战斗邀请", "屏蔽好友组队邀请", false),
|
||||
SettingEntry.Info("浏览器通知", "已启用", "当游戏不是活动窗口时从其他玩家那里获取信息"),
|
||||
SettingEntry.Toggle("showDropZones", ST("game.SHOW_DROP_ZONES", "显示空投区"), ST("game.SHOW_DROP_ZONES_DESCRIPTION", "显示道具箱在地图掉落的位置"), true),
|
||||
SettingEntry.Toggle("alternateCamera", ST("game.ALTERNATE_CAMERA", "备用视角"), ST("game.ALTERNATE_CAMERA_DESCRIPTION", "开启备用视角功能"), false),
|
||||
SettingEntry.Toggle("showYourDrone", ST("game.SHOW_YOUR_DRONE", "显示您的无人机"), ST("game.SHOW_YOUR_DRONE_DESCRIPTION", "在屏幕上显示您的无人机"), true),
|
||||
SettingEntry.Toggle("showOtherDrone", ST("game.SHOW_OTHER_DRONE", "显示其他无人机"), ST("game.SHOW_OTHER_DRONE_DESCRIPTION", "显示其他无人机"), true),
|
||||
SettingEntry.Toggle("showChat", ST("game.SHOW_CHAT", "显示聊天窗口"), ST("game.SHOW_CHAT_DESCRIPTION", "显示聊天窗口"), true),
|
||||
SettingEntry.Toggle("showNotifications", ST("game.SHOW_NOTIFICATIONS", "显示通知"), ST("game.SHOW_NOTIFICATIONS_DESCRIPTION", "在屏幕上显示您的通知"), true),
|
||||
SettingEntry.Toggle("receivePresents", ST("game.RECEIVE_PRESENTS_ENABLED", "接收礼物"), ST("game.RECEIVE_PRESENTS_ENABLED_DESCRIPTION", "允许您接收其他玩家的礼物"), true),
|
||||
SettingEntry.Toggle("backgroundSound", ST("game.BACKGROUND_SOUND", "背景声音"), ST("game.BACKGROUND_SOUND_DESCRIPTION", "启用背景音效"), true),
|
||||
SettingEntry.Toggle("blurMute", ST("game.BLUR_MUTE", "后台自动静音"), ST("game.BLUR_MUTE_DESCRIPTION", "标签页失焦时静音战斗"), true),
|
||||
SettingEntry.Toggle("disableBattleInvites", ST("game.DISABLE_SHOWING_BATTLE_INVITES", "屏蔽战斗邀请"), ST("game.DISABLE_SHOWING_BATTLE_INVITES_DESCRIPTION", "屏蔽好友组队邀请"), false),
|
||||
SettingEntry.Action(
|
||||
"激活兑换码",
|
||||
"兑换码可让您获得水晶、VIP 天数、金箱子、迷彩和车库中的一些物品。",
|
||||
"激活",
|
||||
ST("game.ACTIVATE_PROMOCODE", "激活兑换码"),
|
||||
ST("game.ACTIVATE_PROMOCODE_DESCRIPTION", "兑换码可让您获得水晶、VIP 天数、金箱子、迷彩和车库中的一些物品。"),
|
||||
ST("game.ACTIVATE_PROMOCODE", "激活"),
|
||||
"兑换码功能将在账户协议接入后开放。",
|
||||
),
|
||||
)
|
||||
1 -> listOf(
|
||||
SettingEntry.Header("图形质量"),
|
||||
SettingEntry.Toggle("aimDot", ST("battle.SHOW_AIM_HELPER_DOT", "在屏幕中间显示一个点"), ST("battle.SHOW_AIM_HELPER_DOT_DESCRIPTION", "显示一个点状光标,以便于镜头定位"), false),
|
||||
SettingEntry.Toggle("showDamage", ST("battle.SHOW_DAMAGE", "显示伤害"), ST("battle.SHOW_DAMAGE_DESCRIPTION", "显示您对敌人造成的伤害生命值"), true),
|
||||
SettingEntry.Toggle("autoSuicide", ST("battle.AUTO_SUICIDE_ON_OVERTURN", "自动自毁"), ST("battle.AUTO_SUICIDE_ON_OVERTURN_DESCRIPTION", "如果您的坦克翻车或者侧翻,将会开启自动自毁。"), true),
|
||||
SettingEntry.Toggle("showStatusName", ST("battle.SHOW_STATUS_NAME", "状态效果文字提示"), ST("battle.SHOW_STATUS_NAME_DESCRIPTION", "显示状态效果的指示文字"), true),
|
||||
SettingEntry.Toggle("centeredLayout", ST("battle.IS_CENTERED_LAYOUT", "屏幕中央的战斗界面"), ST("battle.IS_CENTERED_LAYOUT_DESCRIPTION", "在屏幕底部的中央显示战斗界面的信息。"), false),
|
||||
SettingEntry.Toggle("showGoldBoxCreator", ST("battle.SHOW_GOLD_BOX_CREATOR", "显示谁投放了金箱子"), ST("battle.SHOW_GOLD_BOX_CREATOR_DESCRIPTION", "在掉落金箱子时显示投放者昵称"), true),
|
||||
SettingEntry.Toggle("showTankPointer", ST("battle.SHOW_TANK_POINTER", "显示伤害方向指示器"), ST("battle.SHOW_TANK_POINTER_DESCRIPTION", "受到伤害时显示指向伤害来源的指示器"), true),
|
||||
SettingEntry.Toggle("autoSupply", ST("battle.AUTO_SUPPLY", "战斗中自动激活道具"), ST("battle.AUTO_SUPPLY", "在战斗中自动使用已装备的道具"), false),
|
||||
SettingEntry.Toggle("showButtonLabels", ST("battle.SHOW_BUTTON_LABELS", "按钮上显示快捷键"), ST("battle.SHOW_BUTTON_LABELS_DESCRIPTION", "显示战斗界面按钮所绑定的快捷键"), true),
|
||||
SettingEntry.Slider("battleUiScale", ST("battle.BATTLE_UI_SCALE", "战斗画面尺寸"), ST("battle.BATTLE_UI_SCALE_DESCRIPTION", "调整战斗界面的大小"), 100),
|
||||
SettingEntry.Slider("aimOpacity", ST("battle.AIM_OPACITY", "镜头中心点不透明度"), ST("battle.AIM_OPACITY", "调整镜头中心点的透明度"), 80),
|
||||
SettingEntry.Choice(
|
||||
"quality", "图形质量", "允许您在精美的图形和快速的性能之间做出最佳选择。",
|
||||
listOf("最低", "低", "中", "高", "最高", "自定义"), 3,
|
||||
"aimScale", ST("battle.AIM_SCALE", "镜头中心点大小"), ST("battle.AIM_SCALE", "调整镜头中心点的大小。"),
|
||||
listOf(
|
||||
ST("battle.AIM_SCALE_MINIMAL", "最小"),
|
||||
ST("battle.AIM_SCALE_SMALL", "中等"),
|
||||
ST("battle.AIM_SCALE_MEDIUM", "巨大"),
|
||||
ST("battle.AIM_SCALE_LARGE", "特大"),
|
||||
ST("battle.AIM_SCALE_MAXIMAL", "最大"),
|
||||
),
|
||||
1,
|
||||
),
|
||||
SettingEntry.Toggle("showFps", "显示帧数和延迟", "显示您的帧数和延迟", false),
|
||||
SettingEntry.Toggle("skybox", "显示天空", "显示地图天空", true),
|
||||
SettingEntry.Toggle("autoQuality", "自动图形质量", "自动设置图形质量", true),
|
||||
SettingEntry.Header("阴影与光照"),
|
||||
SettingEntry.Toggle("dynamicShadows", "动态阴影", "启用动态阴影", true),
|
||||
SettingEntry.Toggle("dynamicLighting", "动态照明", "启用动态照明", true),
|
||||
SettingEntry.Toggle("shadows", "阴影", "启用阴影", true),
|
||||
SettingEntry.Toggle("softShadows", "软阴影", "启用软阴影", true),
|
||||
SettingEntry.Toggle("softParticles", "软粒子", "启用软粒子", true),
|
||||
SettingEntry.Toggle("ssao", "环境光遮蔽", "启用环境光遮蔽", true),
|
||||
SettingEntry.Toggle("fog", "雾效", "启用雾效", true),
|
||||
SettingEntry.Header("效果与分辨率"),
|
||||
SettingEntry.Choice("decals", "射弹孔与爆炸痕迹", "更改战斗中地图上显示的射击和爆炸痕迹。", listOf("关闭", "低", "中", "高", "最大"), 2),
|
||||
SettingEntry.Choice("trees", "树木图形质量", "更改灌木和树木的渲染质量。", listOf("精简", "低", "中", "高"), 2),
|
||||
SettingEntry.Choice("resolution", "图像分辨率", "在战斗中更改游戏屏幕分辨率,这会明显影响性能。", listOf("最低", "非常低", "低", "最高"), 3),
|
||||
SettingEntry.Choice("fpsLimit", "帧数限制", "限制游戏的最大帧数。", listOf("30", "60", "120", "最高"), 1),
|
||||
SettingEntry.Toggle("vsync", "垂直同步", "启用垂直同步", false),
|
||||
SettingEntry.Toggle("antialiasing", "抗锯齿", "启用抗锯齿", true),
|
||||
SettingEntry.Toggle("dust", "弹壳与扬尘", "显示移动轨迹下的弹壳与扬尘", true),
|
||||
SettingEntry.Toggle("anisotropic", "各向异性过滤", "更改远处纹理的图像质量", true),
|
||||
)
|
||||
2 -> listOf(
|
||||
SettingEntry.Header("音量"),
|
||||
SettingEntry.Slider("masterVolume", "主音量", "允许您更改主音量", 80),
|
||||
SettingEntry.Slider("musicVolume", "音乐音量", "允许您更改大厅音乐的音量", 60),
|
||||
SettingEntry.Slider("ambientVolume", "环境音量", "允许您更改游戏中的背景声音", 50),
|
||||
SettingEntry.Slider("sfxVolume", "音效音量", "允许您更改游戏中的战斗声音(射击、爆炸声)", 90),
|
||||
SettingEntry.Slider("uiVolume", "界面音量", "允许您更改界面的音量", 70),
|
||||
SettingEntry.Header("命中提示"),
|
||||
SettingEntry.Slider("hitmarkPlayer", "受到敌方伤害时的音量", "允许您更改敌人射击您坦克的音量", 60),
|
||||
SettingEntry.Slider("hitmarkEnemy", "对敌方造成伤害时的音量", "允许您更改您自己射击敌方坦克的音量", 60),
|
||||
SettingEntry.Toggle("backgroundSound", "背景声音", "启用背景音效", true),
|
||||
SettingEntry.Toggle("blurMute", "后台自动静音", "标签页失焦时静音战斗", true),
|
||||
SettingEntry.Choice(
|
||||
"quality", ST("graphics.QUALITY_BRACKET_TITLE_LABEL", "图形质量"), ST("graphics.QUALITY_BRACKETS_DESCRIPTION", "允许您在精美的图形和快速的性能之间做出最佳选择。"),
|
||||
listOf(
|
||||
ST("graphics.QUALITY_BRACKET_MINIMUM", "最低"),
|
||||
ST("graphics.QUALITY_BRACKET_LOW", "低"),
|
||||
ST("graphics.QUALITY_BRACKET_MEDIUM", "中"),
|
||||
ST("graphics.QUALITY_BRACKET_HIGH", "高"),
|
||||
ST("graphics.QUALITY_BRACKET_MAXIMUM", "最高"),
|
||||
ST("graphics.QUALITY_BRACKET_OTHER", "自定义"),
|
||||
),
|
||||
3,
|
||||
),
|
||||
SettingEntry.Toggle("showFps", ST("graphics.SHOW_FPS_AND_PING", "显示帧数和延迟"), ST("graphics.SHOW_FPS_AND_PING_DESCRIPTION", "显示您的帧数和延迟"), false),
|
||||
SettingEntry.Toggle("skybox", ST("graphics.SHOW_SKYBOX", "显示天空"), ST("graphics.SHOW_SKYBOX_DESCRIPTION", "显示地图天空"), true),
|
||||
SettingEntry.Toggle("autoQuality", ST("graphics.GRAPHICS_AUTO_QUALITY", "自动图形质量"), ST("graphics.GRAPHICS_AUTO_QUALITY_DESCRIPTION", "自动设置图形质量"), true),
|
||||
SettingEntry.Toggle("dynamicShadows", ST("graphics.DYNAMIC_SHADOWS", "动态阴影"), ST("graphics.DYNAMIC_SHADOWS_DESCRIPTION", "启用动态阴影"), true),
|
||||
SettingEntry.Toggle("dynamicLighting", ST("graphics.DYNAMIC_LIGHTING", "动态照明"), ST("graphics.DYNAMIC_LIGHTING_DESCRIPTION", "启用动态照明"), true),
|
||||
SettingEntry.Toggle("shadows", ST("graphics.SHADOWS", "阴影"), ST("graphics.SHADOWS_DESCRIPTION", "启用阴影"), true),
|
||||
SettingEntry.Toggle("softShadows", ST("graphics.SOFT_SHADOWS", "软阴影"), ST("graphics.SOFT_SHADOWS_DESCRIPTION", "启用软阴影"), true),
|
||||
SettingEntry.Toggle("softParticles", ST("graphics.SOFT_PARTICLES", "软粒子"), ST("graphics.SOFT_PARTICLES_DESCRIPTION", "启用软粒子"), true),
|
||||
SettingEntry.Toggle("ssao", ST("graphics.SSAO", "环境光遮蔽"), ST("graphics.SSAO_DESCRIPTION", "启用环境光遮蔽"), true),
|
||||
SettingEntry.Toggle("fog", ST("graphics.FOG", "雾效"), ST("graphics.FOG_DESCRIPTION", "启用雾效"), true),
|
||||
SettingEntry.Choice(
|
||||
"decals", ST("graphics.DECALS", "射弹孔与爆炸痕迹"), ST("graphics.DECALS_DESCRIPTION", "更改战斗中地图上显示的射击和爆炸痕迹。"),
|
||||
listOf(
|
||||
ST("graphics.DECALS_KEY_OFF", "关闭"),
|
||||
ST("graphics.DECALS_KEY_FEW", "低"),
|
||||
ST("graphics.DECALS_KEY_MANY", "中"),
|
||||
ST("graphics.DECALS_KEY_TOO_MANY", "高"),
|
||||
ST("graphics.DECALS_KEY_MAXIMUM", "最大"),
|
||||
),
|
||||
2,
|
||||
),
|
||||
SettingEntry.Choice(
|
||||
"trees", ST("graphics.TREES_QUALITY", "树木图形质量"), ST("graphics.TREES_QUALITY_DESCRIPTION", "更改灌木和树木的渲染质量。"),
|
||||
listOf(
|
||||
ST("graphics.TREES_QUALITY_SPRITES", "精简"),
|
||||
ST("graphics.TREES_QUALITY_LOW", "低"),
|
||||
ST("graphics.TREES_QUALITY_MEDIUM", "中"),
|
||||
ST("graphics.TREES_QUALITY_HIGH", "高"),
|
||||
),
|
||||
2,
|
||||
),
|
||||
SettingEntry.Choice(
|
||||
"resolution", ST("graphics.GRAPHICS_RESOLUTION", "图像分辨率"), ST("graphics.GRAPHICS_RESOLUTION_DESCRIPTION", "在战斗中更改游戏屏幕分辨率,这会明显影响性能。"),
|
||||
listOf(
|
||||
ST("graphics.GRAPHICS_RESOLUTION_MINIMAL", "最低"),
|
||||
ST("graphics.GRAPHICS_RESOLUTION_VERY_LOW", "非常低"),
|
||||
ST("graphics.GRAPHICS_RESOLUTION_LOW", "低"),
|
||||
ST("graphics.GRAPHICS_RESOLUTION_MAXIMAL", "最高"),
|
||||
),
|
||||
3,
|
||||
),
|
||||
SettingEntry.Choice("fpsLimit", ST("graphics.FPS_LIMIT", "帧数限制"), ST("graphics.FPS_LIMIT", "限制游戏的最大帧数。"), listOf("30", "60", "120", ST("graphics.FPS_LIMIT_MAX", "最高")), 1),
|
||||
SettingEntry.Toggle("vsync", ST("graphics.VSYNC", "垂直同步"), ST("graphics.VSYNC_DESCRIPTION", "启用垂直同步"), false),
|
||||
SettingEntry.Toggle("antialiasing", ST("graphics.ANTIALIASING", "抗锯齿"), ST("graphics.ANTIALIASING_DESCRIPTION", "启用抗锯齿"), true),
|
||||
SettingEntry.Toggle("dust", ST("graphics.DUST", "弹壳与扬尘"), ST("graphics.DUST_DESCRIPTION", "显示移动轨迹下的弹壳与扬尘"), true),
|
||||
SettingEntry.Toggle("anisotropic", ST("graphics.ANISOTROPIC_FILTERING", "各向异性过滤"), ST("graphics.ANISOTROPIC_FILTERING_DESCRIPTION", "更改远处纹理的图像质量"), true),
|
||||
)
|
||||
3 -> listOf(
|
||||
SettingEntry.Header("输入设备"),
|
||||
SettingEntry.Choice("inputDevice", "输入设备", "选择用于控制坦克的输入设备。", listOf("鼠标 + 键盘", "键盘", "游戏手柄", "触摸屏"), 0),
|
||||
SettingEntry.Slider("sensitivity", "镜头灵敏度", "调整鼠标移动时的镜头灵敏度。", 50),
|
||||
SettingEntry.Toggle("invertShaft", "反转垂直轴方向", "反转狙击模式垂直轴方向", false),
|
||||
SettingEntry.Toggle("inversedBackward", "倒车时倒转转向", "倒车时反转转向", false),
|
||||
SettingEntry.Toggle("inversedCamera", "反转镜头控制", "垂直移动瞄准摇杆时反转镜头方向", false),
|
||||
SettingEntry.Toggle("mouseAcceleration", "系统鼠标加速", "如果鼠标操作时镜头经常突然跳动,请禁用此选项。", false),
|
||||
SettingEntry.Header("按键绑定"),
|
||||
SettingEntry.Slider("masterVolume", ST("game.MASTER_VOLUME", "主音量"), ST("game.MASTER_VOLUME_DESCRIPTION", "允许您更改主音量"), 80),
|
||||
SettingEntry.Slider("musicVolume", ST("game.MUSIC_VOLUME", "音乐音量"), ST("game.MUSIC_VOLUME_DESCRIPTION", "允许您更改大厅音乐的音量"), 60),
|
||||
SettingEntry.Slider("ambientVolume", ST("game.AMBIENT_VOLUME", "环境音量"), ST("game.AMBIENT_VOLUME_DESCRIPTION", "允许您更改游戏中的背景声音"), 50),
|
||||
SettingEntry.Slider("sfxVolume", ST("game.SFX_VOLUME", "音效音量"), ST("game.SFX_VOLUME_DESCRIPTION", "允许您更改游戏中的战斗声音(射击、爆炸声)"), 90),
|
||||
SettingEntry.Slider("uiVolume", ST("game.UI_VOLUME", "界面音量"), ST("game.UI_VOLUME_DESCRIPTION", "允许您更改界面的音量"), 70),
|
||||
SettingEntry.Slider("hitmarkPlayer", ST("game.HITMARK_PLAYER_VOLUME", "受到敌方伤害时的音量"), ST("game.HITMARK_PLAYER_VOLUME_DESCRIPTION", "允许您更改敌人射击您坦克的音量"), 60),
|
||||
SettingEntry.Slider("hitmarkEnemy", ST("game.HITMARK_ENEMY_VOLUME", "对敌方造成伤害时的音量"), ST("game.HITMARK_ENEMY_VOLUME_DESCRIPTION", "允许您更改您自己射击敌方坦克的音量"), 60),
|
||||
)
|
||||
4 -> listOf(
|
||||
SettingEntry.Choice(
|
||||
"inputDevice", ST("controls.inputDevice.INPUT_DEVICE", "输入设备"), ST("controls.inputDevice.INPUT_DEVICE", "选择用于控制坦克的输入设备。"),
|
||||
listOf(
|
||||
ST("controls.inputDevice.MOUSE_KEYBOARD", "鼠标 + 键盘"),
|
||||
ST("controls.inputDevice.KEYBOARD", "键盘"),
|
||||
ST("controls.inputDevice.GAMEPAD", "游戏手柄"),
|
||||
ST("controls.inputDevice.TOUCHSCREEN", "触摸屏"),
|
||||
),
|
||||
0,
|
||||
),
|
||||
SettingEntry.Slider("sensitivity", ST("controls.inputDevice.mouse.CAMERA_SENSITIVITY", "镜头灵敏度"), ST("controls.inputDevice.mouse.CAMERA_SENSITIVITY", "调整鼠标移动时的镜头灵敏度。"), 50),
|
||||
SettingEntry.Toggle("invertShaft", ST("controls.INVERT_SHAFT_VERTICAL_AXIS", "反转垂直轴方向"), ST("controls.INVERT_SHAFT_VERTICAL_AXIS_DESCRIPTION", "反转狙击模式垂直轴方向"), false),
|
||||
SettingEntry.Toggle("inversedBackward", ST("controls.INVERSED_BACKWARD_MOVING", "倒车时倒转转向"), ST("controls.INVERSED_BACKWARD_MOVING_DESCRIPTION", "倒车时反转转向"), false),
|
||||
SettingEntry.Toggle("inversedCamera", ST("controls.INVERSED_CAMERA_HEIGHT", "反转镜头控制"), ST("controls.INVERSED_CAMERA_HEIGHT_DESCRIPTION", "垂直移动瞄准摇杆时反转镜头方向"), false),
|
||||
SettingEntry.Toggle("mouseAcceleration", ST("controls.inputDevice.mouse.ENABLE_ACCELERATION", "系统鼠标加速"), ST("controls.inputDevice.mouse.ENABLE_ACCELERATION_DESCRIPTION", "如果鼠标操作时镜头经常突然跳动,请禁用此选项。"), false),
|
||||
SettingEntry.Keys(
|
||||
listOf(
|
||||
"坦克前进" to "W",
|
||||
"坦克后退" to "S",
|
||||
"坦克左转" to "A",
|
||||
"坦克右转" to "D",
|
||||
"炮塔左转" to "←",
|
||||
"炮塔右转" to "→",
|
||||
"射击" to "空格",
|
||||
"使用维修工具" to "1",
|
||||
"使用护甲提升" to "2",
|
||||
"使用伤害提升" to "3",
|
||||
"使用速度提升" to "4",
|
||||
"布设地雷" to "5",
|
||||
"投掷手榴弹" to "G",
|
||||
"终极技能" to "F",
|
||||
"暂停" to "Esc",
|
||||
"战绩统计" to "Tab",
|
||||
"快速进入车库" to "L",
|
||||
ST("keyboard.MOVE_TANK_FORWARD", "坦克前进") to "W",
|
||||
ST("keyboard.MOVE_TANK_BACKWARDS", "坦克后退") to "S",
|
||||
ST("keyboard.TURN_TANK_LEFT", "坦克左转") to "A",
|
||||
ST("keyboard.TURN_TANK_RIGHT", "坦克右转") to "D",
|
||||
ST("keyboard.ROTATE_TURRET_LEFT", "炮塔左转") to "←",
|
||||
ST("keyboard.ROTATE_TURRET_RIGHT", "炮塔右转") to "→",
|
||||
ST("keyboard.SHOOT", "射击") to "空格",
|
||||
ST("keyboard.USE_FIRST_AID_SUPPLY", "使用维修工具") to "1",
|
||||
ST("keyboard.USE_DOUBLE_ARMOR_SUPPLY", "使用护甲提升") to "2",
|
||||
ST("keyboard.USE_DOUBLE_DAMAGE_SUPPLY", "使用伤害提升") to "3",
|
||||
ST("keyboard.USE_SPEED_BOOST_SUPPLY", "使用速度提升") to "4",
|
||||
ST("keyboard.DROP_MINE", "布设地雷") to "5",
|
||||
ST("keyboard.DROP_GRENADE", "投掷手榴弹") to "G",
|
||||
ST("keyboard.OVERDRIVES", "终极技能") to "F",
|
||||
ST("keyboard.PAUSE", "暂停") to "Esc",
|
||||
ST("keyboard.STATISTICS", "战绩统计") to "Tab",
|
||||
ST("keyboard.QUICK_GARAGE", "快速进入车库") to "L",
|
||||
),
|
||||
),
|
||||
)
|
||||
4 -> listOf(
|
||||
SettingEntry.Header("账户信息"),
|
||||
SettingEntry.Info("昵称", UserName.ifBlank { "未登录" }),
|
||||
SettingEntry.Info("您的位置", "中国"),
|
||||
SettingEntry.Info("绑定邮箱", "未绑定", "绑定邮箱后可以更安全地找回账号。"),
|
||||
SettingEntry.Header("账户安全"),
|
||||
5 -> listOf(
|
||||
SettingEntry.Info(ST("account.NEW_UID", "昵称"), UserName.ifBlank { "未登录" }),
|
||||
SettingEntry.Info(ST("account.YOUR_LOCATION", "您的位置"), "中国"),
|
||||
SettingEntry.Info(ST("account.EMAIL_INPUT_LABEL", "绑定邮箱"), "未绑定", ST("account.CONNECT_EMAIL_TITLE", "绑定邮箱后可以更安全地找回账号。")),
|
||||
SettingEntry.Action(
|
||||
"更改密码和电子邮件",
|
||||
"通过验证当前密码来更新登录邮箱和密码。",
|
||||
"更改",
|
||||
ST("account.CHANGE_PASSWORD_AND_EMAIL", "更改密码和电子邮件"),
|
||||
ST("account.CHANGE_PASSWORD_AND_EMAIL", "通过验证当前密码来更新登录邮箱和密码。"),
|
||||
ST("account.CHANGE_BUTTON", "更改"),
|
||||
"更改密码和电子邮件将在账户协议接入后开放。",
|
||||
),
|
||||
SettingEntry.Action(
|
||||
"绑定邮箱",
|
||||
"绑定您的邮箱以保护您的账号!",
|
||||
"连接",
|
||||
ST("account.CONNECT_EMAIL_TITLE", "绑定邮箱"),
|
||||
ST("account.CONNECT_EMAIL_TITLE", "绑定您的邮箱以保护您的账号!"),
|
||||
ST("account.CONNECT_BUTTON", "连接"),
|
||||
"邮箱绑定功能将在账户协议接入后开放。",
|
||||
),
|
||||
SettingEntry.Action(
|
||||
"更改昵称",
|
||||
"首次更改昵称免费。",
|
||||
"更改昵称",
|
||||
ST("account.USER_RENAME_TITLE", "更改昵称"),
|
||||
ST("account.UID_RENAME_FREE_HINT", "首次更改昵称免费。"),
|
||||
ST("account.USER_RENAME_TITLE", "更改昵称"),
|
||||
"昵称修改功能将在账户协议接入后开放。",
|
||||
),
|
||||
SettingEntry.Header("账号管理"),
|
||||
SettingEntry.Action(
|
||||
"账号删除",
|
||||
"提交申请后,您将有 30 天时间取消此决定;超过该期限后,账号将无法恢复。",
|
||||
"删除账号",
|
||||
ST("account.ACCOUNT_REMOVAL_BUTTON", "删除账号"),
|
||||
ST("account.ACCOUNT_REMOVAL_DESCRIPTION_SHORT", "提交申请后,您将有 30 天时间取消此决定。"),
|
||||
ST("account.ACCOUNT_REMOVAL_BUTTON", "删除账号"),
|
||||
"账号删除功能将在账户协议接入后开放。",
|
||||
),
|
||||
)
|
||||
5 -> listOf(
|
||||
SettingEntry.Header("界面"),
|
||||
SettingEntry.Toggle("aimDot", "在屏幕中间显示一个点", "显示一个点状光标,以便于镜头定位", false),
|
||||
SettingEntry.Toggle("showDamage", "显示伤害", "显示您对敌人造成的伤害生命值", true),
|
||||
SettingEntry.Toggle("autoSuicide", "自动自毁", "如果您的坦克翻车或者侧翻,将会开启自动自毁。", true),
|
||||
SettingEntry.Toggle("showStatusName", "状态效果文字提示", "显示状态效果的指示文字", true),
|
||||
SettingEntry.Toggle("centeredLayout", "屏幕中央的战斗界面", "在屏幕底部的中央显示战斗界面的信息。", false),
|
||||
SettingEntry.Toggle("showGoldBoxCreator", "显示谁投放了金箱子", "在掉落金箱子时显示投放者昵称", true),
|
||||
SettingEntry.Toggle("showTankPointer", "显示伤害方向指示器", "受到伤害时显示指向伤害来源的指示器", true),
|
||||
SettingEntry.Toggle("autoSupply", "战斗中自动激活道具", "在战斗中自动使用已装备的道具", false),
|
||||
SettingEntry.Toggle("showButtonLabels", "按钮上显示快捷键", "显示战斗界面按钮所绑定的快捷键", true),
|
||||
SettingEntry.Header("瞄准与缩放"),
|
||||
SettingEntry.Slider("battleUiScale", "战斗画面尺寸", "调整战斗界面的大小", 100),
|
||||
SettingEntry.Slider("aimOpacity", "镜头中心点不透明度", "调整镜头中心点的透明度", 80),
|
||||
SettingEntry.Choice("aimScale", "镜头中心点大小", "调整镜头中心点的大小。", listOf("最小", "中等", "巨大", "特大", "最大"), 1),
|
||||
)
|
||||
6 -> listOf(
|
||||
SettingEntry.Header("双重身份验证"),
|
||||
SettingEntry.Info("状态", "未启用", "双重身份验证可提高您账号的安全性。"),
|
||||
else -> listOf(
|
||||
SettingEntry.Info(ST("security.TITLE", "双重身份验证"), "未启用", ST("security.DESCRIPTION", "双重身份验证可提高您账号的安全性。")),
|
||||
SettingEntry.Action(
|
||||
"启用双重身份验证",
|
||||
"完成 3 个简单步骤,让您的账号更安全:安装验证程序、扫描二维码、输入安全码。",
|
||||
"启用",
|
||||
ST("security.TITLE", "启用双重身份验证"),
|
||||
ST("security.INTRO", "完成 3 个简单步骤,让您的账号更安全。"),
|
||||
ST("security.ENABLE_BUTTON", "启用"),
|
||||
"双重身份验证将在账户协议接入后开放。",
|
||||
),
|
||||
SettingEntry.Header("隐私"),
|
||||
SettingEntry.Toggle("hideProfile", "隐藏您的个人资料", "在公共应用编程接口中隐藏您的游戏统计信息和个人档案信息", false),
|
||||
SettingEntry.Header("会话"),
|
||||
SettingEntry.Info("登录记录", "—"),
|
||||
SettingEntry.Info("会话过期时间", "7 天"),
|
||||
SettingEntry.Toggle("hideProfile", ST("security.HIDE_PROFILE_TITLE", "隐藏您的个人资料"), ST("security.HIDE_PROFILE_DESCRIPTION", "在公共应用编程接口中隐藏您的游戏统计信息和个人档案信息"), false),
|
||||
SettingEntry.Action(
|
||||
"退出所有设备",
|
||||
"让所有已登录设备上的会话立即失效。",
|
||||
"退出",
|
||||
"会话管理将在账户协议接入后开放。",
|
||||
),
|
||||
)
|
||||
else -> listOf(
|
||||
SettingEntry.Header("客户端"),
|
||||
SettingEntry.Info("客户端版本", "Kotlin/JS"),
|
||||
SettingEntry.Info("协议版本", "S3"),
|
||||
SettingEntry.Info("渲染模式", "WebGL"),
|
||||
SettingEntry.Header("帮助与政策"),
|
||||
SettingEntry.Action(
|
||||
"技术支持",
|
||||
"请使用另一台设备的摄像头扫描支持门户二维码,或在浏览器中打开支持网站。",
|
||||
"打开支持网站",
|
||||
"支持网站将在外部浏览器打开。",
|
||||
),
|
||||
SettingEntry.Action(
|
||||
"使用许可及服务协议",
|
||||
"查看游戏的使用许可及服务协议。",
|
||||
"打开",
|
||||
ST("policy.TERMS_AND_CONDITIONS", "使用许可及服务协议"),
|
||||
ST("policy.TERMS_AND_CONDITIONS", "查看游戏的使用许可及服务协议。"),
|
||||
ST("policy.TERMS_AND_CONDITIONS", "打开"),
|
||||
"政策页面将在外部浏览器打开。",
|
||||
),
|
||||
SettingEntry.Action(
|
||||
"隐私政策",
|
||||
"查看游戏的隐私政策。",
|
||||
"打开",
|
||||
ST("policy.PRIVACY_POLICY", "隐私政策"),
|
||||
ST("policy.PRIVACY_POLICY", "查看游戏的隐私政策。"),
|
||||
ST("policy.PRIVACY_POLICY", "打开"),
|
||||
"政策页面将在外部浏览器打开。",
|
||||
),
|
||||
SettingEntry.Action(
|
||||
"第三方共享个人信息清单",
|
||||
"查看第三方共享个人信息清单。",
|
||||
"打开",
|
||||
ST("policy.SHARED_INFO", "第三方共享个人信息清单"),
|
||||
ST("policy.SHARED_INFO", "查看第三方共享个人信息清单。"),
|
||||
ST("policy.SHARED_INFO", "打开"),
|
||||
"政策页面将在外部浏览器打开。",
|
||||
),
|
||||
)
|
||||
@@ -2160,8 +2131,8 @@ private val SettingsMenuHighlight: csstype.PropertiesBuilder.() -> Unit = {
|
||||
Style("left", "0")
|
||||
Style("width", "18em")
|
||||
Style("height", "2.5em")
|
||||
Style("background", "linear-gradient(to right, #2E3235, rgba(46, 50, 53, 0))")
|
||||
Style("color", "rgb(255, 188, 9)")
|
||||
Style("background", Palette.MenuGradient)
|
||||
Style("color", Palette.Yellow)
|
||||
Style("z-index", "1")
|
||||
Style("transition", "all 0.1s ease-in-out")
|
||||
Style("pointer-events", "none")
|
||||
@@ -2172,7 +2143,7 @@ private val SettingsMenuLine: csstype.PropertiesBuilder.() -> Unit = {
|
||||
Style("left", "0")
|
||||
Style("width", "0.313em")
|
||||
Style("height", "2.5em")
|
||||
Style("background-color", "rgb(255, 188, 9)")
|
||||
Style("background-color", Palette.Yellow)
|
||||
Style("z-index", "3")
|
||||
Style("transition", "all 0.1s ease-in-out")
|
||||
Style("pointer-events", "none")
|
||||
@@ -2227,7 +2198,7 @@ private val SettingsPanel: csstype.PropertiesBuilder.() -> Unit = {
|
||||
Style("padding", "1.875em")
|
||||
Style("padding-bottom", "0")
|
||||
Style("position", "relative")
|
||||
Style("background-color", "rgba(255, 255, 255, 0.1)")
|
||||
Style("background-color", Palette.Panel)
|
||||
Style("box-sizing", "border-box")
|
||||
Style("overflow-x", "hidden")
|
||||
Style("overflow-y", "auto")
|
||||
@@ -2237,7 +2208,7 @@ private val SettingsPanel: csstype.PropertiesBuilder.() -> Unit = {
|
||||
|
||||
private val SettingsDivider: csstype.PropertiesBuilder.() -> Unit = {
|
||||
Style("flex", "0 0 auto")
|
||||
Style("background-color", "rgba(255, 255, 255, 0.1)")
|
||||
Style("background-color", Palette.Panel)
|
||||
Style("width", "49.125em")
|
||||
Style("height", "0.063em")
|
||||
Style("margin-bottom", "1.875em")
|
||||
@@ -2258,6 +2229,7 @@ private val SettingsHeadline: csstype.PropertiesBuilder.() -> Unit = {
|
||||
private val SettingsRow: csstype.PropertiesBuilder.() -> Unit = {
|
||||
Style("display", "flex")
|
||||
Style("flex-direction", "row")
|
||||
Style("flex-wrap", "wrap")
|
||||
Style("justify-content", "space-between")
|
||||
Style("align-items", "center")
|
||||
Style("width", "100%")
|
||||
@@ -2273,14 +2245,14 @@ private val SettingsLabel: csstype.PropertiesBuilder.() -> Unit = {
|
||||
Style("font-weight", "normal")
|
||||
Style("font-size", "1em")
|
||||
Style("line-height", "normal")
|
||||
Style("color", "rgba(255, 255, 255, 0.9)")
|
||||
Style("color", Palette.White90)
|
||||
}
|
||||
|
||||
private val SettingsDesc: csstype.PropertiesBuilder.() -> Unit = {
|
||||
Style("font-family", "BaseFontRegular, FallbackFontRegular")
|
||||
Style("font-size", "0.85em")
|
||||
Style("line-height", "1.35")
|
||||
Style("color", "rgba(255, 255, 255, 0.5)")
|
||||
Style("color", Palette.White50)
|
||||
Style("margin-top", "0.2em")
|
||||
}
|
||||
|
||||
@@ -2297,7 +2269,7 @@ private val SettingsDropTitle: csstype.PropertiesBuilder.() -> Unit = {
|
||||
Style("font-size", "1em")
|
||||
Style("line-height", "normal")
|
||||
Style("margin", "0 0 1em")
|
||||
Style("color", "rgba(255, 255, 255, 0.9)")
|
||||
Style("color", Palette.White90)
|
||||
}
|
||||
|
||||
private val SettingsSelect: csstype.PropertiesBuilder.() -> Unit = {
|
||||
@@ -2307,9 +2279,9 @@ private val SettingsSelect: csstype.PropertiesBuilder.() -> Unit = {
|
||||
Style("min-width", "4.375em")
|
||||
Style("width", "100%")
|
||||
Style("height", "3.125em")
|
||||
Style("border", "0.063em solid rgba(255, 255, 255, 0.2)")
|
||||
Style("border", "0.063em solid " + Palette.PanelBorder)
|
||||
Style("box-sizing", "border-box")
|
||||
Style("background-color", "rgba(255, 255, 255, 0.1)")
|
||||
Style("background-color", Palette.Panel)
|
||||
Style("padding-left", "0.875em")
|
||||
Style("padding-right", "0.875em")
|
||||
Style("color", "white")
|
||||
@@ -2346,7 +2318,7 @@ private val SettingsRange: csstype.PropertiesBuilder.() -> Unit = {
|
||||
Style("appearance", "none")
|
||||
Style("width", "100%")
|
||||
Style("height", "0.563em")
|
||||
Style("background-color", "rgba(255, 255, 255, 0.2)")
|
||||
Style("background-color", Palette.White20)
|
||||
Style("outline", "none")
|
||||
Style("accent-color", "rgb(255, 188, 9)")
|
||||
}
|
||||
@@ -2367,7 +2339,7 @@ private val SettingsButtons: csstype.PropertiesBuilder.() -> Unit = {
|
||||
private val SettingsButton: csstype.PropertiesBuilder.() -> Unit = {
|
||||
Style("width", "15.625em")
|
||||
Style("height", "3.125em")
|
||||
Style("background-color", "rgba(255, 255, 255, 0.1)")
|
||||
Style("background-color", Palette.Panel)
|
||||
Style("border", "0")
|
||||
Style("color", "white")
|
||||
Style("font-family", "BaseFontBold, FallbackFontBold")
|
||||
@@ -2382,6 +2354,13 @@ private val SettingsButtonWide: csstype.PropertiesBuilder.() -> Unit = {
|
||||
Style("width", "18.125em")
|
||||
}
|
||||
|
||||
private val SettingsActionButton: csstype.PropertiesBuilder.() -> Unit = {
|
||||
Apply(SettingsButton)
|
||||
Style("width", "10em")
|
||||
Style("min-width", "0")
|
||||
Style("padding", "0 1em")
|
||||
}
|
||||
|
||||
private val SettingsCheckboxRow: csstype.PropertiesBuilder.() -> Unit = {
|
||||
Style("display", "flex")
|
||||
Style("align-items", "center")
|
||||
@@ -2431,7 +2410,7 @@ private val SettingsKeyRow: csstype.PropertiesBuilder.() -> Unit = {
|
||||
Style("align-items", "center")
|
||||
Style("justify-content", "space-between")
|
||||
Style("padding", "0.35em 0")
|
||||
Style("border-bottom", "0.063em solid rgba(255, 255, 255, 0.1)")
|
||||
Style("border-bottom", "0.063em solid " + Palette.White10)
|
||||
}
|
||||
|
||||
private val SettingsScreen = FC<Props> {
|
||||
@@ -2440,6 +2419,7 @@ private val SettingsScreen = FC<Props> {
|
||||
var Sliders by useState<Map<String, Int>>(emptyMap())
|
||||
var Choices by useState<Map<String, Int>>(emptyMap())
|
||||
val UserName = StateOrNull()?.User?.Uid ?: ""
|
||||
val Tabs = SettingsTabLabels()
|
||||
val Entries = SettingsEntries(Tab, UserName)
|
||||
|
||||
fun ResetAll() {
|
||||
@@ -2449,7 +2429,7 @@ private val SettingsScreen = FC<Props> {
|
||||
ToastContext.Show("已重置当前设置(离线模式)")
|
||||
}
|
||||
|
||||
ScreenShell("设置", SettingsTabs.getOrElse(Tab) { "" }, FullBleed = true) {
|
||||
ScreenShell("设置", Tabs.getOrElse(Tab) { "" }, FullBleed = true) {
|
||||
div {
|
||||
css(SettingsPage)
|
||||
div {
|
||||
@@ -2468,7 +2448,7 @@ private val SettingsScreen = FC<Props> {
|
||||
Style("top", "calc(${Tab * 5}em + 1.25em)")
|
||||
}
|
||||
}
|
||||
for ((Index, Name) in SettingsTabs.withIndex()) {
|
||||
for ((Index, Name) in Tabs.withIndex()) {
|
||||
button {
|
||||
css(SettingsMenuItem)
|
||||
onClick = { Tab = Index }
|
||||
@@ -2484,6 +2464,7 @@ private val SettingsScreen = FC<Props> {
|
||||
css(SettingsContainer)
|
||||
div {
|
||||
css(SettingsPanel)
|
||||
div { css(SettingsHeadline); +Tabs.getOrElse(Tab) { "" } }
|
||||
var HasHeader = false
|
||||
for (Entry in Entries) {
|
||||
when (Entry) {
|
||||
@@ -2540,7 +2521,17 @@ private val SettingsScreen = FC<Props> {
|
||||
value = Entry.Options.getOrElse(Index) { Entry.Options.firstOrNull() ?: "" }
|
||||
onChange = { E ->
|
||||
val Found = Entry.Options.indexOf(E.target.value)
|
||||
if (Found >= 0) Choices = Choices + (Entry.Id to Found)
|
||||
if (Found >= 0) {
|
||||
Choices = Choices + (Entry.Id to Found)
|
||||
if (Entry.Id == "language") {
|
||||
val Code = Translations.Languages.getOrNull(Found)?.first ?: "zh-CN"
|
||||
Translations.LoadLocale(Code) {
|
||||
ScreenMount.Render()
|
||||
HeadMount.Render()
|
||||
HomeMount.Render()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Option in Entry.Options) option { value = Option; +Option }
|
||||
}
|
||||
@@ -2556,7 +2547,7 @@ private val SettingsScreen = FC<Props> {
|
||||
if (Entry.Desc.isNotEmpty()) div { css(SettingsDesc); +Entry.Desc }
|
||||
}
|
||||
button {
|
||||
css(SettingsButton)
|
||||
css(SettingsActionButton)
|
||||
onClick = { ToastContext.Show(Entry.Toast) }
|
||||
+Entry.Button
|
||||
}
|
||||
@@ -2590,8 +2581,8 @@ private val SettingsScreen = FC<Props> {
|
||||
css {
|
||||
Style("min-width", "2.2em")
|
||||
Style("padding", "0.2em 0.45em")
|
||||
Style("border", "0.063em solid rgba(255, 255, 255, 0.2)")
|
||||
Style("background-color", "rgba(255, 255, 255, 0.1)")
|
||||
Style("border", "0.063em solid " + Palette.PanelBorder)
|
||||
Style("background-color", Palette.Panel)
|
||||
Style("text-align", "center")
|
||||
Style("font", "500 0.8em/1.3 ${Ui.FontMedium}")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
// Palette.kt —— 原版配色表
|
||||
//
|
||||
// 来源:module_82347 的 C9i(E9i() 单例)构造器。
|
||||
// 这些是原版 Kotlin/JS 主题对象的字段值,不是从截图上取的近似色。
|
||||
package App.Browser.Ui
|
||||
|
||||
object Palette {
|
||||
// 基础
|
||||
const val Transparent = "transparent"
|
||||
const val Black = "rgb(0, 0, 0)"
|
||||
const val Black20 = "rgba(0, 0, 0, 0.2)"
|
||||
const val Black30 = "rgba(0, 0, 0, 0.3)"
|
||||
const val Black50 = "rgba(0, 0, 0, 0.5)"
|
||||
const val White = "rgb(255, 255, 255)"
|
||||
const val White05 = "rgba(255, 255, 255, 0.05)"
|
||||
const val White10 = "rgba(255, 255, 255, 0.1)"
|
||||
const val White15 = "rgba(255, 255, 255, 0.15)"
|
||||
const val White20 = "rgba(255, 255, 255, 0.2)"
|
||||
const val White25 = "rgba(255, 255, 255, 0.25)"
|
||||
const val White30 = "rgba(255, 255, 255, 0.3)"
|
||||
const val White40 = "rgba(255, 255, 255, 0.4)"
|
||||
const val White50 = "rgba(255, 255, 255, 0.5)"
|
||||
const val White60 = "rgba(255, 255, 255, 0.6)"
|
||||
const val White70 = "rgba(255, 255, 255, 0.7)"
|
||||
const val White90 = "rgba(255, 255, 255, 0.9)"
|
||||
const val White95 = "rgba(255, 255, 255, 0.95)"
|
||||
|
||||
// 主色
|
||||
const val Yellow = "rgb(255, 188, 9)"
|
||||
const val Yellow30 = "rgba(255, 188, 9, 0.3)"
|
||||
const val Yellow20 = "rgba(255, 188, 9, 0.2)"
|
||||
const val YellowSoft = "rgb(255, 214, 48)"
|
||||
const val Cyan = "rgb(0, 212, 255)"
|
||||
const val CyanBright = "rgb(0, 215, 255)"
|
||||
const val Green = "rgb(118, 255, 51)"
|
||||
const val Green70 = "rgba(118, 255, 51, 0.7)"
|
||||
const val Green30 = "rgba(118, 255, 51, 0.3)"
|
||||
const val BlueLight = "rgb(191, 213, 255)"
|
||||
const val Blue = "rgb(80, 182, 255)"
|
||||
const val BlueDark = "rgb(61, 111, 186)"
|
||||
const val Red = "rgb(255, 124, 124)"
|
||||
const val RedSoft = "rgb(255, 102, 102)"
|
||||
const val RedStrong = "rgb(235, 87, 87)"
|
||||
const val Orange = "rgb(232, 139, 0)"
|
||||
const val Purple = "rgb(175, 115, 225)"
|
||||
const val Teal = "rgb(48, 213, 200)"
|
||||
|
||||
// 面板 / 边框 / 文本
|
||||
const val Panel = White10
|
||||
const val PanelSoft = White05
|
||||
const val PanelBorder = White20
|
||||
const val Divider = White25
|
||||
const val DividerSoft = White15
|
||||
const val Text = White
|
||||
const val TextMuted = White60
|
||||
const val TextDim = White50
|
||||
const val TextFaint = White40
|
||||
|
||||
// 原版渐变
|
||||
const val PageGradient = "radial-gradient(#203040 0%, #03080D 100%)"
|
||||
const val PageGradientTop = "linear-gradient(to top right, #4A4A5B 0%, #32363E 100%)"
|
||||
const val MenuGradient = "linear-gradient(to right, #2E3235, rgba(46, 50, 53, 0))"
|
||||
const val MenuGradientDown = "linear-gradient(to bottom, #2E3235 0%, #2E3235 0.01%, rgba(46, 50, 53, 0.1) 83.57%, rgba(46, 50, 53, 0) 100%)"
|
||||
const val TopGradient = "linear-gradient(180deg, rgba(0, 25, 38, 0.98), rgba(0, 16, 24, 0.94))"
|
||||
}
|
||||
@@ -8,20 +8,20 @@ import csstype.PropertiesBuilder
|
||||
import react.dom.html.HTMLAttributes
|
||||
|
||||
internal object Ui {
|
||||
// 颜色
|
||||
// 颜色(全部来自 Palette.kt 的原版 C9i 配色表)
|
||||
const val Bg = "#001926"
|
||||
const val BgDeep = "#000b12"
|
||||
const val Panel = "rgba(0, 18, 28, 0.82)"
|
||||
const val PanelSoft = "rgba(0, 18, 28, 0.55)"
|
||||
const val Divider = "rgba(255, 255, 255, 0.25)"
|
||||
const val DividerSoft = "rgba(191, 213, 255, 0.12)"
|
||||
const val Text = "#ffffff"
|
||||
const val Muted = "rgba(255, 255, 255, 0.55)"
|
||||
const val Accent = "#76ff33"
|
||||
const val Cyan = "#00d4ff"
|
||||
const val Ruby = "#ff4a6a"
|
||||
const val Crystal = "#7fd4ff"
|
||||
const val Danger = "#ff5a5a"
|
||||
const val BgDeep = "#03080D"
|
||||
const val Panel = Palette.Panel
|
||||
const val PanelSoft = Palette.PanelSoft
|
||||
const val Divider = Palette.Divider
|
||||
const val DividerSoft = Palette.DividerSoft
|
||||
const val Text = Palette.Text
|
||||
const val Muted = Palette.TextMuted
|
||||
const val Accent = Palette.Green
|
||||
const val Cyan = Palette.Cyan
|
||||
const val Ruby = Palette.Red
|
||||
const val Crystal = Palette.BlueLight
|
||||
const val Danger = Palette.RedStrong
|
||||
|
||||
// 字体
|
||||
const val FontRegular = "BaseFontRegular, \"Segoe UI\", sans-serif"
|
||||
@@ -50,8 +50,8 @@ internal val ScreenRoot: PropertiesBuilder.() -> Unit = {
|
||||
Style("display", "flex")
|
||||
Style("flex-direction", "column")
|
||||
Style("min-height", "0")
|
||||
Style("background", "radial-gradient(#203040 0%, #03080D 100%)")
|
||||
Style("background-color", "#03080D")
|
||||
Style("background", Palette.PageGradient)
|
||||
Style("background-color", Ui.BgDeep)
|
||||
Style("color", Ui.Text)
|
||||
Style("font-family", Ui.FontRegular)
|
||||
Style("overflow", "hidden")
|
||||
|
||||
@@ -241,9 +241,9 @@ body { margin: 0; overflow: hidden; background: #001926; color: #fff; }
|
||||
|
||||
/* ---------------- 屏幕 / 返回 / 底部信息 ---------------- */
|
||||
.ms-content {
|
||||
position: absolute; inset: 0; z-index: 6;
|
||||
padding: 7em 3em 2.5em; box-sizing: border-box; overflow: auto;
|
||||
background: linear-gradient(180deg, rgba(0, 12, 20, 0.86), rgba(0, 8, 14, 0.94));
|
||||
position: absolute; inset: 6em 0 0 0; z-index: 1;
|
||||
padding: 0; box-sizing: border-box; overflow: hidden;
|
||||
background: none;
|
||||
}
|
||||
.hidden { display: none !important; }
|
||||
.ms-back {
|
||||
|
||||
Reference in new issue
Block a user