A random sentence for a random mind.

[ut] Any good tutorials on how TournamentWeapon works?

For questions and discussion about UnrealEd, UnrealScript, and other aspects of Unreal Engine design.

Moderators: Semfry, ividyon

User avatar Draco Nihil
Skaarj Lord Skaarj Lord
Posts: 197
Joined: 06 Jun 2012, 21:18
Location: Independence, Kansas
Contact:

Subject: [ut] Any good tutorials on how TournamentWeapon works?

Post Posted: 26 May 2013, 18:23

Because as opposed to the simplicity of the Weapon class Unreal 1 had... this crap with UT99 is almost mindnumbingly awkward to work with... ESPECIALLY getting stuff to work properly online.

Was this crap all made just to "reduce" bandwidth usage...? I mean really? state ClientFire...? What the hell is all this.....
“I am the dragon without a name...”

User avatar Gizzy
Skaarj Berserker Skaarj Berserker
Posts: 450
Joined: 02 Feb 2010, 12:55

Subject: Re: [ut] Any good tutorials on how TournamentWeapon works?

Post Posted: 27 May 2013, 04:00

This would be incredibly helpful to know too, I'm looking to port some cool new shit to UT, but subclassing TournamentWeapon breaks it entirely. What the hell UT?

User avatar Dr.Flay
Skaarj Lord Skaarj Lord
Posts: 222
Joined: 23 Aug 2012, 06:24
Location: Kernow, UK
Contact:

Subject: Re: [ut] Any good tutorials on how TournamentWeapon works?

Post Posted: 27 May 2013, 07:25

Maybe Feralidragon can help, though Wormbo knows his stuff too.
Both of them are likely to have some good weapon tutorials.

Z-enzyme
White Tusk White Tusk
Posts: 2136
Joined: 13 Nov 2007, 20:01

Subject: Re: [ut] Any good tutorials on how TournamentWeapon works?

Post Posted: 27 May 2013, 11:13

I think I can help you with that. But not this week probably.

User avatar Draco Nihil
Skaarj Lord Skaarj Lord
Posts: 197
Joined: 06 Jun 2012, 21:18
Location: Independence, Kansas
Contact:

Subject: Re: [ut] Any good tutorials on how TournamentWeapon works?

Post Posted: 28 May 2013, 03:57

I have a feeling all this will only ever really work properly with Unreal 1:


Before anyone asks, I want to make it so there is little (at the very most only bot functions are in subclasses) code put into child classes, the weapon can be configured entirely through default properties.

If I'm a total idiot for coming up with this idea then oh well, it's my way and I don't feel like having to copy paste what's effectively "boiler plate" code to child classes just to get weapons that mostly act the same to work.

Code: Select all

//=============================================================================
// GoldenEyeWeapon.
//=============================================================================
class GoldenEyeWeapon expands TournamentWeapon
abstract;

var   travel int     RoundsLeft;       // Current rounds remaining in magazine\clip.
var travel bool    bLastShotFired;    // If the last shot was fired when we reload then don't add a extra round.
var       bool    bUsingScope;      // Are we using a sniper scope?
var travel byte      TracerCount;      // Keeps track of when to fire off a tracer.
var       byte      BurstCounter;      // Keeps track of three shot burst.
var       float    StillTime, StillStart;
var       vector    OwnerLocation;

var() enum EWeaponFireType
{
   TYPE_Semi,                      // Semi automatic fire (you have to press the fire button again after each shot)
   TYPE_Auto,                      // Automatic fire (You can hold the button or press it once for instant three shot burst)
   TYPE_Shotgun,                   // Pump-action Shotgun (Fires a spread of pellets, firing functions like TYPE_Semi)
   TYPE_Melee                      // Melee (Swing a melee weapon)
} WeaponFireType;

var()       float   BaseAccuracy;       // How accurate is the weapon? (higher numbers are worse, affects TYPE_Semi and TYPE_Auto)
var()       float    Recoil;          // How much recoil does the weapon generate? (higher numbers are worse)

var()       float    PelletSpread;      // Size of the cone to spread the pellets around (affects only TYPE_Shotgun)
var()       int      NumPellets;         // How many pellets to fire from a single shot (affects only TYPE_Shotgun)

var()       int       BaseHitDamage;       // How much damage is dealt per shot?
var()       int       RandomHitDamage;    // Random value to tack onto base (optional)
var()      float   MomentumTransfer;   // How powerful do the bullets kick targets back?

