红脚本配置框架

创作者: DigitalVixen
已更新:2026-09-12 20:37:24
147KB

关于此 MOD

女孩就该得到自己想要的。带有动态内容的配置框架,支持Redscript及游戏内使用。(づ。◕‿‿◕。)づ
《双人展演》制作方 咖啡2A!-

一些简短的 GIF 动图,展示了“真·第一人称摄像机 2.0”使用该框架的效果。





- 引言 -

我发现,我需要一个更好的模组配置工具。具体来说,我想在游戏中直接调整我的《真·第一人称视角2.0》模组,而不必每次都跳出游戏去菜单里设置。如果能更轻松、更流畅地浏览选项,那就更棒了…… 

环顾四周后,我意识到摆在我面前的无非两条路:要么放弃,要么用CET作为桥梁,借助覆盖系统来实现。但在《赛博朋克》的模组制作生涯里,我早对CET积怨已久,所以这条路根本行不通……那该怎么办呢?自己动手呗,你这懒姑娘!哦,行吧……

那——这是什么?这是一个基于弹窗的配置框架,日后我所有的模组都将使用它。它支持多标签页、子标签、分区标题、下拉列表、提示框、滑块、开/关按钮、其他按钮、加减步进器,甚至还能显示图片。超过一页的选项会自动滚动,因此即便模组包含数百项设置,也能保持整洁易读。发布时还会支持两种风格,未来计划按模组分配颜色。

该模组借助优秀的 RedData 与 RedFilesystem 模组,扩展了 Redscript 的功能,使其能轻松读写 JSON 文件,并将所有配置以 JSON 格式存储。

想要使用该框架的模组可以通过几种不同方式实现,具体方法将在下文详细说明。简而言之:将预制的JSON文件放入框架存储目录、调用API接口,或直接编写代码调用即可。

关于这些,其实还有更多要说的,不过我容易跑题,还是戴上我的码农帽,直接切入下面的具体细节吧。给所有玩家——太长不看版会帮你概括清楚!干杯!

TL;DR:动态配置优于静态配置——而且更酷炫!


- 配置器选项 -

自定义配置现已适配你的需求。 设置 面板标题中的按钮会打开独立的设置页面:

  • 整体缩放 整体缩放面板、窗口、控件及文本。专为高分辨率、客厅/电视游玩及掌机设备优化。
  • 文本大小 - 在缩放基础上增加独立的字号步进,用于在不放大窗口的情况下调整文本大小。
  • 手柄按键 在每条滑条两侧添加加号和减号按钮,方便控制器操作。
  • 记住最后位置 重新打开配置器时,将直接回到上次关闭的位置:包括相同的模组、标签页、子标签页以及滚动位置。当您调试设置时,能省去大量点击操作。 不跨存档保留.

一切改动即时生效,你的选择将在各轮游戏中保留。

- 恢复默认设置 -

每个模组面板都有一个 重置 恢复为模组作者预设值的按钮。确认提示会根据模组类型自适应:单页模组仅出现单个 重置全部模组标签模组已添加 重置此页签,且带有子标签的模组会增加 重置此子标签页 这样你就可以只清除你尝试的部分,或者重新开始整个模组。


- 计划更新 -

一系列改进正在筹备中,包括框架本身及其配套工具和文档的优化工作。
请提供需要翻译的文本内容。 可伸缩性 - 能够缩放窗口. 完成!
2. 文本大小 - 调整文字大小. 完成!
3. 更好的手柄支持. 完成!
4. 重置按钮. 完成!
5. 记住你当时的位置. 完成!
6. 翻译支持. 完成.

工具与文档:
基于Python的转换器,将Mod设置迁移至本框架。  制作中.
2. 包含详细模组制作资源的 Readme.md 文件。  制作中.
3. 附有清晰代码注释的演示模组。  制作中.

希望这些即将推出的更新与新增内容能帮助更多人上手。在此期间,如果你想使用框架并有疑问,欢迎通过私信、评论或Discord随时联系我!


- 框架技术详情 -

框架的核心是一套轻量的RedScript系统,配合一个Codeware弹窗。MOD无需构建任何用户界面,也无需改动任何文件,所有操作只需交付给框架处理。 请提供需要翻译的文本内容。 (该设置的说明文字)和一个 提供商 (一个按名称读写设置的小类。)框架负责渲染面板、处理鼠标及手柄输入、绘制提示框,并将所有内容保存至磁盘。

