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

UIFIELDS
{
FIELD<		 INT,attackRange,"Attack Range",500>;		// At what range do I start shooting?
FIELD<		 INT,withdrawRange,"Withdraw Range",750>;		// At what range do I withdraw from combat entirely?
FIELD< 		 INT,piloting,"Piloting Skill",50>;			// Piloting skill
FIELD< 		 INT,gunnery,"Gunnery Skill",50>;			// Gunnery skill/chance to hit
FIELD< 		 FLOAT,minDelay,"Minimum fire Delay",1.0>;			// Minimum amount of time I will wait between shots once a weapon is reloaded
FIELD< 		 FLOAT,maxDelay,"Maximum fire Delay",2.0>;			// Maximum amount of time I will wait between shots once a weapon is reloaded
FIELD< 		 INT,eliteLevel,"Elite Level",60>;			// Elite level.  This helps determine tactics, defensive manuevers, opportunity fire
													// and other things.  It indicates a general level of combat experience.
FIELD<  		 INT,isShotRadius,"Is Shot Radius",120>;		// How far away from me will I detect an enemy shot?		
FIELD<INT,	takeOffDistance,"Take Off Distance (ignored if not a plane)",160>;
FIELD<INT,	attackThrottle,"Percent throttle when in combat",80>;

FIELD< 		 INT,path,"First Path",-1>;				// My path
FIELD< 		 INT,path2,"Second Path",-1>;				// My path
FIELD< 		 INT,moveType,"Nocycle = 1, Circle = 2, Seesaw = 3",2>;			// How I move along the path
FIELD<INT, speed,"Movement Speed",600>;		

FIELD<		 INT,attackRange2,"Attack Range on second path",500>;		// At what range do I start shooting?
FIELD<		 INT,withdrawRange2,"Withdraw Range on second path",750>;		// At what range do I withdraw from combat entirely?
FIELD< 		 INT,moveType2,"(path 2) Nocycle = 1, Circle = 2, Seesaw = 3",2>;			// How I move along the path
FIELD<INT, trigger,"ID of trigger that makes the unit swap paths",1>;		
FIELD<INT, trigger,"ID of trigger that makes the unit wake up",1>;

}


fsm Generic_PatrolRespond : integer;


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

// Generic_PatrolRespond:
//   Follows a path.  If anything comes near, it goes off and attacks it,
//   and then comes back to the path when there's nothing left to attack.
//   When a specific trigger is set, it goes to another point or path
//   and does the same thing.

//   I.e. this is the same as Generic_Patrol, except that it
//   goes to a second point or path upon firing of a trigger.

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



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

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

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

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

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

	var
		static integer			attackRange1;		// The range at which I start attacking if in the original patrol
		static integer			withdrawRange1;		// The range at which I withdraw from combat entirely
		static integer			path1;				// My original path
		static integer			moveType1;			// How I move along the path
		static boolean			canLeavePath1;		// Can I leave the path if attacked? (TRUE by default)
		static integer			speed1;				// The speed at which I move along the path

		static integer			triggerID;			// The trigger that will move me from my original patrol state to my new patrol state

		static integer			attackRange2;		// The range at which I start attacking after the trigger has fired
		static integer			withdrawRange2;		// The range at which I withdraw from combat entirely
		static integer			path2;				// My path after the trigger fires
		static integer			moveType2;			// How I move along the second path
		static boolean			canLeavePath2;		// Can I leave the second path if attacked? (TRUE by default)
		static integer			speed2;				// The speed at which I move along the second path

		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
		
		// Variables set by editor
		attackRange1		= <attackRange>;
		withdrawRange1	= <withdrawRange>;
		takeOffDistance	= <takeOffDistance>;
 		piloting		= <piloting>;
		gunnery			= <gunnery>;
		minDelay		= <minDelay>;
		maxDelay		= <maxDelay>;
		eliteLevel		= <eliteLevel>;
		isShotRadius	= <isShotRadius>;
    attackThrottle	= <attackThrottle>;

		path1			= <path>;
		path2			= <path2>;
		moveType1		= <moveType>;
		speed1			= <speed>;
		
		attackRange2		= <attackRange>;
		withdrawRange2	= <withdrawRange>;
		moveType2		= <moveType>;
		speed2			= <speed>;
		triggerID		= <trigger>;
		
		// script-specific variables
		canLeavePath1	= true;

		canLeavePath2	= true;
		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 FollowPath1State;
		endif;

endstate;			

//------------------------------------------------------------------
//	FollowPath1State: follow the original path, but keep an eye out for enemies
//------------------------------------------------------------------

state FollowPath1State;
	code
		if (GetGlobalTrigger(triggerID)) then
			trans FollowPath2State;
		endif;

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

		if (path1 <> -1) then
			OrderMoveResumePatrol(path1,speed1,moveType1,true,false);
		else
			OrderMoveLookOut;
		endif;
endstate;

//------------------------------------------------------------------
//	Attack1State: attack my current target, or return to original path if done
//------------------------------------------------------------------

state Attack1State;
	code
		if (GetGlobalTrigger(triggerID)) then
			trans Attack2State;
		endif;

		if (LeaveAttackState(withdrawRange1)) then
			OrderStopAttacking;
			SetTarget(ME,NO_UNIT);
			trans FollowPath1State;
		endif;

		if (attackSound <> -1) then	
			PlaySoundOnce(attackSound);
		endif;

		OrderAttack(canLeavePath1);

endstate;

//------------------------------------------------------------------
//	FollowPath2State: follow the second path, but keep an eye out for enemies
//------------------------------------------------------------------

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

		if (path2 <> -1) then
			OrderMoveResumePatrol(path2,speed2,moveType2,true,false);
		else
			OrderMoveLookOut;
		endif;
endstate;

//------------------------------------------------------------------
//	Attack2State: attack my current target, or return to second path if done
//------------------------------------------------------------------

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

		if (attackSound <> -1) then	
			PlaySoundOnce(attackSound);
		endif;

		OrderAttack(canLeavePath2);

endstate;


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

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

		orderDie;

endstate;


endfsm.

