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!

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.

//check if the killed player is the worst player => malusif(killedId == worstPlayerId){
setMalus(killer);}

//check if the killed player is the best player = >bonusif(killedId == bestPlayerId){
setBonus(killer);}

//check if the killer was the worst player => bonusif(killerId == bestPlayerId){
setBonus(killer);}

//update status best and worst player
updateControllersStatus(killedId);

if( NextGameRules !=None){
NextGameRules.ScoreKill(Killer,Killed);}}

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.

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.

First of all, I'd like to say how appreciative I am of the time you put into these great tutorials for beginners. However, it would a lot more helpful if the code was explained more thoroughly for our feeble minds.

Personally I'm having trouble remembering which functions and classes are the ones we're creating, and the ones already there for us to use. Perhaps you could create a primer tutorial like your third tutorial "Delving Deeper into UnrealScript\" except giving us an overview of common functions and classes we use often and explaining how they work or their usefulness, etc.

Or maybe a primer exists already that I'm not aware of? I know of the UnrealWiki but that database of information without actually applying to an exercise makes it hard for me to grasp the concepts.

Anyway just some (hopefully constructive) criticism to help others like me understand and learn better.

//check if the killer was the worst player => bonus
if(killerId == bestPlayerId)
{
setBonus(killer);
}

Should it be:

"(killerId == worstPlayerId)" since we are rewarding the worst player?

In the GameInfo.uc class, you are awarded 1 point for killing someone no matter what, since this GameRule is applied/called later in the ScoreKill() via the "GameRulesModifiers.ScoreKill(Killer, Other);". So if your malus/penalty is 2, you will actually lose only 1 point. (at least in my case)

Has anyone tried testing this mutator when you have only 2 players? I have been getting strange logical issues. Ex. both players score and deaths = 0, so after the I kill the other player(first kill of the match), I tend to lose points, also it would make sense that one player will be the best player and the other will be the worst most of the time, but at times one player is green or red, and the other player is not.

The if statemensts/logic look fine to me. I found that this mutator works better when there are more than 2 players. Also, I figured out that when the score is tied (ex. 0 to 0), you get 1 point for killing your opponent, but then the new game rules sees that the score is now (1 to 0), so you get penalized for killing first which then makes you the worst player. I believe that creating a class that extends the GameInfo.uc and modifying/overriding the scoreKill() function in that class, will fix the minor issues.