- 如何组合在一起 -

  • 枢纽 控制器。快捷键可打开该界面,依次显示模组选择器及所选模组的面板。
  • 注册表 已注册此会话的模组实时列表。
  • 提供者 - 你与框架的契约:每个模组一个小型类,构建模式,按键存取数值,处理按钮。
  • 商店 持久性。框架掌控所有配置文件;你的模组完全不涉及任何文件操作。

流程很简单:存档加载时,你的模组会注册一次。框架会在面板打开前,从磁盘读取你保存的数据,并推送至你的提供者,这样你的模组就能以正确的设置运行。当用户关闭面板时,框架会将当前数值写回。

两套视觉风格开箱即用:经典模式(文字标签,正宗第一人称视角)与按钮模式(边框按钮标签)。由服务商选定其中一套。打开快捷键默认为F8,可在游戏内通过模组设置重新绑定。

```json { "settings": "设置", "new game": "新游戏", "load game": "读取存档", "save": "保存", "exit": "退出", "confirm": "确认", "cancel": "取消", "yes": "是", "no": "否", "accept quest": "接受任务", "quest completed": "任务完成", "talk": "交谈", "use": "使用", "attack": "攻击", "defend": "防御", "item": "道具", "magic": "魔法", "equip": "装备", "unequip": "卸下", "buy": "购买", "sell": "出售", "leave": "离开", "you got": "获得", "hp": "生命值", "mp": "魔力值", "exp": "经验值", "level up": "升级", "game over": "游戏结束", "continue": "继续", "load": "读取", "options": "选项", "language": "语言", "volume": "音量", "graphics": "画面", "controls": "操作", "key bindings": "按键设置", "apply": "应用", "reset to defaults": "恢复默认", "skip": "跳过", "auto": "自动", "log": "日志", "inventory": "背包", "equipment": "装备栏", "skills": "技能", "status": "状态", "map": "地图", "journal": "日志", "help": "帮助", "you died": "你死了", "retry": "重试", "return to menu": "返回主菜单", "save complete": "保存完成", "overwrite": "覆盖", "empty slot": "空位", "new game+": "二周目", "difficulty": "难度", "easy": "简单", "normal": "普通", "hard": "困难", "loading...": "加载中…", "press any key": "按任意键", "objective updated": "目标已更新", "quest failed": "任务失败", "reward": "奖励", "talk to": "与…交谈", "defeat": "击败", "collect": "收集", "deliver": "交付", "protect": "保护", "escort": "护送", "search": "搜索", "activate": "激活", "deactivate": "关闭", "locked": "已锁定", "unlocked": "已解锁", "requires": "需要", "key item": "关键道具", "consumable": "消耗品", "weapon": "武器", "armor": "护甲", "accessory": "饰品", "potion": "药水", "elixir": "灵药", "antidote": "解毒剂", "revive": "复活", "full restore": "完全恢复", "damage": "伤害", "heal": "治疗", "buff": "增益", "debuff": "减益", "critical hit": "暴击", "miss": "未命中", "dodge": "闪避", "block": "格挡", "resistance": "抗性", "weakness": "弱点", "immune": "免疫", "absorb": "吸收", "reflect": "反射", "status effect": "状态效果", "poison": "中毒", "paralyze": "麻痹", "sleep": "睡眠", "silence": "沉默", "confuse": "混乱", "blind": "致盲", "curse": "诅咒", "petrify": "石化", "instant death": "即死" } ```

框架利用JSON实现两项功能:无需RedScript即可注册完整配置面板,同时作为所有模组数据的存储仓库。这两项功能均需依赖优秀的RedData与RedFileSystem模组运行。

- 使用JSON文件注册 -

将名为 <modId>.schema.json 的单个文件放入 Framework 存储文件夹中。
r6\storages\RedscriptConfigFramework\<模组ID>.schema.json

框架在加载时读取该文件,基于它构建面板、注册模组,并自动存储数值。无需提供类、注册调用或任何RedScript。该文件自上而下描述面板结构:
{
  "modId": "mymod"
  “displayName”:“我的模组”
  "description": "配置我的模组。"
  "tabStyle": "经典风格"
  "tabs": [
    {
      "name": "将军"
      小白
        {
          "name": "行为"
          "rows": [
            {"kind": "label", "label": "简短标题。"}
            { "kind": "header", "label": "子章节标题" }
            { "kind": "toggle", "key": "enabled", "label": "启用", "tooltip": "可选。", "default": true }
            { "kind": "slider", "key": "strength", "label": "力量", "min": 0.0, "max": 100.0, "step": 5.0, "isInt": false, "default": 60.0 }
            { "kind": "stepper", "key": "level", "label": "等级", "min": 1.0, "max": 10.0, "step": 1.0, "isInt": true, "default": 3 }
            { "kind": "dropdown", "key": "mode", "label": "模式", "options": ["关闭", "低", "高"], "default": 1 }
            重置为默认
            { "种类": "图像", "图集": "base\\...\\some.inkatlas", "部件": "部件名称", "宽度": 600.0, "高度": 200.0 }
          ]
        }
      ]
    }
  ]
}

