home *** CD-ROM | disk | FTP | other *** search
/ Game Level Design / GLDesign.bin / Software / UnrealEngine2Runtime / UE2Runtime-22262001_Demo.exe / Engine / Classes / Weapon.uc < prev    next >
Text File  |  2003-06-23  |  35KB  |  1,455 lines

  1. //=============================================================================
  2. // Parent class of all weapons.
  3. // FIXME - should bReplicateInstigator be true???
  4. //=============================================================================
  5. class Weapon extends Inventory
  6.     abstract
  7.     native
  8.     nativereplication;
  9.  
  10. #exec Texture Import File=Textures\Weapon.pcx Name=S_Weapon Mips=Off MASKED=1
  11.  
  12. //-----------------------------------------------------------------------------
  13. // Weapon ammo information:
  14. var        class<ammunition> AmmoName;     // Type of ammo used.
  15. var        int     PickupAmmoCount;        // Amount of ammo initially in pick-up item.
  16. var        travel ammunition    AmmoType;    // Inventory Ammo being used.
  17. var        byte    ReloadCount;            // Amount of ammo depletion before reloading. 0 if no reloading is done.
  18.  
  19. //-----------------------------------------------------------------------------
  20. // Weapon firing/state information:
  21.  
  22. var        bool      bPointing;        // Indicates weapon is being pointed
  23. var        bool      bWeaponUp;        // Used in Active State
  24. var        bool      bChangeWeapon;    // Used in Active State
  25. var        bool      bCanThrow;        // if true, player can toss this weapon out
  26. var        bool      bRapidFire;        // used by pawn animations in determining firing animation, and for net replication
  27. var        bool      bForceReload;
  28. var        bool      bSpectated;
  29.  
  30. var Weapon OldWeapon;
  31. var        float    StopFiringTime;    // repeater weapons use this
  32. var        int        AutoSwitchPriority;
  33. var     vector    FireOffset;            // Offset from first person eye position for projectile/trace start
  34. var     float    ShakeMag;
  35. var     float    ShakeTime;
  36. var     vector  ShakeVert;
  37. var        vector  ShakeSpeed;
  38. var        texture    CrossHair;
  39. var        Powerups Affector;            // powerup chain currently affecting this weapon
  40.  
  41. var        float    TraceAccuracy;
  42.  
  43. //-----------------------------------------------------------------------------
  44. // AI information
  45. var        bool    bMeleeWeapon;   // Weapon is only a melee weapon
  46. var        bool    bSniping;        // weapon useful for sniping
  47. var        float    AimError;        // Aim Error for bots (note this value doubled if instant hit weapon)
  48. var        float    AIRating;
  49. var        float    CurrentRating;
  50. var        float    TraceDist;        // how far instant hit trace fires go
  51. var        float   MaxRange;        // max range of weapon for non-trace hit attacks
  52. var        Rotator AdjustedAim;
  53.  
  54. //-----------------------------------------------------------------------------
  55. // Sound Assignments
  56. var() sound     FireSound;
  57. var() sound     SelectSound;
  58.  
  59. // messages
  60. var() Localized string MessageNoAmmo;
  61. var   Localized string WeaponDescription;
  62. var   Color NameColor;    // used when drawing name on HUD
  63.  
  64. var        bool    bSteadyToggle;
  65. var        bool bForceFire, bForceAltFire;
  66.  
  67. var string    LeftHandedMesh;    // string of name of left-handed view mesh (if different)
  68. var float DisplayFOV;        // FOV for drawing the weapon in first person view
  69.  
  70. //-----------------------------------------------------------------------------
  71. // first person Muzzle Flash
  72. // weapon is responsible for setting and clearing bMuzzleFlash whenever it wants the
  73. // MFTexture drawn on the canvas (see RenderOverlays() )
  74.  
  75. var                    float    FlashTime;            // time when muzzleflash will be cleared (set in RenderOverlays())
  76. var(MuzzleFlash)    float    MuzzleScale;        // scaling of muzzleflash
  77. var(MuzzleFlash)    float    FlashOffsetY;        // flash center offset from centered Y (as pct. of Canvas Y size) 
  78. var(MuzzleFlash)    float    FlashOffsetX;        // flash center offset from centered X (as pct. of Canvas X size) 
  79. var(MuzzleFlash)    float    FlashLength;        // How long muzzle flash should be displayed in seconds
  80. var(MuzzleFlash)    float    MuzzleFlashSize;    // size of (square) texture
  81. var                    texture MFTexture;            // first-person muzzle flash sprite
  82. var                    byte    FlashCount;            // when incremented, draw muzzle flash for current frame
  83. var                    bool    bAutoFire;            // when changed, draw muzzle flash for current frame
  84. var                    bool    bMuzzleFlash;        // if !=0 show first-person muzzle flash
  85. var                    bool    bSetFlashTime;        // reset FlashTime clock when false
  86. var                    bool    bDrawMuzzleFlash;    // enable first-person muzzle flash
  87.  
  88. //-----------------------------------------------------------------------------
  89. // third person muzzleflash
  90.  
  91. var        bool    bMuzzleFlashParticles;
  92. var        mesh    MuzzleFlashMesh;
  93. var        float    MuzzleFlashScale;
  94. var    ERenderStyle MuzzleFlashStyle;
  95. var        texture MuzzleFlashTexture;
  96.  
  97. var float FireAdjust;
  98.  
  99. // Network replication
  100. //
  101. replication
  102. {
  103.     // Things the server should send to the client.
  104.     reliable if( bNetOwner && bNetDirty && (Role==ROLE_Authority) )
  105.         AmmoType, Affector, ReloadCount;
  106.  
  107.     // Functions called by server on client
  108.     reliable if( Role==ROLE_Authority )
  109.         ClientWeaponEvent, ClientWeaponSet, ClientForceReload;
  110.  
  111.     // functions called by client on server
  112.     reliable if( Role<ROLE_Authority )
  113.         ServerForceReload, ServerFire, ServerAltFire, ServerRapidFire, ServerStopFiring;
  114. }
  115.  
  116. // AI Functions
  117. function float RangedAttackTime()
  118. {
  119.     return 0;
  120. }
  121.  
  122. function bool RecommendRangedAttack()
  123.     return false;
  124. }
  125.  
  126. function bool SplashDamage()
  127. {
  128.     return AmmoType.bSplashDamage;
  129. }
  130.  
  131. function float GetDamageRadius()
  132. {
  133.     return AmmoType.GetDamageRadius();
  134. }
  135.  
  136. function bool FocusOnLeader(bool bLeaderFiring)
  137. {
  138.     return false;
  139. }
  140. function float RefireRate()
  141. {
  142.     return AmmoType.RefireRate;
  143. }
  144.  
  145. function bool RecommendSplashDamage()
  146. {
  147.     return AmmoType.bRecommendSplashDamage;
  148. }
  149.  
  150. function FireHack(byte Mode);
  151.  
  152. // fixme - make IsFiring() weapon state based
  153. function bool IsFiring()
  154. {
  155.     return ((Instigator != None) && (Instigator.Controller != None)
  156.         && ((Instigator.Controller.bFire !=0) || (Instigator.Controller.bAltFire != 0)));
  157. }
  158.  
  159. /* IncrementFlashCount()
  160. Tell WeaponAttachment to cause client side weapon firing effects
  161. */
  162. simulated function IncrementFlashCount()
  163. {
  164.     FlashCount++;
  165.     if ( WeaponAttachment(ThirdPersonActor) != None )
  166.     {
  167.         WeaponAttachment(ThirdPersonActor).FlashCount = FlashCount;
  168.         WeaponAttachment(ThirdPersonActor).ThirdPersonEffects();
  169.     }
  170. }
  171.  
  172. simulated event PostNetBeginPlay()
  173. {
  174.     if ( Role == ROLE_Authority )
  175.         return;
  176.     if ( (Instigator == None) || (Instigator.Controller == None) )
  177.         SetHand(0);
  178.     else
  179.         SetHand(Instigator.Controller.Handedness);
  180. }
  181.  
  182. /* Force reloading even though clip isn't empty.  Called by player controller exec function,
  183. and implemented in idle state */
  184. simulated function ForceReload();
  185.  
  186. function ServerForceReload()
  187. {
  188.     bForceReload = true;
  189. }
  190.  
  191. simulated function ClientForceReload()
  192. {
  193.     bForceReload = true;
  194.     GotoState('Reloading');
  195. }
  196.  
  197. /* DisplayDebug()
  198. list important controller attributes on canvas
  199. */
  200. simulated function DisplayDebug(Canvas Canvas, out float YL, out float YPos)
  201. {
  202.     local string T;
  203.     local name Anim;
  204.     local float frame,rate;
  205.  
  206.     Canvas.SetDrawColor(0,255,0);
  207.     Canvas.DrawText("WEAPON "$GetItemName(string(self)));
  208.     YPos += YL;
  209.     Canvas.SetPos(4,YPos);
  210.  
  211.     T = "     STATE: "$GetStateName()$" Timer: "$TimerCounter;
  212.  
  213.     if ( Default.ReloadCount > 0 )
  214.         T = T$" Reload Count: "$ReloadCount;
  215.  
  216.     Canvas.DrawText(T, false);
  217.     YPos += YL;
  218.     Canvas.SetPos(4,YPos);
  219.     
  220.     if ( DrawType == DT_StaticMesh )        
  221.         Canvas.DrawText("     StaticMesh "$StaticMesh$" AmbientSound "$AmbientSound, false);
  222.     else 
  223.         Canvas.DrawText("     Mesh "$Mesh$" AmbientSound "$AmbientSound, false);
  224.     YPos += YL;
  225.     Canvas.SetPos(4,YPos);
  226.     if ( Mesh != None )
  227.     {
  228.         // mesh animation
  229.         GetAnimParams(0,Anim,frame,rate);
  230.         T = "     AnimSequence "$Anim$" Frame "$frame$" Rate "$rate;
  231.         if ( bAnimByOwner )
  232.             T= T$" Anim by Owner";
  233.         
  234.         Canvas.DrawText(T, false);
  235.         YPos += YL;
  236.         Canvas.SetPos(4,YPos);
  237.     }
  238.  
  239.     if ( AmmoType == None )
  240.     {
  241.         Canvas.DrawText("ERROR - NO AMMUNITION");
  242.         YPos += YL;
  243.         Canvas.SetPos(4,YPos);
  244.     }
  245.     else
  246.         AmmoType.DisplayDebug(Canvas,YL,YPos);
  247.  
  248. }
  249.  
  250. //=============================================================================
  251. // Inventory travelling across servers.
  252.  
  253. event TravelPostAccept()
  254. {
  255.     Super.TravelPostAccept();
  256.     if ( Pawn(Owner) == None )
  257.         return;
  258.     if ( AmmoName != None )
  259.     {
  260.         AmmoType = Ammunition(Pawn(Owner).FindInventoryType(AmmoName));
  261.         if ( AmmoType == None )
  262.         {        
  263.             AmmoType = Spawn(AmmoName);    // Create ammo type required        
  264.             Pawn(Owner).AddInventory(AmmoType);        // and add to player's inventory
  265.             AmmoType.AmmoAmount = PickUpAmmoCount; 
  266.             AmmoType.GotoState('');
  267.         }
  268.     }
  269.     if ( self == Pawn(Owner).Weapon )
  270.         BringUp();
  271.     else GotoState('');
  272. }
  273.  
  274. function SetAITarget(Actor T);
  275.  
  276. function Destroyed()
  277. {
  278.     Super.Destroyed();
  279.     if( (Pawn(Owner)!=None) && (Pawn(Owner).Weapon == self) )
  280.         Pawn(Owner).Weapon = None;
  281. }
  282.  
  283. function GiveTo(Pawn Other)
  284. {
  285.     Super.GiveTo(Other);
  286.     bTossedOut = false;
  287.     Instigator = Other;
  288.     GiveAmmo(Other);
  289.     ClientWeaponSet(true);
  290. }
  291.  
  292. //=============================================================================
  293. // Weapon rendering
  294. // Draw first person view of inventory
  295. simulated event RenderOverlays( canvas Canvas )
  296. {
  297.     local rotator NewRot;
  298.     local bool bPlayerOwner;
  299.     local int Hand;
  300.     local  PlayerController PlayerOwner;
  301.     local float ScaledFlash;
  302.  
  303.     DrawCrosshair(Canvas);
  304.  
  305.     if ( Instigator == None )
  306.         return;
  307.  
  308.     PlayerOwner = PlayerController(Instigator.Controller);
  309.  
  310.     if ( PlayerOwner != None )
  311.     {
  312.         bPlayerOwner = true;
  313.         Hand = PlayerOwner.Handedness;
  314.         if (  Hand == 2 )
  315.             return;
  316.     }
  317.  
  318.     if ( bMuzzleFlash && bDrawMuzzleFlash && (MFTexture != None) )
  319.     {
  320.         if ( !bSetFlashTime )
  321.         {
  322.             bSetFlashTime = true;
  323.             FlashTime = Level.TimeSeconds + FlashLength;
  324.         }
  325.         else if ( FlashTime < Level.TimeSeconds )
  326.             bMuzzleFlash = false;
  327.         if ( bMuzzleFlash )
  328.         {
  329.             ScaledFlash = 0.5 * MuzzleFlashSize * MuzzleScale * Canvas.ClipX/640.0;
  330.             Canvas.SetPos(0.5*Canvas.ClipX - ScaledFlash + Canvas.ClipX * Hand * FlashOffsetX, 0.5*Canvas.ClipY - ScaledFlash + Canvas.ClipY * FlashOffsetY);
  331.             DrawMuzzleFlash(Canvas);
  332.         }
  333.     }
  334.     else
  335.         bSetFlashTime = false;
  336.  
  337.     SetLocation( Instigator.Location + Instigator.CalcDrawOffset(self) );
  338.     NewRot = Instigator.GetViewRotation();
  339.  
  340.     if ( Hand == 0 )
  341.         newRot.Roll = 2 * Default.Rotation.Roll;
  342.     else
  343.         newRot.Roll = Default.Rotation.Roll * Hand;
  344.  
  345.     setRotation(newRot);
  346.     Canvas.DrawActor(self, false, false, DisplayFOV);
  347. }
  348.  
  349. simulated function DrawCrossHair( canvas Canvas)
  350. {
  351.     local float XLength;
  352.  
  353.     if ( CrossHair == None )
  354.         return;
  355.     XLength = 32.0;
  356.     Canvas.bNoSmooth = False;
  357.     Canvas.SetPos(0.503 * (Canvas.ClipX - XLength), 0.504 * (Canvas.ClipY - XLength));
  358.     Canvas.Style = ERenderStyle.STY_Translucent;
  359.     Canvas.SetDrawColor(255,255,255);
  360.     Canvas.DrawTile(CrossHair, XLength, XLength, 0, 0, 32, 32);
  361.     Canvas.bNoSmooth = True;
  362.     Canvas.Style = Style;
  363. }
  364.  
  365. /* DrawMuzzleFlash()
  366. Default implementation assumes that flash texture can be drawn inverted in X and/or Y direction to increase apparent
  367. number of flash variations
  368. */
  369. simulated function DrawMuzzleFlash(Canvas Canvas)
  370. {
  371.     local float Scale, ULength, VLength, UStart, VStart;
  372.  
  373.     Scale = MuzzleScale * Canvas.ClipX/640.0;
  374.     Canvas.Style = ERenderStyle.STY_Translucent;
  375.     ULength = MFTexture.USize;
  376.     if ( FRand() < 0.5 )
  377.     {
  378.         UStart = ULength;
  379.         ULength = -1 * ULength;
  380.     }
  381.     VLength = MFTexture.VSize;
  382.     if ( FRand() < 0.5 )
  383.     {
  384.         VStart = VLength;
  385.         VLength = -1 * VLength;
  386.     }
  387.  
  388.     Canvas.DrawTile(MFTexture, Scale * MFTexture.USize, Scale * MFTexture.VSize, UStart, VStart, ULength, VLength);
  389.     Canvas.Style = ERenderStyle.STY_Normal;
  390. }
  391.  
  392. //-------------------------------------------------------
  393. // AI related functions
  394.  
  395. /* CanAttack()
  396. return true if other is in range of this weapon
  397. */
  398. function bool CanAttack(Actor Other)
  399. {
  400.     local float MaxDist, CheckDist;
  401.     local vector HitLocation, HitNormal,X,Y,Z, projStart;
  402.     local actor HitActor;
  403.  
  404.     if ( (Instigator == None) || (Instigator.Controller == None) )
  405.         return false;
  406.  
  407.     // check that target is within range
  408.     MaxDist = MaxRange;
  409.     if ( AmmoType.bInstantHit )
  410.         MaxDist = TraceDist;
  411.     if ( VSize(Instigator.Location - Other.Location) > MaxDist )
  412.         return false;
  413.  
  414.     // check that can see target
  415.     if ( !Instigator.Controller.LineOfSightTo(Other) )
  416.         return false;
  417.  
  418.     // check that would hit target, and not a friendly
  419.     GetAxes(Instigator.Controller.Rotation,X,Y,Z);
  420.     projStart = GetFireStart(X,Y,Z);
  421.     if ( AmmoType.bInstantHit )
  422.         HitActor = Trace(HitLocation, HitNormal, Other.Location + Other.CollisionHeight * vect(0,0,0.7), projStart, true);
  423.     else
  424.     {
  425.         // for non-instant hit, only check partial path (since others may move out of the way)
  426.         CheckDist = FClamp(AmmoType.ProjectileClass.Default.Speed,600, VSize(Other.Location - Location));
  427.         HitActor = Trace(HitLocation, HitNormal, 
  428.                 projStart + CheckDist * Normal(Other.Location + Other.CollisionHeight * vect(0,0,0.7) - Location), 
  429.                 projStart, true);
  430.     }
  431.  
  432.     if ( (HitActor == None) || (HitActor == Other) ||
  433.         ((Pawn(HitActor) != None) && !Instigator.Controller.SameTeamAs(Pawn(HitActor).Controller)) )
  434.         return true;
  435.  
  436.     return false;
  437. }
  438.  
  439. /* AmmoStatus()
  440. return percent of full ammo (0 to 1 range)
  441. */
  442. function float AmmoStatus()
  443. {
  444.     return float(AmmoType.AmmoAmount)/AmmoType.MaxAmmo;
  445. }
  446.  
  447. simulated function bool HasAmmo()
  448. {
  449.     return AmmoType.HasAmmo();
  450. }
  451.  
  452. function bool SplashJump()
  453. {
  454.     return false;
  455. }
  456.  
  457. /* GetRating()
  458. returns rating of weapon based on its current configuration (no configuration change)
  459. */
  460. function float GetRating()
  461. {
  462.     return RateSelf(); // don't do this if RateSelf() changes weapon configuration
  463. }
  464.  
  465. simulated function float RateSelf()
  466. {
  467.     if ( !HasAmmo() )
  468.         CurrentRating = -2;
  469.     else if ( Instigator.Controller == None )
  470.         return 0;
  471.     else
  472.         CurrentRating = Instigator.Controller.RateWeapon(self);
  473.     return CurrentRating;
  474. }
  475.  
  476. function float GetAIRating()
  477. {
  478.     return AIRating;
  479. }
  480.  
  481. // return delta to combat style
  482. function float SuggestAttackStyle()
  483. {
  484. // FIXME - implement
  485. //    if ( VSize(Instigator.Target.Location - Instigator.Location) > MaxRange )
  486. //        return 1.0;
  487.     return 0.0;
  488. }
  489.  
  490. function float SuggestDefenseStyle()
  491. {
  492.     return 0.0;
  493. }
  494.  
  495. //-------------------------------------------------------
  496.  
  497. function ClientWeaponEvent(name EventType);
  498.  
  499. /* HandlePickupQuery()
  500. If picking up another weapon of the same class, add its ammo.
  501. If ammo count was at zero, check if should auto-switch to this weapon.
  502. */
  503. function bool HandlePickupQuery( Pickup Item )
  504. {
  505.     local int OldAmmo, NewAmmo;
  506.     local Pawn P;
  507.  
  508.     if (Item.InventoryType == Class)
  509.     {
  510.         if ( WeaponPickup(item).bWeaponStay && ((item.inventory == None) || item.inventory.bTossedOut) )
  511.             return true;
  512.         P = Pawn(Owner);
  513.         if ( AmmoType != None )
  514.         {
  515.             OldAmmo = AmmoType.AmmoAmount;
  516.             if ( Item.Inventory != None )
  517.                 NewAmmo = Weapon(Item.Inventory).PickupAmmoCount;
  518.             else
  519.                 NewAmmo = class<Weapon>(Item.InventoryType).Default.PickupAmmoCount;
  520.             if ( AmmoType.AddAmmo(NewAmmo) && (OldAmmo == 0) 
  521.                 && (P.Weapon.class != item.InventoryType) )
  522.                     ClientWeaponSet(true);
  523.         }
  524.         Item.AnnouncePickup(Pawn(Owner));
  525.         return true;
  526.     }
  527.     if ( Inventory == None )
  528.         return false;
  529.  
  530.     return Inventory.HandlePickupQuery(Item);
  531. }
  532.  
  533. // set which hand is holding weapon
  534. simulated function setHand(float Hand)
  535. {
  536.     if ( Hand == 2 )
  537.     {
  538.         PlayerViewOffset.Y = 0;
  539.         FireOffset.Y = 0;
  540.         return;
  541.     }
  542.  
  543.     LinkMesh(Default.Mesh);
  544.     if ( Hand == 0 )
  545.     {
  546.         PlayerViewOffset.X = Default.PlayerViewOffset.X * 0.88;
  547.         PlayerViewOffset.Y = -0.2 * Default.PlayerViewOffset.Y;
  548.         PlayerViewOffset.Z = Default.PlayerViewOffset.Z * 1.12;
  549.     }
  550.     else
  551.     {
  552.         PlayerViewOffset.X = Default.PlayerViewOffset.X;
  553.         PlayerViewOffset.Y = Default.PlayerViewOffset.Y * Hand;
  554.         PlayerViewOffset.Z = Default.PlayerViewOffset.Z;
  555.         if ( (Hand == -1) && (LeftHandedMesh != "") )
  556.         {
  557.             // load left handed mesh
  558.             LinkMesh(mesh(DynamicLoadObject(LeftHandedMesh, class'Mesh')));
  559.         }
  560.     }
  561.     FireOffset.Y = Default.FireOffset.Y * Hand;
  562. }
  563.  
  564. //
  565. // Change weapon to that specificed by F matching inventory weapon's Inventory Group.
  566. simulated function Weapon WeaponChange( byte F, bool bSilent )
  567. {    
  568.     local Weapon newWeapon;
  569.      
  570.     if ( InventoryGroup == F )
  571.     {
  572.         if ( !AmmoType.HasAmmo() )
  573.         {
  574.             if ( Inventory == None )
  575.                 newWeapon = None;
  576.             else
  577.                 newWeapon = Inventory.WeaponChange(F, bSilent);
  578.             if ( !bSilent && (newWeapon == None) && Instigator.IsHumanControlled() )
  579.                 Instigator.ClientMessage( ItemName$MessageNoAmmo );        
  580.             return newWeapon;
  581.         }        
  582.         else 
  583.             return self;
  584.     }
  585.     else if ( Inventory == None )
  586.         return None;
  587.     else
  588.         return Inventory.WeaponChange(F, bSilent);
  589. }
  590.  
  591. // Find the previous weapon (using the Inventory group)
  592. simulated function Weapon PrevWeapon(Weapon CurrentChoice, Weapon CurrentWeapon)
  593. {
  594.     if ( AmmoType.HasAmmo() )
  595.     {
  596.         if ( (CurrentChoice == None) )
  597.         {
  598.             if ( CurrentWeapon != self )
  599.                 CurrentChoice = self;
  600.         }
  601.         else if ( InventoryGroup == CurrentChoice.InventoryGroup )
  602.         {
  603.             if ( InventoryGroup == CurrentWeapon.InventoryGroup )
  604.             {
  605.                 if ( (GroupOffset < CurrentWeapon.GroupOffset)
  606.                     && (GroupOffset > CurrentChoice.GroupOffset) )
  607.                     CurrentChoice = self;
  608.             }
  609.             else if ( GroupOffset > CurrentChoice.GroupOffset )
  610.                 CurrentChoice = self;
  611.         }
  612.         else if ( InventoryGroup > CurrentChoice.InventoryGroup )
  613.         {
  614.             if ( (InventoryGroup < CurrentWeapon.InventoryGroup)
  615.                 || (CurrentChoice.InventoryGroup > CurrentWeapon.InventoryGroup) )
  616.                 CurrentChoice = self;
  617.         }
  618.         else if ( (CurrentChoice.InventoryGroup > CurrentWeapon.InventoryGroup)
  619.                 && (InventoryGroup < CurrentWeapon.InventoryGroup) )
  620.             CurrentChoice = self;
  621.     }
  622.     if ( Inventory == None )
  623.         return CurrentChoice;
  624.     else
  625.         return Inventory.PrevWeapon(CurrentChoice,CurrentWeapon);
  626. }
  627.  
  628. simulated function Weapon NextWeapon(Weapon CurrentChoice, Weapon CurrentWeapon)
  629. {
  630.     if ( AmmoType.HasAmmo() )
  631.     {
  632.         if ( (CurrentChoice == None) )
  633.         {
  634.             if ( CurrentWeapon != self )
  635.                 CurrentChoice = self;
  636.         }
  637.         else if ( InventoryGroup == CurrentChoice.InventoryGroup )
  638.         {
  639.             if ( InventoryGroup == CurrentWeapon.InventoryGroup )
  640.             {
  641.                 if ( (GroupOffset > CurrentWeapon.GroupOffset)
  642.                     && (GroupOffset < CurrentChoice.GroupOffset) )
  643.                     CurrentChoice = self;
  644.             }
  645.             else if ( GroupOffset < CurrentChoice.GroupOffset )
  646.                 CurrentChoice = self;
  647.         }
  648.  
  649.         else if ( InventoryGroup < CurrentChoice.InventoryGroup )
  650.         {
  651.             if ( (InventoryGroup > CurrentWeapon.InventoryGroup)
  652.                 || (CurrentChoice.InventoryGroup < CurrentWeapon.InventoryGroup) )
  653.                 CurrentChoice = self;
  654.         }
  655.         else if ( (CurrentChoice.InventoryGroup < CurrentWeapon.InventoryGroup)
  656.                 && (InventoryGroup > CurrentWeapon.InventoryGroup) )
  657.             CurrentChoice = self;
  658.     }
  659.     if ( Inventory == None )
  660.         return CurrentChoice;
  661.     else
  662.         return Inventory.NextWeapon(CurrentChoice,CurrentWeapon);
  663. }
  664.  
  665. simulated function AnimEnd(int Channel)
  666. {
  667.     if ( Level.NetMode == NM_Client )
  668.         PlayIdleAnim();
  669. }
  670.  
  671. function GiveAmmo( Pawn Other )
  672. {
  673.     if ( AmmoName == None )
  674.         return;
  675.     AmmoType = Ammunition(Other.FindInventoryType(AmmoName));
  676.     if ( AmmoType != None )
  677.         AmmoType.AddAmmo(PickUpAmmoCount);
  678.     else
  679.     {
  680.         AmmoType = Spawn(AmmoName);    // Create ammo type required        
  681.         Other.AddInventory(AmmoType);        // and add to player's inventory
  682.         AmmoType.AmmoAmount = PickUpAmmoCount; 
  683.     }
  684. }    
  685.  
  686. // Return the switch priority of the weapon (normally AutoSwitchPriority, but may be
  687. // modified by environment (or by other factors for bots)
  688. simulated function float SwitchPriority() 
  689. {
  690.     if ( !Instigator.IsHumanControlled() )
  691.         return RateSelf();
  692.     else if ( !AmmoType.HasAmmo() )
  693.     {
  694.         if ( Pawn(Owner).Weapon == self )
  695.             return -0.5;
  696.         else
  697.             return -1;
  698.     }
  699.     else 
  700.         return default.AutoSwitchPriority;
  701. }
  702.  
  703. // Compare self to current weapon.  If better than current weapon, then switch
  704. simulated function ClientWeaponSet(bool bOptionalSet)
  705. {
  706.     local weapon W;
  707.  
  708.     Instigator = Pawn(Owner); //weapon's instigator isn't replicated to client
  709.     if ( Instigator == None )
  710.     {
  711.         GotoState('PendingClientWeaponSet');
  712.         return;
  713.     }
  714.     else if ( IsInState('PendingClientWeaponSet') )
  715.         GotoState('');
  716.     if ( Instigator.Weapon == self )
  717.         return;
  718.  
  719.     if ( Instigator.Weapon == None )
  720.     {
  721.         Instigator.PendingWeapon = self;
  722.         Instigator.ChangedWeapon();
  723.         return;    
  724.     }
  725.     if ( bOptionalSet && (Instigator.IsHumanControlled() && PlayerController(Instigator.Controller).bNeverSwitchOnPickup) )
  726.         return;
  727.     if ( Instigator.Weapon.SwitchPriority() < SwitchPriority() ) 
  728.     {
  729.         W = Instigator.PendingWeapon;
  730.         Instigator.PendingWeapon = self;
  731.         GotoState('');
  732.  
  733.         if ( !Instigator.Weapon.PutDown() )
  734.             Instigator.PendingWeapon = W;
  735.         return;
  736.     }
  737.     GotoState('');
  738. }
  739.  
  740. simulated function Weapon RecommendWeapon( out float rating )
  741. {
  742.     local Weapon Recommended;
  743.     local float oldRating;
  744.  
  745.     if ( Instigator.IsHumanControlled() )
  746.         rating = SwitchPriority();
  747.     else
  748.     {
  749.         rating = RateSelf();
  750.         if ( (self == Instigator.Weapon) && (Instigator.Controller.Enemy != None) 
  751.             && AmmoType.HasAmmo() )
  752.             rating += 0.21; // tend to stick with same weapon
  753.             rating += Instigator.Controller.WeaponPreference(self);
  754.     }
  755.     if ( inventory != None )
  756.     {
  757.         Recommended = inventory.RecommendWeapon(oldRating);
  758.         if ( (Recommended != None) && (oldRating > rating) )
  759.         {
  760.             rating = oldRating;
  761.             return Recommended;
  762.         }
  763.     }
  764.     return self;
  765. }
  766.  
  767. // Toss this weapon out
  768. function DropFrom(vector StartLocation)
  769. {
  770.     AIRating = Default.AIRating;
  771.     bMuzzleFlash = false;
  772.     if ( AmmoType != None )
  773.     {
  774.         PickupAmmoCount = AmmoType.AmmoAmount;
  775.         AmmoType.AmmoAmount = 0;
  776.     }
  777.     Super.DropFrom(StartLocation);
  778. }
  779.  
  780. function HolderDied();
  781.  
  782. //**************************************************************************************
  783. //
  784. // Firing functions and states
  785. //
  786. simulated function bool RepeatFire()
  787. {
  788.     return bRapidFire;
  789. }
  790.  
  791. function ServerStopFiring()
  792. {
  793.     StopFiringTime = Level.TimeSeconds;
  794. }
  795.  
  796. function ServerRapidFire()
  797. {
  798.     ServerFire();
  799.     if ( IsInState('NormalFire') )
  800.         StopFiringTime = Level.TimeSeconds + 0.6;
  801. }
  802.     
  803. function ServerFire()
  804. {
  805.     if ( AmmoType == None )
  806.     {
  807.         // ammocheck
  808.         log("WARNING "$self$" HAS NO AMMO!!!");
  809.         GiveAmmo(Pawn(Owner));
  810.     }
  811.     if ( AmmoType.HasAmmo() )
  812.     {
  813.         GotoState('NormalFire');
  814.         ReloadCount--;
  815.         if ( AmmoType.bInstantHit )
  816.             TraceFire(TraceAccuracy,0,0);
  817.         else
  818.             ProjectileFire();
  819.         LocalFire();
  820.     }
  821. }
  822.  
  823. simulated function Fire( float Value )
  824. {
  825.     if ( !AmmoType.HasAmmo() )
  826.         return;
  827.  
  828.     if ( !RepeatFire() )
  829.         ServerFire();
  830.     else if ( StopFiringTime < Level.TimeSeconds + 0.3 )
  831.     {
  832.         StopFiringTime = Level.TimeSeconds + 0.6;
  833.         ServerRapidFire();
  834.     }
  835.     if ( Role < ROLE_Authority )
  836.     {
  837.         ReloadCount--;
  838.         LocalFire();
  839.         GotoState('ClientFiring');
  840.     }
  841. }
  842.     
  843. simulated function LocalFire()
  844. {
  845.     local PlayerController P;
  846.  
  847.     bPointing = true;
  848.  
  849.     if ( (Instigator != None) && Instigator.IsLocallyControlled() )
  850.     {
  851.         P = PlayerController(Instigator.Controller);
  852.         if (P!=None)
  853.             P.ShakeView(ShakeTime, ShakeMag, ShakeVert, 120000, ShakeSpeed, 1);
  854.     }
  855.     if ( Affector != None )
  856.         Affector.FireEffect();
  857.     PlayFiring();
  858. }        
  859.  
  860. function ServerAltFire()
  861. {
  862.     if ( !IsInState('Idle') )
  863.         GotoState('Idle');
  864. }
  865.  
  866. /* AltFire()
  867. Weapon mode change.
  868. */
  869. simulated function AltFire( float Value )
  870. {
  871.     if ( !IsInState('Idle') )
  872.         GotoState('Idle');
  873.     ServerAltFire();
  874. }
  875.  
  876. simulated function PlayFiring()
  877. {
  878.     //Play firing animation and sound
  879. }
  880.  
  881. simulated function vector GetFireStart(vector X, vector Y, vector Z)
  882. {
  883.     return (Instigator.Location + Instigator.EyePosition() + FireOffset.X * X + FireOffset.Y * Y + FireOffset.Z * Z); 
  884. }
  885.  
  886. function ProjectileFire()
  887. {
  888.     local Vector Start, X,Y,Z;
  889.  
  890.     Owner.MakeNoise(1.0);
  891.     GetAxes(Instigator.GetViewRotation(),X,Y,Z);
  892.     Start = GetFireStart(X,Y,Z); 
  893.     AdjustedAim = Instigator.AdjustAim(AmmoType, Start, AimError);    
  894.     AmmoType.SpawnProjectile(Start,AdjustedAim);    
  895. }
  896.  
  897. function TraceFire( float Accuracy, float YOffset, float ZOffset )
  898. {
  899.     local vector HitLocation, HitNormal, StartTrace, EndTrace, X,Y,Z;
  900.     local actor Other;
  901.  
  902.     Owner.MakeNoise(1.0);
  903.     GetAxes(Instigator.GetViewRotation(),X,Y,Z);
  904.     StartTrace = GetFireStart(X,Y,Z); 
  905.     AdjustedAim = Instigator.AdjustAim(AmmoType, StartTrace, 2*AimError);    
  906.     EndTrace = StartTrace + (YOffset + Accuracy * (FRand() - 0.5 ) ) * Y * 1000
  907.         + (ZOffset + Accuracy * (FRand() - 0.5 )) * Z * 1000;
  908.     X = vector(AdjustedAim);
  909.     EndTrace += (TraceDist * X); 
  910.     Other = Trace(HitLocation,HitNormal,EndTrace,StartTrace,True);
  911.     AmmoType.ProcessTraceHit(self, Other, HitLocation, HitNormal, X,Y,Z);
  912. }
  913.  
  914. simulated function bool NeedsToReload()
  915. {
  916.     return ( bForceReload || (Default.ReloadCount > 0) && (ReloadCount == 0) );
  917. }
  918.  
  919. /* BotFire()
  920. called by NPC firing weapon.  Weapon chooses appropriate firing mode to use (typically no change)
  921. bFinished should only be true if called from the Finished() function
  922. FiringMode can be passed in to specify a firing mode (used by scripted sequences)
  923. */
  924. function bool BotFire(bool bFinished, optional name FiringMode)
  925. {
  926.     if ( !bFinished && !IsIdle() )
  927.         return false;
  928.     Instigator.Controller.bFire = 1;
  929.     Instigator.Controller.bAltFire = 0;
  930.     if ( !RepeatFire() )
  931.         Global.ServerFire();
  932.     else if ( StopFiringTime < Level.TimeSeconds + 0.3 )
  933.     {
  934.         StopFiringTime = Level.TimeSeconds + 0.6;
  935.         Global.ServerRapidFire();
  936.     }
  937.     // in some situations, weapon might want to call CauseAltFire() instead, and set bAltFire=1
  938.     return true;
  939. }
  940.  
  941. function bool IsIdle()
  942. {
  943.     return false;
  944. }
  945.  
  946. // Finish a sequence
  947. function Finish()
  948. {
  949.     local bool bForce, bForceAlt;
  950.  
  951.     if ( NeedsToReload() && AmmoType.HasAmmo() )
  952.     {
  953.         GotoState('Reloading');
  954.         return;
  955.     }
  956.  
  957.     bForce = bForceFire;
  958.     bForceAlt = bForceAltFire;
  959.     bForceFire = false;
  960.     bForceAltFire = false;
  961.  
  962.     if ( bChangeWeapon )
  963.     {
  964.         GotoState('DownWeapon');
  965.         return;
  966.     }
  967.  
  968.     if ( (Instigator == None) || (Instigator.Controller == None) )
  969.     {
  970.         GotoState('');
  971.         return;
  972.     }
  973.  
  974.     if ( !Instigator.IsHumanControlled() )
  975.     {
  976.         if ( !AmmoType.HasAmmo() )
  977.         {
  978.             Instigator.Controller.SwitchToBestWeapon();
  979.             if ( bChangeWeapon )
  980.                 GotoState('DownWeapon');
  981.             else
  982.                 GotoState('Idle');
  983.             return;
  984.         }
  985.         if ( AIController(Instigator.Controller) != None )
  986.         {
  987.             if ( !AIController(Instigator.Controller).WeaponFireAgain(AmmoType.RefireRate,true) )
  988.             {
  989.                 if ( bChangeWeapon )
  990.                     GotoState('DownWeapon');
  991.                 else
  992.                     GotoState('Idle');
  993.             }
  994.             return;
  995.         }
  996.     }
  997.     if ( !AmmoType.HasAmmo() && Instigator.IsLocallyControlled() )
  998.     {
  999.         SwitchToWeaponWithAmmo();
  1000.         return;
  1001.     }
  1002.     if ( Instigator.Weapon != self )
  1003.         GotoState('Idle');
  1004.     else if ( (StopFiringTime > Level.TimeSeconds) || bForce || Instigator.PressingFire() )
  1005.         Global.ServerFire();
  1006.     else if ( bForceAlt || Instigator.PressingAltFire() )
  1007.         CauseAltFire();
  1008.     else 
  1009.         GotoState('Idle');
  1010. }
  1011.  
  1012. function SwitchToWeaponWithAmmo()
  1013.     {
  1014.     // if local player, switch weapon
  1015.     Instigator.Controller.SwitchToBestWeapon();
  1016.     if ( bChangeWeapon )
  1017.     {
  1018.         GotoState('DownWeapon');
  1019.         return;
  1020.     }
  1021.     else
  1022.         GotoState('Idle');
  1023. }
  1024.  
  1025. function CauseAltFire()
  1026. {
  1027.     Global.ServerAltFire();
  1028. }
  1029.  
  1030. simulated function ClientFinish()
  1031. {
  1032.     if ( (Instigator == None) || (Instigator.Controller == None) )
  1033.     {
  1034.         GotoState('');
  1035.         return;
  1036.     }
  1037.     if ( NeedsToReload() && AmmoType.HasAmmo() )
  1038.     {
  1039.         GotoState('Reloading');
  1040.         return;
  1041.     }
  1042.     if ( !AmmoType.HasAmmo() )
  1043.     {
  1044.         Instigator.Controller.SwitchToBestWeapon();
  1045.         if ( !bChangeWeapon )
  1046.         {
  1047.             PlayIdleAnim();
  1048.             GotoState('Idle');
  1049.             return;
  1050.         }
  1051.     }
  1052.     if ( bChangeWeapon )
  1053.         GotoState('DownWeapon');
  1054.     else if ( Instigator.PressingFire() )
  1055.         Global.Fire(0);
  1056.     else
  1057.     {
  1058.         if ( Instigator.PressingAltFire() )
  1059.             Global.AltFire(0);
  1060.         else
  1061.         {
  1062.             PlayIdleAnim();
  1063.             GotoState('Idle');
  1064.         }
  1065.     }
  1066. }
  1067.  
  1068. function CheckAnimating();
  1069.  
  1070. ///////////////////////////////////////////////////////
  1071. state NormalFire
  1072. {
  1073.     function CheckAnimating()
  1074.     {
  1075.         if ( !IsAnimating() )
  1076.             warn(self$" stuck in NormalFire and not animating!");
  1077.     }
  1078.  
  1079.     function ServerFire()
  1080.     {
  1081.         bForceFire = true;
  1082.     }
  1083.  
  1084.     function ServerAltFire()
  1085.     {
  1086.         bForceAltFire = true;
  1087.     }
  1088.  
  1089.     function Fire(float F) {}
  1090.     function AltFire(float F) {} 
  1091.  
  1092.     function AnimEnd(int Channel)
  1093.     {
  1094.         Finish();
  1095.         CheckAnimating();
  1096.     }
  1097.  
  1098.     function EndState()
  1099.     {
  1100.         StopFiringTime = Level.TimeSeconds;
  1101.     }
  1102.  
  1103. Begin:
  1104.     Sleep(0.0);
  1105. }
  1106.  
  1107. /*
  1108. Weapon is up and ready to fire, but not firing.
  1109. */
  1110. state Idle
  1111. {
  1112.     function bool IsIdle()
  1113.     {
  1114.         return true;
  1115.     }
  1116.  
  1117.     simulated function ForceReload()
  1118.     {
  1119.         ServerForceReload();
  1120.     }
  1121.  
  1122.     function ServerForceReload()
  1123.     {
  1124.         if ( AmmoType.HasAmmo() )
  1125.             GotoState('Reloading');
  1126.     }    
  1127.     
  1128.     simulated function AnimEnd(int Channel)
  1129.     {
  1130.         PlayIdleAnim();
  1131.     }
  1132.  
  1133.     simulated function bool PutDown()
  1134.     {
  1135.         GotoState('DownWeapon');
  1136.         return True;
  1137.     }
  1138.  
  1139. Begin:
  1140.     bPointing=False;
  1141.     if ( NeedsToReload() && AmmoType.HasAmmo() )
  1142.         GotoState('Reloading');
  1143.     if ( !AmmoType.HasAmmo() ) 
  1144.         Instigator.Controller.SwitchToBestWeapon();  //Goto Weapon that has Ammo
  1145.     if ( Instigator.PressingFire() ) Fire(0.0);
  1146.     if ( Instigator.PressingAltFire() ) AltFire(0.0);    
  1147.     PlayIdleAnim();
  1148. }
  1149.  
  1150. state Reloading
  1151. {
  1152.     function ServerForceReload() {}
  1153.     function ClientForceReload() {}
  1154.     function Fire( float Value ) {}
  1155.     function AltFire( float Value ) {}
  1156.  
  1157.     function ServerFire()
  1158.     {
  1159.         bForceFire = true;
  1160.     }
  1161.  
  1162.     function ServerAltFire()
  1163.     {
  1164.         bForceAltFire = true;
  1165.     }
  1166.  
  1167.     simulated function bool PutDown()
  1168.     {
  1169.         bChangeWeapon = true;
  1170.         return True;
  1171.     }
  1172.  
  1173.     simulated function BeginState()
  1174.     {
  1175.         if ( !bForceReload )
  1176.         {
  1177.             if ( Role < ROLE_Authority )
  1178.                 ServerForceReload();
  1179.             else
  1180.                 ClientForceReload();
  1181.         }
  1182.         bForceReload = false;
  1183.         PlayReloading();
  1184.     }
  1185.  
  1186.     simulated function AnimEnd(int Channel)
  1187.     {
  1188.         ReloadCount = Default.ReloadCount;
  1189.         if ( Role < ROLE_Authority )
  1190.             ClientFinish();
  1191.         else
  1192.             Finish();
  1193.         CheckAnimating();
  1194.     }
  1195.  
  1196.     function CheckAnimating()
  1197.     {
  1198.         if ( !IsAnimating() )
  1199.             warn(self$" stuck in Reloading and not animating!");
  1200.     }
  1201. }
  1202.  
  1203. /* Active
  1204. Bring newly active weapon up.
  1205. The weapon will remain in this state while its selection animation is being played (as well as any postselect animation).
  1206. While in this state, the weapon cannot be fired.
  1207. */
  1208. state Active
  1209. {
  1210.     function Fire( float Value ) {}
  1211.     function AltFire( float Value ) {}
  1212.  
  1213.     function ServerFire()
  1214.     {
  1215.         bForceFire = true;
  1216.     }
  1217.  
  1218.     function ServerAltFire()
  1219.     {
  1220.         bForceAltFire = true;
  1221.     }
  1222.  
  1223.     simulated function bool PutDown()
  1224.     {
  1225.         local name anim;
  1226.         local float frame,rate;
  1227.         GetAnimParams(0,anim,frame,rate);
  1228.         if ( bWeaponUp || (frame < 0.75) )
  1229.             GotoState('DownWeapon');
  1230.         else
  1231.             bChangeWeapon = true;
  1232.         return True;
  1233.     }
  1234.  
  1235.     simulated function BeginState()
  1236.     {
  1237.         Instigator = Pawn(Owner);
  1238.         bForceFire = false;
  1239.         bForceAltFire = false;
  1240.         bWeaponUp = false;
  1241.         bChangeWeapon = false;
  1242.     }
  1243.  
  1244.     simulated function EndState()
  1245.     {
  1246.         bForceFire = false;
  1247.         bForceAltFire = false;
  1248.     }
  1249.  
  1250.     simulated function AnimEnd(int Channel)
  1251.     {
  1252.         if ( bChangeWeapon )
  1253.             GotoState('DownWeapon');
  1254.         if ( Owner == None )
  1255.         {
  1256.             log(self$" no owner");
  1257.             Global.AnimEnd(0);
  1258.             GotoState('');
  1259.         }
  1260.         else if ( bWeaponUp )
  1261.         {
  1262.             if ( Role == ROLE_Authority )
  1263.                 Finish();
  1264.             else
  1265.                 ClientFinish();
  1266.         }
  1267.         else
  1268.         {
  1269.             PlayPostSelect();
  1270.             bWeaponUp = true;
  1271.         }
  1272.         CheckAnimating();
  1273.     }
  1274.  
  1275.     function CheckAnimating()
  1276.     {
  1277.         if ( !IsAnimating() )
  1278.             warn(self$" stuck in Active and not animating!");
  1279.     }
  1280. }
  1281.  
  1282. /* DownWeapon
  1283. Putting down weapon in favor of a new one.  No firing in this state
  1284. */
  1285. State DownWeapon
  1286. {
  1287.     function Fire( float Value ) {}
  1288.     function AltFire( float Value ) {}
  1289.  
  1290.     function ServerFire() {}
  1291.     function ServerAltFire() {}
  1292.  
  1293.     simulated function bool PutDown()
  1294.     {
  1295.         return true; //just keep putting it down
  1296.     }
  1297.  
  1298.     simulated function AnimEnd(int Channel)
  1299.     {
  1300.         Pawn(Owner).ChangedWeapon();
  1301.     }
  1302.  
  1303.     simulated function BeginState()
  1304.     {
  1305.         OldWeapon = None;
  1306.         bChangeWeapon = false;
  1307.         bMuzzleFlash = false;
  1308.         TweenDown();
  1309.     }
  1310. }
  1311.  
  1312. /* 
  1313. Fire on the client side. This state is only entered on the network client of the player that is firing this weapon. 
  1314. */
  1315. state ClientFiring
  1316. {
  1317.     function Fire( float Value ) {}
  1318.     function AltFire( float Value ) {}
  1319.  
  1320.     simulated function AnimEnd(int Channel)
  1321.     {
  1322.         ClientFinish();
  1323.         CheckAnimating();
  1324.     }
  1325.  
  1326.     function CheckAnimating()
  1327.     {
  1328.         if ( !IsAnimating() )
  1329.             warn(self$" stuck in ClientFiring and not animating!");
  1330.     }
  1331.  
  1332.     simulated function EndState()
  1333.     {
  1334.         AmbientSound = None;
  1335.         if ( RepeatFire() && !bPendingDelete )
  1336.             ServerStopFiring();
  1337.     }
  1338. }
  1339.  
  1340. /* PendingClientWeaponSet
  1341. Weapon on network client side may be set here by the replicated function ClientWeaponSet(), to wait,
  1342. if needed properties have not yet been replicated.  ClientWeaponSet() is called by the server to 
  1343. tell the client about potential weapon changes after the player runs over a weapon (the client 
  1344. decides whether to actually switch weapons or not.
  1345. */
  1346. State PendingClientWeaponSet
  1347. {
  1348.     simulated function Timer()
  1349.     {
  1350.         if ( Pawn(Owner) != None )
  1351.             ClientWeaponSet(false);
  1352.     }
  1353.  
  1354.     simulated function BeginState()
  1355.     {
  1356.         SetTimer(0.05, true);
  1357.     }
  1358.  
  1359.     simulated function EndState()
  1360.     {
  1361.         SetTimer(0.0, false);
  1362.     }
  1363. }
  1364.  
  1365. simulated function BringUp(optional weapon PrevWeapon)
  1366. {
  1367.     if ( (PrevWeapon != None) && PrevWeapon.HasAmmo() )
  1368.         OldWeapon = PrevWeapon;
  1369.     else
  1370.         OldWeapon = None;
  1371.     if ( Instigator.IsHumanControlled() )
  1372.     {
  1373.         SetHand(PlayerController(Instigator.Controller).Handedness);
  1374.         PlayerController(Instigator.Controller).EndZoom();
  1375.     }    
  1376.     bWeaponUp = false;
  1377.     PlaySelect();
  1378.     GotoState('Active');
  1379. }
  1380.  
  1381. simulated function bool PutDown()
  1382. {
  1383.     bChangeWeapon = true;
  1384.     return true; 
  1385. }
  1386.  
  1387. simulated function TweenDown()
  1388. {
  1389.     local name Anim;
  1390.     local float frame,rate;
  1391.  
  1392.     if ( IsAnimating() && AnimIsInGroup(0,'Select') )
  1393.     {
  1394.         GetAnimParams(0,Anim,frame,rate);
  1395.         TweenAnim( Anim, frame * 0.4 );
  1396.     }
  1397.     else
  1398.         PlayAnim('Down', 1.0, 0.05);
  1399. }
  1400.  
  1401. simulated function PlayReloading()
  1402. {
  1403.     AnimEnd(0);
  1404. }
  1405.  
  1406. simulated function PlaySelect()
  1407. {
  1408.     bForceFire = false;
  1409.     bForceAltFire = false;
  1410.     if ( !IsAnimating() || !AnimIsInGroup(0,'Select') )
  1411.         PlayAnim('Select',1.0,0.0);
  1412.     Owner.PlaySound(SelectSound, SLOT_Misc, 1.0);    
  1413. }
  1414.  
  1415. simulated function PlayPostSelect()
  1416. {
  1417.     GotoState('Idle');
  1418.     AnimEnd(0);
  1419. }
  1420.  
  1421. simulated function PlayIdleAnim()
  1422. {
  1423. }
  1424.  
  1425. simulated function zoom();
  1426.  
  1427. defaultproperties
  1428. {
  1429.     AttachmentClass=class'WeaponAttachment'
  1430.     bReplicateInstigator=true
  1431.     DisplayFOV=+85.0
  1432.     drawtype=DT_Mesh
  1433.     FireAdjust=1.0
  1434.      bCanThrow=true
  1435.      aimerror=550.000000
  1436.      shakemag=300.000000
  1437.      shaketime=0.100000
  1438.      shakevert=(X=0.0,Y=0.0,Z=5.00000)
  1439.      shakespeed=(X=100.0,Y=100.0,Z=100.0)
  1440.      AIRating=0.500000
  1441.      CurrentRating=0.50
  1442.      ItemName="Weapon"
  1443.      MessageNoAmmo=" has no ammo."
  1444.      AutoSwitchPriority=1
  1445.      InventoryGroup=1
  1446.      PlayerViewOffset=(X=30.000000,Z=-5.000000)
  1447.      MuzzleScale=1.0
  1448.      FlashLength=+0.1
  1449.      Icon=Texture'Engine.S_Weapon'
  1450.      NameColor=(R=255,G=255,B=255,A=255)
  1451.      TraceDist=+10000.0
  1452.      MaxRange=+8000.0
  1453. }
  1454.