This example will show how projectiles like the ripper blades are converted into a subclass of EnhancedProjectile.
Often projectiles will work if you just replace the "extends Projectile" in
the class declaration with "extends EnhancedProjectile", but they can't take
advantage of the features the EnhancedProjectile class offers.
Projectiles require a bit more work than the projectile weapon they are fired
from, but depending on the projectile there might be much less code in the
class than before. The changes include the use of the death message variables,
the DirectHit
and/or SplashDamage
functions and the
Explosion
and SpawnSubmunition
functions.
The advantage of placing the death messages in the projectile class will become
clearly visible if you try the following: Fire some ripper blades or shock
rifle plasma balls at a nenemy that is very far away and quickly switch to
another weapon, e.g. the impact hammer. If those shots kill the enemy you will
now get the death message message of the currently selected weapon, e.g.
"<your enemy's name> was smeared by <your name>'s
piston.", which obviously isn't the message that should be displayed.
Try to use the Explosion
function to handle the projectile's
impact effect.
%k
(the killer's name),
%o
(the victim's name), %w
(the killer's weapon) and
%p
(this projectile's name).%o
, %w
and
%p
. If %o
is not used the suicider's name is placed
in front of the message.%p
in death messages. The headshot strings will only be used if
bCanHeadShoot
is True
. (see
EnhancedProjectile
for details)DamageRadius > 0
)DamageRadius == 0
)SpawnSubMunition
function spawns the amount and type of
projectiles specified in the SubMunitionCount
and
SubMunitionClass
. These projectiles can be modified through the
ModifySubMunition
function.SpawnExplosionEffects
creates the visual impact effects
(ExplosionEffectClass
) and decals (ExplosionDecal
).DirectHit
instead of TakeDamage
and SplashDamage
instead of
HurtRadius
unless you are sure that no player is going to be hit,
because these functions activate the death messages. If you want to have the
death messages when killing a pawn with the Died
function you can
use these functions:SetKillType
activates the specified type of death message and
RestoreKillType
resets it.
The ripper blades are an excellent example, since they are capable of doing
headshots, they can hit their owner and with secondary firing mode they can
also do splash damage.
First we'll look at the Razor2
class, then we'll change the
Razor2Alt
class. Start by copying both classes and let them extend
from EnhancedProjectile. Delete the #exec
lines. The original
Ripper's models, textures and sounds can be used.
The first thing we'll change in Razor2
is the
ProcessTouch
function of the Flying
state:
simulated function ProcessTouch (Actor Other, Vector HitLocation) // old { if ( bCanHitInstigator || (Other != Instigator) ) { if ( Role == ROLE_Authority ) { if ( Other.bIsPawn && (HitLocation.Z - Other.Location.Z > 0.62 * Other.CollisionHeight) && (!Instigator.IsA('Bot') || !Bot(Instigator).bNovice) ) Other.TakeDamage(3.5 * damage, instigator,HitLocation, (MomentumTransfer * Normal(Velocity)), 'decapitated' ); else Other.TakeDamage(damage, instigator,HitLocation, (MomentumTransfer * Normal(Velocity)), 'shredded' ); } if ( Other.bIsPawn ) PlaySound(MiscSound, SLOT_Misc, 2.0); else PlaySound(ImpactSound, SLOT_Misc, 2.0); destroy(); } } simulated function ProcessTouch (Actor Other, Vector HitLocation) // new { if ( bCanHitInstigator || Other != Instigator ) { if ( Other != None && Other.bIsPawn ) PlaySound(MiscSound, SLOT_Misc, 2.0); else PlaySound(ImpactSound, SLOT_Misc, 2.0); Explosion(HitLocation,,Other); } }As you can see there's much less code in that function now. The missing code will not be added anywhere else, everything is handled in the
Explosion
function.defaultproperties
section:
defaultproperties { DirectHitString="%k ripped a chunk of meat out of %o with the %w." SplashHitString="%k killed %o with an explosive %p." HeadHitString="%k ripped %o's head off!" SuicideString=" ripped into himself." SuicideFString=" ripped into herself." HeadSuicideString=" ripped his own head off." HeadSuicideFString=" ripped her own head off." bCanHeadShoot=True HeadShotDamageFactor=3.500000 MyDamageType=Sliced FiredFrom=<your ripper class here> ProjectileName="ripper blade" (...) }For some reason the damage type was not specified here. (And 'sliced' sounds much more descriptive than 'shredded' in this case.) Set
FiredFrom
to the class of the ripper you created in the Ripper
I tutorial.HeadDamageType
is not set here, since we
still want the "Head Shot!" announcement, which will only be
displayed when the damage type is 'Decapitated', the default value of
HeadDamageType
.SplashHitString
could have been added to the alt fire ripper
blade, but it's nicer to have all those strings in one class, if you want to
translate them using localization files.ProcessTouch
Explode
BlowUp
if ( Level.bDropDetail )to
if ( Level.bDropDetail || (bDropEffects && !bKeepLightEffects) )in the
PostBeginPlay
function. This will disable the light effect
of the explosive blade not only in the frame rate is low, but also if the
player chose to drop some effects to further increase performance.HitWall
function from
Super(Projectile).HitWall(HitNormal, Wall);to
Super(EnhancedProjectile).HitWall(HitNormal, Wall);The reason for that change is pretty obvious: The primary blade's parent class is EnhancedProjectile now, instead of Projectile.
defaultproperties
section. Remove the MomentumTransfer
and MyDamageType
lines and add:
bCanHeadShoot=False SplashDamageType=RipperSplashDamage DamageRadius=180.000000 SplashMomentum=87000.000000 ExplosionEffectClass=Class'Botpack.RipperPulse' ExploWallOut=16.000000The alt firing blade cannot cause headshots, but it does splash damage and plays and explosion animation.
Congratulations! You can now compile and test your new Ripper.