class ZombieScrakeOS extends KFMonsterOS;

var         bool    bCharging;
var float DistBeforeSaw;
var bool bEnableOldScrakeBehavior;

replication
{
    reliable if(Role == ROLE_Authority)
        bCharging;
}

simulated function PostNetBeginPlay()
{
    EnableChannelNotify ( 1,1);
    AnimBlendParams(1, 1.0, 0.0,, SpineBone1);
    super.PostNetBeginPlay();
}

simulated function PostNetReceive()
{
    if (bCharging)
        MovementAnims[0]='ZombieRun';
    else if( !(bCrispified && bBurnified) )
        MovementAnims[0]=default.MovementAnims[0];
}

// This zed has been taken control of. Boost its health and speed
function SetMindControlled(bool bNewMindControlled)
{
    if( bNewMindControlled )
    {
        NumZCDHits++;

        // if we hit him a couple of times, make him rage!
        if( NumZCDHits > 1 )
        {
            if( !IsInState('ChargeToMarker') )
            {
                GotoState('ChargeToMarker');
            }
            else
            {
                NumZCDHits = 1;
                if( IsInState('ChargeToMarker') )
                {
                    GotoState('');
                }
            }
        }
        else
        {
            if( IsInState('ChargeToMarker') )
            {
                GotoState('');
            }
        }

        if( bNewMindControlled != bZedUnderControl )
        {
            SetGroundSpeed(OriginalGroundSpeed * 1.25);
            Health *= 1.25;
            HealthMax *= 1.25;
        }
    }
    else
    {
        NumZCDHits=0;
    }

    bZedUnderControl = bNewMindControlled;
}

// Handle the zed being commanded to move to a new location
function GivenNewMarker()
{
    if( bCharging && NumZCDHits > 1  )
    {
        GotoState('ChargeToMarker');
    }
    else
    {
        GotoState('');
    }
}

simulated function SetBurningBehavior()
{
    if( Role == Role_Authority && IsInState('RunningState') )
    {
        super.SetBurningBehavior();
        GotoState('');
    }

    super.SetBurningBehavior();
}

function RangedAttack(Actor A)
{
    local float Dist;

    Dist = VSize(A.Location - Location);

    if ( bShotAnim || Physics == PHYS_Swimming)
        return;
    else if ( Dist < (MeleeRange - DistBeforeSaw + CollisionRadius + A.CollisionRadius) && CanAttack(A) )
    {
        //Reset to default when you swing
        OnlineHeadshotOffset = default.OnlineHeadshotOffset;
        bShotAnim = true;
        SetAnimAction(MeleeAnims[Rand(2)]);
        CurrentDamType = ZombieDamType[0];
        PlaySound(sound'Claw2s', SLOT_None);
        GoToState('SawingLoop');
    }

    if(AnimAction == MeleeAnims[0])
        MeleeDamage = Max( (DifficultyDamageModifer() * default.MeleeDamage * 0.85), 1 );
    else if(AnimAction == MeleeAnims[1])
         MeleeDamage = Max( (DifficultyDamageModifer() * default.MeleeDamage * 1.15), 1 );

    if( !bShotAnim && !bDecapitated && !bEnableOldScrakeBehavior )
    {
        if ( Level.Game.GameDifficulty < 5.0 )
        {
            if ( float(Health)/HealthMax < 0.5 )
                GoToState('RunningState');
        }
        else
        {
            if ( float(Health)/HealthMax < 0.75 )
                GoToState('RunningState');
        }
    }
}

