class ScrnDeagle extends Deagle; //deagle has an additional fix for the hammer //and also extra slide movement //and extra slide locked back travel var name ReloadShortAnim; var float ReloadShortRate; var transient bool bShortReload; var transient bool bTweeningSlide; var transient bool bAnimatingHammer; var transient bool bEnhancedSlideMovement; //adding extra slide movement to fire animation var transient float SlideMoveRate; //stores total amount of time each slide movement is (in cases where fire animation is sped up) var transient float SlideMoveBackTime; var transient float SlideMoveForwardTime; //var transient float SlideLockMult; var bool bSlideReturned; var float DefaultSlideReturnStartMult; //multiplier for reload timer to start slide return var float DefaultSlideReturnEndMult; //multiplier for reload timer to start slide return var float SlideReturnStartTime; //time to that slide finishes moving forward for empty reload (in multiplier of reloadrate) var float SlideReturnEndTime; //time to that slide finishes moving forward for empty reload (in multiplier of reloadrate) var float SlideReturnDuration; //amount of time in seconds the slide returns for var transient float HammerRotateRate; var transient float HammerRotateBackTime; var transient float HammerRotateForwardTime; var transient float HammerRotateMult; var float DefaultSlideMoveMult; var float DefaultHammerRotateMult; var float DefaultHammerRotateRate; var float TweenEndTime; var vector PistolSlideOffset; //for tactical reload var vector PistolSlideLockedOffset; //for tactical reload var rotator PistolHammerRotation; //for deagle's stupid hammer var bool bFiringLastRound; simulated function PostNetReceive() { super.PostNetReceive(); if ( Role < ROLE_Authority ) { if ( MagAmmoRemaining == 0 && !bIsReloading ) { LockSlideBack(); RotateHammerBack(); } } } simulated function Fire(float F) { bFiringLastRound = MagAmmoRemaining == 1; super.Fire(f); } simulated function BringUp(optional Weapon PrevWeapon) { Super.BringUp(PrevWeapon); RotateHammerBack(); //always do this now if (MagAmmoRemaining == 0) LockSlideBack(); } simulated function bool PutDown() { if ( Instigator.PendingWeapon.class == class'ScrnBalanceSrv.ScrnDualDeagle' ) { bIsReloading = false; } return super(KFWeapon).PutDown(); } simulated function ResetSlidePosition() { SetBoneLocation( 'Slide', PistolSlideOffset, 0 ); //reset slide position } simulated function ResetHammerRotation() { SetBoneRotation( 'Hammer', PistolHammerRotation, , 0); //reset hammer rotation } simulated function LockSlideBack() { SetBoneLocation( 'Slide', -1.4*PistolSlideOffset, 100 ); //lock slide back a lot } simulated function RotateHammerBack() { SetBoneRotation( 'Hammer', -1*PistolHammerRotation, , 100); //set hammer rotation for empty reload } //used for tactical reload simulated function InterpolateSlide(float time) { local rotator AdjustedHammerPitch; AdjustedHammerPitch.Pitch = 120*time*5; SetBoneLocation( 'Slide', PistolSlideOffset, (time*500) ); // SetBoneRotation( 'Hammer', AdjustedHammerPitch-PistolHammerRotation, ,100 ); //(Pitch=120,Yaw=0,Roll=0) } //used for enhanced slide movement backwards during firing simulated function MoveSlideSmooth(float rate, bool bMovingSlideBack) { local float RateMult; //calculate how much rate should be multiplied by to give 100 at end RateMult = 100/SlideMoveRate; if(bMovingSlideBack ) SetBoneLocation( 'Slide', -DefaultSlideMoveMult*PistolSlideOffset, Rate*RateMult ); //move slide back else SetBoneLocation( 'Slide', -DefaultSlideMoveMult*PistolSlideOffset, 100 - Rate*RateMult ); //move slide forward } //used for enhanced hammer rotation forwards during firing simulated function RotateHammerSmooth(float rate, bool bRotatingHammerBack) { local float RateMult; //calculate how much rate should be multiplied by to give 100 at end RateMult = 100/HammerRotateRate; if(bRotatingHammerBack ) SetBoneRotation( 'Hammer', -1*PistolHammerRotation, ,100 - Rate*RateMult/3 ); //needs to move from 0 to -120 else SetBoneRotation( 'Hammer', 0.3*PistolHammerRotation, , 100- Rate*RateMult ); //needs to move from 0 to 45 } //returns slide after empty reload simulated function DoSlideReturn() { bSlideReturned = false; SlideReturnStartTime = Level.TimeSeconds + DefaultSlideReturnStartMult*ReloadRate; SlideReturnEndTime = Level.TimeSeconds + DefaultSlideReturnEndMult*ReloadRate; SlideReturnDuration = SlideReturnEndTime - SlideReturnStartTime; } simulated function ReturnSlideSmooth(float rate) { local float RateMult; RateMult = 100/SlideReturnDuration; //calculate how much rate should be multiplied by to give 100 at end SetBoneLocation( 'Slide', -0.45*DefaultSlideMoveMult*PistolSlideOffset, (rate*rateMult) ); //return slide back from -0.45 to 0 SetBoneRotation( 'Hammer', -1*PistolHammerRotation, ,100 - (rate*rateMult) ); //needs to move from 0 to -120 } //this function makes slide move back more when firing because default animation moves less than 9mm and looks really bad simulated function AddExtraSlideMovement(float FireRateMod) { bEnhancedSlideMovement = True; SlideMoveRate = 0.04/FireRateMod; //0.08 SlideMoveBackTime = Level.TimeSeconds + SlideMoveRate; //set time SlideMoveForwardTime = Level.TimeSeconds + 2*SlideMoveRate; //set time } //this function sets the times for hammer drop simulated function DoHammerDrop(float FireRateMod) { bAnimatingHammer = True; HammerRotateRate = 0.04/FireRateMod; //0.08 HammerRotateForwardTime = Level.TimeSeconds + HammerRotateRate; //set time HammerRotateBackTime = Level.TimeSeconds + 4*HammerRotateRate; //set time (3 times longer than) } simulated function HandleSlideMovement() { if (TweenEndTime > 0) { if (TweenEndTime - Level.TimeSeconds > 0) InterpolateSlide(TweenEndTime - Level.TimeSeconds); if (TweenEndTime - Level.TimeSeconds < 0) { ResetSlidePosition(); TweenEndTime = 0; bTweeningSlide = false; } } } simulated function EnhanceSlideMovement() { if (Level.TimeSeconds < SlideMoveBackTime && Level.TimeSeconds < SlideMoveForwardTime ) MoveSlideSmooth(SlideMoveBackTime - Level.TimeSeconds, false); //move slide backwards with vector and "rate" if (Level.TimeSeconds > SlideMoveBackTime ) MoveSlideSmooth(SlideMoveForwardTime - Level.TimeSeconds, true); //move slide forwards with vector and "rate" if (Level.TimeSeconds > SlideMoveForwardTime ) { bEnhancedSlideMovement = false; //finished moving slide ResetSlidePosition(); //reset it to normal position } } simulated function DoHammerRotation() { if (Level.TimeSeconds < HammerRotateForwardTime && Level.TimeSeconds < HammerRotateBackTime ) RotateHammerSmooth(HammerRotateForwardTime - Level.TimeSeconds, false); //rotate hammer forwards if (Level.TimeSeconds > HammerRotateForwardTime ) RotateHammerSmooth(HammerRotateBackTime - Level.TimeSeconds, true); //rotate hammer backwards if (Level.TimeSeconds > HammerRotateBackTime ) { bAnimatingHammer = false; //finished rotating hammer RotateHammerBack(); //reset it to normal position ResetSlidePosition(); } } simulated function ReleaseEnhancedSlide() { if (bIsReloading && !bShortReload && !bSlideReturned && Level.TimeSeconds > SlideReturnStartTime && Level.TimeSeconds < SlideReturnEndTime) { ReturnSlideSmooth( SlideReturnEndTime - Level.TimeSeconds ); //0 to 100 } if (Level.TimeSeconds > SlideReturnEndTime) { bSlideReturned = true; SlideReturnEndTime = 0; RotateHammerBack(); //reset it to normal position } } simulated function WeaponTick(float dt) { if (Level.NetMode != NM_DedicatedServer) { if (bTweeningSlide ) { HandleSlideMovement(); } if (bEnhancedSlideMovement) { EnhanceSlideMovement(); } if (bAnimatingHammer) { DoHammerRotation(); } if (SlideReturnEndTime > 0) { ReleaseEnhancedSlide(); } } Super.WeaponTick(dt); } //allowing +1 reload with full mag simulated function bool AllowReload() { UpdateMagCapacity(Instigator.PlayerReplicationInfo); if(KFInvasionBot(Instigator.Controller) != none && !bIsReloading && MagAmmoRemaining <= MagCapacity && AmmoAmount(0) > MagAmmoRemaining) return true; if(KFFriendlyAI(Instigator.Controller) != none && !bIsReloading && MagAmmoRemaining <= MagCapacity && AmmoAmount(0) > MagAmmoRemaining) return true; if(FireMode[0].IsFiring() || FireMode[1].IsFiring() || bIsReloading || MagAmmoRemaining > MagCapacity || ClientState == WS_BringUp || AmmoAmount(0) <= MagAmmoRemaining || (FireMode[0].NextFireTime - Level.TimeSeconds) > 0.1 ) return false; return true; } simulated function ClientFinishReloading() { PlayIdle(); RotateHammerBack(); if(bShortReload) StartTweeningSlide(); //start tweening slide back else ResetSlidePosition(); //since deagle has additional slide correction bIsReloading = false; if(Instigator.PendingWeapon != none && Instigator.PendingWeapon != self) Instigator.Controller.ClientSwitchToBestWeapon(); } exec function ReloadMeNow() { local float ReloadMulti; if(!AllowReload()) return; if ( bHasAimingMode && bAimingRifle ) { FireMode[1].bIsFiring = False; ZoomOut(false); if( Role < ROLE_Authority) ServerZoomOut(false); } if ( KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo) != none && KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo).ClientVeteranSkill != none ) ReloadMulti = KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo).ClientVeteranSkill.Static.GetReloadSpeedModifier(KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo), self); else ReloadMulti = 1.0; bIsReloading = true; ReloadTimer = Level.TimeSeconds; bShortReload = MagAmmoRemaining > 0; if ( bShortReload ) ReloadRate = Default.ReloadShortRate / ReloadMulti; else ReloadRate = Default.ReloadRate / ReloadMulti; if( bHoldToReload ) { NumLoadedThisReload = 0; } ClientReload(); Instigator.SetAnimAction(WeaponReloadAnim); if ( Level.Game.NumPlayers > 1 && KFGameType(Level.Game).bWaveInProgress && KFPlayerController(Instigator.Controller) != none && Level.TimeSeconds - KFPlayerController(Instigator.Controller).LastReloadMessageTime > KFPlayerController(Instigator.Controller).ReloadMessageDelay ) { KFPlayerController(Instigator.Controller).Speech('AUTO', 2, ""); KFPlayerController(Instigator.Controller).LastReloadMessageTime = Level.TimeSeconds; } } simulated function ClientReload() { local float ReloadMulti; if ( bHasAimingMode && bAimingRifle ) { FireMode[1].bIsFiring = False; ZoomOut(false); if( Role < ROLE_Authority) ServerZoomOut(false); } if ( KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo) != none && KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo).ClientVeteranSkill != none ) ReloadMulti = KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo).ClientVeteranSkill.Static.GetReloadSpeedModifier(KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo), self); else ReloadMulti = 1.0; bIsReloading = true; ResetHammerRotation(); //use reload animation's if (MagAmmoRemaining <= 0) { bShortReload = false; PlayAnim(ReloadAnim, ReloadAnimRate*ReloadMulti, 0.001); SetBoneLocation( 'Slide', -0.45*PistolSlideOffset, 100 ); //special case for deagle because default slide animation sucks DoSlideReturn(); //sets times for slide return } else if (MagAmmoRemaining >= 1) { bShortReload = true; PlayAnim(ReloadShortAnim, ReloadAnimRate*ReloadMulti, 0.001); //reduced tween time to prevent slide from sliding SetBoneLocation( 'Slide', PistolSlideOffset, 100 ); //move the slide forward } } simulated function StartTweeningSlide() { bTweeningSlide = true; //start slide tweening TweenEndTime = Level.TimeSeconds + 0.2; } function AddReloadedAmmo() { local int a; UpdateMagCapacity(Instigator.PlayerReplicationInfo); a = MagCapacity; if ( bShortReload ) a++; // 1 bullet already bolted if ( AmmoAmount(0) >= a ) MagAmmoRemaining = a; else MagAmmoRemaining = AmmoAmount(0); // this seems redudant -- PooSH // if( !bHoldToReload ) // { // ClientForceKFAmmoUpdate(MagAmmoRemaining,AmmoAmount(0)); // } if ( PlayerController(Instigator.Controller) != none && KFSteamStatsAndAchievements(PlayerController(Instigator.Controller).SteamStatsAndAchievements) != none ) { KFSteamStatsAndAchievements(PlayerController(Instigator.Controller).SteamStatsAndAchievements).OnWeaponReloaded(); } } function GiveTo( pawn Other, optional Pickup Pickup ) { local KFPlayerReplicationInfo KFPRI; local KFWeaponPickup WeapPickup; KFPRI = KFPlayerReplicationInfo(Other.PlayerReplicationInfo); WeapPickup = KFWeaponPickup(Pickup); //pick the lowest sell value if ( WeapPickup != None && KFPRI != None && KFPRI.ClientVeteranSkill != none ) { SellValue = 0.75 * min(WeapPickup.Cost, WeapPickup.default.Cost * KFPRI.ClientVeteranSkill.static.GetCostScaling(KFPRI, WeapPickup.class)); } Super.GiveTo(Other,Pickup); } defaultproperties { ReloadShortAnim="Reload" ReloadShortRate=1.660000 DefaultSlideReturnStartMult=0.848480 DefaultSlideReturnEndMult=0.878780 DefaultSlideMoveMult=1.400000 PistolSlideOffset=(X=0.019700) PistolHammerRotation=(Pitch=120) Weight=4.000000 FireModeClass(0)=Class'ScrnBalanceSrv.ScrnDeagleFire' PickupClass=Class'ScrnBalanceSrv.ScrnDeaglePickup' ItemName="Handcannon SE" }