UT Tutorial: UT - QHealth

Want to alter the health of a player? Then this is the tutorial for you. It's quite short, because it is based on my QHealth mutator, which is also very small ;-)

QHealth does two things. It lets players start with 125% health, and slowly takes down your health if you have more than 100%. This gives freshly spawned players a little more protection so that they can find some killing gear.

This tutorial not only covers the basic function of the mutator, but also shows a common programming error and its solution, which you might want to be aware of.

© Sybren Stüvel, written on 21-jan-2000

Assumptions

I assume you have read the Simpe mod tutorial, part 2, and you have downloaded & examined the QHealth mutator.

The tutorial

QHealth does two things. It lets players start with 125% health, and slowly takes down your health if you have more than 100%.

Starting with more health

This one is easy. Three lines will do the trick:

function ModifyPlayer(PlayerPawn Other) { Other.Health=125; }

That's all! ModifyPlayer is called at the server side every time a player (re)spawns. The Other argument refers to the player being respawned. I guess you get the point.

Slowly dropping the health

var config float SpeedFactor; var float HealthTime; function Tick(float DeltaTime) { local Pawn P; Super.Tick(DeltaTime); HealthTime+=SpeedFactor*DeltaTime; if(HealthTime<1.0) return; for(P=Level.PawnList; P!=None; P=P.NextPawn) { if(P.Health>100) P.Health-=int(HealthTime); } HealthTime-=int(HealthTime); }

The Tick function is called as many times as possible, with DeltaTime being the time between this call and the previous. Let's assume it is called 10 times every second, so DeltaTime will be 0.1. The health of a player is stored as an integer, so if we would simply substract DeltaTime from the health, you'll get this effect:

  • Health is 130%
  • Substract 0.1, so the result is 129.9%
  • This is stored as an integer, so remove all the digits after the decimal point.
  • Health is now 129%

As you can see, the health would be reduced by 1% ten times per second! This is not wat we want, so I used a different approach.

I stored the passed time in a float variable called HealthTime. After 1 second, this variable will be exactly 1. The mutator does nothing until a second or more has passed. After that second, the integer part of HealthTime is substracted from the health of each player healthier than 100%, and is substracted from itself as well.

This way, we have bridged the gap between floating point and integer variables. One glitch might show up if the server is really slow. If Tick is called less than one time per second, the integer part of HealthTime might be 2 or more. Let's assume it is 3 (REALLY slow server!), and a player is at 101% health. Because now 3 is substracted, the player will end up with 98% instead of 100% health.

Please note: I am talking about the speed the server runs UScript. This is entirely different from network/connection speeds, ping times etc.

I wanted the speed with which the health drops to be configurable, so I created a SpeedFactor. It is stored in QHealth.ini because of the config keywords.

Network issues

I haven't tested the code on a networked game yet. However, since the code runs at the server side, and health is also stored at the server, things should be ok. The health is replicated to the client in the Engine.Pawn class.