Engine
Class Weapon

source: e:\games\UnrealTournament\Engine\Classes\Weapon.uc
Core.Object
   |
   +--Engine.Actor
      |
      +--Engine.Inventory
         |
         +--Engine.Weapon
Direct Known Subclasses:TournamentWeapon, MovieHead, FlakCannon, GESBioRifle, Minigun, QuadShot, RazorJack, Rifle, ASMD, AutoMag, DispersionPistol, Eightball, Stinger

class Weapon
extends Engine.Inventory

//============================================================================= // Parent class of all weapons. //=============================================================================
Variables
 Rotator AdjustedAim
           used when drawing name on HUD
 name AltDamageType
           Offset from drawing location for projectile/trace start
 sound AltFireSound
           Offset from drawing location for projectile/trace start
 class AltProjectileClass
           Offset from drawing location for projectile/trace start
 class AmmoName
           Type of ammo used.
 Ammo AmmoType
           Inventory Ammo being used.
 sound CockingSound
           Offset from drawing location for projectile/trace start
 string DeathMessage
           Offset from drawing location for projectile/trace start
 vector FireOffset
           Offset from drawing location for projectile/trace start
 sound FireSound
           Offset from drawing location for projectile/trace start
 float FiringSpeed
           used by human animations in determining firing speed
 float FlashTime
           used when drawing name on HUD
 float MaxTargetRange
           Maximum distance to target.
 string MessageNoAmmo
           Offset from drawing location for projectile/trace start
 sound Misc1Sound
           Offset from drawing location for projectile/trace start
 sound Misc2Sound
           Offset from drawing location for projectile/trace start
 sound Misc3Sound
           Offset from drawing location for projectile/trace start
 name MyDamageType
           Offset from drawing location for projectile/trace start
 Color NameColor
           used when drawing name on HUD
 int PickupAmmoCount
           Amount of ammo initially in pick-up item.
 class ProjectileClass
           Offset from drawing location for projectile/trace start
 byte ReloadCount
           Amount of ammo depletion before reloading. 0 if no reloading is done.
 sound SelectSound
           Offset from drawing location for projectile/trace start
 float ShakeMag
           Offset from drawing location for projectile/trace start
 float ShakeTime
           Offset from drawing location for projectile/trace start
 float ShakeVert
           Offset from drawing location for projectile/trace start
 bool bAltInstantHit
           If true, instant hit rather than projectile firing weapon for AltFire
 bool bCanThrow
           if true, player can toss this weapon out
 bool bChangeWeapon
           Used in Active State
 bool bInstantHit
           If true, instant hit rather than projectile firing weapon
 bool bLockedOn
           Used in Active State
 byte bMuzzleFlash
           used when drawing name on HUD
 bool bOwnsCrosshair
           this weapon is responsible for drawing its own crosshair (in its postrender function)
 bool bRapidFire
           used by human animations in determining firing animation (for still firing)
 bool bSetFlashTime
           used when drawing name on HUD
 bool bWeaponStay
           if true, player can toss this weapon out
 bool bWeaponUp
           Used in Active State

States
DownWeapon, Active, Idle, AltFiring, NormalFire

Function Summary
 void AltFire(float Value)
 void BecomePickup()
     
// Become a pickup
 void CheckVisibility()
     
//**************************************************************************************
//
// Firing functions and states
//
 bool ClientAltFire(float Value)
 bool ClientFire(float Value)
 void ClientWeaponEvent(name EventType)
 void Destroyed()
 void DropFrom(vector StartLocation)
     
// Toss this weapon out
 void Finish()
     
// Finish a firing sequence
 void Fire(float Value)
 void ForceAltFire()
 void ForceFire()
 void GiveAmmo(Pawn Other)
 bool HandlePickupQuery(Inventory Item)
 
simulated
PlayAltFiring()
 
simulated
PlayFiring()
 void PostBeginPlay()
     
//-------------------------------------------------------
// AI related functions
 
simulated
PostRender(Canvas Canvas)
 
simulated
PreRender(Canvas Canvas)
     
//-------------------------------------------------------
 void ProcessTraceHit(Actor Other, Vector HitLocation, Vector HitNormal, Vector X, Vector Y, Vector Z)
 float RateSelf(out int)
 Weapon RecommendWeapon(out float, out int)
 void SetSwitchPriority(Pawn Other)
 void SetWeaponStay()
 Inventory SpawnCopy(Pawn Other)
     
// Either give this inventory to player Other, or spawn a copy
// and give it to the player Other, setting up original to be respawned.
// Also add Ammo to Other's inventory if it doesn't already exist
//
 bool SplashJump()
 float SuggestAttackStyle()
     
// return delta to combat style
 float SuggestDefenseStyle()
 float SwitchPriority()
     
// Return the switch priority of the weapon (normally AutoSwitchPriority, but may be
// modified by environment (or by other factors for bots)
 void TraceFire(float Accuracy)
 
simulated
TweenToStill()
 Weapon WeaponChange(byte F)
     
//
// Change weapon to that specificed by F matching inventory weapon's Inventory Group.
 bool WeaponSet(Pawn Other)
     
// Compare self to current weapon.  If better than current weapon, then switch
 void setHand(float Hand)
     
