class ScrnDualMK23Pistol extends DualMK23Pistol;

var         name            ReloadShortAnim;
var         float           ReloadShortRate;
var         float           ReloadHalfShortRate;

var transient bool bShortReload;
var transient bool bHalfShortReload;
var transient bool bTweeningSlide;
var transient bool bTweenLeftSlide;
var transient bool bTweenRightSlide;
var transient bool bFrameSkipRequired; //because of mk23's tactical reload
var float TweenEndTime;

var vector PistolSlideOffset; //for tactical reload

var float ShortReloadFrameSkip; //for tactical reload
var transient int ClientMagAmmoRemaining;
var transient int FiringRound;


simulated function PostNetReceive()
{
    super.PostNetReceive();

    if ( Role < ROLE_Authority ) {
        if ( ClientMagAmmoRemaining != MagAmmoRemaining ) {
            if ( MagAmmoRemaining > ClientMagAmmoRemaining ) {
                // mag update after reload
                ScrnDualMK23Fire(GetFireMode(0)).SetPistolFireOrder( (MagAmmoRemaining%2) == 1 );
            }
            if ( MagAmmoRemaining <= 1 ) {
                LockLeftSlideBack();
                if ( MagAmmoRemaining == 0 )
                    LockRightSlideBack();
            }
            ClientMagAmmoRemaining = MagAmmoRemaining;
        }
    }
}

simulated function Fire(float F)
{
    FiringRound = MagAmmoRemaining;
    super.Fire(f);
}

function AttachToPawn(Pawn P)
{
    super(Dualies).AttachToPawn(P); // skip code duplication in Dual44Magnum
}

function bool HandlePickupQuery( pickup Item )
{
    if ( Item.InventoryType==Class'ScrnBalanceSrv.ScrnMK23Pistol' )
    {
        if( LastHasGunMsgTime < Level.TimeSeconds && PlayerController(Instigator.Controller) != none )
        {
            LastHasGunMsgTime = Level.TimeSeconds + 0.5;
            PlayerController(Instigator.Controller).ReceiveLocalizedMessage(Class'KFMainMessages', 1);
        }

        return True;
    }

    return Super.HandlePickupQuery(Item);
}

function DropFrom(vector StartLocation)
{
    local int m;
    local KFWeaponPickup Pickup;
    local int AmmoThrown, OtherAmmo;
    local KFWeapon SinglePistol;

    if( !bCanThrow )
        return;

    AmmoThrown = AmmoAmount(0);
    ClientWeaponThrown();

    for (m = 0; m < NUM_FIRE_MODES; m++)
    {
        if (FireMode[m].bIsFiring)
            StopFire(m);
    }

    if ( Instigator != None )
        DetachFromPawn(Instigator);

    if( Instigator.Health > 0 )
    {
        OtherAmmo = AmmoThrown / 2;
        AmmoThrown -= OtherAmmo;
        SinglePistol = Spawn(Class'ScrnBalanceSrv.ScrnMK23Pistol');
        SinglePistol.SellValue = SellValue / 2;
        SinglePistol.GiveTo(Instigator);
        SinglePistol.Ammo[0].AmmoAmount = OtherAmmo;
        SinglePistol.MagAmmoRemaining = MagAmmoRemaining / 2;
        MagAmmoRemaining = Max(MagAmmoRemaining-SinglePistol.MagAmmoRemaining,0);
    }

    Pickup = Spawn(class'ScrnBalanceSrv.ScrnMK23Pickup',,, StartLocation);

    if ( Pickup != None )
    {
        Pickup.InitDroppedPickupFor(self);
        Pickup.DroppedBy = PlayerController(Instigator.Controller);
        Pickup.Velocity = Velocity;
        //fixing dropping exploit
        Pickup.SellValue = SellValue / 2;
        Pickup.Cost = Pickup.SellValue / 0.75;
        Pickup.AmmoAmount[0] = AmmoThrown;
        Pickup.MagAmmoRemaining = MagAmmoRemaining;
        if (Instigator.Health > 0)
            Pickup.bThrown = true;
        //Log("--- Pickup "$String(Pickup)$" spawned with Cost = "$Pickup.Cost);
    }

    Destroyed();
    Destroy();
}

simulated function BringUp(optional Weapon PrevWeapon)
{
    Super.BringUp(PrevWeapon);
    if (Level.NetMode != NM_DedicatedServer)
    {
        if (MagAmmoRemaining == 0)
        {
            LockLeftSlideBack();
            LockRightSlideBack();
        }
        if (MagAmmoRemaining == 1)
            LockLeftSlideBack();
    }
}

simulated function bool PutDown()
{
    if ( Instigator.PendingWeapon == none || Instigator.PendingWeapon.class == class'ScrnBalanceSrv.ScrnMK23Pistol' )
    {
        bIsReloading = false;
    }

    return super.PutDown();
}

simulated function ResetLeftSlidePosition()
{
    SetBoneLocation( 'Slide01', PistolSlideOffset, 0 ); //reset Slide position
}

simulated function ResetRightSlidePosition()
{
    SetBoneLocation( 'Slide', PistolSlideOffset, 0 ); //reset Slide position
}

simulated function LockLeftSlideBack()
{
    SetBoneLocation( 'Slide01', -PistolSlideOffset, 100 ); //lock slide back
}

simulated function LockRightSlideBack()
{
    SetBoneLocation( 'Slide', -PistolSlideOffset, 100 ); //lock slide back
}

