Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
268 lines
9.2 KiB
Smarty
268 lines
9.2 KiB
Smarty
|
|
//------------------------------------------------------------------
|
|
// 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.
|
|
|