popctl - GTA IV 人口控制

popctl - GTA IV 人口控制

GTA IV中的行人和交通在硬编码距离处被删除,密度设置无法改变这一点。popctl 可以移动这个距离。一份研究发布,记录了移除循环、为什么这两个常量不能就地编辑,以及哪些被测量了、哪些没有被测量。

[size=5][b]popctl:GTA IV:完整版的入口密度控制[/b][/size]
[i]研究性发布。源码、图表和问题追踪:[url=https://github.com/gutbash/popctl]github.com/gutbash/popctl[/url][/i]

[size=4][b]摘要[/b][/size]
GTA IV 中的环境行人在玩家身后不远处就会消失,而模组作者通常会去调整的设置项对此并无效果。本次发布记录了原因。入口密度管理器的移除循环会将每个行人与玩家之间的平方距离与两个常量之一进行比较,这两个常量是 6400 和 225,由每个行人各自的标志位决定,并删除超出范围的行人。生成密度和移除半径是相互独立的,因此提高密度只会生成更多行人,而这些行人仍会在相同距离处被删除。由于这两个常量位于一个共享的只读池中,且该池还有其他读取者,因此无法就地修改它们。popctl 改为重写每个比较指令的四字节位移量,使其读取插件内部的浮点值,从而只改变这两个读取者,不影响其他任何内容。同样的技术也应用于每帧生成上限以及八个车辆入口密度静态变量。

[size=4][b]问题[/b][/size]
社区中用于控制人群密度的标准手段包括 popcycle.dat、密度倍率原生函数以及车辆密度命令行参数。于 2026-09-06 针对行人计数进行测试后,这些手段均未能将计数范围推进到约 60 米以外:密度倍率设为两倍时无变化;设为四倍时无变化;重写 popcycle.dat 后无变化。

在了解其机制后,这一结果是符合预期的。密度控制的是行人被创建的数量。它与行人被销毁的距离无关。

[size=4][b]方法[/b][/size]
移除循环位于 RVA 0x73AF50,由入口密度管理器 Process 在 0x73B540 处调用。它遍历行人池,计算平方距离,通过 vtable+0xD4 再读取字节 +0x142 来获取每个行人的标志位,然后分支到两个比较之一:
[code]0x73B04B    comiss xmm0, [6400.0]     80 m,屏幕内分支
0x73B054    comiss xmm0, [225.0]      15 m,其他情况[/code]两个操作数都是共享常量池中的条目。修改池条目会改变每一个读取该条目的指令,而距离两个条目之外的 60.0 在整个可执行文件中拥有 119 个读取者,因此这个池并不像看上去那样局部化。popctl 改为重写每条指令内部的位移量。两条指令都不会移动,常量池条目也不会改变。

另外三组值是普通数据全局变量,直接进行修补:位于 0xC4594C 的每帧环境生成上限,以及从 0xC3FF60 开始的 CVehiclePopulation 静态变量。

完整版的 .text 在加载时是加密的,因此每个补丁都要等待字节签名,根据实际映像基址验证位移量,然后才写入。任何未读取到其预期原始值的修补点都会被跳过并记录日志。

[size=4][b]发现[/b][/size]
[list]
[]决定可见人群深度的是移除半径,而非生成密度。这是主要结论,也是上述三种手段无效的原因。[/]
[]两个半径分别服务于不同的行人类别,必须同步调整,否则当行人跨越屏幕内标志位边界时效果会不均匀。[/]
[]SpawnsPerFrame 在 16 处饱和。管理器每帧最多收集十六个候选生成节点,因此更高的上限没有可消耗的对象。[/]
[]车辆池容纳 140 个条目,工厂在其之后返回 null,而入口密度代码在未检查的情况下对其解引用。VehMaxCars 设为 160 时可靠崩溃;发行值为 110。[/]
[/list][b]未进行帧时间测量。[/b]保持更多实体存活会消耗主线程 CPU,而该成本从未被量化。本文中的任何内容都不应被解读为任一方向的性能声明。

[size=4][b]安装[/b][/size]
[list=1]
[]确保已安装 ASI 加载器。通常使用的是作为 dinput8.dll 的 Ultimate ASI Loader,如果你使用 FusionFix,则已经拥有它。[/]
[]将 popctl.asi 和 popctl.ini 放入你的 GTAIV 文件夹,与 GTAIV.exe 放在一起。[/]
[]启动游戏。popctl.log 会出现在插件旁边,记录每次修补尝试及其结果。[/]
[/list]要卸载,删除这两个文件即可。插件不会向磁盘写入任何内容,也不会修改任何游戏文件。

popctl.ini 中有完整注释。FarKeepMetres 是关键的设置项,如果你的帧时间受到影响,也应首先降低它。

[size=4][b]限制[/b][/size]
以下是经过测试的范围边界。不应假定此范围之外的任何内容可以正常工作。
[list]
[][b]仅限完整版 1.2.0.59。[/b]每个地址都是该确切版本的硬编码偏移量。在任何其他版本上,检查都会失败,不会修补任何内容,日志会说明这一点。[/]
[][b]未进行性能表征。[/b]更大半径所带来的 CPU 成本是真实存在的,且未经测量。[/]
[][b]单一机器,单一模组组合。[/b]开发仅针对一个通过 ASI 加载器载入 FusionFix 的安装环境。[/]
[][b]池上限未改变。[/b]这控制的是游戏保留其已生成对象的时间长度,并不会扩大行人池或车辆池。[/]
[][b]屏幕内标志位为推断所得。[/b]+0x142 处的每个行人字节行为类似于屏幕内检测,并被当作此类处理。其确切语义尚未确认。[/]
[/list]
[size=4][b]可复现性[/b][/size]
上述发现来自单一系统的观察。任何复现这些结果的人都应报告游戏版本、所更改的手段,以及按距离统计行人数量的方法。明显的下一步工作包括:针对 FarKeepMetres 的帧时间成本曲线、对 VehMaxCars 崩溃阈值进行恰当的二分查找,以及确认标志位的语义。

[size=4][b]验证你下载的内容[/b][/size]
完整源码以 MIT 许可证发布于 GitHub,每个二进制文件都由公开的 GitHub Actions 从该源码构建,因此你可以阅读构建日志或自行构建,而不必信任上传内容。它是一个单一的翻译单元,除 Win32 SDK 外没有其他依赖。

popctl.asi SHA-256 e5ee804cb323b75168ac2774d70c3978fa311590ac390e27a5fb30c8b8158dbf

[size=4][b]配套发布[/b][/size]
[url=https://github.com/gutbash/revd]revd[/url] 解除了 GTA IV 的二十五个槽位引擎音频上限,这正是密集交通中大多数车辆无声的原因。不同的限制,不同的修复,与本发布相互独立。如果你使用 popctl 来提高交通多样性,你就会遇到那个上限,因此两者值得一起阅读。

[size=4][b]许可证[/b][/size]
MIT。随你喜欢使用它,包括将其打包进你自己的模组包中。