• Please make sure you are familiar with the forum rules. You can find them here: https://forums.tripwireinteractive.com/index.php?threads/forum-rules.2334636/

Code Mutator Common Coding Problems and solutions

FBX

Grizzled Veteran
Aug 17, 2006
238
42
Please help write this. I'm going to list out some questions and I'd appreciate responses that give instructions on how to do whatever the question asks. Then I can update this main post with the answer. The idea is that the thread becomes a one-stop location to learn to do things.

This thread assumes you something about coding at the very least and have experience with a programming language similar to unreal script (a c-like language)

Note that some of these questions I think I know the answer to but I'm not filling them in until I actually try it out.

1. Where is the unreal script source code located?
A:
Code:
The core unreal script source code is at:
<steam install location>\steamapps\common\red orchestra 2\Development\Src

However, to make your mutator, the scripting code needs to be located at <My Documents>\My Games\RedOrchestra2\ROGame\Src\<Myfoldername>\Classes

Example:
C:\Users\<Windows Username>\Documents\My Games\RedOrchestra2\ROGame\Src\MyMutatorName
2. I have Windows 7 and its file contents search doesn't work. At all. Whats a good program that allows me to quickly and easily search what I'm looking for in the .us files?

3. How do I compile a mutator in RO2?
Code:
Create a shortcut to ROGame.exe This is NOT the
steam shortcut. Actually navigate to the .exe location and 
create a windows shortcut, then add "make" (no quotes) after 
the end of the quoted section.

Example:
"C:\Program Files (x86)\Steam\steamapps\common\red orchestra 2\Binaries\Win64\ROGame.exe" make
4. How do I run/test a mutator?

5. What's a basic template for starting a mutator?
Code:
Create a text file as MyMutatorName.uc (i.e. the file extension is .uc, not .txt)
Code:
class MyMutatorName extends Mutator;

// variable declarations go here
 
// hooks go here

defaultproperties
{
  GroupName="MyMutator"
  FriendlyName="My Mutator"
  Description="My Horrible Creation"
}
6. How do I start a timed event?

http://udn.epicgames.com/Three/UnrealScriptFunctions.html#Timers

7. How do I concurrently run different timers?

http://udn.epicgames.com/Three/UnrealScriptFunctions.html#Timers

8. What accessor variables/functions are visible to a mutator?
Code:
From What I can tell, everything must be reached somehow by the
 functions you see in Mutator.uc. Note that the function returns regular
 unreal entities and not Red Orchestra entities. I believe you can type
 cast them to get what you want. For example, using our Mutator template
 as a starting point:

// function hooks go here

function ModifyPlayer(Pawn Other)
{
    local ROPawn MyPawn;
    MyPawn = ROPawn(Other);
    MyPawn.NumBandages = 0;
    super.ModifyPlayer(Other);
}

My guess is this would give each player 0 bandages to start out with. However I don't know how to test/install a mutator yet to confirm
9. How do I replace a class with my own if I can't determine where it is being created?
Code:
From what I can tell, you can't.
Duplicating a class name gives a warning and probably won't
work correctly. A lot of game elements are accessible from the 
Pawn class though and you can get a player pawn from the 
ModifyPlayer callback function
10. What is the core player entity and how do I access its values?
Code:
ROPawn is the core entity
11. I see a core engine or game function that I want to override or extend. What is the best way to do this?

12. What scope does a mutator run from? I.E. What do I need to worry about in terms of keeping things in sync between the client and the server?

13. What overridable function callbacks are visible to a mutator?
Code:
Engine\Classes\Mutator.uc is a starting point. Are there others?
14. What appears mutatable but isn't?

15. What's the difference between the ways mutators need to be loaded between listen servers and dedicated servers?

16. How do I know if my reference to a class object is the same as another reference to a class object?
Code:
From what I can tell, you can't. == isn't valid with some (but not all???) class nor struct references so the only means seem to be indirect ones (comparing the member variables)
 
Last edited:
I can't answer about mutators as I haven't tried them in RO2, and I haven't made any since working on UT3 a few years ago.

A few quick answers to most of your other questions.

1) Yes that is where RO2 code is, your code should go in <USERDIR>\My Documents\My Games\RedOrchestra2\ROGame\Src
In there you should have a folder for your package, a folder within that called classes, and then within folder go all your .uc files.

