There is a file UniversalBrain.ABL under data/mission/warriors folder. I tried to make one universal brain that will make things easier for mission designers. Here is "how to" use it.
//****************************************************************************************//
//
// Universal Warrior Brain for Mech Commander Omnitech
//****************************************************************************************//
fsm UniversalBrain; //EACH BRAIN MUST HAVE AN UNIQUE FSM ID..- every brain file used in the same mission must have different fsm name
var
static WorldPosition startPosition;
static PatrolState PState;
static PatrolPath PPath;
static boolean willRequestHelp;
static real lastHelpRequestTime;
static real helpRequestFrequency;
static integer AttackStateHandle;
static boolean poweredDown;
static boolean powerUp;
//static boolean been_hit; //use this if powered down and you want to power up when hit.
//static boolean All_power; //use this if powered down and you want to power up all mates on this unit power-up.
static integer scanRange;
static WorldPosition MovePoint;
static integer escortSquadID;
static integer[20] moverList;
static real escortRange;
static boolean IsEscortUnitDead;
static worldPosition guardSpot;
static integer Orders1; //declare here for control in this file or declare in main mission.abl as eternal boolean for control from there.
//****************************************************************************************
function init;
code
//********************************************************************
// Scan Ranges for Unit
scanRange = 500;
//********************************************************************
// Patrol brain part - only need to change if you make a patrol brain or complex brain controlled from main mission.ABL
// Patrol STATE
PState[0] = 1; // This is the Type of Patrol. 0 = Linear. 1 = Looping
//(Linear = Unit will move from 1 to 2 to 3, then 3 to 2 to 1) Assuming there are only 3 points to the Patrol
//(Looping = Unit will move from 1 to 2 to 3, then 1 to 2 to 3) Assuming there are only 3 points to the Patrol
PState[1] = 7; //This is the Amount of Move Points there are listed below. Make sure you Count Patrol Point '0'
PState[2] = -1; //This is How many Times the unit will perform the Patrol.. (-1 = Forever).
// Patrol Points below
//Enter the Coordinates of where you want the Unit to Patrol. It will do them in Order Start from 0 and ending at the Last Point
//Make sure you change the Index number (numbers in Brackets [0, 0] to match the correct Patrol Point.
//Also, the number of Mover Points MUST match the number you have entered in the Patrol State.
PPath[0, 0] = -3178; //X coordinate found in the editor
PPath[0, 1] = -6208; //Y coordinate found in the editor
PPath[1, 0] = -4842;
PPath[1, 1] = -3520;
PPath[2, 0] = -5184;
PPath[2, 1] = -704;
PPath[3, 0] = -4416;
PPath[3, 1] = 1898;
PPath[4, 0] = -3050;
PPath[4, 1] = 2666;
PPath[5, 0] = -704;
PPath[5, 1] = -789;
PPath[6, 0] = 2112;
PPath[6, 1] = -2794;
PState[3] = PATROL_DIRECTION_FORWARD;
PState[4] = -1; //reset cur point
PState[5] = -1; //reset cur cycle
PState[6] = CONTACT_CRITERIA_ENEMY + CONTACT_CRITERIA_VISUAL_OR_SENSOR + CONTACT_CRITERIA_NOT_DISABLED;
//********************************************************************
// Escort brain part - only need to change if you make escort brain or complex brain controlled from main mission.ABL
// Unit ID to escort
escortSquadID = 2; //This is the Squad ID (Found in editor) for the unit you want to escort
escortRange = 250.0; //How far the escorting unit will drift
// Guard Location if escortee is dead
guardSpot[0] = -704; //The X Coordinate (Found in the editor) is the area this Unit will Guard if the Unit it is suppose to Escort is destroyed
guardSpot[1] = 4842; //The Y Coordinate (Found in the editor) is the area this Unit will Guard if the Unit it is suppose to Escort is destroyed
guardSpot[2] = 0;
IsEscortUnitDead = False;
getUnitMates(escortSquadID, moverList);
//********************************************************************
// Grab his start position...
getObjectPosition(-1, startPosition);
setTargetPriority(0, TARGET_PRIORITY_CURTARGET, -1, 150, CONTACT_CRITERIA_ENEMY + CONTACT_CRITERIA_VISUAL_OR_SENSOR + CONTACT_CRITERIA_NOT_DISABLED);
setTargetPriority(1, TARGET_PRIORITY_MOVER, 0, scanRange, CONTACT_CRITERIA_ENEMY + CONTACT_CRITERIA_VISUAL_OR_SENSOR + CONTACT_CRITERIA_NOT_DISABLED);
setTargetPriority(2, TARGET_PRIORITY_NONE, 0, 0, 0);
AttackStateHandle = getStateHandle("attack");
willRequestHelp = true; //?true or false
helpRequestFrequency = 20.0; //?in secs
lastHelpRequestTime = -100.0;
setWillHelp(True);
//********************************************************************
//use this if unit is powered down
poweredDown = False;
powerUp = True;
//been_hit = True;
//All_power = True;
//********************************************************************
//Use this if unit powered down and out of map
MovePoint[0] = -448;
MovePoint[1] = -7146;
MovePoint[2] = 0;
//********************************************************************
//Control variable use to set brain type - you can init here or init in main mission ABL and control/change from there
//If it is used from main mission ABL comment out declaration and init here. There could be more OrdersX variables (Orders1, Orders2)
//change Orders1 in this file accordingly.
Orders1 = 0; //0 - guard
//1 - attack object - guard
//2 - moveto position - guard
//3 - patrol
//4 - dredattack
//5 - sentry
//6 - escort
endfunction;
//----------------------------------------------------------------------------------------
function update : integer;
var
boolean processingPilotEvents;
integer pilotEventID;
integer pilotState;
integer[20] pilotEventParams;
integer curTarget;
real curTime;
real[3] myPos;
real[3] attackerPos;
integer curStateHandle;
static integer numFunctionalWeapons;
static integer[20] weaponList;
code
curTime = getTime;
curStateHandle = getCurrentStateHandle;
//--------------------------------------------------
// Process the pilot events since the last update...
numFunctionalWeapons = getWeapons(weaponList, 1);
if (numFunctionalWeapons == 0) then
trans noWeapons;
endif;
//--------------------------------------------------
// Check to see escorting Unit is dead
if (((objectStatus(moverList[0]) == 1) or (objectStatus(moverList[0]) == 2)) and (Not IsEscortUnitDead)) then
IsEscortUnitDead = True;
endif;
processingPilotEvents = TRUE;
while (processingPilotEvents) do
pilotEventID = getNextPilotEvent(pilotEventParams);
if (pilotEventID == PILOT_EVENT_NONE) then
processingPilotEvents = FALSE;
else
switch (pilotEventID)
case PILOT_EVENT_TARGETED:
curTarget = getTarget(-1);
if (lastHelpRequestTime < (curTime - helpRequestFrequency)) then
lastHelpRequestTime = curTime;
if (willRequestHelp) then
getObjectPosition(pilotEventParams[0], attackerPos);
getObjectPosition(-1, myPos);
requestHelp(pilotEventParams[0], myPos, 300.0, attackerPos, 300.0, 1);
endif;
endif;
numFunctionalWeapons = getWeapons(weaponList, 0);
if (curStateHandle <> AttackStateHandle) then
if ((numFunctionalWeapons > 0) and (curTarget == 0)) then
corerun = True;
magicAttack(pilotEventParams[0]);
setState(AttackStateHandle);
endif;
endif;
endcase;
case PILOT_EVENT_ATTACK_ORDER:
curTarget = getTarget(-1);
if (curStateHandle <> AttackStateHandle) then
if ((numFunctionalWeapons > 0) and (curTarget == 0))then
corerun = True;
magicAttack(pilotEventParams[0]);
setState(AttackStateHandle);
endif;
endif;
endcase;
case PILOT_EVENT_FIRED_WEAPON:
endcase;
case PILOT_EVENT_HIT:
if ((poweredDown) AND (powerUp)) then
corePower(True);
powerUp = False;
endif;
endcase;
endswitch;
endif;
endwhile;
return(0);
endfunction;
//----------------------------------------------------------------------------------------
state noWeapons;
code
if (objectClass(-1) == 2) then
coreEject;
else
corePower(false);
endif;
endstate;
//----------------------------------------------------------------------------------------
state attack;
code
update;
corerun = True;
magicAttack(0);
resetOrders(1);
transBack;
endstate;
//----------------------------------------------------------------------------------------
state start;
var
worldposition escortPos;
code
//Activate this if unit is powered down
// if (not poweredDown) then
// corePower(false);
// poweredDown = true;
// endif;
// if ((been_hit) AND (beenhit)) then //beenhit is a system variable that is set to True when hit by weapon fire
// corePower(True);
// been_hit = False; //close this loop forever unit is active
// All_powerup = True; //global variable defined in main mission.ABL used for global power-up other from beenhit - here used to send power-up signal for all mates
// All_power = False; //close the following loop forever unit is active
// endif;
// if ((All_power) AND (All_powerup)) then //this loop is used if you recive power-up signal from mates or global power-up (All_powerup=True)
// corePower(True);
// All_power = False; //close this loop forever unit is active
// been_hit = False; //close the previous loop forever unit is active
// endif;
switch (Orders1)
case 0:
corerun = True;
magicGuard(startposition, -1);
endcase;
case 1:
if ((getenemycount(-1) == 0)) then
if isalive(73402) then //73402 is building ID from the editor - target can be mover (you must use getUnitMates(SquadID, moverList);
magicAttack(73402); //magicAttack(moverList[0]);
endif;
else
corerun = True;
getObjectPosition(-1, startPosition);
magicGuard(startposition, -1);
endif;
endcase;
case 2:
if (distancetoposition(-1, MovePoint) > 150) then
corerun = True;
coreMoveTo(MovePoint, TACORDER_PARAM_RUN);
else
corerun = True;
getObjectPosition(-1, startPosition);
magicGuard(startposition, -1);
endif;
endcase;
case 3:
corerun = True;
magicPatrol(PState, PPath);
endcase;
case 4:
corerun = True;
getObjectPosition(-1, startPosition);
magicGuard(startposition, -1);
endcase;
case 5:
coreRun = True;
coreSentry(startposition, 300, -1);
endcase;
case 6:
if not IsEscortUnitDead then
getObjectPosition(moverList[0], escortPos);
corerun = True;
setMoveArea(escortPos, escortRange);
magicEscort(moverList[0]);
else
coreRun = True;
magicGuard(guardSpot, -1);
endif;
endcase;
endswitch;
update;
resetOrders(1);
endstate;
//----------------------------------------------------------------------------------------
endfsm.
In order to use this brain you must copy then change file name and change fsm ID (usually the same as file name).
Everything is controlled by Orders1 variable.
Orders1 = 0; //0 - guard
//1 - attack object - guard
//2 - moveto position - guard
//3 - patrol
//4 - dredattack
//5 - sentry
//6 - escort
It can be defined locally in this file or globally in main mission.ABL file.
If you only want one type of brain local declaration is enough you just need to change the line Orders1 = X.
Orders1 = 0)
no need to change anything it is simple guard brain
Orders1 = 1)
if you want your brain to attack building object you will need building ID from the editor:
if ((getenemycount(-1) == 0)) then
if isalive(73402) then //73402 is building ID from the editor
magicAttack(73402);
endif;
else
corerun = True;
getObjectPosition(-1, startPosition);
magicGuard(startposition, -1);
endif;
If you want to attack mover object (mech or vehicle) then:
(INIT section - get unit ID from squad ID from the editor - using already declared scortSquadID and moverList variables)
escortSquadID = X; //X is squad ID from the editor
getUnitMates(escortSquadID, moverList);
Then the code is:
if ((getenemycount(-1) == 0)) then
if isalive(moverList[0]) then
magicAttack(moverList[0]);
endif;
else
corerun = True;
getObjectPosition(-1, startPosition);
magicGuard(startposition, -1);
endif;
Orders1 = 2)
You must set MovePoint in INIT from the coordinates of the point you want your unit to move from the editor.
if (distancetoposition(-1, MovePoint) > 150)
corerun = True;
coreMoveTo(MovePoint, TACORDER_PARAM_RUN);
else
corerun = True;
getObjectPosition(-1, startPosition);
magicGuard(startposition, -1);
endif;
Orders1 = 3)
INIT section
You must set the number of patrol points you want and X, Y coordinates for every patrol point (from the editor).
Example below is for 5 patrol points.
PState[1] = 5; //This is the Amount of Move Points there are listed below. Make sure you Count Patrol Point '0'
PState[2] = -1; //This is How many Times the unit will perform the Patrol.. (-1 = Forever).
// Patrol Points below
PPath[0, 0] = -3178; //X coordinate found in the editor
PPath[0, 1] = -6208; //Y coordinate found in the editor
PPath[1, 0] = -4842;
PPath[1, 1] = -3520;
PPath[2, 0] = -5184;
PPath[2, 1] = -704;
PPath[3, 0] = -4416;
PPath[3, 1] = 1898;
PPath[4, 0] = -3050;
PPath[4, 1] = 2666;
Orders1 = 4)
Simple attack brain, you just need to set Orders1 to 4.
Orders1 = 5)
Simple sentry brain around 300 radius around startposition.
coreRun = True;
coreSentry(startposition, 300, -1);
You can set different coordinates for startposition.
Orders1 = 6)
You must set escortSquadID in init section:
escortSquadID = X; //X is squad ID from the editor
That is ALL if you want to use it as simple (one order) brain.
If you want to use it as complex brain you must declare Order1 in main mission.abl as eternal boolean variable.
There could be more then one definition of similar Orders variables in main mission ABL (Orders1, Orders2,..., OrdersX)
If you use exactly the same name (Orders1) you must comment out declaration and init of Orders1 in brain file.
Or simply use Order1, Order2,..., OrderX variables to avoid any possible conflict (no "s").
This way you can change orders for that unit by changing Orders1 variable here
switch (Orders1)
to OrderX.
How can you control OrderX variable from main mission.ABL file?
1) you must set OrderX to 0 or 1 or 2 or 3 or 4 or 5 or 6. Depends on what you want your unit to do first in INIT section of main mission.ABL file.
2) When some condition is met (objective completed, point reached, some unit dead, ...) you can change OrderX to another number and change the brain from e.g. guard (0) to escort (6). You MUST define every parameter for every role in brain file, in this case escortSquadID.
3) another condition is met (escorted unit has reached its destination) and you want your unit to guard again simply set OrderX to 0 again or maybe patrol (3 - you must have all parameter for patrol defined in brain file).
OR you can simply use multiple brain files using my new command:
setbrain(PartID, brainName);
PartID - number from the editor for buildings, part id for mover (obtained with getunitmates(squadID)) from squad ID.
brainName - the name of the brain file without extension.
DECLARATION section
static integer Commando;
static integer[2] moverList;
INIT section
getUnitMates(5, moverList);
Commando = moverList[0];
CODE section
if (LopCCC) then
if (checkObjectiveStatus(3) == 1) then //Objective3 completed
addmovertoplayer(Commando, 0, 2); //remove commando from player roster and add to allied team
setbrain(Commando, "p_guard"); //brain file name is p_guard.abl
LopCCC = False;
endif;
endif;
If you want your unit to be powered down at start you will have use this
//Activate this if unit is powered down
if (not poweredDown) then
corePower(false);
poweredDown = true;
endif;
//If you want your unit to power-up when hit by weapon fire you must activate the following loop
if ((been_hit) AND (beenhit)) then //beenhit is a system variable that is set to True when hit by weapon fire
corePower(True);
been_hit = False; //close this loop forever unit is active
All_powerup = True; //global variable defined in main mission.ABL used for global power-up other from beenhit - here used to send power-up signal for all mates
All_power = False; //close the following loop forever unit is active
endif;
//if you have defined global activation trigger (All_powerup) in main mission.ABL file activate this loop otherwise comment out All_powerup = True; in previous loop
if ((All_power) AND (All_powerup)) then //this loop is used if you recive power-up signal from mates or global power-up (All_powerup=True)
corePower(True);
All_power = False; //close this loop forever unit is active
been_hit = False; //close the previous loop forever unit is active
endif;
I know this is complicated but it is much better then using weird way of GOTO states from original MC2.
Good luck.