Example: Ripper I - Converting a TournamentWeapons to EnhancedWeapon
This example will show how a weapon like the UT Ripper is converted into a
subclass of EnhancedWeapon.
Related Topics
Conversion Basics
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.
What exactly do I have to change?
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)
- The PlayAnim function's Rate parameter determines, how fast the animation
should play. Higher values basically make the animation faster, so just
multiply the Rate parameter with the SpeedScale variable. If that parameter is
not yet used just add SpeedScale as Rate.
TweenTime specifies how long it takes to transform the current animation
sequence to the new one. The new sequence starts after this time has passed.
If the TweenTime parameter has a significant influence on the time whole
animation need for playing it sould be divided by SpeedScale to make the tween
time shorter. If TweenTime is not used it is treated like 0, so it has no
influence at all.
- LoopAnim(name Sequence, optional float
Rate, optional float TweenTime, optional float MinRate)
- LoopAnim is changed in the same way like PlayAnim. If the MinRate parameter
is used treat it like the Rate parameter.
- TweenAnim(name Sequence, optional float
Time)
- TweenAnim just smoothly transforms the current animation sequence to the
new one, but does not play that sequence. The Time parameter should be divided
by SpeedScale to speed up the animation when SpeedScale gets larger.
- SetTimer(float NewTimerRate, bool
bLoop)
- NewTimerRate should be divided by SpeedScale if the timer is used spawn
projectiles or adjust the firing animation.
- Sleep(float Seconds)
- Seconds should be divided by SpeedScale if the Sleep function has direct
influence on the firing speed, e.g when it's used in the NormalFire state.
- Pawn(Owner).PlayRecoil(float Rate)
- PlayRecoil is used to animate the mesh of the weapon's owner to play the
recoil effect when firing the weapon. The Rate parameter has direct influence
on the PlayAnim function of the weapon's owner which plays the effect, so it
should also be multiplied with SpeedScale.
- Sound AmbientSound
- byte SoundPitch
- Some weapons like the minigun and the pulsegun use the AmbientSound
property to play the firing sound. In this case you can speed up the firing
sound by multiplying the default SoundPitch (which usually is 64) with
Sqrt(SpeedScale). Play around with this one to get the best results.
I guess you got the point now. If you use other methods to control the firing
speed, e.g. a timer variable in a Tick function or using Level.TimeSeconds,
also implement SpeedScale there.
Details - What does this mean for the Ripper?
Since 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.
- The SoundDampening value might change to make the owner produce less noise
Same goes for PlayAltFiring:
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.
The value of IdenticalTo can be used by the ClassIsA and OtherIsA functions
available in most of the EnhancedItems classes to identify the new class as a
Ripper. This can be used in mutators to replace the original version of the
Ripper as well as its new version with something else. Let's say you want to
play a map that uses EnhancedWeapon version of the UT weapons, but you want to
play it using Rockets UT. If the Rockets UT mutator finds an EnhancedWeapon
with IdenticalTo set to 'Ripper' it treats the weapon like UT's Ripper and
replaces it correctly.
You should change the
ProjectileClass
and
AltProjectileClass
to the new classes after you've followed the
tutorial for the ripper blades.
Related Topics