Modding with the UDK - XCOM:EU 2012

From Nexus Mods Wiki
Jump to: navigation, search


Overview

This article is derived from discoveries in the R&D XCOM Map Alterations thread, and others in the Nexus Mod Talk Forum.

Intended to point out some initial resources, we make no pretense to being all inclusive. Make use of the Unreal community terminology in your 'search-fu' with your preferred search engine. Do not be deterred by the references in the material to other Unreal Engine based games. The lessons should be generally applicable to the Unreal Engine and Unreal Development Kit (UDK) themselves.

As is often the case, knowing the correct terminology used in a community can make all the difference when searching for related material. Here is a list of "Legacy" (pre-Unreal3) terminology, which appears to have remained relevant. The longevity of the Unreal Engine has resulted in a large body of preexisting articles. Use of the correct terminology will make these easier to locate.

Given XCOM:EU 2012 is based upon the Unreal Engine 3, it follows that we should be able to exploit the existing mod support capabilities of that engine. One of these is the ability to use the free-for-non-commercial-use UDK to create new "packages" or "mods" for the game. Such content can be implemented as a simple mutator, a gametype, a total conversion, a player model, a VoicePack, an AnnouncerPack, and a few other ways.

Use of the UDK is a departure from the initial efforts to mod XCOM, which relied upon hex editing the game files and making the provided limited changes to INI values. Use of the UDK should permit more robust mods; ones that can add new content, and avoid the need for hex editing that requires updating after every patch.

Programs and Tools

See Unreal Developer Network (UDN) UE3 Home for many articles and resources.

Details

Would-be UE3 mod developers are advised to start with Mutators, because they can be stacked with others to combine their modifications.

Mutators only ever make small changes to the game - and should only ever make small changes. Because they do this, many mutators may be used at the same time in combinations for all manner of wierd and wonderful effects - this is the benefit and the flexibility of the mutator.

(More elaborate mods should look into adding levels to the game.)

According to this tutorial, mutator packages are created in conjunction with the UDK: even using assets from the existing game packages, but also by adding new art assets to new maps included in the package. "Named variables" are the means by which values from one package may be accessed in another. It seems that combined with 'streaming' map content from our new package, this would open many possibilities.

The Base Mutator class is found in XCOM's Engine.UPK:

The basics appear to be:

You write and compile your mod as usual. Since you want to write a mutator, you obviously need to subclass UT3's mutator class. What code you put into your subclass and what additional classes you need depends entirely on what exactly you want to achieve.


It seems like there was some initial thought of supporting modding better with XCOM, but apparently there wasn't the funding or time, maybe?

Anyhow, in the function XComGameInfo are found the variables :

config array<config string> ModNames
array<XComMod> Mods

However, ModNames isn't ever configured or used by default, and the XComMod class is empty. The ModNames config array IS used to define the pathnames to the inventory image data and mods that are passed from the DefaultGame.ini ModNames section. (See the How To section below, and the article Class: XComMod - XCOM:EU 2012 for details.)

General UE3 Tutorials:

Some specific links to learning to make mutators are at:

Differences from UTGame

First of all, while the hooks for Mutators are present in the code, there is no default implementation mechanism. See the subtopic #MutatorEnabler for a PatcherGUI mod to implement an INI-configurable Mutator enabler for XCOM.

With this mod #MutatorEnabler installed, Mutators can be added via DefaultGame.ini:

[XComStrategyGame.XComHeadquartersGame]
+MutatorNames=XComMutator.MyMutator

[XComGame.XComTacticalGame] +MutatorNames=XComMutator.MyMutator

Why two separate sections? Because XComHeadquartersGame and XComTacticalGame are two different games: Strategic and Tactical respectively. Both are children of the XComGameInfo class, so they share code but not variables. There also is MP Game and it's own GameInfo class and Mutators can theoretically affect MP games too, but this has not yet been investigated.

So with MutatorEnabler in place, to add a mutator in game one needs to create a new package containing mutator code, and add this package to DefaultEngine.ini, and it will include the new mutator automatically.

Here's an example mutator and configs: TestMutator.zip

Enable the console in EW (see Developer Console - XCOM:EU 2012) and type:

Mutate 4

to speed up animation or:

Mutate 0.1

to make it slower. Works the same as the slomo command.

Note Mutators are not going to perform the same as they do in UTGame. Because XCOM is very different from any FPS game, which was the target audience of the engine. In fact, the more I look into the code, the more I understand that XCOM is not using the Unreal Game Engine 3 so much as it's hacking it.

As a specific example of this, I've tried to actually replace XGAIBehavior_Sectoid class with a newly created XGAIBehavior_Sectoid_Alt class. And had no success.

After XGAIBehavior is spawned, it gets assigned to a unit and initialized. After. AFTER. So, by replacing it, I get units with no behavior at all, as I can't figure out what unit this behavior is supposed to belong to at the stage of spawning. Yes, behavior class has a reference to it's unit, but it gets assigned after it was spawned: when Init() function is called. Owner object can't help either, as behavior gets spawned by Player class, not Unit class.

I tried to replace XGUnit with XGUnit_Alt and rewrite behavior spawn, but with no luck either. Since replaced units get removed, I immediately win the mission.

So, mutators are good for UTGame, but not so good for XCOM. Unfortunately. All we can do with mutators (at the moment), seems to be inject some code into the PostBeginPlay function of an actor, but I can't even think of situations in which it can be useful.

If we had source codes, we could rewrite it to handle XCOM-specific mutators, but even then it would require a lot of work. More investigation is required.

How To

(The following is detailed by Amineri (lead programmer of the Long War mod) in the Nexus Mod Talk Forum "UI Editing" thread beginning here.)

The key to successfully using the UDK with XCOM is to realize an older version is required. The EW 'cooked' files indicate they were built with "Version 845, Licensee Version 64, Engine Version 8916", which is older than the oldest version of UDK (March 2012) found available from the Epic website. You can see in some of the earlier posts what happened where using a more recent version of the UDK. In that case the package won't load, or attempts to hex edit it to force loading causes the game to CTD because the UPK format was slightly altered.

Adding with Mutators

The following is taken from the Nexus Mod Talk Forum thread Scripting with UDK, as a result of explorations by wghost81.

XCOM does have a base abstract Engine.Mutator class. Engine.GameInfo class holds a variable named BaseMutator, which contains a first loaded Mutator. All the subsequent Mutators are organized into a linked chain by using the NextMutator variable, which is a member of the base Mutator class. So, for example, if we have 2 mutators (MyMut1 and MyMut2), the chain will look like:

BaseMutator=MyMut1, BaseMutator.NextMutator=MyMut2

Any "mutation" starts with BaseMutator and then gets propagated to other Mutators by using this chain.

