//=============================================================================
// PigCop.uc
//=============================================================================
class PigCop extends Grunt;

#exec OBJ LOAD FILE=..\Meshes\c_characters.dmx
#exec AUDIO IMPORT FILE="..\Sounds\Pigcop\PIGRG.wav" NAME="AcquisitionSound" 
#exec AUDIO IMPORT FILE="..\Sounds\Pigcop\PIGPN.wav" NAME="PainSound" 
#exec AUDIO IMPORT FILE="..\Sounds\Pigcop\PIGDY.wav" NAME="DeathSound" 
#exec AUDIO IMPORT FILE="..\Sounds\Pigcop\PIGRM.wav" NAME="RoamSound" 
#exec AUDIO IMPORT FILE="..\Sounds\Pigcop\ROAM29.wav" NAME="WanderSound" 

//Functions here
function ChooseMeleeAttackState()
{
	// log( "ChooseMeleeAttackState called from state "$GetStateName() );
	if( !bSnatched )
		GotoState( 'TentacleThrust' );
	else
		return;
}

function Died( pawn Killer, class<DamageType> DamageType, vector HitLocation, optional vector Momentum )
{
//	WarnFriendsOnDeath();
	if( MyCombatController != None )
		MyCombatController.UnsetHunting( self );

	if( CurrentCoverSpot != None )
	{
		// log( self$" DIED! Unsetting currentcoverspot: "$CurrentCoverSpot );
		CurrentCoverSpot.bOccupied = false;
		CurrentCoverSpot.OccupiedBy = none;
	}
	Super.Died( Killer, DamageType, HitLocation );
	PlaySound( Sound'dnAI.PigCop.DeathSound', SLOT_Talk, 5.0);
}

//States here