2) nFringe, UDKEclipse are some IDE's to use, or you can use Notepad++ or a text editor of your choice.

You can use UnCodeX to very easily index and explore RO2's code base.

3) Create a shortcut to <steam install location>SteamApps\common\red orchestra 2\Binaries\Win64\ROGame.exe and append " make" to the command line. so the command line will look like this:

"C:\Program Files (x86)\Steam\steamapps\common\red orchestra 2\Binaries\Win64\ROGame.exe" make

You will also need to edit ROEditor.ini in <USERDIR>\My Documents\My Games\RedOrchestra2\ROGame

Find the section [ModPackages] and add this line for each package you want to make
ModPackages=PACKAGENAME

6 & 7: http://udn.epicgames.com/Three/UnrealScriptFunctions.html#TimerFunctions
 
Last edited:
Upvote 0
I noticed you updated the top post with some info you had found on mutators and I have a bit of extra info.

Again, I haven't tried mutators in RO2, but generally speaking this is how they work in UE3.

9:
You can't just duplicate a class with the same name, you'd need to create a new class with a new name and make it extend the class you want to replace. Then in the mutator class, you override the function CheckReplacement and use the function in the post below to replace the original class at run time. I've provided an example from an old UT3 mutator of mine.
http://forums.tripwireinteractive.com/showpost.php?p=965851&postcount=34

Code:
function bool CheckReplacement(Actor Other)
{
	if(Other.IsA('UTPawn') && !Other.IsA('HTCorpSecPawn'))
	{
		ReplaceWith(Other,"HTGame.HTCorpSec");
	}
	
	return true;
}

8:
Your method here should be changed:
Code:
function ModifyPlayer(Pawn Other)
{
    local ROPawn MyPawn;
    MyPawn = ROPawn(Other);
    MyPawn.NumBandages = 0;
    if ( NextMutator != None )
        NextMutator.ModifyPlayer(Other);
}
To
Code:
function ModifyPlayer(Pawn Other)
{
    local ROPawn MyPawn;
    MyPawn = ROPawn(Other);
    MyPawn.NumBandages = 0;
    super.ModifyPlayer(Other);
}

It's generally considered bad practice to copy and paste the contents of a function from a parent class unless there is a compelling reason to do so (such as the parent function including specific functionality that you are attempting to remove). Generally you should just call the parents version of the function as I've done here. That way you benefit from any bugfixes and improvements from upstream with little to no effort.
 
Last edited:
Upvote 0
When I figure out how to run a compiled mutator I can post some updates :S Preferably on a listen server. I can figure out how to start a listen server with bots but I'm not seeing any means of loading the mutator. I've tried adding "?mutator=mymutator" but if its not giving any evidence that its loading my mutator or attempting to. No console message indicating it couldn't find it, even when I intentionally mistype the name.

Code:
Open te-fallenfighters?minplayers=14?maxplayers=14?mutator=mymutator
 
Upvote 0
4. How do I run/test a mutator?
Testing in the client is easy. Once your script is compiled and cooked, it'll wind up where it needs to be, in My Documents \ MyGames \ RedOrchestra2 \ ROGame \ Published \ CookedPC \ Script. At that point, you just feed the mutator into a map command, like opening the console and doing
Code:
open mapname?mutator=PackageName.ClassName

I'm currently at a loss on how to run it on a dedicated server. I've only gotten the PCserver cooking to spit out a _SF upk, and I'm not sure how to get the game to read that.

Also, that example mutator uses ReplaceWith, which is a function of UTMutator. RO only has the parent Mutator class.
 
Upvote 0
Weird, mine showed up in the unpublished directory, but even testing it in the published directory it still wouldn't load.

I'm guessing I probably have something wrong with my configuration. It compiled and I have the .u file but again, no indication if I don't see my changes because of a code bug or if its because its not loading at all.

I think it would be helpful to see an uncompiled "hello world" mutator.

Don't Dedicated server mutators need to be in "CookedPCServer" instead of "CookedPC"?
 
