// Completely invisible Stalker
// (c) PooSH, 2014
// used 'ClawAndMove' code from Scary Ghost's SuperStaler
// Ported to 'NiceMonster' parent class
class NiceZombieGhost extends NiceZombieStalker;
// max distance squared for player to see cloacked Stalkers. 
// Beyond that distance Stalkers will appear completely invisible.
var float CloakDistanceSqr; 
// Unclock distance squared for Commandos
var float UncloakDistanceSqr;
var const Material CloakMat;
var const Material InvisibleMat;
var const Material UncloakMat, UncloakFBMat;
var const Material GlowFX;
static simulated function PreCacheMaterials(LevelInfo myLevel)
{
    myLevel.AddPrecacheMaterial(default.CloakMat);
    myLevel.AddPrecacheMaterial(default.InvisibleMat);
    myLevel.AddPrecacheMaterial(default.UncloakMat);
    myLevel.AddPrecacheMaterial(default.UncloakFBMat);
    myLevel.AddPrecacheMaterial(default.GlowFX);
    myLevel.AddPrecacheMaterial(Combiner'KF_Specimens_Trip_T.stalker_env_cmb');
    myLevel.AddPrecacheMaterial(Texture'KF_Specimens_Trip_T.stalker_diff');
    myLevel.AddPrecacheMaterial(Texture'KF_Specimens_Trip_T.stalker_spec');
    myLevel.AddPrecacheMaterial(Combiner'KF_Specimens_Trip_T.StalkerCloakOpacity_cmb');
    myLevel.AddPrecacheMaterial(Material'KF_Specimens_Trip_T.StalkerCloakEnv_rot');
    myLevel.AddPrecacheMaterial(Material'KF_Specimens_Trip_T.stalker_opacity_osc');
    myLevel.AddPrecacheMaterial(Material'KFCharacters.StalkerSkin');
}


simulated function PostNetBeginPlay()
{
    super.PostNetBeginPlay();
    if ( LocalKFHumanPawn != none ) {
       CloakDistanceSqr = fmax(CloakDistanceSqr, 3.0 * UncloakDistanceSqr * LocalKFHumanPawn.GetStalkerViewDistanceMulti());
       UncloakDistanceSqr *= LocalKFHumanPawn.GetStalkerViewDistanceMulti();
    }
}

function RenderOverlays(Canvas Canvas)
{
    Canvas.SetDrawColor(0, 92, 255, 255);
    super.RenderOverlays(Canvas);
}
// makes Stalker invisible or glowing (for commando)
simulated function CloakStalker()
{
    // No cloaking if zapped
    if( bZapped )
    {
       return;
    }
    if ( bSpotted ) {
       if( Level.NetMode == NM_DedicatedServer )
           return;

       Skins[0] = GlowFX;
       Skins[1] = GlowFX;
       bUnlit = true;
    }
    else if ( !bDecapitated && !bCrispified ) // No head, no cloak, honey.  updated :  Being charred means no cloak either :D
    {
       Visibility = 1;
       bCloaked = true;

       if( Level.NetMode == NM_DedicatedServer )
           Return;

       Skins[0] = InvisibleMat;
       Skins[1] = InvisibleMat;
       bUnlit = false;

       // Invisible - no shadow
       if(PlayerShadow != none)
           PlayerShadow.bShadowActive = false;
       if(RealTimeShadow != none)
           RealTimeShadow.Destroy();

       // Remove/disallow projectors on invisible people
       Projectors.Remove(0, Projectors.Length);
       bAcceptsProjectors = false;
       SetOverlayMaterial(Material'KFX.FBDecloakShader', 0.25, true);
    }
}
simulated function UnCloakStalker()
{
    if( bZapped )
    {
       return;
    }
    if( !bCrispified )
    {
       LastUncloakTime = Level.TimeSeconds;

       Visibility = default.Visibility;
       bCloaked = false;
       bUnlit = false;

       // 25% chance of our Enemy saying something about us being invisible
       if( Level.NetMode!=NM_Client && !KFGameType(Level.Game).bDidStalkerInvisibleMessage && FRand()<0.25 && Controller.Enemy!=none &&
        PlayerController(Controller.Enemy.Controller)!=none )
       {
           PlayerController(Controller.Enemy.Controller).Speech('AUTO', 17, "");
           KFGameType(Level.Game).bDidStalkerInvisibleMessage = true;
       }
       if( Level.NetMode == NM_DedicatedServer )
           Return;

       if ( Skins[0] != UncloakMat )
       {
           Skins[1] = FinalBlend'KF_Specimens_Trip_T.stalker_fb';
           Skins[0] = UncloakMat;

           if (PlayerShadow != none)
               PlayerShadow.bShadowActive = true;

           bAcceptsProjectors = true;

           SetOverlayMaterial(Material'KFX.FBDecloakShader', 0.25, true);
       }
    }
}
function RemoveHead()
{
    Super(NiceMonster).RemoveHead();
    if (!bCrispified)
    {
       Skins[1] = UncloakFBMat;
       Skins[0] = UncloakMat;
    }
}
simulated function PlayDying(class<DamageType> DamageType, vector HitLoc)
{
    Super(NiceMonster).PlayDying(DamageType,HitLoc);
    if(bUnlit)
       bUnlit=!bUnlit;
    LocalKFHumanPawn = none;
    if (!bCrispified)
    {
       Skins[1] = UncloakFBMat;
       Skins[0] = UncloakMat;
    }
}