state RunningState
{
    //Fixes slow charge for charging zeds
    //Credits:NikC for forum link, aleat0r for the code
    simulated function float GetOriginalGroundSpeed()
    {
        return 3.5 * OriginalGroundSpeed;
    }

    simulated function SetZappedBehavior()
    {
        Global.SetZappedBehavior();
        GoToState('');
    }

    function bool CanSpeedAdjust()
    {
        return false;
    }

    //Dont play hit anims while charging so people don't complain about broken head hitboxes :)
    function OldPlayHit(float Damage, Pawn InstigatedBy, vector HitLocation, class<DamageType> damageType, vector Momentum, optional int HitIndex){}

    function BeginState()
    {
        if( bZapped )
            GoToState('');
        else
        {
            SetGroundSpeed(OriginalGroundSpeed * 3.5);
            bCharging = true;
            if( Level.NetMode!=NM_DedicatedServer )
                PostNetReceive();

            OnlineHeadshotOffset.Z = 41;
            OnlineHeadshotOffset.X = 30;
            OnlineHeadshotOffset.Y = -10;
            NetUpdateTime = Level.TimeSeconds - 1;
        }
    }

    function EndState()
    {
        if( !bZapped )
            SetGroundSpeed(GetOriginalGroundSpeed());
        bCharging = false;
        if( Level.NetMode!=NM_DedicatedServer )
            PostNetReceive();
        OnlineHeadshotOffset = default.OnlineHeadshotOffset;
    }

    function RemoveHead()
    {
        GoToState('');
        Global.RemoveHead();
    }

    function RangedAttack(Actor A)
    {
        local float Dist;

        Dist = VSize(A.Location - Location);
        DistBeforeSaw = 20.0;

        if ( bShotAnim || Physics == PHYS_Swimming)
            return;
        else if ( Dist < (MeleeRange - DistBeforeSaw + CollisionRadius + A.CollisionRadius) && CanAttack(A) )
        {
            bShotAnim = true;
            if(Level.Game.GameDifficulty < 5.0)
                SetAnimAction(MeleeAnims[Rand(2)]);
            else
                SetAnimAction(MeleeAnims[0]);
            CurrentDamType = ZombieDamType[0];
            GoToState('SawingLoop');
            OnlineHeadshotOffset = default.OnlineHeadshotOffset;
        }
    }
}

state RunningToMarker extends RunningState
{
}

State SawingLoop
{

    function bool CanSpeedAdjust()
    {
        return false;
    }

    function RangedAttack(Actor A)
    {
        if ( bShotAnim )
            return;
        else if ( CanAttack(A) )
        {
            Acceleration = vect(0,0,0);
            bShotAnim = true;
            MeleeDamage = default.MeleeDamage*0.6;
            SetAnimAction('SawImpaleLoop');
            CurrentDamType = ZombieDamType[0];
        }
        else GoToState('');
    }
    function AnimEnd( int Channel )
    {
        super.AnimEnd(Channel);
        if( Controller!=none && Controller.Enemy!=none )
            RangedAttack(Controller.Enemy);
    }

    function EndState()
    {
        MeleeDamage = Max( DifficultyDamageModifer() * default.MeleeDamage, 1 );

        SetGroundSpeed(GetOriginalGroundSpeed());
        bCharging = false;
        if( Level.NetMode!=NM_DedicatedServer )
            PostNetReceive();
    }
}

function TakeDamage( int Damage, Pawn InstigatedBy, Vector Hitlocation, Vector Momentum, class<DamageType> damageType, optional int HitIndex)
{
    local bool bIsHeadShot;

    bIsHeadShot = IsHeadShot(Hitlocation, normal(Momentum), 1.0);

    if ( Level.Game.GameDifficulty >= 5.0 && bIsHeadshot && (class<DamTypeCrossbow>(damageType) != none || class<DamTypeCrossbowHeadShot>(damageType) != none) )
    {
        Damage *= 0.5;
    }

    super.takeDamage(Damage, instigatedBy, hitLocation, momentum, damageType, HitIndex);

    if ( Level.Game.GameDifficulty >= 5.0 && !IsInState('SawingLoop') && !IsInState('RunningState') && float(Health) / HealthMax < 0.75 )
        RangedAttack(InstigatedBy);
}

function PlayTakeHit(vector HitLocation, int Damage, class<DamageType> DamageType)
{
    super(ZombieScrake).PlayTakeHit(HitLocation,Damage,DamageType);
}

simulated function int DoAnimAction( name AnimName )
{
    if( AnimName=='SawZombieAttack1' || AnimName=='SawZombieAttack2' /*|| AnimName=='SawImpaleLoop' */)
    {
        AnimBlendParams(1, 1.0, 0.0,, 'Bip01 Spine1');
        PlayAnim(AnimName,, 0.0, 1);
        return 1;
    }
    return super.DoAnimAction(AnimName);
}

simulated event SetAnimAction(name NewAction)
{
    local int meleeAnimIndex;

    if( NewAction=='' )
        return;

    if(NewAction == 'Claw')
    {
        meleeAnimIndex = Rand(3);
        NewAction = meleeAnims[meleeAnimIndex];
        CurrentDamtype = ZombieDamType[meleeAnimIndex];
    }

    ExpectingChannel = DoAnimAction(NewAction);

    if( AnimNeedsWait(NewAction) )
        bWaitForAnim = true;

    if( Level.NetMode!=NM_Client )
    {
        AnimAction = NewAction;
        bResetAnimAct = true;
        ResetAnimActTime = Level.TimeSeconds+0.3;
    }
}

