Sometimes when a monster dies it might be appropriate for it to cause damage to nearby players. This tutorial will show you how.
Damage is always handled by the server so the function chosen to perform this task must meet some criteria. Firstly is has to be executed at some point near the monsters death and secondly it has to be executed on the server. The Died() function is a server only function and it also executes the PlayDying() function which is a perfect place to start. The PlayDying() function tells the clients to start simulating everything about the Actor on it’s own – it will no longer recieve any updates from the server. It does this by setting bTearOff = true; So we must create the damage code before this happens, otherwise the monster could be in a different location on all the client machines and on the server, which would make the damage appear to be coming form the wrong place. We don’t need to re-write the same code in PlayDying() so we will use the Super command appropriately.
simulated function PlayDying(class<DamageType> DamageType, vector HitLoc) { Super.PlayDying(DamageType, HitLoc); }
A function already exists which causes damage in a certain radius, it is the HurtRadius() function declared in Actor. We can use this but it will cause damage to everything nearby. Even though the PlayDying() is a simulated function the HurtRadius() performs a role check and ensures the server deals the damage. Otherwise you would need to use a role check around the damage code ie. if(Role==Role_Authority). This is an example of what the code should look like.
var() float DamageAmount; var() float DamageRadius; var() float Momentum; var() class<DamageType> RadiusDamageType; simulated function PlayDying(class<DamageType> DamageType, vector HitLoc) { HurtRadius( DamageAmount, DamageRadius, RadiusDamageType, Momentum, HitLoc); Super.PlayDying(DamageType, HitLoc); } defaultproperties { DamageAmount=200 DamageRadius=500 Momentum=1000 RadiusDamageType=class'corroded' }
As you can see, I have created some new global variables that are used in the HurtRadius function. The PlayDying() function already has access to a HitLocation we can use, so I have just passed that variable on to the HurtRadius function. The others are self explanatory. In game if you summon your monster and kill it, if you are close enough it will kill you too, and anything else nearby, including other monsters! This could set off a chain reaction if you had a lot of these monsters stood next to each other!
To make it affect everything except other monsters, the function needs re-writing slightly. The code looks like this.
var() float DamageAmount; var() float DamageRadius; var() float Momentum; var() class RadiusDamageType; simulated function PlayDying(class DamageType, vector HitLoc) { HurtRadius( DamageAmount, DamageRadius, RadiusDamageType, Momentum, HitLoc); Super.PlayDying(DamageType, HitLoc); } simulated function HurtRadius( float DamageAmount, float DamageRadius, class DamageType, float Momentum, vector HitLocation ) { local actor Victims; local float damageScale, dist; local vector dir; if( bHurtEntry ) return; bHurtEntry = true; foreach VisibleCollidingActors( class 'Actor', Victims, DamageRadius, HitLocation ) { // don't let blast damage affect fluid - VisibleCollisingActors doesn't really work for them - jag if( (Victims != self) && (!Victims.isA('Monster')) && (Victims.Role == ROLE_Authority) && (!Victims.IsA('FluidSurfaceInfo')) ) { dir = Victims.Location - HitLocation; dist = FMax(1,VSize(dir)); dir = dir/dist; damageScale = 1 - FMax(0,(dist - Victims.CollisionRadius)/DamageRadius); Victims.TakeDamage ( damageScale * DamageAmount, Instigator, Victims.Location - 0.5 * (Victims.CollisionHeight + Victims.CollisionRadius) * dir, (damageScale * Momentum * dir), DamageType ); if (Instigator != None && Vehicle(Victims) != None && Vehicle(Victims).Health > 0) Vehicle(Victims).DriverRadiusDamage(DamageAmount, DamageRadius, Instigator.Controller, DamageType, Momentum, HitLocation); } } bHurtEntry = false; } defaultproperties { DamageAmount=200 DamageRadius=500 Momentum=1000 RadiusDamageType=class'corroded' }
Additionally, to play a sound when a monster dies the rules are similar to the damage radius above. The code once again needs to be executed by the server to ensure that all the relevant clients hear it. Monsters play death sounds anyway and those can be set in the defaultproperties. But if you wanted an additional sound the code would look like this.
simulated function PlayDying(class<DamageType> DamageType, vector HitLoc) { if(Role==Role_Authority) { PlaySound(sound'SkaarjPack_rc.Skaarj.death2sk',SLOT_Misc); } Super.PlayDying(DamageType, HitLoc); }
If you want an effect to spawn when the monster dies, such as an explosion then check out my tutorial “How to make your monster spawn effects when it dies”. That’s it! Good luck.
TIP – You can use TimeSeconds to track the length of time between sounds, this will help to stop sound spam.
Recent Comments