XCOM doesn't have an in-game GUI to load mutators. The only way to load Mutators into an unmodified game I have found so far is by command line (game launch) parameters. Launch parameters are passed to the Engine.GameInfo.InitGame function, parsed and, if Mutator related options are found, corresponding mutators are created. The "Unreal Tournament Game (UTGame) has a way to add mutators via config file, but I can't find anything similar for XCOM. Anyway, since we can modify existing packages, we can either add direct spawning of our mutators, or duplicate UTGame config functionality.

Engine classes have built-in code to work with Mutators. This code allows catching some of the in-game events and modifying those with Mutators.

Basic Mutator functions, which can do actual game changes, are:

  • ModifyPlayer - modify Player spawn process. It is called whenever a player spawns. Since XCom Player is actually a cursor, this function is not so interesting for us. But in FPS game it allows easily modification of player starting attributes and inventory.
  • FindPlayerStart - modify player start position.
  • CheckReplacement - the most important function. It allows replacing one class with another class whenever an exemplar of a class is spawned. In other words, it allows us to "mutate" a class into a different class.

And a couple of other functions. Since Mutator is a child of Actor, it can also use and modify all the existing Actor class functions.

The important thing is: Mutators are intended to make a small changes to game rules. For UTGame those are starting player attributes and inventory, weapon and other equipment parameters, damage. The XCOM equivalent for such a small change can be, for example, the XGAIBehavior_Sectoid class. By creating a mutator and using CheckReplacement of the newly created mutator to replace XGAIBehavior_Sectoid class with a new XGAIBehavior_SectoidMod class, one can alter Sectoid AI without changing the existing class. The same thing could be done with, say, XGStrategyAI class to completely (or partially) rewrite its functionality.

Since mutators generally function by replacing one class with another one, two mods which both modify different functions inside the same class won't be compatible. But, as UE documentations states, mutators are intended for small modifications, not for big ones.

So far, only partial success has been achieved in implementing a Mutator. "Partially", because I couldn't activate it with a command line argument. I've added MUTATOR=XComMutator.MyMutator to the launcher parameters and I saw that line in the log, but my Mutator wasn't created. So I just hacked in with PatcherGUI and added

AddMutator("XComMutator.MyMutator", true);

line at the end of the Engine.GameInfo.InitGame function and then it worked.

I'm still trying to figure out what function is called when, so my first Mutator is very simple:

class MyMutator extends Mutator;

function Mutate(string MutateString, PlayerController Sender) { Sender.WorldInfo.Game.SetGameSpeed(float(MutateString)); super.Mutate(MutateString, Sender); }

The Mutate function can be called as a XCOM console command, for example, "Mutate 2". It will increases game speed to 2.0, same as the "slomo 2" command does.

wghost81 has a github project for XCOM-Mutators. It also has wiki pages, describing how to set up the UDK and how to create dummy scripts (necessary for compiling in the absence of unavailable Firaxis proprietary libraries). From there you can advance into other UDK functionality, like adding new content. The whole XCOM Randomized mod, which is also included in LW, was built by wghost81 using the UDK.

Add new image content

The goal in this test case is to add new image content to the "Long War" modded EW game using it's own custom UPK file.

  1. Downloaded and installed with June2010 UDK for the initial test case. (Later found and using Sep2011 UDK, originally located on GamersHell.com, which appears to match the "Enemy Unknown" versions exactly.)
    Some further refining on which UDK versions have been found available compared with the one used to "cook" XCOM:EW (Firaxis Unreal version: Version 845, Engine Version 8916).
    1. June 2010 UDK : version 727, engine version 6829
    2. September 2011 UDK : Version 845, Engine Version 8916
    3. Firaxis Unreal version : XCOM EU : Version 845, Engine Version 8916
    4. Firaxis Unreal version : XCOM EW : Version 845, Engine Version 8917
    5. December 2011 UDK : Version 852, Engine Version 9249
    6. March 2012 UDK : Version 859, Engine Version 9656
    ("Enemy Within" incremented the Engine Version by 1, apparently due to some minor change, perhaps something that Firaxis did to the Unreal Engine source code.)
  2. Created a new package in UDK:
    1. Within the UDKGame/Content folder, created a new subfolder LongWar/InventoryImages/.
    2. Added BMP image data to the new folder and imported the images into the UDK, into the "LongWar" package using the BuildFromFilePath option. "TextureGroup_UI" was used.
    3. Saved the resultant package file to Content/LongWar.upk.
  3. Copied the LongWar.upk file into the appropriate CookedPCConsole folder. The new UPK is already uncompressed. No hex alterations to the UPK are required.
  4. Configured the game to load the LongWar UPK file in DefaultContent.ini by adding the line Package=LongWar after:
    Map=Command1
    Package=StrategyResources
    Package=UICollection_Strategy
    Package=LongWar
    (If creating a package file with a different name, use yours, of course.)
  5. Edit DefaultGame.ini ModNames to update the pathname for the new image; (recommended: see example in code block below).
    NOTE: In the original test case the following hex edit was performed. This is no longer necessary but preserved for the benefit of other mod makers understanding.
    ----
    Hex edit XComGame.UIUtilities.GetInventoryImagePath and UIItilities.GetItemImagePath. This basically requires resizing the object using either PatchUPK or UPKmodder to fit the extra lines of code.
    For test case, redirected the call from the Pistol Inventory Image ID to the new image defined in LongWar.upk:
    case 37:
    return "img:///LongWar.InventoryImages.Long_War_Banner_2";
    ----
  6. Launched game and verified that new image data was loading into the game, and took the screenshot below.

New Content: Long War Pistol
(Image by Amineri, used with permission.)


Interested mod creators should read the Call for Long War Art thread for "lessons learned", and the Adding and changing art assets wiki article.


Example from "Long War" mod of adding pathnames to the DefaultGame.ini ModNames section:

[XComGame.XComGameInfo]