var()       bool    bHasScope;         // Does the weapon have a sniper scope?

var()      float   SemiDelay;         // How long to sleep after each semi shot. (Prevent's spam)

var()      bool      bHasTracers;      // Can the weapon fire tracer shots?
var()      byte      TracerDelay;      // How many rounds until a tracer is fired?
var()      bool      bHasWeaponFlash;   // Can the weapon flash the client's screen?

var()      name      FireAnimation;      // Name of the AnimSequence for Firing
var()      name      ReloadAnimation;   // Name of the AnimSequence for Reloading
var()      name      PostReloadAnimation;// Name of the AnimSequence for Post Reloading (i.e. weapons that don't have proper reload animation)
var()      name      IdleAnimation;      // Name of the AnimSequence for Idle

replication
{
   Reliable if ( bNetOwner && (Role == ROLE_Authority) )
      RoundsLeft, WeaponFireType, bLastShotFired;
}

function PreBeginPlay()
{
   Super.PreBeginPlay();

   if( RoundsLeft <= 0 )
   {
      if( ReloadCount > 1 )
         RoundsLeft = ReloadCount-1;
      else
         RoundsLeft = ReloadCount;
   }
}

simulated function PostRender( canvas Canvas )
{
   local PlayerPawn P;
   local float Scale;

   Super.PostRender(Canvas);
   P = PlayerPawn(Owner);
   if ( (P != None) && (P.DesiredFOV != P.DefaultFOV) )
   {
      bOwnsCrossHair = true;
      Scale = Canvas.ClipX/640;
      Canvas.SetPos(0.5 * Canvas.ClipX - 128 * Scale, 0.5 * Canvas.ClipY - 128 * Scale );
      if ( Level.bHighDetailMode )
         Canvas.Style = ERenderStyle.STY_Translucent;
      else
         Canvas.Style = ERenderStyle.STY_Normal;
      Canvas.DrawIcon(Texture'RReticle', Scale);
      Canvas.SetPos(0.5 * Canvas.ClipX + 64 * Scale, 0.5 * Canvas.ClipY + 96 * Scale);
      Canvas.DrawColor.R = 0;
      Canvas.DrawColor.G = 255;
      Canvas.DrawColor.B = 0;
      Scale = P.DefaultFOV/P.DesiredFOV;
      Canvas.DrawText("X"$int(Scale)$"."$int(10 * Scale - 10 * int(Scale)));
   }
   else
      bOwnsCrossHair = false;
}

function GenerateBullet()
{
   PlayOwnedSound(FireSound, SLOT_None, Pawn(Owner).SoundDampening*3.0);

   if ( (PlayerPawn(Owner) != None) && (bHasWeaponFlash) )
      PlayerPawn(Owner).ClientInstantFlash( -0.2, vect(325, 225, 95));

   TraceFire(BaseAccuracy);
}

function GenerateSpray()
{
   local int i;

   NumPellets = Min(1,NumPellets);

   PlayOwnedSound(FireSound, SLOT_None, Pawn(Owner).SoundDampening*3.0);

   if ( (PlayerPawn(Owner) != None) && (bHasWeaponFlash) )
      PlayerPawn(Owner).ClientInstantFlash( -0.2, vect(325, 225, 95));

   for ( i=1; i<NumPellets; i++ )
      TraceFire(PelletSpread);
}

function TraceFire( float Accuracy )
{
   local vector HitLocation, HitNormal, StartTrace, EndTrace, X,Y,Z, AimDir;
   local actor Other;

   Owner.MakeNoise(Pawn(Owner).SoundDampening);
   GetAxes(Pawn(owner).ViewRotation,X,Y,Z);
   StartTrace = Owner.Location + CalcDrawOffset() + FireOffset.Y * Y + FireOffset.Z * Z;
   AdjustedAim = pawn(owner).AdjustAim(1000000, StartTrace, 2.75*AimError, False, False);   
   EndTrace = StartTrace + Accuracy * (FRand() - 0.5 )* Y * 1000
      + Accuracy * (FRand() - 0.5 ) * Z * 1000;
   AimDir = vector(AdjustedAim);
   EndTrace += (10000 * AimDir);
   Other = Pawn(Owner).TraceShot(HitLocation,HitNormal,EndTrace,StartTrace);

   if( bHasTracers )
   {
      TracerCount++;
      if ( TracerCount >= TracerDelay )
      {
         TracerCount = 0;
         if ( VSize(HitLocation - StartTrace) > 250 )
            Spawn(class'MTracer',,, StartTrace + 96 * AimDir,rotator(EndTrace - StartTrace));
      }
   }

   ProcessTraceHit(Other, HitLocation, HitNormal, vector(AdjustedAim),Y,Z);
}

