//=============================================================================
// AICommand_Base_Crawler
//=============================================================================
// Base controller for the Crawler
//=============================================================================
// Killing Floor 2
// Copyright (C) 2015 Tripwire Interactive LLC
//=============================================================================

class AICommand_Base_Crawler extends AICommand_Base_Zed
	within KFAIController_ZedCrawler;

var KFWallPathNode	LeapTarget;
var bool			bJumpingToWall;
var vector			TempDest;
var vector			OriginalTrans;
var actor			TempMoveGoal;

/*********************************************************************************************
* Initialization
********************************************************************************************* */

function Pushed()
{
	Super.Pushed();
	Originaltrans = Pawn.Mesh.Translation;
	if( OldFloor == vect(0,0,0) )
	{
		OldFloor = vect(0,0,1);
	}
	//EnableSeePlayer();
	GotoState( DefaultStateName );
}

function Paused( GameAICommand NewCommand )
{
	`AILog( self$" "$GetFuncName()$"() Paused for "$NewCommand, 'Crawler' );
	Super.Paused( NewCommand );
}

function BeginMoveToWall()
{
    // Disabled for Early Access 1/14/15 as part of disabling wall walking - Ramm
	//GotoState( 'MoveToWall',, true );
}

function SightCheck();

function Resumed( name OldCommandName )
{
	`AILog( self$" "$GetFuncName()$"() (OldCommandName: "$OldCommandName$")", 'Crawler' );
	Super.Resumed( OldCommandName );
// Untested WIP
// 	DisableSeePlayer();
// 	if( Pawn.Physics == PHYS_Walking || Pawn.Physics == PHYS_Falling )
// 	{
// 		DisableMeleeRangeEventProbing();
// 		GotoState( 'MoveToWall' );
// 	}
// 	else if( GetStateName() != DefaultStateName && Pawn.Physics == PHYS_Spider && CanSee(Enemy) )
// 	{
// 		GotoState( 'MoveToWall', 'Begin' );
// 	}
// 	else
// 		GotoState( DefaultStateName,, true );
}

