飞行自由

飞行自由

移除飞行高度上限和禁飞区规则。黑星和飞龙可以随心所欲地爬升,在高空或城镇上空都不会被摔下来,坐骑也可以在深渊中召唤。一次表写入,三处字节补丁,不触碰任何游戏文件。

[size=5][b]Flight Freedom[/b][/size]
[i]无飞行高度上限,无禁飞区,不会因进入城镇被强制下坐骑,且可在深渊中召唤坐骑。Crimson Desert 2.03.00。[/i]

Blackstar 和 Wyvern 在 1350 高度停止爬升,而在大约 1550 高度时游戏会强行夺走你的坐骑。这两个数值都来自游戏自身的数据。安装本模组后,两种飞行坐骑的高度上限都被移除,也不再有任何因素会因为飞得太高而将你从坐骑上摔下。那条会将你从坐骑上摔下的规则,同时也是深渊地面上提示"Cannot summon in this area."的原因,因此该限制也一并移除。

[size=4][b]更改内容[/b][/size]
[list]
[][b]高度上限。[/b]游戏 vehicleinfo 表中每种坐骑都有最大高度:Blackstar 和 Wyvern 为 1350,其余 32 种则没有。插件在启动时按名称找到该表,将你的设置写入这两行,并读回日志中,以便你确认已生效。[/]
[][b]禁飞区。[/b]每个地区都带有一份它拒绝的坐骑类别列表。有一个例程用于判断你所处的地区、或任何包含该地区的区域,是否列出了你当前骑乘的坐骑。这一判断结果正是将你从高空飞行坐骑上摔下、以及拒绝进入被列出地区的原因。三个字节可让它对所有位置都回答"未封锁"。[/]
[][b]深渊召唤。[/b]召唤检查会调用同一例程,其拒绝便是"Cannot summon in this area."这条消息。第二个补丁,一个字节,可让它跳过该拒绝,因此即使你决定保留区域限制,仍可在地下召唤坐骑。[/]
[][b]飞越城镇。[/b]另有一条规则会因你低空飞越城镇、离开道路而将你从坐骑上摔下,并提示"Cannot ride the mount in town."。该条件为"在城镇内且不在 20 范围内的道路上方",这就是为什么沿道路骑乘时从未触发过。三个字节可让道路条件半部分始终回答 yes,从而该规则永不会为真。该检查在整个游戏中仅被一个条件行使用;城镇内检测保持原样,因为有 23 行将其用于赏金升级和交易定价。[/]
[/list]其余内容均未改动。不修改任何游戏文件,也不会触及你的存档。游戏关闭时所有补丁都会撤销。

[size=4][b]设置[/b][/size]
FlightFreedom.ini 位于插件旁边,位于 [settings] 节点下。其中每个默认值也同时是插件自身的默认值,因此该文件是可选的:删除它也不会有任何损失。
[list]
[][b]Ceiling[/b] (-1) 飞行坐骑的高度上限。-1 表示移除,0 表示保留游戏的 1350,某个数字表示设置为你自己的值。[/]
[][b]NoFlyZones[/b] (1) 设为 1 表示没有地区会阻挡任何坐骑。设为 0 则高度摔下会回归。[/]
[][b]AbyssSummon[/b] (1) 设为 1 表示召唤检查不会再因你所处地区而拒绝你。在 NoFlyZones 开启时它不会做额外的事,且作为独立项存在,以便你保留摔下区域的同时仍能在地下召唤。[/]
[][b]PlatformSummon[/b] (0) 设为 1 表示召唤检查不会再因你所站立的物体而拒绝你。该检查正是阻止你在深渊 Nexus 传送圆上召唤的原因。默认关闭:该结果来自反汇编和一份报告,且开启后你也能够在游戏中任何移动平台上进行召唤。[/]
[][b]TownFlight[/b] (1) 设为 1 表示低空飞越城镇的离路区域时永远不会将你摔下。设为 0 则为游戏自身行为。[/]
[][b]BlackstarStays[/b] (1) Blackstar 会像 Wyvern 一样停留在你下坐骑的位置,而不会稍后再次起飞。设为 0 则为游戏自身行为。此项替代了 LandedTimeout,后者从未生效于该计时器,现已忽略。[/]
[][b]Probe[/b] (0) 构建本模组时使用的研究模式。它会挂钩游戏中所有与坐骑相关的检查,读取另外三个 ini 节点,可以挂钩、修补或监视任意地址,并写入非常大的日志。除非你在深入研究某些内容,否则请保持关闭。[/]
[/list]
[size=4][b]安装[/b][/size]
[b]使用 Definitive Mod Manager (DMM)[/b]
[list=1]
[]下载 DMM 文件并将其拖到 DMM 窗口上。[/]
[]启用并 Mount。DMM 会注册 FlightFreedom.asi 并引入其自带的加载器。[/]
[/list]DMM 压缩包中只有插件本身,因为这就是 DMM 所安装的内容。默认值已编译在内,因此它本身便是完整的。从 1.1.3 起,插件首次在自身旁边未发现 FlightFreedom.ini 时便会写入一个,因此启动一次游戏后该文件便会出现在 bin64 中等待编辑。已经存在的 ini 会被保留不动。