state Idling
{
	ignores HitWall, SeeMonster;

 	function BeginState()
	{
		EnableHeadTracking( true );
		EnableEyeTracking( true );
		Disable( 'SeeMonster' );
		Enable( 'SeePlayer' );
		Disable( 'EnemyNotVisible' );
	}

	function EndState()
	{
		PeripheralVision = -1.0;
	}

	function PlayIdlingAnimation()
	{
		PlayAllAnim( InitialIdlingAnim,, 0.1, true );
	}

	function HearNoise(float Loudness, Actor NoiseMaker)
	{
		local vector OldLastSeenPos;
		
		if( NoiseMaker.IsA( 'HITPACKAGE_Level' ) )
		{
			bCanTorsoTrack = true;
			HeadTrackingActor = NoiseMaker;

			NoiseInstigator = NoiseMaker.Instigator;
			if( NoiseInstigator.IsA( 'PlayerPawn' ) )
			{
				Enemy = NoiseInstigator;
				if( MyCombatController == None )
					GotoState( 'Reacting' );
				else
					GotoState( 'WaitingForEnemy' );
				return;
			}
		}

		if( NoiseMaker.IsA( 'LaserMine' ) && !LaserMine( NoiseMaker ).bNPCsIgnoreMe && Loudness == 0.5 && !LineOfSightTo( NoiseMaker ) )
		{
			SuspiciousActor = NoiseMaker;
			GotoState( 'Investigating' );
			return;
		}

		if( bAggressiveToPlayer && NoiseMaker.IsA( 'PlayerPawn' ) || ( bAggressiveToPlayer && NoiseMaker.Instigator.IsA( 'PlayerPawn' ) ) )
		{
			Enemy = NoiseMaker.Instigator;
			if( Enemy != None )
			{
				// log( "Going to Attacking 5a" );
				GotoState( 'Attacking' );
			}
		}
	}

	function SeePlayer( actor SeenPlayer )
	{
		local float Dist;

		if( !bPatrolled && bPatrolIgnoreSeePlayer )
			return;

		if( bForcedAttack && Enemy != None )
			return;

		// Invisiblilty support.
		if( Pawn( SeenPlayer ) != None && Pawn( SeenPlayer ).Visibility <= 0 )
			return;

		if( bFixedEnemy )
			return;
		
		if( SeenPlayer.IsA( 'PlayerPawn' ) )
		{
			Dist = VSize( Location - SeenPlayer.Location );

			if( bAggressiveToPlayer )
			{
				if( Dist > AggressionDistance )
					return;
				// log( self$" SETTING ENEMY A" );
				Enemy = SeenPlayer;
				GotoState( 'Acquisition' );
				return;
			}
			// Sneaky attacks (only if they cannot be seen). Necessary for Grunts, or not?
			else if( bSnatched && !bAggressiveToPlayer )
			{
				if( Dist <= AggroSnatchDistance )
				{
					if( !PlayerCanSeeMe()  )
					{
						Disable( 'SeePlayer' );
						// log( self$" SETTING ENEMY B" );
						Enemy = SeenPlayer;
						
						NextState = 'Attacking';
						bAggressiveToPlayer = true;
						GotoState( 'SnatchedEffects' );
					}
				}
			}
		}
	}

EnemyDead:
	PlayTopAnim( 'None' );
	if( GetPostureState() == PS_Crouching )
	{		
		bIntoCrouch = true;
		PlayToStanding();
		FinishAnim( 2 );
		PlayBottomAnim( 'None' );
		bIntoCrouch = false;
		SetPostureState( PS_Standing );
		PlayToWaiting( 0.35 );
		PlayWeaponIdle();
		Sleep( 0.15 );
	}
	Goto( 'Begin' );

Acquisition:
	Sleep( 0.15 );
	PlayWeaponIdle( 0.12 );
	// // // log( self$" ChooseAttackState from Idling 1" );
	ChooseAttackState();

StandUp:
	if( GetPostureState() == PS_Crouching && !bKneelAtStartup )
	{
		bIntoCrouch = true;
		PlayToStanding();
		FinishAnim( 2 );

		PlayBottomAnim( 'None' );
		bIntoCrouch = false;
		SetPostureState( PS_Standing );
		PlayToWaiting( 0.35 );
		Sleep( 0.15 );
	}
Begin:
	// // // // // log( Idling state begin label for "$self );
	// log( self$" Idling state 1 at "$level.timeseconds );
	if( GetPostureState() == PS_Crouching && !bKneelAtStartup )
	{
		Goto( 'StandUp' );
	}
//	bKneelAtStartup = false;
	Enable( 'SeePlayer' );

	// log( self$" Idling state 2 at "$level.timeseconds );
	if( HateTag != '' )
	{
		// // log( CALLING TRIGGERHATE for "$self );
		TriggerHate();
	}

	StopMoving();
	PlayToWaiting( 0.2 );
	Disable( 'SeeMonster' );
	// log( self$" Idling state 3 at "$level.timeseconds );
	if( InitialIdlingAnim != '' )
	{	
		PlayIdlingAnimation();
		if( !bReuseIdlingAnim )
			InitialIdlingAnim = '';
	}
	// // // // // log( Idling state begin label 2 for "$self );
	// log( self$" Idling state 4 at "$level.timeseconds );
	if( bFixedEnemy )
	{
		Sleep( 0.15 );
		bFixedEnemy = false;
		// // // // log( GOING TO ATTACKING 4 "$self );
				// log( "Going to Attacking 5b" );
		GotoState( 'Attacking' );
	}

	if( bStrafeRightOnSpawn || bStrafeLeftOnSpawn )
	{
		if( !bSteelSkin )
			PlaySound( Sound'dnAI.PigCop.RoamSound', SLOT_Talk, 5.0);;
		GotoState( 'DodgeSideStep' );
	}
	else if( bRollRightOnSpawn || bRollLeftOnSpawn )
	{
		// log( self$" Going to DodgeRoll state at "$Level.TimeSeconds );
	if( !bSteelSkin )
		PlaySound( Sound'dnAI.PigCop.RoamSound', SLOT_Talk, 5.0);

		GotoState( 'DodgeRoll' );
	}
	else if( !bPatrolled && !bRetreatAtStartup )
	{
		if( NPCOrders == ORDERS_Patrol )
		{
			// // // log( self$" Going to patrolling state" );
			GotoState( 'Patrolling' );
			bPatrolled = true;
		}
	}

IdleLoop:
	Sleep( 1.0 + Rand( 2 ) );
	if( FRand() < 0.75 )
	{
		PlaySound( Sound'dnAI.PigCop.WanderSound', SLOT_Talk, 5.0);
	}
	Sleep( 3.0 );
	Goto( 'IdleLoop' );
}

