
//------------------------------------------------------------------
// NOTE: The fsm name below MUST be changed in order for the
// script to be considered a unique entity!

fsm Generic_SentryAlly : integer;


//------------------------------------------------------------------

// Generic_SentryAlly:
//   Stands still.  Move to attack anything that comes within range.
//   Whenever we get within a certain range of a target unit,
//   we follow that unit, and continue to attack any enemies.

//------------------------------------------------------------------



//------------------------------------------------------------------
//     Constants
//------------------------------------------------------------------

	const
		#include_ <content\ABLScripts\mwconst.abi>

//------------------------------------------------------------------
//     Types
//------------------------------------------------------------------

	type
		#include_ <content\ABLScripts\mwtype.abi>
	

//------------------------------------------------------------------
//     Variables
//------------------------------------------------------------------

	var
		static integer			attackRange1;		// At what range do I start shooting?
		static integer			withdrawRange1;		// At what range do I withdraw from combat completely?

		static ObjectID			whoToJoin;			// Who do I want to join?
		static integer			joinRange;			// At what range do I join my leader?
		static integer			followXOffset;		// My follow X offset
		static integer			followYOffset;		// My follow Y offset

		static integer			attackRange2;		// At what range do I start shooting (after joining)?
		static integer			withdrawRange2;		// At what range do I stop shooting (after joining)?

		static integer			piloting;			// Piloting skill
		static integer			gunnery;			// Gunnery skill/chance to hit
		static real				minDelay;			// Minimum amount of time I will wait between shots once a weapon is reloaded
		static real				maxDelay;			// Maximum amount of time I will wait between shots once a weapon is reloaded
		static integer 			eliteLevel;			// Elite level.  This helps determine tactics, defensive manuevers, opportunity fire
													// and other things.  It indicates a general level of combat experience.
		static integer			attackThrottle;		// My attack throttle
		static integer			findTypes;			// What kind of enemies to look for

 		static integer			isShotRadius;		// How far away from me will I detect an enemy shot?

		static integer 			attackSound;		// The attack sound I play when I first attack
		static integer 			deathSound;			// The sound I play when I die
		
		static integer			mood;				// My default mood.

		static integer			takeOffDistance;	// My take-off distance if I'm an airplane (ignored if not an airplane)

//------------------------------------------------------------------
//     Init: my initialization function
//------------------------------------------------------------------

function Init;
	code
		// script-specific variables
		attackRange1	= 500;
		withdrawRange1	= attackRange1 * 3 / 2;

		whoToJoin		= NO_UNIT;
		joinRange		= 500;
		followXOffset	= 0;
		followYOffset	= 50;

		attackRange2	= attackRange1;
		withdrawRange2	= attackRange2 * 3 / 2;
 
		takeOffDistance	= 150; 

		// driver settings
		piloting		= 50;
		gunnery			= 30;
		minDelay		= 1.5;
		maxDelay		= 3.0;
		eliteLevel		= 30;
		attackThrottle	= 80;
		isShotRadius	= 120;
		attackSound		= -1; // no sound
		deathSound		= -1; // no sound
		mood			= NEUTRAL_START;
		findTypes		= FT_DEFAULT;

endfunction;

//------------------------------------------------------------------
//	StartState: my initial state
//------------------------------------------------------------------

state StartState;

	code
		SetFiringDelay			(ME,minDelay,maxDelay);
		SetIgnoreFriendlyFire	(ME,true);
		SetIsShotRadius			(ME,isShotRadius);
		SetEntropyMood			(ME,mood);
		SetCurMood				(ME,mood);
		SetSkillLevel			(ME,piloting,gunnery,eliteLevel);
		SetAttackThrottle		(ME,attackThrottle);

		if (orderTakeOff(takeOffDistance) == true) then
			trans Wait1State; 
		endif;

endstate;

//------------------------------------------------------------------
//	Wait1State: wait for something to shoot
//------------------------------------------------------------------

state Wait1State;
	code
		OrderMoveLookOut;

		if (IsWithin(ME,whoToJoin,joinRange)) then
			trans FollowState;
		endif;

		if (FindEnemy(attackRange1,findTypes)) then
			trans Attack1State;
		endif;		
endstate;

//------------------------------------------------------------------
//	Attack1State: look for something to shoot
//------------------------------------------------------------------

state Attack1State;
	code
		if (LeaveAttackState(withdrawRange1)) then
			OrderStopAttacking;
			SetTarget(ME,NO_UNIT);
			trans Wait1State;
		endif;

		if (IsWithin(ME,whoToJoin,joinRange)) then
			trans Attack2State;
		endif;

		OrderAttack(true);

endstate;

//------------------------------------------------------------------
//	FollowState: follow the chosen unit
//------------------------------------------------------------------

state FollowState;
	code
		if (FindEnemy(attackRange2,findTypes)) then
			trans Attack2State;
		endif;		

		OrderMoveFollow(whoToJoin,followXOffset,followYOffset);

endstate;

//------------------------------------------------------------------
//	Attack2State: look for something to shoot
//------------------------------------------------------------------

state Attack2State;
	code
		if (LeaveAttackState(withdrawRange2)) then
			OrderStopAttacking;
			SetTarget(ME,NO_UNIT);
			trans FollowState;
		endif;

		OrderAttack(true);

endstate;

//------------------------------------------------------------------
//	DeadState: OK, I kicked the bucket.
//------------------------------------------------------------------

state DeadState;
	code
		if (deathSound <> -1) then	
			PlaySoundOnce(deathSound);
		endif;		

		orderDie;

endstate;


endfsm.