// Disabled for Early Access 1/14/15 as part of disabling wall walking - Ramm
//state MoveToWall
//{
//	event BeginState( name PreviousStateName )
//	{
//	}
//
//	event EndState( name NextStateName )
//	{
//	}
//
//	function BeginMoveToWall();
//
//	function SightCheck()
//	{
//// 		if( FRand() < 0.33f && Enemy.Controller.CanSee(Pawn) && Pawn.Physics == PHYS_Spider )
//// 		{
//// 			StopAllLatentMovement();
//// 			JumpToTarget();
//// 			return;
//// 		}
//// 		SetTimer( 1.f + FRand() * 2.f, false, nameof(SightCheck), self );
//	}
//
//	function JumpToTarget()
//	{
//		local Vector Suggested;
//		local NavigationPoint ClosestToEnemy, ClosestToMe;
//		local actor Target;
//
//		ClosestToEnemy = class'NavigationPoint'.static.GetNearestNavToActor( Enemy, class'KFPathnode' );
//		DrawDebugSphere( ClosestToEnemy.Location, 32, 8, 255, 0, 0, true );
//		ClosestToMe = class'NavigationPoint'.static.GetNearestNavToActor( Pawn, class'KFPathnode' );
//		DrawDebugSphere( ClosestToMe.Location, 32, 8, 0, 255, 0, true );
//		if( VSize( ClosestToEnemy.Location - Pawn.Location ) < VSize(Enemy.Location - Pawn.Location) )
//		{
//			Target = ClosestToEnemy;
//		}
//		else
//		{
//			Target = ClosestToMe;
//		}
//
//		//class'NavigationPoint'.static.GetAllNavInRadius( Outer, Enemy.Location
//		if( Target != none )// && ActorReachable(Target) && VSize(Target.Location - Pawn.Location) < 750.f )
//		{
//			MyKFPawn.SuggestJumpVelocity( Suggested, Target.Location, Pawn.Location );
//			MyKFPawn.Velocity = Suggested * MyKFPawn.Floor;;
//			MoveTarget = Target;
//			//MyKFPawn.Acceleration = vect( 0,0,0 );
//			MyKFPawn.SetPhysics( PHYS_Falling );
//			Pawn.ResetDesiredRotation();
//			Focus = none;
//			SetFocalPoint(MoveTarget.Location);
//	//		Focus = none;
//
//			//Focus = Enemy;
//		}
//	}
//
//	function SetBestAnchor()
//	{
//		local NavigationPoint BestAnchor;
//		local float Dist;
//
//		BestAnchor = Pawn.GetBestAnchor( Pawn, Pawn.Location, true, false, Dist );
//		if( BestAnchor != none )
//		{
//			Pawn.SetAnchor( BestAnchor );
//		}
//	}
//
//Jumping:
//	if( MyKFPawn.IsPawnMovingTowardMe( Enemy, 250.f ) )
//	{
//		Sleep( 0.1f );
//		Goto( 'Jumping' );
//	}
//
//	Sleep( FRand() );
////	SetFocalPoint(vect(0,0,0) );
////	Focus = Enemy;
//	StopAllLatentMovement();
//	AIZeroMovementVariables();
//	JumpToTarget();
//	WaitForLanding();
//	SetBestAnchor();
//	LastAmbushNode = none;
//	if( Pawn.Physics == PHYS_Walking )
//	{
//		GotoState( DefaultStateName,, true );
//	}
//	else
//	{
//		if( FRand() < 0.22f )
//		{
//			Sleep( 0.5f );
//		}
//		GotoState( DefaultStateName,, true );
//	}
//
//Begin:
//	// do not do this, this is set in the above function do not reset it
//	//MyKFPawn.bIsSprinting = true;
//	MyKFPawn.SetSprinting( true );
//	if( FindAmbushNode(true) )
//	{
//		LastAmbushNode = NavigationPoint( RouteGoal );
//
//		SetMoveGoal(  RouteGoal,, false,, false, true, false, false, true );
//		Goto( 'Jumping' );
//	//	Sleep( 0.f );
//	}
//	GotoState( DefaultStateName,, true );
//Moving:
//	if( Steering != none )
//	{
//		Steering.EnableDefaultAcceleration();
//	}
//	//MyKFPawn.bIsSprinting = true;
//	MyKFPawn.SetSprinting( true );
//	SetTempDest();
//	if( VSize( TempDest - Pawn.Location ) > 96.f  )
//	{
//		//MoveTo( Pawn.Location + TempDest * 512.f );
//		MoveTo( TempDest );
//	}
//	else
//	{
//		Sleep( 0.1f * FRand() );
//	}
//
//	Sleep( 0.f );
//	Goto( 'Begin' );
//}

function CheckWalls()
{
	local KFWallPathNode KFWP, BestKFWP;
	local float BestDist;

// 	if( Pawn.Physics == PHYS_Spider )
// 	{
//		return;
//	}

	DisableSeePlayer(0.f);
	Enemy = none;
	foreach WorldInfo.AllNavigationPoints( class'KFWallPathNode', KFWP )
	{
		if( BestKFWP == None || VSize(KFWP.Location - Pawn.Location) < BestDist )
		{
			if( KFWP.Location.Z > 350.f )
			{
				BestDist = VSize(KFWP.Location - Pawn.Location);
				BestKFWP = KFWP;
			}
		}
	}
	LeapTarget = BestKFWP;
	StopAllLatentMovement();
	//GotoState( 'ZedBaseCommand', 'Leaping' );
}