state Reacting
{
	ignores HearNoise, EnemyNotVisible;

Begin:
	Sleep( 0.5 );
	GotoState( 'Acquisition' );
}


state Acquisition
{
	ignores SeePlayer, SawEnemy, SeeMonster;

	function BeginState()
	{
		if( Enemy != None )
			HeadTrackingActor = Enemy;
		PlaySound(Sound'dnAI.PigCop.AcquisitionSound', SLOT_Talk, 5.0);
	}

	function Timer( optional int TimerNum )
	{
		// // // log( self$" ChooseAttackState from Acquisition Timer" );

		ChooseAttackState();
	}

Begin:
	StopMoving();
	TurnToward( Enemy );
	PlayToWaiting( 0.12 );
	Sleep( 0.12 );
	PlayWeaponIdle( 0.12 );
//	Sleep( PreAcquisitionDelay );

	if( MyCombatController != None )
	{
		log(" CALLING WARNFRIENDS" );
		MyCombatController.WarnFriends( self, Enemy );
	}

	if( bRetreatAtStartup )
		GotoState( 'Retreat' );

	if( bCoverOnAcquisition && MyCombatController == None )
		GotoState( 'NewCover' );

	if( AcquisitionSound != None )
		PlaySound( AcquisitionSound, SLOT_Talk,,,,,true );

	else
	{
		// // // log( self$" ChooseAttackState From Acquisition 2" );
		ChooseAttackState();
	}
	SetTimer( GetSoundDuration( AcquisitionSound )+ 0.25, false );

	if( AcquisitionTopAnim != 'None' )
		PlayTopAnim( AcquisitionTopAnim,, 0.1, false );

	if( AcquisitionBottomAnim != 'None' )
		PlayBottomAnim( AcquisitionBottomAnim,, 0.1, false );

	if( AcquisitionAllAnim != 'None' )
		PlayAllAnim( AcquisitionAllAnim,, 0.1, bLoopAcquisitionAnim );
}


