This page is one of a series of UnrealScript Lessons.
Previous tutorials:
- You've set up your environment: Setting Up UnrealScript
Contents
Overview
This tutorial will teach you how to compile a small mutator whose sole purpose in life is to write "Hello World" into the Unreal Tournament log file (UnrealTournament.log, UT2003.log or UT2004.log).
We assume that you've never tried building anything in UnrealScript before, and you haven't got a clue where to actually start. What follows applies equally well to UT , UT2003 or UT2004.
Create the Directory Structure
In your UT directory create a directory called MutHelloWorld. MutHelloWorld is the name of our package.
In the newly created MutHelloWorld directory create another directory called Classes. (For more on this step, see Set Up Package Folders.)
You should now have the following directory structure
- {Base Directory}\MutHelloWorld
- {Base Directory}\MutHelloWorld\Classes
So far so good. Now let's write the code.
Creating the mutator
Within the {Base Directory}\MutHelloWorld\Classes directory create a new file called HelloWorld.uc.
This is just a normal text file so you can use Notepad, vi, or any other text editor application of your choice to create/edit it. The uc extension means that it's an Unreal Class file. All UnrealScript code is contained in UC Files (see that page for tips on working with them).
- Caution: Be careful to actually name your file HelloWorld.uc, not HelloWorld.uc.txt when using Notepad or another Windows text editor. By default Windows Explorer would hide the ".txt" part of the file name, so only "HelloWorld.uc" would show up along with a "text file" icon. The compiler won't find that file though and complain about it.(If you're using notepad change the "save as type" to "All files" to ensure it wont save it to a .txt file)
Place the following code within the file you just created (HelloWorld.uc)
class HelloWorld extends Mutator; function PostBeginPlay() { Super.PostBeginPlay(); // Run the super class function (Mutator.PostBeginPlay). Log("Hello World"); // Write our log message }
- Caution: Note that the name of the class must be exactly the same as the filename with the .uc taken off.
The first line says "This describes a new class of object called a 'HelloWorld' which is just like a 'Mutator' except for what follows..."
The PostBeginPlay() function is called immediately after the object has "entered the game" so to speak. All we need this function to do is write a line to the log.
This is already enough for UT, but in UT2003 and UT2004 we need some more. Add the following lines at the end of the file:
defaultproperties { FriendlyName="Hello World Mutator" Description="Log 'Hello World'." }
defaultproperties allows the programmer (that's you!) to embed default values for properties in the source file. FriendlyName and Description are declared in Mutator and here we give them default values for the HelloWorld variety of Mutator.
Save the file and, if you used notepad, make sure it has an extension of .uc and not .uc.txt.
Compile Your Code
So far we have created our code and created a file that will tell UT about our fantastic mutator. We still don't actually have any code that UT can run. We need to compile our code into a package file (a .u extension). To do this we need to tweak the Game Ini File – UnrealTournament.ini, UT2003.ini or UT2004.ini – depending on which game you are using.
Open the INI (the one that resides in the /System directory, not the one in the {Base Directory}) file in your favourite text editor and search for the following string EditPackages=. You'll find a whole list of them. These are the packages that the compile command you are about to learn will attempt to build when executed. Only packages that are not found will be built.
Immediately after the last EditPackages=.... line (doesn't matter what the .... is) add the following line:
EditPackages=MutHelloWorld
Save the file and get a command prompt up (e.g. "Start" -> "Run..." -> type "cmd" and press <Return> to get the command prompt). Change the directory you are in until you are in the {Base Directory}/System directory (e.g. type: cd \UT2004\System). Once in the {Base Directory}/System directory enter the following command:
ucc make
This will run the compiler. It will list each package you have on your EditPackages=... lines in your UT ini file, but will only attempt to compile a package if its .u (or package file) is not there. In this case, because this is the first time we have built our mutator the package file MutHelloWorld.u doesn't exist.
Assuming you weren't told about any errors you should be able to see your compiled mutator's package file MutHelloWorld.u in your {Base Directory}/System directory.
Creating the package interface file
for running with UT and UT2003
(This is specific for UT2003. UT2004 package descriptions are made easiest after compilation, so read below)
The package interface file has an extension of .int. This file tells UT what classes are available within the package of the same name (it has a .u extension instead) for interrogation and/or public use. All INT files need to live within the {Base Directory}/System directory. So lets create our INT file now.
Using your favourite text editor create a file called MutHelloWorld.int in the {Base Directory}/System directory. All INT files are plain text so you can look at the others in the {Base Directory}/System directory if you wish. Just don't change any of them.
Add the following two lines of text to your MutHelloWorld.int file and save it to disk:
[Public] Object=(Class=Class,MetaClass=Engine.Mutator,Name=MutHelloWorld.HelloWorld,Description="Hello World Example")
The Description=... part won't be used in UT2003, but it helps identifying the mutator if you have more than only one of them in your package.
- Caution: Make sure you don't indent any of the lines within the .int file. The .int files are not parsed correctly by the Unreal Engine when lines are indented.
You'll find more on this step on the "Create An INT File" tutorial page.
for running with UT2004
The package interface file has an extension of .ucl. It is accompanied by an INT file that can contain localised text. The UCL file tells UT what classes are available within the package of the same name (it has a .u extension instead) for public use. UCL files live within the {Base Directory}/System directory. UCL and INT files are generated automatically by UCC. You can create the UCL and INT files by running these two lines from your {Base Directory}/System directory (easiest by creating a batch file):
ucc dumpint MutHelloWorld.u
ucc exportcache MutHelloWorld.u
See DumpIntCommandlet and ExportCacheCommandlet for more on these. ExportCache will be called automatically by UCC Make or UnrealEd in UT2004 v3204 and above. For this to work the INI file used during compiling (by default that's UT2004.ini, but with UMake it's the project's make.ini) needs to have its CacheRecordPath entry in the [Core.System] section to be set to the {Base Directory}/System directory.
for running with KillingFloor
If you are making this mutator for KF, it will not appear in the mutator list. To fix this append this line into command that is in the .ucl file:
GroupName=KF
example from my .ucl file:
Mutator=(ClassName=MutHelloWorld.HelloWorld,IconMaterialName=MutatorArt.nosym,GroupName=KF,FriendlyName=MutHelloWorld.HelloWorld.FriendlyName,Description=MutHelloWorld.HelloWorld.Description,FriendlyName=MutHelloWorld.HelloWorld.FriendlyName,FallbackName="Hello World Mutator",FallbackDesc="Log 'Hello World'.")
That's All Folks
Right, we've created our package interface file (.int), written our code (.uc), and compiled it into a package file (.u) it's now time to test our mutator.
Start up Unreal Tournament and go to the mutator page (e.g. for UT2004 you find the Mutator button/tab via the Instant Action menu option, you may have to select a Gametype first). You should see your Hello World mutator in the list of available mutators. Add it to the game and start killing things.
Once you've been in the game for a few seconds quit Unreal Tournament. If you look in your Unreal Tournament log file (UNREALTOURNAMENT.log, UT2003.log or UT2004.log) you should be able to find your Hello World message in there. If you can then your mutator worked :) Well done. If you can't and did everything as explained above, look again. It has to be in there ;).
How it works
The game looks at all INT file when it starts up. The INT file you created tells it to load the package you compiled. More precisely, "MutHelloWorld.HelloWorld" means the class "HelloWorld" in package "MutHelloWorld", and the INT file tells the game that this class is a mutator, and should therefore be displayed in the interface for the player to select.
In the case of UT2003, the values in the "default properties" section tell the game what to display in the GUI interface.
If a mutator class has been enabled by the player, then an instance of it is created when the game begins. This is an object of class "HelloWorld" that now exists in the game.
The function PostBeginPlay() is called on all objects that exist. So at some point right at the start of the game (quite a bit less than a single second), the function PostBeginPlay() in the script you pasted is called.
This calls Log("Hello World"), which is a special function that handles writing output to the log. The object thus write the string "Hello World" to the log, and then does nothing else for the remainder of the match.
Some Other Things to Look At
OK, so now you've built your first mod you're probably wanting to make one that does more than write to the UT log file. Well, here's some suggested reading.
- UMake – Will make building and managing your mods easier
- Mod Authoring – An excellent overview of the types of mods - it's a little dated now but worth the read.
If you are looking for a list of 'special' function names, such as "PostBeginPlay", then you will might want to read some of these related articles :
Also, since most of the classes you will be writing are subclasses of "Pawn" or "Actor" (Pawn is a subclass of actor) I suggest that you read those classes to find out what functions you can overload (another term for replace).
- Pawn
- Actor
Don't forget about the search function in the Wiki.
On a final note, I have found a difference between UT and UT2003. In the UT2003.INI file there are 2 EditPackages=.... sections. One for the game, and one for the editor. It seems that the EditPackages=.... in the editor section (2nd in the file) is re-written whenever the editor is closed. So if you start UnrealEd (UT2003 version) up and it complains about a missing package file, check the UnrealEd EditPackages=... section in your UT2003.INI file.
Related Topics
- Regen Mutator – your recommended next step
- UnrealScript Lessons – all the UnrealScript tutorials
- UnrealScript – all the reference pages
- Mutator Topics – more on mutators
- Making Mods – more on the organizational and social aspects
Discussion
Mychaeel: What about using Level.GetLocalPlayerController().ClientMessage instead of "Log" for that Hello World script though? That'd give people something to look at in-game. – And I'd be in favor of mentioning UMake somewhere after explaining the individual compilation steps.
EntropicLqd: I did think about actually displaying the Log message on screen - but decided that the additional code might be too scary - if it only appears once people would miss it so it would have to be on a timer ..... The benefit of using Log() is that it forces people to look in their UT log file - a good reminder that it exists. I am intending to add some additional reading links to the page - but didn't get time last night. In terms of the name of the page, feel free to rename it to anything you feel is more appropriate.
UserEquals1D10T Does the INT file serve the same function as a header file does in C++?
EntropicLqd: They are similar - but INT files are not compulsory. You don't actually need an INT file to run a mod if you specify it on the command line (e.g. CTF-Coret?mutator=MutMyMutator.MyMutator). However, both UT and UT2K3 use the INT files to determine which mods are installed. They essentially search through the INT files for public classes of type Mutator and GameInfo so they can list gametypes and mutators in the interface. So if you want your mutator/mod to appear in the menus then you need to create an INT file.
Foxpaw: From what I've heard, UCC takes quite a while to compile so it isn't high on the list of things to debug at Epic right now.
DodgerWA: (Okay, I'm commenting by editing the page because I can't find any kind of Add Comment button/link.) The information regarding editing the INI is not complete. In order to compile, you must add a ServerPackages entry. I presume the EditPackages is only for the editor, but it won't compile with that alone:
EntropicLqd: Good spot. Main text corrected.
[Engine.GameEngine] EditPackages=MutHelloWorld
Wormbo: ServerPackages for compiling? What are you trying to to, coding as a multiplayer game? :) It's always EditPackages when dealing with development. ServerPackages only comes into play when network-testing your compiled stuff.
EntropicLqd: You are ofcourse correct. I'd plead insanity but it's more likely the headache from hell I'm suffering from. Somehow I'm going to squeeze in some UScript this weekend. Maybe that'll make my headache go away.
DodgerWA: (Wrote this once before but it's not there now.) Dunno what to tell you. Compiler complained that it didn't know anything about the existence of my package. The only change I made was adding the ServerPackage line and it compiled. This was from the command line. Seems to work fine using WOTgreal.
MythOpus: Try adding your package to both ServerPackages AND EditPackages. Also make sure your .int are set up correctly. (You need a .int and a .ini file to register your mutator into the game)
EntropicLqd: If the compiler says it can't find your package then you've probably not got some things in the right place. The fact that it's looking for your package means that you most likely have added the EditPackages=.... line in the INI file correctly. However, you must put your code in the /UT2004/<your package name>/Classes directory otherwise your code will not be found. The package name used in your EditPackages=... line must match exactly the directory name the classes directory is contained in. Maybe your ServerPackage and EditPackage lines were different.
I've also noticed that in UT2004 a .ucl file is created from the .int first time the mutator is used (to allow caching and some other stuff - it's in a header somewhere and I've not had time to investigate it. It may be that these two files are out of sync or something.
Kamek: A ServerPackages entry shouldn't be necessary unless the package contains classes with simulated functions or variables, or other things that the client needs to know about such as new weapons or something. In the case of this HelloWorld mutator it shouldn't need a ServerPackage line, and just adds to the list of stuff the client has to download when connecting.
Mortal Monkey: If you're using UEd's built-in script editor, neither ServerPackages nor EditPackages should be necessary. I wouldn't know about the other way(s) though, as I've just recently downloaded WOTgreal.
Boksha: I've tried editing this page so making UCL and INT files works correctly for UT2004. I'm not sure if everything I've written down is correct, although it should work just fine for small mutators.
Atlantis|TheKing Just added an line on where to find those mutators in UT2004.
LinkeT i have the current Unreal Engine 2 Runtime Demo - this sample doesnt work
Log: 16781187818.5ms Unloading: Package MutHelloWorld
was added to log after load the test-map
I follow all instructions all time the same message
Mcx: this sample works with Unreal Engine 2 Runtime Demo too!
just start your runtime with the command line like
"C:\UnrealEngine2RuntimeDemo\System\UE2Runtime.exe EM_Runtime?mutator=MutHelloWorld.HelloWorld"
Mstram: Are mutators applicable to the UnrealEngine2 Runtime? I'm trying to do the the "UnrealScript Hello World" tutor (http://wiki.beyondunreal.com/wiki/UnrealScript_Hello_World) and can't find the "mutator page" ("Start up Unreal Tournament and go to the mutator page ...)
EntropicLqd: Mstram - the mutator page is part of UT2004. Mutators do work with the Unreal Engine Runtime though. You simply need to specify the mutaor and map on the command line. (See the last comment by Mcx.
Mstram: Ok, thx, I got it to work. I also dug through my cd collection and found my copy of UT(436). I got the mutator code to work in it as well, but I had to add the contents of the MutHelloWorld.int file to the BotPack.int file, for the mutator to show up in the game interface. Is that the correct procedure? (If anybody is still running such an old version :) )
EntropicLqd: No. You should never have to change any of the game files to make your mods work. It's hard to know what you did wrong though. Check the ini file for the EditPackages (and ServerPackages just to be complete) lines. Also check you've got .int, u., and .ucl files for your mutator in the /UT2004/System directory.
Mstram: ".int, u., and .ucl files for your mutator in the /UT2004/System directory." ... This isn't UT2004 .. it's an old (the first ??) version of Unreal Tournament ... there are no .ucl files.... it's probably amazing that I have it working at all :)
Infernus: The old versions of Unreal dont use ".ucl" files.