simulated function bool AnimNeedsWait(name TestAnim)
{
    if( TestAnim == 'SawImpaleLoop' || TestAnim == 'DoorBash' || TestAnim == 'KnockDown' )
        return true;

    return false;
}


simulated function SpawnGibs(Rotator HitRotation, float ChunkPerterbation)
{
    super.SpawnGibs(HitRotation,ChunkPerterbation);
}

static simulated function PreCacheMaterials(LevelInfo myLevel)
{
    myLevel.AddPrecacheMaterial(Texture'KFOldSchoolZeds_Textures.Scrake.ScrakeSkin');
    myLevel.AddPrecacheMaterial(TexOscillator'KFOldSchoolZeds_Textures.Scrake.SawChainOSC');
    myLevel.AddPrecacheMaterial(Texture'KFOldSchoolZeds_Textures.Scrake.ScrakeFrockSkin');
    myLevel.AddPrecacheMaterial(Texture'KFOldSchoolZeds_Textures.Scrake.ScrakeSawSkin');
}

defaultproperties
{
     MeleeAnims(0)="SawZombieAttack1"
     MeleeAnims(1)="SawZombieAttack2"
     MoanVoice=SoundGroup'KFOldSchoolZeds_Sounds.Scrake.Scrake_Speech'
     BleedOutDuration=6.000000
     bCannibal=True
     ZapThreshold=1.250000
     ZappedDamageMod=1.250000
     bHarpoonToBodyStuns=False
     DamageToMonsterScale=8.000000
     ZombieFlag=3
     MeleeDamage=20
     damageForce=-100000
     bFatAss=True
     KFRagdollName="FleshPoundRag"
     JumpSound=Sound'KFOldSchoolZeds_Sounds.Shared.Male_ZombieJump'
     bMeleeStunImmune=True
     Intelligence=BRAINS_Mammal
     bUseExtendedCollision=True
     ColOffset=(Z=55.000000)
     ColRadius=29.000000
     ColHeight=18.000000
     PlayerCountHealthScale=0.500000
     PoundRageBumpDamScale=0.010000
     OnlineHeadshotOffset=(X=10.000000,Y=-7.000000,Z=58.000000)
     OnlineHeadshotScale=1.200000
     HeadHealth=650.000000
     PlayerNumHeadHealthScale=0.300000
     MotionDetectorThreat=3.000000
     HitSound(0)=SoundGroup'KFOldSchoolZeds_Sounds.Shared.Male_ZombiePain'
     DeathSound(0)=SoundGroup'KFOldSchoolZeds_Sounds.Shared.Male_ZombieDeath'
     ScoringValue=75
     IdleHeavyAnim="SawZombieIdle"
     IdleRifleAnim="SawZombieIdle"
     MeleeRange=60.000000
     GroundSpeed=85.000000
     WaterSpeed=75.000000
     HealthMax=1000.000000
     Health=1000
     HeadRadius=8.000000
     HeadHeight=6.000000
     AmbientSoundScaling=5.000000
     MenuName="Scrake 2.5"
     ControllerClass=Class'KFOldSchoolZeds.ControllerScrakeOS'
     MovementAnims(0)="SawZombieWalk"
     MovementAnims(1)="SawZombieWalk"
     MovementAnims(2)="SawZombieWalk"
     MovementAnims(3)="SawZombieWalk"
     WalkAnims(0)="SawZombieWalk"
     WalkAnims(1)="SawZombieWalk"
     WalkAnims(2)="SawZombieWalk"
     WalkAnims(3)="SawZombieWalk"
     IdleCrouchAnim="SawZombieIdle"
     IdleWeaponAnim="SawZombieIdle"
     IdleRestAnim="SawZombieIdle"
     AmbientSound=Sound'KFOldSchoolZeds_Sounds.Scrake.Saw_Idle'
     Mesh=SkeletalMesh'KFCharacterModelsOldSchool.SawZombie'
     PrePivot=(Z=0.000000)
     Skins(0)=Texture'KFOldSchoolZeds_Textures.Scrake.ScrakeSkin'
     Skins(1)=TexOscillator'KFOldSchoolZeds_Textures.Scrake.SawChainOSC'
     Skins(2)=Texture'KFOldSchoolZeds_Textures.Scrake.ScrakeFrockSkin'
     Skins(3)=Texture'KFOldSchoolZeds_Textures.Scrake.ScrakeSawSkin'
     SoundRadius=200.000000
     Mass=500.000000
     RotationRate=(Yaw=45000,Roll=0)
}
