Legacy:Weapon Modification (UT) - Unreal Wiki

# Legacy:Weapon Modification (UT)

### From Unreal Wiki, The Unreal Engine Documentation Site

This page is one of a series of UnrealScript Lessons.

## Introduction

This is my first UnrealScript Tutorial.

This tutorial assume that you have basic UnrealScript knowledge.

## Weapon Modification: Faster Sniper Rifle

You will learn how to modify a standard Weapon, in this case the Sniper Rifle, for the original Unreal Tournament. Here, we will try to enhance the Sniper Rifle to make it shoot faster. Some modifications will be made on the new weapon's ammo for conveniance.

Two classes will be created:

SniperRifle >> FastRifle
  The sniper rifle modification class
Mutator >> FastRifleMutator
  The mutator class to replace stuff

## FastRifle.uc

    class FastRifle extends SniperRifle; // We are modifying the Sniper Rifle

    var float fRifleAnimRate; // Custom rifle animation rate multiplier

    // Play firing sound and animation (override PlayFiring() in SniperRifle)
    simulated function PlayFiring() {
        PlayOwnedSound( FireSound, SLOT_None, Pawn(Owner).SoundDampening * 3.0 );
        PlayAnim( FireAnims[Rand(5)], fRifleAnimRate, 0.05 );

        if ( ( PlayerPawn(Owner) != None ) && ( PlayerPawn(Owner).DesiredFOV == PlayerPawn(Owner).DefaultFOV ) )
            bMuzzleFlash++;
    }

    defaultproperties
    {
        fRifleAnimRate=6.0   // Custom rifle animation rate multiplier
        PickupAmmoCount=40   // Defined in SniperRifle class Default = 8
    }

### class FastRifle extends SniperRifle;

To get access to its functions and properties, we must subclass the `SniperRifle` class. Our new weapon is now the same as the `SniperRifle`.

### var float fRifleAnimRate;

This is a new variable we create here to store animation rate multiplier. I will talk about it in details in the following sections.

### PlayFiring()

This function is declared in TournamentWeapon, the parent class of the `SniperRifle`.

It is overriden in the `SniperRifle` class of the `Botpack` package:

    simulated function PlayFiring() {
        PlayOwnedSound(FireSound, SLOT_None, Pawn(Owner).SoundDampening*3.0);
        PlayAnim(FireAnims[Rand(5)], 0.5 + 0.5 * FireAdjust, 0.05);

        if ( (PlayerPawn(Owner) != None) && (PlayerPawn(Owner).DesiredFOV == PlayerPawn(Owner).DefaultFOV) )
            bMuzzleFlash++;
    }

Basically, `PlayFiring()` is called when you press the Fire button and it is called again and again as long as you hold the fire button and the current weapon still contains some ammos.

The interesting part here is the `PlayAnim()` function. It is defined in the Actor class:

PlayAnim (name Sequence, optional float Rate, optional float TweenTime)
  Plays an Animation.

Sequence
    Anim sequence Name.
    Rate: Animation Rate multiplier.
    TweenTime: Amount of Time to "tween" into the first frame of this animation sequence if in a different sequence.

This function plays the given Sequence. The Rate parameter is a multiplier. That means the animation will be played Rate times faster than normal. The faster the animation is played, the sooner `PlayFiring()` will be called again. :)

The FireAdjust variable is defined in `TournamentWeapon` and will always be 1.0 if Pawn is not a Bot. Since we don't want the bots to shoot at a different Rate than us, we will get rid of this variable in the animation rate and replace it with 1.0. Then now, 0.5 + 0.5 * 1.0 = 1.0, the default firing rate is 1.0.

So, we need to overrides `PlayFiring()` in order to modify this animation Rate multiplier. The new function will be:

    simulated function PlayFiring() {
        PlayOwnedSound( FireSound, SLOT_None, Pawn(Owner).SoundDampening * 3.0 );
        PlayAnim( FireAnims[Rand(5)], fRifleAnimRate, 0.05 );
        if ( ( PlayerPawn(Owner) != None ) && ( PlayerPawn(Owner).DesiredFOV == PlayerPawn(Owner).DefaultFOV ) )
            bMuzzleFlash++;
    }

The only difference with our new function is the Rate of the `PlayAnim()` function. This was a fixed value of 1.0, and now it is set to our new fRifleAnimRate variable.

