Advertisement
GreatEmerald

U2Weapon.uc

Mar 5th, 2011
197
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
D 42.04 KB | None | 0 0
  1. //-----------------------------------------------------------
  2. // U2Weapon.uc
  3. // To make sure there are NO REFERENCES to XMPPlayer.
  4. // 2009, GreatEmerald
  5. //-----------------------------------------------------------
  6. class U2Weapon extends Weapon
  7.     abstract
  8.     config(User);
  9.  
  10. #EXEC OBJ LOAD FILE=..\Animations\WeaponsK.ukx
  11.  
  12. var bool bAllowCustomCrosshairs;
  13. var     float   TraceDist;      // how far instant hit trace fires go
  14.  
  15. var() array<name> TargetableTypes;  // Types of classes we can target (for crosshair glows).
  16. //var string Crosshair;             // UI event to send when switching to the weapon to show the crosshair.
  17. var bool bGlowing;                  // Whether the crosshair is currently glowing.
  18. var string LastTargetName;          // Last viewed target name (for TargetID).
  19.  
  20. //-----------------------------------------------------------------------------
  21. // GE: AI variables ported from Unreal II:
  22.  
  23. //-----------------------------------------------------------------------------
  24. // U2 Weapon AI properties
  25. //-----------------------------------------------------------------------------
  26.  
  27. const MaxRapidFireRate      =   0.50;       // firing rates <= this are considered rapid fire
  28. const MinSlowFireRate       =   0.51;       // firing rates >= this are considered slow fire
  29.  
  30. // special weapon rating values
  31. const RatingFireNow         = 100.000;      // weapon wants Pawn to fire it immediately (i.e. even if no target)
  32. const RatingHighest         =  90.000;      // weapon thinks it would be highly effective if used now
  33. const RatingDefault         =   0.000;      // default
  34. const RatingLow             =  -5.000;      // weapon is a poor choice but could be used if nothing better
  35. const RatingIneffective     = -10.000;      // weapon will have no effect on target in current situation
  36. const RatingDangerous       = -20.000;      // using weapon now will likely hurt/kill owner
  37. const RatingNoAmmo          = -30.000;      // not enough ammo to fire/altfire
  38. const RatingCantFire        = -40.000;      // can't actually fire weapon currently (not ready etc.)
  39. const RatingDisabled        = -50.000;      // weapon is disabled (alt and primary fire)
  40. const RatingNone            = -99.999;      // no rating (e.g. no weapon)
  41.  
  42. const RangeUnlimited        = 32767.0;      // no limit to effective range of weapon (limit to reasonable size for levels)
  43.  
  44. // AI !!mdf-tbd: generalize
  45. var() bool bAimFire;                        // whether primary fire requires owner aiming (usually true)
  46. var() bool bAimAltFire;                     // whether alt fire requires owner aiming (usually true)
  47. var() bool bFireEnabledForOwner;            // supports disabling fire for specific weapons for specific NPCs
  48. var() bool bAltFireEnabledForOwner;         // supports disabling altfire for specific weapons for specific NPCs
  49.  
  50. //NOTE: AIRating still used to specify the "global" rating for a weapon vs other weapons and should be set
  51. //to Max( AIRatingFire, AIRatingAltFire );
  52. //!!mdf-tbd: turn all of these into config vars for tweaking purposes
  53. var() const float RangeMinFire;                   // min range to target for firing weapon (-1 = range not considered)
  54. var() const float RangeIdealFire;                 // ideal range to target for firing weapon (-1 = range not considered)
  55. var() const float RangeMaxFire;                   // max range to target for firing weapon (-1 = range not considered)
  56. var() const float RangeLimitFire;                 // absolute limit of range to target for firing weapon (default is use RangeMaxFire as limit)
  57. var() const float RatingInsideMinFire;            // rating for firing weapon inside min range
  58. var() const float RatingRangeMinFire;             // rating for firing weapon at min range
  59. var() const float RatingRangeIdealFire;           // rating for firing weapon at ideal range
  60. var() const float RatingRangeMaxFire;             // rating for firing weapon at max range
  61. var() const float RatingRangeLimitFire;           // rating for firing weapon at limit of range
  62. var() float AIRatingFire;                   // default rating for firing weapon (used when range not considered or no target)
  63.  
  64. var() const float RangeMinAltFire;                // min range to target for alt-firing weapon (-1 = range not considered)
  65. var() const float RangeIdealAltFire;              // ideal range to target for alt-firing weapon (-1 = range not considered)
  66. var() const float RangeMaxAltFire;                // max range to target for alt-firing weapon (-1 = range not considered)
  67. var() const float RangeLimitAltFire;              // absolute limit of range to target for alt-firing weapon (default is use RangeMaxAltFire as limit)
  68. var() const float RatingInsideMinAltFire;         // rating for alt-firing weapon inside min range
  69. var() const float RatingRangeMinAltFire;          // rating for alt-firing weapon at min range
  70. var() const float RatingRangeIdealAltFire;        // rating for alt-firing weapon at ideal range
  71. var() const float RatingRangeMaxAltFire;          // rating for alt-firing weapon at max range
  72. var() const float RatingRangeLimitAltFire;        // rating for alt-firing weapon at limit of range
  73. var() float AIRatingAltFire;                // default rating for alt-firing weapon (used when range not considered or no target
  74.  
  75. var InterpCurve RatingCurveFire, RatingCurveAltFire; //GE: Rating curves compiled from the data above.
  76.  
  77. //GE: Ported from XMPPlayer.uc
  78. var Actor LastViewTargetActor;
  79. var float LastViewTargetTime;
  80.  
  81. var float LastViewTargetTraceDistance;
  82. var float LastViewTargetActualDistance;
  83. var vector LastViewTargetLocation;
  84. var rotator LastViewTargetRotation;
  85. var vector LastViewTargetHitLocation;
  86. var vector LastViewTargetHitNormal;
  87.  
  88. //-----------------------------------------------------------------------------
  89. // Debug flags:
  90. var globalconfig bool bUpdateCrosshair;
  91. var              bool bUpdateLocation;
  92. var globalconfig bool bDrawWeapon;
  93. var globalconfig bool bClearZ;
  94.  
  95. struct Point
  96. {
  97.     var() public float X;
  98.     var() public float Y;
  99. };
  100.  
  101. var     int     AutoSwitchPriority;
  102.  
  103. //-----------------------------------------------------------------------------
  104. // Sound Assignments
  105. var() sound ReloadSound,
  106.             ReloadUnloadedSound;
  107.  
  108. //-----------------------------------------------------------------------------
  109. var() Name ReloadAnim;
  110. var() float ReloadAnimRate;
  111.  
  112. //-----------------------------------------------------------------------------
  113. var() int ClipSize;
  114. var int ClipRoundsRemaining, ClientRoundsRemaining;
  115.  
  116. var() float ReloadTime, ReloadUnloadedTime;
  117. var float ReloadTimer; //Time when reload was executed
  118.  
  119. var bool bIsReloading, bPendingReload; //GE: bIsReloading == iIntVariable. Captain obvious.
  120.  
  121. var float DownUnloadedTime;
  122. var float SelectUnloadedTime;
  123.  
  124. var name LastAnim;
  125.  
  126. var float EquipResidue;                 // resuppling leftover between updates
  127.  
  128. var bool bLastRound;
  129. var int IdleTicks;  //GE: 1 IdleTick ~= 3 seconds of DeltaTime
  130.  
  131.  
  132. replication
  133. {
  134.     // Things the server should send to the client.
  135.     reliable if(bNetOwner && Role == ROLE_Authority)
  136.         ClipRoundsRemaining;
  137.  
  138.     //Functions called on the client from the server.
  139.     reliable if(Role == ROLE_Authority)
  140.        ClientReload;
  141.  
  142.     reliable if(Role < ROLE_Authority)
  143.         Reload;
  144. }
  145.  
  146. simulated function PreBeginPlay()
  147. {
  148.     Super.PreBeginPlay();
  149.     ClipRoundsRemaining = ClipSize;
  150.     ClientRoundsRemaining = ClipSize;
  151.  
  152.     BuildInterpolationCurves();
  153. }
  154.  
  155. simulated function PostNetReceive()
  156. {
  157.     Super.PostNetReceive();
  158.     if ( ClientRoundsRemaining < ClipRoundsRemaining )
  159.         ClientRoundsRemaining = ClipRoundsRemaining;
  160. }
  161.  
  162. simulated function Weapon NextWeapon(Weapon CurrentChoice, Weapon CurrentWeapon)
  163. {
  164.     if ( HasAmmo() )
  165.     {
  166.         if ( (CurrentChoice == None) )
  167.         {
  168.             if ( CurrentWeapon != self )
  169.                 CurrentChoice = self;
  170.         }
  171.         else if (InventoryGroup == CurrentWeapon.InventoryGroup && InventoryGroup == CurrentChoice.InventoryGroup) {
  172.             if (
  173.                 ( GroupOffset < CurrentChoice.GroupOffset && CurrentChoice.GroupOffset < CurrentWeapon.GroupOffset ) ||
  174.                 ( CurrentWeapon.GroupOffset < GroupOffset && GroupOffset < CurrentChoice.GroupOffset ) ||
  175.                 ( CurrentChoice.GroupOffset < CurrentWeapon.GroupOffset && CurrentWeapon.GroupOffset < GroupOffset)
  176.             )
  177.                 CurrentChoice = self;
  178.         }
  179.         else if (
  180.             ( CurrentWeapon.InventoryGroup == InventoryGroup && CurrentWeapon.GroupOffset < GroupOffset) ||
  181.             ( CurrentWeapon.InventoryGroup == CurrentChoice.InventoryGroup && CurrentChoice.GroupOffset < CurrentWeapon.GroupOffset) ||
  182.             ( CurrentChoice.InventoryGroup == InventoryGroup && GroupOffset < CurrentChoice.GroupOffset ) ||
  183.             ( InventoryGroup < CurrentChoice.InventoryGroup && CurrentChoice.InventoryGroup < CurrentWeapon.InventoryGroup ) ||
  184.             ( CurrentWeapon.InventoryGroup < InventoryGroup && InventoryGroup < CurrentChoice.InventoryGroup ) ||
  185.             ( CurrentChoice.InventoryGroup < CurrentWeapon.InventoryGroup && CurrentWeapon.InventoryGroup < InventoryGroup)
  186.         )
  187.             CurrentChoice = self;
  188.     }
  189.     if ( Inventory == None )
  190.         return CurrentChoice;
  191.     else
  192.         return Inventory.NextWeapon(CurrentChoice,CurrentWeapon);
  193. }
  194.  
  195. simulated function Weapon PrevWeapon(Weapon CurrentChoice, Weapon CurrentWeapon)
  196. {
  197.     if ( HasAmmo() )
  198.     {
  199.         if ( (CurrentChoice == None) )
  200.         {
  201.             if ( CurrentWeapon != self )
  202.                 CurrentChoice = self;
  203.         }
  204.         else if (InventoryGroup == CurrentWeapon.InventoryGroup && InventoryGroup == CurrentChoice.InventoryGroup) {
  205.             if (
  206.                 ( GroupOffset > CurrentChoice.GroupOffset && CurrentChoice.GroupOffset > CurrentWeapon.GroupOffset ) ||
  207.                 ( CurrentWeapon.GroupOffset > GroupOffset && GroupOffset > CurrentChoice.GroupOffset ) ||
  208.                 ( CurrentChoice.GroupOffset > CurrentWeapon.GroupOffset && CurrentWeapon.GroupOffset > GroupOffset)
  209.             )
  210.                 CurrentChoice = self;
  211.         }
  212.         else if (
  213.             ( CurrentWeapon.InventoryGroup == InventoryGroup && CurrentWeapon.GroupOffset > GroupOffset) ||
  214.             ( CurrentWeapon.InventoryGroup == CurrentChoice.InventoryGroup && CurrentChoice.GroupOffset > CurrentWeapon.GroupOffset) ||
  215.             ( CurrentChoice.InventoryGroup == InventoryGroup && GroupOffset > CurrentChoice.GroupOffset ) ||
  216.             ( InventoryGroup > CurrentChoice.InventoryGroup && CurrentChoice.InventoryGroup > CurrentWeapon.InventoryGroup ) ||
  217.             ( CurrentWeapon.InventoryGroup > InventoryGroup && InventoryGroup > CurrentChoice.InventoryGroup ) ||
  218.             ( CurrentChoice.InventoryGroup > CurrentWeapon.InventoryGroup && CurrentWeapon.InventoryGroup > InventoryGroup)
  219.         )
  220.             CurrentChoice = self;
  221.     }
  222.     if ( Inventory == None )
  223.         return CurrentChoice;
  224.     else
  225.         return Inventory.PrevWeapon(CurrentChoice,CurrentWeapon);
  226. }
  227.  
  228.  
  229.  
  230. simulated function int AmmoUsed(int mode)
  231. {
  232.     return FireMode[mode].AmmoPerFire;
  233. }
  234.  
  235. simulated function int AmmoMax(int mode)
  236. {
  237.     if ( bNoAmmoInstances )
  238.             return MaxAmmo(mode);
  239.     if ( Ammo[mode] != None )
  240.         return Ammo[mode].MaxAmmo;
  241.  
  242.     return 0;
  243. }
  244.  
  245. simulated function int AmmoInitial(int mode)
  246. {
  247.     if ( bNoAmmoInstances )
  248.         return AmmoClass[mode].default.InitialAmount;
  249.     if ( Ammo[mode] != None )
  250.          return Ammo[mode].InitialAmount;
  251. }
  252.  
  253. simulated function GetAmmoCount(out float MaxAmmoPrimary, out float CurAmmoPrimary)
  254. {
  255.     if ( AmmoClass[0] == None )
  256.         return;
  257.  
  258.     if ( bNoAmmoInstances )
  259.     {
  260.         MaxAmmoPrimary = MaxAmmo(0);
  261.         CurAmmoPrimary = FMax(0,AmmoCharge[0]);
  262.         return;
  263.     }
  264.  
  265.     if ( Ammo[0] == None )
  266.         return;
  267.     MaxAmmoPrimary = Ammo[0].MaxAmmo;
  268.     CurAmmoPrimary = FMax(0,Ammo[0].AmmoAmount);
  269. }
  270.  
  271. simulated function float ResupplyStatus()
  272. {
  273.     local float Amount, Max, Result;
  274.  
  275.     if ( bNoAmmoInstances )
  276.     {
  277.         Amount = AmmoCharge[0] - ClipRoundsRemaining;
  278.         Max = AmmoInitial(0) - ClipSize;
  279.     }
  280.     else
  281.     {
  282.         Amount = Ammo[0].AmmoAmount - ClipRoundsRemaining;
  283.         Max = AmmoInitial(0) - ClipSize;
  284.     }
  285.  
  286.     if( Max == 0 )
  287.         Result = ClipRoundsRemaining;
  288.     else if( FireMode[0].AmmoPerFire == 0 )
  289.         Result = 1.0;
  290.     else if (Max > 0)
  291.         Result = Amount / Max;
  292.     else
  293.         Result = Amount;
  294.     if( Result > 1.0 )
  295.         Result = 1.0;
  296.     return Result;
  297. }
  298.  
  299. function Resupply( float AddedPercent )
  300. {
  301.     Ammo_Resupply( AddedPercent );
  302. }
  303.  
  304. function Ammo_Resupply( float AddedPercent )
  305. {
  306.     local int ResupplyMax;
  307.     local float AddedAmmoAmount;
  308.     local int Max;
  309.  
  310.     // jy -- sanity check
  311.     if ( ResupplyStatus() >= 1 ) return;
  312.  
  313.     Max = AmmoInitial(0) - ClipSize;
  314.  
  315.     // Special handling for items that can hold only one ammo (which gets put in their clip) and therefore have a MaxAmmo of zero.
  316. //  if( AmmoMax(0) == 0 && AmmoAmount(0) == 0 )
  317.     if ( Max == 0 && AmmoAmount(0) == 0 )
  318.     {
  319.         EquipResidue += AddedPercent;
  320.         if( EquipResidue >= 1.0 )
  321.         {
  322.             Ammo_SetAmmoAmount(1);
  323.             Ammo_SetClipRoundsRemaining(1);
  324.             //bPendingReload = false;
  325.             EquipResidue = 0.0;
  326.         }
  327.         return;
  328.     }
  329.  
  330.     // fill up all the ammo except what's in the clip
  331.     ResupplyMax = Max - AmmoAmount(0) + ClipRoundsRemaining;
  332.  
  333.     if( ResupplyMax > 0 )
  334.     {
  335.         AddedAmmoAmount = AddedPercent * Max + EquipResidue;
  336.         AddedAmmoAmount = FClamp( AddedAmmoAmount, 0,  ResupplyMax );
  337.         Ammo_SetAmmoAmount( AmmoAmount(0) + int(AddedAmmoAmount) );
  338.         EquipResidue = AddedAmmoAmount - int(AddedAmmoAmount);
  339.     }
  340. }
  341.  
  342. // Notify the player that an ammunition property has changed
  343. function Ammo_NotifyAmmoChanged();
  344.  
  345.  
  346. simulated function Ammo_SetAmmoAmount(int NewAmmoAmount)
  347. {
  348.     if ( bNoAmmoInstances )
  349.     {
  350.         if ( AmmoClass[0] != None )
  351.             AmmoCharge[0] = NewAmmoAmount;
  352.         if ( (AmmoClass[1] != None) && (AmmoClass[0] != AmmoClass[1]) )
  353.             AmmoCharge[1] = NewAmmoAmount;
  354.         Ammo_NotifyAmmoChanged();
  355.         return;
  356.     }
  357.     if ( Ammo[0] != None )
  358.         Ammo[0].AmmoAmount = NewAmmoAmount;
  359.     if ( Ammo[1] != None )
  360.         Ammo[1].AmmoAmount = NewAmmoAmount;
  361.     Ammo_NotifyAmmoChanged();
  362. }
  363.  
  364. simulated function Ammo_SetClipRoundsRemaining( int NewClipRoundsRemaining )
  365. {
  366.     ClipRoundsRemaining = NewClipRoundsRemaining;
  367.     ClientRoundsRemaining = NewClipRoundsRemaining;
  368.     log(self$": Ammo_SetClipRoundsRemaining("$NewClipRoundsRemaining$")");
  369.     Ammo_NotifyAmmoChanged();
  370. }
  371.  
  372. function Ammo_SetMaxAmmo(int NewMaxAmmo)
  373. {
  374. //  MaxAmmo[AmmoIndex] = NewMaxAmmo;
  375.     Ammo_NotifyAmmoChanged();
  376. }
  377.  
  378. function GiveTo(Pawn Other, optional Pickup Pickup)
  379. {
  380.     Super.GiveTo(Other, PickUp);
  381.     Ammo_NotifyAmmoChanged();
  382. }
  383.  
  384.  
  385. simulated function PlayAnimEx(name Sequence, optional float Rate)
  386. {
  387.     local float TweenTime;
  388.  
  389.     if (Sequence!='')
  390.     {
  391.         if (Rate == 0.0)
  392.             Rate = 1.0;
  393.  
  394.         //class'GEUtilities'.static.LogSelf(self, "Playing"@Sequence);
  395.         if (Sequence != FireMode[0].default.FireAnim &&
  396.             Sequence != FireMode[1].default.FireAnim)
  397.             TweenTime = 0.1;
  398.         PlayAnim(Sequence, Rate, TweenTime);
  399.         LastAnim=Sequence;
  400.     }
  401. }
  402.  
  403. simulated function bool ReloadRequired()
  404. {
  405.     if ( HasAmmo() == false ) return true;
  406.  
  407.     return Ammo_ReloadRequired(FireMode[0].AmmoPerFire) &&
  408.         Ammo_ReloadRequired(FireMode[1].AmmoPerFire);
  409. }
  410.  
  411. simulated function bool Ammo_ReloadRequired( optional int AmountNeeded )
  412. {
  413.     if( AmountNeeded == 0 )
  414.         AmountNeeded = FireMode[0].AmmoPerFire;
  415.     return AmountNeeded > ClipRoundsRemaining;
  416. }
  417.  
  418. function bool BotFire(bool bFinished, optional name FiringMode)
  419. {
  420.     if ( ReloadRequired() && HasAmmo() )
  421.         Reload();
  422.     return Super.BotFire(bFinished, FiringMode);
  423. }
  424.  
  425. simulated function bool CanReload()
  426. {
  427.     if( bIsReloading || !ReadyToReload() )
  428.         return false;
  429.  
  430.     return Ammo_CanReload();
  431. }
  432.  
  433. simulated function BringUp(optional Weapon PrevWeapon)
  434. {
  435.     local int Mode;
  436.  
  437.     // hack to fix stupid sniper rifle unzoom bug
  438.     if( Instigator != None && PlayerController(Instigator.Controller) != None )
  439.     {
  440.         PlayerController(Instigator.Controller).DesiredFOV = PlayerController(Instigator.Controller).DefaultFOV;
  441.         PlayerController(Instigator.Controller).FOVAngle = PlayerController(Instigator.Controller).DefaultFOV;
  442.     }
  443.     if( Instigator != None && Instigator.Controller != None && Instigator.Controller.IsA( 'PlayerController' ) )
  444.         PlayerController(Instigator.Controller).EndZoom();
  445.  
  446.     if ( ClientState == WS_Hidden )
  447.     {
  448.         Instigator.PlaySound(SelectSound,SLOT_Misc,1.0,,TransientSoundRadius*0.3);
  449. //        PlayOwnedSound(SelectSound, SLOT_Interact,,,,, false);
  450.         ClientPlayForceFeedback(SelectForce);  // jdf
  451.  
  452.         if ( Instigator != None && Instigator.IsLocallyControlled() )
  453.         {
  454.             if ( (Mesh!=None)  )
  455.             {
  456.                 if ( ReloadRequired() )
  457.                 {
  458.                     PlayAnim('SelectUnloaded',SelectAnimRate,0.0);
  459.                     BringUpTime = default.SelectUnloadedTime;
  460.                 }
  461.                 else
  462.                 {
  463.                     PlayAnim('Select',SelectAnimRate,0.0);
  464.                     BringUpTime = default.BringUpTime;
  465.                 }
  466.             }
  467.         }
  468.  
  469.         ClientState = WS_BringUp;
  470.         SetTimer(BringUpTime, false);
  471.     }
  472.     for (Mode = 0; Mode < NUM_FIRE_MODES; Mode++)
  473.     {
  474.         FireMode[Mode].bIsFiring = false;
  475.         FireMode[Mode].HoldTime = 0.0;
  476.         FireMode[Mode].bServerDelayStartFire = false;
  477.         FireMode[Mode].bServerDelayStopFire = false;
  478.         FireMode[Mode].bInstantStop = false;
  479.     }
  480.     if ( (PrevWeapon != None) && PrevWeapon.HasAmmo() && !PrevWeapon.bNoVoluntarySwitch )
  481.         OldWeapon = PrevWeapon;
  482.     else
  483.         OldWeapon = None;
  484.  
  485.     bIsReloading = false;
  486. }
  487.  
  488. simulated function bool PutDown()
  489. {
  490.     local int Mode;
  491.  
  492.     if (ClientState == WS_BringUp || ClientState == WS_ReadyToFire)
  493.     {
  494.         if ( (Instigator.PendingWeapon != None) && !Instigator.PendingWeapon.bForceSwitch )
  495.         {
  496.             for (Mode = 0; Mode < NUM_FIRE_MODES; Mode++)
  497.             {
  498.                 if ( FireMode[Mode].bFireOnRelease && FireMode[Mode].bIsFiring )
  499.                     return false;
  500.                 if ( FireMode[Mode].NextFireTime > Level.TimeSeconds + FireMode[Mode].FireRate*(1.f - MinReloadPct))
  501.                     DownDelay = FMax(DownDelay, FireMode[Mode].NextFireTime - Level.TimeSeconds - FireMode[Mode].FireRate*(1.f - MinReloadPct));
  502.             }
  503.         }
  504.  
  505.         if (Instigator.IsLocallyControlled())
  506.         {
  507.             for (Mode = 0; Mode < NUM_FIRE_MODES; Mode++)
  508.             {
  509.                 if ( FireMode[Mode].bIsFiring )
  510.                     ClientStopFire(Mode);
  511.             }
  512.  
  513.             if ( DownDelay <= 0 )
  514.             {
  515.                 if ( ClientState == WS_BringUp )
  516.                     TweenAnim(SelectAnim,PutDownTime);
  517.                 else if ( HasAnim(PutDownAnim) && HasAmmo() )
  518.                     PlayAnim(PutDownAnim, PutDownAnimRate, 0.0);
  519.             }
  520.         }
  521.         ClientState = WS_PutDown;
  522.         DownDelay = 0;
  523.         SetTimer(PutDownTime, false);
  524.     }
  525.     for (Mode = 0; Mode < NUM_FIRE_MODES; Mode++)
  526.     {
  527.         FireMode[Mode].bServerDelayStartFire = false;
  528.         FireMode[Mode].bServerDelayStopFire = false;
  529.     }
  530.     Instigator.AmbientSound = None;
  531.     OldWeapon = None;
  532.     return true; // return false if preventing weapon switch
  533. }
  534.  
  535.  
  536. simulated function Timer()
  537. {
  538.     local int Mode;
  539.     local float OldDownDelay;
  540.  
  541.     if ( Instigator == none )
  542.         return;
  543.  
  544.     OldDownDelay = DownDelay;
  545.     DownDelay = 0;
  546.  
  547.  
  548.  
  549.     if (ClientState == WS_BringUp)
  550.     {
  551.         for( Mode = 0; Mode < NUM_FIRE_MODES; Mode++ )
  552.            FireMode[Mode].InitEffects();
  553.  
  554.         if ( ReloadRequired() && CanReload() )
  555.             Reload();
  556.         else
  557.             PlayIdle();
  558.         ClientState = WS_ReadyToFire;
  559.     }
  560.     else if (ClientState == WS_PutDown)
  561.     {
  562.         if ( OldDownDelay > 0 )
  563.         {
  564.             if ( HasAnim(PutDownAnim) && HasAmmo() )
  565.                 PlayAnim(PutDownAnim, PutDownAnimRate, 0.0);
  566.             SetTimer(PutDownTime, false);
  567.             return;
  568.         }
  569.         if ( Instigator.PendingWeapon == None )
  570.         {
  571.             if ( ReloadRequired() &&  CanReload()  )
  572.                 Reload();
  573.             else
  574.                 PlayIdle();
  575.             ClientState = WS_ReadyToFire;
  576.         }
  577.         else
  578.         {
  579.             ClientState = WS_Hidden;
  580.             Instigator.ChangedWeapon();
  581.             if ( Instigator.Weapon == self )
  582.             {
  583.                 if ( ReloadRequired() &&  CanReload()  )
  584.                     Reload();
  585.                 else
  586.                     PlayIdle();
  587.                 ClientState = WS_ReadyToFire;
  588.             }
  589.             else
  590.             {
  591.                 for( Mode = 0; Mode < NUM_FIRE_MODES; Mode++ )
  592.                     FireMode[Mode].DestroyEffects();
  593.             }
  594.         }
  595.     }
  596. }
  597.  
  598.  
  599. simulated function PlayIdle()
  600. {
  601.     if (ReloadRequired())
  602.         LoopAnim('AmbientUnloaded',IdleAnimRate,0.25);
  603.     else
  604.     {
  605.         LoopAnim('Ambient',IdleAnimRate,0.25);
  606.         IdleTicks++;
  607.         if ((IdleTicks > (FRand()*3 + 2)) && IdleAnim != '' && IdleAnim != 'None')
  608.         {
  609.             PlayAnim(IdleAnim);
  610.             IdleTicks = 0;
  611.         }
  612.     }
  613. }
  614.  
  615. //Reduce ClipCount every time a bullet is fired.
  616. simulated function bool ConsumeAmmo(int Mode, float load, optional bool bAmountNeededIsMax)
  617. {
  618.     if ( Load > ClipRoundsRemaining )
  619.         return false;
  620.     if( Super.ConsumeAmmo(Mode, Load, bAmountNeededIsMax) )
  621.     {
  622.         ClipRoundsRemaining -= load;
  623.         Ammo_NotifyAmmoChanged();
  624.         return true;
  625.     }
  626.     return false;
  627. }
  628.  
  629. //=============================================================================
  630.  
  631. simulated function DisplayDebug(Canvas Canvas, out float YL, out float YPos)
  632. {
  633.     Super.DisplayDebug(Canvas, YL, YPos);
  634.  
  635.     Canvas.DrawText("ClipRoundsRemaining "$ClipRoundsRemaining);
  636.     YPos += YL;
  637.     Canvas.SetPos(4,YPos);
  638.  
  639.     Canvas.DrawText("ClientRoundsRemaining "$ClientRoundsRemaining);
  640.     YPos += YL;
  641.     Canvas.SetPos(4,YPos);
  642.  
  643.     Canvas.DrawText("ResupplyStatus "$ResupplyStatus());
  644.     YPos += YL;
  645.     Canvas.SetPos(4,YPos);
  646. }
  647.  
  648. simulated final function Actor PlayerSees( float MaxDistance, float MaxLatency )
  649. {
  650.     local vector TempLoc;
  651.     local rotator TempRot;
  652.     return PlayerSeesEx(MaxDistance,MaxLatency,TempLoc,TempRot);
  653. }
  654. simulated final function Actor PlayerSeesEx( float MaxDistance, float MaxLatency, out vector CameraLocation, out rotator CameraRotation )
  655. {
  656.     local vector HitLocation, HitNormal;
  657.     return PlayerSeesEx2(MaxDistance,MaxLatency,CameraLocation,CameraRotation,HitLocation,HitNormal);
  658. }
  659. //NOTE[aleiby]: If you don't hit anything, then HitLocation,HitNormal are undefined.
  660. simulated final function Actor PlayerSeesEx2( float MaxDistance, float MaxLatency, out vector CameraLocation, out rotator CameraRotation, out vector HitLocation, out vector HitNormal )
  661. {
  662.     local vector End;
  663.     local actor Unused;
  664.  
  665.     if(Instigator.Controller == None || PlayerController(Instigator.Controller) == None || PlayerController(Instigator.Controller).Pawn == None )
  666.         return none;
  667.  
  668.     if( (LastViewTargetTime + MaxLatency < Level.TimeSeconds) ||
  669.         ((LastViewTargetActor == None) &&
  670.         (MaxDistance > LastViewTargetTraceDistance)) )
  671.     {
  672.         LastViewTargetTime = Level.TimeSeconds;
  673.         XPlayerCalcView( Unused, LastViewTargetLocation, LastViewTargetRotation );
  674.         End = LastViewTargetLocation + MaxDistance * vector(LastViewTargetRotation);
  675.         LastViewTargetActor = Instigator.Trace( HitLocation, HitNormal, End, LastViewTargetLocation, true );
  676.         LastViewTargetTraceDistance = MaxDistance;
  677.         LastViewTargetActualDistance = VSize(HitLocation - LastViewTargetLocation);
  678.         LastViewTargetHitLocation = HitLocation;
  679.         LastViewTargetHitNormal = HitNormal;
  680.         CameraLocation = LastViewTargetLocation;
  681.         CameraRotation = LastViewTargetRotation;
  682.         return LastViewTargetActor;
  683.     }
  684.     else if ((LastViewTargetActor != None) && (MaxDistance < LastViewTargetActualDistance) )
  685.     {
  686.         CameraLocation = LastViewTargetLocation;
  687.         CameraRotation = LastViewTargetRotation;
  688.         return None;
  689.     }
  690.     else
  691.     {
  692.         CameraLocation = LastViewTargetLocation;
  693.         CameraRotation = LastViewTargetRotation;
  694.         HitLocation = LastViewTargetHitLocation;
  695.         HitNormal = LastViewTargetHitNormal;
  696.         return LastViewTargetActor;
  697.     }
  698. }
  699.  
  700. simulated final function XPlayerCalcView(out actor ViewActor, out vector CameraLocation, out rotator CameraRotation )
  701. {
  702.     local Pawn PTarget;
  703.  
  704.     // If desired, call the pawn's own special callview
  705.     if( Instigator != None && Instigator.bSpecialCalcView )
  706.     {
  707.         // try the 'special' calcview. This may return false if its not applicable, and we do the usual.
  708.         if( Instigator.SpecialCalcView(ViewActor, CameraLocation, CameraRotation) )
  709.             return;
  710.     }
  711.  
  712.     if ( (PlayerController(Instigator.Controller).ViewTarget == None) || PlayerController(Instigator.Controller).ViewTarget.bDeleteMe )
  713.     {
  714.         if ( (Instigator != None) && !Instigator.bDeleteMe )
  715.             PlayerController(Instigator.Controller).SetViewTarget(Instigator);
  716.         else if ( PlayerController(Instigator.Controller).RealViewTarget != None )
  717.             PlayerController(Instigator.Controller).SetViewTarget(PlayerController(Instigator.Controller).RealViewTarget);
  718.         else
  719.             PlayerController(Instigator.Controller).SetViewTarget(PlayerController(Instigator.Controller));
  720.     }
  721.  
  722.     ViewActor = PlayerController(Instigator.Controller).ViewTarget;
  723.     CameraLocation = PlayerController(Instigator.Controller).ViewTarget.Location;
  724.  
  725.     if ( PlayerController(Instigator.Controller).ViewTarget.IsA('Pawn') )
  726.     {
  727.         if( PlayerController(Instigator.Controller).bBehindView ) //up and behind
  728.             PlayerController(Instigator.Controller).CalcBehindView(CameraLocation, CameraRotation, PlayerController(Instigator.Controller).CameraDist * Instigator.Default.CollisionRadius);
  729.         else
  730.             PlayerController(Instigator.Controller).CalcFirstPersonView( CameraLocation, CameraRotation );
  731.         return;
  732.     }
  733.     if ( PlayerController(Instigator.Controller).ViewTarget == PlayerController(Instigator.Controller) )
  734.     {
  735.         CameraRotation = PlayerController(Instigator.Controller).Rotation;
  736.         return;
  737.     }
  738.  
  739.     CameraRotation = PlayerController(Instigator.Controller).ViewTarget.Rotation;
  740.     PTarget = Pawn(PlayerController(Instigator.Controller).ViewTarget);
  741.     if ( PTarget != None )
  742.     {
  743.         if ( PTarget.IsPlayerPawn() )
  744.             CameraRotation = PTarget.GetViewRotation();
  745.         if ( !PlayerController(Instigator.Controller).bBehindView )
  746.             CameraLocation += PTarget.EyePosition();
  747.     }
  748.     if ( PlayerController(Instigator.Controller).bBehindView )
  749.     {
  750.         CameraLocation = CameraLocation + (PlayerController(Instigator.Controller).ViewTarget.Default.CollisionHeight - PlayerController(Instigator.Controller).ViewTarget.CollisionHeight) * vect(0,0,1);
  751.         PlayerController(Instigator.Controller).CalcBehindView(CameraLocation, CameraRotation, PlayerController(Instigator.Controller).CameraDist * PlayerController(Instigator.Controller).ViewTarget.Default.CollisionRadius);
  752.     }
  753. }
  754.  
  755. //=============================================================================
  756. // Weapon rendering
  757. // Draw first person view of inventory
  758. simulated event RenderOverlays( canvas Canvas )
  759. {
  760.     if ( Instigator == None )
  761.         return;
  762.  
  763.     if ( bUpdateCrosshair && PlayerController(Instigator.Controller) != None )
  764.         UpdateCrosshair( Canvas );
  765.  
  766.     Super.RenderOverlays(Canvas);
  767. }
  768.  
  769. simulated function UpdateCrosshair( Canvas Canvas ) //GE: HitActor is usually the enemy.
  770. {
  771.     local Actor HitActor;
  772.     local vector ViewLoc;
  773.     local rotator ViewRot;
  774.     local Pawn Target;
  775.  
  776.     HitActor = PlayerSeesEx( TraceDist, 0.25, ViewLoc, ViewRot );
  777.     HandleTargetDetails( HitActor, Canvas, ViewLoc, ViewRot );
  778.  
  779.     if( !bGlowing && HitActor!=none && IsTargetable(HitActor) )
  780.     {
  781.         Target = Pawn(HitActor);
  782.         if( Target!=none && !Target.bPendingDelete && Target.PlayerReplicationInfo!=none
  783.             && Target.PlayerReplicationInfo.Team!=none && Target.PlayerReplicationInfo.Team.TeamIndex != Instigator.PlayerReplicationInfo.Team.TeamIndex )
  784.         {
  785.             LastTargetName = Target.PlayerReplicationInfo.PlayerName;
  786.             //SendEvent("TargetIDOn");
  787.         }
  788.  
  789.         bGlowing=true;
  790.         //SendEvent("Glow");
  791.     }
  792.     else if( bGlowing && (HitActor==none || !IsTargetable(HitActor)) )
  793.     {
  794.         bGlowing=false;
  795.         //SendEvent("UnGlow");
  796.         //SendEvent("TargetIDOff");
  797.     }
  798. }
  799.  
  800. simulated function HandleTargetDetails( Actor A, Canvas Canvas, vector ViewLoc, rotator ViewRot );
  801.  
  802. simulated function bool IsTargetable( Actor A )
  803. {
  804.     local int i;
  805.  
  806.     if( A==Owner )
  807.         return false;
  808.     if( A.bHidden )
  809.         return false;
  810.     if( A.Physics == PHYS_None ) // don't target carcasses & such?
  811.         return false;
  812.  
  813.     for( i=0; i<TargetableTypes.Length; i++ )
  814.         if( A.IsA( TargetableTypes[i] ) )
  815.             return true;
  816.  
  817.     return false;
  818. }
  819.  
  820.  
  821. static function bool IsValidDefaultInventory( pawn PlayerPawn ) { return true; }
  822.  
  823.  
  824.  
  825. simulated function Weapon RecommendWeapon( out float rating )
  826. {
  827.     local Weapon Recommended;
  828.     local float oldRating;
  829.  
  830.     if ( Instigator.IsHumanControlled() )
  831.         rating = SwitchPriority();
  832.     else
  833.     {
  834.         rating = RateSelf();
  835.         if ( (self == Instigator.Weapon) && (Instigator.Controller.Enemy != None) && HasAmmo() )
  836.             rating += 0.21; // tend to stick with same weapon
  837.             rating += Instigator.Controller.WeaponPreference(self);
  838.     }
  839.     if ( inventory != None )
  840.     {
  841.         Recommended = inventory.RecommendWeapon(oldRating);
  842.         if ( (Recommended != None) && (oldRating > rating) )
  843.         {
  844.             rating = oldRating;
  845.             return Recommended;
  846.         }
  847.     }
  848.     return self;
  849. }
  850.  
  851. // Return the switch priority of the weapon (normally AutoSwitchPriority, but may be
  852. // modified by environment (or by other factors for bots)
  853. simulated function float SwitchPriority()
  854. {
  855.     if ( !Instigator.IsHumanControlled() )
  856.         return RateSelf();
  857.     else if ( !HasAmmo() )
  858.     {
  859.         if ( Pawn(Owner).Weapon == self )
  860.             return -0.5;
  861.         else
  862.             return -1;
  863.     }
  864.     else
  865.         return default.AutoSwitchPriority;
  866. }
  867.  
  868. //mdfxmp 2003.09.01 BEGIN
  869. //-----------------------------------------------------------------------------
  870. // Subclasses can return values > 0.0 to indicate that they should be switched
  871. // to instead of using SwitchToBestWeapon when a SwitchAway occurs (due to out
  872. // of ammo). e.g. when placing deployable items (turrets, fieldgenerators), we
  873. // can force a switch to another deployable item which has ammo rather than
  874. // switching to the best weapon (so player can place all turrets etc.).
  875.  
  876. simulated function float GetSpecialSwitchPriority( Weapon OldWeapon )
  877. {
  878.     return 0.0;
  879. }
  880.  
  881. //-----------------------------------------------------------------------------
  882. // Calls GetSpecialSwitchPriority on all weapons in Instigator's inventory, and
  883. // switches to the weapon which returned the highest switch priority, if this
  884. // is > 0.0. Returns true if a swich occurred, false otherwise.
  885.  
  886. simulated function bool SpecialSwitchAway()
  887. {
  888.     local Inventory Inv;
  889.     local float SwitchPriority, BestSwitchPriority;
  890.     local U2Weapon W, BestWeapon;
  891.  
  892.     for( Inv = Instigator.Inventory; Inv != None; Inv = Inv.Inventory )
  893.     {
  894.         W = U2Weapon(Inv);
  895.         if( W != None )
  896.         {
  897.             SwitchPriority = W.GetSpecialSwitchPriority( Self );
  898.  
  899.             if( SwitchPriority > 0.0 && SwitchPriority > BestSwitchPriority )
  900.             {
  901.                 BestWeapon = W;
  902.                 BestSwitchPriority = SwitchPriority;
  903.             }
  904.         }
  905.     }
  906.  
  907.     if( BestWeapon != None )
  908.     {
  909.         Instigator.PendingWeapon = BestWeapon;
  910.         Instigator.ChangedWeapon();
  911.         return true;
  912.     }
  913.  
  914.     return false;
  915. }
  916.  
  917. //-----------------------------------------------------------------------------
  918. // Allow weapons in instigator's inventory to override switching to the best
  919. // weapon if applicable.
  920.  
  921. simulated function SwitchAway()
  922. {
  923.     if( !SpecialSwitchAway() )
  924.         Instigator.Controller.SwitchToBestWeapon();
  925. }
  926. //mdfxmp 2003.09.01 END
  927.  
  928. simulated function DoAutoSwitch()
  929. {
  930.     if( !SpecialSwitchAway() )
  931.         Instigator.Controller.SwitchToBestWeapon();
  932. }
  933.  
  934.  
  935.  
  936. static final function float Blend( float A, float B, float Pct )
  937. {
  938.     return A + ((B-A) * Pct);
  939. }
  940.  
  941. static final function float Ablend( float A, float B, float Result )
  942. {
  943.     return (Result-A)/(B-A);
  944. }
  945.  
  946. static final function float BlendR( Range R, float Pct )
  947. {
  948.     return Blend( R.Min, R.Max, Pct );
  949. }
  950.  
  951. static final function float AblendR( Range R, float Result )
  952. {
  953.     return ABlend( R.Min, R.Max, Result );
  954. }
  955.  
  956.  
  957.  
  958. exec function offset()
  959. {
  960.     Instigator.ClientMessage("X=" $ PlayerViewOffset.X);
  961.     Instigator.ClientMessage("Y=" $ PlayerViewOffset.Y);
  962.     Instigator.ClientMessage("Z=" $ PlayerViewOffset.Z);
  963. }
  964.  
  965. exec function soffset()
  966. {
  967.     Instigator.ClientMessage("X=" $ SmallViewOffset.X);
  968.     Instigator.ClientMessage("Y=" $ SmallViewOffset.Y);
  969.     Instigator.ClientMessage("Z=" $ SmallViewOffset.Z);
  970. }
  971.  
  972. exec function soffsetX(float XPos)
  973. {
  974.     SmallViewOffset.X = XPos;
  975. }
  976.  
  977. exec function soffsetY(float YPos)
  978. {
  979.     SmallViewOffset.Y = YPos;
  980. }
  981.  
  982. exec function soffsetZ(float ZPos)
  983. {
  984.     SmallViewOffset.Z = ZPos;
  985. }
  986.  
  987. simulated function bool Ammo_CanReload()
  988. {
  989.     return ( (AmmoAmount(0) > ClipRoundsRemaining) && (ClipRoundsRemaining < ClipSize) );
  990. }
  991.  
  992. simulated function bool ReadyToReload()
  993. {
  994.     local int Mode;
  995.  
  996.     for (Mode = 0; Mode < NUM_FIRE_MODES; Mode++)
  997.     {
  998.         if ( FireMode[Mode].bFireOnRelease && FireMode[Mode].bIsFiring )
  999.             return false;
  1000.         if ( FireMode[Mode].NextFireTime > Level.TimeSeconds)
  1001.             return false;
  1002.     }
  1003.     return true;
  1004. }
  1005.  
  1006. exec function Reload()
  1007. {
  1008.  
  1009.     bPendingReload = false;
  1010.     if ( HasAmmo() && CanReload() )
  1011.     {
  1012.  
  1013.         //go to the state for the duration of the reload
  1014.         GotoState('Reloading');
  1015.         ClientReload();
  1016.     }
  1017. }
  1018.  
  1019.  
  1020. simulated exec function ClientReload()
  1021. {
  1022.     if (Role >= ROLE_Authority)
  1023.        return;
  1024.  
  1025.     GotoState('Reloading'); // only do this if on the client machine
  1026. }
  1027.  
  1028. simulated state Reloading
  1029. {
  1030. ignores Fire,AltFire,Reload;
  1031.     simulated function bool PutDown()
  1032.     {
  1033.         if ( Global.PutDown() )
  1034.         {
  1035.             GotoState('Hidden');
  1036.             return true;
  1037.         }
  1038.         else
  1039.         {
  1040.             return false;
  1041.         }
  1042.     }
  1043.  
  1044.     simulated function PlayIdle();
  1045.  
  1046.     simulated event BeginState()
  1047.     {
  1048.         //local int Mode;
  1049.  
  1050.         //ClientState = WS_BringUp;
  1051.         bIsReloading = true;
  1052.         log(self$": I'm inside Reloading!");
  1053.  
  1054.     }
  1055.     simulated event EndState()
  1056.     {
  1057.         //ClientState = WS_ReadyToFire;
  1058.         ReloadTime = default.ReloadTime;
  1059.         bLastRound = false;
  1060.         bIsReloading = false;
  1061.         log(self$": No longer Reloading! IsFiring"@IsFiring());
  1062.     }
  1063.  
  1064. Begin:
  1065.     if ( Instigator.IsLocallyControlled() )
  1066.     {
  1067.         FireMode[0].NextFireTime = Level.TimeSeconds + ReloadTime;
  1068.         FireMode[1].NextFireTime = Level.TimeSeconds + ReloadTime;
  1069.     }
  1070.  
  1071.     PlayReloading();
  1072.     Sleep(ReloadTime);
  1073.     Ammo_Reload();
  1074.  
  1075.     GotoState('Hidden');
  1076. }
  1077.  
  1078. simulated function PlayReloading()
  1079. {
  1080.     if ( xPawn(Instigator) != none )
  1081.     {
  1082.         if (xPawn(Instigator).Species == class'XGame.SPECIES_Alien') //GE: A hackish way of determining it's an alien mesh
  1083.             xPawn(Instigator).SetAnimAction('Idle_Character01');
  1084.         else
  1085.             xPawn(Instigator).SetAnimAction('Weapon_Switch');
  1086.     }
  1087.     if( !bLastRound )
  1088.     {
  1089.         PlayAnimEx(ReloadAnim, ReloadAnimRate);
  1090.         //Instigator.PlaySound(ReloadSound,SLOT_Misc,1.0,,TransientSoundRadius*0.3);
  1091.         PlayOwnedSound(ReloadSound,SLOT_Interact,TransientSoundVolume,,TransientSoundRadius,,false);
  1092.     }
  1093.     else
  1094.     {
  1095.         if( LastAnim!=U2WeaponFire(FireMode[0]).default.AnimFireLastReload &&
  1096.             LastAnim!=U2WeaponFire(FireMode[1]).default.AnimFireLastReload )
  1097.         {
  1098.             //if ( Role == ROLE_Authority )
  1099.             //  Instigator.ClientMessage( "LastAnim: " $ LastAnim );
  1100.  
  1101.             PlayAnimEx('ReloadUnloaded');
  1102.             if( default.ReloadUnloadedTime!=0.0 )
  1103.                 ReloadTime=default.ReloadUnloadedTime;
  1104.         }
  1105.         //Instigator.PlaySound(ReloadUnloadedSound,SLOT_Misc,1.0,,TransientSoundRadius*0.3);
  1106.         PlayOwnedSound(ReloadUnloadedSound,SLOT_Interact,TransientSoundVolume,,TransientSoundRadius,,false);
  1107.     }
  1108. }
  1109.  
  1110. //DEBUG --
  1111. simulated function Fire(float F)
  1112. {
  1113.     log(self$": Fire()");
  1114. }
  1115. /*simulated event ClientStartFire(int Mode)
  1116. {
  1117.     log(self$": ClientStartFire()");
  1118.     if ( Pawn(Owner).Controller.IsInState('GameEnded') || Pawn(Owner).Controller.IsInState('RoundEnded') )
  1119.         return;
  1120.     if (Role < ROLE_Authority)
  1121.     {
  1122.         if (StartFire(Mode))
  1123.         {
  1124.             ServerStartFire(Mode);
  1125.         }
  1126.     }
  1127.     else
  1128.     {
  1129.         StartFire(Mode);
  1130.     }
  1131.     //Super.ClientStartFire(Mode);
  1132. }*/
  1133. simulated event ClientStopFire(int Mode)
  1134. {
  1135.     log(self$": ClientStopFire()");
  1136.     Super.ClientStopFire(Mode);
  1137. }
  1138. event ServerStartFire(byte Mode)
  1139. {
  1140.     log(self$": ServerStartFire()");
  1141.     Super.ServerStartFire(Mode);
  1142. }
  1143. function ServerStopFire(byte Mode)
  1144. {
  1145.     log(self$": ServerStopFire()");
  1146.     Super.ServerStopFire(Mode);
  1147. }
  1148. //StartFire below
  1149. simulated event StopFire(int Mode)
  1150. {
  1151.     log(self$": StopFire()");
  1152.     Super.StopFire(Mode);
  1153. }
  1154. //-- GUBED
  1155.  
  1156. simulated function Ammo_Reload()
  1157. {
  1158.     local float AmmoMax,AmmoCount;
  1159.  
  1160.     GetAmmoCount(AmmoMax,AmmoCount);
  1161.     Ammo_SetClipRoundsRemaining(Min(ClipSize,AmmoCount));
  1162. }
  1163.  
  1164. simulated function bool StartFire(int mode) //GE: Reload on (usually) AltFire, if costs more.
  1165. {
  1166.     log(self$": StartFire()");
  1167.     if (U2WeaponFire(FireMode[mode]).Ammo_ReloadRequired(U2WeaponFire(FireMode[mode]).AmmoPerFire) && CanReload() )
  1168.         Reload();
  1169.     return Super.StartFire(mode);
  1170. }
  1171.  
  1172. //-----------------------------------------------------------------------------
  1173. //GE: AI code follows.
  1174.  
  1175. //GE: Modifies the AI rating. This decides what weapon to bring up.
  1176. /*
  1177.  * GE: Unreal II knows these ranges:
  1178.  * Inside minimum - always at RatingInsideMin
  1179.  * Minimum - peaks with RatingRangeMin
  1180.  * Ideal - peaks with RatingRangeIdeal
  1181.  * Maximum - peaks with RatingRangeMax
  1182.  * Limit - peaks with RatingRangeLimit, always RatingIneffective when more
  1183.  */
  1184. function float GetAIRating()
  1185. {
  1186.     local Bot B;
  1187.     local float EnemyDist;
  1188.  
  1189.     B = Bot(Instigator.Controller);
  1190.     if ( (B == None) || (B.Enemy == None) )
  1191.         return AIRating; //GE: No enemy? Prepare your favourite.
  1192.  
  1193.     EnemyDist = VSize(B.Enemy.Location - Instigator.Location);
  1194.  
  1195.     //log("U2Weapon: AI rating for"@self@"at"@EnemyDist@"is"@Max(GetPrimaryRating(EnemyDist), GetSecondaryRating(EnemyDist)));
  1196.     return FMax(GetPrimaryRating(EnemyDist), GetSecondaryRating(EnemyDist))*Lerp(AmmoStatus(), 0.9, 1.1);
  1197. }
  1198.  
  1199. //GE: Choose from regular or alt fire.
  1200. function byte BestMode()
  1201. {
  1202.     local Bot B;
  1203.     local float EnemyDist;
  1204.  
  1205.     B = Bot(Instigator.Controller);
  1206.     if ( (B == None) || (B.Enemy == None) )
  1207.         return byte(AIRatingFire < AIRatingAltFire);//GE: No enemy? Return the higher rating.
  1208.  
  1209.     EnemyDist = VSize(B.Enemy.Location - Instigator.Location);
  1210.     if (GetPrimaryRating(EnemyDist) < GetSecondaryRating(EnemyDist))
  1211.         return 1;
  1212.     return 0;
  1213. }
  1214.  
  1215. function float GetPrimaryRating(float EnemyDist)
  1216. {
  1217.     //GE: Calc primary fire rating.
  1218.     if ( EnemyDist < RangeMinFire ) //GE: Inside minimum range
  1219.         return RatingInsideMinFire;
  1220.     if ( EnemyDist <= RangeLimitFire ) //GE: Inside the interpolation curve.
  1221.        return InterpCurveEval(RatingCurveFire, EnemyDist);
  1222.     //GE: More than limit range
  1223.     return RatingIneffective;
  1224. }
  1225.  
  1226. function float GetSecondaryRating(float EnemyDist)
  1227. {
  1228.     //GE: Calc secondary fire rating.
  1229.     if ( EnemyDist < RangeMinAltFire ) //GE: Inside minimum range
  1230.         return RatingInsideMinAltFire;
  1231.     if ( EnemyDist <= RangeLimitAltFire ) //GE: Inside the interpolation curve.
  1232.         return InterpCurveEval(RatingCurveAltFire, EnemyDist);
  1233.     //GE: More than limit range
  1234.     return RatingIneffective;
  1235. }
  1236.  
  1237. //GE: Builds the interpolation curves. Call this to rebuild them?
  1238. function BuildInterpolationCurves()
  1239. {
  1240.     local InterpCurvePoint ICP;
  1241.     //local int i;
  1242.  
  1243.     //GE: Make sure the input is valid, and build the curve for primary fire.
  1244.     //GE: Invalid points are omitted from the curve.
  1245.     if (RangeMinFire >= 0.0)
  1246.     {
  1247.         ICP.InVal=RangeMinFire;
  1248.         ICP.OutVal=RatingRangeMinFire;
  1249.         RatingCurveFire.Points[RatingCurveFire.Points.Length]=ICP;
  1250.     }
  1251.     if (RangeIdealFire >= 0.0)
  1252.     {
  1253.         ICP.InVal=RangeIdealFire;
  1254.         ICP.OutVal=RatingRangeIdealFire;
  1255.         RatingCurveFire.Points[RatingCurveFire.Points.Length]=ICP;
  1256.     }
  1257.     if (RangeMaxFire >= 0.0)
  1258.     {
  1259.         ICP.InVal=RangeMaxFire;
  1260.         ICP.OutVal=RatingRangeMaxFire;
  1261.         RatingCurveFire.Points[RatingCurveFire.Points.Length]=ICP;
  1262.     }
  1263.     if (RangeLimitFire >= 0.0)
  1264.     {
  1265.         ICP.InVal=RangeLimitFire;
  1266.         ICP.OutVal=RatingRangeLimitFire;
  1267.         RatingCurveFire.Points[RatingCurveFire.Points.Length]=ICP;
  1268.     }
  1269.  
  1270.     //GE: Now the same for secondary fire.
  1271.     if (RangeMinAltFire >= 0.0)
  1272.     {
  1273.         ICP.InVal=RangeMinAltFire;
  1274.         ICP.OutVal=RatingRangeMinAltFire;
  1275.         RatingCurveAltFire.Points[RatingCurveAltFire.Points.Length]=ICP;
  1276.     }
  1277.     if (RangeIdealAltFire >= 0.0)
  1278.     {
  1279.         ICP.InVal=RangeIdealAltFire;
  1280.         ICP.OutVal=RatingRangeIdealAltFire;
  1281.         RatingCurveAltFire.Points[RatingCurveAltFire.Points.Length]=ICP;
  1282.     }
  1283.     if (RangeMaxAltFire >= 0.0)
  1284.     {
  1285.         ICP.InVal=RangeMaxAltFire;
  1286.         ICP.OutVal=RatingRangeMaxAltFire;
  1287.         RatingCurveAltFire.Points[RatingCurveAltFire.Points.Length]=ICP;
  1288.     }
  1289.     if (RangeLimitAltFire >= 0.0)
  1290.     {
  1291.         ICP.InVal=RangeLimitAltFire;
  1292.         ICP.OutVal=RatingRangeLimitAltFire;
  1293.         RatingCurveAltFire.Points[RatingCurveAltFire.Points.Length]=ICP;
  1294.     }
  1295.  
  1296.     //GE: Failed to provide any meaningful information? Build it as a flat line with RatingLow everywhere.
  1297.     if (RatingCurveFire.Points.Length == 0)
  1298.     {
  1299.         RatingCurveFire.Points.Length=2;
  1300.         RatingCurveFire.Points[0].InVal=0.0;
  1301.         RatingCurveFire.Points[0].OutVal=RatingLow;
  1302.         RatingCurveFire.Points[1].InVal=RangeUnlimited;
  1303.         RatingCurveFire.Points[1].OutVal=RatingLow;
  1304.     }
  1305.     if (RatingCurveAltFire.Points.Length == 0)
  1306.     {
  1307.         RatingCurveAltFire.Points.Length=2;
  1308.         RatingCurveAltFire.Points[0].InVal=0.0;
  1309.         RatingCurveAltFire.Points[0].OutVal=RatingLow;
  1310.         RatingCurveAltFire.Points[1].InVal=RangeUnlimited;
  1311.         RatingCurveAltFire.Points[1].OutVal=RatingLow;
  1312.     }
  1313. }
  1314.  
  1315. defaultproperties
  1316. {
  1317.      bAllowCustomCrosshairs=True
  1318.      TraceDist=10000.000000
  1319.      TargetableTypes(0)="Pawn"
  1320.      bUpdateCrosshair=True
  1321.      bUpdateLocation=True
  1322.      bDrawWeapon=True
  1323.      bClearZ=True
  1324.      ReloadAnim="Reload"
  1325.      ReloadAnimRate=1.000000
  1326.      ClipSize=1
  1327.      ReloadTime=1.000000
  1328.      DownUnloadedTime=0.533000
  1329.      SelectUnloadedTime=0.600000
  1330.      SelectAnimRate=1.000000
  1331.      PutDownAnimRate=1.000000
  1332.      PutDownTime=0.533000
  1333.      BringUpTime=0.600000
  1334.      DisplayFOV=60.000000
  1335.      PlayerViewOffset=(X=30.000000,Z=-5.000000)
  1336.      PlayerViewPivot=(Yaw=-16384)
  1337.      BobDamping=0.700000
  1338.      NetUpdateFrequency=1.000000
  1339.      TransientSoundVolume=1.000000
  1340.  
  1341.      AmbientGlow=0
  1342.  
  1343.     bAimFire=true
  1344.     bAimAltFire=true
  1345.     bFireEnabledForOwner=true
  1346.     bAltFireEnabledForOwner=true
  1347.  
  1348.     RangeMinFire=-1.000000
  1349.     RangeIdealFire=-1.000000
  1350.     RangeMaxFire=-1.000000
  1351.     RangeLimitFire=-1.000000
  1352.     RatingInsideMinFire=-10.000000
  1353.     RatingRangeMinFire=-1.000000
  1354.     RatingRangeIdealFire=-1.000000
  1355.     RatingRangeMaxFire=-1.000000
  1356.     RatingRangeLimitFire=-1.000000
  1357.     AIRatingFire=-99.999001
  1358.     RangeMinAltFire=-1.000000
  1359.     RangeIdealAltFire=-1.000000
  1360.     RangeMaxAltFire=-1.000000
  1361.     RangeLimitAltFire=-1.000000
  1362.     RatingInsideMinAltFire=-10.000000
  1363.     RatingRangeMinAltFire=-1.000000
  1364.     RatingRangeIdealAltFire=-1.000000
  1365.     RatingRangeMaxAltFire=-1.000000
  1366.     RatingRangeLimitAltFire=-1.000000
  1367.     AIRatingAltFire=-99.999001
  1368.  
  1369. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement