I was seeking for it inside mpqs so here they are...
As AI doesn't work yet and editor isn't available yet we could try playing around with these ;)
Its way to go.
I was going to check If I could add some AI using these but I thought sharing what I found would be nice so here you go ...
I know it contains a lot of useless junk too :/
BuildAI.galaxy
//--------------------------------------------------------------------------------------------------
// AI Building Functions
//--------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------
// Build Flags
//--------------------------------------------------------------------------------------------------
const int c_makeNoFlags = 0x00000000;
const int c_avoidClosePowerOrCreep = 0x00000001;
const int c_avoidCloseFactory = 0x00000002;
const int c_avoidCloseDefense = 0x00000004;
const int c_avoidCloseDropoff = 0x00000008;
const int c_avoidFarPowerOrCreep = 0x00000010;
const int c_avoidFarFactory = 0x00000020;
const int c_avoidFarDefense = 0x00000040;
const int c_avoidFarDropoff = 0x00000080;
const int c_nearClosePowerOrCreep = 0x00000100;
const int c_nearCloseFactory = 0x00000200;
const int c_nearCloseDefense = 0x00000400;
const int c_nearCloseDropoff = 0x00000800;
const int c_nearFarPowerOrCreep = 0x00001000;
const int c_nearFarFactory = 0x00002000;
const int c_nearFarDefense = 0x00004000;
const int c_nearFarDropoff = 0x00008000;
const int c_avoidResource = 0x00010000;
const int c_avoidChokePoint = 0x00020000;
const int c_nearResource = 0x00040000;
const int c_nearChokePoint = 0x00080000;
const int c_valueSpaceMinor = 0x00100000;
const int c_valueSpaceMajor = 0x00200000;
const int c_canLower = 0x08000000;
const int c_onVespeneGas = 0x10000000;
const int c_onlyHere = 0x20000000;
const int c_ignoreDanger = 0x40000000;
const int c_avoidPowerOrCreep = c_avoidClosePowerOrCreep | c_avoidFarPowerOrCreep;
const int c_avoidFactory = c_avoidCloseFactory | c_avoidFarFactory;
const int c_avoidDefense = c_avoidCloseDefense | c_avoidFarDefense;
const int c_avoidDropoff = c_avoidCloseDropoff | c_avoidFarDropoff;
const int c_nearPowerOrCreep = c_nearClosePowerOrCreep | c_nearFarPowerOrCreep;
const int c_nearFactory = c_nearCloseFactory | c_nearFarFactory;
const int c_nearDefense = c_nearCloseDefense | c_nearFarDefense;
const int c_nearDropoff = c_nearCloseDropoff | c_nearFarDropoff;
const int c_makeStandard = c_makeNoFlags;
const int c_makeCenter = c_nearResource;
const int c_makeCreep = c_valueSpaceMajor | c_avoidPowerOrCreep;
const int c_makePower = c_valueSpaceMajor | c_avoidPowerOrCreep;
const int c_makeExpanPower = c_nearResource | c_nearDropoff | c_avoidClosePowerOrCreep;
const int c_makeDarkPower = c_nearResource | c_nearDropoff;
const int c_makeCollector = c_onVespeneGas | c_nearDropoff;
const int c_makeDefense = c_avoidCloseDefense | c_nearResource | c_nearFarDropoff | c_nearFarFactory | c_nearFarPowerOrCreep | c_nearChokePoint;
const int c_makeResourceDefense = c_avoidCloseDefense | c_nearResource;
const int c_makeLowerable = c_makeStandard | c_canLower;
const int c_makeDefault = -1;
//--------------------------------------------------------------------------------------------------
// AI Get Default Build Flags Functions
//--------------------------------------------------------------------------------------------------
int AIGetDefaultBuildFlags (int player, string objType) {
// special protoss units
if (objType == c_PB_Nexus) {
return c_makeCenter;
}
if (objType == c_PB_Pylon) {
return c_makePower;
}
if (objType == c_PB_Obelisk) {
return c_makeDarkPower;
}
if (objType == c_PB_PhotonCannon) {
return c_makeDefense;
}
if (objType == c_PB_Assimilator) {
return c_makeCollector;
}
// special terran units
if (objType == c_TB_CommandCenter) {
return c_makeCenter;
}
if (objType == c_TB_Bunker) {
return c_makeDefense;
}
if (objType == c_TB_MissileTurret) {
return c_makeResourceDefense;
}
if (objType == c_TB_SensorTower) {
return c_nearChokePoint;
}
if (objType == c_TB_PlanetaryFortress) {
return c_makeDefense;
}
if (objType == c_TB_Refinery) {
return c_makeCollector;
}
if (objType == c_TB_SupplyDepot) {
return c_makeLowerable;
}
// special zerg units
if (objType == c_ZB_Hatchery) {
return c_makeCenter;
}
if (objType == c_ZB_Lair) {
return c_makeCenter;
}
if (objType == c_ZB_Hive) {
return c_makeCenter;
}
if (objType == c_ZB_CreepTumor) {
return c_makeCreep;
}
if (objType == c_ZB_SpineCrawler) {
return c_makeDefense;
}
if (objType == c_ZB_SporeCrawler) {
return c_makeResourceDefense;
}
if (objType == c_ZB_Extractor) {
return c_makeCollector;
}
// default
return c_makeStandard;
}
Computer.galaxy
include "TriggerLibs/MeleeAI"
include "TriggerLibs/Terran"
include "TriggerLibs/Protoss"
include "TriggerLibs/Zerg"
MeleeAI.galaxy
//==================================================================================================
// Melee AI Functions
//--------------------------------------------------------------------------------------------------
// rough rating target:
// insane 2300
// very hard 2000
// hard 1700
// medium 1400
// easy 1100
// very easy 800
//==================================================================================================
const bool DEBUG = true;
const bool DEBUG_MAIN_STATE = false;
const bool DEBUG_ATTACK_STATE = false;
const bool DEBUG_WAVE = false;
const int e_flagsScouting = 1;
const int e_flagsDiversion = 2;
const int e_flagsTimeout = 3;
const int e_flagsRunScared = 4;
const int e_flagsDetect = 5;
const int e_flagsZergStock = 6;
const int e_flagsExpanded = 7;
const int e_flagsLateScout = 8;
const int e_flagsClearObs = 9;
const int e_flagsEarlyDefScout = 10;
// limit of 16 states in CCaptain
const int e_mainState = 1;
const int e_mainSubState = 2;
const int e_attackState = 3;
const int e_divert1State = 4;
const int e_divert2State = 5;
const int e_openRollState = 6;
const int e_middleRollState = 7;
const int e_lateRollState = 8;
// main states
const int e_mainState_Disabled = -1;
const int e_mainState_Off = 0;
const int e_mainState_Init = 1;
const int e_mainState_OpenGnd0 = 2;
const int e_mainState_OpenGnd1 = 3;
const int e_mainState_OpenGnd2 = 4;
const int e_mainState_OpenGnd3 = 5;
const int e_mainState_OpenGnd4 = 6;
const int e_mainState_OpenGnd5 = 7;
const int e_mainState_OpenAir0 = 8;
const int e_mainState_OpenAir1 = 9;
const int e_mainState_OpenAir2 = 10;
const int e_mainState_OpenAir3 = 11;
const int e_mainState_OpenAir4 = 12;
const int e_mainState_OpenAir5 = 13;
const int e_mainState_Mid0 = 14;
const int e_mainState_Mid1 = 15;
const int e_mainState_Mid2 = 16;
const int e_mainState_Mid3 = 17;
const int e_mainState_Mid4 = 18;
const int e_mainState_Mid5 = 19;
const int e_mainState_Late0 = 20;
const int e_mainState_Late1 = 21;
const int e_mainState_Late2 = 22;
const int e_mainState_Late3 = 23;
const int e_mainState_Late4 = 24;
const int e_mainState_Late5 = 25;
// main sub states
const int e_mainSubState_Unset = 1;
const int e_mainSubState_GndA = 2;
const int e_mainSubState_GndB = 3;
const int e_mainSubState_AirA = 4;
const int e_mainSubState_AirB = 5;
// attack states
const int e_attackState_Wait = 1;
const int e_attackState_Idle = 2;
const int e_attackState_Attack = 3;
const int e_attackState_DropAttack = 4;
const int e_attackState_Scared = 5;
const int e_attackState_Retreat = 6;
const int e_attackState_DropRetreat = 7;
const int e_attackState_InRetreat = 8;
const fixed c_evalDefendRange = 20;
const fixed c_evalRange = 10;
const fixed c_evalHarassRange = 8;
// drop attack variables
const fixed c_dropCheckRollFreq = 60.0;
const fixed c_dropCheckAttackFreq = 240.0;
const int c_dropAttackChance = 75;
//--------------------------------------------------------------------------------------------------
// DebugAI
//--------------------------------------------------------------------------------------------------
void DebugAI (string s) {
if (DEBUG) {
TriggerDebugOutput(1, StringToText(s), true);
}
}
//--------------------------------------------------------------------------------------------------
void DebugAIPlayer (int player, string s) {
if (DEBUG) {
TriggerDebugOutput(
1,
StringToText("[") +
PlayerColorName(PlayerGetColorIndex(player, false)) +
StringToText("] ") +
StringToText(s),
true
);
}
}
//--------------------------------------------------------------------------------------------------
void DebugAIPlayerWave (int player, string s) {
if (DEBUG_WAVE) {
DebugAIPlayer(player, s);
}
}
//--------------------------------------------------------------------------------------------------
void DebugVarInt (string s, int value) {
DebugAI(s + "= " + IntToString(value));
}
//--------------------------------------------------------------------------------------------------
void DebugVarString (string s, string value) {
DebugAI(s + "= " + value);
}
//--------------------------------------------------------------------------------------------------
void DebugVarInt2 (string s1, int value1, string s2, int value2) {
DebugAI(s1 + "= " + IntToString(value1) + ", " + s2 + "= " + IntToString(value2));
}
//--------------------------------------------------------------------------------------------------
void DebugVarInt3 (string s1, int value1, string s2, int value2, string s3, int value3) {
DebugAI(s1 + "= " + IntToString(value1) + ", "
+ s2 + "= " + IntToString(value2) + ", "
+ s3 + "= " + IntToString(value3)
);
}
//--------------------------------------------------------------------------------------------------
void DebugVarBool (string s, bool value) {
if (value) {
DebugAI(s + "= true");
}
else {
DebugAI(s + "= false");
}
}
//--------------------------------------------------------------------------------------------------
string AttackStateName (int state) {
if (state == e_attackState_Wait) { return "Wait"; }
if (state == e_attackState_Attack) { return "Attack"; }
if (state == e_attackState_DropAttack) { return "DropAttack"; }
if (state == e_attackState_Idle) { return "Idle"; }
if (state == e_attackState_Scared) { return "Scared"; }
if (state == e_attackState_Retreat) { return "Retreat"; }
if (state == e_attackState_DropRetreat) { return "DropRetreat"; }
if (state == e_attackState_InRetreat) { return "InRetreat"; }
return "?" + IntToString(state) + "?";
}
//--------------------------------------------------------------------------------------------------
string WaveStateName (int state) {
if (state == c_waveStateIdle) { return "Idle"; }
if (state == c_waveStateSuicide) { return "Suicide"; }
if (state == c_waveStateMerge) { return "Merge"; }
if (state == c_waveStateAttack) { return "Attack"; }
if (state == c_waveStateDefend) { return "Defend"; }
if (state == c_waveStateScout) { return "Scout"; }
if (state == c_waveStateRetreat) { return "Retreat"; }
if (state == c_waveStateClearObs) { return "ClearObs"; }
if (state == c_waveStateGuardHome) { return "Home"; }
return "?" + IntToString(state) + "?";
}
//--------------------------------------------------------------------------------------------------
void DebugWave (int player, string name, wave w) {
string threat;
if (AIDefenseThreat(c_dtAnyThreat, player, w)) {
threat = "true";
}
else {
threat = "false";
}
DebugAIPlayer(
player,
"wave=" + name +
", units=" + IntToString(AIWaveUnitCount(w)) +
", state=" + WaveStateName(AIWaveState(w)) +
", ratio=" + IntToString(AIWaveEvalRatio(w, c_evalRange)) +
", combat=" + IntToString(AIWaveGetTimeInCombat(w)) +
", safe=" + IntToString(AIWaveGetTimeSinceCombat(w)) +
", threat=" + threat
);
}
//--------------------------------------------------------------------------------------------------
void DebugMelee (int player) {
DebugWave(player, "main", AIWaveGet(player, c_waveMain));
DebugWave(player, "atck", AIWaveGet(player, c_waveAttack));
DebugWave(player, "dfnd", AIWaveGet(player, c_waveDefend));
DebugWave(player, "div1", AIWaveGet(player, c_waveDivert1));
DebugWave(player, "div2", AIWaveGet(player, c_waveDivert2));
DebugWave(player, "clob", AIWaveGet(player, c_waveClearObs));
DebugWave(player, "home", AIWaveGet(player, c_waveHome));
DebugVarInt2(
"peons cur", AIGetCurPeonCount(player, c_townMax),
"max", AIGetMaxPeonCount(player, c_townMax)
);
DebugVarBool("e_flagsScouting", AIGetFlag(player, e_flagsScouting));
DebugVarBool("e_flagsTimeout", AIGetFlag(player, e_flagsTimeout));
}
//--------------------------------------------------------------------------------------------------
bool DebugMeleeTrigger (bool c, bool a) {
if (a) {
DebugMelee(StringToInt(StringWord(EventChatMessage(false), 2)));
}
return true;
}
//--------------------------------------------------------------------------------------------------
bool g_debugMeleeInit = false;
void DebugMeleeInit () {
trigger t;
if (!g_debugMeleeInit) {
t = TriggerCreate("DebugMeleeTrigger");
TriggerAddEventChatMessage(t, 1, "waves", false);
g_debugMeleeInit = true;
}
}
//--------------------------------------------------------------------------------------------------
string MainStateName (int state) {
if (state == e_mainState_Init) { return "Init"; }
else if (state == e_mainState_OpenGnd0) { return "OpenGnd0"; }
else if (state == e_mainState_OpenGnd1) { return "OpenGnd1"; }
else if (state == e_mainState_OpenGnd2) { return "OpenGnd2"; }
else if (state == e_mainState_OpenGnd3) { return "OpenGnd3"; }
else if (state == e_mainState_OpenGnd4) { return "OpenGnd4"; }
else if (state == e_mainState_OpenGnd5) { return "OpenGnd5"; }
else if (state == e_mainState_OpenAir0) { return "OpenAir0"; }
else if (state == e_mainState_OpenAir1) { return "OpenAir1"; }
else if (state == e_mainState_OpenAir2) { return "OpenAir2"; }
else if (state == e_mainState_OpenAir3) { return "OpenAir3"; }
else if (state == e_mainState_OpenAir4) { return "OpenAir4"; }
else if (state == e_mainState_OpenAir5) { return "OpenAir5"; }
else if (state == e_mainState_Mid0) { return "Mid0"; }
else if (state == e_mainState_Mid1) { return "Mid1"; }
else if (state == e_mainState_Mid2) { return "Mid2"; }
else if (state == e_mainState_Mid3) { return "Mid3"; }
else if (state == e_mainState_Mid4) { return "Mid4"; }
else if (state == e_mainState_Mid5) { return "Mid5"; }
else if (state == e_mainState_Late0) { return "Late0"; }
else if (state == e_mainState_Late1) { return "Late1"; }
else if (state == e_mainState_Late2) { return "Late2"; }
else if (state == e_mainState_Late3) { return "Late3"; }
else if (state == e_mainState_Late4) { return "Late4"; }
else if (state == e_mainState_Late5) { return "Late5"; }
else if (state == e_mainState_Off) { return "Off"; }
return "?" + IntToString(state) + "?";
}
//--------------------------------------------------------------------------------------------------
// AISetAttackState
//--------------------------------------------------------------------------------------------------
void AISetAttackState (int player, int attackState) {
string msg;
int oldState = AIState(player, e_attackState);
AISetSpecificState(player, e_attackState, attackState);
if (DEBUG_ATTACK_STATE) {
msg = "Player " + IntToString(player) + "-" + PlayerRace(player) + " attack state " +
AttackStateName(oldState) + " -> " + AttackStateName(attackState);
DebugAI(msg);
}
}
//--------------------------------------------------------------------------------------------------
// AISetMainState
//--------------------------------------------------------------------------------------------------
void AISetMainState (int player, int mainState, int mainSubState) {
string msg;
int oldMainState = AIState(player, e_mainState);
int oldSubState = AIState(player, e_mainSubState);
AISetSpecificState(player, e_mainState, mainState);
AISetSpecificState(player, e_mainSubState, mainSubState);
if (DEBUG_MAIN_STATE) {
msg = "Player " + IntToString(player) + "-" + PlayerRace(player) + " main state " +
MainStateName(oldMainState) + "(" + IntToString(oldSubState) + ") --> " +
MainStateName(mainState) + "(" + IntToString(mainSubState) + ")";
DebugAI(msg);
}
}
//--------------------------------------------------------------------------------------------------
// EndMeleeScript
//--------------------------------------------------------------------------------------------------
void EndMeleeScript (int player) {
string msg = "Reached end of script for player " + IntToString(player) + "-" +
PlayerRace(player) + " : More AI code coming soon.";
UIDisplayMessage(PlayerGroupAll(), c_messageAreaSubtitle, StringToText(msg));
DebugAI(msg);
AISetMainState(player, e_mainState_Disabled, e_mainSubState_Unset);
}
//--------------------------------------------------------------------------------------------------
// ErrorMeleeScript
//--------------------------------------------------------------------------------------------------
void ErrorMeleeScript (int player, string error) {
string msg = "A script logic error occurred for player " + IntToString(player) +
"-" + PlayerRace(player) + " : " + error;
UIDisplayMessage(PlayerGroupAll(), c_messageAreaSubtitle, StringToText(msg));
DebugAI(msg);
AISetMainState(player, e_mainState_Disabled, e_mainSubState_Unset);
}
//--------------------------------------------------------------------------------------------------
// AISetGasPeons
//--------------------------------------------------------------------------------------------------
void AISetGasPeons (int player, int count, string type, string from) {
int sources = AITechCount(player, from, c_techCountCompleteOnly);
if (sources < 1
|| AIHasRes(player, 0, 200)
|| AITechCount(player, type, c_techCountCompleteOnly) < 8)
{
AISetGasPeonCountOverride(player, c_townMain, c_defaultGasPeonCount);
}
else if (sources == 1) {
AISetGasPeonCountOverride(player, c_townMain, 3);
}
else { // sources == 2+
AISetGasPeonCountOverride(player, c_townMain, count);
}
}
//--------------------------------------------------------------------------------------------------
// AISetStockAll
//--------------------------------------------------------------------------------------------------
void AISetStockAll (int player, string source, int max, string what) {
int make = AITechCount(player, what, c_techCountCompleteOnly)
+ 2 * AITechCount(player, source, c_techCountCompleteOnly);
if (make > max) {
make = max;
}
AISetStock(player, make, what);
}
//--------------------------------------------------------------------------------------------------
// AIMergeUnit
//--------------------------------------------------------------------------------------------------
void AIMergeUnit (int player, unit u, wave w) {
wave merge = AIWaveCreate(AIWaveInfoCreate(), player, AIGetGatherLocation(player, c_townMain));
AIWaveAddUnit(merge, u);
AIWaveSetType(merge, c_waveStateMerge, AIWaveTargetMerge(w));
}
//--------------------------------------------------------------------------------------------------
// AINewUnitDefault
//--------------------------------------------------------------------------------------------------
void AINewUnitDefault (int player, unit u) {
wave w = AIWaveGet(player, c_waveMain);
if (AIDefenseThreat(c_dtAnyThreat, player, w)) {
AIMergeUnit(player, u, w);
}
else {
AIWaveAddUnit(w, u);
}
}
//--------------------------------------------------------------------------------------------------
// AICreateOrder
//--------------------------------------------------------------------------------------------------
order AICreateOrder (int player, string abilLink, int abilIndex) {
abilcmd cmd = AbilityCommand(abilLink, abilIndex);
order ord;
if (cmd == c_nullCmd) {
return null;
}
ord = Order(cmd);
OrderSetPlayer(ord, player);
return ord;
}
MeleeAI.galaxy < suite
//--------------------------------------------------------------------------------------------------
// AITacticalOrder
//--------------------------------------------------------------------------------------------------
order AITacticalOrder (int player, unit aiUnit, string abilLink) {
order ord = AICreateOrder(player, abilLink, 0);
if (!UnitOrderIsValid(aiUnit, ord)) {
return null;
}
return ord;
}
//--------------------------------------------------------------------------------------------------
// AITacticalOrderIndex
//--------------------------------------------------------------------------------------------------
order AITacticalOrderIndex (int player, unit aiUnit, string abilLink, int abilIndex) {
order ord = AICreateOrder(player, abilLink, abilIndex);
if (!UnitOrderIsValid(aiUnit, ord)) {
return null;
}
return ord;
}
//--------------------------------------------------------------------------------------------------
// AICombatPriority
//--------------------------------------------------------------------------------------------------
unit AICombatPriority (unit target, unitgroup attackers, unitgroup enemies) {
return AIDefaultCombatPriority(target, attackers, enemies);
}
//--------------------------------------------------------------------------------------------------
// AIDefendTown
//--------------------------------------------------------------------------------------------------
void AIDefendTown (int player, wave w) {
int eval = AIWaveEvalRatio(w, c_evalDefendRange);
int staticPercent = AILastWaveEvalStaticRatio();
int neededEval = 60;
if (staticPercent > 90) {
neededEval = 80;
}
else if (staticPercent > 40) {
neededEval = 70;
}
if (eval < neededEval) {
if (AIWaveState(w) != c_waveStateRetreat) {
DebugAIPlayerWave(player, "defend1 set wave = retreat to gather defense");
AIWaveSetType(w, c_waveStateRetreat, AIWaveTargetGatherD(player, c_townMax));
}
}
else if (AIWaveState(w) != c_waveStateDefend) {
if (eval > neededEval+10) {
if (AIWaveGetTimeSinceOrdered(w) >= 20) {
DebugAIPlayerWave(player, "defend2 set wave = defend vs. threats");
AIWaveSetType(w, c_waveStateDefend, AIWaveTargetMeleeDefend(player));
}
}
}
}
//--------------------------------------------------------------------------------------------------
// AIWaveDefend
//--------------------------------------------------------------------------------------------------
void AIWaveDefend (int player, wave w) {
if (AIDefenseThreat(c_dtAnyThreat, player, w)) {
AIDefendTown(player, w);
}
else if (AIWaveState(w) != c_waveStateIdle) {
DebugAIPlayerWave(player, "defend3 set defend = idle at gather defense");
AIWaveSetType(w, c_waveStateIdle, AIWaveTargetGatherD(player, c_townMax));
}
}
//--------------------------------------------------------------------------------------------------
// AIWaveMain
//--------------------------------------------------------------------------------------------------
void AIWaveMain (int player, wave w) {
unit obstruction = null;
int count = AIWaveUnitCount(w);
int state = AIWaveState(w);
int attackState = AIState(player, e_attackState);
if (AIWaveIsInCombat(w)) {
return;
}
if (AIDefenseThreat(c_dtAnyThreat, player, w)) {
AIDefendTown(player, w);
return;
}
if (count >= 3 && AIGetFlag(player, e_flagsTimeout)) {
if (attackState != e_attackState_DropAttack && attackState != e_attackState_DropRetreat) {
AIWaveMerge(player, c_waveMain, c_waveAttack);
return;
}
}
if (state != c_waveStateIdle) {
DebugAIPlayerWave(player, "main2 set main = idle at gather offense");
AIWaveSetType(w, c_waveStateIdle, AIWaveTargetGatherO(player, c_townMax));
}
}
//--------------------------------------------------------------------------------------------------
// AIWaveDivert
//--------------------------------------------------------------------------------------------------
void AIWaveDivert (int player, wave w, int stateIndex) {
int state;
int count;
if (AIDefenseThreat(c_dtAnyThreat, player, w)) {
AIDefendTown(player, w);
return;
}
state = AIWaveState(w);
if (state == c_waveStateDefend) {
DebugAIPlayerWave(player, "divert1 set divert = idle at gather defense");//xxx
AIWaveSetType(w, c_waveStateIdle, AIWaveTargetGatherD(player, c_townMax));
return;
}
if (!AIGetFlag(player, e_flagsDiversion)) {
return;
}
if (AIWaveEvalRatio(w, c_evalHarassRange) < 100) {
if (state != c_waveStateRetreat) {
DebugAIPlayerWave(player, "divert2 set divert = retreat to harass point");//xxx
AIWaveSetType(w, c_waveStateRetreat, AIWaveHarassRetreat(player, w, c_evalHarassRange));
}
}
else if (state != c_waveStateAttack) {
if (AIWaveGetTimeSinceOrdered(w) >= 10) {
DebugAIPlayerWave(player, "divert3 set divert = attack harass target");//xxx
AIWaveSetType(w, c_waveStateAttack, AIWaveTargetMeleeHarass(player));
}
}
}
//--------------------------------------------------------------------------------------------------
// AIWaveHome
//--------------------------------------------------------------------------------------------------
void AIWaveHome (int player, wave w) {
int state;
state = AIWaveState(w);
if (state != c_waveStateGuardHome) {
DebugAIPlayerWave(player, "home set divert = idle at gather defense");
AIWaveSetType(w, c_waveStateGuardHome, AIWaveTargetGatherD(player, c_townMax));
return;
}
}
//--------------------------------------------------------------------------------------------------
// AIWaveClearObs
//--------------------------------------------------------------------------------------------------
void AIWaveClearObs (int player, wave w) {
unit obstruction = AIGetObstruction(player);
unit oldTarget = null;
int obsLife;
int state = AIWaveState(w);
// If there are no longer any obstructions, merge back into the main wave
if (obstruction == null) {
DebugAIPlayerWave(player, "clearobs1 merge clear obstruction -> main");
AIWaveMerge(player, c_waveClearObs, c_waveMain);
return;
}
// Defend against threats, unless we're almost done destroying the obstruction
obsLife = UnitGetPropertyInt(obstruction, c_unitPropLifePercent, c_unitPropCurrent);
if (AIDefenseThreat(c_dtAnyThreat, player, w) && obsLife > 20) {
AIDefendTown(player, w);
return;
}
// Let's hunt some rock!
oldTarget = AIWaveTargetGetUnit(AIWaveGetTarget(w));
if (state != c_waveStateClearObs || obstruction != oldTarget) {
DebugAIPlayerWave(player, "clearobs2 set clear obstruction = clear obstruction");
AIWaveSetType(w, c_waveStateClearObs, AIWaveTargetUnit(obstruction));
}
}
//--------------------------------------------------------------------------------------------------
// AINewDetector
//--------------------------------------------------------------------------------------------------
void AINewDetector (int player, unit u, bool offerToScout) {
wave defendWave = AIWaveGet(player, c_waveDefend);
wave attackWave = AIWaveGet(player, c_waveAttack);
// first offer it to the attack wave if that wave has some units in it
if (AIWaveUnitCount(attackWave) >= 4) {
if (AIWaveDetectorCount(attackWave) == 0) {
AIWaveAddUnitPriority(attackWave, u, c_prioWavePeon);
return;
}
}
// next offer it to the defense wave
if (AIWaveDetectorCount(defendWave) == 0) {
AIWaveAddUnitPriority(defendWave, u, c_prioWavePeon);
return;
}
// last offer it to the scout synapse
if (offerToScout) {
if (AIOfferNewScout(player, u)) {
return;
}
}
// let the attack wave claim a second one
if (AIWaveUnitCount(attackWave) >= 4) {
if (AIWaveDetectorCount(attackWave) < 2) {
AIWaveAddUnitPriority(attackWave, u, c_prioWavePeon);
return;
}
}
// else add the detector to the extra scout group
AIAddToExtraScoutGroup(player, u);
}
//--------------------------------------------------------------------------------------------------
// AIWaveNeedClearObsUnits
//--------------------------------------------------------------------------------------------------
bool AIWaveNeedClearObsUnits (int player) {
unit obstruction = null;
wave waveClob = null;
wave waveAtck = null;
int countClob = 0;
int countAtck = 0;
int evalAtck = 0;
// Check global option
if (AIGetFlag(player, e_flagsClearObs) == false) {
return false;
}
// Don't clear obstructions in the first 10 minutes (leaves the AI too open to being rushed)
if (AIGetTime() < 600) {
return false;
}
// See if there is any obstruction
obstruction = AIGetObstruction(player);
if (obstruction == null) {
return false;
}
// See if the clear obstruction wave is already full
waveClob = AIWaveGet(player, c_waveClearObs);
countClob = AIWaveUnitCount(waveClob);
if (countClob >= 4) {
return false;
}
// If the attack wave is getting weak, keep units available for it instead
waveAtck = AIWaveGet(player, c_waveAttack);
countAtck = AIWaveUnitCount(waveAtck);
evalAtck = AIWaveEvalRatio(waveAtck, c_evalRange);
if (countAtck > 0 && evalAtck < 80) {
return false;
}
// Yes, units are needed for clear obstruction duty
return true;
}
//--------------------------------------------------------------------------------------------------
// AIWaveAttackDefend
//--------------------------------------------------------------------------------------------------
static bool AIWaveAttackDefend (int player, wave w, int state) {
if (!AIDefenseThreat(c_dtRealThreat, player, w)) {
return false;
}
if ( state == e_attackState_Idle || state == e_attackState_Wait ||
(AIWaveEval(AIWaveGet(player, c_waveMain)) + AIWaveEval(AIWaveGet(player, c_waveDefend)) < AIDefenseThreatEval(c_dtEvalRealThreats, player)) )
{
return true;
}
return false;
}
//--------------------------------------------------------------------------------------------------
// AIIsAttacking
//--------------------------------------------------------------------------------------------------
bool AIIsAttacking (int player) {
wave waveAttack = null;
// for now I'm not counting e_attackState_DropAttack as attacking, it is a specialized attack
// and not easy for other AI's to coordinate with it
if (AIState(player, e_attackState) != e_attackState_Attack) {
return false;
}
waveAttack = AIWaveGet(player, c_waveAttack);
if (AIWaveUnitCount(waveAttack) == 0) {
return false;
}
if (AIWaveState(waveAttack) != c_waveStateAttack) {
return false;
}
return true;
}
//--------------------------------------------------------------------------------------------------
// AINeedsDefending
//--------------------------------------------------------------------------------------------------
bool AINeedsDefending (int player) {
return AIWaveAttackDefend(player, c_nullWave, e_attackState_Attack);
}
//--------------------------------------------------------------------------------------------------
// TestUseDropAttack
//--------------------------------------------------------------------------------------------------
bool TestUseDropAttack (int player, wave w) {
int numMobileTransports;
// see if we can and want to do a drop attack
numMobileTransports = AIGetNumMobileTransports(player);
if (numMobileTransports >= 1) {
// we have a transport, so request more so we can use them to do a drop later
AISetWantsMultipleTransport(player, true);
}
else {
// don't worry about drops if we have no transports.
return false;
}
if (numMobileTransports < 3) {
// wait until we have at least 3 transports to try a drop
return false;
}
if (AIGetNextDropTimeCheck(player) >= AIGetTime()) {
// only check drop attacks every so often
return false;
}
AISetNextDropTimeCheck(player, AIGetTime() + c_dropCheckRollFreq);
if (RandomInt(1,100) > c_dropAttackChance) {
return false;
}
if (!AIFindDropAttackTarget(player, AIGetGatherLocation(player, c_townMain))) {
return false;
}
AISetNextDropTimeCheck(player, AIGetTime() + c_dropCheckAttackFreq);
AISetAttackState(player, e_attackState_DropAttack);
DebugAIPlayerWave(player, "attack1drop merge main -> attack; set attack = drop attack");
AIWaveMerge(player, c_waveMain, c_waveAttack);
AIWaveSetType(w, c_waveStateDropAttack, AIWaveTargetMeleeDrop(player, AILastDropLocation(), AILastDropGoal()));
return true;
}
//--------------------------------------------------------------------------------------------------
// AdvancedIdleAttackLogic
//--------------------------------------------------------------------------------------------------
void AdvancedIdleAttackLogic (int player, wave w, int count) {
// hard/insane logic for when to attack again
int eval;
bool enoughForce = false;
if (AILastAttackRatio(w) >= 120) {
// if the last attack was successful (we killed a good bit more than we lost)
// then attack again as soon as we've gathered 20 units or it's been a short amount of time
if (count >= 20) {
AISetAttackState(player, e_attackState_Attack);
}
else if (count >= 10 && AIGetFlag(player, e_flagsTimeout) && AIWaveGetTimeSinceCombat(w) >= 120) {
AISetAttackState(player, e_attackState_Attack);
}
}
else if (AILastAttackRatio(w) >= 80) {
// if the last attack was even (we did fight and we killed about as much as we lost)
// then we to attack until we've regrouped a bit
if (count >= 12) {
if (TestUseDropAttack(player,w)) {
return;
}
}
if (count >= 30) {
AISetAttackState(player, e_attackState_Attack);
}
else if (count >= 15 && AIGetFlag(player, e_flagsTimeout) && AIWaveGetTimeSinceCombat(w) >= 300 - 5*count) {
AISetAttackState(player, e_attackState_Attack);
}
}
else { // AILastAttackRatio(w) < 80
// if the last attack was a failure (we either retreated right away or lost more then we killed)
if (count >= 12) {
if (TestUseDropAttack(player,w)) {
return;
}
}
if (count < 20) {
return;
}
// force us to gather more units than last time, or use at least 160 food cap
if (PlayerGetPropertyInt(player, c_playerPropSuppliesUsed) > 160) {
enoughForce = true;
}
else {
eval = AIWaveEval(w) + AIWaveEval(AIWaveGet(player, c_waveMain));
if (IntToFixed(eval) > IntToFixed(AILastAttackStartEval(w)) * 1.33) {
enoughForce = true;
}
}
if (enoughForce) {
AISetAttackState(player, e_attackState_Attack);
}
}
}
//--------------------------------------------------------------------------------------------------
// AIWaveAttack
//--------------------------------------------------------------------------------------------------
void AIWaveAttack (int player, wave w) {
int state = AIState(player, e_attackState);
int eval;
int time;
int count;
//--- DEFEND ---
if (AIWaveAttackDefend(player, w, state)) {
AIDefendTown(player, w);
return;
}
//--- ATTACK ---
if (state == e_attackState_Attack) {
time = AIWaveGetTimeInCombat(w);
eval = AIWaveEvalRatio(w, c_evalRange);
if (eval >= 70 && eval <= 85 && time <= 3) { // when not fighting and only a little weak
if (AIGetFlag(player, e_flagsRunScared)) { // need to add check for ranges & max eval
AISetAttackState(player, e_attackState_Scared);
}
else {
AISetAttackState(player, e_attackState_Retreat);
}
}
else if (eval < 70) { // need to add check for faster/retreat blocked
AISetAttackState(player, e_attackState_Retreat);
}
else if (AIWaveState(w) != c_waveStateAttack) {
DebugAIPlayerWave(player, "attack1 merge main -> attack; set attack = attack vs. melee target");
AIWaveMerge(player, c_waveMain, c_waveAttack);
AIWaveSetType(w, c_waveStateAttack, AIWaveTargetMelee(player));
}
}
//--- DROP-ATTACK ---
if (state == e_attackState_DropAttack) {
eval = AIWaveEvalRatio(w, c_evalRange);
if (eval < 80) { // need to add check for can we retreat successfully
AISetAttackState(player, e_attackState_DropRetreat);
}
if (AIWaveState(w) != c_waveStateDropAttack) {
DebugAIPlayerWave(player, "attack1a In drop attack state, but not drop attack wave state?");
AISetAttackState(player, e_attackState_DropRetreat);
}
}
//--- SCARED ---
else if (state == e_attackState_Scared) {
eval = AIWaveEvalRatio(w, c_evalRange);
if (eval > 95) { // turn and fight when strong
AISetAttackState(player, e_attackState_Attack);
}
else if (eval < 70) { // retreat entirely if getting picked off
AISetAttackState(player, e_attackState_Retreat);
}
else if (AIWaveState(w) != c_waveStateRetreat) {
DebugAIPlayerWave(player, "attack2 merge main -> attack; set attack = retreat to gather offense");
AIWaveMerge(player, c_waveMain, c_waveAttack);
AIWaveSetType(w, c_waveStateRetreat, AIWaveTargetGatherO(player, c_townMain));
}
}
//--- RETREAT ---
else if (state == e_attackState_Retreat) {
DebugAIPlayerWave(player, "attack3 set attack = retreat to gather offense");
AIWaveSetType(w, c_waveStateRetreat, AIWaveTargetGatherO(player, c_townMain));
AISetAttackState(player, e_attackState_InRetreat);
}
//--- DROP RETREAT ---
else if (state == e_attackState_DropRetreat) {
DebugAIPlayerWave(player, "attack3drop set attack = drop retreat to gather offense");
AIWaveSetType(w, c_waveStateDropRetreat, AIWaveTargetGatherO(player, c_townMain));
AISetAttackState(player, e_attackState_InRetreat);
}
//--- IN RETREAT ---
else if (state == e_attackState_InRetreat) {
if (AIWaveState(w) != c_waveStateRetreat && AIWaveState(w) != c_waveStateDropRetreat) {
DebugAIPlayerWave(player, "attack4 merge main -> attack");
AIWaveMerge(player, c_waveMain, c_waveAttack);
AISetAttackState(player, e_attackState_Idle);
}
}
MeleeAI.galaxy < suite
//--- IDLE ---
else if (state == e_attackState_Idle) {
count = AIWaveUnitCount(w) + AIWaveUnitCount(AIWaveGet(player, c_waveMain));
// wait 30 seonds at least after retreating before attacking again
if (AIWaveGetTimeSinceRetreat(w) > 30) {
// always support allies attacking
if (AIAnyAllyAttacking(player)) {
AISetAttackState(player, e_attackState_Attack);
}
if (PlayerDifficulty(player) >= c_skirVeryHard) {
if (AIWaveState(w) == c_waveStateIdle) {
// wait until the wave is idle before considering attacking again
AdvancedIdleAttackLogic(player, w, count);
}
}
else {
// base logic attack any time we have more than 30 units or it's been a while
if (count >= 30) {
AISetAttackState(player, e_attackState_Attack);
}
else if (AIGetFlag(player, e_flagsTimeout) && AIWaveGetTimeSinceCombat(w) >= 300-10*count) {
AISetAttackState(player, e_attackState_Attack);
}
}
}
if (AIState(player, e_attackState) == e_attackState_Idle) {
if (AIWaveState(w) != c_waveStateIdle) {
DebugAIPlayerWave(player, "attack5 set attack = idle at gather offense");
AIWaveSetType(w, c_waveStateIdle, AIWaveTargetGatherO(player, c_townMax));
}
}
}
}
//--------------------------------------------------------------------------------------------------
// AIWaveThinkDefault
//--------------------------------------------------------------------------------------------------
void AIWaveThinkDefault (int player, wave w, int type) {
if (AIWaveUnitCount(w) < 1) {
return;
}
if (type == c_waveMain) {
AIWaveMain(player, w);
}
else if (type == c_waveDefend) {
AIWaveDefend(player, w);
}
else if (type == c_waveAttack) {
AIWaveAttack(player, w);
}
else if (type == c_waveDivert1) {
AIWaveDivert(player, w, e_divert1State);
}
else if (type == c_waveDivert2) {
AIWaveDivert(player, w, e_divert2State);
}
else if (type == c_waveClearObs) {
AIWaveClearObs(player, w);
}
else if (type == c_waveHome) {
AIWaveHome(player, w);
}
}
//--------------------------------------------------------------------------------------------------
// AIMainStateSelect
//--------------------------------------------------------------------------------------------------
int AIMainStateSelect (int player, int roll, int range, int state, int subState) {
if (roll >= 1 && roll <= range) {
AISetMainState(player, state, subState);
}
return roll - range;
}
//--------------------------------------------------------------------------------------------------
// AIMergeWait
//--------------------------------------------------------------------------------------------------
void AIMergeWait (int player, int count, string what, int size, int state, int subState) {
wave atk = AIWaveGet(player, c_waveAttack);
if (AIWaveState(atk) != c_waveStateRetreat) {
if (AIWaveUnitCount(AIWaveGet(player, c_waveMain)) >= 3 ||
AITechCount(player, what, c_techCountCompleteOnly) >= count)
{
DebugAIPlayerWave(player, "merge1 merge main -> attack");
AIWaveMerge(player, c_waveMain, c_waveAttack);
}
}
if (AIWaveUnitCount(atk) >= size) {
AISetAttackState(player, e_attackState_Attack);
AISetMainState(player, state, subState);
AISetFlag(player, e_flagsTimeout, true);
}
else if (AIHasRes(player, 1000, 500)) {
AISetMainState(player, state, subState);
AISetFlag(player, e_flagsTimeout, true);
}
}
//--------------------------------------------------------------------------------------------------
// AIStockAndWait
//--------------------------------------------------------------------------------------------------
bool AIStockAndWait (int player, int count, string type) {
if (AITechCount(player, type, c_techCountInProgressOrBetter) < count) {
AISetStock( player, count, type );
AIEnableStock(player);
return true;
}
return false;
}
//--------------------------------------------------------------------------------------------------
// AISuspectDetectionDanger
//--------------------------------------------------------------------------------------------------
bool AISuspectDetectionDanger (int player) {
bool suspectDanger = false;
suspectDanger = AIDefaultSuspectDetectionDanger(player);
// script additions / override of the default
return suspectDanger;
}
//--------------------------------------------------------------------------------------------------
// AITownIsFull
//--------------------------------------------------------------------------------------------------
void AITownIsFull (int player, int town) {
// town was unable to place a building because it ran out of room, it may still
// be possible to place a smaller building or a different type of building
AIUpdateMainTown(player);
// if we only have no non-full town, we may want to expand now
}
//--------------------------------------------------------------------------------------------------
// AITownWasLost
//--------------------------------------------------------------------------------------------------
void AITownWasLost (int player, int town) {
// one of our towns was destroyed/lost, happens when we lose our last dropoff at the town (or all buildings).
AIUpdateMainTown(player);
}
//--------------------------------------------------------------------------------------------------
// AIMakeTest
//--------------------------------------------------------------------------------------------------
bool AIMakeTest (int player, int min, int max, string type, string tech,
string base, int addons, string addon)
{
int count = AICounterUnits(player, c_maxPlayers, type);
if (count <= 0) {
return false;
}
if (count < min) {
count = min;
}
else if (count > max) {
count = max;
}
if (AITechCount(player, type, c_techCountInProgressOrBetter) >= count) {
return false;
}
if (count > 5) {
AISetStockUnitNext( player, 3, base, c_stockIdle );
AISetStockUnitNext( player, addons, addon, c_stockIdle );
}
else if (count > 2) {
AISetStockUnitNext( player, 2, base, c_stockIdle );
if (addons > 2) {
AISetStockUnitNext( player, 2, addon, c_stockIdle );
}
else {
AISetStockUnitNext( player, addons, addon, c_stockIdle );
}
}
if (tech != c_noTech) {
AISetStock( player, 1, tech );
}
AISetStockUnitNext( player, count, type, c_stockAlways );
return true;
}
//--------------------------------------------------------------------------------------------------
// AIMineralsTotal
//--------------------------------------------------------------------------------------------------
int AIMineralsTotal (int player) {
return PlayerGetPropertyInt(player, c_playerPropMinerals) + AIGetMineralAmountLeft(player, c_townMax);
}
//--------------------------------------------------------------------------------------------------
// AIWavePrimaryCount
//--------------------------------------------------------------------------------------------------
int AIWavePrimaryCount (int player) {
return AIWaveUnitCount(AIWaveGet(player, c_waveMain)) + AIWaveUnitCount(AIWaveGet(player, c_waveAttack));
}
//--------------------------------------------------------------------------------------------------
// AIDiffEnum
//--------------------------------------------------------------------------------------------------
int AIDiffEnum (int player, int base) {
return base + PlayerDifficulty(player);
}
//--------------------------------------------------------------------------------------------------
// AIDiffThreshold
//--------------------------------------------------------------------------------------------------
int AIDiffThreshold (int player, int defaultValue, int threshold, int alternateValue) {
int diff = PlayerDifficulty(player);
if (diff < threshold) {
return defaultValue;
}
return alternateValue;
}
//--------------------------------------------------------------------------------------------------
// AIAddDetectionDangerUnits
//--------------------------------------------------------------------------------------------------
void AIAddDetectionDangerUnits (int player) {
AIAddDetectionDanger(player, c_TU_Ghost);
AIAddDetectionDanger(player, c_TU_Banshee);
AIAddDetectionDanger(player, c_ZU_Lurker);
AIAddDetectionDanger(player, c_PU_DarkTemplar);
AIAddDetectionDanger(player, c_PU_Mothership);
AIAddDetectionDanger(player, c_TB_GhostAcademy);
AIAddDetectionDanger(player, c_TB_FusionCore);
AIAddDetectionDanger(player, c_ZB_LurkerDen);
AIAddDetectionDanger(player, c_PB_DarkShrine);
}
//--------------------------------------------------------------------------------------------------
// Default startup routine
//--------------------------------------------------------------------------------------------------
void AIMeleeStart (int player) {
point targ;
if (DEBUG) {
DebugMeleeInit();
}
AIStart(player, false, DifficultyAPM(PlayerDifficulty(player)));
if (PlayerDifficulty(player) >= c_skirVeryHard) {
if (PlayerDifficulty(player) >= c_skirCheater) {
AIHarvestBonus(player, 2.0);
AISetDifficulty(player, c_diffNormalVision, false);
AISetDifficulty(player, c_diffLimitAPM, false);
}
AISetFlag(player, e_flagsRunScared, false); // TODO fix scared and re-add this
}
else {
AISetDifficulty(player, c_diffAdvanceWave, false);
AISetDifficulty(player, c_diffFleeDamage, false);
AISetDifficulty(player, c_diffWaveAvoidDanger, false);
AISetFlag(player, e_flagsRunScared, false);
}
AISetDifficulty(player, c_diffAutoLoadBunkers, false);
AISetDifficulty(player, c_diffEarlyGameRepair, false);
AISetDifficulty(player, c_diffEarlyDefenseScout, false);
AISetFlag(player, e_flagsLateScout, false);
AISetFlag(player, e_flagsClearObs, false);
AIDeclareTown(player, c_townOne, PlayerStartLocation(player));
AISetMainTown(player, c_townOne);
AIHarvest(player, c_townOne);
AISetNumScouts(player, 1);
AIScout(player);
AISetAllStates(player, 1);
targ = AIWaveTargetGatherOPoint(player, c_townMain);
AIWaveSet(player, c_waveMain, AIWaveCreate(AIWaveInfoCreate(), player, targ));
AIWaveSet(player, c_waveAttack, AIWaveCreate(AIWaveInfoCreate(), player, targ));
AIWaveSet(player, c_waveDivert1, AIWaveCreate(AIWaveInfoCreate(), player, targ));
AIWaveSet(player, c_waveDivert2, AIWaveCreate(AIWaveInfoCreate(), player, targ));
AIWaveSet(player, c_waveClearObs, AIWaveCreate(AIWaveInfoCreate(), player, targ));
AIWaveSet(player, c_waveHome, AIWaveCreate(AIWaveInfoCreate(), player, targ));
targ = AIWaveTargetGatherDPoint(player, c_townMain);
AIWaveSet(player, c_waveDefend, AIWaveCreate(AIWaveInfoCreate(), player, targ));
AITransportIgnore(player, "VikingAssault");
AITransportSetPanic(player, 0.6);
AITransportSetReturn(player, targ);
AISpecifiedMakers();
AISetDefaultCombatFlags(player, true);
AIAddDetectionDangerUnits(player);
//AISetNukeConstants(player);
}
include "TriggerLibs/MeleeNotHardAI"
MeleeNotHardAI.galaxy
//==================================================================================================
// Melee AI Functions only used by beginner/easy/medium.
//--------------------------------------------------------------------------------------------------
// Very Easy
// APM: 100
// scouts: starts late game
// detect: late game or after being attacked by cloakers
// wave 1: 100 resources, ~2 units, 480 seconds
// wave 2: 300 resources, ~3 units, +360 seconds (840)
// wave 3: 600 resources, ~4 units, +360 seconds (1200)
// wave X: 900 resources, ~5 units, +300 seconds
//--------------------------------------------------------------------------------------------------
// Easy
// APM: 200
// scouts: starts late game
// detect: late game or after being attacked by cloakers
// wave 1: 300 resources, ~4 units, 450 seconds
// wave 2: 800 resources, ~6 units, +340 seconds (790)
// wave 3: 1500 resources, ~8 units, +340 seconds (1130)
// wave X: xxx resources, ~10 units, +280 seconds
//--------------------------------------------------------------------------------------------------
// Medium
// APM: 300
// scouts: starts middle game
// detect: middle game or after being attacked by cloakers
// wave 1: 500 resources, ~6 units, 420 seconds
// wave 2: 1000 resources, ~9 units, +320 seconds (740)
// wave 3: 1800 resources, ~12 units, +320 seconds (1060)
// wave X: xxx resources, ~15 units, +260 seconds
//--------------------------------------------------------------------------------------------------
// Hard
// APM: 400
// scouts: starts early game
// detect: middle game or after being attacked by cloakers
// wave 1: 700 resources, ~8 units, 390 seconds
// wave 2: 1200 resources, ~12 units, +300 seconds (690)
// wave 3: 2100 resources, ~16 units, +300 seconds (990)
// wave X: xxx resources, ~20 units, +240 seconds
//==================================================================================================
//==================================================================================================
// OPEN
//==================================================================================================
//--------------------------------------------------------------------------------------------------
// AIGenericStock
//--------------------------------------------------------------------------------------------------
static void AIGenericStock (int player, int state1, int state2) {
AIWaveMerge(player, c_waveMain, c_waveAttack);
AISetAttackState(player, e_attackState_Attack);
AISetMainState(player, state1, state2);
AIResetUserData(player);
}
//--------------------------------------------------------------------------------------------------
// AIEnableStockOpen
//--------------------------------------------------------------------------------------------------
static bool AIEnableStockOpen (int player, string peonType, int time, bool veryEasy, int nextState) {
AIEnableStock(player);
if (veryEasy) {
if (AITechCount(player, peonType, c_techCountCompleteOnly) >= 8) {
AISetGasPeonCountOverride(player, c_townMain, 2);
}
else {
AISetGasPeonCountOverride(player, c_townMain, 0);
}
}
if (AIGetTime() < time) {
return true;
}
AIGenericStock(player, nextState, e_mainSubState_GndA);
return false;
}
bool AIEnableVeryEasyStockOpen (int player, string peonType) {
return AIEnableStockOpen(player, peonType, 480, true, e_mainState_Mid0);
}
bool AIEnableEasyStockOpen (int player, string peonType) {
return AIEnableStockOpen(player, peonType, 450, false, e_mainState_Mid1);
}
bool AIEnableMediumStockOpen (int player, string peonType) {
return AIEnableStockOpen(player, peonType, 420, false, e_mainState_Mid2);
}
bool AIEnableHardStockOpen (int player, string peonType) {
return AIEnableStockOpen(player, peonType, 390, false, e_mainState_Mid3);
}
//==================================================================================================
// MID A
//==================================================================================================
//--------------------------------------------------------------------------------------------------
// AIVeryEasyHarvest
//--------------------------------------------------------------------------------------------------
void AIVeryEasyHarvest (int player, string peonType, int count) {
if (AIHasRes(player, 0, 200) || AITechCount(player, peonType, c_techCountCompleteOnly) < 8) {
AISetGasPeonCountOverride(player, c_townMain, c_defaultGasPeonCount);
}
else {
AISetGasPeonCountOverride(player, c_townMain, count);
}
}
//--------------------------------------------------------------------------------------------------
// AIEnableStockMidA
//--------------------------------------------------------------------------------------------------
static bool AIEnableStockMidA (int player, string peonType, int count, bool veryEasy, int time, int nextState) {
AIEnableStock(player);
if (veryEasy) {
AIVeryEasyHarvest(player, peonType, count);
}
if (AIGetTime() < time) {
return true;
}
AIGenericStock(player, nextState, e_mainSubState_GndB);
return false;
}
bool AIEnableVeryEasyStockMidA (int player, string peonType, int count) {
return AIEnableStockMidA(player, peonType, count, true, 840, e_mainState_Mid0);
}
bool AIEnableEasyStockMidA (int player) {
return AIEnableStockMidA(player, "", 0, false, 790, e_mainState_Mid1);
}
bool AIEnableMediumStockMidA (int player) {
return AIEnableStockMidA(player, "", 0, false, 740, e_mainState_Mid2);
}
bool AIEnableHardStockMidA (int player) {
return AIEnableStockMidA(player, "", 0, false, 690, e_mainState_Mid3);
}
//==================================================================================================
// MID B
//==================================================================================================
//--------------------------------------------------------------------------------------------------
// AIEnableStockMidB
//--------------------------------------------------------------------------------------------------
bool AIEnableStockMidB (int player, string peonType, int count, bool veryEasy, int time, int nextState) {
AIEnableStock(player);
if (veryEasy) {
AIVeryEasyHarvest(player, peonType, count);
}
if (AIGetTime() < time) {
return true;
}
AIGenericStock(player, nextState, e_mainSubState_GndA);
AISetFlag(player, e_flagsScouting, true);
AISetFlag(player, e_flagsClearObs, true);
return false;
}
bool AIEnableVeryEasyStockMidB (int player, string peonType, int count) {
return AIEnableStockMidB(player, peonType, count, true, 1200, e_mainState_Late0);
}
bool AIEnableEasyStockMidB (int player, string peonType, int count) {
return AIEnableStockMidB(player, peonType, count, false, 1130, e_mainState_Late1);
}
bool AIEnableMediumStockMidB (int player, string peonType, int count) {
return AIEnableStockMidB(player, peonType, count, false, 1060, e_mainState_Late2);
}
bool AIEnableHardStockMidB (int player, string peonType, int count) {
return AIEnableStockMidB(player, peonType, count, false, 990, e_mainState_Late3);
}
//==================================================================================================
// LATE
//==================================================================================================
//--------------------------------------------------------------------------------------------------
// AIEnableStockLate
//--------------------------------------------------------------------------------------------------
static bool AIEnableStockLate (int player, string peonType, int count, int time) {
AIEnableStock(player);
AIVeryEasyHarvest(player, peonType, count);
if (AIGetTime() % time < 5) {
return true;
}
AIWaveMerge(player, c_waveMain, c_waveAttack);
AISetAttackState(player, e_attackState_Attack);
AIResetUserData(player);
return false;
}
bool AIEnableVeryEasyStockLate (int player, string peonType, int count) {
return AIEnableStockLate(player, peonType, count, 300);
}
bool AIEnableEasyStockLate (int player, string peonType, int count) {
return AIEnableStockLate(player, peonType, count, 280);
}
bool AIEnableMediumStockLate (int player, string peonType, int count) {
return AIEnableStockLate(player, peonType, count, 260);
}
bool AIEnableHardStockLate (int player, string peonType, int count) {
return AIEnableStockLate(player, peonType, count, 240);
}
//==================================================================================================
// OTHER
//==================================================================================================
//--------------------------------------------------------------------------------------------------
// AIPickFrom2
//--------------------------------------------------------------------------------------------------
string AIPickFrom2 (string a, string b) {
int roll = RandomInt(1,2);
if (roll == 1) {
return a;
}
return b;
}
//--------------------------------------------------------------------------------------------------
// AIPickFrom3
//--------------------------------------------------------------------------------------------------
string AIPickFrom3 (string a, string b, string c) {
int roll = RandomInt(1,3);
if (roll == 1) {
return a;
}
if (roll == 2) {
return b;
}
return c;
}
//--------------------------------------------------------------------------------------------------
// AISetStockUserData
//--------------------------------------------------------------------------------------------------
void AISetStockUserData (int player) {
int index = 1;
while (index <= 10) {
AISetStock(player, AIGetUserInt(player, index), AIGetUserString(player, index));
index = index + 1;
}
}
//==================================================================================================
// TECH
//==================================================================================================
//--------------------------------------------------------------------------------------------------
// TerranTechUp
//--------------------------------------------------------------------------------------------------
void TerranTechUp (int player, int tier) {
AISetStock( player, 1, c_TB_Barracks );
AISetStock( player, 1, c_TB_Refinery );
AISetStock( player, 1, c_TB_BarracksTechLab );
if (tier >= 2) {
AISetStock( player, 1, c_TB_Factory );
AISetStock( player, 1, c_TB_FactoryTechLab );
if (tier >= 3) {
AISetStock( player, 1, c_TB_Starport );
AISetStock( player, 1, c_TB_StarportTechLab );
}
}
AISetStock( player, 1, c_TB_EngineeringBay );
if (tier >= 2) {
AISetStock( player, 1, c_TB_SensorTower );
AISetStock( player, 1, c_TB_GhostAcademy );
AISetStock( player, 1, c_TB_MercCompound );
if (tier >= 3) {
AISetStock( player, 1, c_TB_Armory );
if (tier >= 4) {
AISetStock( player, 1, c_TB_FusionCore );
}
}
}
}
//--------------------------------------------------------------------------------------------------
// ZergTechUp
//--------------------------------------------------------------------------------------------------
void ZergTechUp (int player, int tier) {
AISetStock( player, 1, c_ZB_SpawningPool );
AISetStock( player, 1, c_ZB_Extractor );
AISetStock( player, 1, c_ZB_EvolutionChamber );
AISetStock( player, 1, c_ZB_HydraliskDen );
AISetStock( player, 1, c_ZR_HydraliskSpeed );
if (tier >= 2) {
AISetStock( player, 1, c_ZR_OverseerSpeed );
AISetStock( player, 1, c_ZB_BanelingNest );
if (tier >= 3) {
AISetStock( player, 1, c_ZB_RoachWarren );
AISetStock( player, 1, c_ZB_Spire );
AISetStock( player, 1, c_ZB_InfestationPit );
if (tier >= 4) {
AISetStock( player, 1, c_ZR_OverlordTransport );
AISetStock( player, 1, c_ZB_UltraliskCavern );
AISetStock( player, 1, c_ZB_LurkerDen );
AISetStock( player, 1, c_ZB_GreaterSpire );
}
}
}
}
//--------------------------------------------------------------------------------------------------
// ProtossTechUp
//--------------------------------------------------------------------------------------------------
void ProtossTechUp (int player, int tier) {
AISetStock( player, 1, c_PB_Gateway );
AISetStock( player, 1, c_PB_Forge );
AISetStock( player, 1, c_PB_Assimilator );
if (tier >= 3) {
AISetStock( player, 1, c_PB_RoboticsFacility );
AISetStock( player, 1, c_PB_Stargate );
AISetStock( player, 1, c_PB_TwilightCouncil );
if (tier >= 4) {
AISetStock( player, 1, c_PB_TemplarArchives );
AISetStock( player, 1, c_PB_RoboticsBay );
AISetStock( player, 1, c_PB_DarkShrine );
AISetStock( player, 1, c_PB_FleetBeacon );
}
}
}
Protoss0.galaxy
//==================================================================================================
// Protoss Melee Very Easy
//==================================================================================================
static void LateGround (int player);
//--------------------------------------------------------------------------------------------------
// ProtossOpenGnd0
//--------------------------------------------------------------------------------------------------
void ProtossOpenGnd0 (int player) {
AIClearStock(player);
AISetStock( player, 1, c_PB_Nexus );
AISetStock( player, 8, c_PU_Probe );
AISetStock( player, 1, c_PB_Pylon );
// around 100 resources in about 2 units
AISetStock( player, 1, c_PU_Zealot );
ProtossTechUp(player, 1);
if (AIEnableVeryEasyStockOpen(player, c_PU_Probe)) {
return;
}
// around 300 resources in about 3 unit
AIAddStringInt(player, c_PU_Stalker, 1);
AIAddStringInt(player, AIPickFrom2(c_PU_Zealot, c_PU_Disruptor), 1);
}
//--------------------------------------------------------------------------------------------------
// ProtossMidGndA
//--------------------------------------------------------------------------------------------------
static void ProtossMidGndA (int player) {
AIClearStock(player);
AIDefaultEconomy(player, c_PB_Nexus, c_PB_Assimilator, c_PB_Pylon, c_PU_Probe, 8, c_stockAlways);
if (AISawCloakedUnit(player)) {
AISetStock( player, 2, c_PB_PhotonCannon );
AISetStock( player, 1, c_PU_Observer );
}
AISetStockUserData(player);
ProtossTechUp(player, 2);
if (AIEnableVeryEasyStockMidA(player, c_PU_Probe, 4)) {
return;
}
// around 600 resources in about 4 unit
AIAddStringInt(player, c_PU_Stalker, 1);
AIAddStringInt(player, AIPickFrom2(c_PU_Zealot, c_PU_Disruptor), 1);
}
//--------------------------------------------------------------------------------------------------
// ProtossMidGndB
//--------------------------------------------------------------------------------------------------
static void ProtossMidGndB (int player) {
AIClearStock(player);
AIDefaultEconomy(player, c_PB_Nexus, c_PB_Assimilator, c_PB_Pylon, c_PU_Probe, 8, c_stockAlways);
if (AISawCloakedUnit(player)) {
AISetStock( player, 2, c_PB_PhotonCannon );
AISetStock( player, 1, c_PU_Observer );
}
AISetStockUserData(player);
ProtossTechUp(player, 3);
if (AIEnableVeryEasyStockMidB(player, c_PU_Probe, 4)) {
return;
}
// around 900 resources in about 5 unit
LateGround(player);
}
//--------------------------------------------------------------------------------------------------
// LateGround
//--------------------------------------------------------------------------------------------------
static void LateGround (int player) {
AIAddStringInt(player, c_PU_Stalker, 1);
AIAddStringInt(player, c_PU_Disruptor, 1);
AIAddStringInt(player, AIPickFrom2(c_PU_Zealot, c_PU_Stalker), 1);
AIAddStringInt(player, AIPickFrom2(c_PU_Zealot, c_PU_Disruptor), 1);
}
//--------------------------------------------------------------------------------------------------
// LateGnd
//--------------------------------------------------------------------------------------------------
static void LateGnd (int player) {
AIClearStock(player);
AIDefaultEconomy(player, c_PB_Nexus, c_PB_Assimilator, c_PB_Pylon, c_PU_Probe, 8, c_stockAlways);
AIDefaultExpansion(player, c_PB_Nexus, 6000, 0, c_expandDefault);
AISetStockUserData(player);
AISetStock( player, 4, c_PU_Observer );
AISetStock( player, 1, c_PU_WarpPrism );
ProtossTechUp(player, 4);
AISetStock( player, 4, c_PU_Observer );
if (AIEnableVeryEasyStockLate(player, c_TU_SCV, 4)) {
return;
}
LateGround(player);
}
//--------------------------------------------------------------------------------------------------
// ProtossOpenAir0
//--------------------------------------------------------------------------------------------------
void ProtossOpenAir0 (int player) {
AIClearStock(player);
AISetStock( player, 1, c_PB_Nexus );
AISetStock( player, 8, c_PU_Probe );
AISetStock( player, 1, c_PB_Pylon );
AISetStock( player, 1, c_PB_Assimilator );
AISetStock( player, 1, c_PB_Gateway );
AISetStock( player, 1, c_PB_CyberneticsCore );
AISetStock( player, 1, c_PB_Stargate );
AISetStock( player, 1, c_PU_VoidRay );
AISetStock( player, 2, c_PU_Stalker );
AIEnableStock(player);
//stock 3
//---------------------------------------------------------
if (AITechCount(player, c_PU_VoidRay, c_techCountCompleteOnly) < 1) {
return;
}
AIWaveMerge(player, c_waveMain, c_waveAttack);
AISetAttackState(player, e_attackState_Attack);
AISetMainState(player, e_mainState_Mid1, e_mainSubState_AirA);
}
//--------------------------------------------------------------------------------------------------
// ProtossMidAirA
//--------------------------------------------------------------------------------------------------
static void ProtossMidAirA (int player) {
AIClearStock(player);
AIDefaultEconomy(player, c_PB_Nexus, c_PB_Assimilator, c_PB_Pylon, c_PU_Probe, 8, c_stockAlways);
AISetStock( player, 2, c_PU_Stalker );
AISetStock( player, 1, c_PU_VoidRay );
AISetStock( player, 2, c_PB_Pylon );
AISetStock( player, 1, c_PB_RoboticsFacility );
AISetStock( player, 1, c_PU_Phoenix );
AISetStock( player, 1, c_PU_Observer );
AISetStock( player, 1, c_PU_WarpPrism );
AISetStock( player, 2, c_PU_VoidRay );
AISetStock( player, 1, c_PB_Forge );
AIEnableStock(player);
//---------------------------------------------------------
if (AIGetTime() < 700) {
return;
}
AIWaveMerge(player, c_waveMain, c_waveAttack);
AISetAttackState(player, e_attackState_Attack);
AISetMainState(player, e_mainState_Mid1, e_mainSubState_AirB);
}
//--------------------------------------------------------------------------------------------------
// ProtossMidAirB
//--------------------------------------------------------------------------------------------------
static void ProtossMidAirB (int player) {
AIClearStock(player);
AIDefaultEconomy(player, c_PB_Nexus, c_PB_Assimilator, c_PB_Pylon, c_PU_Probe, 8, c_stockAlways);
AIDefaultExpansion(player, c_PB_Nexus, 6000, 1000, c_expandDefault);
AISetStock( player, 2, c_PU_Stalker );
AISetStock( player, 1, c_PU_VoidRay );
AISetStock( player, 2, c_PB_Pylon );
AISetStock( player, 1, c_PU_Phoenix );
AISetStock( player, 1, c_PU_Observer );
AISetStock( player, 1, c_PU_WarpPrism );
AISetStock( player, 3, c_PU_VoidRay );
AISetStock( player, 2, c_PU_Observer );
AISetStock( player, 2, c_PU_Phoenix );
AISetStock( player, 3, c_PB_PhotonCannon );
AIEnableStock(player);
//---------------------------------------------------------
if (AIGetTime() < 1200) {
return;
}
AIWaveMerge(player, c_waveMain, c_waveAttack);
AISetAttackState(player, e_attackState_Attack);
AISetMainState(player, e_mainState_Late1, e_mainSubState_AirA);
AISetFlag(player, e_flagsScouting, true);
AISetFlag(player, e_flagsClearObs, true);
}
//--------------------------------------------------------------------------------------------------
// LateAir
//--------------------------------------------------------------------------------------------------
static void LateAir (int player) {
AIClearStock(player);
AIDefaultEconomy(player, c_PB_Nexus, c_PB_Assimilator, c_PB_Pylon, c_PU_Probe, 8, c_stockAlways);
AIDefaultExpansion(player, c_PB_Nexus, 6000, 1000, c_expandDefault);
AISetStock( player, 2, c_PU_Stalker );
AISetStock( player, 1, c_PU_VoidRay );
AISetStock( player, 2, c_PB_Pylon );
AISetStock( player, 1, c_PU_Phoenix );
AISetStock( player, 1, c_PU_Observer );
AISetStock( player, 1, c_PU_WarpPrism );
AISetStock( player, 3, c_PU_VoidRay );
AISetStock( player, 2, c_PU_Observer );
AISetStock( player, 2, c_PU_Phoenix );
AISetStock( player, 1, c_PU_Carrier );
AISetStock( player, 4, c_PU_Observer );
AIEnableStock(player);
//---------------------------------------------------------
if (AIGetTime() % 300 > 5) {
return;
}
AIWaveMerge(player, c_waveMain, c_waveAttack);
AISetAttackState(player, e_attackState_Attack);
AISetFlag(player, e_flagsScouting, true);
AISetFlag(player, e_flagsClearObs, true);
}
//--------------------------------------------------------------------------------------------------
// ProtossMid0
//--------------------------------------------------------------------------------------------------
void ProtossMid0 (int player) {
int mainSubState = AIState(player, e_mainSubState);
if (mainSubState == e_mainSubState_GndA) { ProtossMidGndA(player); }
else if (mainSubState == e_mainSubState_GndB) { ProtossMidGndB(player); }
else if (mainSubState == e_mainSubState_AirA) { ProtossMidAirA(player); }
else if (mainSubState == e_mainSubState_AirB) { ProtossMidAirB(player); }
else { ErrorMeleeScript(player, "Invalid Mid mainSubState"); }
}
//--------------------------------------------------------------------------------------------------
// ProtossLate0
//--------------------------------------------------------------------------------------------------
void ProtossLate0 (int player) {
int mainSubState = AIState(player, e_mainSubState);
if (mainSubState == e_mainSubState_GndA) { LateGnd(player); }
else if (mainSubState == e_mainSubState_AirA) { LateAir(player); }
else { ErrorMeleeScript(player, "Invalid Late mainSubState"); }
}
Protoss.galaxy
//==================================================================================================
// Protoss Melee AI
//==================================================================================================
include "TriggerLibs/Protoss0"
//--------------------------------------------------------------------------------------------------
// Counter-Attack Units
//--------------------------------------------------------------------------------------------------
static void InitCounters (int player) {
//xxx lots of old data -- needs to be totally redone
// versus Protoss
AICounterUnit(player, c_PB_PhotonCannon, 0.40, c_PU_Immortal );
AICounterUnit(player, c_PU_Zealot, 1.00, c_PU_Zealot );
AICounterUnit(player, c_PU_Stalker, 1.00, c_PU_Zealot );
AICounterUnit(player, c_PU_Immortal, 2.00, c_PU_Zealot );
AICounterUnit(player, c_PU_Disruptor, 0.75, c_PU_Zealot );
AICounterUnit(player, c_PU_HighTemplar, 1.00, c_PU_Stalker );
AICounterUnit(player, c_PU_DarkTemplar, 2.00, c_PU_Zealot );
AICounterUnit(player, c_PU_Archon, 1.00, c_PU_Immortal );
AICounterUnit(player, c_PU_Colossus, 1.00, c_PU_Immortal );
AICounterUnit(player, c_PU_VoidRay, 1.50, c_PU_Phoenix );
AICounterUnit(player, c_PU_Phoenix, 0.40, c_PU_Carrier );
AICounterUnit(player, c_PU_Carrier, 1.67, c_PU_VoidRay );
// versus Terran
AICounterUnit(player, c_TB_Bunker, 0.40, c_PU_Immortal );
AICounterUnit(player, c_TU_Marine, 0.50, c_PU_Zealot );
AICounterUnit(player, c_TU_Reaper, 1.00, c_PU_Zealot );
AICounterUnit(player, c_TU_Marauder, 1.00, c_PU_Zealot );
AICounterUnit(player, c_TU_Ghost, 1.00, c_PU_Stalker );
AICounterUnit(player, c_TU_Hellion, 0.25, c_PU_Immortal );
AICounterUnit(player, c_TU_SiegeTank_Alias, 2.00, c_PU_Zealot );
AICounterUnit(player, c_TU_Thor, 3.00, c_PU_Zealot );
AICounterUnit(player, c_TU_Viking_Alias, 1.00, c_PU_Zealot );
AICounterUnit(player, c_TU_Viking_Alias, 0.50, c_PU_Phoenix );
AICounterUnit(player, c_TU_Banshee, 0.50, c_PU_Phoenix );
AICounterUnit(player, c_TU_BattlecruiserClass, 2.00, c_PU_VoidRay );
// versus Zerg
AICounterUnit(player, c_ZB_SpineCrawler, 0.33, c_PU_Immortal );
AICounterUnit(player, c_ZU_Zergling, 0.25, c_PU_Zealot );
AICounterUnit(player, c_ZU_Roach, 0.80, c_PU_Stalker );
AICounterUnit(player, c_ZU_Hydralisk, 0.50, c_PU_Stalker );
AICounterUnit(player, c_ZU_Lurker, 1.00, c_PU_Immortal );
AICounterUnit(player, c_ZU_Infestor, 0.50, c_PU_Stalker );
AICounterUnit(player, c_ZU_Ultralisk, 1.00, c_PU_Stalker );
AICounterUnit(player, c_ZU_Mutalisk, 0.80, c_PU_Stalker );
AICounterUnit(player, c_ZU_Corruptor, 0.50, c_PU_Stalker );
AICounterUnit(player, c_ZU_BroodLord, 0.50, c_PU_Phoenix );
}
//--------------------------------------------------------------------------------------------------
// ProtossSubStateName
//--------------------------------------------------------------------------------------------------
string ProtossSubStateName (int state) {
// TODO Call the individual difficulties to return a real substate name
return "-" + IntToString(state) + "-";
}
//--------------------------------------------------------------------------------------------------
// DebugCallbackProt
//--------------------------------------------------------------------------------------------------
void DebugCallbackProt (int player) {
DebugAI("=====PROTOSS=====\n");
DebugMelee(player);
DebugAI("e_mainState = " + MainStateName(AIState(player, e_mainState)) +
", e_mainSubState = " + ProtossSubStateName(AIState(player, e_mainSubState)) +
", e_attackState = " + AttackStateName(AIState(player, e_attackState))
);
}
//--------------------------------------------------------------------------------------------------
// AINewUnitProt
//--------------------------------------------------------------------------------------------------
void AINewUnitProt (int player, unit u) {
int obs;
string type = UnitGetType(u);
// ignored units
//
if (UnitTypeTestAttribute(type, c_unitAttributeStructure)) {
return;
}
if (UnitTypeTestFlag(type, c_unitFlagWorker)) {
return;
}
if (type == c_PU_WarpPrism) {
AIAddToExtraScoutGroup(player, u);
return;
}
// detector
//
if (type == c_PU_Observer) {
AINewDetector(player, u, true);
return;
}
// clear obstacle units
//
if (AIWaveNeedClearObsUnits(player)) {
if (type == c_PU_Zealot || type == c_PU_Stalker || type == c_PU_DarkTemplar) {
AIMergeUnit(player, u, AIWaveGet(player, c_waveClearObs));
return;
}
}
// main wave units
//
AINewUnitDefault(player, u);
}
//--------------------------------------------------------------------------------------------------
// AIGetScoutProt
//--------------------------------------------------------------------------------------------------
unit AIGetScoutProt (int player, int index, unit prev) {
unit obs;
if (!AIGetFlag(player, e_flagsScouting)) {
return c_nullUnit;
}
if (UnitGetType(prev) == c_PU_Observer) {
return prev;
}
obs = AIGrabUnit(player, c_PU_Observer, c_prioScout, null);
if (obs) {
return obs;
}
if (prev) {
return prev;
}
if (AIGetFlag(player, e_flagsLateScout)) {
return c_nullUnit;
}
return AIGrabUnit(player, c_PU_Probe, c_prioScout, null);
}
//--------------------------------------------------------------------------------------------------
// AIEarlyDefScoutProt
//--------------------------------------------------------------------------------------------------
unit AIEarlyDefScoutProt (int player, unit prev) {
unit obs;
if (!AIGetFlag(player, e_flagsEarlyDefScout)) {
return c_nullUnit;
}
if (UnitGetType(prev) == c_PU_Observer) {
return prev;
}
obs = AIGrabUnit(player, c_PU_Observer, c_prioScout, null);
if (obs) {
return obs;
}
if (UnitGetType(prev) == c_PU_Zealot) {
return prev;
}
obs = AIGrabUnit(player, c_PU_Zealot, c_prioScout, null);
if (obs) {
return obs;
}
if (prev) {
return prev;
}
return AIGrabUnit(player, c_PU_Probe, c_prioScout, null);
}
//--------------------------------------------------------------------------------------------------
// AIWaveThinkProt
//--------------------------------------------------------------------------------------------------
void AIWaveThinkProt (int player, wave w, int type) {
AIWaveThinkDefault(player, w, type);
}
//--------------------------------------------------------------------------------------------------
// Protoss Init
//--------------------------------------------------------------------------------------------------
static void ProtossInit (int player) {
int state;
InitCounters(player);
AISetNumScouts(player, 1);
AISetFlag(player, e_flagsScouting, false);
AISetFlag(player, e_flagsEarlyDefScout, false);
AISetPowerBuilding(player, c_PB_Pylon);
AITransportSetPanic(player, 0.27); // just below max shield threshold
if (AIGetGroundStartLocs(PlayerStartLocation(player)) > 0) {
state = AIDiffEnum(player, e_mainState_OpenGnd0);
}
else {
state = AIDiffEnum(player, e_mainState_OpenAir0);
}
AISetMainState(player, state, e_mainSubState_Unset);
}
//--------------------------------------------------------------------------------------------------
// AIMeleeProt
//--------------------------------------------------------------------------------------------------
void AIMeleeProt (int player) {
int mainState = AIState(player, e_mainState);
if (mainState == e_mainState_Init) { ProtossInit(player); }
else if (mainState == e_mainState_OpenGnd0) { ProtossOpenGnd0(player); }
//else if (mainState == e_mainState_OpenGnd1) { ProtossOpenGnd1(player); }
//else if (mainState == e_mainState_OpenGnd2) { ProtossOpenGnd2(player); }
//else if (mainState == e_mainState_OpenGnd3) { ProtossOpenGnd3(player); }
//else if (mainState == e_mainState_OpenGnd4) { ProtossOpenGnd4(player); }
//else if (mainState == e_mainState_OpenGnd5) { ProtossOpenGnd5(player); }
else if (mainState == e_mainState_OpenAir0) { ProtossOpenAir0(player); }
//else if (mainState == e_mainState_OpenAir1) { ProtossOpenAir1(player); }
//else if (mainState == e_mainState_OpenAir2) { ProtossOpenAir2(player); }
//else if (mainState == e_mainState_OpenAir3) { ProtossOpenAir3(player); }
//else if (mainState == e_mainState_OpenAir4) { ProtossOpenAir4(player); }
//else if (mainState == e_mainState_OpenAir5) { ProtossOpenAir5(player); }
else if (mainState == e_mainState_Mid0) { ProtossMid0(player); }
//else if (mainState == e_mainState_Mid1) { ProtossMid1(player); }
//else if (mainState == e_mainState_Mid2) { ProtossMid2(player); }
//else if (mainState == e_mainState_Mid3) { ProtossMid3(player); }
//else if (mainState == e_mainState_Mid4) { ProtossMid4(player); }
//else if (mainState == e_mainState_Mid5) { ProtossMid5(player); }
else if (mainState == e_mainState_Late0) { ProtossLate0(player); }
//else if (mainState == e_mainState_Late1) { ProtossLate1(player); }
//else if (mainState == e_mainState_Late2) { ProtossLate2(player); }
//else if (mainState == e_mainState_Late3) { ProtossLate3(player); }
//else if (mainState == e_mainState_Late4) { ProtossLate4(player); }
//else if (mainState == e_mainState_Late5) { ProtossLate5(player); }
else if (mainState == e_mainState_Off) { EndMeleeScript(player); }
else if (mainState == e_mainState_Disabled) { }
else { ErrorMeleeScript(player, "Invalid mainState"); }
}
RequirementsAI.galaxy
//--------------------------------------------------------------------------------------------------
// AI Requirements Functions
//--------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------
// Neutral Units
//--------------------------------------------------------------------------------------------------
const string c_NU_Minerals = "MineralField";
const string c_NU_HighYieldMinerals = "HighYieldMineralField";
const string c_NU_VespeneGeyser = "VespeneGeyser";
//--------------------------------------------------------------------------------------------------
// Protoss Units
//--------------------------------------------------------------------------------------------------
const string c_PU_Archon = "Archon";
const string c_PU_Carrier = "Carrier";
const string c_PU_Colossus = "Colossus";
const string c_PU_DarkTemplar = "DarkTemplar";
const string c_PU_HighTemplar = "HighTemplar";
const string c_PU_Immortal = "Immortal";
const string c_PU_Mothership = "Mothership";
const string c_PU_Disruptor = "Disruptor";
const string c_PU_Observer = "Observer";
const string c_PU_Phoenix = "Phoenix";
const string c_PU_Probe = "Probe";
const string c_PU_Stalker = "Stalker";
const string c_PU_VoidRay = "VoidRay";
const string c_PU_WarpPrism = "WarpPrism";
const string c_PU_WarpPrismPhasing = "WarpPrismPhasing";
const string c_PU_Zealot = "Zealot";
//--------------------------------------------------------------------------------------------------
// Protoss Buildings
//--------------------------------------------------------------------------------------------------
const string c_PB_Assimilator = "Assimilator";
const string c_PB_CyberneticsCore = "CyberneticsCore";
const string c_PB_DarkShrine = "DarkShrine";
const string c_PB_Obelisk = "Obelisk";
const string c_PB_FleetBeacon = "FleetBeacon";
const string c_PB_Forge = "Forge";
const string c_PB_Gateway = "Gateway";
const string c_PB_Nexus = "Nexus";
const string c_PB_PhotonCannon = "PhotonCannon";
const string c_PB_Pylon = "Pylon";
const string c_PB_RoboticsBay = "RoboticsBay";
const string c_PB_RoboticsFacility = "RoboticsFacility";
const string c_PB_Stargate = "Stargate";
const string c_PB_WarpGate = "WarpGate";
const string c_PB_TemplarArchives = "TemplarArchive";
const string c_PB_TwilightCouncil = "TwilightCouncil";
//--------------------------------------------------------------------------------------------------
// Protoss Research Upgrades
//--------------------------------------------------------------------------------------------------
const string c_PR_AirArmor1 = "ProtossAirArmorsLevel1";
const string c_PR_AirArmor2 = "ProtossAirArmorsLevel2";
const string c_PR_AirArmor3 = "ProtossAirArmorsLevel3";
const string c_PR_AirWeapons1 = "ProtossAirWeaponsLevel1";
const string c_PR_AirWeapons2 = "ProtossAirWeaponsLevel2";
const string c_PR_AirWeapons3 = "ProtossAirWeaponsLevel3";
const string c_PR_ColossusRange = "ExtendedThermalLance"; // ExtendedThermalLance
const string c_PR_GroundArmor1 = "ProtossGroundArmorsLevel1";
const string c_PR_GroundArmor2 = "ProtossGroundArmorsLevel2";
const string c_PR_GroundArmor3 = "ProtossGroundArmorsLevel3";
const string c_PR_GroundWeapons1 = "ProtossGroundWeaponsLevel1";
const string c_PR_GroundWeapons2 = "ProtossGroundWeaponsLevel2";
const string c_PR_GroundWeapons3 = "ProtossGroundWeaponsLevel3";
const string c_PR_HighTemplarEnergy = "HighTemplarKhaydarinAmulet"; // KhaydarinAmulet
const string c_PR_HighTemplarPsiStorm = "PsiStormTech"; // PsiStorm
const string c_PR_DisruptorHallucination = "haltech"; // Hallucination
const string c_PR_ObserverSpeed = "ObserverGraviticBooster"; // GraviticBoosters
const string c_PR_Shields1 = "ProtossShieldsLevel1";
const string c_PR_Shields2 = "ProtossShieldsLevel2";
const string c_PR_Shields3 = "ProtossShieldsLevel3";
const string c_PR_StalkerBlink = "BlinkTech"; // Blink
const string c_PR_WarpGateResearch = "WarpGateResearch"; // gateway -> warp gate
const string c_PR_WarpPrismSpeed = "GraviticDrive"; // GraviticDrive
const string c_PR_ZealotCharge = "Charge"; // Charge
//--------------------------------------------------------------------------------------------------
// Terran Units
//--------------------------------------------------------------------------------------------------
const string c_TU_AutoTurret = "AutoTurret";
const string c_TU_Banshee = "Banshee";
const string c_TU_Battlecruiser = "Battlecruiser";
const string c_TU_BattlecruiserClass = "Alias_BattlecruiserClass";
const string c_TU_BattlecruiserDefensive = "BattlecruiserDefensiveMatrix";
const string c_TU_BattlecruiserMissile = "BattlecruiserHurricane";
const string c_TU_BattlecruiserYamato = "BattlecruiserYamato";
const string c_TU_D8Charge = "MagneticMine";
const string c_TU_Ghost = "Ghost";
const string c_TU_Hellion = "Hellion";
const string c_TU_Marauder = "Marauder";
const string c_TU_Marine = "Marine";
const string c_TU_Medivac = "Medivac";
const string c_TU_Raven = "Raven";
const string c_TU_Reaper = "Reaper";
const string c_TU_SCV = "SCV";
const string c_TU_SiegeTank = "SiegeTank";
const string c_TU_SiegeTankSieged = "SiegeTankSieged";
const string c_TU_SiegeTank_Alias = "Alias_SiegeTank";
const string c_TU_Thor = "Thor";
const string c_TU_Viking = "VikingFighter";
const string c_TU_VikingAir = "VikingFighter";
const string c_TU_VikingGnd = "VikingAssault";
const string c_TU_Viking_Alias = "Alias_Viking";
//--------------------------------------------------------------------------------------------------
// Terran Buildings
//--------------------------------------------------------------------------------------------------
const string c_TB_Armory = "Armory";
const string c_TB_Barracks = "Barracks";
const string c_TB_BarracksReactor = "BarracksNuclearReactor";
const string c_TB_BarracksTechLab = "BarracksTechLab";
const string c_TB_Bunker = "Bunker";
const string c_TB_CommandCenter = "CommandCenter";
const string c_TB_CommandCenter_Alias = "Alias_CommandCenter";
const string c_TB_EngineeringBay = "EngineeringBay";
const string c_TB_Factory = "Factory";
const string c_TB_FactoryReactor = "FactoryNuclearReactor";
const string c_TB_FactoryTechLab = "FactoryTechLab";
const string c_TB_FusionCore = "FusionCore";
const string c_TB_GenericTechLab = "TechLab";
const string c_TB_GhostAcademy = "GhostAcademy";
const string c_TB_MercCompound = "MercCompound";
const string c_TB_MissileTurret = "MissileTurret";
const string c_TB_NuclearReactor = "NuclearReactor";
const string c_TB_OrbitalCommand = "OrbitalCommand";
const string c_TB_PlanetaryFortress = "PlanetaryFortress";
const string c_TB_Refinery = "Refinery";
const string c_TB_SensorTower = "SensorTower";
const string c_TB_Starport = "Starport";
const string c_TB_StarportReactor = "StarportNuclearReactor";
const string c_TB_StarportTechLab = "StarportTechLab";
const string c_TB_SupplyDepot = "SupplyDepot";
const string c_TB_SupplyDepot_Alias = "Alias_SupplyDepot";
//--------------------------------------------------------------------------------------------------
// Terran Research Upgrades
//--------------------------------------------------------------------------------------------------
const string c_TR_BansheeCloak = "BansheeCloak"; // CloakingField
const string c_TR_BattlecruiserEnergy = "ColossalReactor"; // ColossalReactor
const string c_TR_BuildingArmor = "TerranBuildingArmor";
const string c_TR_BunkerSpace = "NeosteelFrame"; // NeosteelFrame
const string c_TR_GhostCloak = "PersonalCloaking"; // PersonalCloaking
const string c_TR_GhostEnergy = "GhostMoebiusReactor"; // MoebiusReactor
const string c_TR_HellionDamage = "HighCapacityBarrels"; // InfernalPreIgniter
const string c_TR_InfantryArmor1 = "TerranInfantryArmorsLevel1";
const string c_TR_InfantryArmor2 = "TerranInfantryArmorsLevel2";
const string c_TR_InfantryArmor3 = "TerranInfantryArmorsLevel3";
const string c_TR_InfantryWeapons1 = "TerranInfantryWeaponsLevel1";
const string c_TR_InfantryWeapons2 = "TerranInfantryWeaponsLevel2";
const string c_TR_InfantryWeapons3 = "TerranInfantryWeaponsLevel3";
const string c_TR_MarineShield = "ShieldWall"; // ShieldWall
const string c_TR_MarineStimPack = "StimPack"; // StimPack
const string c_TR_MedivacEnergy = "MedivacCaduceusReactor"; // CaduceusReactor
const string c_TR_MissileTurretRange = "TerranDefenseRangeBonus"; // DefenseRangeBonus
const string c_TR_RavenEnergy = "TitanReactor"; // TitanReactor
const string c_TR_RavenMissiles = "HunterSeeker"; // HunterSeekerMissiles
const string c_TR_ReaperSpeed = "ReaperSpeed"; // Reaper Speed Upgrade
const string c_TR_ShipPlating1 = "TerranShipArmorsLevel1";
const string c_TR_ShipPlating2 = "TerranShipArmorsLevel2";
const string c_TR_ShipPlating3 = "TerranShipArmorsLevel3";
const string c_TR_ShipWeapons1 = "TerranShipWeaponsLevel1";
const string c_TR_ShipWeapons2 = "TerranShipWeaponsLevel2";
const string c_TR_ShipWeapons3 = "TerranShipWeaponsLevel3";
const string c_TR_SiegeTankSiege = "SiegeTech"; // SiegeTech
const string c_TR_VehiclePlating1 = "TerranVehicleArmorsLevel1";
const string c_TR_VehiclePlating2 = "TerranVehicleArmorsLevel2";
const string c_TR_VehiclePlating3 = "TerranVehicleArmorsLevel3";
const string c_TR_VehicleWeapons1 = "TerranVehicleWeaponsLevel1";
const string c_TR_VehicleWeapons2 = "TerranVehicleWeaponsLevel2";
const string c_TR_VehicleWeapons3 = "TerranVehicleWeaponsLevel3";
//--------------------------------------------------------------------------------------------------
// Zerg Units
//--------------------------------------------------------------------------------------------------
const string c_ZU_Baneling = "Baneling";
const string c_ZU_BanelingEgg = "BanelingEgg";
const string c_ZU_Broodling = "Broodling";
const string c_ZU_Changeling = "Changeling";
const string c_ZU_ChangelingZealot = "ChangelingZealot";
const string c_ZU_ChangelingZergling = "ChangelingZergling";
const string c_ZU_ChangelingZerglingWings = "ChangelingZerglingWings";
const string c_ZU_ChangelingMarineShield = "ChangelingMarineShield";
const string c_ZU_ChangelingMarine = "ChangelingMarine";
const string c_ZU_Cocoon = "MutaliskCocoon";
const string c_ZU_Corruptor = "Corruptor";
const string c_ZU_CreepTumor = "CreepTumor";
const string c_ZU_Drone = "Drone";
const string c_ZU_Hydralisk = "Hydralisk";
const string c_ZU_Infestor = "Infestor";
const string c_ZU_InfestedTerran = "InfestedTerran";
const string c_ZU_InfestedTerranEgg = "InfestedTerransEggPlacement";
const string c_ZU_Larva = "Larva";
const string c_ZU_Lurker = "Lurker";
const string c_ZU_LurkerEgg = "LurkerEgg";
const string c_ZU_Mantaling = "SwarmGuardianSpawn";
const string c_ZU_Mutalisk = "Mutalisk";
const string c_ZU_Overlord = "Overlord";
const string c_ZU_Overlord_Alias = "Alias_Overlord";
const string c_ZU_OverlordCocoon = "OverlordCocoon";
const string c_ZU_Overseer = "Overseer";
const string c_ZU_Queen = "Queen";
const string c_ZU_Roach = "Roach";
const string c_ZU_BroodLord = "BroodLord";
const string c_ZU_Ultralisk = "Ultralisk";
const string c_ZU_Zergling = "Zergling";
//----------------------------------------------------------------------------------------------------
// Zerg Buildings
//--------------------------------------------------------------------------------------------------
const string c_ZB_BanelingNest = "BanelingNest";
const string c_ZB_CreepTumor = "CreepTumorBurrowed";
const string c_ZB_EvolutionChamber = "EvolutionChamber";
const string c_ZB_Extractor = "Extractor";
const string c_ZB_GreaterSpire = "GreaterSpire";
const string c_ZB_Hatchery = "Hatchery";
const string c_ZB_Hatchery_Alias = "Alias_Hatchery";
const string c_ZB_Hive = "Hive";
const string c_ZB_HydraliskDen = "HydraliskDen";
const string c_ZB_HydraliskDen_Alias = "Alias_HydraliskDen";
const string c_ZB_InfestationPit = "InfestationPit";
const string c_ZB_Lair = "Lair";
const string c_ZB_Lair_Alias = "Alias_Lair";
const string c_ZB_LurkerDen = "LurkerDen";
const string c_ZB_NydusNetwork = "NydusNetwork";
const string c_ZB_NydusWorm = "NydusCanal";
const string c_ZB_RoachWarren = "RoachWarren";
const string c_ZB_SpawningPool = "SpawningPool";
const string c_ZB_SpineCrawler = "SpineCrawler";
const string c_ZB_SpineCrawlerUp = "SpineCrawlerUprooted";
const string c_ZB_Spire = "Spire";
const string c_ZB_Spire_Alias = "Alias_Spire";
const string c_ZB_SporeCrawler = "SporeCrawler";
const string c_ZB_SporeCrawlerUp = "SporeCrawlerUprooted";
const string c_ZB_UltraliskCavern = "UltraliskCavern";
//--------------------------------------------------------------------------------------------------
// Zerg Research Upgrades
//--------------------------------------------------------------------------------------------------
const string c_ZR_Burrow = "Burrow"; // Burrow
const string c_ZR_BanelingSpeed = "CentrificalHooks"; // CentrificalHooks
const string c_ZR_CorruptorAttack = "EnduringCorruption"; // EnduringCorruption
const string c_ZR_FlyerAttacks1 = "ZergFlyerWeaponsLevel1";
const string c_ZR_FlyerAttacks2 = "ZergFlyerWeaponsLevel2";
const string c_ZR_FlyerAttacks3 = "ZergFlyerWeaponsLevel3";
const string c_ZR_FlyerCarapace1 = "ZergFlyerArmorsLevel1";
const string c_ZR_FlyerCarapace2 = "ZergFlyerArmorsLevel2";
const string c_ZR_FlyerCarapace3 = "ZergFlyerArmorsLevel3";
const string c_ZR_GroundCarapace1 = "ZergGroundArmorsLevel1";
const string c_ZR_GroundCarapace2 = "ZergGroundArmorsLevel2";
const string c_ZR_GroundCarapace3 = "ZergGroundArmorsLevel3";
const string c_ZR_HydraliskSpeed = "hydraliskspeed"; // MuscularAugments
const string c_ZR_InfestorEnergy = "MetasynapticNode"; // MetasynapticNode
const string c_ZR_InfestorSpell = "Disease"; // FungalInfestation
const string c_ZR_MeleeAttacks1 = "ZergMeleeWeaponsLevel1";
const string c_ZR_MeleeAttacks2 = "ZergMeleeWeaponsLevel2";
const string c_ZR_MeleeAttacks3 = "ZergMeleeWeaponsLevel3";
const string c_ZR_MissileAttacks1 = "ZergMissileWeaponsLevel1";
const string c_ZR_MissileAttacks2 = "ZergMissileWeaponsLevel2";
const string c_ZR_MissileAttacks3 = "ZergMissileWeaponsLevel3";
const string c_ZR_OverseerSpeed = "overlordspeed"; // PneumatizedCarapace
const string c_ZR_OverlordTransport = "overlordtransport"; // VentralSacks
const string c_ZR_QueenDamagePlague = "RazorTech"; // RazorPlague
const string c_ZR_RoachRegen = "OrganicCarapace"; // OrganicCarapace
const string c_ZR_RoachSpeed = "GlialReconstitution"; // GlialReconstitution
const string c_ZR_ZerglingHaste = "zerglingattackspeed"; // AdrenalGlands
const string c_ZR_ZerglingSpeed = "zerglingmovementspeed"; // MetabolicBoost
RequirementsAI.galaxy < suite
//--------------------------------------------------------------------------------------------------
// Markers
//--------------------------------------------------------------------------------------------------
const string c_MK_Danger = "AI/Tactical/Danger";
const string c_MK_EMP = "Abil/EMP/AI";
const string c_MK_PhaseShift = "Abil/PhaseShift/AI";
const string c_MK_ForceField = "Abil/ForceField/AI";
const string c_MK_FungalGrowth = "Abil/FungalGrowth/AI";
const string c_MK_GameFungalGrowth = "Abil/FungalGrowth";
const string c_MK_GameNeuralParasite = "Abil/NeuralParasite";
const string c_MK_InfestorDisease = "Abil/InfestorDisease/AI";
const string c_MK_Lockdown = "Abil/Lockdown/AI";
const string c_MK_D8Charge = "Abil/D8Charge/AI";
const string c_MK_D8ChargeFlee = "Abil/D8ChargeFlee/AI";
const string c_MK_MissilePods = "Abil/MissilePods/AI";
const string c_MK_LeviathanCharge = "Abil/LeviathanCharge/AI";
const string c_MK_NeuralParasite = "Abil/NeuralParsite/AI";
const string c_MK_PsiStorm = "Abil/PsiStorm/AI";
const string c_MK_GravitonBeam = "Abil/GravitonBeam/AI";
const string c_MK_SapStructure = "Abil/SapStructure/AI";
const string c_MK_Snipe = "Abil/Snipe/AI";
const string c_MK_SeekerMissile = "Abil/HunterSeekerMissile/AI";
const string c_MK_250mmStrikeCannons = "Abil/250mmStrikeCannons/AI";
const string c_MK_UnstableMutation = "Abil/UnstableMutation/AI";
const string c_MK_Yamato = "Abil/Yamato/AI";
//--------------------------------------------------------------------------------------------------
// Buffs
//--------------------------------------------------------------------------------------------------
const string c_BF_FungalGrowth = "FungalGrowth";
const string c_BF_GravitonBeam = "GravitonPrison";
const string c_BF_Lockdown = "LockdownB";
const string c_BF_MutantLarvaTimer = "SpawnMutantLarvaTimer";
const string c_BF_PersonalCloaking = "PersonalCloaking";
const string c_BF_ProbeBuff = "ProtonCharge";
const string c_BF_PsionicShockwave = "PsionicShockwaveBehaviorController";
const string c_BF_Stim = "stim";
const string c_BF_SupplyDrop = "SupplyDrop";
const string c_BF_SwarmInfestation = "SwarmInfestation";
const string c_BF_TemporalBuff = "TemporalRiftUnit";
const string c_BF_UnstableMutation = "UnstableMutation";
//--------------------------------------------------------------------------------------------------
// Effects
//--------------------------------------------------------------------------------------------------
const string c_EF_AcidSporesArea = "AcidSporesSearch";
const string c_EF_BaneBuilding = "BanelingU2";
const string c_EF_BaneUnit = "BanelingU";
const string c_EF_ConsumeDNADamage = "ConsumeDNADamage";
const string c_EF_ConsumeDNAPersistent = "ConsumeDNACP";
const string c_EF_EMPArea = "EMP2A";
const string c_EF_HybridStunArea = "HybridFAoESearch";
const string c_EF_InfestorDiseaseArea = "InfestorDiseaseSearch";
const string c_EF_D8ChargeDmg = "D8ChargeExplodeDamage";
const string c_EF_MissilePodArea = "HurricaneMissileDamage";
const string c_EF_Nuke = "nuke";
const string c_EF_NukeDamage = "nukeDamage";
const string c_EF_OdinBarrageArea = "BarrageSearchArea";
const string c_EF_OmegaStormArea = "OmegaStormSearchArea";
const string c_EF_PlasmaBlastDamage = "HybridCPlasmaBlastDamage";
const string c_EF_ProbeBuffArea = "ProbeBuffSearchArea";
const string c_EF_ProtonChargeSearchArea = "ProtonChargeSearchArea";
const string c_EF_PsionicShockWaveArea = "PsionicShockwaveSearchArea";
const string c_EF_PsiStormArea = "PsiStormSearch";
const string c_EF_SeekerDamage = "HunterSeekerDamage";
const string c_EF_ShockWavePersistent = "PsionicShockwaveCreatePersistent";
const string c_EF_SnipeDamage = "snipeDamage";
const string c_EF_TemporalRiftSearchArea = "TemporalRiftUnitSearchArea";
const string c_EF_250mmStrikeCannonsDamage = "250mmStrikeCannonsDamage";
const string c_EF_250mmStrikeCannonsPersistent= "250mmStrikeCannonsCreatePersistent";
const string c_EF_Transfusion = "Transfusion";
const string c_EF_YamatoDamage = "YamatoU";
const string c_EF_VortexArea = "VortexSearchArea";
const string c_EF_LeviathanChargeDamage = "LeviathanChargeU";
const string c_EF_LeviathanCharge = "LeviathanCharge";
const string c_EF_ZergVortexArea = "ZergVortexSearchArea";
//--------------------------------------------------------------------------------------------------
// Weapons
//--------------------------------------------------------------------------------------------------
const string c_WE_AutoTurret = "AutoTurret";
const string c_WE_Reaper = "Reaper";
const string c_WE_SiegeTankSieged = "SiegeTankSieged";
const string c_WE_SpineCrawler = "SpineCrawler";
const string c_WE_VikingFighter = "VikingFighter";
const string c_WE_InfestedTerran = "InfestedTerran";
//--------------------------------------------------------------------------------------------------
// Abilities
//--------------------------------------------------------------------------------------------------
const string c_AB_Move = "move";
const string c_AB_Follow = "move";
const string c_AB_AcidSpores = "AcidSpores";
const string c_AB_AssaultMode = "AssaultMode";
const string c_AB_Attack = "attack";
const string c_AB_AutoTurret = "AutoTurret";
const string c_AB_Blink = "Blink";
const string c_AB_BuildFighter = "CarrierHangar";
const string c_AB_BansheeCloak = "BansheeCloak";
const string c_AB_BurrowBanelingDown = "BurrowBanelingDown";
const string c_AB_BurrowBanelingUp = "BurrowBanelingUp";
const string c_AB_BurrowDroneDown = "BurrowDroneDown";
const string c_AB_BurrowDroneUp = "BurrowDroneUp";
const string c_AB_BurrowHydraliskDown = "BurrowHydraliskDown";
const string c_AB_BurrowHydraliskUp = "BurrowHydraliskUp";
const string c_AB_BurrowInfestorDown = "BurrowInfestorDown";
const string c_AB_BurrowInfestorUp = "BurrowInfestorUp";
const string c_AB_BurrowLurkerDown = "BurrowLurkerDown";
const string c_AB_BurrowLurkerUp = "BurrowLurkerUp";
const string c_AB_BurrowRoachDown = "BurrowRoachDown";
const string c_AB_BurrowRoachUp = "BurrowRoachUp";
const string c_AB_BurrowQoBDown = "Val03QueenOfBladesBurrow";
const string c_AB_BurrowQoBUp = "Val03QueenOfBladesUnburrow";
const string c_AB_BurrowQueenDown = "BurrowQueenDown";
const string c_AB_BurrowQueenUp = "BurrowQueenUp";
const string c_AB_BurrowUltraliskDown = "BurrowUltraliskDown";
const string c_AB_BurrowUltraliskUp = "BurrowUltraliskUp";
const string c_AB_BurrowZerglingDown = "BurrowZerglingDown";
const string c_AB_BurrowZerglingUp = "BurrowZerglingUp";
const string c_AB_Changeling = "SpawnChangeling";
const string c_AB_ConsumeDNA = "ConsumeDNA";
const string c_AB_DefensiveMatrix = "DefensiveMatrix";
const string c_AB_DepotLower = "SupplyDepotLower";
const string c_AB_DepotRaise = "SupplyDepotRaise";
const string c_AB_Drill = "RestoreResources";
const string c_AB_EMP = "EMP";
const string c_AB_ArgusLink = "ArgusLink";
const string c_AB_PhaseShift = "PhaseShift";
const string c_AB_FighterMode = "FighterMode";
const string c_AB_ForceField = "ForceField";
const string c_AB_FungalGrowth = "FungalGrowth";
const string c_AB_GenerateCreep = "GenerateCreep";
const string c_AB_GhostCloak = "PersonalCloaking";
const string c_AB_GravitonPrison = "GravitonPrison";
const string c_AB_HybridAoEStun = "HybridFAoEStun";
const string c_AB_HybridBlink = "HybridBlink";
const string c_AB_InfestorDisease = "InfestorDisease";
const string c_AB_InfestedTerrans = "InfestedTerrans";
const string c_AB_Lockdown = "Lockdown";
const string c_AB_D8Charge = "D8Charge";
const string c_AB_MissilePods = "MissilePods";
const string c_AB_NeuralParasite = "NeuralParasite";
const string c_AB_Nuke = "nuke";
const string c_AB_OdinBarrage = "OdinBarrage";
const string c_AB_Overload = "Overload";
const string c_AB_CalldownMULE = "CalldownMULE";
const string c_AB_GravitonBeam = "GravitonBeam";
const string c_AB_PlasmaBlast = "HybridCPlasmaBlast";
const string c_AB_ProbeBuff = "ProtonCharge";
const string c_AB_PsionicShockwave = "PsionicShockwave";
const string c_AB_PsiStorm = "PsiStorm";
const string c_AB_QoBIndignation = "Indignation";
const string c_AB_QoBImplosion = "Implosion";
const string c_AB_QoBOmegaStorm = "OmegaStorm";
const string c_AB_QueenBuild = "QueenBuild";
const string c_AB_Rally = "Rally";
const string c_AB_SapStructure = "SapStructure";
const string c_AB_ScannerSweep = "ScannerSweep";
const string c_AB_SeekerMissile = "HunterSeekerMissile";
const string c_AB_ShieldBattery = "ShieldBattery";
const string c_AB_SiegeMode = "SiegeMode";
const string c_AB_SiegeUnmode = "Unsiege";
const string c_AB_Snipe = "Snipe";
const string c_AB_SpawnMutantLarva = "SpawnMutantLarva";
const string c_AB_SpiderMine = "SpiderMine";
const string c_AB_Stim = "StimPack";
const string c_AB_SupplyDrop = "SupplyDrop";
const string c_AB_SpineCrawlerRoot = "SpineCrawlerRoot";
const string c_AB_SporeCrawlerRoot = "SporeCrawlerRoot";
const string c_AB_SpineCrawlerUproot = "SpineCrawlerUproot";
const string c_AB_SporeCrawlerUproot = "SporeCrawlerUproot";
const string c_AB_SwarmInfestation = "SwarmInfestation";
const string c_AB_TemporalRift = "TemporalRift";
const string c_AB_ThorRebirth = "ThorReborn";
const string c_AB_250mmStrikeCannons = "250mmStrikeCannons";
const string c_AB_Transfusion = "Transfusion";
const string c_AB_UnstableMutation = "UnstableMutation";
const string c_AB_Vortex = "Vortex";
const string c_AB_UpgradeToWarpGate = "UpgradeToWarpGate";
const string c_AB_WormholeTransit = "WormholeTransit";
const string c_AB_WPPhasingMode = "PhasingMode";
const string c_AB_WPTransportMode = "TransportMode";
const string c_AB_WraithCloak = "WraithCloak";
const string c_AB_Yamato = "Yamato";
const string c_AB_LeviathanCharge = "LeviathanCharge";
const string c_AB_ZergVortex = "ZergVortex";
const string c_AB_BunkerChange = "BunkerTransport";
const string c_AB_CommandCenterChange = "CommandCenterTransport";
const int e_AB_TransportLoadUnit = 0;
const int e_AB_TransportUnloadAll = 1;
const int e_AB_TransportUnloadUnit = 3;
const int e_AB_TransportLoadAll = 4;
const string c_AB_Hallucinate = "HighTemplarTrain";
const int e_AB_Hallucinate_Probe = 0;
const int e_AB_Hallucinate_Zealot = 1;
const int e_AB_Hallucinate_Stalker = 2;
const int e_AB_Hallucinate_Immortal = 3;
const int e_AB_Hallucinate_HighTemplar = 4;
const int e_AB_Hallucinate_Archon = 5;
const int e_AB_Hallucinate_VoidRay = 6;
const int e_AB_Hallucinate_Phoenix = 7;
const int e_AB_Hallucinate_WarpPrism = 8;
const int e_AB_Hallucinate_Colossus = 9;
//--------------------------------------------------------------------------------------------------
// Unit Attributes
//--------------------------------------------------------------------------------------------------
const int e_unitAttributeNone = -1;
const int e_unitAttributeLight = 0;
const int e_unitAttributeArmored = 1;
const int e_unitAttributeBiological = 2;
const int e_unitAttributeMechanical = 3;
const int e_unitAttributeRobotic = 4;
const int e_unitAttributePsionic = 5;
const int e_unitAttributeMassive = 6;
const int e_unitAttributeStructure = 7;
const int e_unitAttributeHover = 8;
const int e_unitAttributeHeroic = 9;
//--------------------------------------------------------------------------------------------------
// Object Types
//--------------------------------------------------------------------------------------------------
const int c_objTypeIsInvalid = -1;
const int c_objTypeIsUnit = 0;
const int c_objTypeIsBuilding = 1;
const int c_objTypeIsResearch = 2;
//--------------------------------------------------------------------------------------------------
// AI Get Object Type
//--------------------------------------------------------------------------------------------------
int AIGetObjectType (int player, string objType) {
// override any special cases here
return AIDefaultGetObjectType(player, objType);
}
//--------------------------------------------------------------------------------------------------
// AI Get Maker
//--------------------------------------------------------------------------------------------------
string AIGetMaker (int player, string objType) {
// override any special cases here
return AIDefaultGetMaker(player, objType);
}
//--------------------------------------------------------------------------------------------------
// AI Get First Missing Req
//--------------------------------------------------------------------------------------------------
string AIGetFirstMissingReq (int player, string objType) {
// override any special cases here
return AIDefaultGetFirstMissingReq(player, objType);
}
//--------------------------------------------------------------------------------------------------
// AI Any Unbuilt Reqs
//--------------------------------------------------------------------------------------------------
string AIGetFirstUnfinishedReq (int player, string objType) {
// override any special cases here
return AIDefaultGetFirstUnfinishedReq(player, objType);
}
//--------------------------------------------------------------------------------------------------
// AI Get Full Make Time
//--------------------------------------------------------------------------------------------------
int AIGetFullMakeTime (int player, string objType) {
// override any special cases here
return AIDefaultGetFullMakeTime(player, objType);
}
//--------------------------------------------------------------------------------------------------
// AI Specified Makers
//--------------------------------------------------------------------------------------------------
void AISpecifiedMakers () {
AIReqAddSpecialMaker(c_TU_BattlecruiserDefensive, c_TU_Battlecruiser, "BattlecruiserSpecialize", 0);
AIReqAddSpecialMaker(c_TU_BattlecruiserMissile, c_TU_Battlecruiser, "BattlecruiserSpecialize", 1);
AIReqAddSpecialMaker(c_TU_BattlecruiserYamato, c_TU_Battlecruiser, "BattlecruiserSpecialize", 3);
}
//--------------------------------------------------------------------------------------------------
// Declare the Nuke Constant Setting here
//--------------------------------------------------------------------------------------------------
void AISetNukeConstants (int player);
TacticalAI.galaxy
//==================================================================================================
// Tactical AI Functions
//==================================================================================================
//==================================================================================================
//
// Tactical AI System Known Issues:
// * Marker Bug With Abilities that are missiles (Assigned to Andy / Dave)
// - i.e. infestor, hunter seeker missile
// - marker dissapears after cast, but before effect, so multiple casters may cast on the same unit
// * Some Infestor / Overseer spells need AI (Assigned to Dave, Bob, or Andy & David Kim)
// - An untested version of the old fungal growth and acid spores were started and then abandoned
// when abilities changed fundamentally (see TactZergAI)
// - An untested version of the old unstable mutation was started and then abandoned when the ability
// changed fundamentally (see TactZergAI)
// - Check with David Kim, who said that these are 90% sure going to change again.
// * Infested Marine / Civilian Burrow (Task assigned to Andy Bond)
// - AI Commented out for Burrow
// - Needs to be placed back in after Andy fixes support to turn off abilities on Campaign
// - Maps with infested units need to be tested
//
// Wish List
// * Need equivalent of AITime from synapses for tactical ai thinks
// - scale it back when too much thinking, scale it up when too little
//
//==================================================================================================
//--------------------------------------------------------------------------------------------------
// CATALOG ACCESSOR CONSTANTS
//--------------------------------------------------------------------------------------------------
const string c_fieldAmount = "Amount";
const string c_fieldAreaRadius0 = "AreaArray[0].Radius";
const string c_fieldAreaRadius1 = "AreaArray[1].Radius";
const string c_fieldAreaRadius2 = "AreaArray[2].Radius";
const string c_fieldAreaFraction0 = "AreaArray[0].Fraction";
const string c_fieldAreaFraction1 = "AreaArray[1].Fraction";
const string c_fieldAreaFraction2 = "AreaArray[2].Fraction";
const string c_fieldAttrStructure = "AttributeBonus[Structure]";
const string c_fieldAttrArmored = "AttributeBonus[Armored]";
const string c_fieldAttrPsionic = "AttributeBonus[Psionic]";
const string c_fieldAttrLight = "AttributeBonus[Light]";
const string c_fieldDrainFactor = "DrainVitalCostFactor";
const string c_fieldEffectChange0 = "VitalArray[0].Change";
const string c_fieldEffectChange1 = "VitalArray[1].Change";
const string c_fieldEffectChange2 = "VitalArray[2].Change";
const string c_fieldEnergyCost = "Cost[0].Vital[Energy]";
const string c_fieldEnergyMax = "EnergyMax";
const string c_fieldFilters = "SearchFilters";
const string c_fieldMinRange = "MinimumRange";
const string c_fieldModification0 = "Modification.VitalRegenArray[Energy]";
const string c_fieldPeriodCount = "PeriodCount";
const string c_fieldRadius = "Radius";
const string c_fieldRadiusBonus0 = "AreaArray[0].RadiusBonus";
const string c_fieldRange0 = "Range[0]";
const string c_fieldRange = "Range";
const string c_fieldSightDawn = "Sight";
const string c_fieldTargetFilters = "TargetFilters";
const string c_fieldTargetFiltersAB = "TargetFilters[0]";
const string c_fieldTargetFilters0 = "ValidatorArray[0].value.value";
//--------------------------------------------------------------------------------------------------
// TACTICAL API
//
// Usage:
// filter = AIFilter(owner);
// ...set various filter information...
// newGroup = AIGetFilterGroup(filter, oldGroup);
//--------------------------------------------------------------------------------------------------
native aifilter AIFilter (int player);
native void AISetFilterAlliance (aifilter filter, int want);
native void AISetFilterMarker (aifilter filter, int min, int max, marker m);
native void AISetFilterSelf (aifilter filter, unit exclude);
native void AISetFilterBits (aifilter filter, unitfilter uf);
native void AISetFilterRange (aifilter filter, unit center, fixed radius);
native void AISetFilterLife (aifilter filter, fixed min, fixed max);
native void AISetFilterLifeLost (aifilter filter, fixed min, fixed max);
native void AISetFilterLifePercent (aifilter filter, fixed min, fixed max);
native void AISetFilterLifeSortReference (aifilter filter, fixed value, fixed distance);
native void AISetFilterLifeMod (aifilter filter, int type, fixed mod);
native void AISetFilterLifePerMarker (aifilter filter, fixed each, marker m);
native void AISetFilterShields (aifilter filter, fixed min, fixed max);
native void AISetFilterPlane (aifilter filter, int plane);
native void AISetFilterCanAttackEnemy (aifilter filter, int enemyGroundCount, int enemyAirCount);
native void AISetFilterCanAttackAlly (aifilter filter, bool groundAllies, bool airAllies);
native void AISetFilterBehaviorCount (aifilter filter, int minBehavior, int maxBehavior, string behaviorType);
const fixed c_minDamageFraction = .5;
const fixed c_distanceFromDamage = .2;
const int c_noMarkersMin = 0;
const int c_noMarkersMax = 0;
const int c_noBehaviorMin = 0;
const int c_noBehaviorMax = 0;
const int c_noMax = -1;
const int c_noMin = -1;
const bool c_groundAlliesNearby = true;
const bool c_airAlliesNearby = true;
const fixed c_noThreshold = 0;
native unitgroup AIGetFilterGroup (aifilter filter, unitgroup group);
const fixed c_maxDistanceToMinerals = 10;
native unitgroup AIFilterCasters (unitgroup group);
native unitgroup AIFilterPathable (unitgroup group, point inStart);
native unitgroup AIFilterGathering (unitgroup group, int inResource, fixed distance);
native fixed AIUnitGroupStrength (unitgroup inGroup);
native fixed AIAllyEnemyRatio (int player, point p, unitfilter filter, fixed range, fixed minThreshold);
native bool AIIsFollowingUnit (unit aiUnit, string unitType);
native int AIGetPlayerGroup (unitgroup inGroup);
native bool AINearbyPlaneTest (point p, int player, fixed range, int inPlane, int inAlliance);
//--------------------------------------------------------------------------------------------------
// *** CATALOG INFO ***
//--------------------------------------------------------------------------------------------------
string AIAbilityStr (int player, string entry, string field) {
return CatalogFieldValueGet(c_gameCatalogAbil, entry, field, player);
}
string AIEffectStr (int player, string entry, string field) {
return CatalogFieldValueGet(c_gameCatalogEffect, entry, field, player);
}
string AIWeaponStr (int player, string entry, string field) {
return CatalogFieldValueGet(c_gameCatalogWeapon, entry, field, player);
}
string AIUnitStr (int player, string entry, string field) {
return CatalogFieldValueGet(c_gameCatalogUnit, entry, field, player);
}
string AIBehaviorStr (int player, string entry, string field) {
return CatalogFieldValueGet(c_gameCatalogBehavior, entry, field, player);
}
fixed AIAbilityFixed (int player, string entry, string field) {
return StringToFixed(AIAbilityStr(player, entry, field));
}
fixed AIEffectFixed (int player, string entry, string field) {
return StringToFixed(AIEffectStr(player, entry, field));
}
fixed AIWeaponFixed (int player, string entry, string field) {
return StringToFixed(AIWeaponStr(player, entry, field));
}
fixed AIUnitFixed (int player, string entry, string field) {
return StringToFixed(AIUnitStr(player, entry, field));
}
fixed AIBehaviorFixed (int player, string entry, string field) {
return StringToFixed(AIBehaviorStr(player, entry, field));
}
int AIAbilityInt (int player, string entry, string field) {
return StringToInt(AIAbilityStr(player, entry, field));
}
int AIEffectInt (int player, string entry, string field) {
return StringToInt(AIEffectStr(player, entry, field));
}
int AIWeaponInt (int player, string entry, string field) {
return StringToInt(AIWeaponStr(player, entry, field));
}
int AIUnitInt (int player, string entry, string field) {
return StringToInt(AIUnitStr(player, entry, field));
}
int AIBehaviorInt (int player, string entry, string field) {
return StringToInt(AIBehaviorStr(player, entry, field));
}
unitgroup AIAbilityGroup (int player, string entry, unitgroup base) {
return UnitGroupFilter(null, c_playerAny, base,
UnitFilterStr(AIAbilityStr(player, entry, c_fieldTargetFiltersAB)), 0);
}
unitgroup AIEffectGroup (int player, string entry, unitgroup base) {
return UnitGroupFilter(null, c_playerAny, base,
UnitFilterStr(AIEffectStr(player, entry, c_fieldFilters)), 0);
}
unitgroup AIWeaponGroup (int player, string entry, unitgroup base) {
return UnitGroupFilter(null, c_playerAny, base,
UnitFilterStr(AIWeaponStr(player, entry, c_fieldTargetFilters)), 0);
}
//--------------------------------------------------------------------------------------------------
native void AISetTacticalAttackTargetPoint (unit u, point t);
native void AISetTacticalAttackTargetUnit (unit u, unit t);
//--------------------------------------------------------------------------------------------------
// AIUnitGroupGetValidOrder
//--------------------------------------------------------------------------------------------------
const bool c_forwards = true;
const bool c_backwards = false;
// Loops over a unitgroup forwards or backwards until finding a unit that makes a valid order.
//
native order AIUnitGroupGetValidOrder(unitgroup inGroup, order inOrder, unit caster, bool forwards);
//--------------------------------------------------------------------------------------------------
// AICampSkirDiffTest
//--------------------------------------------------------------------------------------------------
bool AICampSkirDiffTest (int player, int campMinDiff, int skirMinDiff) {
if (AIIsCampaign(player)) {
return PlayerDifficulty(player) >= campMinDiff;
}
return PlayerDifficulty(player) >= skirMinDiff;
}
//--------------------------------------------------------------------------------------------------
// AICastStandard
//--------------------------------------------------------------------------------------------------
bool AICastStandard (unit aiUnit, order ord, marker mark, bool retreat) {
if (!UnitOrderIsValid(aiUnit, ord)) {
return false;
}
AICast(aiUnit, ord, mark, retreat);
return true;
}
//--------------------------------------------------------------------------------------------------
// AIMarker
//--------------------------------------------------------------------------------------------------
marker AIMarker (unit aiUnit, string name) {
marker mark = MarkerCastingUnit(name, aiUnit);
MarkerSetMatchFlag(mark, c_markerMatchLink, true);
MarkerSetMatchFlag(mark, c_markerMatchCasterPlayer, true);
return mark;
}
//--------------------------------------------------------------------------------------------------
// AISpellPriority
//--------------------------------------------------------------------------------------------------
void AISpellPriority (unitgroup src, unitgroup dst) {
// TODO: units that currently have an order should be prioritized lower than idle units since
// they're already doing something.
// this simple AI just takes the first unit plus all following that share the same command
//
int count = UnitGroupCount(src, c_unitCountAll);
unit first = UnitGroupUnit(src, 1);
unit test;
UnitGroupAdd(dst, first);
while (count > 1) {
test = UnitGroupUnit(src, count);
count = count - 1;
if (AISameCommand(first, test)) {
UnitGroupAdd(dst, test);
}
}
}
//--------------------------------------------------------------------------------------------------
// AIIsAttackOrder
//--------------------------------------------------------------------------------------------------
bool AIIsAttackOrder (order o) {
return StringEqual(AbilityCommandGetAbility(OrderGetAbilityCommand(o)), c_AB_Attack, true);
}
// These should both be replaced by the xml/code versions CTargetFindRallyPoint
////--------------------------------------------------------------------------------------------------
//// AIThinkSetRallyDefault
////--------------------------------------------------------------------------------------------------
//void AIThinkSetRallyDefault (int player, unit aiUnit, int commandIndex) {
// point rally;
// order ord;
//
// // Don't set rally points on campaign
// if (AIIsCampaign(player)) {
// return;
// }
//
// if (UnitRallyPointTargetCount(aiUnit, commandIndex + 1) != 0) {
// return;
// }
//
// ord = AICreateOrder(player, c_AB_Rally, commandIndex);
// if (!UnitOrderIsValid(aiUnit, ord)) {
// return;
// }
//
// rally = AIWaveTargetGatherOPoint(player, c_townMax);
// if (UnitRallyPointTargetPoint(aiUnit, 1, 1) == rally) {
// return;
// }
//
// OrderSetTargetPoint(ord, rally);
// AICast(aiUnit, ord, c_noMarker, c_castHold);
//}
//
////--------------------------------------------------------------------------------------------------
//// AIThinkSetRallyWorker
////--------------------------------------------------------------------------------------------------
//void AIThinkSetRallyWorker (int player, unit aiUnit, int commandIndex) {
// order ord;
// unitgroup findResults;
//
// if (UnitRallyPointTargetCount(aiUnit, commandIndex + 1) != 0) {
// return;
// }
//
// ord = AICreateOrder(player, c_AB_Rally, commandIndex);
// if (!UnitOrderIsValid(aiUnit, ord)) {
// return;
// }
//
// findResults = AIFindUnits(0, c_NU_Minerals, UnitGetPosition(aiUnit), 8, c_noMaxCount);
// if (UnitGroupCount(findResults, c_unitCountAll) == 0) {
// findResults = AIFindUnits(0, c_NU_HighYieldMinerals, UnitGetPosition(aiUnit), 8, c_noMaxCount);
// if (UnitGroupCount(findResults, c_unitCountAll) == 0) {
// OrderSetTargetPoint(ord, UnitGetPosition(aiUnit));
// AICast(aiUnit, ord, c_noMarker, c_castHold);
// return;
// }
// }
//
// OrderSetTargetUnit(ord, UnitGroupUnit(findResults, 1));
// AICast(aiUnit, ord, c_noMarker, c_castHold);
//}
//--------------------------------------------------------------------------------------------------
// PointAlongLine
//--------------------------------------------------------------------------------------------------
point PointAlongLine (point from, point toward, fixed distance) {
return PointWithOffsetPolar(from, distance, AngleBetweenPoints(toward, from));
}
//--------------------------------------------------------------------------------------------------
// Set Nuke Constants
//--------------------------------------------------------------------------------------------------
void AISetNukeConstants (int player) {
AISetNukeGhost(player, c_TU_Ghost);
AISetNukeNukeEffect(player, c_EF_Nuke);
AISetNukeCloak(player, c_TR_GhostCloak);
AISetNukeNukeAbilLink(player, c_AB_Nuke);
AISetNukeCloakAbilLink(player, c_AB_GhostCloak);
AISetNukeCloakRegenRate(player, AIBehaviorFixed(player, c_BF_PersonalCloaking, c_fieldModification0));
AISetNukeCloakCost(player, AIAbilityFixed(player, c_AB_GhostCloak, c_fieldEnergyCost));
AISetNukeNukeCastTime(player, 20);
AISetNukeDamage(player, AIEffectFixed(player, c_EF_NukeDamage, c_fieldAmount), AIEffectFixed(player, c_EF_NukeDamage, c_fieldAttrStructure));
AISetNukeRadiusClose(player, AIEffectFixed(player, c_EF_NukeDamage, c_fieldAreaRadius0), AIEffectFixed(player, c_EF_NukeDamage, c_fieldAreaFraction0));
AISetNukeRadiusMedium(player, AIEffectFixed(player, c_EF_NukeDamage, c_fieldAreaRadius1), AIEffectFixed(player, c_EF_NukeDamage, c_fieldAreaFraction1));
AISetNukeRadiusFar(player, AIEffectFixed(player, c_EF_NukeDamage, c_fieldAreaRadius2), AIEffectFixed(player, c_EF_NukeDamage, c_fieldAreaFraction2));
}
//--------------------------------------------------------------------------------------------------
// AISetDefaultCombatFlags
//--------------------------------------------------------------------------------------------------
void AISetDefaultCombatFlags (int player, bool isMelee) {
int group1;
int group2;
if (isMelee) {
group1 = c_skirVeryEasy;
group2 = c_skirHard;
}
else {
group1 = c_campBeginner;
group2 = c_campExpert;
}
AICombatTargetProduction (player, AIDiffThreshold(player, c_combatDisable, group1, c_combatEnable));
AICombatTargetDropOffs (player, AIDiffThreshold(player, c_combatDisable, group1, c_combatEnable));
AICombatTargetFood (player, AIDiffThreshold(player, c_combatDisable, group1, c_combatEnable));
AICombatTargetActiveProduction (player, AIDiffThreshold(player, c_combatDisable, group1, c_combatEnable));
AICombatTargetSelfThreats (player, AIDiffThreshold(player, c_combatDisable, group1, c_combatEnable));
AICombatTargetCurrent (player, AIDiffThreshold(player, c_combatDisable, group1, c_combatEnable));
AICombatTargetAir (player, AIDiffThreshold(player, c_combatDisable, group1, c_combatEnable));
AICombatTargetMovers (player, AIDiffThreshold(player, c_combatDisable, group1, c_combatEnable));
AICombatTargetInAttackRange (player, AIDiffThreshold(player, c_combatDisable, group1, c_combatEnable));
AICombatTargetThreats (player, AIDiffThreshold(player, c_combatDisable, group1, c_combatEnable));
AICombatTargetAttackers (player, AIDiffThreshold(player, c_combatDisable, group1, c_combatEnable));
AICombatTargetSpecial (player, AIDiffThreshold(player, c_combatDisable, group1, c_combatEnable));
AICombatAvoidNonThreats (player, AIDiffThreshold(player, c_combatDisable, group1, c_combatEnable));
AICombatAvoidTimedUnits (player, AIDiffThreshold(player, c_combatDisable, group1, c_combatEnable));
AICombatAvoidWeakUnits (player, AIDiffThreshold(player, c_combatDisable, group1, c_combatEnable));
AICombatAvoidDisabledUnits (player, AIDiffThreshold(player, c_combatDisable, group1, c_combatEnable));
AICombatTargetWorkers (player, AIDiffThreshold(player, c_combatDisable, group2, c_combatEnable));
AICombatTargetAllyThreats (player, AIDiffThreshold(player, c_combatDisable, group2, c_combatEnable));
AICombatTargetInjuries (player, AIDiffThreshold(player, c_combatDisable, group2, c_combatEnable));
AICombatTargetHealers (player, AIDiffThreshold(player, c_combatDisable, group2, c_combatEnable));
AICombatTargetSiege (player, AIDiffThreshold(player, c_combatDisable, group2, c_combatEnable));
}
//--------------------------------------------------------------------------------------------------
include "TriggerLibs/TactProtAI"
include "TriggerLibs/TactTerrAI"
include "TriggerLibs/TactZergAI"
TactProtAI.galaxy
//--------------------------------------------------------------------------------------------------
// *** Disruptor ***
//--------------------------------------------------------------------------------------------------
const fixed c_forceFieldRadius = 3;
const fixed c_disruptorRange = 11;
fixed AIRangeDisruptor (int player, unit aiUnit) {
return c_disruptorRange;
}
order AIForceField (int player, unit aiUnit, unitgroup scanGroup, fixed scanRange, marker m) {
order ord;
order enemyOrd;
unitgroup enemyGroup;
unitgroup friendlyGroup;
unitfilter filter;
unit enemyUnit;
unit friendlyUnit;
unit possibleTargetUnit;
unit bestTargetUnit = null;
point myPos = UnitGetPosition(aiUnit);
fixed myFacing = UnitGetFacing(aiUnit);
point forceFieldTarget;
int forceFieldMaxRadius = 5;
int priorityFound = 10;
bool emergencyCast = false;
// Loop control
int enemyCount = 0;
int friendlyCount = 0;
// Enemy test values
int enemyVit = 0;
point enemyPos;
fixed enemyFacing = 0;
// Friendly test values
int friendlyVit = 0;
fixed friendlyFacing = 0;
// Do not proceed if the order is invalid for some reason
ord = AICreateOrder(player, c_AB_ForceField, 0);
if (!UnitOrderIsValid(aiUnit, ord)) {
return ord;
}
// Is there a threat in the area
enemyGroup = UnitGroupFilterThreat(scanGroup, aiUnit, null, 0);
enemyCount = UnitGroupCount(enemyGroup, c_unitCountAlive);
if (enemyCount <= 0) {
return ord;
}
// Assess life and energy
// A good energy buffer is 50 energy left over. 100 energy is needed to cast in any battle
// If our life is less than 50%, use the energy buffer.
if (UnitGetPropertyInt(aiUnit, c_unitPropEnergy, c_unitPropCurrent) <= 100) {
if (UnitGetPropertyInt(aiUnit, c_unitPropLifePercent, c_unitPropCurrent) <= 50) {
emergencyCast = true;
}
}
// Setup a friendly filter
filter = UnitFilter(0,0,0,0);
UnitFilterSetState(filter, c_targetFilterSelf, c_unitFilterRequired);
UnitFilterSetState(filter, c_targetFilterAlly, c_unitFilterRequired);
UnitFilterSetState(filter, c_targetFilterUncommandable, c_unitFilterExcluded);
UnitFilterSetState(filter, c_targetFilterWorker, c_unitFilterExcluded);
UnitFilterSetState(filter, c_targetFilterUnderConstruction, c_unitFilterExcluded);
UnitFilterSetState(filter, c_targetFilterStructure, c_unitFilterExcluded);
// *** Scan the area for the following, set priority unit when found ***
// Priority 1: A friendly unit close to death, who has a melee enemy close by
// Priority 2: An enemy unit close to death, who has a friendly unit close by
// Priority 3: A friendly ranged unit who has a melee enemy close by
// Priority 4: Enemy near me
// Priority 5: Any Enemy close to death, facing away from me
//
// Scan enemies
while (enemyCount > 0) {
enemyUnit = UnitGroupUnit(enemyGroup, enemyCount);
enemyCount = enemyCount - 1;
// Get enemy data
enemyVit = UnitGetPropertyInt(enemyUnit, c_unitPropLifePercent, c_unitPropCurrent);
enemyFacing = UnitGetFacing(enemyUnit);
enemyPos = UnitGetPosition(enemyUnit);
enemyOrd = UnitOrder(enemyUnit, 0);
friendlyGroup = UnitGroup(null, c_playerAny, RegionCircle(enemyPos, forceFieldMaxRadius), filter, 0);
friendlyCount = UnitGroupCount(friendlyGroup, c_unitCountAll);
// Scan friends near enemyUnit
while (friendlyCount > 0) {
friendlyUnit = UnitGroupUnit(friendlyGroup, friendlyCount);
friendlyCount = friendlyCount - 1;
// Get friendly data
friendlyVit = UnitGetPropertyInt(friendlyUnit, c_unitPropLifePercent, c_unitPropCurrent);
if (UnitMarkerCount(friendlyUnit, m) > 0) {
continue;
}
// Test Priority Target 4 first, if we are in a state of saving ourself
if (emergencyCast) {
if (PointsInRange(myPos, enemyPos, forceFieldMaxRadius)) {
priorityFound = 1;
bestTargetUnit = friendlyUnit;
break;
}
}
// Test Priority Target 1
else if (friendlyVit < 25) {
priorityFound = 1;
bestTargetUnit = friendlyUnit;
break;
}
// Test Priority Target 2
else if (priorityFound > 2 && enemyVit < 25) { // && Test for non-ranged only
priorityFound = 2;
possibleTargetUnit = enemyUnit;
}
// Test Priority Target 3
else if (false) { //priorityFound > 3
// Not really able to test for this yet
// Need to determine if the unit in question has a ranged weapon
}
// Test Priority Target 4
else if (priorityFound > 4 && PointsInRange(myPos, enemyPos, forceFieldMaxRadius)) {
priorityFound = 4;
possibleTargetUnit = enemyUnit;
}
// Test Priority Target 5
else if (priorityFound > 5 && enemyVit < 25 && enemyFacing - myFacing < 90) {
priorityFound = 5;
possibleTargetUnit = enemyUnit;
}
// More tests here
}
if (bestTargetUnit) {
break;
}
}
if (bestTargetUnit != null) {
if (possibleTargetUnit) {
bestTargetUnit = possibleTargetUnit;
}
}
// Do some other things here, like if we are targetting a retreating enemy (priority 5)
// adjust the target offset a bit ahead of the unit based on facing.
// We would want this for priority 3 as well when that is valid.
forceFieldTarget = UnitGetPosition(bestTargetUnit);
if (!forceFieldTarget) {
return null;
}
OrderSetTargetPoint(ord, forceFieldTarget);
return ord;
}
//--------------------------------------------------------------------------------------------------
static bool Hallucinate (int player, unit aiUnit, unitgroup scanGroup) {
point here;
order ord;
// wait until fighting 5+ enemy units
//
if (!AIIsAttackOrder(UnitOrder(aiUnit, 0))) {
return false;
}
if (UnitGroupCount(scanGroup, c_unitCountAlive) < 5) {
return false;
}
ord = AICreateOrder(player, c_AB_Hallucinate, e_AB_Hallucinate_Zealot);
if (!UnitOrderIsValid(aiUnit, ord)) {
return false;
}
here = UnitGetPosition(aiUnit);
if (AINearbyUnits(player, c_PU_Zealot, here, 5, 2)) {
AICast(aiUnit, ord, c_noMarker, c_castHold);
return true;
}
if (AINearbyUnits(player, c_PU_Stalker, here, 5, 2)) {
ord = AICreateOrder(player, c_AB_Hallucinate, e_AB_Hallucinate_Stalker);
AICast(aiUnit, ord, c_noMarker, c_castHold);
return true;
}
if (AINearbyUnits(player, c_PU_Immortal, here, 5, 2)) {
ord = AICreateOrder(player, c_AB_Hallucinate, e_AB_Hallucinate_Immortal);
AICast(aiUnit, ord, c_noMarker, c_castHold);
return true;
}
return false;
}
//--------------------------------------------------------------------------------------------------
static bool ForceField (int player, unit aiUnit, unitgroup scanGroup) {
return false;
// forceFieldMarker = MarkerCastingUnit(c_MK_Snipe, aiUnit);
// MarkerSetMatchFlag(forceFieldMarker, c_markerMatchLink, true);
// MarkerSetMismatchFlag(forceFieldMarker, c_markerMatchId, true);
//
// ord = AIForceField(player, aiUnit, scanGroup, c_disruptorRange, forceFieldMarker);
//
// if (ord) {
// AICast(aiUnit, ord, forceFieldMarker, c_castHold);
// return;
// }
}
//--------------------------------------------------------------------------------------------------
static bool MolDisplacer (int player, unit aiUnit, unitgroup scanGroup) {
return false;
}
//--------------------------------------------------------------------------------------------------
void AIThinkDisruptor (int player, unit aiUnit, unitgroup scanGroup) {
if (Hallucinate(player, aiUnit, scanGroup)) {
return;
}
if (ForceField(player, aiUnit, scanGroup)) {
return;
}
MolDisplacer(player, aiUnit, scanGroup);
}
//--------------------------------------------------------------------------------------------------
// *** DARK PYLON ***
//--------------------------------------------------------------------------------------------------
fixed AIRangeObelisk (int player, unit aiUnit) {
return AIAbilityFixed(player, c_AB_ShieldBattery, c_fieldRange0) + 1;
//return MaxF(AIAbilityFixed(player, c_AB_ArgusLink, c_fieldRange0),
// AIAbilityFixed(player, c_AB_ShieldBattery, c_fieldRange0)) + 1
// ;
}
////--------------------------------------------------------------------------------------------------
//order ProtonCharge (int player, unit aiUnit, unitgroup scanGroup) {
// order ord;
// point loc;
// unitgroup probeGroup;
// aifilter filter;
//
// ord = AITacticalOrder(player, aiUnit, c_AB_ProbeBuff);
// if (!UnitOrderIsValid(aiUnit, ord)) {
// return null;
// }
//
// probeGroup = AIFindUnits(
// player,
// c_PU_Probe,
// UnitGetPosition(aiUnit),
// AIAbilityFixed(player, c_AB_ProbeBuff, c_fieldRange0) + AIEffectFixed(player, c_EF_ProtonChargeSearchArea, c_fieldAreaRadius0),
// c_noMaxCount
// );
//
// // Filter for probes that are gathering, but not buffed.
// //
// filter = AIFilter(player);
// AISetFilterBits(filter, UnitFilterStr(AIAbilityStr(player, c_AB_ProbeBuff, c_fieldTargetFiltersAB)));
// AISetFilterBehaviorCount(filter, c_noBehaviorMin, c_noBehaviorMax, c_BF_ProbeBuff);
// probeGroup = AIGetFilterGroup(filter, probeGroup);
// probeGroup = AIFilterGathering(probeGroup, c_resourceTypeMinerals, c_maxDistanceToMinerals);
//
// loc = AIBestTargetPoint(
// probeGroup,
// 5, // min hits
// 50, // damage base. set to whatever since don't care about score.
// 0, // score. set to zero since only care about hits.
// AIEffectFixed(player, c_EF_ProtonChargeSearchArea, c_fieldAreaRadius0),
// UnitGetPosition(aiUnit),
// AIAbilityFixed(player, c_AB_ProbeBuff, c_fieldRange0),
// c_unitAttributeNone
// );
//
// if (loc == null) {
// return null;
// }
//
// OrderSetTargetPoint(ord, loc);
// if (!UnitOrderIsValid(aiUnit, ord)) {
// return null;
// }
// return ord;
//}
////--------------------------------------------------------------------------------------------------
//const fixed c_argusLinkMax = 150;
//
//order ArgusLink (int player, unit aiUnit, unitgroup scanGroup) {
// order ord;
// unitgroup group;
// aifilter filter;
//
// fixed reserve;
// fixed highTemplarMaxEnergy;
// fixed energy;
// fixed argusLinkMin;
//
// ord = AITacticalOrder(player, aiUnit, c_AB_ArgusLink);
// if (!UnitOrderIsValid(aiUnit, ord)) {
// return null;
// }
//
// // Find the minimum amount of mana the high templar must have in order to
// // save 25 mana for buffing probes.
// //
// reserve = AIAbilityFixed(player, c_AB_ProbeBuff, c_fieldEnergyCost);
// highTemplarMaxEnergy = AIUnitFixed(player, c_PU_HighTemplar, c_fieldEnergyMax);
// energy = UnitGetPropertyFixed(aiUnit, c_unitPropEnergy, c_unitPropCurrent);
// argusLinkMin = highTemplarMaxEnergy + (reserve - energy) / AIAbilityFixed(player, c_AB_ArgusLink, c_fieldDrainFactor);
//
// if (argusLinkMin > c_argusLinkMax) {
// return null;
// }
//
// // For now, just recharge high templars.
// //
// group = AIFindUnits(player, c_PU_HighTemplar, UnitGetPosition(aiUnit), AIRangeObelisk(player, aiUnit), c_noMaxCount);
// filter = AIFilter(player);
// AISetFilterBits(filter, UnitFilterStr(AIAbilityStr(player, c_AB_ArgusLink, c_fieldTargetFiltersAB)));
// AISetFilterAlliance(filter, c_playerGroupAlly);
// AISetFilterEnergy(filter, argusLinkMin, c_argusLinkMax);
// AISetFilterLife(filter, c_noMin, c_noMax); // Give the energy to the highest life high templar first.
//
// group = AIGetFilterGroup(filter, group);
// return AIUnitGroupGetValidOrder(group, ord, aiUnit, c_forwards);
//}
////--------------------------------------------------------------------------------------------------
//const fixed c_shieldBatteryMaxShields = 15;
//const int c_batteryMinEnergyNoHostiles = 100;
//const int c_batteryMinEnergyHostiles = 6;
//
//order ShieldBattery (int player, unit aiUnit, unitgroup scanGroup) {
// order ord;
// aifilter allyFilter;
// unitgroup group;
// region r;
// int energy = UnitGetPropertyInt(aiUnit, c_unitPropEnergy, c_unitPropCurrent);
//
// // It looks silly to cast every time the shield battery gains one energy, so require some low minimum threshold.
// //
// if (energy < c_batteryMinEnergyHostiles) {
// return null;
// }
//
// ord = AITacticalOrder(player, aiUnit, c_AB_ShieldBattery);
// if (!UnitOrderIsValid(aiUnit, ord)) {
// return null;
// }
//
// // If there are no enemy units, and energy is too low, don't heal.
// //
// r = RegionCircle(UnitGetPosition(aiUnit), AIRangeObelisk(player, aiUnit));
// if (UnitGroupCount(UnitGroupAlliance(player, c_unitAllianceEnemy, r, null, c_noMaxCount), c_unitCountAll) == 0 && energy > c_batteryMinEnergyNoHostiles) {
// return null;
// }
//
// // Otherwise, look for allies with low shields to heal.
// //
// group = AIFindUnits(player, null, UnitGetPosition(aiUnit), AIRangeObelisk(player, aiUnit), c_noMaxCount);
// allyFilter = AIFilter(player);
// AISetFilterBits(allyFilter, UnitFilterStr(AIAbilityStr(player, c_AB_ShieldBattery, c_fieldTargetFiltersAB)));
// AISetFilterAlliance(allyFilter, c_playerGroupAlly);
// AISetFilterShields(allyFilter, c_noMin, c_shieldBatteryMaxShields);
//
// group = AIGetFilterGroup(allyFilter, group);
// return AIUnitGroupGetValidOrder(group, ord, aiUnit, c_forwards);
//}
TactProtAI.galaxy < suite
//--------------------------------------------------------------------------------------------------
void AIThinkObelisk (int player, unit aiUnit, unitgroup scanGroup) {
//// 1. Buff harvesting probes
//// 2. If unit shields low & enemies nearby, heal it.
//// 3. If high templar nearby, charge mana.
//order ord;
////ord = ProtonCharge(player, aiUnit, scanGroup);
////if (ord != null) {
//// AICast(aiUnit, ord, c_noMarker, c_castHold);
//// return;
////}
////ord = ArgusLink(player, aiUnit, scanGroup);
////if (ord != null) {
//// AICast(aiUnit, ord, c_noMarker, c_castHold);
////}
////ord = ShieldBattery(player, aiUnit, scanGroup);
////if (ord != null) {
//// AICast(aiUnit, ord, c_noMarker, c_castHold);
////}
}
//--------------------------------------------------------------------------------------------------
// *** MOTHERSHIP ***
//--------------------------------------------------------------------------------------------------
fixed AIRangeMothership (int player, unit aiUnit) {
return MaxF(AIAbilityFixed(player, c_AB_Vortex, c_fieldRange0) + 1,
AIAbilityFixed(player, c_AB_TemporalRift, c_fieldRange0) + 1);
}
fixed MinToCastMotherShip (int player) {
//return AIAbilityFixed(player, c_AB_Vortex, c_fieldEnergyCost) + // To Save enough mana for wormhole transit, swap out the commented lines.
// AIAbilityFixed(player, c_AB_WormholeTransit, c_fieldEnergyCost);
return AIAbilityFixed(player, c_AB_Vortex, c_fieldEnergyCost);
}
const fixed c_enemyMultiplierVortex = 1.25;
//--------------------------------------------------------------------------------------------------
order Vortex (int player, unit aiUnit, unitgroup scanGroup) {
point loc;
unitgroup vortexGroup;
order ord = AITacticalOrder(player, aiUnit, c_AB_Vortex);
if (ord == null) {
return null;
}
vortexGroup = AIEffectGroup(player, c_EF_VortexArea, scanGroup);
loc = AIBestTargetPoint(
vortexGroup,
5, // min hits
40, // damage base
4.0, // score
AIEffectFixed(player, c_EF_VortexArea, c_fieldAreaRadius0),
UnitGetPosition(aiUnit),
AIRangeMothership(player, aiUnit),
c_unitAttributeNone
);
if (loc == null) {
return null;
}
OrderSetTargetPoint(ord, loc);
if (!UnitOrderIsValid(aiUnit, ord)) {
return null;
}
return ord;
}
//--------------------------------------------------------------------------------------------------
order TemporalRift (int player, unit aiUnit, unitgroup scanGroup) {
point loc;
order ord = AITacticalOrder(player, aiUnit, c_AB_TemporalRift);
if (ord == null) {
return null;
}
loc = AIBestTargetPoint(
AIEffectGroup(player, c_EF_TemporalRiftSearchArea, scanGroup),
5, // min hits
40, // damage base
3.85, // min score
AIEffectFixed(player, c_EF_TemporalRiftSearchArea, c_fieldAreaRadius0),
UnitGetPosition(aiUnit),
AIRangeMothership(player, aiUnit),
c_unitAttributeNone
);
if (loc == null) {
return null;
}
OrderSetTargetPoint(ord, loc);
if (!UnitOrderIsValid(aiUnit, ord)) {
return null;
}
return ord;
}
//--------------------------------------------------------------------------------------------------
void AIThinkMothership (int player, unit aiUnit, unitgroup scanGroup) {
order ord;
unitfilter f;
fixed allyEnemyRatio;
aifilter filter;
// Make sure to save mana so we use both abilities.
//
if (UnitGetPropertyInt(aiUnit, c_unitPropEnergy, c_unitPropCurrent) < MinToCastMotherShip(player)) {
return;
}
// If a unit already has temporal rift, filter it.
//
filter = AIFilter(player);
AISetFilterBehaviorCount(filter, c_noBehaviorMin, c_noBehaviorMax, c_BF_TemporalBuff);
scanGroup = AIGetFilterGroup(filter, scanGroup);
// Get the ratio of allies to enemies to see if we should cast vortex or temporal rift
//
f = UnitFilterStr("-;Missile,Dead,Stasis,Worker");
allyEnemyRatio = AIAllyEnemyRatio(player, UnitGetPosition(aiUnit), f, AIRangeMothership(player, aiUnit), c_noThreshold);
if (allyEnemyRatio < c_enemyMultiplierVortex) {
ord = Vortex(player, aiUnit, scanGroup);
if (ord != null) {
AICast(aiUnit, ord, c_noMarker, c_castRetreat);
return;
}
}
ord = TemporalRift(player, aiUnit, scanGroup);
if (ord != null) {
AICast(aiUnit, ord, c_noMarker, c_castRetreat);
return;
}
}
//--------------------------------------------------------------------------------------------------
// *** HIGH TEMPLAR ***
//--------------------------------------------------------------------------------------------------
fixed AIRangeHighTemplar (int player, unit aiUnit) {
return AIAbilityFixed(player, c_AB_PhaseShift, c_fieldRange0) + 1;
}
const int c_phaseShiftMinHealth = 425; // carriers and above.
const int c_phaseShiftLowVitMinHealth = 300;
order PhaseShift (int player, unit aiUnit, unitgroup scanGroup, marker mark, bool lowVitality) {
order ord;
aifilter filter;
bool airAllies;
int minVitality;
ord = AITacticalOrder(player, aiUnit, c_AB_PhaseShift);
if (ord == null) {
return null;
}
if (lowVitality) {
minVitality = c_phaseShiftLowVitMinHealth;
}
else {
minVitality = c_phaseShiftMinHealth;
}
// Test to see if we have airborne allies, to determine whether to PhaseShift
// an enemy that only attacks air.
airAllies = AINearbyPlaneTest(UnitGetPosition(aiUnit), player, AIRangeHighTemplar(player, aiUnit), c_planeAir, c_unitAllianceAlly);
filter = AIFilter(player);
AISetFilterBits(filter, UnitFilterStr(AIAbilityStr(player, c_AB_PhaseShift, c_fieldTargetFiltersAB)));
AISetFilterLife(filter, minVitality, c_noMax);
AISetFilterMarker(filter, c_noMarkersMin, c_noMarkersMax, mark);
AISetFilterCanAttackAlly(filter, c_groundAlliesNearby, airAllies);
scanGroup = AIGetFilterGroup(filter, scanGroup);
return AIUnitGroupGetValidOrder(scanGroup, ord, aiUnit, c_forwards);
}
//--------------------------------------------------------------------------------------------------
const fixed c_EnemyMultiplierHighTemplar = 1.25;
const fixed c_MinThreshold = 100.0;
const int c_HighTemplarLowVitPerc = 50;
void UnitGroupTest (unitgroup scanGroup) {
DebugVarInt("group strength", FixedToInt(AIUnitGroupStrength(scanGroup)));
}
void AIThinkHighTemplar (int player, unit aiUnit, unitgroup scanGroup) {
marker mark;
order ord;
bool lowVitality;
unitfilter f;
region r;
unitgroup enemyGroup;
if (AIEvalTacticalData(aiUnit, null)) {
return;
}
// If we already have a psi storm order, ignore any new orders since psi storm is more important.
// If we already have an PhaseShift order, ignore any new PhaseShift orders.
if (UnitOrderHasAbil(aiUnit, c_AB_PhaseShift) || UnitOrderHasAbil(aiUnit, c_AB_PsiStorm)) {
return;
}
// Low Vitality = less than 50%, then use this to escape.
lowVitality = (UnitGetPropertyInt(aiUnit, c_unitPropVitalityPercent, c_unitPropCurrent) < c_HighTemplarLowVitPerc);
if (!lowVitality) {
// Don't cast if the enemy only has 1 unit when we are at full health.
// If we have less than 1.25 * the enemies forces.
f = UnitFilterStr("-;Missile,Dead,Stasis,Worker");
r = RegionCircle(UnitGetPosition(aiUnit), AIRangeHighTemplar(player, aiUnit));
if ((UnitGroupCount(UnitGroupAlliance(player, c_unitAllianceEnemy, r, null, c_noMaxCount), c_unitCountAll) < 2) ||
AIAllyEnemyRatio(player, UnitGetPosition(aiUnit), f, AIRangeHighTemplar(player, aiUnit), c_MinThreshold) > c_EnemyMultiplierHighTemplar) {
return;
}
}
mark = AIMarker(aiUnit, c_MK_PhaseShift);
ord = PhaseShift(player, aiUnit, scanGroup, mark, lowVitality);
if (ord != null) {
AICast(aiUnit, ord, mark, c_castRetreat);
return;
}
}
//--------------------------------------------------------------------------------------------------
void AIThinkGateway (int player, unit aiUnit, unitgroup scanGroup) {
order ord;
if (AIEvalTacticalData(aiUnit, null)) {
return;
}
if (AITechCount(player, c_PR_WarpGateResearch, c_techCountCompleteOnly) == 0) {
return;
}
AISetWantsToUpgrade(aiUnit);
ord = AICreateOrder(player, c_AB_UpgradeToWarpGate, 0);
if (!UnitOrderIsValid(aiUnit, ord)) {
return;
}
AICast(aiUnit, ord, c_noMarker, c_castHold);
}
//--------------------------------------------------------------------------------------------------
// *** WarpPrism ***
//--------------------------------------------------------------------------------------------------
fixed AIRangeWarpPrism (int player, unit aiUnit) {
return 1;
}
//--------------------------------------------------------------------------------------------------
// *** WarpPrism (transport mode) ***
//--------------------------------------------------------------------------------------------------
const fixed c_warpPrismPhaseRange = 1.0;
void AIThinkWarpPrism (int player, unit aiUnit, unitgroup scanGroup) {
order ord = AICreateOrder(player, c_AB_WPPhasingMode, 0);
string type = AIGetBullyType(aiUnit);
if (UnitOrderCount(aiUnit) > 0) {
return;
}
if (!UnitOrderIsValid(aiUnit, ord)) {
return;
}
if (type != c_PU_WarpPrismPhasing) {
return;
}
if (AIGetHomePosition(aiUnit) == c_nullPoint) {
return;
}
if (!PointsInRange(UnitGetPosition(aiUnit), AIGetHomePosition(aiUnit), c_warpPrismPhaseRange)) {
return;
}
AICast(aiUnit, ord, c_noMarker, c_castHold);
}
//--------------------------------------------------------------------------------------------------
// *** WarpPrism (power mode) ***
//--------------------------------------------------------------------------------------------------
void AIThinkWarpPrismPhasing (int player, unit aiUnit, unitgroup scanGroup) {
order ord = AICreateOrder(player, c_AB_WPTransportMode, 0);
string type = AIGetBullyType(aiUnit);
if (UnitOrderCount(aiUnit) > 0) {
return;
}
if (!UnitOrderIsValid(aiUnit, ord)) {
return;
}
if (type == c_PU_WarpPrismPhasing) {
if (AIGetHomePosition(aiUnit) != c_nullPoint) {
if (PointsInRange(UnitGetPosition(aiUnit), AIGetHomePosition(aiUnit), c_warpPrismPhaseRange)) {
// we're supposed to provide power at this point
return;
}
}
}
AICast(aiUnit, ord, c_noMarker, c_castHold);
}
TactTerrAI.galaxy
//--------------------------------------------------------------------------------------------------
// *** THOR ***
//--------------------------------------------------------------------------------------------------
fixed AIRangeThor (int player, unit aiUnit) {
return AIAbilityFixed(player, c_AB_250mmStrikeCannons, c_fieldRange0) + 1;
}
order AIOrder250mmStrikeCannons(int player, unit aiUnit, unitgroup scanGroup, marker mark) {
order ord;
fixed damage;
aifilter filter;
bool airAllies;
ord = AICreateOrder(player, c_AB_250mmStrikeCannons, 0);
if (!UnitOrderIsValid(aiUnit, ord)) {
return null;
}
damage = AIEffectFixed(player, c_EF_250mmStrikeCannonsPersistent, c_fieldPeriodCount) *
AIEffectFixed(player, c_EF_250mmStrikeCannonsDamage, c_fieldAmount)
;
filter = AIFilter(player);
AISetFilterAlliance(filter, c_playerGroupEnemy);
AISetFilterBits(filter, UnitFilterStr(AIAbilityStr(player, c_AB_250mmStrikeCannons, c_fieldTargetFiltersAB)));
AISetFilterRange(filter, aiUnit, AIRangeThor(player, aiUnit));
AISetFilterMarker(filter, c_noMarkersMin, c_noMarkersMax, mark);
AISetFilterLife(filter, damage*c_minDamageFraction, c_noMax);
AISetFilterLifeSortReference(filter, damage, damage*c_distanceFromDamage);
// Filter out units that can't attack allies since this ability is a disable.
//
airAllies = AINearbyPlaneTest(UnitGetPosition(aiUnit),
player,
AIRangeThor(player, aiUnit),
c_planeAir,
c_unitAllianceAlly)
;
AISetFilterCanAttackAlly(filter, c_groundAlliesNearby, airAllies);
// Select starting from the end, which is the target that has health closest to the cannon's damage
//
scanGroup = AIGetFilterGroup(filter, scanGroup);
return AIUnitGroupGetValidOrder(scanGroup, ord, aiUnit, c_backwards);
}
void AIThinkThor (int player, unit aiUnit, unitgroup scanGroup) {
order ord;
marker mark;
// If we already have a cannon order, ignore new orders so that we do not count
// our own marker again, when validating.
//
if (UnitOrderHasAbil(aiUnit, c_AB_250mmStrikeCannons)) {
return;
}
mark = AIMarker(aiUnit, c_MK_250mmStrikeCannons);
ord = AIOrder250mmStrikeCannons(player, aiUnit, scanGroup, mark);
if (ord != null) {
AICast(aiUnit, ord, c_noMarker, c_castHold);
}
}
//--------------------------------------------------------------------------------------------------
// *** GHOST ***
//--------------------------------------------------------------------------------------------------
fixed AIRangeGhost (int player, unit aiUnit) {
return MaxF(AIAbilityFixed(player, c_AB_EMP, c_fieldRange0) + 1,
AIAbilityFixed(player, c_AB_Snipe, c_fieldRange0) + 1);
}
//---------------------------------------------------------------------------------------------
order AIOrderSnipe (int player, unit aiUnit, unitgroup scanGroup, marker mark) {
order ord;
fixed damage;
aifilter filter;
ord = AICreateOrder(player, c_AB_Snipe, 0);
if (!UnitOrderIsValid(aiUnit, ord)) {
return null;
}
damage = AIEffectInt(player, c_EF_SnipeDamage, c_fieldAmount);
filter = AIFilter(player);
AISetFilterAlliance(filter, c_playerGroupEnemy);
AISetFilterBits(filter, UnitFilterStr(AIAbilityStr(player, c_AB_Snipe, c_fieldTargetFiltersAB)));
AISetFilterRange(filter, aiUnit, AIAbilityFixed(player, c_AB_Snipe, c_fieldRange0) + 1);
AISetFilterLifePerMarker(filter, damage, mark);
AISetFilterLifeSortReference(filter, damage, damage*c_distanceFromDamage);
// Select starting from the end, to obtain the target that has health closest to snipe
// damage.
//
scanGroup = AIGetFilterGroup(filter, scanGroup);
return AIUnitGroupGetValidOrder(scanGroup, ord, aiUnit, c_backwards);
}
//
const int c_gameLoopsPerSecond = 16;
const int c_framesPerThink = 12;
const int c_secondsPerSnipe = 4;
const int c_ghostMaxRandom = c_gameLoopsPerSecond * c_secondsPerSnipe / c_framesPerThink;
//---------------------------------------------------------------------------------------------
void AIThinkGhost (int player, unit aiUnit, unitgroup scanGroup) {
// **Cloaking / EMP relocated to XML**
marker mark;
order ord;
int randomVal;
// Add a delay on campaign.
//
if (AIIsCampaign(player)) {
if (RandomInt(0, c_ghostMaxRandom) != 1) {
return;
}
}
if (AIEvalTacticalData(aiUnit, null)) {
return;
}
mark = AIMarker(aiUnit, c_MK_Snipe);
ord = AIOrderSnipe(player, aiUnit, scanGroup, mark); // this modifies scanGroup.
if (ord != null) {
AICast(aiUnit, ord, mark, c_castHold);
return;
}
}
//--------------------------------------------------------------------------------------------------
// *** REAPER ***
//--------------------------------------------------------------------------------------------------
fixed AIRangeReaper (int player, unit aiUnit) {
return AIWeaponFixed(player, c_WE_Reaper, c_fieldRange);
}
const int c_BldgOnlyPercent = 60;
order AIOrderReapMine (int player, unit aiUnit, unitgroup scanGroup, marker mark) {
order ord;
int scanCount;
unit target;
bool bldgOnly;
unitgroup friends;
aifilter filter;
unitfilter f;
int bonus;
// See if this spell can be cast at all.
//
ord = AICreateOrder(player, c_AB_D8Charge, 0);
if (!UnitOrderIsValid(aiUnit, ord)) {
return null;
}
bonus = AIEffectInt(player, c_EF_D8ChargeDmg, c_fieldAttrArmored) * 2;
bldgOnly = (UnitGetPropertyInt(aiUnit, c_unitPropVitalityPercent, c_unitPropCurrent) > c_BldgOnlyPercent);
if (AICampSkirDiffTest(player, c_campAdvanced, c_skirVeryHard)) {
bldgOnly = false;
}
// Get enemies with enough life to be around when the spell goes off.
//
filter = AIFilter(player);
AISetFilterAlliance(filter, c_playerGroupEnemy);
AISetFilterLife(filter, AIEffectInt(player, c_EF_D8ChargeDmg, c_fieldAmount) * 2, c_noMax - bonus);
AISetFilterLifeMod(filter, c_unitAttributeArmored, bonus);
AISetFilterMarker(filter, c_noMarkersMin, c_noMarkersMax, mark);
if (bldgOnly) {
f = UnitFilterStr("Structure;Missile,Dead,Stasis,Worker"); // require buildings.
}
else {
f = UnitFilterStr("-;Missile,Dead,Stasis,Worker"); // default filter.
}
// Pick a building/unit with no allies nearby, starting with lowest health buildings that passed above tests.
//
scanGroup = AIGetFilterGroup(filter, scanGroup);
scanCount = UnitGroupCount(scanGroup, c_unitCountAll);
while (scanCount > 0) {
target = UnitGroupUnit(scanGroup, scanCount);
scanCount = scanCount - 1;
// For now, Reapers are only used as a diversion wave, so we can't target photon cannons.
// Photon cannons are very dangerous to reapers
//
if (UnitGetType(target) == c_PB_PhotonCannon) {
continue;
}
// Check for friendly fire.
//
friends = UnitGroupFilterAlliance(
AIFindUnits(player, null, UnitGetPosition(target), AIEffectFixed(player, c_EF_D8ChargeDmg, c_fieldAreaRadius2), c_noMaxCount),
player,
c_allianceIdPassive,
0
);
if (UnitGroupCount(friends, c_unitCountAlive) > 0) {
continue;
}
// Check target validity.
//
OrderSetTargetUnit(ord, target);
if (UnitOrderIsValid(aiUnit, ord)) {
return ord;
}
}
return null;
}
void AIThinkReaper (int player, unit aiUnit, unitgroup scanGroup) {
// **Reaper AI reproduced in XML**
// Melee AI does not call this AIThink routine.
// Reaper AI is left in TactTerrAI to serve as an example of two different ways to write the same
// AI. To see the xml equivalent of the Reaper AI, look in TacticalData.xml and TargetFindData.xml.
// In general, AI implemented in galaxy scripts will be slower than AI implemented in data.
// If it is convenient to express AI in data, one should do so. In this case, converting reaper AI
// to xml resulted in a 2x performance gain.
//
marker mark = AIMarker(aiUnit, c_MK_D8Charge);
order ord;
scanGroup = UnitGroupFilterPlane(scanGroup, c_planeGround, 0);
ord = AIOrderReapMine(player, aiUnit, scanGroup, mark); // Modifies scanGroup.
if (ord == null) {
return;
}
AICast(aiUnit, ord, mark, c_castRetreat);
}
//--------------------------------------------------------------------------------------------------
// *** BATTLE CRUISER ***
//--------------------------------------------------------------------------------------------------
order AIOrderYamato (int player, unit aiUnit, unitgroup scanGroup, marker mark) {
order ord;
aifilter filter;
fixed damage;
// Only cast as part of an existing offensive.
//
if (!AIIsAttackOrder(UnitOrder(aiUnit, 0))) {
return null;
}
// See if this spell can be cast at all.
//
ord = AICreateOrder(player, c_AB_Yamato, 0);
if (!UnitOrderIsValid(aiUnit, ord)) {
return null;
}
damage = AIEffectFixed(player, c_EF_YamatoDamage, c_fieldAmount);
// Search enemies for those with hit points closest to the damage yamato gun inflicts.
//
filter = AIFilter(player);
AISetFilterAlliance(filter, c_playerGroupEnemy);
AISetFilterLifePerMarker(filter, damage, mark);
AISetFilterLifeSortReference(filter, damage, damage*c_distanceFromDamage);
scanGroup = AIGetFilterGroup(filter, scanGroup);
return AIUnitGroupGetValidOrder(scanGroup, ord, aiUnit, c_backwards);
}
//---------------------------------------------------------------------------------------------
void AIThinkBattleCruiser (int player, unit aiUnit, unitgroup scanGroup) {
// **Defensive Matrix located in TacticalData.xml / ValidatorData.xml**
// **Missile Pods located in TacticalData.xml / TargetFindData.xml**
marker mark;
order ord;
// If we already have a yamato order, ignore new orders so that we do not count
// our own markers again.
if (UnitOrderHasAbil(aiUnit, c_AB_Yamato)) {
return;
}
// This modifies scanGroup, which is Ok.. so long as it is not used elsewhere.
mark = AIMarker(aiUnit, c_MK_Yamato);
ord = AIOrderYamato(player, aiUnit, scanGroup, mark);
if (ord != null) {
AICast(aiUnit, ord, mark, c_castHold);
return;
}
}
//--------------------------------------------------------------------------------------------------
// *** VIKING (ground mode) ***
//--------------------------------------------------------------------------------------------------
fixed AIRangeViking (int player, unit aiUnit) {
return AIWeaponFixed(player, c_WE_VikingFighter, c_fieldRange) + 2;
}
point VikingModeChange (int player, unit aiUnit, unitgroup scanGroup, bool inAssault) {
int scanCount;
int inAir;
int onGround;
int cliffLevel;
int testCliffLevel;
string type = AIGetBullyType(aiUnit);
point here = UnitGetPosition(aiUnit);
point there;
unitgroup scanGroupThreat;
int onGroundThreatCount;
// First, find all units within viking range.
//
scanGroup = UnitGroupFilterRegion(scanGroup, RegionCircle(here, AIRangeViking(player, null)), 0);
inAir = UnitGroupCount(scanGroup, c_unitCountAlive);
// Next, find the number of ground and air units within viking range.
//
scanGroup = UnitGroupFilterPlane(scanGroup, c_planeGround, 0);
onGround = UnitGroupCount(scanGroup, c_unitCountAlive);
inAir = inAir - onGround; // air = all - ground
// If a bully type is set, check to see if we're in the right mode if idle.
if (type != null && onGround == 0 && inAir == 0 && UnitOrderCount(aiUnit) == 0) {
if (type == UnitGetType(aiUnit)) {
return null;
}
else {
return UnitGetPosition(aiUnit);
}
}
// Only pay attention to threats on the ground.
//
scanGroupThreat = UnitGroupFilterThreat(scanGroup, aiUnit, null, 0);
onGroundThreatCount = UnitGroupCount(scanGroupThreat, c_unitCountAlive);
if (inAssault) { // viking is on ground.
// Go to air mode when there's nothing on the ground anymore.
//
if (onGround == 0) {
return UnitGetPosition(aiUnit);
}
// Also, go to air mode when a pack of new air units shows up and we have killed most of the
// ground units.
if (inAir >= onGroundThreatCount + 3 || (inAir > 0 && onGroundThreatCount == 0)) {
return UnitGetPosition(aiUnit);
}
}
else { // viking is in air.
// If air targets remain, finish them off before switching.
//
if (inAir != 0) {
return null;
}
if (onGround > 0) {
cliffLevel = CliffLevel(here);
// Only switch if there is a ground target on the same or lower cliff level so that
// we are guaranteed to be able to navigate to it.
//
while (onGround > 0) {
there = UnitGetPosition(UnitGroupUnit(scanGroup, onGround));
testCliffLevel = CliffLevel(there);
if (cliffLevel >= testCliffLevel) {
return there;
}
onGround = onGround - 1;
}
}
}
return null;
}
//---------------------------------------------------------------------------------------------
void AIThinkVikingAssault (int player, unit aiUnit, unitgroup scanGroup) {
order ord = AICreateOrder(player, c_AB_FighterMode, 0);
unitgroup airGroup;
int inAir;
// Check to see if this is a valid order at all.
//
if (!UnitOrderIsValid(aiUnit, ord)) {
return;
}
// Check the number of air units to decide whether to ignore based on order count.
//
airGroup = UnitGroupFilterRegion(scanGroup,
RegionCircle(UnitGetPosition(aiUnit), AIRangeViking(player, null)),
0)
;
airGroup = UnitGroupFilterPlane(airGroup, c_planeAir, 0);
inAir = UnitGroupCount(airGroup, c_unitCountAlive);
// Do not switch to an air unit while processing an order on the ground. That way we won't
// interrupt the queued attack move order we get when we were told to land.
//
if (inAir == 0 && UnitOrderCount(aiUnit) > 0) {
return;
}
if (VikingModeChange(player, aiUnit, scanGroup, true) == null) {
return;
}
AICast(aiUnit, ord, c_noMarker, c_castHold);
}
//--------------------------------------------------------------------------------------------------
// *** VIKING (air mode) ***
//--------------------------------------------------------------------------------------------------
void AIThinkVikingFighter (int player, unit aiUnit, unitgroup scanGroup) {
point there;
order ord = AICreateOrder(player, c_AB_AssaultMode, 0);
if (!UnitOrderIsValid(aiUnit, ord)) {
return;
}
there = VikingModeChange(player, aiUnit, scanGroup, false);
if (there == null) {
return;
}
AICast(aiUnit, ord, c_noMarker, c_castHold);
// Queue an attack move towards the threat to make sure we path past a LOS blocker.
//
AISetTacticalAttackTargetPoint(aiUnit, there);
}
TactTerrAI.galaxy < suite
//--------------------------------------------------------------------------------------------------
// CargoDefend
//--------------------------------------------------------------------------------------------------
const fixed c_campaignBunkerLoadRange = 4.0;
const bool c_bunkerUnload = true;
const bool c_bunkerLoad = false;
//---------------------------------------------------------------------------------------------
unit CampaignWantsToBeInBunker (int player, unit aiUnit, unitgroup bunkerGroup, bool unload) {
int bunkerCount;
unit unitToCheck;
bool wantsToBeInBunker;
// When loading, check to see if there is space in the bunker at all.
//
if (!unload) {
if (UnitCargoValue(aiUnit, c_unitCargoSpaceFree) == 0) {
return null;
}
}
bunkerCount = UnitGroupCount(bunkerGroup, c_unitCountAll);
while (bunkerCount > 0) {
unitToCheck = UnitGroupUnit(bunkerGroup, bunkerCount);
bunkerCount = bunkerCount - 1;
// Make sure the unit is alive.
//
if (!UnitIsAlive(unitToCheck)) {
continue;
}
// When loading, make sure the unit is not allready in a transport.
//
if (!unload) {
if (UnitTestState(unitToCheck, c_unitStateInsideTransport)) {
continue;
}
}
// The unit wants to be somewhere far away, do not load it.
//
wantsToBeInBunker = true;
// The unit is forced to move, do not load.
if (AIControlForceToMove(unitToCheck)) {
wantsToBeInBunker = false;
}
// The unit wants to execute order, do not load.
else if (UnitOrderCount(unitToCheck) > 0) {
wantsToBeInBunker = false;
}
// The unit wants to move, do not load if safe.
else if (AIControlWantsToMove(unitToCheck)) {
if (!AIUnitIsInCombat(unitToCheck) && !AIUnitIsInCombat(aiUnit)) {
wantsToBeInBunker = false;
}
}
else {
// Need to check the home point
if (AIGetHomePosition(unitToCheck) == c_nullPoint) {
wantsToBeInBunker = false;
}
else if (!PointsInRange(UnitGetPosition(aiUnit), AIGetHomePosition(unitToCheck), c_campaignBunkerLoadRange)) {
wantsToBeInBunker = false;
}
}
// Do not care about units that want to be in bunker when we want to unload.
// Similarly, do not care about units that do not want to be in bunker when we want to load.
//
if (wantsToBeInBunker == unload) {
continue;
}
return unitToCheck;
}
return null;
}
//---------------------------------------------------------------------------------------------
bool CargoDefend (int player, unit aiUnit, unitgroup scanGroup, int searchRange, int loadRange, string wanted, string command) {
unitgroup nearBunkerGroup;
int bunkerCount;
unit unitToCheck;
order ord = null;
bool autoLoad = false;
bool wantsToBeInBunker;
scanGroup = UnitGroupFilterThreat(scanGroup, aiUnit, null, 0);
scanGroup = UnitGroupFilterRegion(scanGroup, RegionCircle(UnitGetPosition(aiUnit), searchRange), 0);
if (UnitGroupCount(scanGroup, c_unitCountAlive) == 0) { // no nearby enemies.
// Both checks are needed because auto loading bunkers is needed on campaign before the
// AI is active.....
if (AIIsCampaign(player)) {
autoLoad = true;
}
else if (AIGetDifficulty(player, c_diffAutoLoadBunkers)) {
autoLoad = true;
}
if (autoLoad && (command == c_AB_BunkerChange)) {
// handle bunkers on campaign differently.
unitToCheck = CampaignWantsToBeInBunker(player, aiUnit, UnitCargoGroup(aiUnit), c_bunkerUnload);
if (unitToCheck != null) {
ord = AICreateOrder(player, command, e_AB_TransportUnloadUnit); // unload the bunker.
OrderSetTargetPassenger(ord, unitToCheck);
}
if (ord == null) {
unitToCheck = CampaignWantsToBeInBunker(player,
aiUnit,
AIFindUnits(player, wanted, UnitGetPosition(aiUnit), c_campaignBunkerLoadRange, c_noMaxCount),
c_bunkerLoad);
if (unitToCheck != null) {
ord = AICreateOrder(player, command, e_AB_TransportLoadUnit); // load the bunker.
OrderSetTargetUnit(ord, unitToCheck);
}
}
}
else { // not a campaign bunker
if (UnitCargoValue(aiUnit, c_unitCargoSpaceUsed) == 0) { // nothing to unload
return false;
}
ord = AICreateOrder(player, command, e_AB_TransportUnloadAll); // unload bunker
}
}
else { // nearby enemies found.
if (UnitCargoValue(aiUnit, c_unitCargoSpaceFree) == 0) { // check for space
return false;
}
if (command == c_AB_CommandCenterChange) {
if (!AIAnyWorkersFleeingNearby(player,UnitGetPosition(aiUnit),8.0)) {
return false;
}
}
nearBunkerGroup = AIFindUnits(player, wanted, UnitGetPosition(aiUnit), loadRange, c_noMaxCount);
bunkerCount = UnitGroupCount(nearBunkerGroup, c_unitCountAll);
while (bunkerCount > 0) {
unitToCheck = UnitGroupUnit(nearBunkerGroup, bunkerCount);
bunkerCount = bunkerCount - 1;
if (!UnitIsAlive(unitToCheck)) {
continue;
}
if (UnitTestState(unitToCheck, c_unitStateInsideTransport)) {
continue;
}
if (command == c_AB_CommandCenterChange) {
ord = AICreateOrder(player, command, e_AB_TransportLoadAll);
}
else {
ord = AICreateOrder(player, command, e_AB_TransportLoadUnit);
OrderSetTargetUnit(ord, unitToCheck);
}
break;
}
}
if (!UnitOrderIsValid(aiUnit, ord)) {
return false;
}
AICast(aiUnit, ord, c_noMarker, c_castHold);
return true;
}
//--------------------------------------------------------------------------------------------------
// *** COMMAND CENTER ***
//--------------------------------------------------------------------------------------------------
static order CallDownSupply (int player, unit aiUnit) {
unitgroup scanGroup;
int scanCount;
unit depot;
order ord;
aifilter filter;
ord = AICreateOrder(player, c_AB_SupplyDrop, 0);
if (!UnitOrderIsValid(aiUnit, ord)) {
return null;
}
scanGroup = AIFindUnits(player, "SupplyDepotUnderground", UnitGetPosition(aiUnit),
AIUnitFixed(player, c_TB_CommandCenter, c_fieldRadius)
+ AIAbilityFixed(player, c_AB_SupplyDrop, c_fieldRange0),
c_noMaxCount
);
// Filter out supply depots that are already buffed.
//
filter = AIFilter(player);
AISetFilterBits(filter, UnitFilterStr(AIAbilityStr(player, c_AB_SupplyDrop, c_fieldTargetFiltersAB)));
AISetFilterBehaviorCount(filter, c_noBehaviorMin, c_noBehaviorMax, c_BF_SupplyDrop);
scanGroup = AIGetFilterGroup (filter, scanGroup);
return AIUnitGroupGetValidOrder(scanGroup, ord, aiUnit, c_backwards);
}
static bool CallDownMule (int player, unit aiUnit) {
unitgroup scanGroup;
int scanCount;
unit peon;
order ord;
ord = AICreateOrder(player, c_AB_CalldownMULE, 0);
if (!UnitOrderIsValid(aiUnit, ord)) {
return false;
}
scanGroup = AIFindUnits(player, c_TU_SCV, UnitGetPosition(aiUnit),
AIAbilityFixed(player, c_AB_CalldownMULE, c_fieldRange0),
c_noMaxCount
);
// Find only scv's that are gathering minerals and are close to their mineral target.
scanGroup = AIFilterGathering(scanGroup, c_resourceTypeMinerals, c_maxDistanceToMinerals);
scanCount = UnitGroupCount(scanGroup, c_unitCountAll);
while (scanCount > 0) {
// Pick one to cast on / next to.
peon = UnitGroupUnit(scanGroup, scanCount);
scanCount = scanCount - 1;
ord = AICreateOrder(player, c_AB_CalldownMULE, 0);
OrderSetTargetPoint(ord, UnitGetPosition(peon));
if (!UnitOrderIsValid(aiUnit, ord)) {
continue;
}
AICast(aiUnit, ord, c_noMarker, c_castHold);
return true;
}
return false;
}
void AIThinkCommandCenter(int player, unit aiUnit, unitgroup scanGroup) {
order ord;
if (CargoDefend(player, aiUnit, scanGroup, 10, 10, c_TU_SCV, c_AB_CommandCenterChange))
{
return;
}
if (AIEvalTacticalData(aiUnit, null)) {
return;
}
if (AIIsCampaign(player)) {
return;
}
if (AISuspectDetectionDanger(player)) {
if (UnitGetPropertyInt(aiUnit, c_unitPropEnergy, c_unitPropCurrent) < 150) {
return; // save for two comsats
}
}
if (CallDownMule(player, aiUnit)) {
return;
}
// For now do supply only if we can't do mule,
// tempted to comment this out entirely
ord = CallDownSupply(player, aiUnit);
if (ord != null) {
AICast(aiUnit, ord, c_noMarker, c_castHold);
return;
}
}
//--------------------------------------------------------------------------------------------------
// *** BUNKER ***
//--------------------------------------------------------------------------------------------------
void AIThinkBunker(int player, unit aiUnit, unitgroup scanGroup) {
CargoDefend(player, aiUnit, scanGroup, 8, 10, c_TU_Marine, c_AB_BunkerChange);
}
//--------------------------------------------------------------------------------------------------
// ScannerSweep
//--------------------------------------------------------------------------------------------------
bool ScannerSweep (int player, unit aiUnit) {
order ord;
point loc;
ord = AICreateOrder(player, c_AB_ScannerSweep, 0);
if (!UnitOrderIsValid(aiUnit, ord)) {
return false;
}
// If something is attacking while cloaked and we can defend if we reveal it, cast sweep.
//
loc = AIGetCloakedAttacker(player);
// Else if we have high energy then use sweep to scout something.
//
if (loc == null) {
// TODO fix AIGetNextScoutLoc to return only important locations
//if (UnitGetPropertyFixed(aiUnit, c_unitPropEnergyPercent, true) >= 200) {
// loc = AIGetNextScoutLoc(player);
//}
}
if (loc == null) {
return false;
}
OrderSetTargetPoint(ord, loc);
if (!UnitOrderIsValid(aiUnit, ord)) {
return false;
}
AICast(aiUnit, ord, c_noMarker, c_castHold);
AIClearCloakedAttacker(player, loc);
return true;
}
//--------------------------------------------------------------------------------------------------
// *** SURVEILLANCE STATION ***
//--------------------------------------------------------------------------------------------------
void AIThinkOrbitalCommand (int player, unit aiUnit, unitgroup scanGroup) {
if (AIEvalTacticalData(aiUnit, null)) {
return;
}
if (!ScannerSweep(player, aiUnit)) {
AIThinkCommandCenter(player, aiUnit, scanGroup);
}
}
//--------------------------------------------------------------------------------------------------
// *** MagneticMine ***
//--------------------------------------------------------------------------------------------------
fixed AIRangeD8Charge (int player, unit aiUnit) {
return AIEffectFixed(player, c_EF_D8ChargeDmg, c_fieldAreaRadius2) + 1.0;
}
void AIThinkD8Charge (int player, unit aiUnit, unitgroup scanGroup) {
int scanCount;
marker mark = AIMarker(aiUnit, c_MK_D8ChargeFlee);
aifilter filter = AIFilter(player);
scanGroup = AIFindUnits(player, null, UnitGetPosition(aiUnit), AIRangeD8Charge(player, aiUnit), c_noMaxCount);
AISetFilterAlliance(filter, c_playerGroupAlly);
AISetFilterMarker(filter, c_noMarkersMin, c_noMarkersMax, mark);
AISetFilterSelf(filter, aiUnit);
scanGroup = AIGetFilterGroup(filter, scanGroup);
scanCount = UnitGroupCount(scanGroup, c_unitCountAll);
while (scanCount > 0) {
AICastFlee(UnitGroupUnit(scanGroup, scanCount), aiUnit, 6, mark);
scanCount = scanCount - 1;
}
}
//--------------------------------------------------------------------------------------------------
// *** Raven ***
//--------------------------------------------------------------------------------------------------
fixed AIRangeRaven (int player, unit aiUnit) {
return 10;
}
const int c_seekerMissileMinMarker = 0;
const int c_seekerMissileMaxMarker = 0;
order HunterSeekerMissile (int player, unit aiUnit, unitgroup scanGroup, marker mark) {
fixed damage;
unitgroup targetGroup;
aifilter filter;
order ord = AITacticalOrder(player, aiUnit, c_AB_SeekerMissile);
if (!ord) {
return null;
}
// Create the filters
//
filter = AIFilter(player);
AISetFilterBits(filter, UnitFilterStr(AIAbilityStr(player, c_AB_SeekerMissile, c_fieldTargetFiltersAB)));
AISetFilterAlliance(filter, c_playerGroupEnemy);
damage = AIEffectFixed(player, c_EF_SeekerDamage, c_fieldAmount);
AISetFilterLife(filter, damage*c_minDamageFraction, c_noMax);
AISetFilterMarker(filter, c_noMarkersMin, c_noMarkersMax, mark);
AISetFilterLifeSortReference(filter, damage, damage*c_distanceFromDamage);
// Select starting from the end, which is the target who's health is closest to the missile's
// damage.
//
targetGroup = AIGetFilterGroup(filter, scanGroup);
return AIUnitGroupGetValidOrder(targetGroup, ord, aiUnit, c_backwards);
}
//---------------------------------------------------------------------------------------------
static bool CastAutoTurret (int player, unit aiUnit, unitgroup scanGroup, bool lowVitality) {
// must not modify scanGroup in this function
point loc;
order ord = AITacticalOrder(player, aiUnit, c_AB_AutoTurret);
fixed minScore;
if (!ord) {
return false;
}
// Relax the constraints a little if the raven is low on health.
//
if (lowVitality) {
minScore = 1.0;
}
else {
minScore = 2.0;
}
// Finds the best point for the ai to cast an area of effect spell. The point must put the
// turret in range of min hits targets, with an accumulative score GE 2. Each target is assigned
// a score of 0.0 to 1.0 points, depending on whether the target's vitality is from 0.0 to 40.0.
// Up to an additional 1.0 point can be rewarded if the target has the optional bonus attribute.
//
loc = AIBestTargetPoint(
AIWeaponGroup(player, c_WE_AutoTurret, scanGroup),
2, // min hits
40, // damage base
minScore, // min score
AIWeaponFixed(player, c_WE_AutoTurret, c_fieldRange),
UnitGetPosition(aiUnit),
AIRangeRaven(player, aiUnit),
c_unitAttributeNone
);
if (!loc) {
return false;
}
OrderSetTargetPoint(ord, loc);
if (!UnitOrderIsValid(aiUnit, ord)) {
return false;
}
AICast(aiUnit, ord, c_noMarker, c_castRetreat);
return true;
}
fixed minToCastAutoTurret(int player) {
return AIAbilityFixed(player, c_AB_AutoTurret, c_fieldEnergyCost) +
AIAbilityFixed(player, c_AB_SeekerMissile, c_fieldEnergyCost);
}
const int c_RavenLowVitalityPercent = 65;
//---------------------------------------------------------------------------------------------
void AIThinkRaven (int player, unit aiUnit, unitgroup scanGroup) {
order ord;
marker mark;
bool lowVitality;
// Must not modify scanGroup because it will be used for CastAutoTurret.
mark = AIMarker(aiUnit, c_MK_SeekerMissile);
ord = HunterSeekerMissile(player, aiUnit, scanGroup, mark);
if (ord != null) {
AICast(aiUnit, ord, mark, c_castRetreat);
return;
}
// If Raven not in danger, save enough energy for seeker missile.
lowVitality = UnitGetPropertyInt(aiUnit, c_unitPropVitalityPercent, c_unitPropCurrent) < c_RavenLowVitalityPercent;
if (!lowVitality && UnitGetPropertyInt(aiUnit, c_unitPropEnergy, c_unitPropCurrent) < minToCastAutoTurret(player)) {
return;
}
if (CastAutoTurret(player, aiUnit, scanGroup, lowVitality)) {
return;
}
}
TactZergAI.galaxy
//--------------------------------------------------------------------------------------------------
// *** QUEEN ***
//--------------------------------------------------------------------------------------------------
fixed AIRangeQueen (int player, unit aiUnit) {
return MaxF(AIAbilityFixed(player, c_AB_Transfusion, c_fieldRange0),
AIAbilityFixed(player, c_AB_SpawnMutantLarva, c_fieldRange0)) + 1;
}
//--------------------------------------------------------------------------------------------------
order Transfusion (int player, unit aiUnit) {
order ord;
unitgroup group;
aifilter filter;
ord = AICreateOrder(player, c_AB_Transfusion, 0);
if (!UnitOrderIsValid(aiUnit, ord)) {
return null;
}
group = AIFindUnits(player, null, UnitGetPosition(aiUnit),
AIAbilityFixed(player, c_AB_Transfusion, c_fieldRange0) + 1,
c_noMaxCount)
;
filter = AIFilter(player);
AISetFilterAlliance(filter, c_playerGroupAlly);
AISetFilterLifeLost(filter, AIEffectFixed(player, c_EF_Transfusion, c_fieldEffectChange0), c_noMax);
group = AIGetFilterGroup(filter, group);
return AIUnitGroupGetValidOrder(group, ord, aiUnit, c_forwards);
}
//--------------------------------------------------------------------------------------------------
order SpawnLarva (int player, unit aiUnit) {
order ord;
unitgroup hatcheries;
int larvaCount;
// Only cast if idle.
//
if (UnitOrder(aiUnit, 0) != null) {
return null;
}
ord = AICreateOrder(player, c_AB_SpawnMutantLarva, 0);
if (!UnitOrderIsValid(aiUnit, ord)) {
return null;
}
// Don't cast if we already own at least 10 larva
//
larvaCount =
TechTreeBehaviorCount(player, c_BF_MutantLarvaTimer, c_techCountQueuedOrBetter) * 4
+ TechTreeUnitCount(player, c_ZU_Larva, c_techCountQueuedOrBetter)
;
if (larvaCount >= 10) {
return null;
}
hatcheries = AIFindUnits(player,
c_ZB_Hatchery_Alias,
UnitGetPosition(aiUnit),
15,
c_noMaxCount)
;
return AIUnitGroupGetValidOrder(hatcheries, ord, aiUnit, c_backwards);
}
//--------------------------------------------------------------------------------------------------
order CreepTumor (int player, unit aiUnit) {
order ord;
point p;
// Only cast if idle.
//
if (UnitOrder(aiUnit, 0) != null) {
return null;
}
ord = AICreateOrder(player, c_AB_QueenBuild, 1);
if (!UnitOrderIsValid(aiUnit, ord)) {
return null;
}
// Don't cast if there is no creep point set for this player.
p = AIGetBestCreepSpot(player, aiUnit, 8);
if (p == null) {
return null;
}
OrderSetTargetPlacement(ord, p, aiUnit, c_ZU_CreepTumor);
if (!UnitOrderIsValid(aiUnit, ord)) {
return null;
}
return ord;
}
//--------------------------------------------------------------------------------------------------
void AIThinkQueen (int player, unit aiUnit, unitgroup scanGroup) {
order ord;
unit heal;
if (AIEvalTacticalData(aiUnit, null)) {
return;
}
ord = Transfusion(player, aiUnit);
if (ord != null) {
AICast(aiUnit, ord, c_noMarker, c_castHold);
return;
}
ord = SpawnLarva(player, aiUnit);
if (ord != null) {
AICast(aiUnit, ord, c_noMarker, c_castHold);
return;
}
ord = CreepTumor(player, aiUnit);
if (ord != null) {
AICast(aiUnit, ord, c_noMarker, c_castRetreat);
return;
}
}
//--------------------------------------------------------------------------------------------------
// *** INFESTOR ***
//--------------------------------------------------------------------------------------------------
fixed AIRangeInfestor (int player, unit aiUnit) {
return MaxF(AIAbilityFixed(player, c_AB_InfestedTerrans, c_fieldRange0),
AIAbilityFixed(player, c_AB_NeuralParasite, c_fieldRange0)) + 1;
// AIAbilityFixed(player, c_AB_UnstableMutation, c_fieldRange0)
}
// Minimum vitality of a unit in order to mind control it,
// infestors will mind control units > carrier.
const fixed c_neuralParasiteMinVitality = 425;
//---------------------------------------------------------------------------------------------
order NeuralParasite (int player, unit aiUnit, unitgroup scanGroup, marker mark, marker gameMark, bool lowVitality) {
order ord;
aifilter filter;
unit target;
// vars related to nearby enemies.
//
aifilter groundAirFilter;
unitgroup threatGroup;
int enemyGroundCount;
int enemyAirCount;
// Create order and check validity
//
ord = AICreateOrder(player, c_AB_NeuralParasite, 0);
if (!UnitOrderIsValid(aiUnit, ord)) {
return null;
}
// Scan for enemy air and ground units
//
enemyGroundCount = 0;
enemyAirCount = 0;
groundAirFilter = AIFilter(player);
AISetFilterAlliance(groundAirFilter, c_playerGroupEnemy);
AISetFilterPlane(groundAirFilter, c_planeGround);
enemyGroundCount = UnitGroupCount(AIGetFilterGroup(groundAirFilter, scanGroup), c_unitCountAlive);
AISetFilterPlane(groundAirFilter, c_planeAir);
enemyAirCount = UnitGroupCount(AIGetFilterGroup(groundAirFilter, scanGroup), c_unitCountAlive);
// Apply filters to enemies
//
filter = AIFilter(player);
AISetFilterAlliance(filter, c_playerGroupEnemy);
AISetFilterBits(filter, UnitFilterStr(AIAbilityStr(player, c_AB_NeuralParasite, c_fieldTargetFiltersAB)));
AISetFilterRange(filter, aiUnit, AIAbilityFixed(player, c_AB_NeuralParasite, c_fieldRange0) + 1);
AISetFilterLife(filter, c_neuralParasiteMinVitality, c_noMax);
AISetFilterMarker(filter, c_noMarkersMin, c_noMarkersMax, mark);
AISetFilterCanAttackEnemy(filter, enemyGroundCount, enemyAirCount);
scanGroup = AIGetFilterGroup(filter, scanGroup);
// Since it's a missile, we also have to check the game-side marker
//
filter = AIFilter(player);
AISetFilterMarker(filter, c_noMarkersMin, c_noMarkersMax, gameMark);
scanGroup = AIGetFilterGroup(filter, scanGroup);
// Return valid target
//
return AIUnitGroupGetValidOrder(scanGroup, ord, aiUnit, c_forwards);
}
//--------------------------------------------------------------------------------------------------
//fixed MinToCastUnstableMutation (int player) {
// return AIAbilityFixed(player, c_AB_NeuralParasite, c_fieldEnergyCost) +
// AIAbilityFixed(player, c_AB_UnstableMutation, c_fieldEnergyCost);
//}
//
//order UnstableMutation (int player, unit aiUnit, unitgroup scanGroup, marker mark, bool lowVitality) {
// order ord;
// int energy;
// aifilter filter;
// unitgroup enemyCasters;
//
// ord = AICreateOrder(player, c_AB_UnstableMutation, 0);
// if (!UnitOrderIsValid(aiUnit, ord)) {
// return null;
// }
//
// // Save energy for neural parasite
// energy = UnitGetPropertyInt(aiUnit, c_unitPropEnergy, c_unitPropCurrent);
// if (energy < MinToCastUnstableMutation(player)) {
// return null;
// }
//
// // For now, only use on enemy casters, since we want them dead and they can't attack our units.
// filter = AIFilter(player);
// AISetFilterBits(filter, UnitFilterStr(AIAbilityStr(player, c_AB_UnstableMutation, c_fieldTargetFiltersAB)));
// AISetFilterAlliance(filter, c_playerGroupEnemy);
// AISetFilterLife(filter, c_noMin, c_noMax);
// AISetFilterMarker(filter, c_noMarkersMin, c_noMarkersMax, mark);
// AISetFilterBehaviorCount(filter, c_noBehaviorMin, c_noBehaviorMax, c_BF_UnstableMutation);
// enemyCasters = AIGetFilterGroup(filter, scanGroup);
//
// enemyCasters = AIFilterCasters(enemyCasters);
//
// return AIUnitGroupGetValidOrder(enemyCasters, ord, aiUnit, c_forwards);
//}
//---------------------------------------------------------------------------------------------
fixed MinToCastInfestedTerrans (int player) {
return AIAbilityFixed(player, c_AB_NeuralParasite, c_fieldEnergyCost) +
AIAbilityFixed(player, c_AB_InfestedTerrans, c_fieldEnergyCost);
}
order InfestedTerrans (int player, unit aiUnit, unitgroup scanGroup, bool lowVitality) {
order ord;
int energy;
aifilter filter;
point castPoint;
unit target;
unitgroup targetGroup; // Don't want to modify the scanGroup... still need it for neural parasite.
ord = AICreateOrder(player, c_AB_InfestedTerrans, 0);
if (!UnitOrderIsValid(aiUnit, ord)) {
return null;
}
// Reserve 125 mana for neural parasite
energy = UnitGetPropertyInt(aiUnit, c_unitPropEnergy, c_unitPropCurrent);
if (energy < MinToCastInfestedTerrans(player) && !lowVitality) {
return null;
}
// Cast on top of the weakest unit.
//
filter = AIFilter(player);
AISetFilterAlliance(filter, c_playerGroupEnemy);
AISetFilterBits(filter, UnitFilterStr(AIWeaponStr(player, c_WE_InfestedTerran, c_fieldTargetFilters)));
AISetFilterRange(filter, aiUnit, AIAbilityFixed(player, c_AB_InfestedTerrans, c_fieldRange0) + 1);
AISetFilterLifePercent(filter, c_noMin, c_noMax);
targetGroup = AIGetFilterGroup(filter, scanGroup);
// Check for valid target
//
target = UnitGroupUnit(targetGroup, UnitGroupCount(targetGroup, c_unitCountAll));
if (target == null) {
return null;
}
castPoint = AIPlacementNearbyFindTest(player, UnitGetPosition(target), 5.0, c_ZU_InfestedTerranEgg);
if (castPoint == c_nullPoint) {
return null;
}
OrderSetTargetPoint(ord, castPoint);
if (!UnitOrderIsValid(aiUnit, ord)) {
return null;
}
return ord;
}
//---------------------------------------------------------------------------------------------
const fixed enemyMultiplierInfestor = 1.25;
const fixed minThreshold = 100.0;
const int lowVitalityPercent = 75;
void AIThinkInfestor (int player, unit aiUnit, unitgroup scanGroup) {
// **Infestor disease in TargetFindData.xml** Currently not in the game.
marker mark;
marker gameMark;
order ord;
unitfilter f;
bool lowVitality;
if (AIEvalTacticalData(aiUnit, null)) {
return;
}
// Low Vitality = less than 75%, since it takes a WHILE for the infested marines to hatch
lowVitality = (UnitGetPropertyInt(aiUnit, c_unitPropVitalityPercent, c_unitPropCurrent) < lowVitalityPercent);
// If we outnumber the enemy, don't even bother casting any spell, unless we are less than 75%
if (!lowVitality) {
// If we have greater than 1.25 * the enemies forces, we outnumber, so don't cast.
f = UnitFilterStr("-;Missile,Dead,Stasis,Worker");
if (AIAllyEnemyRatio(player, UnitGetPosition(aiUnit), f, AIRangeInfestor(player, aiUnit), minThreshold) > enemyMultiplierInfestor) {
return;
}
}
// This must preserve scanGroup for Neural Parasite check.
ord = InfestedTerrans(player, aiUnit, scanGroup, lowVitality);
if (ord != null) {
AICast(aiUnit, ord, c_noMarker, c_castRetreat);
}
//mark = AIMarker(aiUnit, c_MK_UnstableMutation);
//ord = UnstableMutation(player, aiUnit, scanGroup, mark, lowVitality);
//if (ord != null) {
// AICast(aiUnit, ord, mark, c_castRetreat);
// return;
//}
mark = AIMarker(aiUnit, c_MK_NeuralParasite);
gameMark = AIMarker(aiUnit, c_MK_GameNeuralParasite);
ord = NeuralParasite(player, aiUnit, scanGroup, mark, gameMark, lowVitality);
if (ord != null) {
AICast(aiUnit, ord, mark, c_castRetreat);
return;
}
}
//--------------------------------------------------------------------------------------------------
// *** BANELING ***
//--------------------------------------------------------------------------------------------------
const fixed c_banelingRange = 8;
fixed AIRangeBaneling (int player, unit aiUnit) {
return c_banelingRange;
}
//---------------------------------------------------------------------------------------------
order SapStructure (int player, unit aiUnit, unitgroup scanGroup, marker mark) {
order ord;
unitgroup enemyBuildingGroup;
unitgroup enemyUnitGroup;
unit closestEnemy;
point banelingPosition;
fixed distanceToEnemy;
unit closestEnemyBuilding;
bool airAllies = false;
int damage;
aifilter buildingFilter;
aifilter unitFilter;
// Create and check the validity of order.
//
ord = AICreateOrder(player, c_AB_SapStructure, 0);
if (!UnitOrderIsValid(aiUnit, ord)) {
return null;
}
// Create non-building filter to find the closest enemy.
//
unitFilter = AIFilter(player);
AISetFilterAlliance(unitFilter, c_playerGroupEnemy);
AISetFilterBits(unitFilter, UnitFilterStr(AIEffectStr(player, c_EF_BaneUnit, c_fieldFilters)));
AISetFilterRange(unitFilter, aiUnit, AIRangeBaneling(player, aiUnit));
enemyUnitGroup = AIGetFilterGroup(unitFilter, scanGroup);
banelingPosition = UnitGetPosition(aiUnit);
closestEnemy = UnitGroupNearestUnit(enemyUnitGroup, banelingPosition);
if (closestEnemy != null) {
distanceToEnemy = DistanceBetweenPoints(banelingPosition, UnitGetPosition(closestEnemy));
}
else {
distanceToEnemy = AIRangeBaneling(player, aiUnit); // Default distance.
}
// Create building filter.
//
buildingFilter = AIFilter(player);
AISetFilterAlliance(buildingFilter, c_playerGroupEnemy);
AISetFilterBits(buildingFilter, UnitFilterStr(AIAbilityStr(player, c_AB_SapStructure, c_fieldTargetFiltersAB)));
AISetFilterRange(buildingFilter, aiUnit, distanceToEnemy);
damage = AIEffectInt(player, c_EF_BaneBuilding, c_fieldAmount);
AISetFilterLifePerMarker(buildingFilter, damage, mark);
airAllies = AINearbyPlaneTest(UnitGetPosition(aiUnit), player, AIRangeBaneling(player, aiUnit), c_planeAir, c_unitAllianceAlly);
AISetFilterCanAttackAlly(buildingFilter, c_groundAlliesNearby, airAllies); // Ground allies always true, since banelings are ground units.
enemyBuildingGroup = AIGetFilterGroup(buildingFilter, scanGroup);
closestEnemyBuilding = UnitGroupNearestUnit(enemyBuildingGroup, banelingPosition);
if (closestEnemyBuilding == null) {
return null;
}
OrderSetTargetUnit(ord, closestEnemyBuilding);
if (!UnitOrderIsValid(aiUnit, ord)) {
return null;
}
return ord;
}
//---------------------------------------------------------------------------------------------
void AIThinkBaneling (int player, unit aiUnit, unitgroup scanGroup) {
marker mark;
order ord;
if (AIEvalTacticalData(aiUnit, null)) {
return;
}
mark = AIMarker(aiUnit, c_MK_SapStructure);
ord = SapStructure(player, aiUnit, scanGroup, mark);
if (ord != null) {
AICast(aiUnit, ord, mark, c_castHold);
}
}
//--------------------------------------------------------------------------------------------------
// *** OVERSEER ***
//--------------------------------------------------------------------------------------------------
fixed AIRangeOverseer (int player, unit aiUnit) {
return AIUnitFixed(player, c_ZU_Overseer, c_fieldSightDawn) + 1;
//return MaxF(MaxF(AIAbilityFixed(player, c_AB_FungalGrowth, c_fieldRange0),
// AIAbilityFixed(player, c_AB_AcidSpores, c_fieldRange0)),
// AIAbilityFixed(player, c_AB_Changeling, c_fieldRange0)) + 1;
}
//fixed MinToCastFungalGrowth (int player) {
// return AIAbilityFixed(player, c_AB_FungalGrowth, c_fieldEnergyCost) +
// AIAbilityFixed(player, c_AB_AcidSpores, c_fieldEnergyCost);
//}
//order FungalGrowth (int player, unit aiUnit, marker mark, marker gameMark, unitgroup scanGroup) {
// order ord;
// fixed energy;
// aifilter filter;
// bool groundAllies;
// unitgroup enemyGroup;
// ord = AICreateOrder(player, c_AB_FungalGrowth, 0);
// if (!UnitOrderIsValid(aiUnit, ord)) {
// return null;
// }
// // Save energy for acid spores
// energy = UnitGetPropertyFixed(aiUnit, c_unitPropEnergy, c_unitPropCurrent);
// if (energy < MinToCastFungalGrowth(player)) {
// return null;
// }
//
// groundAllies = AINearbyPlaneTest(UnitGetPosition(aiUnit), player, AIRangeOverseer(player, aiUnit), c_planeGround, c_unitAllianceAlly);
// // Cast on strongest enemy that can attack our allies
// filter = AIFilter(player);
// AISetFilterBits(filter, UnitFilterStr(AIAbilityStr(player, c_AB_FungalGrowth, c_fieldTargetFiltersAB)));
// AISetFilterCanAttackAlly(filter, groundAllies, c_airAlliesNearby);
// AISetFilterLife(filter, c_noMin, c_noMax);
// AISetFilterMarker(filter, c_noMarkersMin, c_noMarkersMax, mark);
// AISetFilterBehaviorCount(filter, c_noBehaviorMin, c_noBehaviorMax, c_BF_FungalGrowth);
// enemyGroup = AIGetFilterGroup(filter, scanGroup);
//
// AISetFilterMarker(filter, c_noMarkersMin, c_noMarkersMax, gameMark);
// enemyGroup = AIGetFilterGroup(filter, scanGroup);
//
// return AIUnitGroupGetValidOrder(enemyGroup, ord, aiUnit, c_forwards);
//}
//--------------------------------------------------------------------------------------------------
//const int c_minAlliesCanAttack = 3;
//order AcidSpores (int player, unit aiUnit, unitgroup scanGroup) {
// order ord;
// aifilter filter;
// bool groundEnemies;
// bool airEnemies;
// region r;
// unitgroup allyGroup;
// int allyCount;
// point position;
//
// ord = AICreateOrder(player, c_AB_AcidSpores, 0);
// if (!UnitOrderIsValid(aiUnit, ord)) {
// return null;
// }
//
// DebugVarInt("const", c_planeAir);
//
// position = UnitGetPosition(aiUnit);
// // Only use it if we have some units that will be able to attack the enemy.
// groundEnemies = AINearbyPlaneTest(position, player, AIRangeOverseer(player, aiUnit), c_planeGround, c_unitAllianceEnemy);
// airEnemies = AINearbyPlaneTest(position, player, AIRangeOverseer(player, aiUnit), c_planeAir, c_unitAllianceEnemy);
//
// //AIEffectFixed(player, c_EF_AcidSporesArea, c_fieldAreaRadius0)
// //UnitFilterStr(AIAbilityStr(player, c_AB_AcidSpores, c_fieldTargetFiltersAB)
// DebugVarBool("grnd", groundEnemies);
// DebugVarBool("air", airEnemies);
//
// r = RegionCircle(UnitGetPosition(aiUnit), AIRangeOverseer(player, aiUnit));
// allyGroup = UnitGroupAlliance(player,
// c_unitAllianceAlly,
// r,
// null,
// c_noMaxCount)
// ;
//
// AISetFilterCanAttackAlly(filter, groundEnemies, airEnemies);
// allyGroup = AIGetFilterGroup(filter, allyGroup);
// allyCount = UnitGroupCount(allyGroup, c_unitCountAll);
//
// DebugVarInt("allyCount:", allyCount);
//
// if (allyCount < c_minAlliesCanAttack) {
// return null;
// }
//
// return null;
//}
TactZergAI.galaxy < suite
//--------------------------------------------------------------------------------------------------
// Limit the number of enemies we check since AIPathCost could be expensive over
// too many units.
const int c_maxEnemyCount = 5;
order Changeling (int player, unit aiUnit, unitgroup scanGroup, fixed range) {
int enemyPlayer = -1;
point here;
order ord;
point camPoint;
fixed camDistance;
ord = AICreateOrder(player, c_AB_Changeling, 0);
if (!UnitOrderIsValid(aiUnit, ord)) {
return null;
}
enemyPlayer = AIGetPlayerGroup(scanGroup);
if (enemyPlayer == -1) {
return null;
}
// A good player should be able to tell when the enemy isn't paying attention
// and then cast changeling. To simulate this, the computer looks for an enemy
// player's camera on hard and insanse.
//
if (AICampSkirDiffTest(player, c_campExpert, c_skirVeryHard)) {
camPoint = CameraGetTarget(enemyPlayer);
here = UnitGetPosition(aiUnit);
camDistance = DistanceBetweenPoints(camPoint, here);
if (camDistance < 20) {
return null;
}
}
// Check to see if we already have a changeling.
if (AINearbyUnits(player, c_ZU_Changeling, here, range, 1) ||
AINearbyUnits(player, c_ZU_ChangelingZealot, here, range, 1) ||
AINearbyUnits(player, c_ZU_ChangelingZergling, here, range, 1) ||
AINearbyUnits(player, c_ZU_ChangelingMarine, here, range, 1) ||
AINearbyUnits(player, c_ZU_ChangelingZerglingWings, here, range, 1)) {
return null;
}
// Check to see if there are enough basic units around to follow.
if ((UnitGroupCount(AIFilterPathable(AIFindUnits(enemyPlayer, c_PU_Zealot, here, range, c_maxEnemyCount), here), c_unitCountAlive) >= 2) ||
(UnitGroupCount(AIFilterPathable(AIFindUnits(enemyPlayer, c_ZU_Zergling, here, range, c_maxEnemyCount), here), c_unitCountAlive) >= 2) ||
(UnitGroupCount(AIFilterPathable(AIFindUnits(enemyPlayer, c_TU_Marine, here, range, c_maxEnemyCount), here), c_unitCountAlive) >= 2)) {
return ord;
}
return null;
}
bool MakeChangeling (int player, unit aiUnit, unitgroup scanGroup) {
order ord;
unitgroup allyGroup;
region r;
aifilter filter;
point position;
bool groundEnemies;
bool airEnemies;
fixed range;
if (AIIsCampaign(player)) {
// don't auto make changlings on campaign
return false;
}
// If we already have a changeling order, ignore new orders so that
// we don't cast again
if (UnitOrderHasAbil(aiUnit, c_AB_Changeling)) {
return false;
}
// Test to see whether the overseer is scouting or fighting.
// For now, just test to see if there are nearby allied units that can fight the enemy.
r = RegionCircle(UnitGetPosition(aiUnit), AIRangeOverseer(player, aiUnit));
allyGroup = UnitGroupAlliance(player, c_unitAllianceAlly, r, null, c_noMaxCount);
position = UnitGetPosition(aiUnit);
range = AIRangeOverseer(player, aiUnit);
groundEnemies = AINearbyPlaneTest(position, player, range, c_planeGround, c_unitAllianceEnemy);
airEnemies = AINearbyPlaneTest(position, player, range, c_planeAir, c_unitAllianceEnemy);
filter = AIFilter(player);
AISetFilterCanAttackAlly(filter, groundEnemies, airEnemies);
allyGroup = AIGetFilterGroup(filter, allyGroup);
if (UnitGroupCount(allyGroup, c_unitCountAll) == 0) {
ord = Changeling(player, aiUnit, scanGroup, range);
if (ord != null) {
AICast(aiUnit, ord, c_noMarker, c_castRetreat);
return true;
}
}
return false;
}
//--------------------------------------------------------------------------------------------------
void AIThinkOverseer (int player, unit aiUnit, unitgroup scanGroup) {
order ord;
marker mark;
marker gameMark;
if (MakeChangeling(player, aiUnit, scanGroup)) {
return;
}
//gameMark = AIMarker(aiUnit, c_MK_GameFungalGrowth);
//mark = AIMarker(aiUnit, c_MK_FungalGrowth);
//ord = FungalGrowth(player, aiUnit, mark, gameMark, scanGroup);
//if (ord != null) {
// AICast(aiUnit, ord, mark, c_castHold);
// return;
//}
//ord = AcidSpores(player, aiUnit, scanGroup);
//if (ord != null) {
// AICast(aiUnit, ord, c_noMarker, c_castHold);
// return;
//}
}
//--------------------------------------------------------------------------------------------------
// *** CHANGELING ***
//--------------------------------------------------------------------------------------------------
fixed AIRangeChangeling (int player, unit aiUnit) {
return AIUnitFixed(player, c_ZU_Overlord, c_fieldSightDawn);
}
void AIThinkChangelingUnit (int player, unit aiUnit, unitgroup scanGroup, string followUnit) {
unitgroup followGroup;
order ord;
int enemyPlayer;
region r;
unitgroup allyGroup;
unitgroup enemyGroup;
if (AIIsFollowingUnit(aiUnit, followUnit)) {
return;
}
// Create a move order, and check validity
ord = AICreateOrder(player, c_AB_Follow, 0);
if (!UnitOrderIsValid(aiUnit, ord)) {
return;
}
r = RegionCircle(UnitGetPosition(aiUnit), AIRangeOverseer(player, aiUnit));
enemyGroup = UnitGroupAlliance(player, c_unitAllianceEnemy, r, null, c_noMaxCount);
enemyPlayer = AIGetPlayerGroup(enemyGroup);
if (enemyPlayer == -1) {
return;
}
// By default, follow the provided unit type.
followGroup = AIFindUnits(enemyPlayer, followUnit, UnitGetPosition(aiUnit), AIRangeChangeling(player, aiUnit), c_noMaxCount);
ord = AIUnitGroupGetValidOrder(followGroup, ord, aiUnit, c_forwards);
if (ord != null) {
AICast(aiUnit, ord, c_noMarker, c_castHold);
return;
}
// Otherwise, find any enemy to follow.
ord = AICreateOrder(player, c_AB_Follow, 0);
if (!UnitOrderIsValid(aiUnit, ord)) {
return;
}
ord = AIUnitGroupGetValidOrder(scanGroup, ord, aiUnit, c_forwards);
if (ord != null) {
AICast(aiUnit, ord, c_noMarker, c_castHold);
return;
}
return;
}
//--------------------------------------------------------------------------------------------------
void AIThinkChangelingZergling (int player, unit aiUnit, unitgroup scanGroup) {
AIThinkChangelingUnit(player, aiUnit, scanGroup, c_ZU_Zergling);
}
void AIThinkChangelingMarine (int player, unit aiUnit, unitgroup scanGroup) {
AIThinkChangelingUnit(player, aiUnit, scanGroup, c_TU_Marine);
}
void AIThinkChangelingZealot (int player, unit aiUnit, unitgroup scanGroup) {
AIThinkChangelingUnit(player, aiUnit, scanGroup, c_PU_Zealot);
}
Terran0.galaxy
//==================================================================================================
// Terran Melee Very Easy
//==================================================================================================
static void RandomInfantry (int player);
static void LateGround (int player);
//--------------------------------------------------------------------------------------------------
// TerranOpenGnd0
//--------------------------------------------------------------------------------------------------
void TerranOpenGnd0 (int player) {
AIClearStock(player);
AISetStock( player, 1, c_TB_CommandCenter_Alias );
AISetStock( player, 8, c_TU_SCV );
// around 100 resources in about 2 units
AISetStock( player, 2, c_TU_Marine );
TerranTechUp(player, 1);
if (AIEnableVeryEasyStockOpen(player, c_TU_SCV)) {
return;
}
// around 300 resources in about 3 unit
RandomInfantry(player);
}
//--------------------------------------------------------------------------------------------------
// TerranMidGndA
//--------------------------------------------------------------------------------------------------
static void TerranMidGndA (int player) {
AIClearStock(player);
AIDefaultEconomy(player, c_TB_CommandCenter_Alias, c_TB_Refinery, c_TB_SupplyDepot, c_TU_SCV, 8, c_stockAlways);
if (AISawCloakedUnit(player)) {
AISetStock( player, 2, c_TB_MissileTurret );
AISetStock( player, 1, c_TB_OrbitalCommand );
}
AISetStockUserData(player);
TerranTechUp(player, 2);
if (AIEnableVeryEasyStockMidA(player, c_TU_SCV, 4)) {
return;
}
// around 600 resources in about 4 unit
AIAddStringInt(player, AIPickFrom2(c_TU_Ghost, c_TU_SiegeTank), 1);
RandomInfantry(player);
}
//--------------------------------------------------------------------------------------------------
// TerranMidGndB
//--------------------------------------------------------------------------------------------------
static void TerranMidGndB (int player) {
AIClearStock(player);
AIDefaultEconomy(player, c_TB_CommandCenter_Alias, c_TB_Refinery, c_TB_SupplyDepot, c_TU_SCV, 8, c_stockAlways);
if (AISawCloakedUnit(player)) {
AISetStock( player, 2, c_TB_MissileTurret );
AISetStock( player, 1, c_TB_OrbitalCommand );
}
AISetStockUserData(player);
TerranTechUp(player, 3);
if (AIEnableVeryEasyStockMidB(player, c_TU_SCV, 4)) {
return;
}
// around 900 resources in about 5 unit
LateGround(player);
}
//--------------------------------------------------------------------------------------------------
// LateGround
//--------------------------------------------------------------------------------------------------
static void LateGround (int player) {
AIAddStringInt(player, c_TU_Marine, 1);
AIAddStringInt(player, AIPickFrom2(c_TU_Hellion, c_TU_Marauder), 1);
AIAddStringInt(player, AIPickFrom2(c_TU_Hellion, c_TU_Marine), 1);
AIAddStringInt(player, AIPickFrom2(c_TU_Marauder, c_TU_Marine), 1);
AIAddStringInt(player, AIPickFrom2(c_TU_SiegeTank, c_TU_Ghost), 1);
AIAddStringInt(player, AIPickFrom2(c_TU_SiegeTank, c_TU_Ghost), 1);
}
//--------------------------------------------------------------------------------------------------
// LateGnd
//--------------------------------------------------------------------------------------------------
static void LateGnd (int player) {
AIClearStock(player);
AIDefaultEconomy(player, c_TB_CommandCenter_Alias, c_TB_Refinery, c_TB_SupplyDepot, c_TU_SCV, 8, c_stockAlways);
AIDefaultExpansion(player, c_TB_CommandCenter_Alias, 6000, 0, c_expandDefault);
AISetStockUserData(player);
AISetStock( player, 1, c_TB_OrbitalCommand );
AISetStock( player, 3, c_TU_Medivac );
AISetStock( player, 1, c_TU_Raven );
TerranTechUp(player, 4);
if (AIEnableVeryEasyStockLate(player, c_TU_SCV, 4)) {
return;
}
LateGround(player);
}
//--------------------------------------------------------------------------------------------------
// TerranOpenAir0
//--------------------------------------------------------------------------------------------------
void TerranOpenAir0 (int player) {
AIClearStock(player);
AISetStock( player, 1, c_TB_CommandCenter_Alias );
AISetStock( player, 8, c_TU_SCV );
AISetStock( player, 1, c_TB_Refinery );
AISetStock( player, 1, c_TB_Barracks );
AISetStock( player, 1, c_TB_Factory );
AISetStock( player, 1, c_TB_Starport );
AISetStock( player, 1, c_TU_Viking );
AISetStock( player, 1, c_TB_BarracksReactor );
AISetStock( player, 1, c_TB_SupplyDepot );
AISetStock( player, 1, c_TU_Marine );
AIEnableStock(player);
// SetGasPeons(player, 3);
//---------------------------------------------------------
if (AITechCount(player, c_TU_Viking, c_techCountCompleteOnly) < 1) {
return;
}
AIWaveMerge(player, c_waveMain, c_waveAttack);
AISetAttackState(player, e_attackState_Attack);
AISetMainState(player, e_mainState_Mid1, e_mainSubState_AirA);
}
//--------------------------------------------------------------------------------------------------
// TerranMidAirA
//--------------------------------------------------------------------------------------------------
static void TerranMidAirA (int player) {
AIClearStock(player);
AIDefaultEconomy(player, c_TB_CommandCenter_Alias, c_TB_Refinery, c_TB_SupplyDepot, c_TU_SCV, 8, c_stockAlways);
AISetStockUnitNext( player, 4, c_TU_Marine, c_stockAlways );
AISetStock( player, 1, c_TU_Viking );
AISetStock( player, 1, c_TB_StarportTechLab );
AISetStock( player, 2, c_TU_Viking );
AISetStock( player, 1, c_TU_Raven );
AISetStock( player, 1, c_TU_Banshee );
AISetStock( player, 1, c_TU_Medivac );
AISetStock( player, 1, c_TB_OrbitalCommand );
AIEnableStock(player);
// SetGasPeons(player, 3);
//---------------------------------------------------------
if (AIGetTime() < 700) {
return;
}
AIWaveMerge(player, c_waveMain, c_waveAttack);
AISetAttackState(player, e_attackState_Attack);
AISetMainState(player, e_mainState_Mid1, e_mainSubState_AirB);
}
//--------------------------------------------------------------------------------------------------
// TerranMidAirB
//--------------------------------------------------------------------------------------------------
static void TerranMidAirB (int player) {
AIClearStock(player);
AIDefaultEconomy(player, c_TB_CommandCenter_Alias, c_TB_Refinery, c_TB_SupplyDepot, c_TU_SCV, 8, c_stockAlways);
AIDefaultExpansion(player, c_TB_CommandCenter_Alias, 6000, 1000, c_expandDefault);
AISetStockUnitNext( player, 4, c_TU_Marine, c_stockAlways );
AISetStockUnitNext( player, 3, c_TU_Viking, c_stockAlways );
AISetStockUnitNext( player, 1, c_TU_Raven, c_stockAlways );
AISetStockUnitNext( player, 1, c_TU_Medivac, c_stockAlways );
AISetStock( player, 1, c_TB_OrbitalCommand );
AISetStockUnitNext( player, 3, c_TB_MissileTurret, c_stockIdle );
AISetStockUnitNext( player, 2, c_TU_Banshee, c_stockAlways );
AISetStockUnitNext( player, 1, c_TU_Battlecruiser, c_stockAlways );
AIEnableStock(player);
// SetGasPeons(player, 4);
//---------------------------------------------------------
if (AIGetTime() < 1200) {
return;
}
AIWaveMerge(player, c_waveMain, c_waveAttack);
AISetAttackState(player, e_attackState_Attack);
AISetMainState(player, e_mainState_Late1, e_mainSubState_AirA);
AISetFlag(player, e_flagsScouting, true);
AISetFlag(player, e_flagsClearObs, true);
}
//--------------------------------------------------------------------------------------------------
// LateAir
//--------------------------------------------------------------------------------------------------
static void LateAir (int player) {
AIClearStock(player);
AIDefaultEconomy(player, c_TB_CommandCenter_Alias, c_TB_Refinery, c_TB_SupplyDepot, c_TU_SCV, 8, c_stockAlways);
AIDefaultExpansion(player, c_TB_CommandCenter_Alias, 6000, 1000, c_expandDefault);
AISetStockUnitNext( player, 4, c_TU_Marine, c_stockAlways );
AISetStockUnitNext( player, 5, c_TU_Viking, c_stockAlways );
AISetStockUnitNext( player, 1, c_TU_Raven, c_stockAlways );
AISetStockUnitNext( player, 1, c_TU_Medivac, c_stockAlways );
AISetStock( player, 1, c_TB_OrbitalCommand );
AISetStockUnitNext( player, 3, c_TB_MissileTurret, c_stockIdle );
AISetStockUnitNext( player, 4, c_TU_Banshee, c_stockAlways );
AISetStockUnitNext( player, 1, c_TU_Battlecruiser, c_stockAlways );
AIEnableStock(player);
// SetGasPeons(player, 4);
//---------------------------------------------------------
if (AIGetTime() % 300 > 5) {
return;
}
AIWaveMerge(player, c_waveMain, c_waveAttack);
AISetAttackState(player, e_attackState_Attack);
AISetFlag(player, e_flagsScouting, true);
AISetFlag(player, e_flagsClearObs, true);
}
//--------------------------------------------------------------------------------------------------
// RandomInfantry
//--------------------------------------------------------------------------------------------------
static void RandomInfantry (int player) {
AIAddStringInt(player, c_TU_Marine, 1);
AIAddStringInt(player, AIPickFrom2(c_TU_Hellion, c_TU_Marauder), 1);
AIAddStringInt(player, AIPickFrom2(c_TU_Hellion, c_TU_Marauder), 1);
}
//--------------------------------------------------------------------------------------------------
// TerranMid0
//--------------------------------------------------------------------------------------------------
void TerranMid0 (int player) {
int mainSubState = AIState(player, e_mainSubState);
if (mainSubState == e_mainSubState_GndA) { TerranMidGndA(player); }
else if (mainSubState == e_mainSubState_GndB) { TerranMidGndB(player); }
else if (mainSubState == e_mainSubState_AirA) { TerranMidAirA(player); }
else if (mainSubState == e_mainSubState_AirB) { TerranMidAirB(player); }
else { ErrorMeleeScript(player, "Invalid Mid mainSubState"); }
}
//--------------------------------------------------------------------------------------------------
// TerranLate0
//--------------------------------------------------------------------------------------------------
void TerranLate0 (int player) {
int mainSubState = AIState(player, e_mainSubState);
if (mainSubState == e_mainSubState_GndA) { LateGnd(player); }
else if (mainSubState == e_mainSubState_AirA) { LateAir(player); }
else { ErrorMeleeScript(player, "Invalid Late mainSubState"); }
}
Terran.galaxy
//==================================================================================================
// Terran Melee AI
//==================================================================================================
include "TriggerLibs/Terran0"
//--------------------------------------------------------------------------------------------------
// Counter-Attack Units
//--------------------------------------------------------------------------------------------------
static void InitCounters (int player) {
//xxx lots of old data -- needs to be totally redone
// versus Protoss
AICounterUnit(player, c_PB_PhotonCannon, 0.50, c_TU_SiegeTank);
AICounterUnit(player, c_PU_Zealot, 1.00, c_TU_Hellion);
AICounterUnit(player, c_PU_Stalker, 1.00, c_TU_Marauder);
AICounterUnit(player, c_PU_Immortal, 2.00, c_TU_Marauder);
AICounterUnit(player, c_PU_Disruptor, 1.00, c_TU_Ghost);
AICounterUnit(player, c_PU_HighTemplar, 1.00, c_TU_Ghost);
AICounterUnit(player, c_PU_DarkTemplar, 1.00, c_TU_Hellion);
AICounterUnit(player, c_PU_Archon, 0.33, c_TU_Hellion);
AICounterUnit(player, c_PU_Colossus, 1.00, c_TU_Thor);
AICounterUnit(player, c_PU_VoidRay, 0.50, c_TU_Battlecruiser);
AICounterUnit(player, c_PU_Phoenix, 0.50, c_TU_BattlecruiserMissile);
AICounterUnit(player, c_PU_Carrier, 0.75, c_TU_BattlecruiserYamato);
// versus Terran
AICounterUnit(player, c_TB_Bunker, 0.33, c_TU_SiegeTank);
AICounterUnit(player, c_TU_Marine, 0.50, c_TU_Hellion);
AICounterUnit(player, c_TU_Reaper, 0.70, c_TU_Hellion);
AICounterUnit(player, c_TU_Marauder, 0.50, c_TU_SiegeTank);
AICounterUnit(player, c_TU_Ghost, 2.00, c_TU_Hellion);
AICounterUnit(player, c_TU_Hellion, 0.25, c_TU_Thor);
AICounterUnit(player, c_TU_SiegeTank_Alias, 0.50, c_TU_Thor);
AICounterUnit(player, c_TU_Thor, 3.00, c_TU_Marauder);
AICounterUnit(player, c_TU_Viking_Alias, 1.00, c_TU_Viking);
AICounterUnit(player, c_TU_Banshee, 1.00, c_TU_Viking);
AICounterUnit(player, c_TU_BattlecruiserClass, 1.00, c_TU_BattlecruiserYamato);
// versus Zerg
AICounterUnit(player, c_ZB_SpineCrawler, 0.33, c_TU_SiegeTank);
AICounterUnit(player, c_ZU_Zergling, 0.25, c_TU_Hellion);
AICounterUnit(player, c_ZU_Roach, 0.80, c_TU_Marauder);
AICounterUnit(player, c_ZU_Hydralisk, 0.50, c_TU_Ghost);
AICounterUnit(player, c_ZU_Lurker, 1.00, c_TU_Marauder);
AICounterUnit(player, c_ZU_Infestor, 0.50, c_TU_Ghost);
AICounterUnit(player, c_ZU_Ultralisk, 1.00, c_TU_Thor);
AICounterUnit(player, c_ZU_Mutalisk, 0.80, c_TU_Viking);
AICounterUnit(player, c_ZU_Corruptor, 0.50, c_TU_Battlecruiser);
AICounterUnit(player, c_ZU_BroodLord, 0.50, c_TU_Viking);
}
//--------------------------------------------------------------------------------------------------
// TerranSubStateName
//--------------------------------------------------------------------------------------------------
string TerranSubStateName (int state) {
// TODO Call the individual difficulties to return a real substate name
return "-" + IntToString(state) + "-";
}
//--------------------------------------------------------------------------------------------------
// DebugCallbackTerr
//--------------------------------------------------------------------------------------------------
void DebugCallbackTerr (int player) {
DebugAI("=====TERRAN=====\n");
DebugMelee(player);
DebugAI("e_mainState = " + MainStateName(AIState(player, e_mainState)) +
", e_mainSubState = " + TerranSubStateName(AIState(player, e_mainSubState)) +
", e_attackState = " + AttackStateName(AIState(player, e_attackState))
);
}
//--------------------------------------------------------------------------------------------------
// AINewUnitTerr
//--------------------------------------------------------------------------------------------------
void AINewUnitTerr (int player, unit u) {
wave w;
string type = UnitGetType(u);
// ignored units
//
if (UnitTypeTestAttribute(type, c_unitAttributeStructure)) {
return;
}
if (UnitTypeTestFlag(type, c_unitFlagWorker)) {
return;
}
if (type == c_TU_Medivac) {
// TODO after normal scouting claims the ones it wants give the rest to the
// attack wave instead of the extra scout group
AIAddToExtraScoutGroup(player, u);
return;
}
// detector
//
if (type == c_TU_Raven) {
AINewDetector(player, u, false);
return;
}
// clear obstacle units
//
if (AIWaveNeedClearObsUnits(player)) {
if (type == c_TU_Marine || type == c_TU_Reaper || type == c_TU_Marauder) {
AIMergeUnit(player, u, AIWaveGet(player, c_waveClearObs));
return;
}
}
// diversion units
if (AIGetFlag(player, e_flagsDiversion)) {
if (type == c_TU_Reaper) {
AIMergeUnit(player, u, AIWaveGet(player, c_waveDivert1));
return;
}
if (type == c_TU_Banshee) {
AIMergeUnit(player, u, AIWaveGet(player, c_waveDivert2));
return;
}
}
// main wave units
//
AINewUnitDefault(player, u);
}
//--------------------------------------------------------------------------------------------------
// AIGetScoutTerr
//--------------------------------------------------------------------------------------------------
unit AIGetScoutTerr (int player, int index, unit prev) {
unit medivac;
if (!AIGetFlag(player, e_flagsScouting)) {
return c_nullUnit;
}
if (UnitGetType(prev) == c_TU_Medivac) {
return prev;
}
medivac = AIGrabUnit(player, c_TU_Medivac, c_prioScout, null);
if (medivac) {
return medivac;
}
if (prev) {
return prev;
}
if (AIGetFlag(player, e_flagsLateScout)) {
return c_nullUnit;
}
return AIGrabUnit(player, c_TU_SCV, c_prioScout, null);
}
//--------------------------------------------------------------------------------------------------
// AIEarlyDefScoutTerr
//--------------------------------------------------------------------------------------------------
unit AIEarlyDefScoutTerr (int player, unit prev) {
unit obs;
if (!AIGetFlag(player, e_flagsEarlyDefScout)) {
return c_nullUnit;
}
if (UnitGetType(prev) == c_TU_Medivac) {
return prev;
}
obs = AIGrabUnit(player, c_TU_Medivac, c_prioScout, null);
if (obs) {
return obs;
}
if (UnitGetType(prev) == c_TU_Marine) {
return prev;
}
obs = AIGrabUnit(player, c_TU_Marine, c_prioScout, null);
if (obs) {
return obs;
}
if (prev) {
return prev;
}
return AIGrabUnit(player, c_TU_SCV, c_prioScout, null);
}
Terran.galaxy < suite
//--------------------------------------------------------------------------------------------------
// AIWaveThinkTerr
//--------------------------------------------------------------------------------------------------
void AIWaveThinkTerr (int player, wave w, int type) {
AIWaveThinkDefault(player, w, type);
}
//--------------------------------------------------------------------------------------------------
// Terran Init
//--------------------------------------------------------------------------------------------------
static void TerranInit (int player) {
int state;
InitCounters(player);
AISetNumScouts(player, 1);
AISetFlag(player, e_flagsScouting, false);
AISetFlag(player, e_flagsEarlyDefScout, false);
AITechCountFixupEither(player, c_TB_CommandCenter, c_TB_OrbitalCommand, c_TB_PlanetaryFortress);
if (AIGetGroundStartLocs(PlayerStartLocation(player)) > 0) {
state = AIDiffEnum(player, e_mainState_OpenGnd0);
}
else {
state = AIDiffEnum(player, e_mainState_OpenAir0);
}
AISetMainState(player, state, e_mainSubState_Unset);
}
//--------------------------------------------------------------------------------------------------
// AIMeleeTerr
//--------------------------------------------------------------------------------------------------
void AIMeleeTerr (int player) {
int mainState = AIState(player, e_mainState);
if (mainState == e_mainState_Init) { TerranInit(player); }
else if (mainState == e_mainState_OpenGnd0) { TerranOpenGnd0(player); }
//else if (mainState == e_mainState_OpenGnd1) { TerranOpenGnd1(player); }
//else if (mainState == e_mainState_OpenGnd2) { TerranOpenGnd2(player); }
//else if (mainState == e_mainState_OpenGnd3) { TerranOpenGnd3(player); }
//else if (mainState == e_mainState_OpenGnd4) { TerranOpenGnd4(player); }
//else if (mainState == e_mainState_OpenGnd5) { TerranOpenGnd5(player); }
else if (mainState == e_mainState_OpenAir0) { TerranOpenAir0(player); }
//else if (mainState == e_mainState_OpenAir1) { TerranOpenAir1(player); }
//else if (mainState == e_mainState_OpenAir2) { TerranOpenAir2(player); }
//else if (mainState == e_mainState_OpenAir3) { TerranOpenAir3(player); }
//else if (mainState == e_mainState_OpenAir4) { TerranOpenAir4(player); }
//else if (mainState == e_mainState_OpenAir5) { TerranOpenAir5(player); }
else if (mainState == e_mainState_Mid0) { TerranMid0(player); }
//else if (mainState == e_mainState_Mid1) { TerranMid1(player); }
//else if (mainState == e_mainState_Mid2) { TerranMid2(player); }
//else if (mainState == e_mainState_Mid3) { TerranMid3(player); }
//else if (mainState == e_mainState_Mid4) { TerranMid4(player); }
//else if (mainState == e_mainState_Mid5) { TerranMid5(player); }
else if (mainState == e_mainState_Late0) { TerranLate0(player); }
//else if (mainState == e_mainState_Late1) { TerranLate1(player); }
//else if (mainState == e_mainState_Late2) { TerranLate2(player); }
//else if (mainState == e_mainState_Late3) { TerranLate3(player); }
//else if (mainState == e_mainState_Late4) { TerranLate4(player); }
//else if (mainState == e_mainState_Late5) { TerranLate5(player); }
else if (mainState == e_mainState_Off) { EndMeleeScript(player); }
else if (mainState == e_mainState_Disabled) { }
else { ErrorMeleeScript(player, "Invalid mainState"); }
}
Zerg0.galaxy
//==================================================================================================
// Zerg Melee Very Easy
//==================================================================================================
static void RandomInfantry (int player);
static void LateGround (int player);
//--------------------------------------------------------------------------------------------------
// ZergOpenGnd0
//--------------------------------------------------------------------------------------------------
void ZergOpenGnd0 (int player) {
AIClearStock(player);
AISetStock( player, 1, c_ZB_Hatchery_Alias );
AISetStock( player, 2, c_ZU_Drone );
AISetStock( player, 1, c_ZU_Overlord );
AISetStock( player, 8, c_ZU_Drone );
AISetStock( player, 1, c_ZB_Extractor );
AISetStock( player, 1, c_ZU_Queen );
AISetStock( player, 2, c_ZU_Overlord_Alias );
// around 100 resources in about 2 units
AISetStock( player, 1, c_ZU_Hydralisk );
ZergTechUp(player, 1);
if (AIEnableVeryEasyStockOpen(player, c_ZU_Drone)) {
return;
}
// around 300 resources in about 3 unit
RandomInfantry(player);
}
//--------------------------------------------------------------------------------------------------
// ZergMidGndA
//--------------------------------------------------------------------------------------------------
static void ZergMidGndA (int player) {
AIClearStock(player);
AIDefaultEconomy(player, c_ZB_Hatchery_Alias, c_ZB_Extractor, c_ZU_Overlord_Alias, c_ZU_Drone, 8, c_stockIdle);
if (AISawCloakedUnit(player)) {
AISetStock( player, 1, c_ZU_Overseer );
}
AISetStockUserData(player);
AISetStock( player, 1, c_ZU_Queen );
ZergTechUp(player, 2);
if (AIEnableVeryEasyStockMidA(player, c_ZU_Drone, 3)) {
return;
}
// around 600 resources in about 4 unit
RandomInfantry(player);
AIAddStringInt(player, c_ZU_Infestor, 1);
}
//--------------------------------------------------------------------------------------------------
// ZergMidGndB
//--------------------------------------------------------------------------------------------------
static void ZergMidGndB (int player) {
AIClearStock(player);
AIDefaultEconomy(player, c_ZB_Hatchery_Alias, c_ZB_Extractor, c_ZU_Overlord_Alias, c_ZU_Drone, 8, c_stockIdle);
if (AISawCloakedUnit(player)) {
AISetStock( player, 1, c_ZU_Overseer );
AISetStock( player, 2, c_ZB_SporeCrawler );
}
AISetStockUserData(player);
AISetStock( player, 1, c_ZU_Queen );
ZergTechUp(player, 3);
if (AIEnableVeryEasyStockMidB(player, c_ZU_Drone, 4)) {
return;
}
// around 900 resources in about 5 unit
LateGround(player);
}
//--------------------------------------------------------------------------------------------------
// LateGround
//--------------------------------------------------------------------------------------------------
static void LateGround (int player) {
int roll = RandomInt(0,2); // infestors
if (roll == 0) {
AIAddStringInt(player, c_ZU_Zergling, 1);
roll = RandomInt(2,6);
AIAddStringInt(player, c_ZU_Hydralisk, roll);
AIAddStringInt(player, c_ZU_Roach, 8 - roll);
}
else if (roll == 1) {
AIAddStringInt(player, c_ZU_Zergling, 1);
roll = RandomInt(2,3);
AIAddStringInt(player, c_ZU_Hydralisk, roll);
AIAddStringInt(player, c_ZU_Roach, 5 - roll);
AIAddStringInt(player, c_ZU_Infestor, 1);
}
else { // infestors == 2
AIAddStringInt(player, AIPickFrom2(c_ZU_Zergling, c_ZU_Roach), 1);
AIAddStringInt(player, c_ZU_Hydralisk, 2);
AIAddStringInt(player, c_ZU_Infestor, 2);
}
}
//--------------------------------------------------------------------------------------------------
// LateGnd
//--------------------------------------------------------------------------------------------------
static void LateGnd (int player) {
AIClearStock(player);
AIDefaultEconomy(player, c_ZB_Hatchery_Alias, c_ZB_Extractor, c_ZU_Overlord, c_ZU_Drone, 8, c_stockIdle);
AIDefaultExpansion(player, c_ZB_Hatchery_Alias, 6000, 0, c_expandDefault);
AISetStockUserData(player);
AISetStock( player, 1, c_ZR_OverlordTransport );
AISetStock( player, 3, c_ZU_Overseer );
ZergTechUp(player, 4);
if (AIEnableVeryEasyStockLate(player, c_TU_SCV, 4)) {
return;
}
LateGround(player);
}
//--------------------------------------------------------------------------------------------------
// ZergOpenAir0
//--------------------------------------------------------------------------------------------------
void ZergOpenAir0 (int player) {
fixed time = AIGetTime();
AIClearStock(player);
AISetGasPeons(player, 3, c_ZU_Drone, c_ZB_Extractor );
AISetStock( player, 1, c_ZB_Hatchery_Alias );
AISetStock( player, 1, c_ZU_Overlord );
AISetStock( player, 10, c_ZU_Drone );
AISetStock( player, 1, c_ZB_Extractor );
AISetStock( player, 1, c_ZB_SpawningPool );
if (time >= 150) {
AISetStock( player, 2, c_ZB_Extractor );
AISetStock( player, 1, c_ZB_Lair );
if (time >= 200) {
AISetStock( player, 2, c_ZU_Overlord );
AISetStock( player, 1, c_ZB_Spire );
AISetStock( player, 1, c_ZU_Queen );
AISetStock( player, 1, c_ZB_HydraliskDen );
AISetStock( player, 1, c_ZU_Mutalisk );
AISetStock( player, 2, c_ZU_Hydralisk );
AISetGasPeons(player, 4, c_ZU_Drone, c_ZB_Extractor );
}
}
AIEnableStock(player);
//---------------------------------------------------------
if (AITechCount(player, c_ZU_Mutalisk, c_techCountCompleteOnly) < 1) {
return;
}
AIWaveMerge(player, c_waveMain, c_waveAttack);
AISetAttackState(player, e_attackState_Attack);
AISetMainState(player, e_mainState_Mid1, e_mainSubState_AirA);
}
//--------------------------------------------------------------------------------------------------
// ZergMidAirA
//--------------------------------------------------------------------------------------------------
static void ZergMidAirA (int player) {
AIClearStock(player);
AIDefaultEconomy(player, c_ZB_Hatchery_Alias, c_ZB_Extractor, c_ZU_Overlord, c_ZU_Drone, 8, c_stockIdle);
AISetStock( player, 1, c_ZU_Queen );
AISetStock( player, 1, c_ZB_Lair );
AISetStock( player, 1, c_ZU_Mutalisk );
AISetStock( player, 2, c_ZU_Hydralisk );
AISetStock( player, 1, c_ZR_OverlordTransport );
AISetStock( player, 1, c_ZU_Overseer );
AISetStock( player, 1, c_ZB_EvolutionChamber );
AISetStock( player, 2, c_ZU_Mutalisk );
AISetStock( player, 3, c_ZB_SporeCrawler );
AISetStock( player, 1, c_ZU_Corruptor );
AIEnableStock(player);
AISetGasPeons(player, 4, c_ZU_Drone, c_ZB_Extractor );
//---------------------------------------------------------
if (AITechCount(player, c_ZU_Corruptor, c_techCountCompleteOnly) < 1) {
return;
}
AIWaveMerge(player, c_waveMain, c_waveAttack);
AISetAttackState(player, e_attackState_Attack);
AISetMainState(player, e_mainState_Mid1, e_mainSubState_AirB);
}
//--------------------------------------------------------------------------------------------------
// ZergMidAirB
//--------------------------------------------------------------------------------------------------
static void ZergMidAirB (int player) {
AIClearStock(player);
AIDefaultEconomy(player, c_ZB_Hatchery_Alias, c_ZB_Extractor, c_ZU_Overlord, c_ZU_Drone, 8, c_stockIdle);
AIDefaultExpansion(player, c_ZB_Hatchery_Alias, 6000, 1000, c_expandDefault);
AISetStock( player, 1, c_ZU_Queen );
AISetStock( player, 2, c_ZU_Mutalisk );
AISetStock( player, 2, c_ZU_Hydralisk );
AISetStock( player, 1, c_ZR_OverlordTransport );
AISetStock( player, 1, c_ZR_OverseerSpeed );
AISetStock( player, 1, c_ZU_Overseer );
AISetStock( player, 3, c_ZB_SporeCrawler );
AISetStock( player, 1, c_ZU_Corruptor );
AISetStock( player, 3, c_ZU_Mutalisk );
AISetStock( player, 2, c_ZU_Corruptor );
AIEnableStock(player);
AISetGasPeons(player, 4, c_ZU_Drone, c_ZB_Extractor );
//---------------------------------------------------------
if (AIGetTime() < 1200) {
return;
}
AIWaveMerge(player, c_waveMain, c_waveAttack);
AISetAttackState(player, e_attackState_Attack);
AISetMainState(player, e_mainState_Late1, e_mainSubState_AirA);
AISetFlag(player, e_flagsScouting, true);
AISetFlag(player, e_flagsClearObs, true);
}
//--------------------------------------------------------------------------------------------------
// LateAir
//--------------------------------------------------------------------------------------------------
static void LateAir (int player) {
AIClearStock(player);
AIDefaultEconomy(player, c_ZB_Hatchery_Alias, c_ZB_Extractor, c_ZU_Overlord, c_ZU_Drone, 8, c_stockIdle);
AIDefaultExpansion(player, c_ZB_Hatchery_Alias, 6000, 1000, c_expandDefault);
AISetStock( player, 1, c_ZU_Queen );
AISetStock( player, 2, c_ZU_Mutalisk );
AISetStock( player, 2, c_ZU_Hydralisk );
AISetStock( player, 1, c_ZR_OverlordTransport );
AISetStock( player, 1, c_ZR_OverseerSpeed );
AISetStock( player, 2, c_ZU_Overseer );
AISetStock( player, 3, c_ZB_SporeCrawler );
AISetStock( player, 1, c_ZU_Corruptor );
AISetStock( player, 4, c_ZU_Mutalisk );
AISetStock( player, 3, c_ZU_Corruptor );
AISetStock( player, 1, c_ZU_BroodLord );
AISetStock( player, 4, c_ZU_Overseer );
AISetStock( player, 1, c_ZR_CorruptorAttack );
AIEnableStock(player);
AISetGasPeons(player, 4, c_ZU_Drone, c_ZB_Extractor );
//---------------------------------------------------------
if (AIGetTime() % 300 > 5) {
return;
}
AIWaveMerge(player, c_waveMain, c_waveAttack);
AISetAttackState(player, e_attackState_Attack);
AISetFlag(player, e_flagsScouting, true);
AISetFlag(player, e_flagsClearObs, true);
}
//--------------------------------------------------------------------------------------------------
// RandomInfantry
//--------------------------------------------------------------------------------------------------
static void RandomInfantry (int player) {
AIAddStringInt(player, c_ZU_Hydralisk, 1);
AIAddStringInt(player, AIPickFrom2(c_ZU_Hydralisk, c_ZU_Roach), 1);
AIAddStringInt(player, AIPickFrom2(c_ZU_Zergling, c_ZU_Roach), 1);
}
//--------------------------------------------------------------------------------------------------
// ZergMid0
//--------------------------------------------------------------------------------------------------
void ZergMid0 (int player) {
int mainSubState = AIState(player, e_mainSubState);
if (mainSubState == e_mainSubState_GndA) { ZergMidGndA(player); }
else if (mainSubState == e_mainSubState_GndB) { ZergMidGndB(player); }
else if (mainSubState == e_mainSubState_AirA) { ZergMidAirA(player); }
else if (mainSubState == e_mainSubState_AirB) { ZergMidAirB(player); }
else { ErrorMeleeScript(player, "Invalid Mid mainSubState"); }
}
//--------------------------------------------------------------------------------------------------
// ZergLate0
//--------------------------------------------------------------------------------------------------
void ZergLate0 (int player) {
int mainSubState = AIState(player, e_mainSubState);
if (mainSubState == e_mainSubState_GndA) { LateGnd(player); }
else if (mainSubState == e_mainSubState_AirA) { LateAir(player); }
else { ErrorMeleeScript(player, "Invalid Late mainSubState"); }
}
Zerg.galaxy
//==================================================================================================
// Zerg Melee AI
//==================================================================================================
include "TriggerLibs/Zerg0"
//--------------------------------------------------------------------------------------------------
// Counter-Attack Units
//--------------------------------------------------------------------------------------------------
static void InitCounters (int player) {
//xxx lots of old data -- needs to be totally redone
// versus Protoss
AICounterUnit(player, c_PU_Zealot, 1.00, c_ZU_Baneling);
AICounterUnit(player, c_PU_Stalker, 1.00, c_ZU_Roach);
AICounterUnit(player, c_PU_Immortal, 8.00, c_ZU_Zergling);
AICounterUnit(player, c_PU_HighTemplar, 2.00, c_ZU_Roach);
AICounterUnit(player, c_PU_Disruptor, 4.00, c_ZU_Zergling);
AICounterUnit(player, c_PU_Archon, 4.00, c_ZU_Zergling);
AICounterUnit(player, c_PU_Archon, 2.00, c_ZU_Hydralisk);
AICounterUnit(player, c_PU_Archon, 2.00, c_ZU_Roach);
AICounterUnit(player, c_PU_Colossus, 1.00, c_ZU_Mutalisk);
AICounterUnit(player, c_PU_VoidRay, 2.00, c_ZU_Corruptor);
AICounterUnit(player, c_PU_VoidRay, 1.00, c_ZU_Mutalisk);
AICounterUnit(player, c_PU_Phoenix, 2.00, c_ZU_Hydralisk);
AICounterUnit(player, c_PU_Carrier, 2.00, c_ZU_Hydralisk);
AICounterUnit(player, c_PU_Carrier, 2.00, c_ZU_Corruptor);
// versus Terran
AICounterUnit(player, c_TU_Marine, 0.60, c_ZU_Baneling);
AICounterUnit(player, c_TU_Marauder, 3.00, c_ZU_Zergling);
AICounterUnit(player, c_TU_Hellion, 0.60, c_ZU_Roach);
AICounterUnit(player, c_TU_Ghost, 6.00, c_ZU_Zergling);
AICounterUnit(player, c_TU_SiegeTank_Alias, 6.00, c_ZU_Zergling);
AICounterUnit(player, c_TU_Reaper, 0.30, c_ZU_Mutalisk);
AICounterUnit(player, c_TU_Thor, 12.00, c_ZU_Zergling);
AICounterUnit(player, c_TU_Banshee, 0.50, c_ZU_Mutalisk);
AICounterUnit(player, c_TU_BattlecruiserClass, 2.00, c_ZU_Corruptor);
AICounterUnit(player, c_TU_BattlecruiserClass, 2.00, c_ZU_Hydralisk);
// versus Zerg
AICounterUnit(player, c_ZU_Zergling, 0.25, c_ZU_Baneling);
AICounterUnit(player, c_ZU_Baneling, 0.25, c_ZU_Lurker);
AICounterUnit(player, c_ZU_Roach, 3.00, c_ZU_Zergling);
AICounterUnit(player, c_ZU_Hydralisk, 1.00, c_ZU_Hydralisk);
AICounterUnit(player, c_ZU_Lurker, 1.50, c_ZU_Hydralisk);
AICounterUnit(player, c_ZU_Mutalisk, 0.50, c_ZU_Mutalisk);
AICounterUnit(player, c_ZU_Mutalisk, 0.50, c_ZU_Corruptor);
AICounterUnit(player, c_ZU_Corruptor, 1.00, c_ZU_Corruptor);
AICounterUnit(player, c_ZU_BroodLord, 0.50, c_ZU_Corruptor);
}
//--------------------------------------------------------------------------------------------------
// ZergSubStateName
//--------------------------------------------------------------------------------------------------
string ZergSubStateName (int state) {
// TODO Call the individual difficulties to return a real substate name
return "-" + IntToString(state) + "-";
}
//--------------------------------------------------------------------------------------------------
// DebugCallbackZerg
//--------------------------------------------------------------------------------------------------
void DebugCallbackZerg (int player) {
DebugAI("=====ZERG=====\n");
DebugMelee(player);
DebugAI("e_mainState = " + MainStateName(AIState(player, e_mainState)) +
", e_mainSubState = " + ZergSubStateName(AIState(player, e_mainSubState)) +
", e_attackState = " + AttackStateName(AIState(player, e_attackState))
);
}
//--------------------------------------------------------------------------------------------------
// AINewUnitZerg
//--------------------------------------------------------------------------------------------------
void AINewUnitZerg (int player, unit u) {
wave w;
string type = UnitGetType(u);
// ignored units
//
if (type == c_ZU_Larva ||
type == c_ZU_Broodling ||
type == c_ZU_Mantaling) {
return;
}
if (UnitTypeTestAttribute(type, c_unitAttributeStructure)) {
return;
}
if (UnitTypeTestFlag(type, c_unitFlagWorker)) {
return;
}
// units that stay near home
//
if (type == c_ZB_SpineCrawler || type == c_ZB_SporeCrawler) {
AIWaveAddUnitPriority(AIWaveGet(player, c_waveHome), u, c_prioWavePeon);
return;
}
if (type == c_ZU_Queen) {
AIWaveAddUnitPriority(AIWaveGet(player, c_waveHome), u, c_prioWavePeon);
return;
}
// detector
//
if (type == c_ZU_Overseer) {
AINewDetector(player, u, true);
return;
}
// extra scout units
//
if (type == c_ZU_Overlord || type == c_ZU_OverlordCocoon ) {
AIAddToExtraScoutGroup(player, u);
return;
}
// clear obstacle units
//
if (AIWaveNeedClearObsUnits(player)) {
if (type == c_ZU_Zergling || type == c_ZU_Roach || type == c_ZU_Hydralisk) {
AIMergeUnit(player, u, AIWaveGet(player, c_waveClearObs));
return;
}
}
// main wave units
//
AINewUnitDefault(player, u);
}
//--------------------------------------------------------------------------------------------------
// AIGetScoutZerg
//--------------------------------------------------------------------------------------------------
unit AIGetScoutZerg (int player, int index, unit prev) {
unit seer;
if (!AIGetFlag(player, e_flagsScouting)) {
return c_nullUnit;
}
if (UnitGetType(prev) == c_ZU_Overseer) {
return prev;
}
seer = AIGrabUnit(player, c_ZU_Overseer, c_prioScout, null);
if (seer) {
return seer;
}
if (prev) {
return prev;
}
if (AIGetFlag(player, e_flagsLateScout)) {
return c_nullUnit;
}
return AIGrabUnit(player, c_ZU_Overlord, c_prioScout, null);
}
//--------------------------------------------------------------------------------------------------
// AIEarlyDefScoutZerg
//--------------------------------------------------------------------------------------------------
unit AIEarlyDefScoutZerg (int player, unit prev) {
unit obs;
if (!AIGetFlag(player, e_flagsEarlyDefScout)) {
return c_nullUnit;
}
if (UnitGetType(prev) == c_ZU_Overseer) {
return prev;
}
obs = AIGrabUnit(player, c_ZU_Overseer, c_prioScout, null);
if (obs) {
return obs;
}
if (UnitGetType(prev) == c_ZU_Zergling) {
return prev;
}
obs = AIGrabUnit(player, c_ZU_Zergling, c_prioScout, null);
if (obs) {
return obs;
}
if (prev) {
return prev;
}
return AIGrabUnit(player, c_ZU_Drone, c_prioScout, null);
}
//--------------------------------------------------------------------------------------------------
// AIWaveThinkZerg
//--------------------------------------------------------------------------------------------------
void AIWaveThinkZerg (int player, wave w, int type) {
AIWaveThinkDefault(player, w, type);
}
//--------------------------------------------------------------------------------------------------
// Zerg Init
//--------------------------------------------------------------------------------------------------
static void ZergInit (int player) {
int state;
InitCounters(player);
AISetNumScouts(player, 1);
AISetFlag(player, e_flagsScouting, true);
AISetFlag(player, e_flagsEarlyDefScout, false);
AIReqCountAsBuiltObject(player, c_ZU_Larva);
AITechCountFixupSingle(player, c_ZB_HydraliskDen, c_ZB_LurkerDen);
AITechCountFixupSingle(player, c_ZB_Spire, c_ZB_GreaterSpire);
AITechCountFixupInOrder(player, c_ZB_Hatchery, c_ZB_Lair, c_ZB_Hive);
AISetCreepBuilding(player, c_ZB_CreepTumor, "ZergBuildingNotOnCreep");
if (AIGetGroundStartLocs(PlayerStartLocation(player)) > 0) {
state = AIDiffEnum(player, e_mainState_OpenGnd0);
}
else {
state = AIDiffEnum(player, e_mainState_OpenAir0);
}
AISetMainState(player, state, e_mainSubState_Unset);
}
//--------------------------------------------------------------------------------------------------
// AIMeleeZerg
//--------------------------------------------------------------------------------------------------
void AIMeleeZerg (int player) {
int mainState = AIState(player, e_mainState);
if (mainState == e_mainState_Init) { ZergInit(player); }
else if (mainState == e_mainState_OpenGnd0) { ZergOpenGnd0(player); }
//else if (mainState == e_mainState_OpenGnd1) { ZergOpenGnd1(player); }
//else if (mainState == e_mainState_OpenGnd2) { ZergOpenGnd2(player); }
//else if (mainState == e_mainState_OpenGnd3) { ZergOpenGnd3(player); }
//else if (mainState == e_mainState_OpenGnd4) { ZergOpenGnd4(player); }
//else if (mainState == e_mainState_OpenGnd5) { ZergOpenGnd5(player); }
else if (mainState == e_mainState_OpenAir0) { ZergOpenAir0(player); }
//else if (mainState == e_mainState_OpenAir1) { ZergOpenAir1(player); }
//else if (mainState == e_mainState_OpenAir2) { ZergOpenAir2(player); }
//else if (mainState == e_mainState_OpenAir3) { ZergOpenAir3(player); }
//else if (mainState == e_mainState_OpenAir4) { ZergOpenAir4(player); }
//else if (mainState == e_mainState_OpenAir5) { ZergOpenAir5(player); }
else if (mainState == e_mainState_Mid0) { ZergMid0(player); }
//else if (mainState == e_mainState_Mid1) { ZergMid1(player); }
//else if (mainState == e_mainState_Mid2) { ZergMid2(player); }
//else if (mainState == e_mainState_Mid3) { ZergMid3(player); }
//else if (mainState == e_mainState_Mid4) { ZergMid4(player); }
//else if (mainState == e_mainState_Mid5) { ZergMid5(player); }
else if (mainState == e_mainState_Late0) { ZergLate0(player); }
//else if (mainState == e_mainState_Late1) { ZergLate1(player); }
//else if (mainState == e_mainState_Late2) { ZergLate2(player); }
//else if (mainState == e_mainState_Late3) { ZergLate3(player); }
//else if (mainState == e_mainState_Late4) { ZergLate4(player); }
//else if (mainState == e_mainState_Late5) { ZergLate5(player); }
else if (mainState == e_mainState_Off) { EndMeleeScript(player); }
else if (mainState == e_mainState_Disabled) { }
else { ErrorMeleeScript(player, "Invalid mainState"); }
}
Ok I am done, you can discuss ^^ . Hope it will come to help for someone
What about the protoss one ?
Annoying playing a TvT. I tried multiple strats, but the only way I was able to win on burning steps (1v1 map) was to do a gay 100 gas, double barracks dual reactor marine spam rush. Very impressive AI though, the hacked resources make it a damn good challenge.
Found all the native function calls and a bunch more enums.
From Core.SC2Data\TriggerLibs\AI.galaxy:
//==================================================================================================
// AI Native Function Prototypes
//==================================================================================================
include "TriggerLibs/RequirementsAI"
include "TriggerLibs/BuildAI"
const int c_ScoutStartLocations = 0;
const int c_ScoutBlockedPath = 1;
const int c_ScoutMinerals = 2;
const int c_ScoutDefault = 3;
const int c_ScoutPlayers = 4;
const int c_noFlags = 0;
const point c_nullPoint = null;
const marker c_noMarker = null;
const string c_noTech = null;
const abilcmd c_nullCmd = null;
const wave c_nullWave = null;
const unit c_nullUnit = null;
const bool c_stockIdle = true;
const bool c_stockAlways = false;
const bool c_stockMinPeons = true;
const bool c_stockMaxPeons = false;
const bool c_stockNeededFarms = true;
const bool c_stockNormalFarms = false;
const int c_allEnemies = -1;
const int c_defaultGasPeonCount = -1;
const int c_expandDefault = 1;
const int c_expandVitalHard = 4;
const int c_expandNormalHard = 6;
const int c_unitAttributeNone = -1;
//--------------------------------------------------------------------------------------------------
// Unit Order Priorities
//--------------------------------------------------------------------------------------------------
// needs to match the order in Brain.h
const int c_prioNone = 0;
const int c_prioExtraScout = 1;
const int c_prioWorkerJob = 2;
const int c_prioUseableBully = 3;
const int c_prioStaticBully = 4;
const int c_prioGather = 5;
const int c_prioExpand = 6;
const int c_prioCombat = 7;
const int c_prioWaveIdle = 8;
const int c_prioScout = 9;
const int c_prioEarlyDefense = 10;
const int c_prioWavePeon = 11;
const int c_prioWave = 12;
const int c_prioTransport = 13;
const int c_prioDetect = 14;
const int c_prioNuke = 15;
const int c_prioScriptControlled = 16;
//--------------------------------------------------------------------------------------------------
// Races
//--------------------------------------------------------------------------------------------------
const int c_raceProtoss = 1;
const int c_raceTerran = 2;
const int c_raceZerg = 3;
//--------------------------------------------------------------------------------------------------
// Build and Train Priorities
//--------------------------------------------------------------------------------------------------
// needs to match the values in Captain.h
const int c_makePriorityLowest = 0;
const int c_makePriorityBully = 1;
const int c_makePriorityTown = 2;
const int c_makePriorityResearch = 3;
const int c_makePriorityAttack = 4;
const int c_makePriorityDefense = 5;
const int c_makePriorityExpand = 6;
const int c_makePriorityContinue = 7;
const int c_makePriorityPowerCreep = 8;
const int c_makePriorityDropoff = 9;
const int c_makePriorityHighest = 10;
//--------------------------------------------------------------------------------------------------
// Town Locations
//--------------------------------------------------------------------------------------------------
const int c_townInvalid = -2;
const int c_townMain = -1;
const int c_townOne = 0;
const int c_townTwo = 1;
const int c_townThree = 2;
const int c_townFour = 3;
const int c_townFive = 4;
const int c_townSix = 5;
const int c_townSeven = 6;
const int c_townEight = 7;
const int c_townMax = 32;
//--------------------------------------------------------------------------------------------------
// Town States
//--------------------------------------------------------------------------------------------------
const int c_townStateInvalid = -1;
const int c_townStateUnused = 0;
const int c_townStateClaimed = 1;
const int c_townStateEstablished = 2;
//--------------------------------------------------------------------------------------------------
// Wave States
//--------------------------------------------------------------------------------------------------
// needs to match CWave::EWaveType
const int c_waveStateUnknown = 0;
const int c_waveStateIdle = 1;
const int c_waveStateSuicide = 2;
const int c_waveStateMerge = 3;
const int c_waveStateAttack = 4;
const int c_waveStateDropAttack = 5;
const int c_waveStateDefend = 6;
const int c_waveStateScout = 7;
const int c_waveStateRetreat = 8;
const int c_waveStateDropRetreat = 9;
const int c_waveStateClearObs = 10;
const int c_waveStateGuardHome = 11;
//--------------------------------------------------------------------------------------------------
// Wave Default Names
//--------------------------------------------------------------------------------------------------
const int c_waveMain = 0;
const int c_waveDefend = 1;
const int c_waveAttack = 2;
const int c_waveDivert1 = 3;
const int c_waveDivert2 = 4;
const int c_waveClearObs = 5;
const int c_waveHome = 6;
//--------------------------------------------------------------------------------------------------
// Defense Threat Query Flags
//--------------------------------------------------------------------------------------------------
const int c_dtAnyThreat = 1;
const int c_dtClosestThreat = 2;
const int c_dtRealThreat = 4;
const int c_dtAnyRealThreat = 5;
const int c_closestRealThreat = 6;
const int c_dtAllowCantAttack = 8;
const int c_dtEvalAllThreats = 2;
const int c_dtEvalRealThreats = 6;
//--------------------------------------------------------------------------------------------------
// Best Target Flags
//--------------------------------------------------------------------------------------------------
// Needs to match the flags in CCaptain
const int c_btNeedsPath = 1;
const int c_btBuildingOrNeedsPath = 2;
const int c_btPrefersPath = 4;
const int c_btAllowJumping = 8;
const int c_btSortByDistance = 16;
const int c_btSortByFullType = 32;
const int c_btSortByLeastRecent = 64;
const int c_btDefaultNeedsPath = 49;
const int c_btDefaultPrefersPath = 52;
//--------------------------------------------------------------------------------------------------
// Breakpoint Routines
//--------------------------------------------------------------------------------------------------
native void DebugString (string value);
native void DebugUnit (unit value);
native void DebugInt (int value);
native void DebugFixed (fixed value);
native void DebugPoint (point value);
//--------------------------------------------------------------------------------------------------
// Difficulty
//--------------------------------------------------------------------------------------------------
const int c_diffAdvanceWave = 0;
const int c_diffRepairDamage = 1;
const int c_diffFleeDamage = 2;
const int c_diffOptimizeGas = 3;
const int c_diffDefendWithPeons = 4;
const int c_diffNormalVision = 5;
const int c_diffLimitAPM = 6;
const int c_diffAutoLoadBunkers = 7;
const int c_diffEarlyGameRepair = 8;
const int c_diffEnableDangerMap = 9;
const int c_diffWaveAvoidDanger = 10;
const int c_diffNormalTargetPrio = 11;
const int c_diffEarlyDefenseScout = 12;
native void AISetDifficulty (int player, int index, bool state);
native bool AIGetDifficulty (int player, int index);
//--------------------------------------------------------------------------------------------------
// Utility
//--------------------------------------------------------------------------------------------------
native void AIStart (int player, bool isCampaign, int apm);
native bool AIGivingUp (int player);
native void AIGoodGame (int player);
native bool AIIsCampaign (int player);
native void AISetAPM (int player, int apm);
native unit AIGrabUnit (int player, string aliasUnitType, int prio, point location);
native int AIState (int player, int index);
native void AISetSpecificState (int player, int index, int state);
native void AISetAllStates (int player, int state);
native void AISetFlag (int player, int index, bool state);
native bool AIGetFlag (int player, int index);
native void AITechFlag (int player, int index, int count, string what, int state);
native void AIResetUserData (int player);
native void AISetUserString (int player, int index, string data);
native string AIGetUserString (int player, int index);
native void AISetUserInt (int player, int index, int data);
native int AIGetUserInt (int player, int index);
native void AIAddStringInt (int player, string data, int change);
native fixed AIGetTime ();
native int AIGetTotalStartLocs ();
native int AIGetGroundStartLocs (point loc);
native int AIGetAirStartLocs (point loc);
native int AIGetTotalTownLocs ();
native int AIGetGroundTownLocs (point loc);
native int AIGetAirTownLocs (point loc);
native int AIRandomVal (int player, int which);
native void AINewChooseSubState (int player, int which, int min, int max, int defaultSubState);
native void AISetSubStateChance (int subState, int chance);
native int AIChooseSubState ();
native bool AIWantsMultipleTransport (int player);
native void AISetWantsMultipleTransport (int player, bool enable);
native int AIGetNumMobileTransports (int player);
native point AIGetBestCreepSpot (int player, unit creator, fixed createRadius);
native void AIAddDetectionDanger (int player, string unitType);
native bool AIDefaultSuspectDetectionDanger (int player);
native bool AIAnyWorkersFleeingNearby (int player, point loc, fixed radius);
native int AIGetNumEnemies (int player);
native int AIGetNumAllies (int player);
native point AIPlacementNearbyFindTest (int player, point loc, fixed range, string unitType);
native void AIAddToExtraScoutGroup (int player, unit u);
native bool AIOfferNewScout (int player, unit u);
//--------------------------------------------------------------------------------------------------
// Misc Melee
//--------------------------------------------------------------------------------------------------
const int c_skirVeryEasy = 0; // difficulty settings
const int c_skirEasy = 1;
const int c_skirMedium = 2;
const int c_skirHard = 3;
const int c_skirVeryHard = 4;
const int c_skirCheater = 5;
native bool AIAnyAllyAttacking (int player);
native point AIBestAllyAttackPoint (int player, wave w);
native bool AIAnyAllyNeedsDefending (int player);
native point AIBestAllyDefendPoint (int player, wave w);
//--------------------------------------------------------------------------------------------------
// Misc Campaign
//--------------------------------------------------------------------------------------------------
const int c_campBeginner = 0; // difficulty settings
const int c_campNormal = 1;
const int c_campAdvanced = 2;
const int c_campExpert = 3;
native void AIGlobalSuicide (int player);
native wave AIUnitGetWave (unit u);
native unitgroup AIWaveGetUnits (wave w);
native unitgroup AIGetAllEscorts (unit u);
native unitgroup AIGetAllEscortsGroup (unitgroup ug);
native void AIRemoveUnitFromAnyWaves (unit u);
native void AIRemoveGroupFromAnyWaves (unitgroup ug);
native unitgroup AIGetUnitsInWavesWithTarget (int player, wavetarget target);
native bool AIIsScriptControlled (unit u);
native void AISetUnitScriptControlled (unit u, bool enable);
native void AISetGroupScriptControlled (unitgroup ug, bool enable);
native bool AIIsSuicideUnit (unit u);
native void AISetUnitSuicide (unit u, bool enable);
native void AISetGroupSuicide (unitgroup ug, bool enable);
native bool AIIsNotUsableInWaves (unit u);
native void AISetUnitNotUsableInWaves (unit u, bool enable);
native void AISetGroupNotUsableInWaves (unitgroup ug, bool enable);
native void AISetWantsToUpgrade (unit u);
native void AIInitCampaignTowns (int player);
native void AIInitCampaignHarvest (int player);
//--------------------------------------------------------------------------------------------------
// Towns
//--------------------------------------------------------------------------------------------------
native void AIDeclareTown (int player, int town, point center);
native int AIGetMainTown (int player);
native void AISetMainTown (int player, int maintown);
native void AIUpdateMainTown (int player);
native int AIGetTownState (int player, int town);
native fixed AIGetTownEstablishedTime (int player, int town);
native point AIGetTownLocation (int player, int town);
native int AIGetClosestTown (int player, point location);
native int AIGetNextUnusedTownSlot (int player);
native int AIGetBuildingCountInTown (int player, int town, string aliasUnitType, int countMask);
native bool AIIsTownHarvestRunning (int player, int town);
native void AIHarvest (int player, int town);
native void AIHarvestRate (int player, int rate);
native void AIHarvestBonus (int player, fixed bonus);
native void AISetGasPeonCountOverride (int player, int town, int desiredGasCount);
native int AIGetCurPeonCount (int player, int town);
native int AIGetMinPeonCount (int player, int town);
native int AIGetMaxPeonCount (int player, int town);
native int AIGetMineralAmountLeft (int player, int town);
native int AIGetGasAmountLeft (int player, int town);
native int AIGetMineralNumSpots (int player, int town);
native int AIGetRawGasNumSpots (int player, int town);
native point AIGetGatherLocation (int player, int town);//xxx remove old functions
native point AIGetGatherDefLocation (int player, int town);
native int AIExpand (int player, point searchStart, string firstBuilding);
native unitgroup AIGetTownThreats (int player, int town);
native unit AIGetObstruction (int player);
native bool AIHasNearbyOpenExpansion (int player);
//-------------------------------------------------------------------------------------------------
// Scouting
//--------------------------------------------------------------------------------------------------
native void AIScout (int player);
native void AISetNumScouts (int player, int num);
native void AISetScoutTimes (int player, int starts, int obstructed, int resources, int other);
native point AIGetNextScoutLoc (int player);
native void AIClearCampaignScout (int player);
...post too long... continued next
//--------------------------------------------------------------------------------------------------
// Construction
//--------------------------------------------------------------------------------------------------
native void AIBuild (int player, int priority, int town, string aliasUnitType, int count, int flags);
native void AITrain (int player, int priority, int town, string aliasUnitType, int count);
native void AIResearch (int player, int priority, int town, string aliasUpgradeType);
native void AIMakeAlways (int player, int priority, int town, string aliasType, int count);
native void AIMakeOnce (int player, int priority, int town, string aliasType, int count);
native void AIClearBuildQueue (int player);
native void AIClearTrainQueue (int player);
native void AIClearResearchQueue (int player);
native bool AIHasRes (int player, int minerals, int gas);
native int AITechCount (int player, string aliasType, int countMask);
native void AITechCountFixupSingle (int player, string baseUnit, string upgradeOne);
native void AITechCountFixupEither (int player, string baseUnit, string upgradeOne, string upgradeTwo);
native void AITechCountFixupInOrder (int player, string baseUnit, string upgradeOne, string upgradeTwo);
native int AIKnownUnitCount (int player, int testPlayerId, string aliasUnitType);
native void AIResetCounterUnits (int player);
native void AICounterUnit (int player, string seeWhat, fixed factor, string makeWhat);
native int AICounterUnits (int player, int testPlayerId, string makeWhat);
native point AIGetRallyPoint (unit u);
native void AISetPowerBuilding (int player, string building);
native void AISetCreepBuilding (int player, string building, string noCreepBehavior);
//--------------------------------------------------------------------------------------------------
// Stock
//--------------------------------------------------------------------------------------------------
native void AIClearStock (int player);
native void AIEnableStock (int player);
native void AISetStockEx (int player, int town, int count, string aliasType, int buildFlags, int stockFlags);
native void AISetStock (int player, int count, string aliasType);
native void AISetStockOpt (int player, int count, string aliasType);
native void AISetStockUnitNext (int player, int count, string aliasUnitType, bool when);
native bool AISetStockTown (int player, string aliasUnitTypeTH, string aliasUnitTypeGas);
native bool AISetStockExpand (int player, string aliasUnitTypeTH, int count);
native void AISetStockExtra (int player, int count, string aliasUnitType, int minerals);
native void AISetStockFarms (int player, string aliasUnitType, bool onlyNeeded);
native void AISetStockPeons (int player, int max, string aliasUnitType, bool onlyMinPeons, bool peonMode);
native void AINewTechStock (int player);
native void AITechStockAdd (string upgradeType);
native void AISetStockTechNext (int player);
void AISetStockAlias (int player, int count, string makeType, string aliasType) {
count = count - AITechCount(player, aliasType, c_techCountQueuedOrBetter);
if (count > 0) {
AISetStock(player, count + AITechCount(player, makeType, c_techCountQueuedOrBetter), makeType);
}
}
void AISetStockFree (int player, int count, string makeType, string prereq) {
if (AITechCount(player, prereq, c_techCountCompleteOnly) > 0) {
AISetStock( player, count, makeType );
}
}
native void AIDefaultEconomy (int player, string hall, string gas, string food, string peon, int cap, bool peonMode);
native void AIDefaultExpansion (int player, string hall, int minerals, int gas, int expandFlags);
native void AIClearLimitTech (int player);
native void AILimitTech (int player, int totalMin, int totalGas, int buildingMin, int buildingGas, int upgradeMin, int upgradeGas);
native void AIImportantTech (int player, string aliasType);
native void AILimitStockLarva (int player, string aliasType);
native bool AIHasStock (int player);
native bool AIHasStockFromTown (int player, int town);
native void AIRemoveStockFromTown (int player, int town);
//--------------------------------------------------------------------------------------------------
// AI Requirements
//--------------------------------------------------------------------------------------------------
native int AIDefaultGetObjectType (int player, string aliasType);
native string AIDefaultGetMaker (int player, string aliasType);
native string AIDefaultGetFirstMissingReq (int player, string aliasType);
native string AIDefaultGetFirstUnfinishedReq (int player, string aliasType);
native int AIDefaultGetFullMakeTime (int player, string aliasType);
native string AIGetBaseName (string aliasType);
native string AIGetBuildAtName (string aliasType);
native void AIReqCountAsBuiltObject (int player, string aliasType);
native void AIReqAddSpecialMaker (string objType, string makerType, string abilName, int abilIndex);
//--------------------------------------------------------------------------------------------------
// Tactical
//--------------------------------------------------------------------------------------------------
native void AIBaseThink (unit who, unitgroup candidates);
native bool AIEvalTacticalData (unit who, string data);
const bool c_castRetreat = true;
const bool c_castHold = false;
native int AICast (unit u, order o, marker m, bool retreat);
native int AICastFlee (unit who, unit from, int distance, marker mark);
native bool AINearbyUnits (int player, string unitType, point p, fixed range, int requiredCount);
native unitgroup AIFindUnits (int player, string unitType, point p, fixed range, int inMaxCount);
native bool AISameCommand (unit u1, unit u2);
native unit AILastAttacker (unit u);
native int AILastAttack (unit u);
native bool AIControlWantsToMove (unit u);
native bool AIControlForceToMove (unit u);
native bool AIControlWantsToUnburrow (unit u);
native bool AIControlWantsToBurrow (unit u);
native bool AIControlForceUnburrow (unit u);
native bool AIUnitIsInCombat (unit u);
native bool AIIsIgnoredByWave (unit u);
native void AISetIgnoredByWave (unit u, bool enable);
native point AIGetHomePosition (unit u);
native point AIGetCloakedAttacker (int p);
native void AIClearCloakedAttacker (int p, point pt);
native bool AISawCloakedUnit (int p);
native point AIRandomSpawnPoint (
int player,
region r,
fixed minDistFromEnemy,
fixed maxDistFromEnemy,
fixed maxDistFromBuilding
);
native point AIBestTargetPoint (
unitgroup group,
int minHits,
int damageBase,
fixed minScore,
fixed radius,
point from,
fixed range,
int bonusAttri
);
native unit AIDefaultCombatPriority (unit target, unitgroup attackers, unitgroup enemies);
const int c_cloakMaxRange = 10;
native bool AICloakEvaluate (unit u, fixed minEnergy, fixed maxLife, fixed range);
//--------------------------------------------------------------------------------------------------
// Combat
//--------------------------------------------------------------------------------------------------
const int c_combatEnable = 1;
const int c_combatDisable = 2;
const int c_combatRead = 3;
void AISetDefaultCombatFlags (int player, bool isMelee);
native bool AICombatTargetProduction (int player, int action);
native bool AICombatTargetDropOffs (int player, int action);
native bool AICombatTargetFood (int player, int action);
native bool AICombatTargetActiveProduction (int player, int action);
native bool AICombatTargetWorkers (int player, int action);
native bool AICombatTargetAllyThreats (int player, int action);
native bool AICombatTargetSelfThreats (int player, int action);
native bool AICombatTargetCurrent (int player, int action);
native bool AICombatTargetAir (int player, int action);
native bool AICombatTargetMovers (int player, int action);
native bool AICombatTargetInjuries (int player, int action);
native bool AICombatTargetInAttackRange (int player, int action);
native bool AICombatTargetThreats (int player, int action);
native bool AICombatTargetHealers (int player, int action);
native bool AICombatTargetSiege (int player, int action);
native bool AICombatTargetAttackers (int player, int action);
native bool AICombatTargetSpecial (int player, int action);
native bool AICombatAvoidTimedUnits (int player, int action);
native bool AICombatAvoidNonThreats (int player, int action);
native bool AICombatAvoidWeakUnits (int player, int action);
native bool AICombatAvoidDisabledUnits (int player, int action);
//--------------------------------------------------------------------------------------------------
// Transports
//--------------------------------------------------------------------------------------------------
native void AITransportIgnore (int player, string unitType);
native void AITransportSetPanic (int player, fixed value);
native void AITransportSetReturn (int player, point center);
//--------------------------------------------------------------------------------------------------
// Waves
//--------------------------------------------------------------------------------------------------
native waveinfo AIWaveInfoCreate ();
native waveinfo AIWaveInfo (wave w);
native void AIWaveInfoAdd (waveinfo info, string unitType, int count);
native int AIWaveInfoAttack (waveinfo info, int player, point from, wavetarget target, int time);
native int AIWaveInfoSuicide (waveinfo info, int player, point from, wavetarget target, int time);
native int AIWaveInfoScout (waveinfo info, int player, point from, int time);
native string AIWaveToString (wave w);
native text AIWaveToText (wave w);
native wave AIWaveCreate (waveinfo info, int player, point from);
native void AIWaveAddUnit (wave w, unit u);
native void AIWaveAddUnitPriority (wave w, unit u, int prio);
native void AIWaveRemoveUnit (wave w, unit u);
native int AIWaveUnitCount (wave w);
native int AIWaveDetectorCount (wave w);
native void AIWaveSetType (wave w, int type, wavetarget target);
native int AIWaveState (wave w);
native void AIWaveDelete (wave w);
native wavetarget AIWaveTargetUnit (unit u);
native wavetarget AIWaveTargetUnitGroup (unitgroup g);
native wavetarget AIWaveTargetUnitPoint (unit u);
native wavetarget AIWaveTargetPoint (point p);
native wavetarget AIWaveTargetPlayer (playergroup players);
native wavetarget AIWaveTargetMelee (int player);
native wavetarget AIWaveTargetMeleeHarass (int player);
native wavetarget AIWaveTargetMeleeDrop (int player, point dropLoc, point goalLoc);
native wavetarget AIWaveTargetMeleeDefend (int player);
native wavetarget AIWaveTargetMerge (wave w);
native wavetarget AIWaveTargetPatrol (int replaceType);
native wavetarget AIWaveTargetEscort (unitgroup g, int replaceType);
native wavetarget AIWaveTargetEscortNL (unitgroup g, int replaceType);
native wavetarget AIWaveTargetGatherO (int player, int town);
native wavetarget AIWaveTargetGatherD (int player, int town);
native wavetarget AIWaveTargetRegion (region r, int replaceType);
native point AIWaveTargetGatherOPoint (int player, int town);
native point AIWaveTargetGatherDPoint (int player, int town);
native unit AIWaveTargetGetUnit (wavetarget wt);
native unitgroup AIWaveTargetGetUnitGroup (wavetarget wt);
native wavetarget AIWaveHarassRetreat (int player, wave w, fixed range);
native wavetarget AIWaveGetTarget (wave w);
native bool AIWaveIsInCombat (wave w);
native int AIWaveGetTimeInCombat (wave w);
native int AIWaveGetTimeSinceCombat (wave w);
native int AIWaveGetTimeSinceOrdered (wave w);
native int AIWaveGetTimeSinceRetreat (wave w);
native bool AIDefenseThreat (int type, int player, wave w);
native int AIDefenseThreatEval (int type, int player);
native int AIWaveEval (wave w);
native int AIWaveEvalRatio (wave w, fixed range);
native int AIUnitAreaEvalRatio (unit u, fixed range);
native int AIEvalRatio (int player);
native void AIEvalSetCustomIndex (int index);
native int AILastWaveEvalStaticRatio ();
native void AIWaveTargetAddWaypoint (wavetarget wt, point waypoint, bool useTransport, int index);
native void AIWaveTargetClearWaypoints (wavetarget wt);
//--- melee games ---
native wave AIWaveGet (int player, int waveName);
native void AIWaveSet (int player, int waveName, wave waveRef);
native int AIWaveType (wave waveRef);
//native void AIWaveSetUserData (wave waveRef, int index, int data);
//native int AIWaveGetUserData (wave waveRef, int index);
native void AIWaveMerge (int player, int waveFrom, int waveInto);
native void AIWaveMergeMelee (int player);
native wave WaveLastCreated ();
native point AIGetBestTarget (int player, playergroup enemies, point gatherPoint, int flags);
native bool AIFindDropAttackTarget (int player, point gatherPoint);
native point AILastDropLocation ();
native point AILastDropGoal ();
native fixed AIGetNextDropTimeCheck(int player);
native void AISetNextDropTimeCheck(int player, fixed time);
native int AILastAttackRatio (wave w);
native int AILastAttackStartEval (wave w);
//--------------------------------------------------------------------------------------------------
// Attack Wave
//--------------------------------------------------------------------------------------------------
// Note: The difficulty parameter is a one-based index into
// the externalized difficulty levels defined in GameData.xml
//
const int c_difficultyAll = -1; // Add the same count to all difficulty levels
native void AIAttackWaveAddUnits (int difficulty, int count, string unitType);
// External utility function to add four counts to the standard four difficulties
void AIAttackWaveAddUnits4 (int n1, int n2, int n3, int n4, string unitType) {
AIAttackWaveAddUnits(2, n1, unitType); // Easy
AIAttackWaveAddUnits(3, n2, unitType); // Normal
AIAttackWaveAddUnits(4, n3, unitType); // Hard
AIAttackWaveAddUnits(5, n4, unitType); // Insane
}
// Old external utility function to add three counts to the standard three difficulties
void AIAttackWaveAddUnits3 (int n1, int n2, int n3, string unitType) {
AIAttackWaveAddUnits4(n1,n2,n3,n3,unitType);
}
native int AIAttackWaveSend (int player, int time, bool wait);
native void AIAttackWaveCancel (wave waveRef);
native void AIAttackWaveSetGatherPoint (int player, point gather);
native void AIAttackWaveUseUnit (int player, unit u);
native void AIAttackWaveUseGroup (int player, unitgroup ug);
native void AIAttackWaveAddEscortUnit (int player, unit u, unit escort, fixed offset, fixed angle);
native void AIAttackWaveAddEscortType (int player, string unitType, unit escort, fixed offset, fixed angle);
native void AIAttackWaveSetTargetUnit (int player, unit u);
native void AIAttackWaveSetTargetUnitGroup (int player, unitgroup ug);
native void AIAttackWaveSetTargetUnitPoint (int player, unit u);
native void AIAttackWaveSetTargetPoint (int player, point p);
native void AIAttackWaveSetTargetPlayer (int player, playergroup players);
native void AIAttackWaveSetTargetMelee (int player);
native void AIAttackWaveSetTargetMeleeHarass (int player);
native void AIAttackWaveSetTargetMeleeDrop (int player, point dropLoc, point goalLoc);
native void AIAttackWaveSetTargetMeleeDefend (int player);
native void AIAttackWaveSetTargetMerge (int player, wave w);
native void AIAttackWaveSetTargetPatrol (int player, int replaceType);
native void AIAttackWaveSetTargetEscort (int player, unitgroup g, int replaceType);
native void AIAttackWaveSetTargetEscortNL (int player, unitgroup g, int replaceType);
native void AIAttackWaveSetTargetGatherO (int player, int town);
native void AIAttackWaveSetTargetGatherD (int player, int town);
native void AIAttackWaveSetTargetRegion (int player, region r, int replaceType);
native void AIAttackWaveSetGatherEarlyNoReplace (int player);
native void AIAttackWaveSetKeepAlive (int player);
native void AIAttackWaveAddWaypoint (int player, point waypoint, bool useTransport);
native void AIAttackWaveClearWaypoints (int player);
//--------------------------------------------------------------------------------------------------
// Bully Functions
//--------------------------------------------------------------------------------------------------
native void AISetMinimumBullyCount (int count, string unitType, int player);
native void AISetGeneralRebuildCount (int count, bool building, int player);
native void AISetSpecificRebuildCount (int count, string unitType, int player);
native void AISetBullyAttackWavePercent (int percent, int player);
native void AINearestTownLimitWaveGather (int player, bool enable);
native void AINearestTownBullyRebuild (int player, bool enable);
native void AIToggleBulliesInRegion (int player, region reg, bool activate);
native void AIResetBullyRebuildCountsInRegion (int player, region reg);
native void AIClearAllBullies (int player);
native void AIAddBully (int player, string unitType, point loc, int rebuildCount);
native string AIGetBullyType (unit u);
Why are these snippets even being posted? Everyone already has them, there's no point.