// Disabled for Early Access 1/14/15 as part of disabling wall walking - Ramm
//state ZedBaseCommand
//{
//	event BeginState( name PreviousStateName )
//	{
//		super.BeginState( PreviousStateName );
//		DisableSeePlayer(0.f);
//		//SetTimer( 1.5f, nameof(CheckWalls), true, self );
//	}
//// Leaping:
//// 	bJumpingToWall = true;
//// 	DoWallLeap( LeapTarget );
////  	if( Pawn.Physics == PHYS_Falling )
//// 	{
////  		WaitForLanding();
////  	}
//// 	Goto( 'Begin' );
//}

// Disabled for Early Access 1/14/15 as part of disabling wall walking - Ramm
//function bool NotifyFallingHitWall(vector HitNormal, actor Wall)
//{
//	return NotifyHitWall( HitNormal, Wall );
//}
//
//// 1.31 check bCanStepUpOn below
//function bool NotifyHitWall( vector HitNormal, actor HitActor )
//{
//	local KFDoorActor HitDoor;
//
//	HitDoor = KFDoorActor( HitActor );
//	if( HitDoor != none && MyKFPawn.Physics != PHYS_Spider )
//	{
//		if( HitDoor.WeldIntegrity <= 0 && KFDoorMarker(HitDoor.MyMarker) != none && !HitDoor.IsCompletelyOpen() )
//		{
//			DisableNotifyHitWall(0.25f);
//			WaitForDoor( HitDoor );
//			`AILog( "NotifyHitWall() while in MoveToGoal, Wall: "$HitActor$" Using door and waiting for it to open", 'Doors' );
//			HitDoor.UseDoor(Pawn);
//			return true;
//		}
//		// NOTE: Unless returning true, if the Wall is a closed door, SuggestMovePreparation event will be called on the associated KFDoorMarker
//		`AILog( GetFuncName()$"() Wall: "$HitActor$" HitNormal: "$HitNormal$" ran into a door!", 'Doors' );
//		if( !HitDoor.IsCompletelyOpen() && HitDoor.WeldIntegrity > 0 && (Pawn.Anchor == HitDoor.MyMarker || (DoorEnemy != none && (DoorEnemy == HitDoor || PendingDoor == HitDoor))) )
//		{
//			DisableNotifyHitWall(0.25f);
//			`AILog( GetFuncName()$"() calling NotifyAttackDoor for "$HitDoor, 'Doors' );
//			NotifyAttackDoor( HitDoor );
//			return true;
//			//`AILog( GetFuncName()$"() has door enemy "$DoorEnemy, 'Doors' );
//		}
//	}
//	if( HitActor != none && !HitActor.bCanStepUpon )
//	{
//		`warn( GetFuncName()$"() Wall "$HitActor$" bCanStepUpOn is FALSE" );
//		return false;
//	}
//
//	if( Pawn != none && HitActor != none && Pawn.Physics == PHYS_Falling )
////		if( bJumpingToWall )
//	{
//		`AILog( "*NotifyHitWall setting physics to PHYS_Spider and base to "$HitActor, 'Crawler' );
//		Pawn.SetPhysics( PHYS_Spider );
//		Pawn.SetBase( HitActor, HitNormal );
//		DisableNotifyHitWall(1.f);
//	}
//	return true;
//}

// Disabled for Early Access 1/14/15 as part of disabling wall walking - Ramm
//state RotateToFocus
//{
//	function PushedState()
//	{
//		super.PushedState();
//		AIActionStatus = "In RotateToFocus state";
//	}
//
//Begin:
//// 	SetFocalPoint( vect(0,0,0) );
//// 	Focus = LeapTarget;
//// 	FinishRotation();
//// 	SetFocalPoint(Vect(0,0,0));
//// 	Focus = none;
//// 	Pawn.ResetDesiredRotation();
//	PopState();
//}