function MeleeTrace()
{
   local vector HitLocation, HitNormal, StartTrace, EndTrace, X,Y,Z, AimDir;
   local actor Other;

   Owner.MakeNoise(Pawn(Owner).SoundDampening);
   GetAxes(Pawn(owner).ViewRotation,X,Y,Z);
   StartTrace = Owner.Location;
   AdjustedAim = pawn(owner).AdjustAim(1000000, StartTrace, 2.75*AimError, False, False);   
   EndTrace = StartTrace * Z * 30;
   AimDir = vector(AdjustedAim);
   EndTrace += (30 * AimDir);
   Other = Pawn(Owner).TraceShot(HitLocation,HitNormal,EndTrace,StartTrace);
   ProcessMeleeHit(Other, HitLocation, HitNormal, vector(AdjustedAim),Y,Z);
}

function ProcessTraceHit(Actor Other, Vector HitLocation, Vector HitNormal, Vector X, Vector Y, Vector Z)
{
   local int ActualDamage;

   BaseHitDamage = Min(1,BaseHitDamage); //Must deal atleast *SOME* damage...

   if( RandomHitDamage > 0 )
      ActualDamage =  BaseHitDamage + Rand(RandomHitDamage);
   else
      ActualDamage = BaseHitDamage;

   if ( FRand() < 0.2 )
      X *= 2.5;

   if ( ((Other == Level) || (!Other.bIsPawn)) && (!Other.IsA('Carcass')) )
   {
      Spawn(class'UT_LightWallHitEffect',,, HitLocation+HitNormal, Rotator(HitNormal));
      Other.TakeDamage(ActualDamage, Pawn(Owner), HitLocation, ActualDamage*MomentumTransfer*X, MyDamageType);
   }
   else if ( (Other!=self) && (Other!=Owner) && (Other != None) )
   {
      Other.PlaySound(Sound 'ChunkHit',, 4.0,,100);

      if ( Other.IsA('Bot') && (FRand() < 0.2) )
         Pawn(Other).WarnTarget(Pawn(Owner), 500, X);

      Other.TakeDamage(ActualDamage, Pawn(Owner), HitLocation, ActualDamage*MomentumTransfer*X, MyDamageType);
   }
}

function ProcessMeleeHit(Actor Other, Vector HitLocation, Vector HitNormal, Vector X, Vector Y, Vector Z)
{
   local int ActualDamage;

   BaseHitDamage = Min(1,BaseHitDamage); //Must deal atleast *SOME* damage...

   if( RandomHitDamage > 0 )
      ActualDamage =  BaseHitDamage + Rand(RandomHitDamage);
   else
      ActualDamage = BaseHitDamage;

   if ( ((Other == Level) || (!Other.bIsPawn)) && (!Other.IsA('Carcass')) )
   {
      PlayOwnedSound(Sound'BladeHit', SLOT_None, Pawn(Owner).SoundDampening);
      Spawn(class'UT_SpriteSmokePuff',,, HitLocation+HitNormal, Rotator(HitNormal));
      Other.TakeDamage(ActualDamage, Pawn(Owner), HitLocation, ActualDamage*MomentumTransfer*X, MyDamageType);
   }
   else if ( (Other!=self) && (Other!=Owner) && (Other != None) )
   {
      Other.PlaySound(Sound 'BladeThunk',, 4.0,,100);
      Other.TakeDamage(ActualDamage, Pawn(Owner), HitLocation, ActualDamage*MomentumTransfer*X, MyDamageType);
   }
}

function Timer()
{
   local actor targ;
   local float bestAim, bestDist;
   local vector FireDir;
   local Pawn P;

   bestAim = 0.95;
   P = Pawn(Owner);
   if ( P == None )
   {
      GotoState('');
      return;
   }
   if ( VSize(P.Location - OwnerLocation) < 6 )
      StillTime += FMin(2.0, Level.TimeSeconds - StillStart);

   else
      StillTime = 0;
   StillStart = Level.TimeSeconds;
   OwnerLocation = P.Location;
   FireDir = vector(P.ViewRotation);
   targ = P.PickTarget(bestAim, bestDist, FireDir, Owner.Location);
   if ( Pawn(targ) != None )
   {
      SetTimer(1 + 4 * FRand(), false);
      bPointing = true;
      Pawn(targ).WarnTarget(P, 200, FireDir);
   }
   else
   {
      SetTimer(0.4 + 1.6 * FRand(), false);
      if ( (P.bFire == 0) && (P.bAltFire == 0) )
         bPointing = false;
   }
}

