class MedicPistol extends KFWeapon
    config(user);


var const   class<ScrnLocalLaserDot>    LaserDotClass;
var         ScrnLocalLaserDot           LaserDot;             // The first person laser site dot

var()       class<InventoryAttachment>  LaserAttachmentClass;      // First person laser attachment class
var         Actor                       LaserAttachment; // First person laser attachment
var         byte                        LaserType;

var transient Vector HealLocation, ClientHealLocation;
var transient Rotator HealRotation;

var Sound HealSound;
var string HealSoundRef;

var name ReloadShortAnim;
var float ReloadShortRate;
var transient bool bShortReload;

var bool bFiringLastRound;

replication
{
    reliable if(Role < ROLE_Authority)
        ServerSetLaserType;

     reliable if( Role == ROLE_Authority )
        ClientSuccessfulHeal;

    reliable if( bNetDirty && Role == ROLE_Authority )
        HealRotation, HealLocation;
}

//=============================================================================
// Dynamic Asset Load
//=============================================================================
static function PreloadAssets(Inventory Inv, optional bool bSkipRefCount)
{
    local MedicPistol W;

    super.PreloadAssets(Inv, bSkipRefCount);

    default.HealSound = sound(DynamicLoadObject(default.HealSoundRef, class'Sound', true));

    if ( W != none ) {
        W.HealSound = default.HealSound;
    }
}

static function bool UnloadAssets()
{
    if ( super.UnloadAssets() )
    {
        default.HealSound = none;
    }

    return true;
}

//=============================================================================
// Functions
//=============================================================================

simulated function PostNetReceive()
{
    if ( Role < ROLE_Authority && ClientHealLocation != HealLocation ) {
        ClientHealLocation = HealLocation;
        HitHealTarget(HealLocation, HealRotation);
    }
}

simulated function Fire(float f)
{
    if ( f == 0)
        bFiringLastRound = MagAmmoRemaining == 1;
    super.Fire(f);
}

simulated function Destroyed()
{
    if (LaserDot != None)
        LaserDot.Destroy();
    if (LaserAttachment != None)
        LaserAttachment.Destroy();

    super.Destroyed();
}

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;
}


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 && ReloadShortAnim != '';
    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;
    if ( MagAmmoRemaining <= 0 || ReloadShortAnim == '' )
    {
        PlayAnim(ReloadAnim, ReloadAnimRate*ReloadMulti, 0.1);
    }
    else if ( MagAmmoRemaining >= 1 )
    {
        PlayAnim(ReloadShortAnim, ReloadAnimRate*ReloadMulti, 0.1);
    }
}

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();
    }
}

simulated function WeaponTick(float dt)
{
//Change the various animations depending on whether the last round was fired
    if (Level.NetMode != NM_DedicatedServer)
    {
        if (MagAmmoRemaining >= 1 || bIsReloading)
        {
            //ReloadAnim = 'ReloadChambered';
            IdleAnim = default.IdleAnim;
            IdleAimAnim = default.IdleAimAnim;
            SelectAnim = default.SelectAnim;
            PutDownAnim = default.PutDownAnim;
            ModeSwitchAnim = default.ModeSwitchAnim;
        }
        else if (MagAmmoRemaining == 0)
        {
            //ReloadAnim = default.ReloadAnim;
            IdleAnim = 'IdleEmpty';
            IdleAimAnim = 'IdleEmpty_Iron';
            SelectAnim = 'SelectEmpty';
            PutDownAnim = 'PutDownEmpty';
            ModeSwitchAnim = 'LightOnEmpty';
        }
    }
//End animation-swapping stuff
    super.WeaponTick(dt);

    if ( (FlashLight != none && FlashLight.bHasLight ) == (LaserType > 0) )
        ToggleLaser(); // automatically turn on laser if flashlight is off
}

