XComModBridge

这是一个模组工具,旨在简化内置模组加载器的使用。它的用法类似于WGhost创建的Mutator方法,但允许双向通信,而非单向。它在游戏之间充当"桥梁"。

实用工具

img

安装:

  1. 将 XComModBridge.u 放入 CookedPCConsole 文件夹
  2. 使用 patchergui 或 upkutils 来应用 XComModBridge.txt 补丁
  3. 打开 DefaultGame.ini,在底部创建新部分 [XComGame.XComGameInfo],然后在该部分下添加行:ModNames[0]=XComModBridge.ModBridge

用法:

你可以在任何 actor 类(任何继承自 actor 的类)中通过使用 XComGameInfo(WorldInfo.Game).Mods[0] 来访问 ModBridge,任何不是 actor 的类则需要使用 XComGameInfo(class'Engine'.static.GetCurrentWorldInfo().Game).Mods[0]

在十六进制(伪代码)中,这看起来像:

10 25 19 2E <Class.XComGameInfo> 19 01 <Engine.Actor.WorldInfo> [@] <Engine.WorldInfo.Game> 00 ( 01 <Engine.WorldInfo.Game> ) [@] <XComGameInfo.Mods> 00 ( 01 <XComGameInfo.Mods> )

10 25 19 2E <Class.XComGameInfo> 19 12 20 <Engine.Engine> [@] <Engine.Engine.GetCurrentWorldInfo.ReturnValue> 00 ( 1B <GetCurrentWorldInfo> 16 ) [@] <Engine.WorldInfo.Game> 00 ( 01 <Engine.WorldInfo.Game> ) [@] <XComGameInfo.Mods> 00 ( 01 <XComGameInfo.Mods> )

ModBridge 内置了一些函数,它们可以作为变量使用,可以在游戏的基础 upk 文件中写入或访问。这是因为对于函数来说,upk 只需要一个“名称”(存储在 .upk 文件中的文本)引用,而不需要完全了解新的脚本文件:

19 ... ... [@] <NullRef> 00 ( 1B <StrValue0> 1F <%t "Sometext"> 16 )

这些函数及其用途如下:

  • string StrValue0(optional string str, optional bool bForce)
  • string StrValue1(optional string str, optional bool bForce)
  • string StrValue2(optional string str, optional bool bForce)
  • int IntValue0(optional int I = -1, optional bool bForce)
  • int IntValue1(optional int I = -1, optional bool bForce)
  • int IntValue2(optional int I = -1, optional bool bForce)
  • array<string> arrStrings(optional array<string> arrStr, optional bool bForce)
  • array<int> arrInts(optional array<int> arrInt, optional bool bForce)

任何不带参数调用的函数将返回其先前存储的值,包括数组,它们看起来像 arrInts()[2];

10 2C 02 1B <arrInts> 16

10 2C 02 19 ... ... [@] <NullRef> 00 ( 1B <arrInts> 16 )

如果你提供第一个参数,它将被存储以便稍后返回,bForce 选项用于强制存储第一个参数(如果你想确保存储的值被覆盖,即使默认值为 -1、0 或 "" 时也很有用)。

ModSorter:

还有一个系统可以通过名称访问添加到 XComMod 系统中的外部脚本。

首先,您想要添加的类必须扩展 XComMod

你可以通过将你的包添加到 CookedPCConsole 文件夹并在 defaultGame.ini 中的 [XComGame.XComGameInfo] 部分下添加一行 ModNames[(>0)]=[Package].[Class] 来使用这个功能,例如 ModNames[1]=MyMod.MyClass

注意:不要使用 [0],确保 XComModBridge 始终位于 [0] 位置,否则会导致某些功能失效。

要访问你的脚本而无需知道它在 ModNames 列表中的编号,请使用 ModBridge 函数 Mods:

  • XComMod Mods(string modName, optional string functName, optional string paras)

那么你有两种方式来访问你的函数,如果 functName 为空,那么该函数将返回你的 Mod,你将能够直接访问你的函数,但是该函数必须被命名为一个 '名称',该名称已经包含在你试图从中访问它的 upk 中,例如: XComGameInfo(WorldInfo.Game).Mods[0].Mods("MyMod.MyClass").SoldierState("某段文本", -3);

19 19 10 25 19 2E <XComGame.XComGameInfo> 19 01 <Engine.Actor.WorldInfo> [@] <Engine.WorldInfo.Game> 00 ( 01 <Engine.WorldInfo.Game> ) [@] <XComGameinfo.Mods> 00 ( 01 <XComGameInfo.Mods> ) [@] <NullRef> 00 ( 1B <Mods> 1F <%t "MyMod.MyClass"> 16 ) [@] <NullRef> 00 ( 1B <SoldierState> 1F <%t "sometext> 1D <%i -3> 16 )

如果该函数被命名为 SoldierStateSort,那么这将无法工作,因为 upk 文件不知道那是什么。

另一种选择是使用指定的 functName,它将访问你的 mod 类的 StartMatch() 函数,同时存储 functNameparas。你需要将 XComModBridge 添加到你的 UDK 项目中,并将你的 StartMatch() 函数设置成类似这样:

simulated function StartMatch()
{
    local string functionName;
    local string functParas;
    functionName = ModBridge(XComGameInfo(Outer).Mods[0]).functionName;
    functParas = ModBridge(XComGameInfo(Outer).Mods[0]).functParas;
    if(functionName == "TestFunct")
    {
        if(functParas != "")
        {
            TestFunct(functParas);
        }
        else
        {
            TestFunct();
        }
    }
}

最后这个功能灵感来源于之前 XCOM 模组中使用的突变器系统,该系统由 WGhost(非常感谢她!)添加以启用外部脚本,此处引入旨在整合各系统。

即将到来:

关于如何创建外部脚本模组和利用 ModBridge 的更深入指南。

实际模组钩子,这样我们就不必通过十六进制编辑基础 upk 文件来加载我们的模组。

TBC.