simulated function PlayReload()
{
   PlayAnim(ReloadAnimation,1.0, 0.05);
}

simulated function PlayPump()
{
   PlayAnim('Reload',1.0, 0.05);
}

simulated function PlayPostReload()
{
   if( (PostReloadAnimation == '') || (PostReloadAnimation == 'None') )
      return;

   PlayAnim(PostReloadAnimation,1.0, 0.05);
}

simulated function PlayCocking()
{
   PlayOwnedSound(CockingSound, SLOT_None, Pawn(Owner).SoundDampening);
}

simulated function PlayClipOut()
{
   PlayOwnedSound(Misc1Sound, SLOT_None, Pawn(Owner).SoundDampening);
}

simulated function PlayClipIn()
{
   PlayOwnedSound(Misc2Sound, SLOT_None, Pawn(Owner).SoundDampening);
}

simulated function PlayFiring()
{
   if( WeaponFireType != TYPE_Auto )
      PlayAnim(FireAnimation,1.0, 0.05);
   else
      LoopAnim(FireAnimation,1.0, 0.05);

   if( WeaponFireType == TYPE_Melee )
      PlayOwnedSound(FireSound, SLOT_None, Pawn(Owner).SoundDampening);

   if ( (PlayerPawn(Owner) != None) && (bHasWeaponFlash) && (WeaponFireType != TYPE_Melee) )
      bMuzzleFlash++;
}

///////////////////////////////////////////////////////
state NormalFire
{
ignores Fire, AltFire, AnimEnd;

Begin:
   BurstCounter = 0;

   if( (RoundsLeft <= 0) && (WeaponFireType != TYPE_Melee) )
      GoToState('Reloading');

   if( WeaponFireType == TYPE_Semi )
      GoTo('SemiFire');
   else if( WeaponFireType == TYPE_Auto )
      GoTo('AutoFire');
   else if( WeaponFireType == TYPE_Shotgun )
      GoTo('ShotFire');
   else if( WeaponFireType == TYPE_Melee )
      GoTo('Melee');
   else
   {
      Sleep(0.0);
      Finish();
   }

SemiFire:
   if( AmmoType.UseAmmo(1) )
   {
      RoundsLeft--;
      bLastShotFired = RoundsLeft<=0;
      GenerateBullet();
      PlayFiring();
      Sleep(SemiDelay);
      GoTo('HoldFire');
   }

AutoFire:
   while ( BurstCounter < 3 )
   {
      BurstCounter++;
      if( AmmoType.UseAmmo(1) )
      {
         RoundsLeft--;
         bLastShotFired = RoundsLeft<=0;
         GenerateBullet();
         Sleep(FiringSpeed);

         if( (AmmoType.AmmoAmount > 0) && (RoundsLeft <= 0) )
         {
            PlayIdleAnim();
            GoToState('Reloading');
            break;
         }

         GoTo('AutoFire');
      }
      else
      {
         PlayIdleAnim();
         Finish();
         break;
      }
   }
   if( Pawn(Owner).bFire != 0 )
      GoTo('RepeatFire');
   else
   {
      PlayIdleAnim();
      Finish();
   }

ShotFire:
   if( AmmoType.UseAmmo(1) )
   {
      RoundsLeft--;
      bLastShotFired = RoundsLeft<=0;
      GenerateSpray();
      PlayFiring();
      FinishAnim();

      if( !bLastShotFired )
      {
         PlayPump();
         FinishAnim();
         PlayIdleAnim();
      }

      Sleep(SemiDelay);
      GoTo('HoldFire');
   }

Melee:
   MeleeTrace();
   FinishAnim();
   Finish();

HoldFire:
   if( (RoundsLeft <= 0) && (AmmoType.AmmoAmount > 0) )
   {
      FinishAnim();
      PlayIdleAnim();
      Sleep(SemiDelay);
      GoToState('Reloading');
   }
   if( Pawn(Owner).bFire != 0 )
   {
      Sleep(SemiDelay);
      GoTo('HoldFire');
   }
   else
   {
      FinishAnim();
      Finish();
   }

RepeatFire:
   if( (RoundsLeft <= 0) && (AmmoType.AmmoAmount > 0) )
   {
      PlayIdleAnim();
      Sleep(FiringSpeed);
      GoToState('Reloading');
   }
   else if( (Pawn(Owner).bFire != 0) && (AmmoType.UseAmmo(1)) )
   {
      RoundsLeft--;
      bLastShotFired = RoundsLeft<=0;
      GenerateBullet();
      Sleep(FiringSpeed);
      GoTo('RepeatFire');
   }
   else
   {
      PlayIdleAnim();
      Finish();
   }
}