function SetTempDest()
{
	local vector V, ProjFocus, X, EnemyLoc;
	local float Distance;

	if( Enemy == none )
	{
		Enemy = GetALocalPlayerController().Pawn;
	}

	EnemyLoc = Enemy.Location;
	EnemyLoc.Z = Pawn.Location.Z + RandRange( -64, 64 );
	v = EnemyLoc - Pawn.Location;
	Distance = (V dot Pawn.Floor);
	ProjFocus = EnemyLoc - Distance * Pawn.Floor;
	X = normal(ProjFocus - Pawn.Location);
	//vector v = Focus - Pawn->Location
	if( X != vect(0,0,0) )
	{
		TempDest = ProjFocus;
		//	return true;
	}
	else
	{
		//	return false;
	}
}

// Disabled for Early Access 1/14/15 as part of disabling wall walking - Ramm
//function bool NotifyBaseChange( actor NewBase, vector NewFloor )
//{
////	if( NewFloor != OldFloor && Pawn.Physics == PHYS_Spider && NewBase != none /*&& bPreciseDestination*/ )
////	{
////		GotoState( GetStateName(), 'HandleNewFloor' );
////
////
////	}
////	else
//
//	if( NewFloor != OldFloor )
//	{
//		if( NewFloor.Z > 0.7f ) // 2.9.2014 was 		if( NewFloor == vect(0,0,1) )
//		{
//			if( Pawn.Physics == PHYS_Spider )
//			{
//				`AILog( GetFuncName()$"() NewFloor is upright, physics is spider - setting physics back to walking!", 'Crawler' );
//				Pawn.SetPhysics(PHYS_Walking);
//			}
//		}
//		else if( Pawn.Physics == PHYS_Walking )
//		{
//			Pawn.SetPhysics( PHYS_Spider );
//		}
//	}
//
//	 `AILog( GetFuncName()$" in "$self$" NewBase: "$NewBase$" NewFloor: "$NewFloor$" Pawn Floor: "$Pawn.Floor$" OldFloor: "$OldFloor$" Physics: "$Pawn.GetPhysicsName(), 'Crawler' );
//	if( NewFloor != OldFloor &&  Pawn != none && Pawn.Physics == PHYS_Spider && NewBase != none && !NewBase.IsA('Pawn') && NewBase.bWorldGeometry )
//	{
//		if( IsDoingLatentMove() )
//		{
//// 			StopAllLatentMovement();
//// 			Pawn.ZeroMovementVariables();
//// 			MoveTimer = -1.f;
//		}
//		//`AILog( "NOTIFYBASECHANGE: "$NewBase$" New floor: "$NewFloor$" Old floor: "$OldFloor$" Floor set yet? "$Pawn.Floor );
//		//GotoState( GetStateName(), 'HandleNewFloor' );
//	}
//
//	return false;
//}
//
//function bool NotifyLanded(vector HitNormal, Actor FloorActor )
//{
//	`AILog( "**** NotifyLanded **** HitNormal: "$HitNormal$" FloorActor: "$FloorActor$" Floor is currently "$Pawn.Floor );
//
//	bJumpingToWall = false;
//	if( Pawn.Floor.Z == 1.f && (Pawn.Physics == PHYS_Walking || Pawn.Physics == PHYS_Falling) )
//	{
//		Pawn.SetPhysics( PHYS_Walking );
//		return true;
//	}
//
//
//	bJumpingToWall = false;
//	`AILog( GetFuncName()$" setting physics to PHYS_Spider, FloorActor: "$FloorActor, 'Crawler');
//	Pawn.SetPhysics(PHYS_Spider);
//	return true;
//}

