class ZombieSirenOS extends KFMonsterOS;

var float DistBeforeScream;
var () int ScreamRadius;

var () class <DamageType> ScreamDamageType;
var () int ScreamForce;

var(Shake)  rotator RotMag;
var(Shake)  float   RotRate;
var(Shake)  vector  OffsetMag;
var(Shake)  float   OffsetRate;
var(Shake)  float   ShakeTime;
var(Shake)  float   ShakeFadeTime;
var(Shake)  float    ShakeEffectScalar;
var(Shake)  float    MinShakeEffectScale;
var(Shake)  float    ScreamBlurScale;

var bool bAboutToDie;
var float DeathTimer;
var bool bEnableSirenNadeBoom;

// Fixes credit: https://github.com/Shtoyan/KF1066/blob/main/docs/VeryAnnoying/ZedIssues.md

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

    if(bEnableSirenNadeBoom)
        ScreamDamageType=class'SirenScreamDamageOS';
}

function bool FlipOver()
{
    return false;
}

function DoorAttack(Actor A)
{
    if ( bShotAnim || Physics == PHYS_Swimming || bDecapitated || A==none )
        return;
    bShotAnim = true;
    SetAnimAction('Siren_Scream');
}

function RangedAttack(Actor A)
{
    local int LastFireTime;
    local float Dist;

    if ( bShotAnim )
        return;

    Dist = VSize(A.Location - Location);

    if ( Physics == PHYS_Swimming )
    {
        SetAnimAction('Claw');
        bShotAnim = true;
        LastFireTime = Level.TimeSeconds;
    }
    else if ( Dist < MeleeRange + CollisionRadius + A.CollisionRadius )
    {
        bShotAnim = true;
        LastFireTime = Level.TimeSeconds;
        SetAnimAction('Claw');
        PlaySound(sound'Claw2s', SLOT_Interact);
        Controller.bPreparingMove = true;
        Acceleration = vect(0,0,0);
    }
    else if( Dist <= (ScreamRadius - DistBeforeScream) && !bDecapitated && !bZapped )
    {
        bShotAnim=true;
        SetAnimAction('Siren_Scream');
        Controller.bPreparingMove = true;
        Acceleration = vect(0,0,0);
    }
}

simulated function SpawnTwoShots()
{
    if( bZapped || bDecapitated)
    {
        return;
    }

    DoShakeEffect();

    if( Level.NetMode!=NM_Client )
    {
        if( Controller!=none && KFDoorMover(Controller.Target)!=none )
            Controller.Target.TakeDamage(ScreamDamage*0.6,self,Location,vect(0,0,0),ScreamDamageType);
        else
            HurtRadius(ScreamDamage ,ScreamRadius, ScreamDamageType, ScreamForce, Location);
    }
}

simulated function DoShakeEffect()
{
    local PlayerController PC;
    local float Dist, scale, BlurScale;

    if (Level.NetMode != NM_DedicatedServer)
    {
        PC = Level.GetLocalPlayerController();
        if (PC != none && PC.ViewTarget != none)
        {
            Dist = VSize(Location - PC.ViewTarget.Location);

            if (Dist < ScreamRadius )
            {
                scale = (ScreamRadius - Dist) / (ScreamRadius);
                scale *= ShakeEffectScalar;
                BlurScale = scale;

                if( !FastTrace(PC.ViewTarget.Location,Location) )
                {
                    scale *= 0.25;
                    BlurScale = scale;
                }
                else
                {
                    scale = Lerp(scale,MinShakeEffectScale,1.0);
                }

                PC.SetAmbientShake(Level.TimeSeconds + ShakeFadeTime, ShakeTime, OffsetMag * Scale, OffsetRate, RotMag * Scale, RotRate);

                if( KFHumanPawn(PC.ViewTarget) != none )
                {
                    KFHumanPawn(PC.ViewTarget).AddBlur(ShakeTime, BlurScale * ScreamBlurScale);
                }

                if ( Level != none && Level.Game != none && !KFGameType(Level.Game).bDidSirenScreamMessage && FRand() < 0.10 )
                {
                    PC.Speech('AUTO', 16, "");
                    KFGameType(Level.Game).bDidSirenScreamMessage = true;
                }
            }
        }
    }
}

simulated function HurtRadius( float DamageAmount, float DamageRadius, class<DamageType> DamageType, float Momentum, vector HitLocation )
{
    local actor Victims;
    local float damageScale, dist;
    local vector dir;
    local float UsedDamageAmount;

    if( bHurtEntry )
        return;

    bHurtEntry = true;

    foreach VisibleCollidingActors( class 'Actor', Victims, DamageRadius, HitLocation )
    {
        if( (Victims != self) && !Victims.IsA('FluidSurfaceInfo') && !Victims.IsA('KFMonster') && !Victims.IsA('ExtendedZCollision') )
        {
            dir = Victims.Location - HitLocation;
            dist = FMax(1,VSize(dir));
            dir = dir/dist;
            damageScale = 1 - FMax(0,(dist - Victims.CollisionRadius)/DamageRadius);

            if (!Victims.IsA('KFHumanPawn'))
                Momentum = 0;

            if (Victims.IsA('KFGlassMover'))
            {
                UsedDamageAmount = 100000;
            }
            else
            {
                UsedDamageAmount = DamageAmount;
            }

            Victims.TakeDamage(damageScale * UsedDamageAmount,Instigator, Victims.Location - 0.5 * (Victims.CollisionHeight + Victims.CollisionRadius) * dir,(damageScale * Momentum * dir),DamageType);

            if (Instigator != none && Vehicle(Victims) != none && Vehicle(Victims).Health > 0)
                Vehicle(Victims).DriverRadiusDamage(UsedDamageAmount, DamageRadius, Instigator.Controller, DamageType, Momentum, HitLocation);
        }
    }

    bHurtEntry = false;
}