////////////////////////////////////////////////////////
state AltFiring
{
ignores Fire, AltFire, AnimEnd;

Begin:
   if( (PlayerPawn(Owner) == None) || (!bHasScope) )
      GoToState('Reload');
   else
   {
      Sleep(0.25);
      if( Pawn(Owner).bAltFire != 0 )
         GoToState('Zooming');
      else
         GoToState('Reload');
   }
}

state Active
{
   ignores animend;

   function ForceFire()
   {
      bForceFire = true;
   }

   function ForceAltFire()
   {
      bForceAltFire = true;
   }

   function EndState()
   {
      Super.EndState();
      bForceFire = false;
      bForceAltFire = false;
   }

Begin:
   FinishAnim();
   if ( bChangeWeapon )
      GotoState('DownWeapon');
   bWeaponUp = True;
   PlayPostSelect();
   FinishAnim();
   bCanClientFire = true;
   
   if ( (Level.Netmode != NM_Standalone) && Owner.IsA('TournamentPlayer')
      && (PlayerPawn(Owner).Player != None)
      && !PlayerPawn(Owner).Player.IsA('ViewPort') )
   {
      if ( bForceFire || (Pawn(Owner).bFire != 0) )
         TournamentPlayer(Owner).SendFire(self);
      else if ( bForceAltFire || (Pawn(Owner).bAltFire != 0) )
         TournamentPlayer(Owner).SendAltFire(self);
      else if ( !bChangeWeapon )
         TournamentPlayer(Owner).UpdateRealWeapon(self);
   }
   Finish();
}


////////////////////////////////////////////////////////
state Reload
{
   ignores Fire, AltFire, ForceClientFire, ForceClientAltFire, ClientFire, ClientAltFire, AnimEnd;

   function EndState()
   {
      if( bLastShotFired )
         RoundsLeft = ReloadCount-1;
      else
         RoundsLeft = ReloadCount;
   }

Begin:
   FinishAnim();

   if( WeaponFireType == TYPE_Shotgun )
   {
      while( RoundsLeft < ReloadCount )
      {
         PlayClipIn();
         RoundsLeft++;
         Sleep(0.1);
      }
   }

   if( (PostReloadAnimation != '') && (PostReloadAnimation != 'None') )
   {
      PlayPostReload();
      FinishAnim();
   }

   if( (WeaponFireType == TYPE_Shotgun) && (bLastShotFired) )
   {
      PlayPump();
      FinishAnim();
   }

   Finish();
}

state Zooming
{
   simulated function Tick(float DeltaTime)
   {
      if ( Pawn(Owner).bAltFire == 0 )
      {
         if ( (PlayerPawn(Owner) != None) && PlayerPawn(Owner).Player.IsA('ViewPort') )
            PlayerPawn(Owner).StopZoom();
         SetTimer(0.0,False);
         GoToState('Idle');
      }
   }

   simulated function BeginState()
   {
      if ( Owner.IsA('PlayerPawn') )
      {
         if ( PlayerPawn(Owner).Player.IsA('ViewPort') )
            PlayerPawn(Owner).ToggleZoom();
         SetTimer(0.2,True);
      }
      else
      {
         Pawn(Owner).bFire = 1;
         Pawn(Owner).bAltFire = 0;
         Global.Fire(0);
      }
   }
}

defaultproperties
{
     SelectSound=Sound'uGoldenEye.Generic.PickupSelect'
     PickupSound=Sound'uGoldenEye.Generic.PickupSelect'
}
“I am the dragon without a name...”


Who is online

Users browsing this forum: No registered users and 38 guests

Copyright © 2001-2024 UnrealSP.org

Powered by phpBB® Forum Software © phpBB Limited