//=============================================================================
// TeamCannon.
//=============================================================================
class TeamCannon expands StationaryPawn;

var() sound FireSound;
var() sound ActivateSound;
var() sound DeActivateSound;
var float SampleTime; 			// How often we sample Instigator's location
var int   TrackingRate;			// How fast Cannon tracks Instigator
var float Drop;					// How far down to drop spawning of projectile
var() bool bLeadTarget;
var() Class<Projectile> ProjectileType;
var bool bShoot; 
var rotator StartingRotation;
var() int MyTeam;

function PreBeginPlay()
{
	bIsPlayer = true;
	Super.PreBeginPlay();
	bIsPlayer = false;  //was true so it would make it into DM
}

function ForceMeshToExist()
{
	Spawn(class'Cannon');
}

function TakeDamage( int NDamage, Pawn instigatedBy, Vector hitlocation, 
					Vector momentum, name damageType)
{
	MakeNoise(1.0);
	Health -= NDamage;
	if (Health <0) 
	{
		PlaySound(DeActivateSound, SLOT_None,5.0);
		NextState='Idle';
		Enemy = None;
		GotoState('DamagedState');
	}
	else if ( Enemy == None )
	{	
		Enemy = instigatedBy;
		GotoState('ActiveCannon');
	}
}

function Trigger( actor Other, pawn EventInstigator )
{
	GotoState('DeActivated');
}

function PlayDeactivate()
{
	PlaySound(ActivateSound, SLOT_None,5.0);
	TweenAnim('Activate', 1.5);
	SetPhysics(PHYS_Rotating);
	DesiredRotation = StartingRotation;
}

auto state Idle
{
	ignores EnemyNotVisible;

	function SeePlayer(Actor SeenPlayer)
	{
        if ( (Pawn(SeenPlayer).PlayerReplicationInfo.Team != MyTeam) || !Level.Game.bTeamGame )
		{
			Enemy = Pawn(SeenPlayer);
			GotoState('ActiveCannon');
		}
	}

	function BeginState()
	{
		Enemy = None;
	}

Begin:
	if ( AnimSequence == 'FAngle4' ) TweenAnim('Angle4', 0.25);
	else if ( AnimSequence == 'FAngle3' ) TweenAnim('Angle3', 0.25);
	else if ( AnimSequence == 'FAngle2' ) TweenAnim('Angle2', 0.25);
	else if ( AnimSequence == 'FAngle1' ) TweenAnim('Angle1', 0.25);
	else if ( AnimSequence == 'FAngle0' ) TweenAnim('Angle0', 0.25);		
	Sleep(5.0);
	PlayDeactivate();
	Sleep(2.0);
	SetPhysics(PHYS_None);
}

state DeActivated
{
	ignores SeePlayer, EnemyNotVisible, TakeDamage;

Begin:
	Health = -1; 
	Enemy = None;
	PlayDeactivate();
	Sleep(6.0);
	SetPhysics(PHYS_None);
}

state DamagedState
{
	ignores TakeDamage, SeePlayer, EnemyNotVisible;

Begin:
	Enemy = None;
	PlayDeactivate();
	Sleep(12.0);
	Health = Default.Health;
	GotoState(NextState);
}