// // Disabled for Early Access 1/14/15 as part of disabling wall walking - Ramm P.S. also doesn't seem to be called anywhere
//state Debug_InCombat
//{
//	function bool NotifyLanded(vector HitNormal, Actor FloorActor )
//    {
//		`AILog( GetFuncName()$" 2 setting physics to PHYS_Spider, FloorActor: "$FloorActor, 'Crawler' );
//		bJumpingToWall = false;
//        Pawn.SetPhysics(PHYS_Spider);
//        return true;
//    }
//
//	function Tick( float DeltaTime )
//	{
////		local vector CeilingTrans;
//
//// 		if( Pawn.Floor.Z == -1 )
//// 		{
//// 			CeilingTrans = OriginalTrans;
//// 			CeilingTrans.X = 36;
//// 			Pawn.Mesh.SetTranslation( CeilingTrans );
//// 		}
//// 		else
//// 		{
//// 			Pawn.Mesh.SetTranslation( vect(0,0,-36) );
//// 		}
//		super.Tick( DeltaTime );
//	}
//
//	event BeginState( name PreviousStateName )
//	{
//		local KFWallPathNode KFWP, BestKFWP;
//		local float BestDist;
//
//		DisableSeePlayer(0.f);
//		Enemy = none;
//		foreach WorldInfo.AllNavigationPoints( class'KFWallPathNode', KFWP )
//		{
//			if( BestKFWP == None || VSize(KFWP.Location - Pawn.Location) < BestDist )
//			{
//					BestDist = VSize(KFWP.Location - Pawn.Location);
//					BestKFWP = KFWP;
//			}
//		}
//		LeapTarget = BestKFWP;
//		//GetAxes(Pawn.Rotation,ViewX,ViewY,ViewZ);
//	}
//
//	function bool NotifyHitWall(vector HitNormal, actor HitActor)
//	{
//		if( !HitActor.bCanStepUpon )
//		{
//			`warn( GetFuncName()$"() Wall "$HitActor$" bCanStepUpOn is FALSE" );
//		}
//
//		if( bJumpingToWall )
//		{
//			`AILog( GetFuncName()$" 3 setting physics to PHYS_Spider, HitActor: "$HitActor, 'Crawler' );
//			Pawn.SetPhysics( PHYS_Spider );
//			Pawn.SetBase( HitActor, HitNormal );
//		}
//	 	return true;
// 	}
//
//	function SetTempDest()
//	{
//		local vector V, ProjFocus, X, EnemyLoc;
//		local float Distance;
//
//		if( Enemy == none )
//		{
//			Enemy = GetALocalPlayerController().Pawn;
//		}
//
//		EnemyLoc = Enemy.Location;
//		EnemyLoc.Z = Pawn.Location.Z + RandRange( -72, 72 );
//		v = EnemyLoc - Pawn.Location;
//		Distance = (V dot Pawn.Floor);
//		ProjFocus = EnemyLoc - Distance * Pawn.Floor;
//		X = normal(ProjFocus - Pawn.Location);
//		if( X != vect(0,0,0) )
//		{
//			TempDest = ProjFocus;
//		}
//	}
//
//Begin:
//	if( Physics == PHYS_Falling )
//	{
//		WaitForLanding();
//	}
//	Pawn.SetPhysics(Phys_Walking);
//	if( LeapTarget != none )
//	{
//		PushState( 'RotateToFocus' );
//	}
//
// //	Focus = none;
//	Sleep( 1.f );
//	bJumpingToWall = true;
//	//DoWallLeap( LeapTarget );
// 	if( Pawn.Physics == PHYS_Falling )
//	{
// 		WaitForLanding();
// 	}
//
////	Enemy = GetALocalPlayerController().Pawn;
//	Sleep( 5.f );
//	Pawn.SetAnchor( LeapTarget );
//	SetMoveGoal( TempMoveGoal,, false,, false, true,,, true );
//Moving:
//	MyKFPawn.SetSprinting( true );
//	if( VSize( TempDest - Pawn.Location ) > 350.f )
//	{
//		//MoveTo( Pawn.Location + TempDest * 512.f );
//		MoveTo( TempDest );
//	}
//	else
//	{
//		Sleep( 2.f * FRand() );
//	}
//	Goto( 'Moving' );
//
//HandleNewFloor:
//	if( Pawn != none && Pawn.IsAliveAndWell() )
//	{
//		AIZeroMovementVariables();
//		StopAllLatentMovement( true );
//		Sleep( 0.1f );
//		Goto( 'Moving' );
//	}
//}

DefaultProperties
{
}