; Define image path strings for existing and modded image paths ; 0-299 are item images ModNames[0]="" ModNames[1]="UILibrary_StrategyImages.InventoryIcons.Inv_LaserShotgun"  ; T4 Scatter Blaster ModNames[2]="UILibrary_StrategyImages.InventoryIcons.Inv_Pistol"  ; T3 Gauss Pistol ModNames[3]="UILibrary_StrategyImages.InventoryIcons.Inv_AssaultRifleModern"  ; T3 Gauss Rifle ModNames[4]="UILibrary_StrategyImages.InventoryIcons.Inv_Shotgun"  ; ModNames[5]="UILibrary_StrategyImages.InventoryIcons.Inv_LMG"  ; ModNames[6]="UILibrary_StrategyImages.InventoryIcons.Inv_SniperRifle"  ; ModNames[7]="UILibrary_StrategyImages.InventoryIcons.Inv_RocketLauncher"  ; ModNames[8]="UILibrary_StrategyImages.InventoryIcons.Inv_LaserPistol"  ; ModNames[9]="UILibrary_StrategyImages.InventoryIcons.Inv_LaserRifle"  ; ModNames[10]="UILibrary_StrategyImages.InventoryIcons.Inv_LaserShotgun"  ; ModNames[11]="UILibrary_StrategyImages.InventoryIcons.Inv_LaserHeavy"  ; ModNames[12]="UILibrary_StrategyImages.InventoryIcons.Inv_LaserSniper"  ; ModNames[13]="UILibrary_StrategyImages.InventoryIcons.Inv_PlasmaPistol"  ; ModNames[14]="UILibrary_StrategyImages.InventoryIcons.Inv_PlasmaRifleLight"  ; ModNames[15]="UILibrary_StrategyImages.InventoryIcons.Inv_PlasmaRifle"  ; ModNames[16]="UILibrary_StrategyImages.InventoryIcons.Inv_PlasmaShotgun"  ; ModNames[17]="UILibrary_StrategyImages.InventoryIcons.Inv_PlasmaHeavy"  ; ModNames[18]="UILibrary_StrategyImages.InventoryIcons.Inv_PlasmaSniper"  ; ModNames[19]="UILibrary_StrategyImages.InventoryIcons.Inv_PlasmaBlasterLauncher"  ; ModNames[20]=""  ; MechtoidPlasmaCannon ModNames[21]=""  ; SeekerPlasmaPistol ModNames[22]="UILibrary_StrategyImages.InventoryIcons.Inv_PlasmaBlasterLauncher"  ; MEC Kinetic Strike Module ModNames[23]="UILibrary_StrategyImages.InventoryIcons.Inv_FlameThrower"  ; MEC Flamethrower ModNames[24]="UILibrary_StrategyImages.InventoryIcons.Inv_FragGrenade"  ; MEC Grenade Launcher ModNames[25]="UILibrary_StrategyImages.InventoryIcons.Inv_Medikit"  ; MEC Restorative Mist ModNames[26]="UILibrary_StrategyImages.InventoryIcons.Inv_ArcThrower"  ; MEC Electropulse ModNames[27]="UILibrary_StrategyImages.InventoryIcons.Inv_RespiratorImplant"  ; MEC Proximity Mine Launcher ModNames[28]="UILibrary_StrategyImages.InventoryIcons.Inv_MECChainGun"  ; ModNames[29]="UILibrary_StrategyImages.InventoryIcons.Inv_MECRailGun"  ; ModNames[30]="UILibrary_StrategyImages.InventoryIcons.Inv_MECParticleCannon"  ; ModNames[31]="UILibrary_StrategyImages.InventoryIcons.Inv_ReaperAmmo"  ; Alloy Jacketed Rounds ModNames[32]="UILibrary_StrategyImages.InventoryIcons.Inv_ExaltAssaultRifle"  ; T1 Assault Carbine ModNames[33]=""  ; SectopodCannon ModNames[34]="UILibrary_StrategyImages.InventoryIcons.Inv_Scope"  ; Marksman's Scope ModNames[35]=""  ; ChryssalidClaw ModNames[36]=""  ; DroneBeam ModNames[37]=""  ; PsiAmp ModNames[38]="UILibrary_StrategyImages.InventoryIcons.Inv_GrappleHook"  ; ModNames[39]=""  ; CyberdiscWeapon ModNames[40]="UILibrary_StrategyImages.InterceptorImages.Inv_EMPCannon"  ; Enhanced Beam Optics ModNames[41]="UILibrary_StrategyImages.InventoryIcons.Inv_PlasmaPistol"  ; SectoidPlasmaPistol ModNames[42]="UILibrary_StrategyImages.InventoryIcons.Inv_PlasmaRifleLight"  ; PlasmaLightRifle_ThinMan ModNames[43]=""  ; PlasmaLightRifle_Floater ModNames[44]=""  ; PlasmaLightRifle_Muton ModNames[45]="UILibrary_StrategyImages.InventoryIcons.Inv_PlasmaRifle"  ; PlasmaAssaultRifle_Muton ModNames[46]=""  ; HeavyPlasma_Floater ModNames[47]="UILibrary_StrategyImages.InventoryIcons.Inv_PlasmaHeavy"  ; HeavyPlasma_Muton ModNames[48]="UILibrary_StrategyImages.InventoryIcons.Inv_SkeletonKey"  ; Plasma Stellerator ModNames[49]=""  ; ZombieFist ModNames[50]=""  ; ElderWeapon ModNames[51]=""  ; MutonBlade ModNames[52]=""  ; OutsiderWeapon ModNames[53]="UILibrary_StrategyImages.InventoryIcons.Inv_AssaultRifleModern"  ; T3 Gauss Carbine ModNames[54]=""  ; Plague ModNames[55]=""  ; SectopodClusterBomb ModNames[56]=""  ; SeekerTentacles ModNames[57]="UILibrary_StrategyImages.InventoryIcons.Inv_ArmorKevlar"  ; ModNames[58]="UILibrary_StrategyImages.InventoryIcons.Inv_ArmorSkeleton"  ; ModNames[59]="UILibrary_StrategyImages.InventoryIcons.Inv_ArmorKevlar"  ; ModNames[60]="UILibrary_StrategyImages.InventoryIcons.Inv_ArmorCarapace"  ; ModNames[61]="UILibrary_StrategyImages.InventoryIcons.Inv_ArmorSkeleton"  ; ModNames[62]="UILibrary_StrategyImages.InventoryIcons.Inv_ArmorTitan"  ; ModNames[63]="UILibrary_StrategyImages.InventoryIcons.Inv_ArmorArchangel"  ; ModNames[64]="UILibrary_StrategyImages.InventoryIcons.Inv_ArmorGhost"  ; ModNames[65]="UILibrary_StrategyImages.InventoryIcons.Inv_ArmorPsi"  ; ModNames[66]=""  ; Covert Ops Armor ModNames[67]="UILibrary_StrategyImages.InventoryIcons.Inv_ArmorArchangel"  ; ModNames[68]="UILibrary_StrategyImages.InventoryIcons.Inv_ArmorPsi"  ; ModNames[69]="UILibrary_StrategyImages.InventoryIcons.Inv_Medikit"  ; ModNames[70]="UILibrary_StrategyImages.InventoryIcons.Inv_CombatStims"  ; ModNames[71]="UILibrary_StrategyImages.InventoryIcons.Inv_MindShield"  ; ModNames[72]="UILibrary_StrategyImages.InventoryIcons.Inv_ChitinPlating"  ; ModNames[73]="UILibrary_StrategyImages.InventoryIcons.Inv_ArcThrower"  ; ModNames[74]="UILibrary_StrategyImages.InventoryIcons.Inv_Scope"  ; ModNames[75]="UILibrary_StrategyImages.InventoryIcons.Inv_NanoFabricVest"  ; ModNames[76]="UILibrary_StrategyImages.InventoryIcons.Inv_RespiratorImplant"  ; ModNames[77]="UILibrary_StrategyImages.InventoryIcons.Inv_ExaltRocketLauncher"  ; Rocket ModNames[78]="UILibrary_StrategyImages.InventoryIcons.Inv_ReaperAmmo"  ; ModNames[79]="UILibrary_StrategyImages.InterceptorImages.Inv_EMPCannon"  ; Laser Sight ModNames[80]="UILibrary_StrategyImages.InventoryIcons.Inv_ReaperAmmo"  ; Hi Cap Mags ModNames[81]="UILibrary_StrategyImages.InventoryIcons.Inv_FragGrenade"  ; ModNames[82]="UILibrary_StrategyImages.InventoryIcons.Inv_SmokeGrenade"  ; ModNames[83]="UILibrary_StrategyImages.InventoryIcons.Inv_Flashbang"  ; ModNames[84]="UILibrary_StrategyImages.InventoryIcons.Inv_AlienGrenade"  ; ModNames[85]="UILibrary_StrategyImages.InventoryIcons.Inv_GhostGrenade"  ; ModNames[86]="UILibrary_StrategyImages.InventoryIcons.Inv_GasGrenade"  ; ModNames[87]="UILibrary_StrategyImages.InventoryIcons.Inv_NeedleGrenade"  ; ModNames[88]="UILibrary_StrategyImages.InventoryIcons.Inv_MimicBeacon"  ; ModNames[89]="UILibrary_StrategyImages.InventoryIcons.Inv_RocketLauncher"  ; Shredder Rocket ModNames[90]="UILibrary_StrategyImages.InventoryIcons.Inv_MotionDetector"  ; Battle Computer (MEC) ModNames[91]="UILibrary_StrategyImages.InventoryIcons.Inv_AlienGrenade"  ; ModNames[92]="UILibrary_StrategyImages.InventoryIcons.Inv_AlienGrenade"  ; ModNames[93]="UILibrary_StrategyImages.InventoryIcons.Inv_AlienGrenade"  ; ModNames[94]="UILibrary_StrategyImages.InventoryIcons.Inv_NanoFabricVest"  ; Chameleon Suit ModNames[95]="UILibrary_StrategyImages.InventoryIcons.Inv_NanoFabricVest"  ; Ceramic Plates ModNames[96]="UILibrary_StrategyImages.InventoryIcons.Inv_Flashbang"  ; ModNames[97]="UILibrary_StrategyImages.InventoryIcons.Inv_BattleScanner"  ; ModNames[98]="UILibrary_StrategyImages.InventoryIcons.Inv_AlienWeaponFragments"  ; Alien Trophy ModNames[99]="UILibrary_StrategyImages.InventoryIcons.Inv_PlasmaShotgun"  ; T5 Reflex Cannon ModNames[100]="UILibrary_StrategyImages.InventoryIcons.Inv_Shiv1"  ; ModNames[101]="UILibrary_StrategyImages.InventoryIcons.Inv_Shiv2"  ; ModNames[102]="UILibrary_StrategyImages.InventoryIcons.Inv_Shiv3"  ; ModNames[103]="UILibrary_StrategyImages.InventoryIcons.Inv_Interceptor"  ; ModNames[104]="UILibrary_StrategyImages.InventoryIcons.Inv_Firestorm"  ; ModNames[105]=""  ; Skyranger ModNames[106]="UILibrary_StrategyImages.InventoryIcons.Inv_Satellite"  ; ModNames[107]="UILibrary_StrategyImages.InventoryIcons.Inv_ReaperAmmo"  ; HEAT Ammo (SHIV) ModNames[108]="UILibrary_StrategyImages.InterceptorImages.Inv_EMPCannon"  ; Holo-Targeter (M/S) ModNames[109]="UILibrary_StrategyImages.InventoryIcons.Inv_SHIVGattlingGun"  ; T1 SHIV Autocannon ModNames[110]="UILibrary_StrategyImages.InventoryIcons.Inv_SHIVGattlingGun"  ; T3 SHIV Sentry ModNames[111]="UILibrary_StrategyImages.InventoryIcons.Inv_SHIVLaserCannon"  ; T2 SHIV Laser ModNames[112]="UILibrary_StrategyImages.InterceptorImages.Inv_InterceptorFusionLance"  ; T5 SHIV Plasma ModNames[113]="UILibrary_StrategyImages.InventoryIcons.Inv_Shiv1"  ; SHIV Tread Deck 1 ModNames[114]="UILibrary_StrategyImages.InventoryIcons.Inv_Shiv2"  ; SHIV Tread Deck 2 ModNames[115]="UILibrary_StrategyImages.InventoryIcons.Inv_Shiv3"  ; SHIV Tread Deck 3 ModNames[116]="UILibrary_StrategyImages.InterceptorImages.Inv_InterceptorMissilePod"  ; Stingray Missiles ModNames[117]="UILibrary_StrategyImages.InterceptorImages.Inv_InterceptorGunPod"  ; ModNames[118]="UILibrary_StrategyImages.InterceptorImages.Inv_InterceptorMissilePod"  ; ModNames[119]="UILibrary_StrategyImages.InterceptorImages.Inv_InterceptorLaserCannon"  ; ModNames[120]="UILibrary_StrategyImages.InterceptorImages.Inv_InterceptorPlasmaCannon"  ; ModNames[121]="UILibrary_StrategyImages.InterceptorImages.Inv_EMPCannon"  ; ModNames[122]="UILibrary_StrategyImages.InterceptorImages.Inv_InterceptorFusionLance"  ; ModNames[123]="UILibrary_StrategyImages.InventoryIcons.Inv_BattleScanner"  ; Counterfire Pods (SHIV) ModNames[124]="UILibrary_StrategyImages.InventoryIcons.Inv_BattleScanner"  ; Smartshell Pods (SHIV) ModNames[125]="UILibrary_StrategyImages.InventoryIcons.Inv_DefenseMatrix"  ; ModNames[126]="UILibrary_StrategyImages.InventoryIcons.Inv_UFOTracking"  ; ModNames[127]="UILibrary_StrategyImages.InventoryIcons.Inv_SatelliteTargeting"  ; ModNames[128]="UILibrary_StrategyImages.InventoryIcons.Inv_GrappleHook"  ; Weapon Supercoolers (SHIV) ModNames[129]="UILibrary_StrategyImages.InterceptorImages.Inv_InterceptorFusionLance"  ; The Thumper (MEC) ModNames[130]="UILibrary_StrategyImages.InterceptorImages.Inv_InterceptorGunPod"  ; AutoSentry Turret (SHIV) ModNames[131]="UILibrary_StrategyImages.InventoryIcons.Inv_BattleScanner"  ; Adaptive Tracking Pods (SHIV) ModNames[132]="UILibrary_StrategyImages.InventoryIcons.Inv_ChitinPlating"  ; Core Armoring (SHIV) ModNames[133]="UILibrary_StrategyImages.InventoryIcons.Inv_BattleScanner"  ; Damage Control Pod (SHIV) ModNames[134]="UILibrary_StrategyImages.CorpseIcons.Corpse_Sectoid"  ; ModNames[135]="UILibrary_StrategyImages.CorpseIcons.Corpse_SectoidCommander"  ; ModNames[136]="UILibrary_StrategyImages.CorpseIcons.Corpse_Floater"  ; ModNames[137]="UILibrary_StrategyImages.CorpseIcons.Corpse_FloaterHeavy"  ; ModNames[138]="UILibrary_StrategyImages.CorpseIcons.Corpse_ThinMan"  ; ModNames[139]="UILibrary_StrategyImages.CorpseIcons.Corpse_Muton"  ; ModNames[140]="UILibrary_StrategyImages.CorpseIcons.Corpse_MutonElite"  ; ModNames[141]="UILibrary_StrategyImages.CorpseIcons.Corpse_Berserker"  ; ModNames[142]="UILibrary_StrategyImages.CorpseIcons.Corpse_Cyberdisc"  ; ModNames[143]="UILibrary_StrategyImages.CorpseIcons.Corpse_Elder"  ; ModNames[144]="UILibrary_StrategyImages.CorpseIcons.Corpse_Cryssalid"  ; ModNames[145]="UILibrary_StrategyImages.InventoryIcons.Inv_ReaperAmmo"  ; Depleted Elerium Rounds (M/S) ModNames[146]="UILibrary_StrategyImages.CorpseIcons.Corpse_Sectopod"  ; ModNames[147]="UILibrary_StrategyImages.CorpseIcons.Corpse_Drone"  ; ModNames[148]="UILibrary_StrategyImages.InterceptorImages.Inv_EMPCannon"  ; Arc Pumper (M/S) ModNames[149]="UILibrary_StrategyImages.InventoryIcons.Inv_SHIVLaserCannon"  ; T2 Superheavy Laser (SHIV) ModNames[150]="UILibrary_StrategyImages.CaptiveIcons.Captive_Sectoid"  ; ModNames[151]="UILibrary_StrategyImages.CaptiveIcons.Captive_SectoidCommander"  ; ModNames[152]="UILibrary_StrategyImages.CaptiveIcons.Captive_Floater"  ; ModNames[153]="UILibrary_StrategyImages.CaptiveIcons.Captive_FloaterHeavy"  ; ModNames[154]="UILibrary_StrategyImages.CaptiveIcons.Captive_ThinMan"  ; ModNames[155]="UILibrary_StrategyImages.CaptiveIcons.Captive_Muton"  ; ModNames[156]="UILibrary_StrategyImages.CaptiveIcons.Captive_MutonElite"  ; ModNames[157]="UILibrary_StrategyImages.CaptiveIcons.Captive_Berserker"  ; ModNames[158]="UILibrary_StrategyImages.CaptiveIcons.Captive_Elder"  ; ModNames[159]="UILibrary_StrategyImages.InventoryIcons.Inv_ArmorCarapace"  ; Phalanx Armor (light) ModNames[160]="UILibrary_StrategyImages.InventoryIcons.Inv_ArmorTitan"  ; Aegis Armor (light) ModNames[161]="UILibrary_StrategyImages.ScienceIcons.IC_Elerium"  ; ModNames[162]="UILibrary_StrategyImages.ScienceIcons.IC_AlienMaterials"  ; ModNames[163]="UILibrary_StrategyImages.InventoryIcons.Inv_AlienWeaponFragments"  ; ModNames[164]="UILibrary_StrategyImages.InventoryIcons.Inv_Meld"  ; ModNames[165]="UILibrary_StrategyImages.ArtifactIcons.Item_AlienEntertainment"  ; ModNames[166]="UILibrary_StrategyImages.ArtifactIcons.Item_AlienFood"  ; ModNames[167]="UILibrary_StrategyImages.ArtifactIcons.Item_StasisTank"  ; ModNames[168]="UILibrary_StrategyImages.ArtifactIcons.Item_UFONav"  ; ModNames[169]="UILibrary_StrategyImages.ArtifactIcons.Item_AlienSurgery"  ; ModNames[170]="UILibrary_StrategyImages.ArtifactIcons.Item_UFOPower"  ; ModNames[171]="UILibrary_StrategyImages.ArtifactIcons.Item_Hyperwave"  ; ModNames[172]="UILibrary_StrategyImages.ArtifactIcons.Item_AlienEntertainmentDamaged"  ; ModNames[173]="UILibrary_StrategyImages.ArtifactIcons.Item_AlienFoodDamaged"  ; ModNames[174]="UILibrary_StrategyImages.ArtifactIcons.Item_StasisTankDamaged"  ; ModNames[175]="UILibrary_StrategyImages.ArtifactIcons.Item_UFONavDamaged"  ; ModNames[176]="UILibrary_StrategyImages.ArtifactIcons.Item_AlienSurgeryDamaged"  ; ModNames[177]="UILibrary_StrategyImages.ArtifactIcons.Item_UFOPowerDamaged"  ; ModNames[178]="UILibrary_StrategyImages.InventoryIcons.Inv_ArmorArchangel"  ; Fuel Cell ModNames[179]="UILibrary_StrategyImages.InterceptorImages.Inv_InterceptorFusionLance"  ; UFO Fusion Launcher ModNames[180]="UILibrary_StrategyImages.ScienceIcons.IC_PsiLink"  ; ModNames[181]="UILibrary_StrategyImages.ArtifactIcons.Item_ExaltIntel"  ; ModNames[182]="UILibrary_StrategyImages.InventoryIcons.Inv_ArmorSkeleton"  ; Kestrel Armor (light) ModNames[183]="UILibrary_StrategyImages.ArtifactIcons.Item_BaseShard"  ; ModNames[184]="UILibrary_StrategyImages.InventoryIcons.Inv_SkeletonKey"  ; ModNames[185]=""  ; SectopodChestCannon ModNames[186]="UILibrary_StrategyImages.InventoryIcons.Inv_SHIVLaserCannon"  ; T2 Laser Lance (MEC) ModNames[187]="UILibrary_StrategyImages.CorpseIcons.Corpse_Mechtoid"  ; ModNames[188]="UILibrary_StrategyImages.CorpseIcons.Corpse_Seeker"  ; ModNames[189]="UILibrary_StrategyImages.InventoryIcons.Inv_ChitinPlating"  ; Alloy Carbide Plating (M/S) ModNames[190]="UILibrary_StrategyImages.InventoryIcons.Inv_SHIVLaserCannon"  ; T4 Pulse Lance (MEC) ModNames[191]="UILibrary_StrategyImages.InventoryIcons.Inv_TargetPainter"  ; Laser Designator ModNames[192]="UILibrary_StrategyImages.InventoryIcons.Inv_MecCivvies"  ; ModNames[193]="UILibrary_StrategyImages.InventoryIcons.Inv_Mec1"  ; ModNames[194]="UILibrary_StrategyImages.InventoryIcons.Inv_Mec2"  ; ModNames[195]="UILibrary_StrategyImages.InventoryIcons.Inv_Mec3"  ; ModNames[196]="UILibrary_StrategyImages.InventoryIcons.Inv_ExaltHeavyMG"  ; Alloy Bipod ModNames[197]="UILibrary_StrategyImages.InventoryIcons.Inv_ReaperAmmo"  ; Breaching Ammo ModNames[198]="UILibrary_StrategyImages.InventoryIcons.Inv_ReaperAmmo"  ; Armor Piercing Ammo ModNames[199]="UILibrary_StrategyImages.InventoryIcons.Inv_MotionDetector"  ; Smartgun Kit ModNames[200]="UILibrary_StrategyImages.InventoryIcons.Inv_NanoFabricVest"  ; Impact Vest ModNames[201]="UILibrary_StrategyImages.InventoryIcons.Inv_MotionDetector"  ; Tactical Sensors (MEC) ModNames[202]="UILibrary_StrategyImages.InventoryIcons.Inv_GrappleHook"  ; Walker Gear ModNames[203]="UILibrary_StrategyImages.InventoryIcons.Inv_Scope"  ; Neural Gunlink ModNames[204]="UILibrary_StrategyImages.InventoryIcons.Inv_ReaperAmmo"  ; Shredder Ammo ModNames[205]="UILibrary_StrategyImages.InventoryIcons.Inv_MindShield"  ; Psi Shield ModNames[206]="UILibrary_StrategyImages.InventoryIcons.Inv_Shiv1"  ; Rebuild SHIV1 ModNames[207]="UILibrary_StrategyImages.InventoryIcons.Inv_Shiv2"  ; Rebuild SHIV2 ModNames[208]="UILibrary_StrategyImages.InventoryIcons.Inv_Shiv3"  ; Rebuild SHIV3 ModNames[209]="UILibrary_StrategyImages.InterceptorImages.Inv_EMPCannon"  ; Illuminator Gunsight ModNames[210]="UILibrary_StrategyImages.InventoryIcons.Inv_SkeletonKey"  ; Zevatron Booster (M/S) ModNames[211]="UILibrary_StrategyImages.InventoryIcons.Inv_GrappleHook"  ; Autoloader (M/S) ModNames[212]="UILibrary_StrategyImages.InventoryIcons.Inv_ExaltAssaultRifle"  ; T1 Assault Rifle ModNames[213]="UILibrary_StrategyImages.InventoryIcons.Inv_ExaltSniperRifle"  ; T1 Sniper Rifle ModNames[214]="UILibrary_StrategyImages.InventoryIcons.Inv_ExaltHeavyMG"  ; T1 SAW ModNames[215]="UILibrary_StrategyImages.InventoryIcons.Inv_ExaltLaserAssaultRifle"  ; T2 Laser Rifle ModNames[216]="UILibrary_StrategyImages.InventoryIcons.Inv_ExaltLaserSniperRifle"  ; T2 Laser Sniper Rifle ModNames[217]="UILibrary_StrategyImages.InventoryIcons.Inv_ExaltLaserHeavyMG"  ; T2 Laser SAW ModNames[218]="UILibrary_StrategyImages.InventoryIcons.Inv_ExaltRocketLauncher"  ; T1 Rocket Launcher ModNames[219]="UILibrary_StrategyImages.InventoryIcons.Inv_BattleScanner"  ; Weapon Gyrostabilizer (M/S) ModNames[220]="UILibrary_StrategyImages.InventoryIcons.Inv_NanoFabricVest"  ; Heavy Alloy Plating ModNames[221]="UILibrary_StrategyImages.InventoryIcons.Inv_GrappleHook"  ; Elerium Turbos (M/S) ModNames[222]="UILibrary_StrategyImages.InventoryIcons.Inv_ExaltLoot1"  ; ModNames[223]="UILibrary_StrategyImages.InventoryIcons.Inv_ExaltLoot2"  ; ModNames[224]="UILibrary_StrategyImages.InventoryIcons.Inv_ExaltLoot3"  ; ModNames[225]="UILibrary_StrategyImages.InventoryIcons.Inv_ChitinPlating"  ; Alloy Belt (M/S) ModNames[226]="UILibrary_StrategyImages.InventoryIcons.Inv_ExaltSniperRifle"  ; T1 Marksman's Rifle ModNames[227]="UILibrary_StrategyImages.InventoryIcons.Inv_ExaltLaserSniperRifle"  ; T2 Laser Strike Rifle ModNames[228]="UILibrary_StrategyImages.InventoryIcons.Inv_SniperRifle"  ; T3 Alloy Strike Rifle ModNames[229]="UILibrary_StrategyImages.InventoryIcons.Inv_LaserSniper"  ; T4 Blaster Rifle ModNames[230]="UILibrary_StrategyImages.InventoryIcons.Inv_PlasmaSniper"  ; T5 Reflex Rifle ModNames[231]="UILibrary_StrategyImages.InventoryIcons.Inv_ExaltAssaultRifle"  ; T1 SMG ModNames[232]="UILibrary_StrategyImages.InventoryIcons.Inv_ExaltLaserAssaultRifle"  ; T2 Laser Shatterray ModNames[233]="UILibrary_StrategyImages.InventoryIcons.Inv_AssaultRifleModern"  ; T3 Gauss Stuttergun ModNames[234]="UILibrary_StrategyImages.InventoryIcons.Inv_LaserRifle"  ; T4 Pulse Stengun ModNames[235]="UILibrary_StrategyImages.InventoryIcons.Inv_PlasmaRifleLight"  ; T5 Plasma Stormgun ModNames[236]="UILibrary_StrategyImages.InventoryIcons.Inv_ExaltAssaultRifle"  ; T1 Machine Pistol ModNames[237]="UILibrary_StrategyImages.InventoryIcons.Inv_ExaltLaserAssaultRifle"  ; T2 Heater ModNames[238]="UILibrary_StrategyImages.InventoryIcons.Inv_AssaultRifleModern"  ; T3 Gauss AutoPistol ModNames[239]="UILibrary_StrategyImages.InventoryIcons.Inv_LaserRifle"  ; T4 Blaster ModNames[240]="UILibrary_StrategyImages.InventoryIcons.Inv_PlasmaRifleLight"  ; T5 Plasma Mauler ModNames[241]="UILibrary_StrategyImages.InventoryIcons.Inv_ExaltAssaultRifle"  ; T1 Battle Rifle ModNames[242]="UILibrary_StrategyImages.InventoryIcons.Inv_ExaltLaserAssaultRifle"  ; T2 Heavy Laser Rifle ModNames[243]="UILibrary_StrategyImages.InventoryIcons.Inv_AssaultRifleModern"  ; T3 Heavy Gauss Rifle ModNames[244]="UILibrary_StrategyImages.InventoryIcons.Inv_LaserRifle"  ; T4 Heavy Pulse Rifle ModNames[245]="UILibrary_StrategyImages.InventoryIcons.Inv_PlasmaRifle"  ; T5 Heavy Plasma Rifle ModNames[246]="UILibrary_StrategyImages.InventoryIcons.Inv_ExaltHeavyMG"  ; T1 LMG ModNames[247]="UILibrary_StrategyImages.InventoryIcons.Inv_ExaltLaserHeavyMG"  ; T2 Gatling Laser ModNames[248]="UILibrary_StrategyImages.InventoryIcons.Inv_LMG"  ; T3 Gauss Machine Gun ModNames[249]="UILibrary_StrategyImages.InventoryIcons.Inv_LaserHeavy"  ; T4 Gatling Pulser ModNames[250]="UILibrary_StrategyImages.InventoryIcons.Inv_PlasmaHeavy"  ; T5 Plasma Dragon ModNames[251]="UILibrary_StrategyImages.InventoryIcons.Inv_ExaltLaserAssaultRifle"  ; T2 Laser Carbine ModNames[252]="UILibrary_StrategyImages.InventoryIcons.Inv_LaserRifle"  ; T4 Pulse Carbine ModNames[253]="UILibrary_StrategyImages.InventoryIcons.Inv_ExaltLaserSniperRifle"  ; T2 Arc Rifle ModNames[254]="UILibrary_StrategyImages.InventoryIcons.Inv_Shotgun"  ; T1 Sawed-off Shotgun ModNames[255]=""

