//------------------------------------------------------------------ // 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_ //------------------------------------------------------------------ // Types //------------------------------------------------------------------ type #include_ //------------------------------------------------------------------ // 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.