[b]手动安装[/b]
[list=1]
[]Ultimate ASI Loader (winmm.dll) 必须位于游戏的 bin64 文件夹中,与 CrimsonDesert.exe 相邻。[/]
[]在游戏关闭的情况下,将 FlightFreedom.asi 和 FlightFreedom.ini 复制到 bin64 中。[/]
[]启动游戏。FlightFreedom.log 会出现在插件旁边,并说明它更改了什么。[/]
[/list]
[b]卸载[/b]只需从 bin64 中删除 FlightFreedom 文件。

[b]如果另一个模组已经占用了 winmm.dll[/b]
OptiScaler、某些帧生成版本和某些 ReShade 配置会安装它们自己的 winmm.dll,而那个 winmm.dll 不会加载任何 ASI 插件。请保留它们的不动,并将 Ultimate ASI Loader 重命名为未被其他东西占用的名称。[b]xinput1_4.dll[/b]、[b]wininet.dll[/b]、[b]winhttp.dll[/b] 和 [b]d3d12.dll[/b] 都由 CrimsonDesert.exe 直接导入。[b]version.dll[/b] 同样可行,只是更进一步:exe 并不导入它,但 sentry.dll 导入它,而 CrimsonDesert.exe 每次启动都会导入 sentry.dll。

[b]一处更正。[/b]本页面直到 9 月 15 日都写着 version.dll 在此处永远无法加载,重命名为它毫无意义。那是错误的,kelstr33 为此花了一个晚上。我读取了 exe 的导入表,发现其中没有 version.dll,便从未查看 exe 自身依赖项导入了什么。

ReShade 和 RenoDX 通常占用 dxgi.dll,这使得 winmm.dll 空闲,而与 ReShade 的 dxgi.dll 并存的 winmm.dll 正是本模组的开发环境。bin64 中出现 FlightFreedom.log 便是全部测试:没有日志意味着没有任何东西加载了插件。

[size=4][b]兼容性[/b][/size]
[list]
[]为 Crimson Desert 2.03.00 (exe 1.0.0.2944) 构建。每个补丁都会检查它即将更改的字节,如果不是此版本所带的字节便会拒绝执行,因此在其他版本上你会在日志中看到一行记录,而不是损坏的游戏。高度上限是按名称并通过匹配表自身的行数找到的,而非按地址,这就是为什么它能在补丁无法存活的更新中存活。[/]
[]用于坐骑冷却和骑乘时长的 JSON 模组运行于不同层面:它们编辑磁盘上的游戏表,而本模组在运行时更改内存中的两条指令。我并未将它们并排运行过,如果你发现情况不同请告知。如果你使用了其中一个模组中的地区摔下文件,本模组会使其变得多余;两者不会冲突。[/]
[]仅限单人游戏。请勿在会对他人形成优势的任何地方使用。[/]
[/list]
[size=4][b]已知限制[/b][/size]
[list]
[]NoFlyZones 会清除游戏中每个地区的坐骑封锁,包括深渊以及高地地区。在此版本中,即使不打补丁,飞越 Hernand 和骑乘穿越城镇也从未被拒绝过,因此应该没有其他需要注意的地方,但这就是它实际的范围。[/]
[]留在深渊内的坐骑会留在那里。请在它尚在空中时召唤它,或骑它出去。无法找到通往你路径的地面坐骑不会被游戏召回,本模组也不更改这一点。[/]
[]"Cannot summon mount while it's on the ground"是一条不同的规则,保持原样。它的意思是你要召唤的坐骑已经在外并站在某处,即游戏按预期运行。[/]
[/list]
[size=4][b]如果出现问题[/b][/size]
FlightFreedom.log 写在插件旁边,在 Steam 安装中即 ...\steamapps\common\Crimson Desert\bin64\FlightFreedom.log。它很短,六十多行,每次启动都会重写。它记录读取到的设置、每个补丁是否写入以及写入前后的字节,以及它从表中读回的高度上限值。请在报告中附上相关行,外加发生了什么以及你当时所处的位置。