### defaultproperties

Here we define a new property and we override an existing one.

fRifleAnimRate
  Modify fRifleAnimRate value to change firing speed.
  I do not recommend setting higher than 30.0. Anyway, number of ammo will be largely insufficient for the firing speed.

SniperRifle
    1.0, Epic Original SniperRifle
    AssaultRifle: 5.0, Zark AssaultRifle
    CyberRifle: 9.0, Ramx CyberRifle

PickupAmmoCount
  Modify the initial number of ammo.
  Since our new weapon is faster than the standard SniperRifle, it would be wise to raise the initial number of ammos the weapon contains when picked up.
  Our weapon uses BulletBox ammo type, that support a `MaxAmmo` count of 50, so setting an initial ammo count higher than 50 would cause some illogical behaviors... excepts if you subclass BulletBox to modify his defaultproperties.

For more weapon properties, see Default Properties For Weapons.

## FastRifleMutator.uc

    class FastRifleMutator extends Mutator;

    // Only allow one instance of this mutator.
    function AddMutator(Mutator M) {
        if ( M != Self )
            Super.AddMutator(M);
    }

    // Do not allow FastRifle to be replaced or removed.
    function bool AlwaysKeep(Actor Other) {
        if( Other.IsA('FastRifle') )
            return true;
        return Super.AlwaysKeep(Other);
    }

    // Replace the default weapon with FastRifle when a player spawn.
    function ModifyPlayer(Pawn Other) {
        DeathMatchPlus(Level.Game).GiveWeapon( Other, "FastRifle.FastRifle" );
        Super.ModifyPlayer(Other);
    }

    // Replace SniperRifle with the FastRifle.
    function bool CheckReplacement(Actor Other, out byte bSuperRelevant) {
        if ( Other.IsA('Weapon') ) {
            if ( Other.IsA('SniperRifle') ) {
                ReplaceWith( Other, "FastRifle.FastRifle" );
                return false;
            }
        }
        return true;
    }

### class FastRifleMutator extends Mutator;

This is added to the mutator list and will be used to replace any `SniperRifle` in the game with our new `FastRifle`.

### AddMutator()

This will prevent this mutator to try adding himself recursively.

### AlwaysKeep()

This will prevent your new weapon to be replaced or removed by another mutator or mod and also avoid to get an endless recursive loop in `CheckReplacement()`, because our new weapon IsA `SniperRifle`.

### ModifyPlayer()

This function allow to init some stuff when the player spawn. We might want to give the `FastRifle` as main weapon when spawning.

This is not recommended behavior, but you can add some way to disable this, like configuration files or such.

### CheckReplacement()

This will Check for the presence of any Actor and allow replacement with `ReplaceWith()`. This is where we will actually replace all original `SniperRifle` in the current game with our new customized `FastRifle`.

## Conclusion

Now compile the package that contains those 2 classes and start a game with this mutator. I'm not sure about network compatibility, i'm new to UnrealScript and need to learn more on replication.

## Related Topics

- UnrealScript Lessons – UnrealScript tutorials
- UnrealScript – UnrealScript reference pages
- Mutator Topics – Topics on mutators
- Creating A New Weapontype – more on weapon creation/modification

## Comments

Ramx: OK, so it should be complete. Please correct me if I am wrong. :)

## Newbie notes (by cla):

The needed .int must be called FastRifle.int, and have only two lines:

      [Public]
      Object=(Name=FastRifle.FastRifleMutator,Class=Class,MetaClass=Engine.Mutator,Description="Fast Rifle Replacement.")

To see this mutator you must be starting a DM or TDM game. By example,It wont be visible starting a CTF game.Thats because the line DeathMatchPlus(Level.Game).GiveWeapon( Other, "FastRifle.FastRifle" );

For the code to work the package must be called FastRifle, thats the same as say 'the .uc files must be under $UTdir\FastRifle\Classes'

If you want to change the package name, say to 'FARifle', then

      put the .uc files under $UTdir\FARifle\Classes
      change all ocurrences of 'FastRifle.FastRifle' to 'FARifle.FastRifle' in the .uc files
      change 'FastRifle.FastRifleMutator' to 'FARifle.FastRifleMutator' in the .int file
      rename the .int file to 'FARifle.int'

Category: Legacy Tutorial

##### Views

- Legacy
- Discussion
- Current revision

##### Search