Can you update it? Here is a revised version, with the new parts in silver.
I haven't tested these revised bits, the reason they didn't get in the first version was because I hadn't bothered putting them in my own code. But it looks right.
Advanced Death Messages for Weapons
By Dragonfly Matthew
Intermediate
Introduction:
UT normally makes an assumption that any kill was caused by the weapon the killer was holding at the time. This is usually ok because most weapons kill instantly, or fast enough that you don’t have time to change weapon.
However, particular weapon like the Eightball sometimes take a long time to kill someone and you may have changed weapons by then. In this situation you have to do something special.
The default UT weapons fix this problem with damagetypes. For example, redeemer kills have the damagetype “redeemerdeath” and whenever someone dies from “redeemerdeath” they get a redeemer death message. Great. The only problem is that this is all coded in the gametype function so unless your weapon comes with a special gametype, you cannot change death messages this way. We need a different approach.
When someone is killed with “specialdamage”, the death message used is the level’s current specialdamagestring. When you are killed in a pressurezone, the Specialdamagestring is changed to something appropriate and you are killed with specialdamage. We will copy this for our weapon.
The actual stuff
At the top of your projectile (or whatever it is) add these properties. If the projectile is one that cannot hurt its owner (like a plasma sphere) you only need the first of there. If the projectile can hurt its owner (like a piece of flack) then you need all three.
var string DamageString; //The normal kill string
var string DamageStringselfhe; //The suicide kill message (male)
var string DamageStringselfshe; // Ditto for females.
In your weapon’s defaultproperties, give these strings values. The text %o will be replaced with the victim’s name, and %k with the killers. A very boring example would be:
Damagestring="%o was killed by %k with a grenade."
Damagestringselfhe="%o killed his own dumb self."
Damagestringselfshe="%o killed her own dumb self."
Ok. Now choose one of these two sections..
If your projectile uses the Takedamage function to cause damage:
This one is simple. Somewhere in your projectile code (for projectile weapons) there will be a line a bit like this:
Other.TakeDamage(Damage, instigator, HitLocation, -10000.0 * Y, MyDamageType);
First we must set up the death message. If the weapon cannot hurt its owner, you only need this line:
Level.Game.Specialdamagestring=damagestring;
Before the TakeDamage function. Then change the damagetype to “specialdamage” and you’re done!
If your projectile can end up hitting its owner, instead of the single line above you will need something like this:
if (Other==Instigator)
{
if (Instigator.bIsFemale) Level.Game.Specialdamagestring=damagestringselfshe;
else Level.Game.Specialdamagestring=damagestringselfhe;
}
else Level.Game.Specialdamagestring=damagestring;
Where Other is the thing you are hurting. This selects the correct death message, and stops you getting messages like “Dragonflymatthew killed Dragonflymatthew with a rocket!”.
As above, change the damage type to special damage.
Now you should have a projectile that gives these special death messages. But there is still one problem.
When someone is killed with SpecialDamage, UT dosen't give the killer a "You killed soandso" message. You can see this in the function Killed in the Gameinfo class.
if (!bSpecialDamage && (Other != None))
{
BroadcastRegularDeathMessage(Killer, Other, damageType);
}
So what we have to do is put that RegularDeathMessage back in.
You need a new boolean variable - bAlreadyDead. Before you hurt the Other, check if they are already dead and stick it in that variable. Then you can use something like this after you deal the damage:
if (!bAlreadyDead && (Other.Isa('PlayerPawn') || Other.Isa('Bot'))
&& (Other!= instigator) && (Other.Health < 0) )
{
BroadcastLocalizedMessage(class’DeathMessagePlus’, 0, Instigator.PlayerReplicationInfo, Other.PlayerReplicationInfo, None);
So, all the code together would be:
//at the start of the function
local bool bAlreadyDead;
//at the part where you hurt the Other
if (Pawn(Other).Health < 0) bAlreadyDead=True;
if (Other==Instigator)
{
if (Instigator.bIsFemale) Level.Game.Specialdamagestring=damagestringselfshe;
else Level.Game.Specialdamagestring=damagestringselfhe;
}
else Level.Game.Specialdamagestring=damagestring;
Other.TakeDamage(Damage, instigator, HitLocation, -10000.0 * Y, MyDamageType);
if (!bAlreadyDead && (Other.Isa('PlayerPawn') || Other.Isa('Bot'))
&& (Other!= instigator) && (Other.Health < 0) )
{
BroadcastLocalizedMessage(class’DeathMessagePlus’, 0, Instigator.PlayerReplicationInfo, Other.PlayerReplicationInfo, None);
If your projectile uses the HurtRadius function to cause damage:
I am assuming that all weapons with a hurtradius can hurt their owner, if not then just set the SpecialDamageString and call the hurtradius function with “specialdamage” as the damage type. Otherwise, it gets more complicated.
We have to change the hurtradius function. Actually, hurtradius is a “final function” so instead we copy it into another function.
Where your weapon used to call the hurtradius function, change it to spechurtradius.
Now, you have to alter your hurtradius so that before it hurts each pawn, it checks to see whether they are the instagator and if so change the death message. All you really need to do is paste this function into your code.
function specHurtRadius( float DamageAmount, float DamageRadius, name DamageName, float Momentum, vector HitLocation )
{
local actor Victims;
local float damageScale, dist;
local vector dir;
local bool bAlreadyDead;
local Pawn PVictim;
if( bHurtEntry )
return;
bHurtEntry = true;
foreach VisibleCollidingActors( class 'Actor', Victims, DamageRadius, HitLocation )
{
if( Victims != self )
{
dir = Victims.Location - HitLocation;
dist = FMax(1,VSize(dir));
dir = dir/dist;
PVictim=Pawn(Victims);
if (PVictim==None)
continue;
damageScale = 1 - FMax(0,(dist - Victims.CollisionRadius)/DamageRadius);
if ((Victims.Isa('PlayerPawn') || Victims.Isa('Bot')) && (Pawn(Victims).Health < 0))
bAlreadyDead=True;
//OK, lets check if this guy we’re about to hurt is the instigator, if so then we change the death message.
if (Pawn(Victims) != Instigator)
Level.Game.SpecialDamageString = DamageString;
else
if (Pawn(Victims).bIsFemale)
Level.Game.SpecialDamageString = FemaleSelfDamageString;
else
Level.Game.SpecialDamageString = SelfDamageString;
//Then we go and hurt them, as normal.
Victims.TakeDamage
(
damageScale * DamageAmount,
instigator,
Victims.Location - 0.5 * (Victims.CollisionHeight + Victims.CollisionRadius) * dir,
(damageScale * Momentum * dir),
DamageName
);
//Now we put the "You killed soandso" message on the killer's screen
if (!bAlreadyDead && (PVictim.Isa('PlayerPawn') || PVictim.Isa('Bot'))
&& (PVictim.Health < 0) && (PVictim != instigator) )
{
BroadcastLocalizedMessage(class’DeathMessagePlus’, 0, Instigator.PlayerReplicationInfo, PVictim.PlayerReplicationInfo, None);
}
}
}
bHurtEntry = false;
}
That’s it. Now you should get the right death message no matter what weapon you are using when your victim dies.
Problems:
The death messages will appear white, which is not the normal death message colour.
I haven't tested these revised bits, the reason they didn't get in the first version was because I hadn't bothered putting them in my own code. But it looks right.
Advanced Death Messages for Weapons
By Dragonfly Matthew
Intermediate
Introduction:
UT normally makes an assumption that any kill was caused by the weapon the killer was holding at the time. This is usually ok because most weapons kill instantly, or fast enough that you don’t have time to change weapon.
However, particular weapon like the Eightball sometimes take a long time to kill someone and you may have changed weapons by then. In this situation you have to do something special.
The default UT weapons fix this problem with damagetypes. For example, redeemer kills have the damagetype “redeemerdeath” and whenever someone dies from “redeemerdeath” they get a redeemer death message. Great. The only problem is that this is all coded in the gametype function so unless your weapon comes with a special gametype, you cannot change death messages this way. We need a different approach.
When someone is killed with “specialdamage”, the death message used is the level’s current specialdamagestring. When you are killed in a pressurezone, the Specialdamagestring is changed to something appropriate and you are killed with specialdamage. We will copy this for our weapon.
The actual stuff
At the top of your projectile (or whatever it is) add these properties. If the projectile is one that cannot hurt its owner (like a plasma sphere) you only need the first of there. If the projectile can hurt its owner (like a piece of flack) then you need all three.
var string DamageString; //The normal kill string
var string DamageStringselfhe; //The suicide kill message (male)
var string DamageStringselfshe; // Ditto for females.
In your weapon’s defaultproperties, give these strings values. The text %o will be replaced with the victim’s name, and %k with the killers. A very boring example would be:
Damagestring="%o was killed by %k with a grenade."
Damagestringselfhe="%o killed his own dumb self."
Damagestringselfshe="%o killed her own dumb self."
Ok. Now choose one of these two sections..
If your projectile uses the Takedamage function to cause damage:
This one is simple. Somewhere in your projectile code (for projectile weapons) there will be a line a bit like this:
Other.TakeDamage(Damage, instigator, HitLocation, -10000.0 * Y, MyDamageType);
First we must set up the death message. If the weapon cannot hurt its owner, you only need this line:
Level.Game.Specialdamagestring=damagestring;
Before the TakeDamage function. Then change the damagetype to “specialdamage” and you’re done!
If your projectile can end up hitting its owner, instead of the single line above you will need something like this:
if (Other==Instigator)
{
if (Instigator.bIsFemale) Level.Game.Specialdamagestring=damagestringselfshe;
else Level.Game.Specialdamagestring=damagestringselfhe;
}
else Level.Game.Specialdamagestring=damagestring;
Where Other is the thing you are hurting. This selects the correct death message, and stops you getting messages like “Dragonflymatthew killed Dragonflymatthew with a rocket!”.
As above, change the damage type to special damage.
Now you should have a projectile that gives these special death messages. But there is still one problem.
When someone is killed with SpecialDamage, UT dosen't give the killer a "You killed soandso" message. You can see this in the function Killed in the Gameinfo class.
if (!bSpecialDamage && (Other != None))
{
BroadcastRegularDeathMessage(Killer, Other, damageType);
}
So what we have to do is put that RegularDeathMessage back in.
You need a new boolean variable - bAlreadyDead. Before you hurt the Other, check if they are already dead and stick it in that variable. Then you can use something like this after you deal the damage:
if (!bAlreadyDead && (Other.Isa('PlayerPawn') || Other.Isa('Bot'))
&& (Other!= instigator) && (Other.Health < 0) )
{
BroadcastLocalizedMessage(class’DeathMessagePlus’, 0, Instigator.PlayerReplicationInfo, Other.PlayerReplicationInfo, None);
So, all the code together would be:
//at the start of the function
local bool bAlreadyDead;
//at the part where you hurt the Other
if (Pawn(Other).Health < 0) bAlreadyDead=True;
if (Other==Instigator)
{
if (Instigator.bIsFemale) Level.Game.Specialdamagestring=damagestringselfshe;
else Level.Game.Specialdamagestring=damagestringselfhe;
}
else Level.Game.Specialdamagestring=damagestring;
Other.TakeDamage(Damage, instigator, HitLocation, -10000.0 * Y, MyDamageType);
if (!bAlreadyDead && (Other.Isa('PlayerPawn') || Other.Isa('Bot'))
&& (Other!= instigator) && (Other.Health < 0) )
{
BroadcastLocalizedMessage(class’DeathMessagePlus’, 0, Instigator.PlayerReplicationInfo, Other.PlayerReplicationInfo, None);
If your projectile uses the HurtRadius function to cause damage:
I am assuming that all weapons with a hurtradius can hurt their owner, if not then just set the SpecialDamageString and call the hurtradius function with “specialdamage” as the damage type. Otherwise, it gets more complicated.
We have to change the hurtradius function. Actually, hurtradius is a “final function” so instead we copy it into another function.
Where your weapon used to call the hurtradius function, change it to spechurtradius.
Now, you have to alter your hurtradius so that before it hurts each pawn, it checks to see whether they are the instagator and if so change the death message. All you really need to do is paste this function into your code.
function specHurtRadius( float DamageAmount, float DamageRadius, name DamageName, float Momentum, vector HitLocation )
{
local actor Victims;
local float damageScale, dist;
local vector dir;
local bool bAlreadyDead;
local Pawn PVictim;
if( bHurtEntry )
return;
bHurtEntry = true;
foreach VisibleCollidingActors( class 'Actor', Victims, DamageRadius, HitLocation )
{
if( Victims != self )
{
dir = Victims.Location - HitLocation;
dist = FMax(1,VSize(dir));
dir = dir/dist;
PVictim=Pawn(Victims);
if (PVictim==None)
continue;
damageScale = 1 - FMax(0,(dist - Victims.CollisionRadius)/DamageRadius);
if ((Victims.Isa('PlayerPawn') || Victims.Isa('Bot')) && (Pawn(Victims).Health < 0))
bAlreadyDead=True;
//OK, lets check if this guy we’re about to hurt is the instigator, if so then we change the death message.
if (Pawn(Victims) != Instigator)
Level.Game.SpecialDamageString = DamageString;
else
if (Pawn(Victims).bIsFemale)
Level.Game.SpecialDamageString = FemaleSelfDamageString;
else
Level.Game.SpecialDamageString = SelfDamageString;
//Then we go and hurt them, as normal.
Victims.TakeDamage
(
damageScale * DamageAmount,
instigator,
Victims.Location - 0.5 * (Victims.CollisionHeight + Victims.CollisionRadius) * dir,
(damageScale * Momentum * dir),
DamageName
);
//Now we put the "You killed soandso" message on the killer's screen
if (!bAlreadyDead && (PVictim.Isa('PlayerPawn') || PVictim.Isa('Bot'))
&& (PVictim.Health < 0) && (PVictim != instigator) )
{
BroadcastLocalizedMessage(class’DeathMessagePlus’, 0, Instigator.PlayerReplicationInfo, PVictim.PlayerReplicationInfo, None);
}
}
}
bHurtEntry = false;
}
That’s it. Now you should get the right death message no matter what weapon you are using when your victim dies.
Problems:
The death messages will appear white, which is not the normal death message colour.