// set which hand is holding weapon


State DownWeapon Function Summary
 void PlayIdleAnim()
 void PlayPostSelect()
 void PlaySelect()
 void TweenSelect()
 void TweenDown()
 bool PutDown()
 void RaiseUp(Weapon OldWeapon)
 void BringUp()
 void BeginState()
 bool PutDown()


State Active Function Summary
 void BeginState()
 bool PutDown()
 void AltFire(float F)
 void Fire(float F)


State Idle Function Summary
 bool PutDown()
 void AnimEnd()


State AltFiring Function Summary
 void AltFire(float F)
 void Fire(float F)


State NormalFire Function Summary
 void AltFire(float F)
 void Fire(float F)



Source Code


00001	//=============================================================================
00002	// Parent class of all weapons.
00003	//=============================================================================
00004	class Weapon extends Inventory
00005		abstract
00006		native
00007		nativereplication;
00008	
00009	#exec Texture Import File=Textures\Weapon.pcx Name=S_Weapon Mips=Off Flags=2
00010	
00011	//-----------------------------------------------------------------------------
00012	// Weapon ammo/firing information:
00013	// Two-element arrays here are defined for normal fire (0) and alt fire (1).
00014	var() float   MaxTargetRange;    // Maximum distance to target.
00015	var() class<ammo> AmmoName;          // Type of ammo used.
00016	var() byte    ReloadCount;       // Amount of ammo depletion before reloading. 0 if no reloading is done.
00017	var() int     PickupAmmoCount;   // Amount of ammo initially in pick-up item.
00018	var travel ammo	AmmoType;		 // Inventory Ammo being used.
00019	var	  bool	  bPointing;		 // Indicates weapon is being pointed
00020	var() bool	  bInstantHit;		 // If true, instant hit rather than projectile firing weapon
00021	var() bool	  bAltInstantHit;	 // If true, instant hit rather than projectile firing weapon for AltFire
00022	var(WeaponAI) bool	  bWarnTarget;		 // When firing projectile, warn the target
00023	var(WeaponAI) bool	  bAltWarnTarget;	 // When firing alternate projectile, warn the target
00024	var   bool	  bWeaponUp;		 // Used in Active State
00025	var   bool	  bChangeWeapon;	 // Used in Active State
00026	var   bool 	  bLockedOn;
00027	var(WeaponAI) bool	  bSplashDamage;	 // used by bot AI
00028	var()		  bool	  bCanThrow;	//if true, player can toss this weapon out
00029	var(WeaponAI) bool	  bRecommendSplashDamage; //if true, bot preferentially tries to use splash damage
00030												  // rather than direct hits
00031	var(WeaponAI) bool	  bRecommendAltSplashDamage; //if true, bot preferentially tries to use splash damage
00032												  // rather than direct hits
00033	var() bool	  bWeaponStay;
00034	var() bool	  bOwnsCrosshair;	// this weapon is responsible for drawing its own crosshair (in its postrender function)
00035	var	  bool	  bHideWeapon;		// if true, weapon is not rendered
00036	var(WeaponAI) bool	  bMeleeWeapon; //Weapon is only a melee weapon
00037	var() bool	  bRapidFire;		// used by human animations in determining firing animation (for still firing)
00038	var	  bool	  bSpecialIcon;
00039	
00040	var() float	  FiringSpeed;		// used by human animations in determining firing speed
00041	
00042	var()   vector	FireOffset;		 // Offset from drawing location for projectile/trace start
00043	var()   class<projectile> ProjectileClass;
00044	var()   class<projectile> AltProjectileClass;
00045	var()	name MyDamageType;
00046	var()	name AltDamageType;
00047	var		float	ProjectileSpeed;
00048	var		float	AltProjectileSpeed;
00049	var		float	AimError;		// Aim Error for bots (note this value doubled if instant hit weapon)
00050	var()	float	ShakeMag;
00051	var()	float	ShakeTime;
00052	var()	float   ShakeVert;
00053	var(WeaponAI)	float	AIRating;
00054	var(WeaponAI)	float	RefireRate;
00055	var(WeaponAI)	float	AltRefireRate;
00056	
00057	//-----------------------------------------------------------------------------
00058	// Sound Assignments
00059	var() sound 	FireSound;
00060	var() sound 	AltFireSound;
00061	var() sound 	CockingSound;
00062	var() sound 	SelectSound;
00063	var() sound 	Misc1Sound;
00064	var() sound 	Misc2Sound;
00065	var() sound 	Misc3Sound;
00066	
00067	var() Localized string MessageNoAmmo;
00068	var() Localized string DeathMessage;
00069	var() Color NameColor;	// used when drawing name on HUD
00070	
00071	var Rotator AdjustedAim;
00072	
00073	//-----------------------------------------------------------------------------
00074	// Muzzle Flash
00075	// weapon is responsible for setting and clearing bMuzzleFlash whenever it wants the
00076	// MFTexture drawn on the canvas (see RenderOverlays() )
00077	var bool bSetFlashTime;
00078	var(MuzzleFlash) bool bDrawMuzzleFlash;
00079	var byte bMuzzleFlash;
00080	var float FlashTime;
00081	var(MuzzleFlash) float MuzzleScale, FlashY, FlashO, FlashC, FlashLength;
00082	var(MuzzleFlash) int FlashS;	// size of (square) texture/2
00083	var(MuzzleFlash) texture MFTexture;
00084	var(MuzzleFlash) texture MuzzleFlare;
00085	var(MuzzleFlash) float FlareOffset; 
00086	
00087	// Network replication
00088	//
00089	replication
00090	{
00091		// Things the server should send to the client.
00092		reliable if( bNetOwner && (Role==ROLE_Authority) )
00093			AmmoType, bLockedOn, bHideWeapon;
00094	}
00095	
00096	//=============================================================================
00097	// Inventory travelling across servers.
00098	
00099	event TravelPostAccept()
00100	{
00101		Super.TravelPostAccept();
00102		if ( Pawn(Owner) == None )
00103			return;
00104		if ( AmmoName != None )
00105		{
00106			AmmoType = Ammo(Pawn(Owner).FindInventoryType(AmmoName));
00107			if ( AmmoType == None )
00108			{		
00109				AmmoType = Spawn(AmmoName);	// Create ammo type required		
00110				Pawn(Owner).AddInventory(AmmoType);		// and add to player's inventory
00111				AmmoType.BecomeItem();
00112				AmmoType.AmmoAmount = PickUpAmmoCount; 
00113				AmmoType.GotoState('Idle2');
00114			}
00115		}
00116		if ( self == Pawn(Owner).Weapon )
00117			BringUp();
00118		else GoToState('Idle2');
00119	}
00120	
00121	function Destroyed()
00122	{
00123		Super.Destroyed();
00124		if( (Pawn(Owner)!=None) && (Pawn(Owner).Weapon == self) )
00125			Pawn(Owner).Weapon = None;
00126	}
00127	
00128	//=============================================================================
00129	// Weapon rendering
00130	// Draw first person view of inventory
00131	simulated event RenderOverlays( canvas Canvas )
00132	{
00133		local rotator NewRot;
00134		local bool bPlayerOwner;
00135		local int Hand;
00136		local PlayerPawn PlayerOwner;
00137	
00138		if ( bHideWeapon || (Owner == None) )
00139			return;
00140	
00141		PlayerOwner = PlayerPawn(Owner);
00142	
00143		if ( PlayerOwner != None )
00144		{
00145			if ( PlayerOwner.DesiredFOV != PlayerOwner.DefaultFOV )
00146				return;
00147			bPlayerOwner = true;
00148			Hand = PlayerOwner.Handedness;
00149	
00150			if (  (Level.NetMode == NM_Client) && (Hand == 2) )
00151			{
00152				bHideWeapon = true;
00153				return;
00154			}
00155		}
00156	
00157		if ( !bPlayerOwner || (PlayerOwner.Player == None) )
00158			Pawn(Owner).WalkBob = vect(0,0,0);
00159	
00160		if ( (bMuzzleFlash > 0) && bDrawMuzzleFlash && Level.bHighDetailMode && (MFTexture != None) )
00161		{
00162			MuzzleScale = Default.MuzzleScale * Canvas.ClipX/640.0;
00163			if ( !bSetFlashTime )
00164			{
00165				bSetFlashTime = true;
00166				FlashTime = Level.TimeSeconds + FlashLength;
00167			}
00168			else if ( FlashTime < Level.TimeSeconds )
00169				bMuzzleFlash = 0;
00170			if ( bMuzzleFlash > 0 )
00171			{
00172				if ( Hand == 0 )
00173					Canvas.SetPos(Canvas.ClipX/2 - 0.5 * MuzzleScale * FlashS + Canvas.ClipX * (-0.2 * Default.FireOffset.Y * FlashO), Canvas.ClipY/2 - 0.5 * MuzzleScale * FlashS + Canvas.ClipY * (FlashY + FlashC));
00174				else
00175					Canvas.SetPos(Canvas.ClipX/2 - 0.5 * MuzzleScale * FlashS + Canvas.ClipX * (Hand * Default.FireOffset.Y * FlashO), Canvas.ClipY/2 - 0.5 * MuzzleScale * FlashS + Canvas.ClipY * FlashY);
00176	
00177				Canvas.Style = 3;
00178				Canvas.DrawIcon(MFTexture, MuzzleScale);
00179				Canvas.Style = 1;
00180			}
00181		}
00182		else
00183			bSetFlashTime = false;
00184	
00185		SetLocation( Owner.Location + CalcDrawOffset() );
00186		NewRot = Pawn(Owner).ViewRotation;
00187	
00188		if ( Hand == 0 )
00189			newRot.Roll = -2 * Default.Rotation.Roll;
00190		else
00191			newRot.Roll = Default.Rotation.Roll * Hand;
00192	
00193		setRotation(newRot);
00194		Canvas.DrawActor(self, false);
00195	}
00196	
00197	//-------------------------------------------------------
00198	// AI related functions
00199	
00200	function PostBeginPlay()
00201	{
00202		Super.PostBeginPlay();
00203		SetWeaponStay();
00204		MaxDesireability = 1.2 * AIRating;
00205		if ( ProjectileClass != None )
00206		{
00207			ProjectileSpeed = ProjectileClass.Default.Speed;
00208			MyDamageType = ProjectileClass.Default.MyDamageType;
00209		}
00210		if ( AltProjectileClass != None )
00211		{
00212			AltProjectileSpeed = AltProjectileClass.Default.Speed;
00213			AltDamageType = AltProjectileClass.Default.MyDamageType;
00214		}
00215	}
00216	
00217	function bool SplashJump()
00218	{
00219		return false;
00220	}
00221	
00222	function SetWeaponStay()
00223	{
00224		bWeaponStay = bWeaponStay || Level.Game.bCoopWeaponMode;
00225	}
00226	
00227	// tell the bot how much it wants this weapon
00228	// called when the bot is trying to decide which inventory item to go after next
00229	event float BotDesireability(Pawn Bot)
00230	{
00231		local Weapon AlreadyHas;
00232		local float desire;
00233	
00234		// bots adjust their desire for their favorite weapons
00235		desire = MaxDesireability + Bot.AdjustDesireFor(self);
00236	
00237		// see if bot already has a weapon of this type
00238		AlreadyHas = Weapon(Bot.FindInventoryType(class)); 
00239		if ( AlreadyHas != None )
00240		{
00241			if ( (RespawnTime < 10) 
00242				&& ( bHidden || (AlreadyHas.AmmoType == None) 
00243					|| (AlreadyHas.AmmoType.AmmoAmount < AlreadyHas.AmmoType.MaxAmmo)) )
00244				return 0;
00245	
00246			// can't pick it up if weapon stay is on
00247			if ( (!bHeldItem || bTossedOut) && bWeaponStay )
00248				return 0;
00249			if ( AlreadyHas.AmmoType == None )
00250				return 0.25 * desire;
00251	
00252			// bot wants this weapon for the ammo it holds
00253			if ( AlreadyHas.AmmoType.AmmoAmount > 0 )
00254				return FMax( 0.25 * desire, 
00255						AlreadyHas.AmmoType.MaxDesireability
00256						 * FMin(1, 0.15 * AlreadyHas.AmmoType.MaxAmmo/AlreadyHas.AmmoType.AmmoAmount) ); 
00257			else
00258				return 0.05;
00259		}
00260		
00261		// incentivize bot to get this weapon if it doesn't have a good weapon already
00262		if ( (Bot.Weapon == None) || (Bot.Weapon.AIRating <= 0.4) )
00263			return 2*desire;
00264	
00265		return desire;
00266	}
00267	
00268	function float RateSelf( out int bUseAltMode )
00269	{
00270		if ( (AmmoType != None) && (AmmoType.AmmoAmount <=0) )
00271			return -2;
00272		bUseAltMode = int(FRand() < 0.4);
00273		return (AIRating + FRand() * 0.05);
00274	}
00275	
00276	// return delta to combat style
00277	function float SuggestAttackStyle()
00278	{
00279		return 0.0;
00280	}
00281	
00282	function float SuggestDefenseStyle()
00283	{
00284		return 0.0;
00285	}
00286	
00287	//-------------------------------------------------------
00288	
00289	simulated function PreRender( canvas Canvas );
00290	simulated function PostRender( canvas Canvas );
00291	
00292	function ClientWeaponEvent(name EventType);
00293	
00294	function bool HandlePickupQuery( inventory Item )
00295	{
00296		local int OldAmmo;
00297		local Pawn P;
00298	
00299		if (Item.Class == Class)
00300		{
00301			if ( Weapon(item).bWeaponStay && (!Weapon(item).bHeldItem || Weapon(item).bTossedOut) )
00302				return true;
00303			P = Pawn(Owner);
00304			if ( AmmoType != None )
00305			{
00306				OldAmmo = AmmoType.AmmoAmount;
00307				if ( AmmoType.AddAmmo(Weapon(Item).PickupAmmoCount) && (OldAmmo == 0) 
00308					&& (P.Weapon.class != item.class) && !P.bNeverSwitchOnPickup )
00309						WeaponSet(P);
00310			}
00311			if (Level.Game.LocalLog != None)
00312				Level.Game.LocalLog.LogPickup(Item, Pawn(Owner));
00313			if (Level.Game.WorldLog != None)
00314				Level.Game.WorldLog.LogPickup(Item, Pawn(Owner));
00315			if (Item.PickupMessageClass == None)
00316				P.ClientMessage(Item.PickupMessage, 'Pickup');
00317			else
00318				P.ReceiveLocalizedMessage( Item.PickupMessageClass, 0, None, None, item.Class );
00319			Item.PlaySound(Item.PickupSound);
00320			Item.SetRespawn();   
00321			return true;
00322		}
00323		if ( Inventory == None )
00324			return false;
00325	
00326		return Inventory.HandlePickupQuery(Item);
00327	}
00328	
00329	// set which hand is holding weapon
00330	function setHand(float Hand)
00331	{
00332		if ( Hand == 2 )
00333		{
00334			PlayerViewOffset.Y = 0;
00335			FireOffset.Y = 0;
00336			bHideWeapon = true;
00337			return;
00338		}
00339		else
00340			bHideWeapon = false;
00341	
00342		if ( Hand == 0 )
00343		{
00344			PlayerViewOffset.X = Default.PlayerViewOffset.X * 0.88;
00345			PlayerViewOffset.Y = -0.2 * Default.PlayerViewOffset.Y;
00346			PlayerViewOffset.Z = Default.PlayerViewOffset.Z * 1.12;
00347		}
00348		else
00349		{
00350			PlayerViewOffset.X = Default.PlayerViewOffset.X;
00351			PlayerViewOffset.Y = Default.PlayerViewOffset.Y * Hand;
00352			PlayerViewOffset.Z = Default.PlayerViewOffset.Z;
00353		}
00354		PlayerViewOffset *= 100; //scale since network passes vector components as ints
00355		FireOffset.Y = Default.FireOffset.Y * Hand;
00356	}
00357	
00358	//
00359	// Change weapon to that specificed by F matching inventory weapon's Inventory Group.
00360	function Weapon WeaponChange( byte F )
00361	{	
00362		local Weapon newWeapon;
00363		 
00364		if ( InventoryGroup == F )
00365		{
00366			if ( (AmmoType != None) && (AmmoType.AmmoAmount <= 0) )
00367			{
00368				if ( Inventory == None )
00369					newWeapon = None;
00370				else
00371					newWeapon = Inventory.WeaponChange(F);
00372				if ( newWeapon == None )
00373					Pawn(Owner).ClientMessage( ItemName$MessageNoAmmo );		
00374				return newWeapon;
00375			}		
00376			else 
00377				return self;
00378		}
00379		else if ( Inventory == None )
00380			return None;
00381		else
00382			return Inventory.WeaponChange(F);
00383	}
00384	
00385	// Either give this inventory to player Other, or spawn a copy
00386	// and give it to the player Other, setting up original to be respawned.
00387	// Also add Ammo to Other's inventory if it doesn't already exist
00388	//
00389	function inventory SpawnCopy( pawn Other )
00390	{
00391		local inventory Copy;
00392		local Weapon newWeapon;
00393	
00394		if( Level.Game.ShouldRespawn(self) )
00395		{
00396			Copy = spawn(Class,Other,,,rot(0,0,0));
00397			Copy.Tag           = Tag;
00398			Copy.Event         = Event;
00399			if ( !bWeaponStay )
00400				GotoState('Sleeping');
00401		}
00402		else
00403			Copy = self;
00404	
00405		Copy.RespawnTime = 0.0;
00406		Copy.bHeldItem = true;
00407		Copy.bTossedOut = false;
00408		Copy.GiveTo( Other );
00409		newWeapon = Weapon(Copy);
00410		newWeapon.Instigator = Other;
00411		newWeapon.GiveAmmo(Other);
00412		newWeapon.SetSwitchPriority(Other);
00413		if ( !Other.bNeverSwitchOnPickup )
00414			newWeapon.WeaponSet(Other);
00415		newWeapon.AmbientGlow = 0;
00416		return newWeapon;
00417	}
00418	
00419	function SetSwitchPriority(pawn Other)
00420	{
00421		local int i;
00422		local name temp, carried;
00423	
00424		if ( PlayerPawn(Other) != None )
00425		{
00426			for ( i=0; i<ArrayCount(PlayerPawn(Other).WeaponPriority); i++)
00427				if ( PlayerPawn(Other).WeaponPriority[i] == class.name )
00428				{
00429					AutoSwitchPriority = i;
00430					return;
00431				}
00432			// else, register this weapon
00433			carried = class.name;
00434			for ( i=AutoSwitchPriority; i<ArrayCount(PlayerPawn(Other).WeaponPriority); i++ )
00435			{
00436				if ( PlayerPawn(Other).WeaponPriority[i] == '' )
00437				{
00438					PlayerPawn(Other).WeaponPriority[i] = carried;
00439					return;
00440				}
00441				else if ( i<ArrayCount(PlayerPawn(Other).WeaponPriority)-1 )
00442				{
00443					temp = PlayerPawn(Other).WeaponPriority[i];
00444					PlayerPawn(Other).WeaponPriority[i] = carried;
00445					carried = temp;
00446				}
00447			}
00448		}		
00449	}
00450	
00451	function GiveAmmo( Pawn Other )
00452	{
00453		if ( AmmoName == None )
00454			return;
00455		AmmoType = Ammo(Other.FindInventoryType(AmmoName));
00456		if ( AmmoType != None )
00457			AmmoType.AddAmmo(PickUpAmmoCount);
00458		else
00459		{
00460			AmmoType = Spawn(AmmoName);	// Create ammo type required		
00461			Other.AddInventory(AmmoType);		// and add to player's inventory
00462			AmmoType.BecomeItem();
00463			AmmoType.AmmoAmount = PickUpAmmoCount; 
00464			AmmoType.GotoState('Idle2');
00465		}
00466	}	
00467	
00468	// Return the switch priority of the weapon (normally AutoSwitchPriority, but may be
00469	// modified by environment (or by other factors for bots)
00470	function float SwitchPriority() 
00471	{
00472		local float temp;
00473		local int bTemp;
00474	
00475		if ( !Owner.IsA('PlayerPawn') )
00476			return RateSelf(bTemp);
00477		else if ( (AmmoType != None) && (AmmoType.AmmoAmount<=0) )
00478		{
00479			if ( Pawn(Owner).Weapon == self )
00480				return -0.5;
00481			else
00482				return -1;
00483		}
00484		else 
00485			return AutoSwitchPriority;
00486	}
00487	
00488	// Compare self to current weapon.  If better than current weapon, then switch
00489	function bool WeaponSet(Pawn Other)
00490	{
00491		local bool bSwitch,bHaveAmmo;
00492		local Inventory Inv;
00493		local weapon W;
00494		
00495		if ( Other.Weapon == self)
00496			return false;
00497	
00498		if ( Other.Weapon == None )
00499		{
00500			Other.PendingWeapon = self;
00501			Other.ChangedWeapon();
00502			return true;	
00503		}
00504		else if ( Other.Weapon.SwitchPriority() < SwitchPriority() ) 
00505		{
00506			W = Other.PendingWeapon;
00507			Other.PendingWeapon = self;
00508			GotoState('');
00509	
00510			if ( Other.Weapon.PutDown() )
00511				return true;
00512			Other.PendingWeapon = W;
00513			return false;
00514		}
00515		else 
00516		{
00517			GoToState('');
00518			return false;
00519		}
00520	}
00521	
00522	function Weapon RecommendWeapon( out float rating, out int bUseAltMode )
00523	{
00524		local Weapon Recommended;
00525		local float oldRating, oldFiring;
00526		local int oldMode;
00527	
00528		if ( Owner.IsA('PlayerPawn') )
00529			rating = SwitchPriority();
00530		else
00531		{
00532			rating = RateSelf(bUseAltMode);
00533			if ( (self == Pawn(Owner).Weapon) && (Pawn(Owner).Enemy != None) 
00534				&& ((AmmoType == None) || (AmmoType.AmmoAmount > 0)) )
00535				rating += 0.21; // tend to stick with same weapon
00536		}
00537		if ( inventory != None )
00538		{
00539			Recommended = inventory.RecommendWeapon(oldRating, oldMode);
00540			if ( (Recommended != None) && (oldRating > rating) )
00541			{
00542				rating = oldRating;
00543				bUseAltMode = oldMode;
00544				return Recommended;
00545			}
00546		}
00547		return self;
00548	}
00549	
00550	// Toss this weapon out
00551	function DropFrom(vector StartLocation)
00552	{
00553		if ( !SetLocation(StartLocation) )
00554			return; 
00555		AIRating = Default.AIRating;
00556		bMuzzleFlash = 0;
00557		AmbientSound = None;
00558		if ( AmmoType != None )
00559		{
00560			PickupAmmoCount = AmmoType.AmmoAmount;
00561			AmmoType.AmmoAmount = 0;
00562		}
00563		Super.DropFrom(StartLocation);
00564	}
00565	
00566	// Become a pickup
00567	function BecomePickup()
00568	{
00569		Super.BecomePickup();
00570		SetDisplayProperties(Default.Style, Default.Texture, Default.bUnlit, Default.bMeshEnviromap );
00571	}
00572	
00573	simulated function TweenToStill();
00574	
00575	//**************************************************************************************
00576	//
00577	// Firing functions and states
00578	//
00579	
00580	function CheckVisibility()
00581	{
00582		local Pawn PawnOwner;
00583	
00584		PawnOwner = Pawn(Owner);
00585		if( Owner.bHidden && (PawnOwner.Health > 0) && (PawnOwner.Visibility < PawnOwner.Default.Visibility) )
00586		{
00587			Owner.bHidden = false;
00588			PawnOwner.Visibility = PawnOwner.Default.Visibility;
00589		}
00590	}
00591	
00592	simulated function bool ClientFire( float Value )
00593	{
00594		return true;
00595	}
00596	
00597	function ForceFire();
00598	function ForceAltFire();
00599	
00600	function Fire( float Value )
00601	{
00602		if (AmmoType.UseAmmo(1))
00603		{
00604			GotoState('NormalFire');
00605			if ( PlayerPawn(Owner) != None )
00606				PlayerPawn(Owner).ShakeView(ShakeTime, ShakeMag, ShakeVert);
00607			bPointing=True;
00608			PlayFiring();
00609			if ( !bRapidFire && (FiringSpeed > 0) )
00610				Pawn(Owner).PlayRecoil(FiringSpeed);
00611			if ( bInstantHit )
00612				TraceFire(0.0);
00613			else
00614				ProjectileFire(ProjectileClass, ProjectileSpeed, bWarnTarget);
00615			if ( Owner.bHidden )
00616				CheckVisibility();
00617		}
00618	}
00619	
00620	simulated function bool ClientAltFire( float Value )
00621	{
00622		return true;
00623	}
00624	
00625	function AltFire( float Value )
00626	{
00627		if (AmmoType.UseAmmo(1))
00628		{
00629			GotoState('AltFiring');
00630			if ( PlayerPawn(Owner) != None )
00631				PlayerPawn(Owner).ShakeView(ShakeTime, ShakeMag, ShakeVert);
00632			bPointing=True;
00633			PlayAltFiring();
00634			if ( !bRapidFire && (FiringSpeed > 0) )
00635				Pawn(Owner).PlayRecoil(FiringSpeed);
00636			if ( bAltInstantHit )
00637				TraceFire(0.0);
00638			else
00639				ProjectileFire(AltProjectileClass, AltProjectileSpeed, bAltWarnTarget);
00640			if ( Owner.bHidden )
00641				CheckVisibility();
00642		}
00643	}
00644	
00645	simulated function PlayFiring()
00646	{
00647		//Play firing animation and sound
00648	}
00649	
00650	simulated function PlayAltFiring()
00651	{
00652		//Play alt firing animation and sound
00653	}
00654	
00655	function Projectile ProjectileFire(class<projectile> ProjClass, float ProjSpeed, bool bWarn)
00656	{
00657		local Vector Start, X,Y,Z;
00658		local Pawn PawnOwner;
00659	
00660		PawnOwner = Pawn(Owner);
00661		Owner.MakeNoise(PawnOwner.SoundDampening);
00662		GetAxes(PawnOwner.ViewRotation,X,Y,Z);
00663		Start = Owner.Location + CalcDrawOffset() + FireOffset.X * X + FireOffset.Y * Y + FireOffset.Z * Z; 
00664		AdjustedAim = PawnOwner.AdjustAim(ProjSpeed, Start, AimError, True, bWarn);	
00665		return Spawn(ProjClass,,, Start,AdjustedAim);	
00666	}
00667	
00668	function TraceFire( float Accuracy )
00669	{
00670		local vector HitLocation, HitNormal, StartTrace, EndTrace, X,Y,Z;
00671		local actor Other;
00672		local Pawn PawnOwner;
00673	
00674		PawnOwner = Pawn(Owner);
00675	
00676		Owner.MakeNoise(PawnOwner.SoundDampening);
00677		GetAxes(PawnOwner.ViewRotation,X,Y,Z);
00678		StartTrace = Owner.Location + CalcDrawOffset() + FireOffset.X * X + FireOffset.Y * Y + FireOffset.Z * Z; 
00679		AdjustedAim = PawnOwner.AdjustAim(1000000, StartTrace, 2*AimError, False, False);	
00680		EndTrace = StartTrace + Accuracy * (FRand() - 0.5 )* Y * 1000
00681			+ Accuracy * (FRand() - 0.5 ) * Z * 1000;
00682		X = vector(AdjustedAim);
00683		EndTrace += (10000 * X); 
00684		Other = PawnOwner.TraceShot(HitLocation,HitNormal,EndTrace,StartTrace);
00685		ProcessTraceHit(Other, HitLocation, HitNormal, X,Y,Z);
00686	}
00687	
00688	function ProcessTraceHit(Actor Other, Vector HitLocation, Vector HitNormal, Vector X, Vector Y, Vector Z)
00689	{
00690		//Spawn appropriate effects at hit location, any weapon lights, and damage hit actor
00691	}
00692	
00693	// Finish a firing sequence
00694	function Finish()
00695	{
00696		local Pawn PawnOwner;
00697	
00698		if ( bChangeWeapon )
00699		{
00700			GotoState('DownWeapon');
00701			return;
00702		}
00703	
00704		PawnOwner = Pawn(Owner);
00705		if ( PlayerPawn(Owner) == None )
00706		{
00707			if ( (AmmoType != None) && (AmmoType.AmmoAmount<=0) )
00708			{
00709				PawnOwner.StopFiring();
00710				PawnOwner.SwitchToBestWeapon();
00711				if ( bChangeWeapon )
00712					GotoState('DownWeapon');
00713			}
00714			else if ( (PawnOwner.bFire != 0) && (FRand() < RefireRate) )
00715				Global.Fire(0);
00716			else if ( (PawnOwner.bAltFire != 0) && (FRand() < AltRefireRate) )
00717				Global.AltFire(0);	
00718			else 
00719			{
00720				PawnOwner.StopFiring();
00721				GotoState('Idle');
00722			}
00723			return;
00724		}
00725		if ( ((AmmoType != None) && (AmmoType.AmmoAmount<=0)) || (PawnOwner.Weapon != self) )
00726			GotoState('Idle');
00727		else if ( PawnOwner.bFire!=0 )
00728			Global.Fire(0);
00729		else if ( PawnOwner.bAltFire!=0 )
00730			Global.AltFire(0);
00731		else 
00732			GotoState('Idle');
00733	}
00734	
00735	///////////////////////////////////////////////////////
00736	state NormalFire
00737	{
00738		function Fire(float F) 
00739		{
00740		}
00741		function AltFire(float F) 
00742		{
00743		}
00744	
00745	Begin:
00746		FinishAnim();
00747		Finish();
00748	}
00749	
00750	////////////////////////////////////////////////////////
00751	state AltFiring
00752	{
00753		function Fire(float F) 
00754		{
00755		}
00756	
00757		function AltFire(float F) 
00758		{
00759		}
00760	
00761	Begin:
00762		FinishAnim();
00763		Finish();
00764	}
00765	
00766	//**********************************************************************************
00767	// Weapon is up, but not firing
00768	state Idle
00769	{
00770		function AnimEnd()
00771		{
00772			PlayIdleAnim();
00773		}
00774	
00775		function bool PutDown()
00776		{
00777			GotoState('DownWeapon');
00778			return True;
00779		}
00780	
00781	Begin:
00782		bPointing=False;
00783		if ( (AmmoType != None) && (AmmoType.AmmoAmount<=0) ) 
00784			Pawn(Owner).SwitchToBestWeapon();  //Goto Weapon that has Ammo
00785		if ( Pawn(Owner).bFire!=0 ) Fire(0.0);
00786		if ( Pawn(Owner).bAltFire!=0 ) AltFire(0.0);	
00787		Disable('AnimEnd');
00788		PlayIdleAnim();
00789	}
00790	
00791	//
00792	// Bring newly active weapon up
00793	// Bring newly active weapon up
00794	state Active
00795	{
00796		function Fire(float F) 
00797		{
00798		}
00799	
00800		function AltFire(float F) 
00801		{
00802		}
00803	
00804		function bool PutDown()
00805		{
00806			if ( bWeaponUp || (AnimFrame < 0.75) )
00807				GotoState('DownWeapon');
00808			else
00809				bChangeWeapon = true;
00810			return True;
00811		}
00812	
00813		function BeginState()
00814		{
00815			bChangeWeapon = false;
00816		}
00817	
00818	Begin:
00819		FinishAnim();
00820		if ( bChangeWeapon )
00821			GotoState('DownWeapon');
00822		bWeaponUp = True;
00823		PlayPostSelect();
00824		FinishAnim();
00825		Finish();
00826	}
00827	
00828	//
00829	// Putting down weapon in favor of a new one.
00830	//
00831	State DownWeapon
00832	{
00833	ignores Fire, AltFire;
00834	
00835		function bool PutDown()
00836		{
00837			Pawn(Owner).ClientPutDown(self, Pawn(Owner).PendingWeapon);
00838			return true; //just keep putting it down
00839		}
00840	
00841		function BeginState()
00842		{
00843			bChangeWeapon = false;
00844			bMuzzleFlash = 0;
00845			Pawn(Owner).ClientPutDown(self, Pawn(Owner).PendingWeapon);
00846		}
00847	
00848	Begin:
00849		TweenDown();
00850		FinishAnim();
00851		Pawn(Owner).ChangedWeapon();
00852	}
00853	
00854	simulated function ClientPutDown(Weapon NextWeapon);
00855	
00856	function BringUp()
00857	{
00858		if ( Owner.IsA('PlayerPawn') )
00859		{
00860			SetHand(PlayerPawn(Owner).Handedness);
00861			PlayerPawn(Owner).EndZoom();
00862		}	
00863		bWeaponUp = false;
00864		PlaySelect();
00865		GotoState('Active');
00866	}
00867	
00868	function RaiseUp(Weapon OldWeapon)
00869	{
00870		BringUp();
00871	}
00872	
00873	function bool PutDown()
00874	{
00875		bChangeWeapon = true;
00876		return true; 
00877	}
00878	
00879	function TweenDown()
00880	{
00881		if ( (AnimSequence != '') && (GetAnimGroup(AnimSequence) == 'Select') )
00882			TweenAnim( AnimSequence, AnimFrame * 0.4 );
00883		else
00884			PlayAnim('Down', 1.0, 0.05);
00885	}
00886	
00887	function TweenSelect()
00888	{
00889		TweenAnim('Select',0.001);
00890	}
00891	
00892	function PlaySelect()
00893	{
00894		PlayAnim('Select',1.0,0.0);
00895		Owner.PlaySound(SelectSound, SLOT_Misc, Pawn(Owner).SoundDampening);	
00896	}
00897	
00898	function PlayPostSelect()
00899	{
00900	}
00901	
00902	function PlayIdleAnim()
00903	{
00904	}
00905	
00906	defaultproperties
00907	{
00908	     MaxTargetRange=4096.000000
00909	     bCanThrow=True
00910	     ProjectileSpeed=1000.000000
00911	     AltProjectileSpeed=1000.000000
00912	     aimerror=550.000000
00913	     shakemag=300.000000
00914	     shaketime=0.100000
00915	     shakevert=5.000000
00916	     AIRating=0.100000
00917	     RefireRate=0.500000
00918	     AltRefireRate=0.500000
00919	     MessageNoAmmo=" has no ammo."
00920	     DeathMessage="%o was killed by %k's %w."
00921	     NameColor=(R=255,G=255,B=255)
00922	     MuzzleScale=4.000000
00923	     FlashLength=0.100000
00924	     AutoSwitchPriority=1
00925	     InventoryGroup=1
00926	     PickupMessage="You got a weapon"
00927	     ItemName="Weapon"
00928	     RespawnTime=30.000000
00929	     PlayerViewOffset=(X=30.000000,Z=-5.000000)
00930	     MaxDesireability=0.500000
00931	     Icon=Texture'Engine.S_Weapon'
00932	     Texture=Texture'Engine.S_Weapon'
00933	     bNoSmooth=True
00934	}

End Source Code