state AttackShotgun
{

Begin:
	Weapon.bInterruptFire = true;
	Enable( 'AnimEnd' );
	RotationRate.Yaw = 80000;
	DesiredRotation = rotator( HeadTrackingActor.Location - Location );
	dnWeapon( Weapon ).FireAnim.AnimSeq = '';
	
Turning:
	if( GetPostureState() == PS_Crouching )
		Goto( 'AfterFire' );
	if( GetSequence( 1 ) == '' )
	{
		StopFiring();	
		PlayTopAnim( 'T_SGIdle',, 0.12, true );
		Sleep( 1.0 );
	}

	if( MustTurn() )
	{
		StopFiring();
		Sleep( 0.2 * FRand() );
		bIsTurning = true;
		Sleep( 0.1 );
		Goto( 'Begin' );
	}
	bReadyToAttack = true;
	if( GetSequence( 1 ) == '' )
	{
			// // // // log( "PLAY WEAPON IDLE 14" );
		PlayWeaponIdle();
		Sleep( 1.0 );
	}

DoneTurn:
	StopFiring();
	PlayBottomAnim( 'None' );
	PlayAllAnim( 'A_IdleStandActive',, 0.1, true );
	bIsTurning = false;
	Sleep( 0.5 );

Firing:
	if( !MustTurn() )
	{
		dnWeapon( Weapon ).FireAnim.AnimTween = 0.14;
			// // // // log( "PLAY WEAPON IDLE 15" );
		PlayWeaponIdle();
		PlayTopAnim( 'T_SGFire',, 0.1, false, false, false );
		PlayRangedAttack();
		//Weapon.ClientSideEffects( false );
	//	Weapon.AmmoLoaded -= 1;
	//	Sleep( 1.5 );
		// // // log( self$" Trying to Finish anim "$GetSequence( 1 ) );
		Sleep( 1.5 );
		// // // log( self$" Finished sequence." );
			// // // // log( "PLAY WEAPON IDLE 16" );
		PlayWeaponIdle();
		StopFiring();
	}
	if( Weapon.GottaReload() ) 
	{
		StopFiring();
		NextState = GetStateName();
		NextLabel = 'AfterFire';
log( self$" GOING TO RELOADING 3" );
		GotoState( 'Reloading' );
	}

AfterFire:
	// Handle crouching.
	if( !MustTurn( Enemy ) && FRand() < 0.2 && GetPostureState() != PS_Crouching && !bCrouchShiftingDisabled )
	{
		bCrouchShiftingDisabled = true;
		PlayToCrouch();
		FinishAnim( 2 );
		// log( self$" ==== PLAYING KNEEL IDLE 5" );
		PlayBottomAnim( 'B_KneelIdle',, 0.13, true );
	}
	// Handle standing back up if necessary, else continue fire loop.
	if( GetPostureState() == PS_Crouching )
	{
		if( !MustTurn( Enemy ) )
			Goto( 'Firing' );
		else 
		{
			bIntoCrouch = true;
			PlayToStanding();
			FinishAnim( 2 );
			PlayBottomAnim( 'None' );
			bIntoCrouch = false;
			SetPostureState( PS_Standing );
			PlayToWaiting( 0.35 );
			// // // // log( "PLAY WEAPON IDLE 17" );
			PlayWeaponIdle();
			SetCrouchDisabled();
			Sleep( 0.25 );
		}
	}

	// Handle random side-to-side dodging.
	else if( !MustTurn( Enemy ) && FRand() < 0.2 && VSize( Location - Enemy.Location ) > 356 )
	{
		HeadTrackingActor = None;
		Disable( 'AnimEnd' );
		bRotateToDesired = false;
		SetDodgeDestination();
		Sleep( 0.1 );
		StrafeTo( Destination, Enemy.Location, 0.5 );
		FinishAnim( 0 );
		StopMoving();
			// // // // log( "PLAY WEAPON IDLE 18" );
		PlayWeaponIdle();
		PlayToWaiting( 0.14 );
		Sleep( 0.12 );
		Enable( 'AnimEnd' );
		HeadTrackingActor = Enemy;
		bRotateToDesired = true;
		Sleep( 0.25 );
	}
	if( Weapon.GottaReload() ) 
	{
		StopFiring();
		NextState = GetStateName();
		NextLabel = 'AfterFire';
log( self$" GOING TO RELOADING 4" );
		GotoState( 'Reloading' );
	}
	if( FRand() < 0.23 && VSize( Location - Enemy.Location ) < 256 && GetPostureState() != PS_Crouching && CanRetreat() )
	{
		GotoState( 'Retreat' );
	}

	Goto( 'Begin' );
}




state MeleeCombat
{
	ignores Bump, SeePlayer;

	function PlayMeleeCombatPunch()
	{
		local float Decision;
		local float TweenTime;

		Decision = Rand( 3 );
		HeadTrackingActor = Enemy;

		if( Physics == PHYS_Swimming )
			TweenTime = 0.22;
		else
			TweenTime = 0.1;

		if( bShieldUser )
		{
			PlayTopAnim( 'None' );
			PlayAllAnim( 'A_ShieldBash',, TweenTime, false );
			return;
		}
		
		if( Physics != PHYS_Swimming )
		{
			if( Decision == 0 )
				PlayTopAnim( 'T_Punch1',, TweenTime, false );
			else if( Decision == 1 )
				PlayTopAnim( 'T_Punch2',, TweenTime, false );
			else if( Decision == 2 )
				PlayTopAnim( 'T_Punch4',, TweenTime, false );
			else 
				PlayTopAnim( 'T_Punch1',, TweenTime, false );
		}
		else
			PlayBottomAnim( 'B_SwimKickWade',, 0.22, true );
	}

	function PlayMeleeCombatKick()
	{
		PlayAllAnim( 'A_Kick_Front',, 0.2, false );
	}
	
	function AnimEndEx( int Channel )
	{}

	function bool EnemyWithinRange()
	{
		local float Dist;

		Dist = VSize( Location - Enemy.Location );

		if( Dist < 96 )
			return true;
		
		return false;
	}

Begin:
	TurnToward( Enemy );

Fighting:
	if( !bShieldUser )
		PlayFightIdle();

	//if( EnemyWithinRange() )
	//{	
		if( FRand() < 0.75 && !bArmless )
		{
			PlayMeleeCombatPunch();
			if( bShieldUser )
				FinishAnim( 0 );
			else
				FinishAnim( 1 );
		}
		else if( Physics != PHYS_Swimming )
		{
			PlayMeleeCombatKick();
			FinishAnim( 0 );
		}
		if( !bShieldUser )
		{
			PlayFightIdle();
		}
		Sleep( 0.2 );
		Goto( 'Begin' );
	//}
	//else
	//{
	//	StopMoving();
	//	PlayToWaiting( 0.12 );
	//	PlayWeaponIdle( 0.12 );
	//	Sleep( 0.12 );
	//	ChooseAttackState();	
//	}
}

