This page is one of a series of UnrealScript Lessons.
Previous tutorials:
- You've set up your environment: Setting Up UnrealScript
- You've made a simple text mutator: UnrealScript Hello World
This page is geared towards UT2003 where needed notes are added for UT2004.
Now we're going to make a mutator that actually does something.
Contents
Make Your Own Package
While some editors don't require you to do this by hand, it's so easy it seems silly not to. To set up package folders that the compiler will recognize, just create a new directory within the Base Directory, named the same as your package e.g. "MyPackage". In it, make a subdirectory called "Classes":
Finally, open your UT2003.ini (for UT2004 open UT2004.ini) and find the list of "EditPackages". Add "EditPackages=MyPackage" to the list. The compiler will now attempt to compile your package with the rest.
Quicknote about the order of EditPackages - if you have one package dependant on the other, the dependant package must come after the other one. Notice how the first package in the list is "Core"
Now go to your command prompt, CD down to your {Base Directory}/System directory and type
ucc make
Voila! You get ... an error! That's because your package is completely empty. Let's quickly fix that.
Subclassing
UT2003 only, for UT2004 read on, you will find the complete code in the next paragraph.
Go into the directory XGame/Classes and open the file "MutRegen.uc" with your editor of choice. Resave this file into your own package's class directory as "MutRegenPlus.uc." Take care not to directly edit any of the classes that came with the game. If you do, the package size will become invalid and you won't be able to play online and you might possibly break the game itself.
Your first step to making MutRegen your own is changing the classname to match what you saved the file as. So change:
//============================================================================= // MutRegen - regenerates players //============================================================================= class MutRegen extends Mutator;
to:
//============================================================================= // MutRegenPlus - regenerates players plus! //============================================================================= class MutRegenPlus extends Mutator;
Writing the script
for UT2003
You should also go ahead and change the default properties from:
GroupName="Regen" FriendlyName="Regeneration" Description="All players regenerate health."
to:
GroupName="Regen" Friendlyname="Regeneration Plus" Description="All players regenerate health to superhealth limits."
Now what fun is modding if you don't modify anything? Take the line down below that says:
if (C.Pawn != None && C.Pawn.Health < C.Pawn.HealthMax ) { C.Pawn.Health = Min( C.Pawn.Health+RegenPerSecond, C.Pawn.HealthMax ); }
And change it to:
if (C.Pawn != None && C.Pawn.Health < C.Pawn.HealthMax*2 ) { C.Pawn.Health = Min( C.Pawn.Health+RegenPerSecond, C.Pawn.HealthMax*2 ); }
You just altered the second variable of the Min function, which is essentially the cap that can be returned.
Save your file and prepare for compiling.
for UT2004
For UT2004 the "MutRegen.uc" does not exist, but the code can be extracted from "System/XGame.u".
Here you find the "Regeneration Plus" (with modifications):
// MutRegenPlus - regenerates players to superhealth //============================================================================= class MutRegenPlus extends Mutator; var() float RegenPerSecond; // Don't call Actor PreBeginPlay() for Mutator event PreBeginPlay() { SetTimer(1.0,true); } function Timer() { local Controller C; for (C = Level.ControllerList; C != None; C = C.NextController) { if (C.Pawn != None && C.Pawn.Health < C.Pawn.HealthMax*2 ) { C.Pawn.Health = Min( C.Pawn.Health+20, C.Pawn.HealthMax*2 ); } } } defaultproperties { GroupName="Regen" Friendlyname="Regeneration Plus" Description="All players regenerate health to superhealth limits." }
Compiling Your Script
for UT2003
Before you can compile you will need to make some changes to your UT2003.ini file that's in your UT2003/System directory. Open the UT2003.ini file and locate the list of of "EditPackages" under [Editor.EditorEngine]. Add your package to the end of that list (e.g. "EditPackages=MyPackage").
Quicknote about the order of EditPackages - if you have one package dependant on the other, the dependant package must come after the other one. Notice how the first package in the list is "Core."
Open up a command prompt, CD to your UT2003/System directory, and type "ucc make" (see Compiling With UCC). You should get something that looks like this:
-------------------------MyPackage - Release-------------------------- Analyzing... Parsing MutRegenPlus Compiling MutRegenPlus Importing Defaults for MutRegenPlus Success - 0 error(s), 0 warning(s) D:\UT2003\System>
Quick note on compiling - if you don't see the above, make sure the UT2003.ini file hasn't been rewritten again without your EditPackages line it from a previous attempt at compiling. If it has, make sure to close out of any programs which might have opened it after putting it back in and recompiling. (This can happen if you have UnrealED or UT2003 open while you edit the .ini file. As soon as you quit either, they will overwrite your .ini with whatever was current when they were launched.)
There should now be a .u file with your package name on it in the UT2003/System directory. But, before you can see your new codework in the game, there is another step you need to do. The code is there, but you have to tell the game to see it. To do this, you'll need to make an INT file named after your package in the System directory. This is a file which will describe to the engine the most basic parts of your package. For now, just copy:
[Public] Object=(Class=Class,MetaClass=Engine.Mutator,Name=MyPackage.MutRegenPlus,Description="Regeneration Plus")
And save it into your package's .int file (e.g. MyPackage.int). If you make any other changes to your .uc script file, recompile your code.
for UT2004
To compile and create the UT2004 .int and .ucl files use:
ucc make
ucc dumpint MyPackage.u
ucc exportcache MyPackage.u
For details on this see UnrealScript Hello World.
Fire it Up
Go ahead and start up UT2003 or UT2004. Go into Instant Action. Select "Regeneration Plus" into your mutator list, and watch as you regenerate to 200 health.
Quicknote on changing this mute! Let's say you want to regenrate 300 health insted of 200. You have already compiled your mutator. You can't just change the MutRegenPlus.uc and ucc make. To change it go to your {Base Directory}/System directory. Delete MutRegenPlus.u and MutRegenPlus.ucl. Make the changes in your MutRegenPlus.uc file and ucc make it!
This tutorial was originally part of RegularX's UTutes series.
Related Topics
- Modify Mutator Tutorial – 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
Comments
DaWrecka: Is there a reason this tutorial involves COPYING a source file, rather than subclassing? I would've thought that with the UnrealScript Hello World touching on inheritance, this would've been a perfect place to expand on it a bit further. I know the next one goes into it further but I don't see how using it here and explaining it in light depth would hurt.
CH3Z: DaWrecka, this is a very light tutorial as far as code and programming concept goes. The intent of this tutorial is to give a walkthrough of the whole proccess of setting up your environment, creating a subclass and running it through the compiler, then creating the int file so it can be used. This would not be the perfect place to get into the whole concept of inheritance. You might want to visit one of the many pages here on the wiki about Object Oriented Programming for more on that. Use the quickbar on your left and start at "UnrealScript Topics". As far as COPYING the source file, the author of this tutorial is trying have you use that file as a template for the purpose of getting you through the process at hand. Once you've copied it then you change the class declaration it becomes a new class. The class that is being subclassed is Mutator, not MutRegen so its not like we're copying a class instead of subclassing one. We copied one to use as a template, now after we make that "copy" its own class via the declaration, we have a new class that is a subclass of Mutator and therefore inherits Mutator's code. Did you go through this tutorial? It would make more sense if you did. Maybe this tut needs an introduction that explains its purpose and later explains that we are copying MutRegen to use it as a template.
Sweavo: in my experience copying is often much simpler than subclassing, and is arguably the right thing to do. Subclassing is apropriate when you are sure you are not going to break any of the behaviour of the superclass, e.g. if I subclass the flak canon then all the existing code that tests for whether something is a flak canon will pass when it runs on my weapon. Looking at the UT script code, most superclasses are abstract in the sense that they have been created for the main purpose of getting subclassed: the firemodes for projectiles and for instant hit, for instance, or ONSWheeledVehicle, ONSHoverVehicle etc (names from memory). Just because something is similar to something else does not make it a subclass. Ask yourself whether you're convinced the new object will do everything the code wanted the superclass to do.
Atlantis|TheKing: UT2004 notes added.