Upvote 0
Don't Dedicated server mutators need to be in "CookedPCServer" instead of "CookedPC"?
Yes, but if you just throw the same .u file in there, the server crashes when it goes to load it. I'm assuming the -seekfreeloadingserver requirement on the dedicated server means that it needs packages specifically cooked for the server platform, and when I run the cooker for PCserver, it's producing a only a packagename_sf.upk. I've tried a multitude of ways of getting the game to load that seekfree package, but haven't had any success yet, and there's not a lot of publically accessible UDN documentation on content cooking or server modes.
 
Upvote 0
How long does it take to cook a mutator? When I clicked on the shortcut, I had to wait about five minutes until a window appeared with a list of some sort. As soon as my mutator appeared in the list, ROGame.exe just crashed.

There should be nothing in the mutator that could crash the compiler as I only added just some very basic code to see if I can compile the scripts. Here's what I found in the logs:

Code:
[0392.27] Heading: --------------------WebAdmin - Release--------------------
[0402.77] Log: PackageName = WebAdmin, LastPackagename = ROGameContent
[0402.77] Log: Loading global macros for WebAdmin
[0402.77] Log: [UCI] Processing include file WebAdmin\Globals.uci, PackageName = WebAdmin
[0402.77] Log: Find files in ..\..\Development\Src\WebAdmin\*.uci
[0402.77] Log: [UCI] Going through UCI file WebAdmin\SettingsMacros.uci, PackageName WebAdmin
[0402.82] Log: [UCI] Going through UCI file WebAdmin\WebAdmin.uci, PackageName WebAdmin
[0402.92] Heading: --------------------FirstMutator - Release--------------------
[0402.92] Critical: appError called: Missing shipping script package FirstMutator
[0402.92] Critical: Windows GetLastError: The operation completed successfully. (0)
[0552.40] Log: === Critical error: ===
Missing shipping script package FirstMutator

It appears that my "FirstMutator" package was not found. However, I put it in Src/FirstMutator and I also referenced it in the ini file.

What could I be missing here?
 
Upvote 0
Yes, that's exactly where I put it. Also, here's an extract from the ROEditor.ini:

Code:
[ModPackages]
ModPackagesInPath=..\..\ROGame\Src
ModOutputDir=..\..\ROGame\Unpublished\CookedPC\Script
ModPackages=FirstMutator

I think that's how it should be, right?

P.S. I re-installed the SDK and now it seems to open the window with the list almost instantly instead of waiting a few minutes like I had to do before. However, the compiler still crashes. Running as administrator doesn't help either.
 
Upvote 0
If I try to compile a mutator, then I do get compiler warnings at these lines (see yellow lines):
Code:
defaultproperties
{
[COLOR=Yellow]    GroupName="BlaBla"
    FriendlyName="Bla Bla"
    Description="Description of Bla Bla"
[/COLOR]}
The warning is like Warning, Unknown property in defaults: GroupName="BlaBla" and it is generated for all 3 lines. Should the scope of the file not contain the next definitions?
Code:
var() string GroupName;
var() string FriendlyName;
var() string Description;
Or am I missing something?
 
Upvote 0
One thing that's definately tripping me up is not being able to modify a lot of the core logic in ROPawn. I've tried creating my own class and inheriting from the ROPawn class but I can't (easily) get the player to be using my custom pawn instead of the ROPawn.

When I use the CheckReplacement and ReplaceWith functions, nothing seems to happen.

I'm having to resort to the the ugly timed loops / manual manipulation crap us modders had to do back in the AMXX mod days.
 
Last edited:
Upvote 0
I have a few questions to which I do not have the answer. I hope someone can help me out:

  1. How can I write something to the RO2 log file?
    I've tried the `log and `logd macro with -debug passed to the make command, but I still do not see anything appear in the log files.
  2. How should I make my mutator known (and selectable) in the web-admin tool?
  3. How should the format of the defaulthullmgmutator.ini file look like for the next mutator class? (it's just a snipped of the class)
Code:
class HullMGMutator extends Mutator
    config(HullMGMutator);
    
struct MissPercentages
{
    var float Recruit;
    var float Soldier;
    var float Veteran;
    var float Hero; 
};

var config MissPercentages HullMGMissPercentages;
I've tried this, but the mutator doesn't seem to load it:
Code:
[HullMGMutator.HullMGMutator]
HullMGMissPercentages=(Recruit=75.0,Soldier=70.0,Veteran=65.0,Hero=60.0)
 
Last edited:
Upvote 0