[size=4][b]发现过程[/b][/size]
最初的猜测是城镇和事件区域被标记为禁飞区,数据似乎支持这一点,但代码却忽略了它。真正的答案需要用一个探测插件,挂钩游戏自身的条件对象并记录每一个回答,然后挂钩 ini 中指定的任意地址。最终定位到一个例程,它在整个可执行文件中仅有两处调用者:将飞行坐骑摔下的检查,以及拒绝召唤的检查。三个补丁中的两个便出自这一发现。城镇规则是后来因玩家报告而发现的,并以同样方式测量后才成为一项设置。探测功能仍通过 Probe=1 保留在插件中。

[size=4][b]文件[/b][/size]
1.1.5 的 SHA-256:
[code]e7b98a56830ef30a123bc81864ee90e7e70a6ae8bf69be909f467ab543876adf FlightFreedom-1.1.5-DMM.zip
0e6c043690eeca578d9fa5b7ecb98101162ae938c40ec8e6fc4241ab099557f4 FlightFreedom-1.1.5.zip
0e9cfa08636074f3a3def27adde6ec277d9eef2e903383a252b0a90f5c02006c FlightFreedom.asi[/code]
尚未有标记。对于 1.1.0,插件在 VirusTotal 上得分为 66 中 0,DMM 压缩包 66 中 0,完整压缩包 68 中 0。所有三个 1.1.1 文件得分为 68 中 0。对于 1.1.2,插件得分为 70 中 0,DMM 压缩包 67 中 0,完整压缩包 68 中 0。对于 1.1.3,插件得分为 70 中 0,两个压缩包均为 68 中 0。对于 1.1.4 以及再次对于 1.1.5,插件得分为 70 中 0,DMM 压缩包 68 中 0,完整压缩包 67 中 0。报告见 [url=https://www.virustotal.com/gui/file/0e9cfa08636074f3a3def27adde6ec277d9eef2e903383a252b0a90f5c02006c]插件[/url]、[url=https://www.virustotal.com/gui/file/e7b98a56830ef30a123bc81864ee90e7e70a6ae8bf69be909f467ab543876adf]DMM 压缩包[/url] 和 [url=https://www.virustotal.com/gui/file/0e6c043690eeca578d9fa5b7ecb98101162ae938c40ec8e6fc4241ab099557f4]完整压缩包[/url]。

该插件只导入一个系统库 kernel32,别无其他:无网络、无注册表、除了自身的 ini 和 log 外不访问任何文件。扫描器仍可能对其形态提出异议,因为它是一个由加载器放入游戏内的 DLL,且一旦进入便会在内存中覆写指令。训练器也这么做,因此以训练器训练的模型会称其为训练器。它已进行代码签名,在 FlightFreedom.asi 上的属性、数字签名中显示为 Seth Walker。

[size=4][b]源码与许可[/b][/size]
MIT 许可。源码与构建说明在 GitHub 上:[url=https://github.com/shin2344234/flight-freedom]github.com/shin2344234/flight-freedom[/url]

[size=4][b]Discord 与 Patreon[/b][/size]
[url=https://discord.gg/AZ2ztQYy74]Shin234's Mods 'n Stuff[/url] 是 Discord,用于提问以及了解正在进行的工作。Bug 最好发在 bugs 标签页或作为 GitHub issues,以便被追踪。
Patreon 为 [url=https://www.patreon.com/cw/Shin234]patreon.com/cw/Shin234[/url],帖子在 [url=https://www.patreon.com/cw/Shin234/posts]patreon.com/cw/Shin234/posts[/url]。所有已发布内容均保持免费,不会为其保留任何东西。