数值范围字段(最小值、最大值、步进、宽度、高度)须使用小数点书写。重置按钮是无脚本面板唯一可关联的按钮,它可将所有数值恢复为默认值。若需实现其他功能(如运行自定义代码的按钮),则需使用下方的API路径。

- 存放数值之处 -

无论模组以何种方式注册,其当前值都存储在一个独立的平面文件中:
r6\storages\RedscriptConfigFramework\<模组ID>.json

这是一个键值对形式的扁平对象,每个键与架构中的绑定键一一对应:
{
  "启用": true
  "力量":75.0
  "模式": 2
}

每个MOD单独使用一个文件是刻意的设计。单个损坏的数值不会影响其他设置,卸载某个MOD只需删除单个文件,排查问题时也便于手动阅读和编辑。你无需亲自打开或解析它;框架会在注册时自动加载该文件,并在设置面板关闭时写入数据,首次运行时还会从默认值生成文件,确保其始终存在。

- API -

集成包含一个小类和一个注册调用。

- 供应商 -

子类 DVRCF_Provider。BuildSchema 描述你的设置;get 和 set 方法将每个键绑定到你的模组实际存储该值的位置(配置系统、持久字段等)。

public class MyModProvider 继承自 DVRCF_Provider
  ```lua public func BuildSchema() -> ref<DVRCF_Schema> { ```
    返回 DVRCF_SchemaBuilder.New("我的模组")
      .Tab("通用")
      .章节("行为")
      .Toggle("enabled", "启用").Tip("开启或关闭模组")
      .Slider("strength", "力量", 0.0, 100.0, 5.0, false)
      .Build();
  }

  public func GetBool(key: String) -> Bool {
    如果(key等于"enabled") { 返回 MyConfig.Get().enabled; }
    返回假;
  }
  public func SetBool(key: String, value: Bool) -> Void {
    如果等于(key, "enabled") { MyConfig.Get().enabled = value; }
  }

  public func GetFloat(key: String) -> Float {
    if Equals(key, "strength") { return MyConfig.Get().strength; }
    返回 0.0;
  }
  public func SetFloat(key: String, value: Float) -> Void { 设置浮点数(键: 字符串, 值: 浮点数) -> 空 }
    如果(key等于"strength") { MyConfig.Get().strength = value; }
  }
}

每行包含一个字符串键,框架会通过该键调用您的提供程序:
  • 切换 绑定一个布尔值(GetBool / SetBool)。
  • 滑块 和 步进者 绑定一个浮点数或整数,当最后一个参数 (isInt) 为真时绑定整数(使用 GetFloat/SetFloat 或 GetInt/SetInt)。屏幕上的数值会根据步长四舍五入显示合理的小数位数,例如步长为0.5时显示“17.5”,步长为10时显示“20”。
  • 下拉菜单 绑定一个整数,表示所选选项的索引(通过GetInt/SetInt进行读写)。
  • 按钮 调用其按键对应的 OnButton。
  • 标签, 组队 (小节标题)且 图片 仅用于显示——不绑定任何按键。

GetTabStyle 选择显示样式(默认为经典)
```swift
public func GetTabStyle() -> DVRCF_TabStyle {
    // 获取标签样式
}
```
  返回 DVRCF_TabStyle.Buttons;
}

- 正在构建计划 -

模式构建器操作流畅。标签页与分区均为可选;若仅使用单层列表,将自动归为一个隐含的标签页与分区。多个标签页会生成顶部标签栏,单个标签页内包含多个分区则会显示左侧子导航栏。在分区内,使用 .Group(...) 可添加子分区标题,将冗长的选项列表按标签分组展示。