state ActiveCannon
{
	ignores SeePlayer;

	function EnemyNotVisible()
	{
		local Pawn P;

		Enemy = None;
		for ( P=Level.PawnList; P!=None; P=P.NextPawn )
                        if ( ((P.PlayerReplicationInfo.Team != MyTeam) || !Level.Game.bTeamGame)
				&& (P.Health > 0) && !P.IsA('Spectator') && !P.IsA('TeamCannon')
				&& LineOfSightTo(P) )
			{
				Enemy = P;
				return;
			}
		GotoState('Idle');
	}
	
	function Killed(pawn Killer, pawn Other, name damageType)
	{
		if ( Other == Enemy )
			EnemyNotVisible();
	}

	function Timer()
	{
		local Pawn P;

		DesiredRotation = rotator(Enemy.Location - Location + Vect(0,0,1)*Drop);
		DesiredRotation.Yaw = DesiredRotation.Yaw & 65535;
		if ( bShoot && (DesiredRotation.Pitch < 1000)
			&& ((Abs(DesiredRotation.Yaw - (Rotation.Yaw & 65535)) < 1000)
			|| (Abs(DesiredRotation.Yaw - (Rotation.Yaw & 65535)) > 64535)) )
			Shoot();
		else 
		{
			if (DesiredRotation.Pitch < -6000 ) TweenAnim('Angle4', 0.25);
			else if (DesiredRotation.Pitch < -4000 ) TweenAnim('Angle3', 0.25);
			else if (DesiredRotation.Pitch < -2000 ) TweenAnim('Angle2', 0.25);
			else if (DesiredRotation.Pitch < -500 ) TweenAnim('Angle1', 0.25);
			else TweenAnim('Angle0', 0.25);		
			bShoot=True;			
		}

		P = Level.PawnList;
		while ( P != None )
		{
			if ( P.IsA('Bot') && (P.PlayerReplicationInfo.Team == MyTeam) && (Bot(P).Orders == 'FreeLance') )
				Bot(P).HandleHelpMessageFrom(self);
			P = P.nextPawn;
		}
		SetTimer(SampleTime,True);
	}
	
	function Shoot()
	{
		local Actor HitActor;
		local Vector HitLocation, HitNormal, FireSpot, ProjStart;
		if (DesiredRotation.Pitch < -10000) Return;
		PlaySound(FireSound, SLOT_None,5.0);
		if (DesiredRotation.Pitch < -6000 ) TweenAnim('FAngle4', 0.1);
		else if (DesiredRotation.Pitch < -4000 ) TweenAnim('FAngle3', 0.1);
		else if (DesiredRotation.Pitch < -2000 ) TweenAnim('FAngle2', 0.1);
		else if (DesiredRotation.Pitch < -500 ) TweenAnim('FAngle1', 0.1);
		else TweenAnim('FAngle0', 0.1);

		ProjStart = Location+Vector(DesiredRotation)*100 - Vect(0,0,1)*Drop;
		if ( bLeadTarget )
		{
			FireSpot = Target.Location + FMin(1, 0.7 + 0.6 * FRand()) * (Target.Velocity * VSize(Target.Location - ProjStart)/ProjectileType.Default.Speed);
			HitActor = Trace(HitLocation, HitNormal, FireSpot, ProjStart, false);
			if (HitActor != None)
				FireSpot = 0.5 * (FireSpot + Target.Location);
			DesiredRotation = Rotator(FireSpot - ProjStart);
		}
		Spawn (ProjectileType,,,ProjStart,DesiredRotation);
		bShoot=False;
		SetTimer(0.05,True);
	}

Begin:
	Disable('Timer');
	FinishAnim();
	TweenAnim('Angle0',0.5);
	PlaySound(ActivateSound, SLOT_None, 2.0);
	FinishAnim();
	Enable('Timer');
	SetTimer(SampleTime,True);
	RotationRate.Yaw = TrackingRate;
	SetPhysics(PHYS_Rotating);
	bShoot=True;

FaceEnemy:
	TurnToward(Enemy);
	Goto('FaceEnemy');
}

defaultproperties
{
     FovAngle=90
     SightRadius=2000
 	 ProjectileType=CannonShot
	 SampleTime=+00000.300000
     Drop=+00060.000000
     Health=+00150.000000
	 TrackingRate=40000
     FireSound=UnrealI.CannonShot
     ActivateSound=UnrealI.CannonActivate
     Mesh=UnrealI.CannonM
     CollisionRadius=+00044.000000
     CollisionHeight=+00044.000000
     bCollideWorld=True
     RotationRate=(Yaw=40000)
     bRotateToDesired=True
}