state TakeHit 
{
	ignores seeplayer, hearnoise, bump, hitwall;

/*	function TakeDamage( int Damage, Pawn instigatedBy, Vector hitlocation, 
						Vector momentum, class<DamageType> DamageType)
	{
		if( bNPCInvulnerable )
			return;

		Super.TakeDamage(Damage, instigatedBy, hitlocation, momentum, damageType);
	}
*/
	
	function Landed(vector HitNormal)
	{
		if (Velocity.Z < -1.4 * JumpZ)
			MakeNoise(-0.5 * Velocity.Z/(FMax(JumpZ, 150.0)));
		bJustLanded = true;
	}

	function Timer( optional int TimerNum )
	{
		bReadyToAttack = true;
	}

	function BeginState()
	{
		//bCanTorsoTrack = false;
		if ( (NextState == 'TacticalTest') && (Region.Zone.ZoneGravity.Z > Region.Zone.Default.ZoneGravity.Z) )
			Destination = location;
		HeadTrackingActor = None;
	}
		
	function EndState()
	{
		//bCanTorsoTrack = true;
		if( TestFocus != None )
			TestFocus.Destroy();
		HeadTrackingActor = Enemy;
		if( FireController != None )
			FireController.Destroy();
		//	HeadTrackingActor = Enemy;
	}

Begin:
	// // // log( self$" TakeHit begin label for "$self );
	StopMoving();
	WaitForLanding();
	if( bRetreatAtStartup )
	{
		bRetreatAtStartup = false;
		bRotateToEnemy = false;
		SetAutoFireOff();
	}

	StopFiring();
	bIsTurning = false;

	PlaySound( Sound'dnAI.PigCop.PainSound', SLOT_Talk, 5.0);
	AimAdjust = 10000;

	if( NextState != 'Reloading' )
		NextState = 'Attacking';
	
	if( IsAnimating( 3 ) )
	{
		FinishAnim( 3 );
		PlaySpecialAnim( 'None' );
	}
	else
		FinishAnim( 0 );

	PlayToWaiting( 0.12 );
	StopMoving();

	if( ShotGun( Weapon ) != None )
	{
		PlayToWaiting( 0.22 );
			// // // // log( "PLAY WEAPON IDLE 19" );
		PlayWeaponIdle( 0.22 );
		Sleep( 0.25 + ( FRand() * 0.2 ) );
	}

	if( bArmless  )
		SwitchToWeapon( ChooseBestWeapon() );

	bAnimatePain = false;
	SetCallBackTimer( 3.5, false, 'EnablePainAnims' );

	AimAdjust = 0;
	//ChooseAttackState( 'Begin', true );
	ChooseAttackState();
}

defaultproperties
{
     EgoKillValue=8
     Mesh=DukeMesh'c_characters.PigCop'
     WeaponInfo(0)=(WeaponClass="dnGame.shotgun",PrimaryAmmoCount=500,altAmmoCount=50)
	 WeaponInfo(1)=(WeaponClass="")
	 WeaponInfo(2)=(WeaponClass="")
     Health=100
     BaseEyeHeight=27.000000
     EyeHeight=27.000000
     GroundSpeed=420.000000
     bIsHuman=True
     CollisionRadius=17.000000
     CollisionHeight=39.000000
	 bAggressiveToPlayer=true
	 bVisiblySnatched=false
	 
}
