class StinkyClot extends ZombieClot;

var() name CompleteAnim;
var() name GrabBone;

var float NextStuckTestTime;
var transient vector OldLocation;
var transient int StuckCounter;

// Teleporting
const TELEPORT_NONE     = 0;
const TELEPORT_FADEOUT  = 1;
const TELEPORT_FADEIN   = 2;
var byte TeleportPhase, ClientTeleportPhase;
var transient vector TeleportLocation;
var transient float AlphaFader;
var string TeleportSoundRef;
var sound TeleportSound;
var transient Actor LastMoveTarget[2];

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


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

    if ( TeleportSound == none ) {
        TeleportSound = sound(DynamicLoadObject(TeleportSoundRef, class'Sound', true));
        default.TeleportSound = TeleportSound;
    }
}

simulated function PostNetBeginPlay()
{
    super.PostNetBeginPlay();
    SetSkin();
}

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

    if (ClientTeleportPhase != TeleportPhase) {
        ClientTeleportPhase = TeleportPhase;
        if (TeleportPhase == TELEPORT_FADEIN) {
            AlphaFader = 1;
            PlaySound(TeleportSound, SLOT_Interact, 4.0);
        }
        else {
            AlphaFader = 255;
        }
    }
    SetSkin();
}

simulated function Tick(float dt)
{
    super.Tick(dt);

    if ( Controller != none && Controller.MoveTarget != none && Controller.MoveTarget != self
            && Controller.IsInState('Moving') )
    {
        if ( LastMoveTarget[0] != Controller.MoveTarget && LastMoveTarget[1] != Controller.MoveTarget ) {
            LastMoveTarget[1] = LastMoveTarget[0];
            LastMoveTarget[0] = Controller.MoveTarget;
            OldLocation = Location;
            StuckCounter = 0;
            NextStuckTestTime = Level.TimeSeconds + 1;
        }
        else if ( Level.TimeSeconds > NextStuckTestTime ) {
            NextStuckTestTime = Level.TimeSeconds + 1;
            OldLocation.Z = Location.Z; // ignore Z difference, because zed may be constantly jumping
            if ( VSizeSquared(Location - OldLocation) < 10000 ) {
                StuckCounter += 3;  // 10 seconds to move away from the current location
            }
            else {
                OldLocation = Location;
                StuckCounter += 1; // 30s to reach the target
            }

            if ( StuckCounter >= 30 ) {
                // if can't reach the target - simply teleport to it
                TeleportLocation = Controller.MoveTarget.Location;
                TeleportLocation.Z += CollisionHeight;
                StartTeleport();
            }
        }
    }

    if ( TeleportPhase != TELEPORT_NONE ) {
        switch ( TeleportPhase ) {
            case TELEPORT_FADEOUT:
                AlphaFader = FMax(AlphaFader - dt * 512, 0);

                if (Level.NetMode != NM_Client && AlphaFader == 0) {
                    DoTeleport();
                }
                break;
            case TELEPORT_FADEIN:
                AlphaFader = FMin(AlphaFader + dt * 256, 255);

                if (Level.NetMode != NM_Client && AlphaFader == 255) {
                    TeleportPhase = TELEPORT_NONE;
                    if (Level.NetMode != NM_DedicatedServer)
                        SetSkin();
                }
                break;
        }

        if (Level.NetMode != NM_DedicatedServer && ColorModifier(Skins[0]) != none) {
            ColorModifier(Skins[0]).Color.A = AlphaFader;
        }
    }
}

simulated function SetSkin()
{
    if ( bBlockActors && TeleportPhase == TELEPORT_NONE) {
        Skins[0] = default.Skins[0];
        if ( bCrispified )
            ZombieCrispUp();
    }
    else {
        Skins[0] = ColorModifier'ScrnTex.Zeds.StinkyColor';
        ColorModifier(Skins[0]).Color.A = AlphaFader;
        ColorModifier(Skins[0]).AlphaBlend = TeleportPhase != TELEPORT_NONE;
    }
}

function StartTeleport()
{
    TeleportPhase = TELEPORT_FADEOUT;
    AlphaFader = 255;
    if ( Level.NetMode != NM_DedicatedServer ) {
        SetSkin();
    }
    StuckCounter = 0;
    NextStuckTestTime = Level.TimeSeconds + 5;
}

