


This example will show how a weapon like the UT Ripper is converted into a subclass of EnhancedWeapon.
Most weapons will work if you just replace the "extends TournamentWeapon" in
the class declaration with "extends EnhancedWeapon", but they usually can't
take advantage of all features the EnhancedWeapon class offers.
The Ripper is a simple projectile weapon. Most of its functionality (like the
firing states) resides in its superclass. The EnhancedWeapon class already
takes care of those functions and states, so you'll only need to change some
functions and/or state code in the weapon class itself.
The changes will concentrate mostly on the PlayAnim, LoopAnim, TweanAnim and
SetTimer and Pawn(Owner).PlayRecoil functions where the animation speed will
depend on the value of the SpeedScale variable so the weapon's speed can be
changed from the PickupPlus class.
SpeedScale initially is 1, but you can use a different default value for
subclasses of your weapon if you want to change their speed without having to
rewrite all those functions. You can think of it as the base speed of the
weapon.
Since the functions are used differently you will have to find out yourself the which changes work best for your weapon, but I will explain in general and in detail for the Ripper. You shouldn't change the speed for bringing up the weapon and for putting it down, since that might look a bit strange at higher SpeedScale values.
PlayAnim(name Sequence, optional float
Rate, optional float TweenTime)
LoopAnim(name Sequence, optional float
Rate, optional float TweenTime, optional float MinRate)
TweenAnim(name Sequence, optional float
Time)
SetTimer(float NewTimerRate, bool
bLoop)
Sleep(float Seconds)
Pawn(Owner).PlayRecoil(float Rate)
Sound AmbientSound
byte SoundPitchSince the Ripper is a built-in UT class you don't need all those
#exec lines. Just delete them after you copied the Ripper class.
Like I mentioned earlier the Ripper mostly uses its suberclass's functions,
so there's not much to change in the Ripper class.
The PlayFire function:
simulated function PlayFiring() // old
{
LoopAnim( 'Fire', 0.7 + 0.6 * FireAdjust, 0.05 );
PlayOwnedSound(class'Razor2'.Default.SpawnSound, SLOT_None,4.2);
}
simulated function PlayFiring() // new
{
LoopAnim('Fire', (0.7 + 0.6 * FireAdjust) * SpeedScale, 0.05);
PlayOwnedSound(ProjectileClass.Default.SpawnSound, SLOT_None,
4.2 * Pawn(Owner).SoundDampening);
}
The TweenTime of the PlayAnim sequence isn't that interesting in this case. The
change in PlayOwnedSound has two reasons:ProjectileClass is much more flexible than
class'Razor2'. Don't go with Epic's way of specifying a fixed
class name, you only make it more difficult for yourself and other people to
create subclasses.simulated function PlayAltFiring() // old
{
LoopAnim('Fire', 0.4 + 0.3 * FireAdjust,0.05);
PlayOwnedSound(class'Razor2Alt'.Default.SpawnSound, SLOT_None,4.2);
}
simulated function PlayAltFiring() // new
{
LoopAnim('Fire', (0.4 + 0.3 * FireAdjust) * SpeedScale, 0.05);
PlayOwnedSound(AltProjectileClass.Default.SpawnSound, SLOT_None,
4.2 * Pawn(Owner).SoundDampening);
}
In the case of our Ripper we will also add some new default properties:
defaultproperties
{
SamePriorityLike=Ripper
IdenticalTo=Ripper
...
}
SamePriorityLike automatically sets the new Ripper's autoswitch priority to the
same value like the original Ripper's priority.ProjectileClass and
AltProjectileClass to the new classes after you've followed the
tutorial for the ripper blades.