This tutorail describes, first, how mutators work, and second, how to make a few of our own mutators!
What is a mutator?
As described in Mutator.uc, a mutator is something that "allows modifications to gameplay while keeping the game rules intact". This means that a mutator is something that modifies the game, but doesn't change the general flow of gameplay for the gametype that is being played. Mutators can modify many diferent things in a game. Things such as player pawn properties, default weapons, and modifying/replacing/removing actors.
Note: Mutators can not alter objects which have the bGameRelevant set to true.
So, why would I want to make a mutator?
Mutators are fun! Things like low gravity, slow motion corpses, high friction corpses, and unlimited Double Damage (this will be made later on) are fun things that change gameplay in a small way. A really good mutator might even give your mod a longer life, because people will be able to make an old game seem new with features added in the mutator.
Sometimes mutators are also used to get things like gametypes played more. For instance, you could actually make a mutator that spawned a class that is derived from the GameRules class. Since clients cant download gametypes, but they can download mutators, the mutator will have it download the class linked, and you have a way to get small gametypes around (If you look at the code for the MutVampire class, you'll see what I mean).
Wow. Sounds cool! So, how do I get started on making these?
Easy! You just need to learn the variables and functions you can use in a mutator, and how to use them.
Here's a list of all the functions you can use, and what they do. We'll use most of them a little more later:
-
- ModifyPlayer - This function is used to modify the properties of the player pawns in the game
- ModifyLogin((out string Portal, out string Options) - Modifies player login parameters
- GetDefaultWeapon() - Returns the classname of the default weapon, but if another mutator uses this after your mutator, it will set the default weapon to the other Mutator's choice.
- GetInventoryClassOverride(string InventoryClassName) - Replaces the default inventory class with the specified
- Mutate(string Command, PlayerController Sender) - This is called when a player enters the command 'mutate <command>' in the console.
- RecommendCombo(string ComboName) - This function tells bots if there is a certain 'Adrenaline Combo' that is best for your mutator.
- AlwaysKeep(Actor Other) - When you return true with this function, it tells the game NEVER to remove the actor specified. Only do this if you have to for your mutator.
- AddMutator(Mutator M) - This can be used to add a mutator into the linked list of mutators
- CheckReplacement(Actor Other, out byte bSuperRelevant) - Returns true if Actor passed can be added into the game. Also, this is pretty usefull for changing properties of objects in the game.
I think most of those are self-descriptive... So, why don't we make a mutator or two?
Creating Our Package, and making our first mutator.
Now, it's finally time to get to making our package so that we can code! This package will be called wcTutMutators, and it will have several different mutators in it, covering how to use a few of the functions listed above. I am assuming that you already know how to create a package, so I will not spend any more time talking about it.
Now, we make our first mutator, which demonstrates the use of the CheckReplacement function. What it does, is it uses CheckReplacement to loop through all objects in the map. If they are adrenaline, it replaces it with a double damage powerup... Fun. Fun. Now, to the code. It will be explained later:
| | | //----------------------------------------------------------- // MutReplaceAdrenaline from Who_Cares' Mutator Tutorial //----------------------------------------------------------- class MutReplaceAdrenaline extends Mutator;
function bool CheckReplacement(Actor Other, out byte bSuperRelevant) { local vector Position;
if (Other.Class == class'AdrenalinePickup') { Position = Other.Location; Other.Destroy(); Spawn(class'UDamagePack', , , Position, ); }
super.CheckReplacement(Other, bSuperRelevant);
return true; }
DefaultProperties { FriendlyName="Adrenaline Replacer" Description="Replaces every adrenaline pickup with a UDamagePack. Watch out;)" } |
What this does is pretty simple. It goes through every Actor, and checks if it's an adrenaline pickup. If it is one, it simply sets the local variable to the spot that the adrenaline (Other) is at, destroys Other, and spawns a new UDamagePack in it's place.
Then we call super.CheckReplacement() so that other mutators can do what they need to do with the CheckReplacement() function.
In the default properties, the two variables we set are used to set the name shown in the mutator tab and the description showin in the status when your mutator is selected. For some reason you have to also put the description in the int file, as shown now.
Now, make your int file for wcTutMutators (system/wcTutMutators.int, in case you forgot), and put this in it:
| | | [Public] Object=(Class=Class,MetaClass=Engine.Mutator,Name=wcTutMutators.MutReplaceAdrenaline,Description="Replaces every adrenaline pickup with a UDamagePack. Watch out!") |
Note: This all has to go on one line, but has been made 2 here to fit on the page.
Now run the game, and test it! Pretty cool, huh? Now, you should know how to use CheckReplacement, and you've made your first mutator! Now for another mutator showing the use of ModifyPlayer()!
Losing The Pickups - Another mutator
Okay. Now, we are going to make a mutator that is an example of using ModifyPlayer(). This one should be a snap since ModifyPlayer() is a lot like checkReplacement(), except for how it only loops through player pawns. Here's the code:
| | | //----------------------------------------------------------- // MutNoPickup from Who_Cares' Mutator Tutorial //----------------------------------------------------------- class MutNoPickups extends Mutator;
function ModifyPlayer(Pawn Other) { Other.bCanPickupInventory = false;
super.ModifyPlayer(Other); }
DefaultProperties { FriendlyName="No Picking Up" Description="Nobody can pick up inventory!" }
|
This, as you can see, is a lot like the previous except for how it only loops through pawns in the game - not every actor. All we did in this was set the bCanPickupInventory variable to false for each player, so people can't pick anything up.
Now for the code to the int file. Here it is:
| | | | Object=(Class=Class,MetaClass=Engine.Mutator,Name=wcTutMutators.MutNoPickups,Description="Nobody can pick up inventory!") |
Now, test the game. If you did everything right, you wont be able pick anything up in the game when this mutator is enabled.
Well, that's all im going to explain in this tutorial. Check back later, as I might make an 'Advanced Mutators' tutorial (Maybe...). Any feedback can be sent back to me at monokrome@gmail.com, and of course, the source to this tutorial can be downloaded here. |