simulated function Tick(float DeltaTime)
{
    local float DistanceSqr;
    Super(NiceMonster).Tick(DeltaTime);
    // Keep the stalker moving toward its target when attacking
    if( Role == ROLE_Authority && bShotAnim && !bWaitForAnim && !bZapped ) {
       if( LookTarget!=none ) {
           Acceleration = AccelRate * Normal(LookTarget.Location - Location);
       }
    } 
    if( Level.NetMode==NM_DedicatedServer )
       Return; // Servers aren't intrested in this info.
    if( bZapped ) {
       // Make sure we check if we need to be cloaked as soon as the zap wears off
       NextCheckTime = Level.TimeSeconds;
    }
    else if( Level.TimeSeconds > NextCheckTime && Health > 0 )
    {
       NextCheckTime = Level.TimeSeconds + 0.5;

       bSpotted = false;
       if ( LocalKFHumanPawn != none ) {
           DistanceSqr = VSizeSquared(Location - LocalKFHumanPawn.Location);
           if( LocalKFHumanPawn.Health > 0 && LocalKFHumanPawn.ShowStalkers()
                   && DistanceSqr < UncloakDistanceSqr ) 
           {
               bSpotted = True;
               if ( Skins[0] != GlowFX ) {
                   Skins[0] = GlowFX;
                   Skins[1] = GlowFX;
                   bUnlit = true;                            }
           }
           else if ( DistanceSqr < CloakDistanceSqr ) {
               if ( bCloaked && Skins[0] != CloakMat ) {
                   Skins[0] = CloakMat;
                   Skins[1] = CloakMat;
                   bUnlit = false;
               }
           }
           else if ( Skins[0] != InvisibleMat ) {
               CloakStalker();
           }
       }
    }
}

function RangedAttack(Actor A) 
{
    if ( !bShotAnim && Physics != PHYS_Swimming && CanAttack(A) ) {
       bShotAnim = true;
       SetAnimAction('ClawAndMove');
    }
}
// copied from ZombieSuperStalker (c) Scary Ghost
simulated event SetAnimAction(name NewAction) 
{
    if( NewAction=='' )
       Return;
    ExpectingChannel = AttackAndMoveDoAnimAction(NewAction);
    bWaitForAnim= false;
    if( Level.NetMode!=NM_Client ) {
       AnimAction = NewAction;
       bResetAnimAct = True;
       ResetAnimActTime = Level.TimeSeconds+0.3;
    }
}
// copied from ZombieSuperStalker (c) Scary Ghost
simulated function int AttackAndMoveDoAnimAction( name AnimName ) 
{
    local int meleeAnimIndex;
    local float duration;
    if( AnimName == 'ClawAndMove' ) {
       meleeAnimIndex = Rand(3);
       AnimName = meleeAnims[meleeAnimIndex];

       duration= GetAnimDuration(AnimName, 1.0);
    }
    if( AnimName=='StalkerSpinAttack' || AnimName=='StalkerAttack1' || AnimName=='JumpAttack') {
       AnimBlendParams(1, 1.0, 0.0,, FireRootBone);
       PlayAnim(AnimName,, 0.1, 1);

       return 1;
    }
    return super.DoAnimAction( AnimName );
}
defaultproperties
{
    CloakDistanceSqr=62500.000000
    UncloakDistanceSqr=360000.000000
    CloakMat=Shader'KF_Specimens_Trip_T.stalker_invisible'
    InvisibleMat=Shader'KF_Specimens_Trip_T.patriarch_invisible'
    UncloakMat=Shader'KF_Specimens_Trip_T.stalker_invisible'
    UncloakFBMat=Shader'KF_Specimens_Trip_T.stalker_invisible'
    MenuName="Ghost"
    Skins(0)=Shader'KF_Specimens_Trip_T.patriarch_invisible'
    Skins(1)=Shader'KF_Specimens_Trip_T.patriarch_invisible'
}