function RemoveHead()
{
    super.RemoveHead();
    if( FRand()<0.5 )
        KilledBy(LastDamagedBy);
    else
    {
        bAboutToDie = true;
        MeleeRange = -500;
        DeathTimer = Level.TimeSeconds+10*FRand();
    }
}

State ZombieDyingOS
{
    ignores AnimEnd, Trigger, Bump, HitWall, HeadVolumeChange, PhysicsVolumeChange, Falling, BreathTimer, Died, RangedAttack, SpawnTwoShots;
}

simulated function Tick( float Delta )
{
    super.Tick(Delta);
    if( bAboutToDie && Level.TimeSeconds>DeathTimer )
    {
        if( Health>0 && Level.NetMode!=NM_Client )
            KilledBy(LastDamagedBy);
        bAboutToDie = false;
    }
}

function PlayDyingSound()
{
    if( !bAboutToDie )
        super.PlayDyingSound();
}

static simulated function PreCacheMaterials(LevelInfo myLevel)
{
    myLevel.AddPrecacheMaterial(Texture'KFOldSchoolZeds_Textures.Siren.SirenSkin');
    myLevel.AddPrecacheMaterial(FinalBlend'KFOldSchoolZeds_Textures.Siren.SirenHairFB');
}

defaultproperties
{
     DistBeforeScream=200.000000
     ScreamRadius=900
     ScreamDamageType=Class'KFMod.SirenScreamDamage'
     ScreamForce=-150000
     RotMag=(Pitch=150,Yaw=150,Roll=150)
     RotRate=500.000000
     OffsetMag=(Y=5.000000,Z=1.000000)
     OffsetRate=500.000000
     ShakeTime=2.000000
     ShakeFadeTime=0.250000
     ShakeEffectScalar=1.000000
     MinShakeEffectScale=0.600000
     ScreamBlurScale=0.850000
     MeleeAnims(0)="Siren_Bite"
     MeleeAnims(1)="Siren_Bite"
     MeleeAnims(2)="Siren_Bite"
     HitAnims(0)="HitReactionF"
     HitAnims(1)="HitReactionF"
     HitAnims(2)="HitReactionF"
     MoanVoice=SoundGroup'KFOldSchoolZeds_Sounds.siren.Siren_Speech'
     ZapThreshold=0.500000
     ZappedDamageMod=1.500000
     ZombieFlag=1
     MeleeDamage=13
     damageForce=5000
     KFRagdollName="SirenRag"
     ZombieDamType(0)=Class'KFMod.DamTypeSlashingAttack'
     ZombieDamType(1)=Class'KFMod.DamTypeSlashingAttack'
     ZombieDamType(2)=Class'KFMod.DamTypeSlashingAttack'
     JumpSound=Sound'KFOldSchoolZeds_Sounds.Shared.Female_ZombieJump'
     ScreamDamage=8
     CrispUpThreshhold=7
     bCanDistanceAttackDoors=True
     bUseExtendedCollision=True
     ColOffset=(Z=48.000000)
     ColRadius=25.000000
     ColHeight=5.000000
     PlayerCountHealthScale=0.100000
     OnlineHeadshotOffset=(X=12.000000,Y=-3.000000,Z=44.000000)
     OnlineHeadshotScale=1.200000
     HeadHealth=200.000000
     PlayerNumHeadHealthScale=0.050000
     MotionDetectorThreat=2.000000
     HitSound(0)=SoundGroup'KFOldSchoolZeds_Sounds.Shared.Female_ZombiePain'
     DeathSound(0)=Sound'KFOldSchoolZeds_Sounds.siren.Siren_Die'
     ScoringValue=25
     SoundGroupClass=Class'KFOldSchoolZeds.KFFemaleZombieSoundsOS'
     IdleHeavyAnim="Siren_Idle"
     IdleRifleAnim="Siren_Idle"
     MeleeRange=45.000000
     GroundSpeed=100.000000
     WaterSpeed=80.000000
     HealthMax=300.000000
     Health=300
     HeadRadius=6.000000
     HeadHeight=4.500000
     MenuName="Siren 2.5"
     ControllerClass=Class'KFOldSchoolZeds.ControllerSirenOS'
     MovementAnims(0)="Siren_Walk"
     MovementAnims(1)="Siren_Walk"
     MovementAnims(2)="Siren_Walk"
     MovementAnims(3)="Siren_Walk"
     WalkAnims(0)="Siren_Walk"
     WalkAnims(1)="Siren_Walk"
     WalkAnims(2)="Siren_Walk"
     WalkAnims(3)="Siren_Walk"
     IdleCrouchAnim="Siren_Idle"
     IdleWeaponAnim="Siren_Idle"
     IdleRestAnim="Siren_Idle"
     Mesh=SkeletalMesh'KFCharacterModelsOldSchool.InfectedWhiteMale2'
     PrePivot=(Z=-8.000000)
     Skins(0)=Texture'KFOldSchoolZeds_Textures.siren.SirenSkin'
     Skins(1)=FinalBlend'KFOldSchoolZeds_Textures.siren.SirenHairFB'
     RotationRate=(Yaw=45000,Roll=0)
}