Add new scripting

The following is taken from the Nexus Mod Talk Forum thread Scripting with UDK, as a result of explorations by wghost81.

The UDK can be used to create new scripting, to include simulated functions that supplement or even replace embedded native functions (which can not be examined to see how they work, so take great care with function names so you don't break the game).

This simple example of the process used by wghost81 to just add some resources (100,000 credits), which can easily be verified by the display in the "Situation Room".

1. Downloaded XCOM compatible version of the UDK: UDKInstall-2011-09, and installed it.

2. Created my own script project:

  • Created new folder: <Path-To-UDK>\Development\Src\XComMod\Classes.
  • Created new script file: TestMod.uc, containing:

class TestMod extends XComMod;

simulated function StartMatch() { local XGStrategy GameCore;
super.StartMatch();
GameCore = XComHeadquartersGame(class'Engine'.static.GetCurrentWorldInfo().Game).GetGameCore();
GameCore.HQ().AddResource(0, 100000);
return; }

3. Created <Path-To-UDK>\Development\Src\XComGame\Classes and <Path-To-UDK>\Development\Src\XComStrategyGame\Classes projects to hold dummy XCOM scripts.

4. Created dummy script files (see below).

5. Added newly created projects to <Path-To-UDK>\Config\DefaultEngine.ini, section:

[UnrealEd.EditorEngine]
+EditPackages=XComGame
+EditPackages=XComStrategyGame
+EditPackages=XComMod

6. Compiled and cooked my project. Cooked script package was placed into <Path-To-UDK>\UDKGame\Script\XComMod.u. Correction: compiling a script already creates a ".u" package; no need for cooking.

7. There is no need to rename the newly compiled XComMod.u to XComMod.upk (the *.u files are read just like unpacked UPK files), but it does need copying to <Path-To-XCom-Enemy-Unknown>\XEW\XComGame\CookedPCConsole (for testing with Enemy Within (EW)).

8. Edited (specific game version, in this case EW's) DefaultEngine.ini, section:

[Engine.ScriptPackages]
+NonNativePackages=XComMod

9. Edited DefaultGame.ini, and added a new section:

[XComStrategyGame.XComHeadquartersGame]
+ModNames=XComMod.TestMod

10. Test in game.

HxD Image
Image by wghost81, used with permission under Creative Commons Attribution-Share Alike (CC BY-SA) license terms.

Note the result is an increase of $200,000 rather than the expected $100,000. This is because the StartMatch function of each of the active mods is called each time when the Strategic (or Tactical) game starts. Which why it's better to adjust starting resources by way of editing the DefaultGameCore.INI file instead of adding them in a new mod. (Andan example of why you always need to test your results.)

Dummy script files

Since XComGame and XComStrategyGame packaged content is cooked into XComMod.u as a set of import objects, those objects don't have to be fully implemented. We just need a correct package: class, variable, and function names. For this simple task, they can be "dummy" placeholders for the most part.

  • XComGame\Classes\XComGameInfo.uc:

class XComGameInfo extends FrameworkGame
   native
   abstract;

A class definition, nothing more, as I don't need anything for my simple script.
  • XComGame\Classes\XComMod.uc:

class XComMod extends Object;

simulated function StartMatch() { return; }

A copy of the decompiled class. It's important, as TestMod class extends XComMod class.
  • XComStrategyGame\Classes\XGStrategyActorNativeBase.uc:

class XGStrategyActorNativeBase extends Actor
   native
   notplaceable;

enum EResourceType { eResource_Money, eResource_Elerium, eResource_Alloys, eResource_Engineers, eResource_Scientists, eResource_Power, eResource_MonthlyNet, eResource_Meld, eResource_Max };
function XGHeadQuarters HQ() { return XComHeadquartersGame(class'Engine'.static.GetCurrentWorldInfo().Game).GetGameCore().GetHQ(); }

Same as before: only functions, which are actually used. Functions can be empty. Or totally different from the original. But they must have the same header and return value.
  • XComStrategyGame\Classes\XGStrategyActor.uc:

class XGStrategyActor extends XGStrategyActorNativeBase
   abstract
   notplaceable;

function AddResource(XGStrategyActorNativeBase.EResourceType eResource, int iAmount, optional bool bRefund) { return; }

Empty AddResource function. Again, it doesn't matter as the actual game will use the actual package with AddResource correctly defined.
  • XComStrategyGame\Classes\XGStrategy.uc:

class XGStrategy extends XGStrategyActor
   notplaceable;

var XGHeadQuarters m_kHQ;
function XGHeadQuarters GetHQ() { return m_kHQ; }

  • XComStrategyGame\Classes\XGHeadQuarters.uc:

class XGHeadQuarters extends XGStrategyActor
   notplaceable;

  • XComStrategyGame\Classes\XComHeadquartersGame.uc:

class XComHeadquartersGame extends XComGameInfo;

var protected XGStrategy m_kGameCore;
function XGStrategy GetGameCore() { return m_kGameCore; }

MutatorEnabler

Here's a PatcherGUI (v.5.2.1+ or later) mod to make an INI-configurable Mutator enabler:

MOD_NAME=PatcherGUI MutatorEnabler

AUTHOR=wghost81 aka Wasteland Ghost DESCRIPTION=Creates an INI-configurable Mutator enabler Version: 1.0
Compatible with XCOM Enemy Unknown / Enemy Within version: - (versions list not provided) - experimental: only tested on EW
UPK_FILE=XComGame.upk
[ADD_NAME_ENTRY] <%u 11> // Length <%t "AddMutator"> // Name <%u 0x00000000> // flags L <%u 0x00070010> // flags H
[ADD_NAME_ENTRY] <%u 13> // Length <%t "MutatorClass"> // Name <%u 0x00000000> // flags L <%u 0x00070010> // flags H
[ADD_NAME_ENTRY] <%u 12> // Length <%t "MutatorName"> // Name <%u 0x00000000> // flags L <%u 0x00070010> // flags H
[ADD_NAME_ENTRY] <%u 13> // Length <%t "MutatorNames"> // Name <%u 0x00000000> // flags L <%u 0x00070010> // flags H
[ADD_EXPORT_ENTRY] <Core.ArrayProperty> // Type <NullRef> // ParentClassRef <Class.XComGameInfo> // OwnerRef <MutatorNames> // NameIdx <NullRef> // ArchetypeRef <% u0x00000000> // flags H <% u0x00070004> // flags L <%u 44> // serial size <%u 0> // serial offset <%u 0> // export flags <%u 0> // net objects count <%u 0> // GUID1 <%u 0> // GUID2 <%u 0> // GUID3 <%u 0> // GUID4 <%u 0> // unknown
[ADD_EXPORT_ENTRY] <Core.StrProperty> // Type <NullRef> // ParentClassRef <XComGameInfo.MutatorNames> // OwnerRef <MutatorNames> // NameIdx <NullRef> // ArchetypeRef <% u0x00000000> // flags H <% u0x00070004> // flags L <%u 40> // serial size <%u 0> // serial offset <%u 0> // export flags <%u 0> // net objects count <%u 0> // GUID1 <%u 0> // GUID2 <%u 0> // GUID3 <%u 0> // GUID4 <%u 0> // unknown
OBJECT=XComGameInfo.MutatorNames REL_OFFSET=16 // skip PrevObjRef + Empty DefaultProperties List + NextObjRef [MODDED_CODE] <%s 1> // ArrayDim <%s 0> // ElementSize <%u 0x00404000> // flags L: Config + NeedCtorLink <%u 0x00000000> // flags H <None> // CategoryIndex <NullRef> // ArrayEnumRef <XComGameInfo.MutatorNames.MutatorNames> // InnerObjRef
OBJECT=XComGameInfo.MutatorNames.MutatorNames REL_OFFSET=16 // skip PrevObjRef + Empty DefaultProperties List + NextObjRef [MODDED_CODE] <%s 1> // ArrayDim <%s 0> // ElementSize <%u 0x00404000> // flags L: Config + NeedCtorLink <%u 0x00000000> // flags H <None> // CategoryIndex <NullRef> // ArrayEnumRef
[ADD_EXPORT_ENTRY] <Core.ClassProperty> // Type <NullRef> // ParentClassRef <XComGameInfo.InitGame> // OwnerRef <MutatorClass> // NameIdx <NullRef> // ArchetypeRef <% u0x00000000> // flags H <% u0x00070004> // flags L <%u 48> // serial size <%u 0> // serial offset <%u 0> // export flags <%u 0> // net objects count <%u 0> // GUID1 <%u 0> // GUID2 <%u 0> // GUID3 <%u 0> // GUID4 <%u 0> // unknown
OBJECT=XComGameInfo.InitGame.MutatorClass REL_OFFSET=16 // skip PrevObjRef + Empty DefaultProperties List + NextObjRef [MODDED_CODE] <%s 1> // ArrayDim <%s 0> // ElementSize <%u 0x00000000> // flags L <%u 0x00000000> // flags H <None> // CategoryIndex <NullRef> // ArrayEnumRef <Core.Class> // OtherObjRef <Engine.Mutator> // ClassObjRef
[ADD_EXPORT_ENTRY] <Core.StrProperty> // Type <NullRef> // ParentClassRef <XComGameInfo.InitGame> // OwnerRef <MutatorName> // NameIdx <NullRef> // ArchetypeRef <% u0x00000000> // flags H <% u0x00070004> // flags L <%u 40> // serial size <%u 0> // serial offset <%u 0> // export flags <%u 0> // net objects count <%u 0> // GUID1 <%u 0> // GUID2 <%u 0> // GUID3 <%u 0> // GUID4 <%u 0> // unknown
OBJECT=XComGameInfo.InitGame.MutatorName REL_OFFSET=16 // skip PrevObjRef + Empty DefaultProperties List + NextObjRef [MODDED_CODE] <%s 1> // ArrayDim <%s 0> // ElementSize <%u 0x00400000> // flags L: NeedCtorLink <%u 0x00000000> // flags H <None> // CategoryIndex <NullRef> // ArrayEnumRef
OBJECT=XComGameInfo.InitGame:AUTO [BEFORE_CODE] //CacheMods() 1B <CacheMods> 16 [AFTER_CODE] //foreach MutatorNames(MutatorName) 58 01 <@MutatorNames> 00 <.MutatorName> 00 4A [@IP] //MutatorClass = class<Mutator>(DynamicLoadObject(MutatorName, class'Class')) 0F 00 <.MutatorClass> 13 <Engine.Mutator> 1C <Core.Object.DynamicLoadObject> 00 <.MutatorName> 20 <Core.Class> 4A 16 //if(MutatorClass != none) 07 [@IN] 77 00 <.MutatorClass> 2A 16 //AddMutator(MutatorName, true) 1B <AddMutator> 00 <.MutatorName> 27 16 [#IN] 31 [#IP] 30 //CacheMods() 1B <CacheMods> 16

With this mod installed, Mutators can be added via DefaultGame.ini:

[XComStrategyGame.XComHeadquartersGame]
+MutatorNames=XComMutator.MyMutator

[XComGame.XComTacticalGame] +MutatorNames=XComMutator.MyMutator

Note the caveats and experiences reported above in #Differences from UTGame.


References

Referred to by this article:



That refer to this article: