游戏状态(供模组制作者使用的CET工具)

游戏状态(供模组制作者使用的CET工具)

一个面向模组作者的轻量级Cyber Engine Tweaks (CET)工具。它跟踪玩家是否拥有完整的角色控制权,检测并返回状态,如菜单/暂停、模糊效果、过场动画等。

在模组研究过程中,我意识到在这款游戏中检测玩家是否处于活跃游戏状态比想象中困难,因此我决定构建这个实用工具,提供实时的活跃游戏状态检测,您无需编写繁重的帧循环或观察器。

它能优雅地处理状态追踪,并通过事件监听系统更新依赖的模组,因此您只需调用一次,且由于不依赖 onDraw 调用,性能极其出色。



[b]使用示例[/b]

[list]

[]如果您的模组有 UI 元素,希望在特定情况下或玩家不处于活跃游戏状态时隐藏。[/]

[]您希望在工具覆盖的特定状态下触发的操作。[/]

[/list]

[b]鸣谢 / 感谢[/b]

[list]

[]特别感谢 [b]psiberx[/b] 提供的开源 [url=https://github.com/psiberx/cp2077-cet-kit]CET KIT[/url]。此工具特别依赖其包含的 [b]GameSession[/b] 来处理大多数原始检测。[/]

[/list][line]

[b][size=4]多重返回状态系统[/size][/b]

该工具同时返回两个值:一个布尔值([size=2][font=Monaco, Menlo, Consolas, monospace]isPlayerInControl[/font][/size])和一个字符串([size=2][font=Monaco, Menlo, Consolas, monospace]currentControlState[/font][/size])。



[b]免责声明:[/b] 此工具提供高级宏观状态检测。它旨在告诉您游戏玩法是否暂停,并非提供超级精细的 UI 追踪。例如,它不会告诉您打开了哪个特定菜单或物品栏标签,这超出了其范围。



[b][size=4]追踪状态与覆盖范围[/size][/b]

[list]

[][font=Courier New][b]In Gameplay[/b][/font] (控制权:[font=Courier New]true[/font]) - 玩家对 V 拥有[b]完全控制权[/b],正常游戏(游戏会话加载后的默认状态)[/]

[][size=2][font=Monaco, Menlo, Consolas, monospace][b]Paused[/b] [/font][/size](控制权:[size=2][font=Monaco, Menlo, Consolas, monospace]false[/font][/size]) - 覆盖游戏内全屏菜单(物品栏、地图、任务等);暂停/Esc菜单;拍照模式;游戏内旅行/加载画面;入侵协议破解小游戏。[/]

[][size=2][font=Monaco, Menlo, Consolas, monospace][b]Blur Menus[/b] [/font][/size](控制权:[size=2][font=Monaco, Menlo, Consolas, monospace]false[/font][/size]) - 覆盖类似武器/快捷物品轮盘、载具呼叫、无线电覆盖层等叠加菜单。[/]

[][size=2][font=Monaco, Menlo, Consolas, monospace][b]Phone Menu[/b] [/font][/size](控制权:[size=2][font=Monaco, Menlo, Consolas, monospace]false[/font][/size]) - 覆盖手机/联系人呼叫列表。此状态比较特殊,因为 GameSession 未能正确检测,我必须为其构建检测器。[/]

[][size=2][font=Monaco, Menlo, Consolas, monospace][b]In Cutscene[/b] [/font][/size](控制权:[size=2][font=Monaco, Menlo, Consolas, monospace]false[/font][/size]) - 覆盖所有第一人称脚本化过场序列、过山车和超梦播放,以及部分失去 V 控制的场景,如抚摸宠物、洗澡等。[/]

[][size=2][font=Monaco, Menlo, Consolas, monospace][b]Player Dead[/b] [/font][/size](控制权:[size=2][font=Monaco, Menlo, Consolas, monospace]false[/font][/size]) - 顾名思义[/]

[][size=2][font=Monaco, Menlo, Consolas, monospace][b]Not Loaded[/b] [/font][/size](控制权:[size=2][font=Monaco, Menlo, Consolas, monospace]false[/font][/size]) - 游戏会话/玩家开始前的初始启动阶段。[/]

[/list][b]例外情况[/b]

[list]

[]使用电脑不算玩家失去控制,因此会返回[b][i]In Gameplay[/i][/b]状态[/]

[]那些不使用游戏系统而是触发特殊变通方法的模组(例如 Fast Travel Anywhere 类模组),如果它们未触发默认加载画面,则不支持(会显示为[i]In Gameplay[/i]状态)[/]

[/list][line]



[b][size=4]如何使用[/size][/b]



[b]1. 安装要求[/b]

在您的 NexusMods 页面上将 [size=2][font=Monaco, Menlo, Consolas, monospace]GameplayState[/font][/size] 添加为硬性需求。



[b]2. 代码示例[/b]

您的模组只需通过 [font=Courier New]GameplayState.OnStateChange[/font] 监听器调用一次。无需担心观察器,且[size=4][b]不要[/b]在 [font=Courier New]onDraw[/font] 中声明监听器。[/size]



请参阅以下示例了解如何使用该工具,始终仅在原生的 [size=2][font=Monaco, Menlo, Consolas, monospace]onInit [/font][/size]事件钩子中使用。



[code]local GameplayState = nil -- 对 GameplayState 模组的引用

local isPlayerInControl = false -- 本地存储状态的变量

local currentControlState = "Unknown"



registerForEvent('onInit', function()

GameplayState = GetMod('GameplayState') -- 获取 GameplayState 模组引用的标准 CET 方法



-- 仅在您的模组初始化时添加监听器。GameplayState 模组将在状态变化时更新变量。

if GameplayState then

GameplayState.OnStateChange(function(inControl, stateName)

isPlayerInControl = inControl

currentControlState = stateName

end, 'Your Mod Name') -- 可选参数,用于在日志中标识您的模组(如需要)

else

print('[Your Mod Name] ERROR: 未找到 GameplayState 模组,请确保已安装!')

end



-- 现在您可以在任何地方(如 onDraw 内)使用本地变量,它将始终与游戏当前状态保持同步。

if GameplayState then

if isPlayerInControl then

-- 当玩家拥有控制权且处于游戏状态时的代码

else

if currentControlState == "In Cutscene" then

-- 为剧情沉浸感完全隐藏自定义 HUD 小部件

elseif currentControlState == "Paused" then

-- 保持 UI 覆盖层打开,但安全暂停生存/状态机制

end

end

end

end)[/code]

如果出于某种原因,您确实需要在其他地方手动调用它,还有一个直接的公共方法 [font=Courier New]GameplayState.isPlayerInControl()[/font] 可用,它将返回 [font=Courier New]inControl、stateName[/font] 的当前值。



[line]



[b][size=4]调试功能[/size][/b]



该工具包含一个内置 HUD,用于实时测试实现,确保其正常工作并返回您所需的内容:

[list]

[][b]监听器检测:[/b]当模组初始化且您的模组按上述示例正确调用 [font=Courier New]OnStateChange[/font] 时,该工具将在 CET 控制台打印一条 INFO 消息。[/]

[][b]配置菜单:[/b]打开 CET 以切换追踪 HUD 复选框。[/]

[][b]调试 HUD:[/b]启用后始终可见(无需打开 CET 覆盖层),实时显示活动状态以及 [b][i]Is Player In Control[/i][/b] 的 [b]是/否[/b]。启用调试模式时,它还会在每次状态变化时在 CET 控制台打印一条记录。[/]

[][b]HUD 位置/关闭:[/b]可拖拽至任意位置,但重新启用时会自动水平居中于屏幕顶部。关闭它会自动禁用调试模式,无需进入 CET 覆盖层模组设置。[/]

[][b]持久化设置:[/b]切换选项会自动保存到本地的 [font=Courier New]config.json[/font] 文件中,并在游戏重启后保留,这意味着即使触发 CET "Reload all mods",它也会持久存在,这对于开发您自己的模组非常有用。[/]

[/list][line]



[b][size=4]我的模组[/size][/b]

[list]

[][size=3][b][url=https://www.nexusmods.com/cyberpunk2077/mods/30315]Gameplay State (供模组制作者使用的 CET 工具)[/url][/b][/size][/]

[][size=3][b][url=https://www.nexusmods.com/cyberpunk2077/mods/29855]Beyond 60 - Level Uncap plus HP and Armor Scaling[/url][/b][/size][/]

[][size=3][b][url=https://www.nexusmods.com/cyberpunk2077/mods/29659]Breach Protocol Level XP[/url] [/b][/size][/]

[][b][url=https://www.nexusmods.com/cyberpunk2077/mods/29477][size=3]Vehicle Contracts (Delivery Missions) XP and Money Boost[/size][/url][/b][/]

[/list]