Jump to content

Scripting with UDK


wghost81

Recommended Posts

Simple cheating done with completely new script package compiled and cooked by UDK:

 

http://i.imgur.com/HqihtLF.jpg

 

Now about how I did it. :smile:

 

1. Downloaded XCOM compatible UDK version: http://www.nexusmods.com/xcom/mods/485 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

 

 

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

7. Renamed XComMod.u to XComMod.upk and copied it to Path-To-XCom-Enemy-Unknown\XEW\XComGame\CookedPCConsole

8. Edited DefaultEngine.ini, section Engine.ScriptPackages:

 

 

+NonNativePackages=XComMod

 

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

 

 

[XComStrategyGame.XComHeadquartersGame]
+ModNames=XComMod.TestMod

 

 

Since XComGame and XComStrategyGame packages content is cooked into XComMod.u as a set of import objects, those object doesn't have to be fully implemented. We just need a correct package, class, variable and function names.

 

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 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 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 actual game will use 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;
}

 

 

I'll write more about XComMod class and how it is used to activate mod scripts later. Stay tuned! :wink:

Link to comment
Share on other sites

  • Replies 61
  • Created
  • Last Reply

Top Posters In This Topic

Wonderful! It is more friendly modding :smile:

 

Whenever I tried UDK for scripting in the past, it failed on references to other packages, as we don't have source scripts at disposal. Glad there is a way around it.

Edited by Drakous79
Link to comment
Share on other sites

Oh yeah! :wub: Finally someone is making further progress into the UDK for XCOM. I'll be adding this to the "Modding with the UDK" article. Initial thought is to put it under the "How To" section and subsection Amineri's piece as "Images" and this as "Scripts".

 

Edit: Added.

 

-Dubious-

Edited by dubiousintent
Link to comment
Share on other sites

dubiousintent, thanks! Very good summary as always.

 

Now about XComMod class.

 

This class is a base class, defined in XComGame package. It is empty and contains only one function:

 

 

class XComMod extends Object;

simulated function StartMatch()
{
    return;
}

 

 

This class is utilized by XComGameInfo class of the same package. XComGameInfo has two member variables, which deal with the mods:

var config array<config string> ModNames;
var array<XComMod> Mods;
ModNames is a config variable, containing class name of the mod. In my previous post this was the name, I've added to DefaultGame.ini:

+ModNames=XComMod.TestMod
When InitGame function is called inside XComGameInfo, it calls for CacheMods function, which iterates through ModNames array, creates new Mod object of the ModClass class (defined in DefaultGame.ini) and adds this object to array of active mods (Mods variable).

 

XComGameInfo also has a function called ModStartMatch:

 

 

simulated function ModStartMatch()
{
    local XComMod Mod;

    foreach Mods(Mod,)
    {
        Mod.StartMatch();        
    }    
    return;
}

 

 

This function is later called by XComHeadquartersGame class (a child of XComGameInfo class) at the end of StartMatch function.

 

In EU it is also called by the same function of XComTacticalGame class (which is also a child of XComGameInfo class), but for EW this piece of the code was removed. To add an active mod into tactical game in EU, one needs to add a section to DefaultGame.ini file:

[XComStrategyGame.XComHeadquartersGame]
+ModNames=ModPackageName.ModClassName
As a result of all this, StartMatch function of each of the active mods is called each time when Strategy (or Tactical) game starts (that's why there are $200000 on my screenshot, not $100000). For example, in EU Slingshot DLC it is used to add new mission to array of Council missions.

 

Using this method we can create our own classes to work in parallel with existing classes and add changes to the game.

 

Theoretically, instead of using dummy scripts, we can try to compile actual XCOM scripts, decompiled by UEExplorer. But UEExplorer decompiles some functions incorrectly and have problems with some of the Default Properties, so doing this this will require a lot of work.

 

Drakous79 reminded me about Mutators, so my next step will be to investigate this possibility.

Edited by wghost81
Link to comment
Share on other sites

I did some reading on Mutators (thanks to dubiousintent for a good collection of references) and searched XCOM decompiled code. That's what I found so far.

 

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 linked chain by using NextMutator variable, which is a member of 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 in-game GUI to load mutators. Only way to load Mutators into unmodified game I found so far is a command line (game launch) parameters. Launch parameters are passed to Engine.GameInfo.InitGame function, parsed and, if Mutator related options are found, corresponding mutators are created. UTGame has a way to add mutators via config file, but I can't find anything similar for XComGame. 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 to catch some of the in-game events and modify 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 :smile: this function is not so interesting for us. But in FPS game it allows to easily modify player starting attributes and inventory.

* FindPlayerStart - modify player start position.

* CheckReplacement - the most important function. It allows to replace one class with another class whenever an exemplar of a class is spawned. In other words, it allows to "mutate" a class into different class.

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

 

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. XCom equivalent for such a small change can be, for example, XGAIBehavior_Sectoid class. By creating a mutator and using CheckReplacement of newly created mutator to replace XGAIBehavior_Sectoid class with new XGAIBehavior_SectoidMod class, one can alter Sectoid AI without changing existing class. 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.

 

As a next step I'll try to add some simple mutator in XCom and report the result.

Edited by wghost81
Link to comment
Share on other sites

Had no success with Mutators so far. Lack of debugging options is frustrating. :sad:

 

Correction to first post: compiling a script already creates .u package, no need for cooking.

 

And two more interesting links:

http://udn.epicgames.com/Three/UT3Mods.html

http://udn.epicgames.com/Three/ConsoleCommands.html

Edited by wghost81
Link to comment
Share on other sites

Hooray! I was able to partially implement a Mutator!

 

"Partially", because I couldn't activate it with command line argument. I've added MUTATOR=XComMutator.MyMutator to launcher params and I saw that line in the log, but my Mutator wasn't created. So I just hacked in with patcher and added

AddMutator("XComMutator.MyMutator", true);
line at the end of 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);
}
Mutate function can be called with XCOM console command, for example, "Mutate 2". It will increases game speed to 2.0, same as "slomo 2" command does. Edited by wghost81
Link to comment
Share on other sites

Does the package work as *.u too? I mean without renaming it to *.upk.

 

Will be good to know, if we can freely distribute UDK created content, or if there are any restrictions.

 

Edit: Another idea is to prefix custom made packages with a string, like CMP (Custom Made Package), CP (Custom Package) or XM (XCom Mod) so they are nicely grouped in CookedPCConsole folder.

Edited by Drakous79
Link to comment
Share on other sites

Created a new article "Class: XComMod - XCOM:EU 2012", and cross-linked it with the "Modding with UDK" article. Also added an "Adding with Mutators" subtopic to the "How to" section of that article.

 

@Drakous79: That's a good idea. Problem will be how to enforce it. Of course if we roll our own interface or config file ... Also good question about just plain "*.u" files.

 

@wghost81: since you referred to your screenshot when talking about the XComMod class, I added it to the tutorial under a CCA-SA license. Please let me know if that's okay with you.

 

-Dubious-

Edited by dubiousintent
Link to comment
Share on other sites

@Drakous79: That's a good idea. Problem will be how to enforce it. Of course if we roll our own interface or config file.

 

In my opinion it should be optional. Let the most active modders say, which option they like, or propose something better, and it may become a way to go for others. Good example should be better than enforcement.

Edited by Drakous79
Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.

×
×
  • Create New...