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.....
[ut] Any good tutorials on how TournamentWeapon works?
5 posts •
Page 1 of 1
- Draco Nihil
- 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
“I am the dragon without a name...”
- Gizzy
- 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?
- Dr.Flay
- 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.
Both of them are likely to have some good weapon tutorials.
- Z-enzyme
- 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.
- Draco Nihil
- 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.
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...”
5 posts •
Page 1 of 1
Who is online
Users browsing this forum: No registered users and 38 guests