DVRCF_SchemaBuilder.New("我的模组")
  .Tab("通用")
  .Section("行为")
  标签("短标题。")
  .Group("能量")
  .开关("启用", "启用").提示("可选悬停描述。")
  .Slider("volume", "音量", 0.0, 100.0, 5.0, false)
  .Group("定时")
  .Stepper("count", "数量", 0.0, 10.0, 1.0, true)
  .Dropdown("mode", "模式", modeOptions)
  按钮("重置", "恢复默认设置")
  关于
  .Image("base\\...\\some.inkatlas", "part_name", 600.0, 200.0)
  .Build() 构建()

.Tip(text) 会在其前一行的行尾附加一个悬停提示框。 .Group(text) 在分区内渲染一个子段落标题(加粗带下划线的标题)。 .Image 绘制 ink Atlas 中的部分图像。 当分区高度超过面板时,内容会自动滚动。

- 注册中 -

登录一次,等会话就绪时:

```protected cb func OnSessionReady(event: ref<GameSessionEvent>) -> Void {
```
  由于您提供的文本“DVRCF.Register(”看起来像是游戏代码或脚本片段,而不是常规的游戏内文本(如UI、对白或任务描述),我无法直接将其翻译为符合玩家习惯的自然中文。 在游戏本地化中,代码通常不会被翻译,除非该代码段是出现在游戏UI中的函数名或按钮标签(例如“注册”或“登记”)。如果这是游戏内某个操作或界面的描述,请提供更完整的上下文或明确的功能说明。 如果您指的是一个UI按钮或系统提示,例如“Register”,可以翻译为: **注册** 或根据游戏风格,如果是军队或科技题材,可译为: **登记** 请提供更多上下文以便进行更准确的翻译。
    this.GetGameInstance(),
    "MyMod"
    “我的模组”
    “配置我的模组”
    new MyModProvider()
  );
}

这就是完整的集成。该模组现已出现在中心界面,渲染其面板,并保持持久运行。

直接跳转到您的页面(例如通过您的热键),请使用深层链接进入中心页面:
DVRCF_Hub.Get(gi).OpenModConfig("MyMod");

- 读取自身代码中的数值 -

如果你是通过 JSON 文件注册的,那么这些值并不归你所有,而是由框架管理。请直接根据模组和键名从中读取。这种方式适用于任何模组,无论其注册方式如何。
let on: Bool = DVRCF.GetBool(gi, "mymod", "enabled");
var strength: Float = DVRCF.GetFloat(gi, "mymod", "strength");
`mymode = DVRCF.GetInt(gi, "mymod", "mode")`

存在匹配的 SetBool / SetFloat / SetInt 调用,用于写入数值并立即保存,适用于需要从代码中更改设置的情况。


- 更新 -

1.0.0 - 首次公开发布。
1.0.1 - 修复了因int32向零取整,导致在-19上每步进0.5时选项卡住的问题。
1.0.2 - 更改了JSON中不存在的值处理方式。
1.1.0 - 可缩放UI(整体缩放+文字尺寸)、面板内选项页、手柄滑块上的-/ +按键、记住上次位置、以及适配各模组结构的恢复默认设置按钮。
1.2.0 - 新增两项控制字符间距的选项;有助于西里尔文或其他有类似需求的字体用户。感谢以下人员: 8LOMU8 仅供参考


- 需求 -

该模组需要您安装以下内容:
红脚本
代码仓库
红文件系统
红数据
输入加载器

可选:
模组设置 (默认按键为F8,可前往设置热键)


- 安装 -

安装所有依赖项。
2) 将下载的文件解压到你的游戏主目录中。


- 卸载 -

删除目录 \Cyberpunk 2077\r6\scripts\RedscriptConfigFramework
删除目录 \Cyberpunk 2077\r6\storages\RedscriptConfigFramework
删除文件 \Cyberpunk 2077\r6\input\dvrcf.xml


- 制作人员名单 -

感谢CET与redscript社区的开发工具及文档支持。

一如既往,特别感谢我出色的测试员与合作者们: 夜起, 咖啡2a 和 阿波克里提亚!

界面缩放功能基于以下贡献者提供的方法实现 8LOMU8 - 使面板尺寸及文本支持缩放——已通过框架配置重新实现。

感谢所有杰出的模组作者,持续为大家创作免费内容,让我们尽情享受游戏乐趣!

此功能属于 DigitalVixen 模组套装。
你现在可以在Discord上找到我 这儿!

赛博朋克 2077 的热门 MOD

探索适用于 赛博朋克 2077 的最佳MOD,带来新功能、升级画面,以及令人兴奋的方式来改变您的游戏体验。

使用 Xmod 解锁 赛博朋克 2077 的全部潜力 — 今天就探索这些顶级 MOD!