Unreal Tournament 3 marks the return of the world's première first-person shooter. It unleashes the full power of Unreal Engine 3, taking graphics, gameplay, and challenge to a whole new level. Players engage in intense battles with other human players online, or against Unreal artificial intelligence that sets the industry standard. With the most powerful futuristic weapons and vehicles available, this is FPS action at its best!
This tutorial will show you how to write a mutator that uses Game Rules. The code was written by Erwan 'Xiongmao' Allain for Shee Labs Mutator Week.
Posted by ambershee on Feb 28th, 2008
Basic Server Side Coding.
Today we're going to recreate a mutator Erwan 'Xiongmao' Allain wrote for Shee Labs Mutator Week! You can read about it here: Moddb.com
It's very short, very sweet and easy to modify to suit your needs. This time, we're going to use Game Rules. Game Rules are special, meaning you can deliberately effect game mode behavious without having to write a whole new game mode for a few little changes. If you were to make drastic changes, then perhaps it's time to write a new game mode instead.
Today, we're going to use the Game Rules to determine the best player and the worst player. We're also going to attach a light to the best and worst players, and we're going to give bonuses and maluses for killing them respectively.
First we need a mutator that implements a new game rules - this is easy. Don't forget to make sure your code is in a folder called 'BestWorst', or rename the code packages as you see fit.
Now the hard part. We want a new game rules class, so we derive from GameRules. We also want to get the controller of the best player, and the worst player. For our best and worst players, we need a PointLightComponent, both of which need a colour. Finally, we want a variable to tell us how many points to add or take away from a score.
Well, that's not too nasty. Next thing we're going to do, is to determine when a player is killed - and for that we have the ScoreKill function, which is called everytime a player is killed. We're also going to invent some new function to contain most of our logic (so our main function doesn't get huge!) as we write our code, so watch out for those in red.
So what happens? This is all quite easy. First things first, we want to get the Ids of both the player that is killed, and the player that kills him. We then also want to find the Ids of the 'best' and 'worst' players. We check to see if if the killed player is then the worst or the best, and set bonuses accordingly, and we also check if the killer is the best player and offer a bonus too. Finally we update the controllers based on the best and worst player, and check to see if there are any more Game Rules to be executed.
Next we need to write those sub functions. Let's get the best and worst player Ids. The best player can be the player with the highest score, but the least deaths, and the worst player can be the one with the lowest score and the most deaths.
Both functions essentially work the same way, so let's dissect getBestPlayerId, and I'll let you work out the rest. We get the GameReplicationInfo (GRI) from the worldinfo, and from that we can get an array of PlayerReplicationInfos (PRI) for every player in the game.
We cycle through this array, and on the first pass, we check to see if the beat player is the current player we're looking at. On successive passes, we check to see if there is a best player, and if their score is less than the current player we're looking at - if so, the best player is actually the current player. Otherwise, we check to see if there is a best player, and if the best player's score is the same as the current player we're looking at, then we compare their deaths. When we're finished checking through every player, then we return the playerId of the best player.
Read it through a few times and wrap your head around it, it's not as horrible as it sounds.
We also need to be able to set the player score relative to the bonus and the malus. This is really easy.We'll set the bonus points for the killing the best player to 2, and we'll set the malus points for killing the worst points to 2 as well - get 2 bonus points or lose 2 extra points.
In these functions, we take the controller and find the score in the PRI. From there, we change their scores, force these to be updated on all clients and then update their kills.
Next we'll write the function that updates the controller status.
This is quite a long one, but it's relatively incomplex. First things first, we get the best and worst playerIds. If the best player is the worst player, then there's no point doing anything, so we just return and do nothing.
We then remove any lights that we might have already attached from the previous best and worst players (we don't want players marked incorrectly!) and create a new point light for the current best and worst players. We cycle through the controllers, find the best and worst controller based on playerId (and if the same, just break and end the function), and finally actually attach the lights.
What's this in red? We haven't written a point light function yet!
Nice an simple. We just create a new PointLightComponent, set it's radius, brightness and colour, enable it and return the light. That's it! We're done. Compile and try and stay in the green!