//bring Laser to current state, which is indicating by LaserType
simulated function ApplyLaserState()
{
    if( Role < ROLE_Authority  )
        ServerSetLaserType(LaserType);

    if ( ThirdPersonActor != none )
        ScrnLaserWeaponAttachment(ThirdPersonActor).SetLaserType(LaserType);

    if ( !Instigator.IsLocallyControlled() )
        return;

    if(LaserType > 0 ) {
        if ( LaserDot == none )
            LaserDot = Spawn(LaserDotClass, self);
        LaserDot.SetLaserType(LaserType);
        //spawn 1-st person laser attachment for weapon owner
        if ( LaserAttachment == none ) {
            LaserAttachment = Spawn(LaserAttachmentClass,,,,);
            AttachToBone(LaserAttachment, FlashBoneName);
        }
        ConstantColor'ScrnTex.Laser.LaserColor'.Color =
            LaserDot.GetLaserColor(); // LaserAttachment's color
        LaserAttachment.bHidden = false;

    }
    else {
        if ( LaserAttachment != none )
            LaserAttachment.bHidden = true;
        if ( LaserDot != none )
            LaserDot.Destroy(); //bHidden = true;
    }
}


// Toggle laser on or off
simulated function ToggleLaser()
{
    if( !Instigator.IsLocallyControlled() )
        return;

    if ( LaserType == 0 )
        LaserType = 3; // Blue
    else
        LaserType = 0;

    ApplyLaserState();
}

simulated function BringUp(optional Weapon PrevWeapon)
{
    ApplyLaserState();
    Super.BringUp(PrevWeapon);
}

simulated function bool PutDown()
{
    TurnOffLaser();
    return super.PutDown();
}

simulated function DetachFromPawn(Pawn P)
{
    TurnOffLaser();
    Super.DetachFromPawn(P);
}

simulated function TurnOffLaser()
{
    if( !Instigator.IsLocallyControlled() )
        return;

    if( Role < ROLE_Authority  )
        ServerSetLaserType(0);

    //don't change Laser type here, because we need to restore it state
    //when next time weapon will be bringed up
    if ( LaserAttachment != none )
        LaserAttachment.bHidden = true;
    if (LaserDot != None)
        LaserDot.Destroy();
}



// Set the new fire mode on the server
function ServerSetLaserType(byte NewLaserType)
{
    LaserType = NewLaserType;
    ScrnLaserWeaponAttachment(ThirdPersonActor).SetLaserType(LaserType);
}


simulated function RenderOverlays( Canvas Canvas )
{
    local int i;
    local Vector StartTrace, EndTrace;
    local Vector HitLocation, HitNormal;
    local Actor Other;
    local vector X,Y,Z;
    local coords C;
    local KFFire KFM;
    local array<Actor> HitActors;

    if (Instigator == None)
        return;

    if ( Instigator.Controller != None )
        Hand = Instigator.Controller.Handedness;

    if ((Hand < -1.0) || (Hand > 1.0))
        return;

    // draw muzzleflashes/smoke for all fire modes so idle state won't
    // cause emitters to just disappear
    for ( i = 0; i < NUM_FIRE_MODES; ++i ) {
        if (FireMode[i] != None)
            FireMode[i].DrawMuzzleFlash(Canvas);
    }

    SetLocation( Instigator.Location + Instigator.CalcDrawOffset(self) );
    SetRotation( Instigator.GetViewRotation() + ZoomRotInterp);

    KFM = KFFire(FireMode[0]);

    // Handle drawing the laser dot
    if ( LaserDot != None )
    {
        //move LaserDot during fire animation too  -- PooSH
        if( bIsReloading )
        {
            C = GetBoneCoords(FlashBoneName);
            X = C.XAxis;
            Y = C.YAxis;
            Z = C.ZAxis;
        }
        else
            GetViewAxes(X, Y, Z);

        StartTrace = Instigator.Location + Instigator.EyePosition();
        EndTrace = StartTrace + 65535 * X;

        while (true) {
            Other = Trace(HitLocation, HitNormal, EndTrace, StartTrace, true);
            if ( ROBulletWhipAttachment(Other) != none ) {
                HitActors[HitActors.Length] = Other;
                Other.SetCollision(false);
                StartTrace = HitLocation + X;
            }
            else {
                if (Other != None && Other != Instigator && Other.Base != Instigator )
                    EndBeamEffect = HitLocation;
                else
                    EndBeamEffect = EndTrace;
                break;
            }
        }
        // restore collision
        for ( i=0; i<HitActors.Length; ++i )
            HitActors[i].SetCollision(true);

        LaserDot.SetLocation(EndBeamEffect - X*LaserDot.ProjectorPullback);

        if(  Pawn(Other) != none ) {
            LaserDot.SetRotation(Rotator(X));
            LaserDot.SetDrawScale(LaserDot.default.DrawScale * 0.5);
        }
        else if( HitNormal == vect(0,0,0) ) {
            LaserDot.SetRotation(Rotator(-X));
            LaserDot.SetDrawScale(LaserDot.default.DrawScale);
        }
        else {
            LaserDot.SetRotation(Rotator(-HitNormal));
            LaserDot.SetDrawScale(LaserDot.default.DrawScale);
        }
    }

    //PreDrawFPWeapon();    // Laurent -- Hook to override things before render (like rotation if using a staticmesh)

    bDrawingFirstPerson = true;
    Canvas.DrawActor(self, false, false, DisplayFOV);
    bDrawingFirstPerson = false;
}