function DoTeleport()
{
    TeleportPhase = TELEPORT_FADEIN;
    AlphaFader = 0;
    if ( Level.NetMode != NM_DedicatedServer ) {
        SetSkin();
    }
    Velocity = vect(0,0,0);
    Acceleration = vect(0,0,0);
    if (SetLocation(TeleportLocation))
    {
        PlaySound(TeleportSound, SLOT_Interact, 4.0);
        Controller.StopWaiting();
    }
}

function TakeDamage(int Damage, Pawn instigatedBy, Vector hitlocation, Vector momentum, class<DamageType> damageType, optional int HitIndex )
{
    if ( bBlockActors )
        super.TakeDamage(Damage, instigatedBy, hitlocation, momentum, damageType, HitIndex);
    // stinky clot does not take damage
}

function Died(Controller Killer, class<DamageType> damageType, vector HitLocation)
{
    local int i;
    local TheGuardian gnome;

    for( i=0; i<Attached.length; i++ ) {
        gnome = TheGuardian(Attached[i]);
        if ( gnome != none )
            gnome.PawnBaseDied();
    }

    super.Died(Killer,damageType,HitLocation);
}


function bool FlipOver()
{
    return false;
}

function RemoveHead()
{
    KilledBy(LastDamagedBy);
}

// removed references to KFMonsterController
event Bump(actor Other)
{
    if ( KFDoorMover(Other) != none )
        BlowUpDoor(KFDoorMover(Other));
    else
        super(Monster).Bump(Other);
}

function BlowUpDoor(KFDoorMover door)
{
    local int i;
    local KFUseTrigger key;

    if ( door == none || !door.bClosed )
        return;

    key = door.MyTrigger;
    if ( key != none ) {
        for ( i=0; i<key.DoorOwners.Length; ++i ) {
            if ( !key.DoorOwners[i].bDoorIsDead )
                key.DoorOwners[i].GoBang(self, Location, vector(Rotation), none);
        }
    }
    else
        door.GoBang(self, Location, vector(Rotation), none);
}

function KickActor()
{
    // no KFMonsterController to perform a kick
}


simulated function SetBurningBehavior()
{
}

simulated function UnSetBurningBehavior()
{
}

simulated function float GetOriginalGroundSpeed()
{
    return GroundSpeed;
}

defaultproperties
{
     CompleteAnim="ClotPunt"
     GrabBone="CHR_RArmPalm"
     TeleportSoundRef="ScrnZedPack_S.Shiver.ShiverWarpGroup"
     EventClasses(0)="ScrnBalanceSrv.StinkyClot"
     MoanVoice=SoundGroup'KF_EnemiesFinalSnd.clot.Clot_Talk'
     MeleeAttackHitSound=SoundGroup'KF_EnemiesFinalSnd.clot.Clot_HitPlayer'
     JumpSound=SoundGroup'KF_EnemiesFinalSnd.clot.Clot_Jump'
     bUseExtendedCollision=False
     DetachedArmClass=Class'KFChar.SeveredArmClot'
     DetachedLegClass=Class'KFChar.SeveredLegClot'
     DetachedHeadClass=Class'KFChar.SeveredHeadClot'
     HeadHealth=1000.000000
     HitSound(0)=SoundGroup'KF_EnemiesFinalSnd.clot.Clot_Pain'
     DeathSound(0)=SoundGroup'KF_EnemiesFinalSnd.clot.Clot_Death'
     ChallengeSound(0)=SoundGroup'KF_EnemiesFinalSnd.clot.Clot_Challenge'
     ChallengeSound(1)=SoundGroup'KF_EnemiesFinalSnd.clot.Clot_Challenge'
     ChallengeSound(2)=SoundGroup'KF_EnemiesFinalSnd.clot.Clot_Challenge'
     ChallengeSound(3)=SoundGroup'KF_EnemiesFinalSnd.clot.Clot_Challenge'
     GroundSpeed=55.000000
     JumpZ=480.000000
     HealthMax=1000.000000
     Health=1000
     MenuName="Stinky Clot"
     ControllerClass=Class'ScrnBalanceSrv.StinkyController'
     bAlwaysRelevant=True
     AmbientSound=Sound'KF_BaseClot.Clot_Idle1Loop'
     Mesh=SkeletalMesh'KF_Freaks_Trip.CLOT_Freak'
     DrawScale=0.500000
     Skins(0)=Combiner'KF_Specimens_Trip_T.clot_cmb'
     CollisionRadius=13.000000
     CollisionHeight=22.000000
     bBlockActors=False
}