simulated function InterpolateRightSlide(float time)
{
    SetBoneLocation( 'Slide', PistolSlideOffset, (time*500)); //after tactical reload tween this from 100 to 0
}

simulated function InterpolateLeftSlide(float time)
{
    SetBoneLocation( 'Slide01', PistolSlideOffset, (time*500)); //after tactical reload tween this from 100 to 0
}


simulated function HandleSlideMovement()
{
    if (TweenEndTime - Level.TimeSeconds > 0)
    {
        if (bTweenRightSlide)
            InterpolateRightSlide(TweenEndTime - Level.TimeSeconds);
        if (bTweenLeftSlide)
            InterpolateLeftSlide(TweenEndTime - Level.TimeSeconds);
    }
    if (TweenEndTime - Level.TimeSeconds < 0)
    {
        ResetLeftSlidePosition();
        ResetRightSlidePosition();
        TweenEndTime = 0;
        bTweeningSlide = false;
        bTweenLeftSlide = false;
        bTweenRightSlide = false;
    }
}

simulated function HandleFrameSkip()
 {
    if (Level.TimeSeconds - ReloadTimer >= ReloadRate*0.648)
    {
        //DoFrameSkip(); //do animation frame skip
        bFrameSkipRequired = false;
    }
}

simulated function WeaponTick(float dt)
{
    if (Level.NetMode != NM_DedicatedServer)
    {
        if ( bTweeningSlide && TweenEndTime > 0 )
        {
            HandleSlideMovement();
        }
        /*
        if (bIsReloading && bFrameSkipRequired)
        {
            HandleFrameSkip();
        }
        */
    }
    Super.WeaponTick(dt);
}

//added this to replace old reloadtimer mult check
simulated function Timer()
{
    if (bIsReloading)
        DoFrameSkip(); //skip to mag change frame
    //else
    //PlayIdle();
    Super.Timer();
}

//skip from ~frame 50 to 75
simulated function DoFrameSkip()
{
    SetAnimFrame(75, , 1);
    //left pistol slide gets released after this skip so reset left slide's position
    SetBoneLocation( 'Slide01', PistolSlideOffset, 0); //reset left slide position
}


simulated function StartTweeningSlide()
{
    bTweeningSlide = true; //start Slide tweening
    TweenEndTime = Level.TimeSeconds + 0.2;
}

//after reload tween slide back if tactical reload
simulated function ClientFinishReloading()
{
    if( bShortReload || bHalfShortReload )
    {
        StartTweeningSlide(); //start tweening Slide back
    }
    Super.ClientFinishReloading();
}

//added slide offset to reload animation
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;
    if (MagAmmoRemaining <= 0)
    {
        bShortReload = false;
        bHalfShortReload = false;
        PlayAnim(ReloadAnim, ReloadAnimRate*ReloadMulti, 0.001);
        SetBoneLocation( 'Slide', PistolSlideOffset, 0 ); //reset Slide so that the animation's Slide position gets used
        SetBoneLocation( 'Slide01', PistolSlideOffset, 0 ); //reset Slide so that the animation's Slide position gets used
    }
    else if (MagAmmoRemaining == 1)
    {
        bShortReload = false;
        bHalfShortReload = true;
        PlayAnim(ReloadAnim, ReloadAnimRate*ReloadMulti, 0.001);
        SetBoneLocation( 'Slide', PistolSlideOffset, 100 ); //move right slide forward
        SetBoneLocation( 'Slide01', PistolSlideOffset, 0 ); //reset left slide so that the animation's slide position gets used
        bTweenRightSlide = true;
    }
    else if (MagAmmoRemaining >= 2)
    {
        bShortReload = true;
        bHalfShortReload = false;
        bFrameSkipRequired = true;
        bTweenRightSlide = true; //this is needed
        PlayAnim(ReloadAnim, ReloadAnimRate*ReloadMulti, 0.001);
        SetBoneLocation( 'Slide', PistolSlideOffset, 100 ); //move slide forward
        SetBoneLocation( 'Slide01', PistolSlideOffset, 100 ); //move slide forward
        SetTimer(1.667/ReloadMulti, false); //timer skips from frame 50 to 75

    }
}

function AddReloadedAmmo()
{
    local int a;

    UpdateMagCapacity(Instigator.PlayerReplicationInfo);

    a = MagCapacity;
    if ( bShortReload )
        a+=2; // 2 bullets already bolted
    if ( bHalfShortReload )
        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();
    }
}

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 ( MagAmmoRemaining >= 2 )
        ReloadRate = default.ReloadShortRate / ReloadMulti;
    else if (MagAmmoRemaining == 1)
        ReloadRate = default.ReloadHalfShortRate / ReloadMulti;
    else if (MagAmmoRemaining <= 0)
        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;
    }
}

defaultproperties
{
     ReloadShortRate=2.570000
     ReloadHalfShortRate=3.350000
     PistolSlideOffset=(Y=-0.023500)
     ShortReloadFrameSkip=75.000000
     MagAmmoRemaining=24
     FireModeClass(0)=Class'ScrnBalanceSrv.ScrnDualMK23Fire'
     DemoReplacement=Class'ScrnBalanceSrv.ScrnMK23Pistol'
     PickupClass=Class'ScrnBalanceSrv.ScrnDualMK23Pickup'
     ItemName="Dual MK23 SE"
}
