//------------------------------------------------------------------ // 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; FIELD; 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; 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; FIELD; } 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_ //------------------------------------------------------------------ // Types //------------------------------------------------------------------ type #include_ //------------------------------------------------------------------ // 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 = ; withdrawRange1 = ; takeOffDistance = ; piloting = ; gunnery = ; minDelay = ; maxDelay = ; eliteLevel = ; isShotRadius = ; attackThrottle = ; path1 = ; path2 = ; moveType1 = ; speed1 = ; attackRange2 = ; withdrawRange2 = ; moveType2 = ; speed2 = ; triggerID = ; // 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.