exec function SwitchModes()
{
    DoToggle();
}


simulated function ClientSuccessfulHeal(PlayerReplicationInfo HealedPRI)
{
    if( PlayerController(Instigator.Controller) != none )
        PlayerController(Instigator.controller).ClientMessage(class'KFMod.MP7MMedicGun'.default.SuccessfulHealMessage $ HealedPRI.PlayerName, 'CriticalEvent');
}

simulated function HitHealTarget(vector HitLocation, rotator HitRotation)
{
    HealLocation = HitLocation;
    HealRotation = HitRotation;

    if( Role == ROLE_Authority ) {
       NetUpdateTime = Level.TimeSeconds - 1;
    }

    PlaySound(HealSound,,2.0);

    if ( EffectIsRelevant(Location,false) )
    {
        Spawn(Class'KFMod.HealingFX',,, HitLocation, HitRotation);
    }
}

defaultproperties
{
     LaserDotClass=Class'ScrnBalanceSrv.ScrnLocalLaserDot'
     LaserAttachmentClass=Class'ScrnBalanceSrv.ScrnLaserAttachmentFirstPerson'
     HealSoundRef="KF_MP7Snd.MP7_DartImpact"
     ReloadShortAnim="ReloadChambered"
     ReloadShortRate=1.500000
     MagCapacity=7
     ReloadRate=2.000000
     ReloadAnim="Reload"
     ReloadAnimRate=1.000000
     FlashBoneName="LightBone"
     WeaponReloadAnim="Reload_Single9mm"
     ModeSwitchAnim="LightOn"
     Weight=2.000000
     bTorchEnabled=True
     bHasAimingMode=True
     IdleAimAnim="Idle_Iron"
     StandardDisplayFOV=70.000000
     bModeZeroCanDryFire=True
     SleeveNum=0
     TraderInfoTexture=Texture'ScrnWeaponPack_T.MedicPistol.HUD_Single_UnSelected'
     MeshRef="ScrnWeaponPack_A.MedicPistol_1st"
     SkinRefs(1)="ScrnWeaponPack_T.MedicPistol.Slide_cmb"
     SkinRefs(2)="ScrnWeaponPack_T.MedicPistol.Frame_cmb"
     SkinRefs(3)="ScrnWeaponPack_T.MedicPistol.Slide_cmb"
     SkinRefs(4)="ScrnWeaponPack_T.MedicPistol.Slide_shd"
     SelectSoundRef="KF_9MMSnd.9mm_Select"
     HudImageRef="ScrnWeaponPack_T.MedicPistol.HUD_Single_UnSelected"
     SelectedHudImageRef="ScrnWeaponPack_T.MedicPistol.HUD_Single_Selected"
     ZoomedDisplayFOV=65.000000
     FireModeClass(0)=Class'ScrnWeaponPack.MedicPistolFire'
     FireModeClass(1)=Class'ScrnWeaponPack.MedicPistolLightFire'
     PutDownAnim="PutDown"
     AIRating=0.250000
     CurrentRating=0.250000
     bShowChargingBar=True
     Description="Primary fire shoots healing darts. Darts heal zeds too, but it doesn't help them much, if titanium needle breaks their skulls first. Shooting multiple dart into the same zed may cause overdose. Alternate fire switch between laser and flashlight."
     DisplayFOV=70.000000
     Priority=60
     InventoryGroup=2
     GroupOffset=1
     PickupClass=Class'ScrnWeaponPack.MedicPistolPickup'
     PlayerViewOffset=(X=20.000000,Y=25.000000,Z=-10.000000)
     BobDamping=6.000000
     AttachmentClass=Class'ScrnWeaponPack.MedicPistolAttachment'
     IconCoords=(X1=434,Y1=253,X2=506,Y2=292)
     ItemName="KF2 Medic Pistol SE"
}
