Aom Ai Script Help File
Aom Ai Script Help File
Age of Mythology™
© 2002, Microsoft Corporation. All rights reserved.
Important: Age of Mythology allows you to create your own AI scripts. You may share
these custom AI scripts for the purposes of gameplay, but you may not sell or make other
commercial uses of the custom AI scripts. Microsoft® reserves all other rights to the
editors and files.
The AoM AI scripting system is a very powerful system that allows the user to craft the
AI using the same language as the folks at Ensemble Studios. While this is a useful
enduser feature, it is officially unsupported.
The high level overview for creating your own random map AI scripts is as follows:
· Write your random map script.
· Add an XML file into your AI directory following the format of default.xml,
defaultboom.xml, or defaultrush.xml.
· See your AI appear in the list of dropdown choices when you run the game.
· Debug it using the ingame debugging facilities:
o Add “aiDebug” to your user.cfg file in the startup directory.
o When the game is running, hit ALT+SHIFT+D to bring up the debugger.
For a scenario, the steps are largely the same, except that you need to associate the AI
script filename with the right player via the scenario editor (Player Data dialog).
A list of the type enumerations and function calls that can be made from the AI scripts is
included at the end of this document.
AoM includes a source debugger for your XS scripts. This is accessed by including a line
with “aiDebug” on it in the user.cfg in the Startup directory of your AoM installation. If
you do not have a user.cfg file, create one with any text editor. Once this is in your
user.cfg, hitting ALT+SHIFT+D will bring up the debugger. Different XS runtimes (AI
for each player, triggers, etc.) will be available for debugging. The debugger is an
unsupported feature.
You can also use the “aiEcho(…)” syscall (see the syscall reference at the end of this
document) to print out debugging strings, etc. during the execution of your AI. To see
these, you must put a “showAIEchoes” line in your user.cfg.
Sample AOM Scripts
The following script code is a sample script from one of the AoM single-player scenarios.
As such, it does not demonstrate everything that is possible with the AI scripting system,
but it does provide a working example. More examples (including all of the script code
for the Random Map AI for AoM) can be found in the “AI” subdirectory of your AoM
installation.
//==============================================================================
// Scn08p2: AI Scenario Script for scenario 8 player 2
//==============================================================================
/*
Overview:
The human player rescues Ajax from the Trojan army, then joins forces at the
allied TC. His goal is to build up and take out the red town to the north, without
the availability of siege units.
The CP sends one trivial attack early, which dies hopelessly to the HP's huge
army left over from the start. Several of the following attack rules are currently
implemented by triggers which attempt to build military buildings near
the HP's town.
The CP attacks down any one of three channels, with the west channel reserved for
higher difficulty levels.
No attempt is made to train units out of the forward buildings, even if the
feeble attempt to build succeeds. If the forward building concept stays in, we should
add rules to make a local army out of each building and use them for extra attacks.
*/
//==============================================================================
// Globals
int lastAttackPlanID = -1; // Updated with plan ID as each attack is launched
int defendPlan = -1;
int reservePlan = -1; // Extra defend plan, higher priority, for final resistance
int startTime = -1; // Updated with start time when cinematic is done.
// In seconds.
// Initial settings are for the easiest difficulty level, others are set in main().
int nextAttackTime = 480000; // 8 minutes
float attackSize = 4.0;
float maxAttackSize = 9.0;
float attackSizeMultiplier = 1.2;
int attackInterval = 300000; // 5 minutes
float reserveSize = 15.0; // Army to keep in reserve
int attackCount = 0;
int trainDelay = 30;
int cavTrainDelay = 30;
int archerTrainDelay = 15;
int infantryTrainDelay = 20;
// Econ
int maxVills = 20; // Will scale with difficulty
int maxFishBoats = 0; // Including one to scout
float goldPercent = 0.25;
float woodPercent = 0.15;
float foodPercent = 0.60;
int gathererTypeID = -1;
int fishGatherer = -1;
int mainBase = -1;
float mainRadius = 100.0;
// *****************************************************************************
//
// Building plan support for forward building
//
// *****************************************************************************
int buildPlan = -1;
int buildDefend = -1;
// Set the following four vars, then just enable testBuildPlan.
int buildUnit = cUnitTypeTower;
vector buildVec = cInvalidVector;
vector startPoint = cInvalidVector;
rule buildPlanRule
inactive
{
aiPlanSetActive(buildDefend);
aiEcho("Creating defend plan");
}
xsEnableRule("endBuildDefend");
xsDisableSelf();
}
rule endBuildDefend
inactive
minInterval 7
{
aiEcho("Build Plan state is "+aiPlanGetState(buildPlan));
if (aiPlanGetState(buildPlan) == -1)
{
aiPlanDestroy(buildDefend);
aiEcho("Destroying build defend plan");
xsDisableSelf();
}
}
// *****************************************************************************
//
// FUNCTIONS
//
// *****************************************************************************
xsEnableRule("attackGenerator");
xsEnableRule("scout");
hippikonMaintainPlan = maintainUnit(cUnitTypeHippikon, reserveSize/3,
kbGetBlockPosition(cbCavalryGather),
cavTrainDelay);
aiPlanSetActive(defendPlan);
aiEcho("Creating defend plan");
}
aiPlanSetActive(reservePlan);
aiEcho("Creating defend plan");
}
void initMainBase()
{
// Nuke bases, add one base to rule them all
kbBaseDestroyAll(cMyID);
int i = 0;
int buildingID = -1;
for (i=0; < count)
{
buildingID = kbUnitQueryGetResult(buildingQuery, i);
// Add it to the base
kbBaseAddUnit( cMyID, mainBase, buildingID );
}
}
void initEcon()
{
aiSetAutoGatherEscrowID(cRootEscrowID);
aiSetAutoFarmEscrowID(cRootEscrowID);
gathererTypeID = kbTechTreeGetUnitIDTypeByFunctionIndex(cUnitFunctionGatherer,0);
aiSetResourceGathererPercentageWeight(cRGPScript, 1);
aiSetResourceGathererPercentageWeight(cRGPCost, 0);
kbSetAICostWeight(cResourceFood, 1.0);
kbSetAICostWeight(cResourceWood, 0.7);
kbSetAICostWeight(cResourceGold, 0.8);
kbSetAICostWeight(cResourceFavor, 7.0);
void main()
{
aiEcho("Starting Scn08p2.xs");
kbSetTownLocation(kbGetBlockPosition(cbP2TC));
aiRandSetSeed();
initMainBase(); // Destroy all auto-bases, make one manual base for everything
initEcon();
aiSetAgeEventHandler(cAge2, "age2EventHandler");
aiSetAgeEventHandler(cAge3, "age3EventHandler");
aiSetAgeEventHandler(cAge4, "age4EventHandler");
switch(aiGetWorldDifficulty())
{ // ignores 0 (easiest), uses initial values in that case.
case 1: // medium
{
nextAttackTime = 300000; // 5 minutes
attackSize = 6.0;
maxAttackSize = 12.0;
attackSizeMultiplier = 1.2;
attackInterval = 240000; // 4 minutes
reserveSize = 20;
age3Time = 1200; // Time (in seconds) to go to age 3
age4Time = 1800;
defendQty = 2;
builderQty = 2;
trainDelay = 25;
break;
}
case 2: // difficult/hard
{
nextAttackTime = 180000; // 3 minutes
attackSize = 8.0;
maxAttackSize = 30.0;
attackSizeMultiplier = 1.2;
attackInterval = 180000; // 3 minutes
reserveSize = 35;
age3Time = 900; // Time (in seconds) to go to age 3
age4Time = 1500;
defendQty = 3;
builderQty = 5;
trainDelay = 15;
break;
}
case 3: // hardest/nightmare
{
nextAttackTime = 30000; // 30 sec
attackSize = 10.0;
maxAttackSize = 50.0;
attackSizeMultiplier = 1.3;
attackInterval = 108000; // 3 minutes
reserveSize = 60;
age3Time = 500; // Time (in seconds) to go to age 3
age4Time = 900;
defendQty = 6;
builderQty = 10;
trainDelay = 10;
break;
}
}
cavTrainDelay = trainDelay;
archerTrainDelay = trainDelay/2;
infantryTrainDelay = (2*trainDelay)/3;
}
void siegeUnitAttack(vector location=vector(-1,-1,-1), int qty=1)
{
static int attackQuery = -1;
static int attackQuery2 = -1;
int attackID=aiPlanCreate("Mixed Unit Attack at "+timeString(),cPlanAttack);
if (attackID < 0)
{
return;
}
if (attackQuery2 < 0)
{
attackQuery2 = kbUnitQueryCreate("Attack Query #2");
configQuery(attackQuery2, cUnitTypeBuilding, -1, cUnitStateAliveOrBuilding,
cPlayerRelationEnemy, location, false, 50);
}
else
{
kbUnitQuerySetPosition(attackQuery2, location);
}
aiPlanSetVariableInt(attackID, cAttackPlanQueryID, 0, attackQuery);
aiPlanSetVariableInt(attackID, cAttackPlanQueryID, 1, attackQuery2);
if (aiRandInt(2) == 0)
aiPlanSetVariableInt(attackID, cAttackPlanAttackRouteID, 0, routeNorthPass);
else
aiPlanSetVariableInt(attackID, cAttackPlanAttackRouteID, 0, routeEastPass);
aiPlanSetVariableVector(attackID, cAttackPlanGatherPoint,
0, kbGetBlockPosition(cbInfantryGather));
aiPlanSetVariableFloat(attackID, cAttackPlanGatherDistance, 0, 25.0);
// *****************************************************************************
//
// RULES
//
// *****************************************************************************
rule goToAge3
inactive
mininterval 20
{
if ( (xsGetTime()/1000) < age3Time )
return;
researchTech(cTechAge3Aphrodite);
xsEnableRule("goToAge4");
xsEnableRule("getAge3UnitUpgrades");
xsEnableRule("getAge3ArmoryUpgrades");
xsDisableSelf();
}
rule goToAge4
inactive
mininterval 20
{
return; // disabled for now.
rule getAge2UnitUpgrades
inactive
minInterval 20
{
if ( (xsGetTime()/1000) < (age3Time/3) )
return;
researchTech(cTechMediumInfantry);
researchTech(cTechMediumArchers);
// researchTech(cTechMediumCavalry);
xsDisableSelf();
}
rule getAge2ArmoryUpgrades
inactive
minInterval 20
{
if ( (xsGetTime()/1000) < (2*age3Time)/3 )
return;
aiEcho("Getting age 2 armory upgrades");
researchTech(cTechCopperWeapons);
researchTech(cTechCopperMail);
researchTech(cTechCopperShields);
xsDisableSelf();
}
rule getAge3UnitUpgrades
inactive
minInterval 20
{
researchTech(cTechHeavyInfantry);
researchTech(cTechHeavyArchers);
researchTech(cTechHeavyCavalry);
xsDisableSelf();
}
rule getAge3ArmoryUpgrades
inactive
minInterval 20
{
researchTech(cTechBronzeWeapons);
researchTech(cTechBronzeMail);
researchTech(cTechBronzeShields);
xsDisableSelf();
}
rule getAge4UnitUpgrades
inactive
minInterval 20
{
researchTech(cTechChampionInfantry);
researchTech(cTechChampionArchers);
researchTech(cTechChampionCavalry);
xsDisableSelf();
}
rule getAge4ArmoryUpgrades
inactive
minInterval 20
{
researchTech(cTechIronWeapons);
researchTech(cTechIronMail);
researchTech(cTechIronShields);
xsDisableSelf();
}
rule scout
inactive
{
// just set up an explore plan
int exploreID = aiPlanCreate("Explore", cPlanExplore);
if(exploreID >= 0)
{
aiPlanSetVariableFloat( exploreID, cExplorePlanLOSMultiplier, 0, 4.0 );
aiPlanAddUnitType(exploreID, cUnitTypeHippikon, 1, 1, 1);
aiPlanSetInitialPosition( exploreID, kbGetBlockPosition(cbNorthWestPlateau));
aiPlanSetActive(exploreID);
}
xsDisableSelf();
}
rule attackGenerator
minInterval 10
inactive
{
static int buildingQuery = -1;
if (buildingQuery < 0)
{
buildingQuery = kbUnitQueryCreate("Building Query");
configQuery(buildingQuery, cUnitTypeBuilding, -1, cUnitStateAliveOrBuilding,
1, kbGetBlockPosition(cbAttack5Tower), false, 20);
}
attackCount = attackCount + 1;
rule useCurse
minInterval 5
inactive
{
if ( targetCount < 6 )
{
vector pVec = aiPlanGetLocation(lastAttackPlanID);
if (xsVectorGetX(pVec)>=0)
{
static int tempQuery2 = -1;
if (tempQuery2 < 0)
{ // Doesn't exist, set it up
tempQuery2 = kbUnitQueryCreate("useCurseArmy");
if ( configQuery(tempQuery2, cUnitTypeUnit, -1, cUnitStateAlive,
1, pVec, true, 50) == false)
return;
}
else // Because pVec changes as army moves
kbUnitQuerySetPosition(tempQuery2, pVec);
kbUnitQueryResetResults(tempQuery2);
targetCount = kbUnitQueryExecute(tempQuery2);
if (targetCount < 6)
return;
else// grab middle unit
targetUnit = kbUnitQueryGetResult(tempQuery2, targetCount/2);
}
else
return;
}
else
targetUnit = kbUnitQueryGetResult(tempQuery, targetCount/2); // grab middle unit
rule usePestilence
minInterval 5
inactive
{
// look for a group of 2 enemy buildings near my army.
if (lastAttackPlanID < 0)
return;
if ( configQuery(tempQuery, cUnitTypeLogicalTypeBuildingsThatTrainMilitary,
-1, cUnitStateAlive, 1, pVec, true, 50) == false)
return;
}
else
kbUnitQuerySetPosition(tempQuery, pVec); // Because pVec changes as army moves
kbUnitQueryResetResults(tempQuery);
int targetCount = kbUnitQueryExecute(tempQuery);
if (targetCount < 2)
return;
rule usePlenty
minInterval 5
inactive
{
vector aimHere = kbGetBlockPosition(cbP2TC);
float dx = aiRandInt(40)-20.0;
float dz = aiRandInt(40)-20.0;
float newX = xsVectorGetX(kbGetBlockPosition(cbP2TC));
float newZ = xsVectorGetZ(kbGetBlockPosition(cbP2TC));
newX = newX + dx;
newZ = newZ + dz;
//==============================================================================
// Failure
// To be called in the event of an error. Breaks the script, preserves
// the current call stack, etc.
//==============================================================================
void failure( string msg="" )
{
aiEcho("Failure: " + msg);
}
// *****************************************************************************
//
// configQuery
//
// Sets up all the non-default parameters so you can config a query on a single call.
// Query must be created prior to calling, and the results reset and the query executed
// after the call.
//
// *****************************************************************************
bool configQuery( int queryID = -1, int unitType = -1, int action = -1, int state = -1,
int player = -1, vector center = vector(-1,-1,-1), bool sort = false, float radius = -1 )
{
if ( queryID == -1)
{
failure("Invalid query ID");
return(false);
}
if (player != -1)
kbUnitQuerySetPlayerID(queryID, player);
if (unitType != -1)
kbUnitQuerySetUnitType(queryID, unitType);
if (action != -1)
kbUnitQuerySetActionType(queryID, action);
if (state != -1)
kbUnitQuerySetState(queryID, state);
if (center != vector(-1,-1,-1))
{
kbUnitQuerySetPosition(queryID, center);
if (sort == true)
kbUnitQuerySetAscendingSort(queryID, true);
if (radius != -1)
kbUnitQuerySetMaximumDistance(queryID, radius);
}
return(true);
}
// *****************************************************************************
//
// configQueryRelation
//
// Sets up all the non-default parameters so you can config a query on a single call.
// Query must be created prior to calling, and the results reset and the query executed
// after the call.
// Unlike configQuery(), this uses the PLAYER RELATION rather than the player number
//
// *****************************************************************************
bool configQueryRelation( int queryID = -1, int unitType = -1, int action = -1,
int state = -1, int playerRelation = -1,
vector center = vector(-1,-1,-1), bool sort = false,
float radius = -1 )
{
if ( queryID == -1)
{
failure("Invalid query ID");
return(false);
}
if (playerRelation != -1)
kbUnitQuerySetPlayerRelation(queryID, playerRelation);
if (unitType != -1)
kbUnitQuerySetUnitType(queryID, unitType);
if (action != -1)
kbUnitQuerySetActionType(queryID, action);
if (state != -1)
kbUnitQuerySetState(queryID, state);
if (center != vector(-1,-1,-1))
{
kbUnitQuerySetPosition(queryID, center);
if (sort == true)
kbUnitQuerySetAscendingSort(queryID, true);
if (radius != -1)
kbUnitQuerySetMaximumDistance(queryID, radius);
}
return(true);
}
//==============================================================================
// getUnit( int unitType, int action, vector center)
//
// Returns a unit of the specified type, doing the specified action.
// Defaults = any unit, any action.
// Searches units owned by this player only, can include buildings.
// If a location is specified, the nearest matching unit is returned.
//==============================================================================
int getUnit( int unitType = -1, int action = -1, vector center = vector(-1,-1,-1) )
{
kbUnitQueryResetResults(unitQueryID);
count = kbUnitQueryExecute(unitQueryID);
// Add buildings in process
kbUnitQuerySetState(unitQueryID, cUnitStateBuilding);
count = kbUnitQueryExecute(unitQueryID);
return(retVal);
}
// *****************************************************************************
//
// trainUnit
//
// Train qty units of type unitID, optionally gathering at gatherPoint and
// training at a minimum of interval seconds apart. Returns the planID, or -1
// on failure.
// *****************************************************************************
int trainUnit( int unitID=-1, int qty=1, vector gatherPoint=vector(-1,-1,-1), int
interval=-1)
{
if (unitID == -1)
return(-1);
if (qty < 1)
return(-1);
int planID = aiPlanCreate("Train "+qty+" "+kbGetProtoUnitName(unitID), cPlanTrain);
if (planID >= 0)
{
aiPlanSetVariableInt(planID, cTrainPlanUnitType, 0, unitID);
aiPlanSetVariableInt(planID, cTrainPlanNumberToTrain, 0, qty);
if (interval > 0)
aiPlanSetVariableInt(planID, cTrainPlanFrequency, 0, interval);
if (xsVectorGetX(gatherPoint) >= 0)
aiPlanSetVariableVector(planID, cTrainPlanGatherPoint, 0, gatherPoint);
aiPlanSetActive(planID);
return(planID);
}
else
return(-1);
}
// *****************************************************************************
//
// maintainUnit
//
// Maintain a total of qty units of type unitID, optionally gathering at gatherPoint and
// training at a minimum of interval seconds apart. Returns the planID, or -1
// on failure.
// *****************************************************************************
int maintainUnit( int unitID=-1, int qty=1, vector gatherPoint=vector(-1,-1,-1), int
interval=-1)
{
if (unitID == -1)
return(-1);
if (qty < 1)
return(-1);
int planID = aiPlanCreate("Maintain "+qty+" "+kbGetProtoUnitName(unitID), cPlanTrain);
if (planID >= 0)
{
aiPlanSetVariableInt(planID, cTrainPlanUnitType, 0, unitID);
aiPlanSetVariableInt(planID, cTrainPlanNumberToMaintain, 0, qty);
if (interval > 0)
aiPlanSetVariableInt(planID, cTrainPlanFrequency, 0, interval);
if (xsVectorGetX(gatherPoint) >= 0)
aiPlanSetVariableVector(planID, cTrainPlanGatherPoint, 0, gatherPoint);
aiPlanSetActive(planID);
return(planID);
}
else
return(-1);
}
// *****************************************************************************
//
// researchTech
//
// Creates a research plan to research the tech at an appropriate building
//
// *****************************************************************************
int researchTech(int techID=-1)
{
int planID = aiPlanCreate("Research "+kbGetTechName(techID), cPlanProgression);
if(planID < 0)
return(-1);
// *****************************************************************************
//
// attackRoute()
//
// Makes an attack route from a series of block names. Must have 2-5 block names.
//
// *****************************************************************************
int attackRoute(string name="default attack route", string block1="", string block2="",
string block3="", string block4="", string block5="")
{
string end="";
int numPoints=0;
if (numPoints < 2)
return(-1);
if (numPoints > 2)
kbPathAddWaypoint(pathID, kbGetBlockPosition(block2));
if (numPoints > 3)
kbPathAddWaypoint(pathID, kbGetBlockPosition(block3));
if (numPoints > 4)
kbPathAddWaypoint(pathID, kbGetBlockPosition(block4));
return(attackRouteID);
}
// *****************************************************************************
//
// int getUnassignedUnitCount(vector center, float radius, int player, int unitType)
//
// Counts the number of player's units of type unitType that don't belong to
// a plan. Count is limited to a distance of radius around point center.
//
// Generally used to count newly spawned units in order to set appropriate want/max
// levels for an attack plan.
// *****************************************************************************
// *****************************************************************************
//
// string timeString(bool trimmed=true)
//
// Returns the current time in h:mm:ss format. If trimmed is true, it suppresses
// leading spaces or zeros. If false, string is always 7 characters.
// Not responible for games over 10 hours. ;-)
//
// *****************************************************************************
string timeString(bool trimmed=true)
{
int hour = 0;
int min = 0;
int sec = 0;
int time = 0;
string retval = "";
if (trimmed == true)
{
// start with h:
if (hour > 0) {
retval = hour+":";
if (min >= 10)
retval = retval+min+":";
else
retval = retval+0+min+":";
if (sec >=10)
retval = retval+sec;
else
retval = retval+0+sec;
}
else
{ // start with min
retval = min+":";
if (sec >=10)
retval = retval+sec;
else
retval = retval+0+sec;
}
}
else // non-trimmed
{
retval = hour+":";
if (min >= 10)
retval = retval+min+":";
else
retval = retval+0+min+":";
if (sec >=10)
retval = retval+sec;
else
retval = retval+0+sec;
}
return(retval);
}
/*
// *****************************************************************************
//
// build(int BuildingID, int areaID)
//
// *****************************************************************************
// *****************************************************************************
//
// echoQuery(int queryID)
//
// aiEchos the list of items in the query result space, with ID numbers and unit types.
//
// *****************************************************************************
void echoQuery(int queryID = -1)
{
if (queryID < 0)
{
aiEcho("Invalid query");
return;
}
int i = 0;
int id = 0;
for (i=0; < kbUnitQueryNumberResults(queryID))
{
id = kbUnitQueryGetResult(queryID, i);
aiEcho(" "+id+" ("+kbGetProtoUnitName(kbGetUnitBaseTypeID(id))+")");
}
//==============================================================================
//createSimpleMaintainPlan: DCP
//==============================================================================
bool createSimpleMaintainPlan(int puid=-1, int number=1, bool economy=true,
int baseID=-1)
{
//Create a the plan name.
string planName="Military";
if (economy == true)
planName="Economy";
// e.g. "Economy maintain 17 villager "
planName=planName+" maintain "+number+" "+kbGetProtoUnitName(puid)+" ";
int planID=aiPlanCreate(planName, cPlanTrain);
if (planID < 0)
return(false);
//Economy or Military.
if (economy == true)
aiPlanSetEconomy(planID, true);
else
aiPlanSetMilitary(planID, true);
//Unit type.
aiPlanSetVariableInt(planID, cTrainPlanUnitType, 0, puid);
//Number.
aiPlanSetVariableInt(planID, cTrainPlanNumberToMaintain, 0, number);
aiPlanSetActive(planID);
//Done.
return(true);
}
List of AOM type enumerations and function calls
These are provided as a reference. All of the const variable definitions are provided by
the game and automatically included in your script (see the RM AI scripts in the AI
directory for a working example). There are some game-dependent items, such as
cNumberPlayers, that will change based on how many players are in the game, etc.
//Player/Game:
const vector cInvalidVector=vector(-1.0, -1.0, -1.0);
const vector cOriginVector=vector(0.0, 0.0, 0.0);
const int cNumberPlayers=13;
const string cFilename="YourAIFilenameHere";
const int cMyID=12;
const string cMyName="RandomCPNameHere";
const int cMyCulture=2;
const int cMyCiv=7;
const string cRandomMapName="RandomMapNameHere";
//Unit Stances:
const int cUnitStanceAggressive=0;
const int cUnitStanceDefensive=1;
const int cUnitStancePassive=2;
//Difficulty Levels:
const int cDifficultyEasy=0;
const int cDifficultyModerate=1;
const int cDifficultyHard=2;
const int cDifficultyNightmare=3;
//Age Constants:
const int cAge1=0;
const int cAge2=1;
const int cAge3=2;
const int cAge4=3;
//Resource Subtypes:
const int cAIResourceSubTypeEasy=0;
const int cAIResourceSubTypeHunt=1;
const int cAIResourceSubTypeHuntAggressive=2;
const int cAIResourceSubTypeFarm=3;
const int cAIResourceSubTypeFish=4;
const int cAIResourceSubTypeTrade=5;
//Escrow IDs:
const int cRootEscrowID=0;
const int cEconomyEscrowID=1;
const int cMilitaryEscrowID=2;
//Plan Types:
const int cPlanMove=0;
const int cPlanAttack=1;
const int cPlanBuild=2;
const int cPlanTrain=3;
const int cPlanResearch=4;
const int cPlanWork=5;
const int cPlanGather=6;
const int cPlanExplore=7;
const int cPlanData=8;
const int cPlanProgression=9;
const int cPlanBuildWall=10;
const int cPlanFarm=11;
const int cPlanHunt=12;
const int cPlanHuntAggressive=13;
const int cPlanFish=14;
const int cPlanHerd=15;
const int cPlanEmpower=16;
const int cPlanTransport=17;
const int cPlanDropoffResource=18;
const int cPlanGatherRelic=19;
const int cPlanAttackStrategy=20;
const int cPlanGodPower=21;
const int cPlanDefend=22;
const int cPlanReserve=23;
const int cPlanGoal=24;
const int cPlanTower=25;
const int cPlanGatherGoal=26;
const int cPlanRepair=27;
const int cPlanTrade=28;
//Plan States:
const int cPlanStateNone=0;
const int cPlanStateDone=1;
const int cPlanStateFailed=2;
const int cPlanStateBuild=3;
const int cPlanStateGather=4;
const int cPlanStatePlace=5;
const int cPlanStateExplore=6;
const int cPlanStateTrain=7;
const int cPlanStateResearch=8;
const int cPlanStateAttack=9;
const int cPlanStateGoto=10;
const int cPlanStateEmpower=11;
const int cPlanStateEnter=12;
const int cPlanStateExit=13;
const int cPlanStateEvaluate=14;
const int cPlanStatePatrol=15;
const int cPlanStateRetreat=16;
const int cPlanStateWorking=17;
const int cPlanStateTransport=18;
const int cPlanStateDualPlace=19;
const int cPlanStateWait=20;
const int cPlanStateCast=21;
//Plan Events:
const int cPlanEventDone=0;
const int cPlanEventFailed=1;
const int cPlanEventPoll=2;
const int cPlanEventIdle=3;
//ProtoPower Constants:
const int cPowerLure=0;
const int cPowerBlessingofZeus=1;
const int cPowerBolt=2;
const int cPowerbramble=3;
const int cPowerBronze=4;
const int cPowerCeaseFireNomad=5;
const int cPowerCeaseFire=6;
const int cPowerCitadel=7;
const int cPowerDwarvenMine=8;
const int cPowerCurse=9;
const int cPowerEarthquake=10;
const int cPowerEclipse=11;
const int cPowerEnrage=12;
const int cPowerFlamingWeapons=13;
const int cPowerForestFire=14;
const int cPowerFrost=15;
const int cPowerGreatHunt=16;
const int cPowerHealingSpring=17;
const int cPowerInferno=18;
const int cPowerLightningStorm=19;
const int cPowerLocustSwarm=20;
const int cPowerMeteor=21;
const int cPowerNidhogg=22;
const int cPowerOmniscience=23;
const int cPowerOracle=24;
const int cPowerPestilence=25;
const int cPowerPlenty=26;
const int cPowerProsperity=27;
const int cPowerRagnorok=28;
const int cPowerRain=29;
const int cPowerRebellion=30;
const int cPowerRestoration=31;
const int cPowerShiftingSands=32;
const int cPowerSentinel=33;
const int cPowerPlagueofSerpents=34;
const int cPowershepherd=35;
const int cPowersight=36;
const int cPowerAncestors=37;
const int cPowerFimbulwinter=38;
const int cPowerSonofOsiris=39;
const int cPowerSPCMeteor=40;
const int cPowerSpy=41;
const int cPowerTornado=42;
const int cPowerUndermine=43;
const int cPowerUnderworldPassage=44;
const int cPowerVision=45;
const int cPowerWalkingWoods=46;
const int cPowerWellOfUrd=47;
const int cPowerwild=48;
//Transport PathTypes:
const int cTransportPathTypePoints=0;
const int cTransportPathTypeAreas=1;
//Resign Types:
const int cResignGatherers=0;
const int cResignSettlements=1;
const int cResignTeammates=2;
const int cResignMilitaryPop=3;
//Civs:
const int cCivZeus=0;
const int cCivPoseidon=1;
const int cCivHades=2;
const int cCivIsis=3;
const int cCivRa=4;
const int cCivSet=5;
const int cCivOdin=6;
const int cCivThor=7;
const int cCivLoki=8;
const int cCivRandom=9;
const int cCivGreek=10;
const int cCivNorse=11;
const int cCivEgyptian=12;
const int cCivNature=13;
//Cultures:
const int cCultureGreek=0;
const int cCultureEgyptian=1;
const int cCultureNorse=2;
const int cCultureNature=3;
//Resources:
const int cResourceGold=0;
const int cResourceWood=1;
const int cResourceFood=2;
const int cResourceFavor=3;
const int cAllResources=-1234;
//Unit Action Constants:
const int cActionBored=0;
const int cActionBuild=1;
const int cActionConvert=2;
const int cActionDeath=3;
const int cActionDecay=4;
const int cActionGather=5;
const int cActionHandAttack=6;
const int cActionHeal=7;
const int cActionHunting=8;
const int cActionIdle=9;
const int cActionMove=10;
const int cActionMoveByGroup=11;
const int cActionRangedAttack=12;
const int cActionRepair=13;
const int cActionResearch=14;
const int cActionTrain=15;
const int cActionOverrideAnimation=16;
const int cActionWork=17;
const int cActionAttack=18;
const int cActionUnused0=19;
const int cActionWander=20;
const int cActionEnter=21;
const int cActionAutoConvert=22;
const int cActionBirth=23;
const int cActionAreaAttack=24;
const int cActionFreeze=25;
const int cActionDormant=26;
const int cActionGatherPoint=27;
const int cActionMoveAttack=28;
const int cActionThrown=29;
const int cActionLightning=30;
const int cActionLight=31;
const int cActionJumpAttack=32;
const int cActionUnused1=33;
const int cActionMeteor=34;
const int cActionAttach=35;
const int cActionGuide=36;
const int cActionJumpMove=37;
const int cActionPickup=38;
const int cActionDiveBomb=39;
const int cActionUnused2=40;
const int cActionRegenerate=41;
const int cActionUse=42;
const int cActionEmpower=43;
const int cActionAutoGather=44;
const int cActionThrow=45;
const int cActionGore=46;
const int cActionDropoff=47;
const int cActionWhirlwindAttack=48;
const int cActionChargedRangedAttack=49;
const int cActionEject=50;
const int cActionFreezeAttack=51;
const int cActionConvertAttack=52;
const int cActionTrade=53;
const int cActionGuard=54;
const int cActionAutoMover=55;
const int cActionGetOnMover=56;
const int cActionSwallow=57;
const int cActionGate=58;
const int cActionLightningAttack=59;
const int cActionExplore=60;
const int cActionEat=61;
const int cActionBoost=62;
const int cActionCorpseDecay=63;
const int cActionTeleport=64;
const int cActionBuckAttack=65;
const int cActionTownBell=66;
const int cActionHeroDeath=67;
const int cActionHeroDeath=67;
//Tech Status:
const int cTechStatusUnobtainable=0;
const int cTechStatusObtainable=1;
const int cTechStatusAvailable=2;
const int cTechStatusResearching=3;
const int cTechStatusActive=4;
const int cTechStatusPersistent=5;
//Attack Routes:
const int cAttackRouteFrontRight=0;
const int cAttackRouteRightFront=1;
const int cAttackRouteRightBack=2;
const int cAttackRouteBackRight=3;
const int cAttackRouteBackLeft=4;
const int cAttackRouteLeftBack=5;
const int cAttackRouteLeftFront=6;
const int cAttackRouteFrontLeft=7;
//Area Types:
const int cAreaTypeForest=1;
const int cAreaTypeWater=2;
const int cAreaTypeImpassableLand=3;
const int cAreaTypeGold=4;
const int cAreaTypeSettlement=5;
//AreaGroup Types:
const int cAreaGroupTypeLand=0;
const int cAreaGroupTypeWater=1;
//Wall Types:
const int cWallTypeStraight=0;
const int cWallTypeRing=1;
const int cWallTypeArea=2;
//Communications Constants:
//Response Types:
const int cAICommResponseNoneRequired=0;
const int cAICommResponseWaiting=1;
const int cAICommResponseYes=2;
const int cAICommResponseNo=3;
const int cAICommResponseIncomingOrder=4;
int aiGoalGetIDByIndex( int goalType, int goalState, bool active, int index )
Returns the ID of matching goal.
int aiPlanGetNumber( int planType, int planState, bool active )
Returns the number of matching plans.
int aiPlanGetIDByIndex( int planType, int planState, bool active, int index )
Returns the ID of matching plan.
int aiPlanGetIDByTypeAndVariableType( int planType, int varType, int varID, bool active )
Returns the ID of the plan with the given parms.
bool aiPlanSetVariableInt( int planID, int planVariableIndex, int valueIndex, int value )
Sets the given variable of the given plan.
int aiWallInArea( string name, int areaID, int numberNeed, int nubmerWant, int numberMax,
int escrowID, int numGates, int planPriority )
walls in the given area.
int aiWallInAreas( string name, int areaID1, int areaID2, int areaID3, int numberNeed,
int nubmerWant, int numberMax, int escrowID, int numGates,
int planPriority )
walls around all 3 areas at once.
int aiWallFromAToB( string name, vector a, vector b, int numberNeed, int nubmerWant,
int numberMax, int escrowID, int numGates, int planPriority )
walls from point a to point b.
int aiWallRingAroundPoint( string name, vector center, float radius, int numberNeed,
int nubmerWant, int numberMax, int escrowID, int numGates, int
planPriority )
walls a ring around the center, with a given radius.
int aiUnitCreateCheat( int playerID, int protoUnitID, vector position, string name,
int numberUnits )
Creates unit(s) with the given parms.
int aiFindBestAttackGodPowerPlan(void)
find a valid god power plan to attach to an attack plan
bool aiGetAutosaveOn()
returns whether or not its cool to turn ai autosaves on.
float aiGetExploreDangerThreshold()
gets the ai's Explore Danger Threshold value.
void aiSetPauseAllAgeUpgrades(bool v)
sets the pause all age upgrades flag in the AI.
bool aiGetPauseAllAgeUpgrades()
gets the pause all age upgrades flag from the AI.
void aiSetMinNumberNeedForGatheringAggressvies(long v)
sets the min number of needed units to gather aggressive animals.
int aiGetMinNumberNeedForGatheringAggressives()
gets the min number of needed units to gather aggressive animals.
void aiSetMinNumberWantForGatheringAggressives(long v)
sets the min number of wanted units to gather aggressive animals.
int aiGetMinNumberWantForGatheringAggressives()
gets the min number of wanted units to gather aggressive animals.
void aiResign()
reigns the current player..
void aiAttemptResign()
asks the player if its ok to resign
int aiGetPopNeeds()
gets the current Pop needs of all the plans.
void kbAreaCalculate()
Creates areas and area groups. DO THIS BEFORE ANYTHING ELSE IN YOUR SCRIPT.
bool kbCanSimPath( vector pointA, vector pointB, long protoUnitTypeID, float range )
Returns true if the given unit type can path from pointA to pointB.
bool kbCanPath2( vector pointA, vector pointB, long protoUnitTypeID, float range )
Returns true if the given unit type can path from pointA to pointB.
bool kbMakeAttackRoutes()
find all the paths to the sector specified.
int kbEscrowCreate( string name, int resourceID, float percentage, int parentID )
Creates an escrow.
bool kbIsGameOver()
Returns whether the game is over or not.
int kbBaseCreate( int playerID, string name, vector position, float distance )
Creates a base.
int kbBaseGetNumberUnits( int playerID, int baseID, int relation, int unitTypeID )
Returns the number of units that match the criteria.
void kbForceContextPlayerID()
use for debugging or manual scenario repair ONLY!!!
int kbTechTreeGetRandomUnitUpgrade()