//===========================================================================
//
// Michael Peppers's Melee AI template (v0.4.1)
// - Automatized Tiering system added
// - Clever Upgrading system! (clever, but not automatized...)
// - Now the AI will handle ALL the worker creation stuff automatically
//
//===========================================================================
//---
// FYI, as long as you can try to make a complete template, you'll still have to make
// most of the BuildPriorities and UpgradePriorities yourself...
//---
//***************************************************************************
//*
//* Global Variables
//*
//***************************************************************************
globals
// Standard AI globals, DON'T TOUCH!!
integer attackWave = 1
integer nextDelay = 0
//misc common.ai and standard global infos:
//"attackWave" can be used to know the current attack wave
//"nextDelay" is used to delay the attack waves
//"take_exp" is a common.ai boolean global, can be used to store/retrieve the need of an expansion
//If you need to know the current gold/wood harvesters, check "AddAttackUnit" in a AI Editor ".ai" file
// Town Hall
constant integer Hall = 'h000'
constant integer Mine = '' //Only with mines that have to be built (UD), in any other case = Hall
constant integer HallTier2 = 'h001'
constant integer HallTier3 = 'h002'
// Workers
constant integer GoldHarvester = 'n000'
constant integer WoodHarvester = 'n000' //In most AIs = GoldHarvester
// Highly volatile globals section
// Buildings
constant integer House = 'h005'
constant integer Altar = 'h004'
constant integer Barracks = 'h006'
constant integer Blacksmith = 'h00A'
constant integer LumberMill = 'h00B' //In most AIs = Blacksmith
constant integer Shop = '0' //No shops = set to 0
constant integer CasterBarracks = 'h00D'
constant integer Tower = 'net1'
constant integer SpecializedBarracks = 'h00N' //Workshop/Beastiary/AncientOfWind/SlaughterHouse etc.
constant integer FlyingBarracks = 'h00I'
// Units
constant integer BasicMelee = 'h007'
constant integer BasicRanged = 'h008' //I hope for my AI's sanity that BasicMelee + BasicRanged >= 5 food. =P
constant integer T2Melee = 'h009' //Specialized Melee, if it doesn't exist, T2MeleeExists MUST be set to false
constant integer MainCaster = 'h00F' //Ala Sorceress
constant integer SupportCaster = 'h00E' //Ala Priest
constant integer OwnageMelee = 'n004' //Ala Knight/Tauren/Abo etc.
constant integer AirAir = 'h00J' //ala Gargoyle
constant integer AirGround = 'h00J' //ala Gryphon
constant integer SiegeRanged = 'h00M'
constant integer MiscUnit1 = '' //Not used as of now
constant integer MiscUnit2 = '' //Not used as of now
// Upgrades
constant integer AttackUpgrade1 = 'R002'
constant integer AttackUpgrade2 = 'R001'
constant integer DefenseUpgrade1 = 'R003'
constant integer DefenseUpgrade2 = 'R004'
constant integer BasicMeleeUpgrade = '0'
constant integer BasicRangedUpgrade = 'R000'
constant integer MainCasterUpgrade = 'R009'
constant integer SupportCasterUpgrade = 'R008'
constant integer LumberHarvestUpgrade = 'R005'
constant integer BuildingDefenseUpgrade = 'R006'
constant integer MiscUpgrade1 = 'R00B'
constant integer MiscUpgrade2 = 'R00A'
constant integer MiscUpgrade3 = 'R00C'
constant integer MiscUpgrade4 = 'R007'
constant integer MiscUpgrade5 = '0'
constant integer MiscUpgrade6 = '0'
constant integer MiscUpgrade7 = '0'
constant integer MiscUpgrade8 = '0'
constant integer MiscUpgrade9 = '0'
constant integer MiscUpgrade10 = '0'
constant integer MiscUpgrade11 = '0'
constant integer MiscUpgrade12 = '' //Not used as of now
//End of highly volatile globals =P
// Heroes
constant integer Heroes = 4 //Number of heroes in the racial altar
constant integer H1 = 'Hblm'
constant integer H2 = 'N003' //Set to 0 if it doesn't exists, shouldn't cause problems, though
constant integer H3 = 'H00C' //Read above
constant integer H4 = '0' //Idem
// Hero Skills
// First Hero
constant integer H1A1 = 'AHfs'
constant integer H1A2 = 'AHbn'
constant integer H1A3 = 'AHdr'
constant integer H1U = 'AHpx'
// Second Hero
constant integer H2A1 = 'ANic'
constant integer H2A2 = 'ANso'
constant integer H2A3 = 'ANlm'
constant integer H2U = 'ANvc'
// Third Hero
constant integer H3A1 = 'AUau'
constant integer H3A2 = 'ANso'
constant integer H3A3 = 'ANrf'
constant integer H3U = 'A000'
// Fourth Hero (yes, the AI supports 4 racial heroes =D)
constant integer H4A1 = '0'
constant integer H4A2 = '0'
constant integer H4A3 = '0'
constant integer H4U = '0'
// Food Conditions for assaults
constant integer Food4Attack = 80 //Food usage needed for assaulting Main Bases
constant integer Food4Exp = 42 //Food usage needed for creating Expansions
// Harvest priorities
constant integer GoldGuys1 = 5 //How many people will gather gold at the 1st mine
constant integer WoodGuys1 = 20 //How many people will gather wood at the base
constant integer GoldGuys2 = 5 //How many people will gather gold at the 2nd mine, 0 to disable
constant integer WoodGuys2 = 20 //How many other people will gather wood at the base, 0 to disable
//Automatized housing values
constant integer HousesToBuild = 2 //How many houses will the AI build at a time
constant integer MaxFoodUsedByUnit = 5 //The food value of the most expensive unit, food-wise
constant integer MaxFood = 100 //The maximum number of food that can be produced
//Automatized tiering values
constant integer GoldForT2 = 600 //When this Gold value is reached, the AI will go to T2
constant integer WoodForT2 = 400 //When this Wood value is reached, the AI will go to T2
constant integer GoldForT3 = 800 //When this Gold value is reached, the AI will go to T3
constant integer WoodForT3 = 600 //When this Wood value is reached, the AI will go to T3
// Misc stuff
constant boolean WantName = true
constant boolean WantDifficultyInName = true
constant string Name = "Test"
constant boolean IsAmphibious = false //Naga-like race?
constant boolean WannaKeepBasicMelee = false //Self-explainatory, I hope =)
constant integer KeepBasicMeleeFoodCap = 34 //As soon as the AI surpasses this food cap it will stop training basic melee units
constant boolean T2MeleeExists = true //No T2 Melee? = set to false
constant integer MinimumForceBasicMelee = 4 //Use wisely: 2 food each = 4, 3 food each = 3
constant integer MinimumForceBasicRanged = 3 //Use wisely: 2 food each = 4, 3 food each = 3
constant integer MinimumForceT2Melee = 3
constant integer MinimumForceOwnageMelee = 3
constant integer AIHasT2Melee = 52 //When this food cap is reached, the AI will use T2Melee too (if enabled) in Minimum Attack
constant integer AIHasOwnageMelee = 72 //When this food cap is reached, the AI will use OwnageMelee too in Minimum Attack
// Difficulty-dependant variables (to change them, look in "main")
integer MinesToOwn = 2 //(2 for Newb AI, 3 for Normal, 4 for Insane)
string array DifficultyName //"(Easy)", "(Normal)", "(Insane)"
// Conditions (Do not touch!!! These are changed by "UpdateConditions" anyway...)
boolean KeepBasicMelee = true
boolean CanAttack = false //Has enough units to help allies/launch small attacks?
endglobals
//***************************************************************************
//*
//* Utility Functions
//*
//***************************************************************************
//HallCount Replicates and enhances common.ai's TownCountEx function, to make it work with custom halls =D
function HallCount takes integer unitid, boolean done returns integer
local integer have_qty
if (not done) then
set have_qty = GetUnitCount(unitid)
if unitid == Hall then
set have_qty = have_qty + GetUnitCount(HallTier2) + GetUnitCount(HallTier3)
elseif unitid == HallTier2 then
set have_qty = have_qty + GetUnitCount(HallTier3)
endif
else
set have_qty = GetUnitCountDone(unitid)
if unitid == Hall then
set have_qty = have_qty + GetUnitCountDone(HallTier2) + GetUnitCountDone(HallTier3)
elseif unitid == HallTier2 then
set have_qty = have_qty + GetUnitCountDone(HallTier3)
endif
endif
return have_qty
endfunction
//===========================================================================
function CheckLastCommand takes boolean pop returns integer
local integer cmd = GetLastCommand()
if (pop) then
call PopLastCommand()
endif
return cmd
endfunction
//===========================================================================
function CheckLastCommandData takes boolean pop returns integer
local integer data = GetLastData()
if (pop) then
call PopLastCommand()
endif
return data
endfunction
//===========================================================================
function BuildExpansion takes boolean build_it returns nothing
if build_it and HallsCompleted(Hall) then
call SetBuildExpa(HallCount(Hall, false) + 1, Hall)
endif
endfunction
//***************************************************************************
//*
//* Basic Options
//*
//***************************************************************************
//===========================================================================
function InitOptions takes nothing returns nothing
call SetMeleeAI()
call SetDefendPlayer(true)
call SetRandomPaths(false)
call SetTargetHeroes(true)
call SetPeonsRepair(true)
call SetHeroesFlee(true)
call SetHeroesBuyItems(true)
call SetUnitsFlee(true)
call SetGroupsFlee(true)
call SetWatchMegaTargets(true)
call SetIgnoreInjured(true)
call SetHeroesTakeItems(true)
call SetSlowChopping(false)
call SetCaptainChanges(true)
call SetSmartArtillery(true)
endfunction
//***************************************************************************
//*
//* Conditions
//*
//***************************************************************************
//===========================================================================
// Updates the values of all preset conditions
//===========================================================================
function UpdateConditions takes nothing returns nothing
if (not WannaKeepBasicMelee) then
set KeepBasicMelee = (FoodCap() < KeepBasicMeleeFoodCap)
endif
if T2MeleeExists then
set CanAttack = (GetUnitCountDone(BasicMelee) >= MinimumForceBasicMelee or GetUnitCountDone(T2Melee) >= MinimumForceT2Melee) and GetUnitCountDone(BasicRanged) >= MinimumForceBasicRanged
else
set CanAttack = (GetUnitCountDone(BasicMelee) >= MinimumForceBasicMelee or GetUnitCountDone(OwnageMelee) >= MinimumForceOwnageMelee) and GetUnitCountDone(BasicRanged) >= MinimumForceBasicRanged
endif
endfunction
//***************************************************************************
//*
//* Heroes
//*
//***************************************************************************
function SetSkills takes nothing returns nothing
set skill[ 1] = H1A1
set skill[ 2] = H1A2
set skill[ 3] = H1A3
set skill[ 4] = H1A1
set skill[ 5] = H1A2
set skill[ 6] = H1U
set skill[ 7] = H1A3
set skill[ 8] = H1A1
set skill[ 9] = H1A2
set skill[10] = H1A3
if hero_id == H1 then
call SetSkillArray(1, H1)
elseif hero_id2 == H1 then
call SetSkillArray(2, H1)
elseif hero_id3 == H1 then
call SetSkillArray(3, H1)
endif
if Heroes > 1 then
set skill[ 1] = H2A1
set skill[ 2] = H2A2
set skill[ 3] = H2A3
set skill[ 4] = H2A1
set skill[ 5] = H2A2
set skill[ 6] = H2U
set skill[ 7] = H2A3
set skill[ 8] = H2A1
set skill[ 9] = H2A2
set skill[10] = H2A3
if hero_id == H2 then
call SetSkillArray(1, H2)
elseif hero_id2 == H2 then
call SetSkillArray(2, H2)
elseif hero_id3 == H2 then
call SetSkillArray(3, H2)
endif
endif
if Heroes > 2 then
set skill[ 1] = H3A1
set skill[ 2] = H3A2
set skill[ 3] = H3A3
set skill[ 4] = H3A1
set skill[ 5] = H3A2
set skill[ 6] = H3U
set skill[ 7] = H3A3
set skill[ 8] = H3A1
set skill[ 9] = H3A2
set skill[10] = H3A3
if hero_id == H3 then
call SetSkillArray(1, H3)
elseif hero_id2 == H3 then
call SetSkillArray(2, H3)
elseif hero_id3 == H3 then
call SetSkillArray(3, H3)
endif
endif
if Heroes > 3 then
set skill[ 1] = H4A1
set skill[ 2] = H4A2
set skill[ 3] = H4A3
set skill[ 4] = H4A1
set skill[ 5] = H4A2
set skill[ 6] = H4U
set skill[ 7] = H4A3
set skill[ 8] = H4A1
set skill[ 9] = H4A2
set skill[10] = H4A3
if hero_id == H4 then
call SetSkillArray(1, H4)
elseif hero_id2 == H4 then
call SetSkillArray(2, H4)
elseif hero_id3 == H4 then
call SetSkillArray(3, H4)
endif
endif
endfunction
function PickRacialHero takes nothing returns nothing
local integer first
local integer second
local integer third
local integer last
local integer array heroes
set heroes[1] = H1
set heroes[2] = H2
set heroes[3] = H3
set heroes[4] = H4
if Heroes > 3 then
if VersionCompatible(VERSION_FROZEN_THRONE) then
set last = 4
else
set last = 3
endif
else
set last = Heroes
endif
if last >= 1 then
set first = GetRandomInt(1,last)
if last >= 2 then
set second = GetRandomInt(1,last-1)
if last >= 3 then
set third = GetRandomInt(1,last-2)
else
set third = 3
endif
else
set second = 2
endif
endif
set hero_id = heroes[first]
set heroes[first] = heroes[last]
set hero_id2 = heroes[second]
set heroes[second] = heroes[last-1]
set hero_id3 = heroes[third]
endfunction
//***************************************************************************
//*
//* Building and Harvesting
//*
//***************************************************************************
//===========================================================================
// Specifies building priorities for workers
//===========================================================================
function BuildPriorities takes nothing returns nothing
local integer mine = TownWithMine()
local boolean twoharvs = false
call InitBuildArray()
call MeleeTownHall(0, Hall)
call MeleeTownHall(1, Hall)
if Hall != Mine and GetGold() < 1500 then //In case of a custom mine
call SecondaryTown(mine, 1, Mine)
endif
call SetBuildUnit(GoldGuys1, GoldHarvester)
if GoldHarvester != WoodHarvester then
set twoharvs = true
endif
if HallCount(HallTier2, false) == 0 and GetGold() >= GoldForT2 and GetWood() >= WoodForT2 then
call SetBuildUnit(1, HallTier2)
elseif HallCount(HallTier3, false) == 0 and GetGold() >= GoldForT3 and GetWood() >= WoodForT3 then
call SetBuildUnit(1, HallTier3)
endif
if FoodCap() < MaxFood and FoodCap() <= (FoodUsed() + MaxFoodUsedByUnit) and GetUnitCount(House) < (GetUnitCountDone(House) + HousesToBuild) and HallCount(Hall, false) <= (HallCount(Hall, true) + (1 + (HallCount(HallTier2, false) - HallCount(HallTier2, true)))) then
call SetBuildUnit(GetUnitCount(House) + 1, House)
endif
if twoharvs = true then
call SetBuildUnit(WoodGuys1 - 1, WoodHarvester)
else
call SetBuildUnit(GoldGuys1 + (WoodGuys1 - 1), WoodHarvester)
endif
call SetBuildUnit(1, Altar)
call SetBuildUnit(1, Barracks)
if twoharvs = true then
call SetBuildUnit(WoodGuys1, WoodHarvester)
else
call SetBuildUnit(GoldGuys1 + WoodGuys1, WoodHarvester)
endif
call SetBuildUnit(1, hero_id)
if KeepBasicMelee then
call SetBuildUnit(3, BasicMelee)
endif
call SetBuildUnit(1, Blacksmith)
call SetBuildUnit(2, BasicRanged)
if Blacksmith != LumberMill then
call SetBuildUnit(1, LumberMill)
endif
call SetBuildUnit(3, BasicRanged)
if KeepBasicMelee then
call SetBuildUnit(5, BasicMelee)
endif
if Shop != 0 then
call SetBuildUnit(1, Shop)
endif
call SetBuildUnit(5, BasicRanged)
call BuildExpansion(GetMinesOwned() < MinesToOwn)
if WoodGuys2 > 0 then
if twoharvs = true then
call SetBuildUnit(WoodGuys1 + WoodGuys2, WoodHarvester)
else
call SetBuildUnit(GoldGuys1 + WoodGuys1 + WoodGuys2, WoodHarvester)
endif
endif
call SetBuildUnit(1, Tower)
call SetBuildUnit(1, CasterBarracks)
if MeleeDifficulty() != MELEE_NEWBIE and Heroes > 1 then //2 heroes? kthxbai
call SetBuildUnit(1, hero_id2)
else //Adding some cannon fodder, >= 5 food in total, I hope...
if KeepBasicMelee then
call SetBuildUnit(6, BasicMelee)
else
call SetBuildUnit(1, BasicMelee)
endif
call SetBuildUnit(6, BasicRanged)
endif
call SetBuildUnit(2, Tower)
if T2MeleeExists then
call SetBuildUnit(3, T2Melee)
endif
if T2MeleeExists then
call SetBuildUnit(4, T2Melee)
if (not KeepBasicMelee) then
call SetBuildUnit(6, T2Melee)
endif
endif
call SetBuildUnit(1, SupportCaster)
call SetBuildUnit(3, Tower)
call SetBuildUnit(1, MainCaster)
call SetBuildUnit(1, SpecializedBarracks)
if GoldGuys2 > 0 then
if twoharvs = true then
call SetBuildUnit(GoldGuys1 + GoldGuys2, GoldHarvester)
else
if WoodGuys2 > 0 then
call SetBuildUnit(GoldGuys1 + GoldGuys2 + WoodGuys1 + WoodGuys2, GoldHarvester)
else
call SetBuildUnit(GoldGuys1 + GoldGuys2 + WoodGuys1, GoldHarvester)
endif
endif
endif
call SetBuildUnit(2, SiegeRanged)
call SetBuildUnit(5, OwnageMelee)
if (not KeepBasicMelee) then
call SetBuildUnit(6, OwnageMelee)
endif
if MeleeDifficulty() == MELEE_INSANE and Heroes > 2 then //3 heroes? 1337sauce
call SetBuildUnit(1, hero_id3)
if (not KeepBasicMelee) then
call SetBuildUnit(7, OwnageMelee)
else
call SetBuildUnit(6, OwnageMelee)
endif
endif
call SetBuildUnit(1, FlyingBarracks)
call SetBuildUnit(3, AirGround)
call SetBuildUnit(3, AirAir)
endfunction
function UpgradePriorities takes nothing returns nothing
//Blacksmith upgrades
if GetUnitCountDone(Blacksmith) > 0 then
if HallCount(HallTier3, true) > 0 then
call SetBuildUpgr(3, AttackUpgrade1)
call SetBuildUpgr(3, AttackUpgrade2)
call SetBuildUpgr(3, DefenseUpgrade1)
call SetBuildUpgr(3, DefenseUpgrade2)
call SetBuildUpgr(3, BuildingDefenseUpgrade)
call SetBuildUpgr(2, LumberHarvestUpgrade)
elseif HallCount(HallTier2, true) > 0 then
call SetBuildUpgr(2, AttackUpgrade1)
call SetBuildUpgr(2, AttackUpgrade2)
call SetBuildUpgr(2, DefenseUpgrade1)
call SetBuildUpgr(2, DefenseUpgrade2)
call SetBuildUpgr(2, BuildingDefenseUpgrade)
call SetBuildUpgr(1, LumberHarvestUpgrade)
else
call SetBuildUpgr(1, AttackUpgrade1)
call SetBuildUpgr(1, AttackUpgrade2)
call SetBuildUpgr(1, DefenseUpgrade1)
call SetBuildUpgr(1, DefenseUpgrade2)
call SetBuildUpgr(1, BuildingDefenseUpgrade)
endif
endif
//Barracks upgrades
if GetUnitCountDone(Barracks) > 0 then
if GetUnitCountDone(BasicMelee) > 2 then
call SetBuildUpgr(1, BasicMeleeUpgrade)
endif
if HallCount(HallTier2, true) > 0 and GetUnitCountDone(BasicRanged) > 2 and GetUnitCountDone(Blacksmith) > 0 then
call SetBuildUpgr(1, BasicRangedUpgrade)
endif
if HallCount(HallTier3, true) > 0 and GetUnitCountDone(OwnageMelee) > 2 and GetUnitCountDone(Blacksmith) > 0 and GetUnitCountDone(CasterBarracks) > 0 then
call SetBuildUpgr(1, MiscUpgrade3)
endif
endif
//CasterBarracks upgrades
if GetUnitCountDone(CasterBarracks) > 0 then
if HallCount(HallTier3, true) > 0 then
if GetUnitCountDone(MainCaster) > 0 then
call SetBuildUpgr(2, MainCasterUpgrade)
endif
if GetUnitCountDone(SupportCaster) > 0 then
call SetBuildUpgr(2, SupportCasterUpgrade)
endif
if GetUnitCountDone(Shop) > 0 and GetUnitCountDone(T2Melee) > 2 then
call SetBuildUpgr(1, MiscUpgrade2)
endif
else
if GetUnitCountDone(MainCaster) > 0 then
call SetBuildUpgr(1, MainCasterUpgrade)
endif
if GetUnitCountDone(SupportCaster) > 0 then
call SetBuildUpgr(1, SupportCasterUpgrade)
endif
endif
if GetUnitCountDone(T2Melee) > 2 then
call SetBuildUpgr(1, MiscUpgrade1)
endif
endif
//FlyingBarracks upgrades
if GetUnitCountDone(FlyingBarracks) > 0 then
if HallCount(HallTier3, true) > 0 then
if GetUnitCountDone(CasterBarracks) > 0 then
if GetUnitCountDone(Blacksmith) > 0 and GetUnitCountDone(AirGround) > 0 then
call SetBuildUpgr(1, MiscUpgrade5)
endif
if GetUnitCountDone(Shop) > 0 then
if GetUnitCountDone(AirAir) > 0 then
call SetBuildUpgr(1, MiscUpgrade4)
endif
if GetUnitCountDone(AirGround) > 0 then
call SetBuildUpgr(1, MiscUpgrade6)
endif
endif
endif
endif
endif
//SpecializedBarracks upgrades
if GetUnitCountDone(SpecializedBarracks) > 0 then
if HallCount(HallTier3, true) > 0 then
if GetUnitCountDone(Blacksmith) > 0 and GetUnitCountDone(SiegeRanged) > 0 then
call SetBuildUpgr(1, MiscUpgrade7)
endif
if GetUnitCountDone(CasterBarracks) > 0 and GetUnitCountDone(MiscUnit1) > 0 then
call SetBuildUpgr(1, MiscUpgrade9)
endif
if GetUnitCountDone(Shop) > 0 and GetUnitCountDone(MiscUnit2) > 0 then
call SetBuildUpgr(1, MiscUpgrade10)
endif
endif
endif
//Misc upgrades
if HallCount(Hall, true) > 0 then
if HallCount(HallTier2, true) > 0 and GetUnitCountDone(Shop) > 0 then
call SetBuildUpgr(1, MiscUpgrade8)
endif
if GetUnitCountDone(Shop) > 0 then
call SetBuildUpgr(1, MiscUpgrade11)
endif
endif
endfunction
function GuysAtWork takes nothing returns nothing
local integer mine
loop
call UpdateConditions()
call ClearHarvestAI()
set mine = TownWithMine()
call HarvestGold(mine + 0, GoldGuys1)
call HarvestWood(0, WoodGuys1)
if GoldGuys2 != 0 and GetMinesOwned() >= 2 then
call HarvestGold(mine + 1, GoldGuys2)
endif
if WoodGuys2 != 0 then
call HarvestWood(0, WoodGuys2)
endif
call BuildPriorities()
call UpgradePriorities()
call Sleep(2)
endloop
endfunction
//***************************************************************************
//*
//* Attacking
//*
//***************************************************************************
//===========================================================================
// Returns true if the minimum forces for an attack exist
//===========================================================================
function HaveMinimumAttackers takes nothing returns boolean
// Check for attack wave limit
if (attackWave > 2) then
return false
endif
return CanAttack
endfunction
//===========================================================================
// Assigns units to attack based on the given attack group
//===========================================================================
function PrepareAttackGroup takes integer groupID returns nothing
// Attack Group #1: Minimum Attack
if (groupID == 1) then
call SetAssaultGroup(GetUnitCountDone(hero_id), -1, hero_id)
call SetAssaultGroup(GetUnitCountDone(BasicRanged), -1, BasicRanged)
call SetAssaultGroup(GetUnitCountDone(BasicMelee), -1, BasicMelee)
if (FoodCap() >= AIHasOwnageMelee) then
call SetAssaultGroup(MinimumForceOwnageMelee, MinimumForceOwnageMelee, OwnageMelee)
endif
if (FoodCap() >= AIHasT2Melee) and T2MeleeExists then
call SetAssaultGroup(MinimumForceT2Melee, MinimumForceT2Melee, T2Melee)
endif
// Attack Group #2: All Units
elseif (groupID == 2) then
call SetAssaultGroup(GetUnitCountDone(hero_id), -1, hero_id)
if Heroes > 1 then //Just in case =)
call SetAssaultGroup(GetUnitCountDone(hero_id2), -1, hero_id2)
if Heroes > 2 then
call SetAssaultGroup(GetUnitCountDone(hero_id3), -1, hero_id3)
endif
endif
call SetAssaultGroup(GetUnitCountDone(BasicRanged), -1, BasicRanged)
call SetAssaultGroup(GetUnitCountDone(BasicMelee), -1, BasicMelee)
call SetAssaultGroup(GetUnitCountDone(OwnageMelee), -1, OwnageMelee)
call SetAssaultGroup(GetUnitCountDone(SupportCaster), -1, SupportCaster)
call SetAssaultGroup(GetUnitCountDone(MainCaster), -1, MainCaster)
if T2MeleeExists then
call SetAssaultGroup(GetUnitCountDone(T2Melee), -1, T2Melee)
endif
call SetAssaultGroup(GetUnitCountDone(AirGround), -1, AirGround)
call SetAssaultGroup(GetUnitCountDone(AirAir), -1, AirAir)
call SetAssaultGroup(GetUnitCountDone(SiegeRanged), -1, SiegeRanged)
call SetAssaultGroup(GetUnitCountDone(MiscUnit1), -1, MiscUnit1)
call SetAssaultGroup(GetUnitCountDone(MiscUnit2), -1, MiscUnit2)
endif
endfunction
//===========================================================================
// Prepares an attack group based on the current attack wave
//===========================================================================
function PrepareForces takes nothing returns nothing
if (attackWave == 1) then
call PrepareAttackGroup(1)
elseif (attackWave == 2) then
call PrepareAttackGroup(2)
endif
endfunction
//===========================================================================
// Sleep delays for each attack wave
//===========================================================================
function AttackWaveDelay takes integer inWave returns nothing
if (inWave < nextDelay) then
return
endif
if (inWave == 1) then
call Sleep(2)
endif
set nextDelay = inWave + 1
endfunction
//===========================================================================
// Advances attack wave counter
//===========================================================================
function AttackWaveUpdate takes nothing returns nothing
call AttackWaveDelay(attackWave)
set attackWave = attackWave + 1
if (attackWave > 2) then
set attackWave = 2
set nextDelay = attackWave + 1
endif
endfunction
//===========================================================================
// Basic attack functionality
//===========================================================================
function AttackTarget takes unit target, boolean addAlliance returns nothing
if (target == null) then
return
endif
if (addAlliance) then
call SetAllianceTarget(target)
endif
call FormGroup(3, true)
call AttackMoveKillA(target)
if (not addAlliance) then
call SetAllianceTarget(null)
endif
endfunction
//===========================================================================
// Initiates an attack based on target priorities
//===========================================================================
function LaunchAttack takes nothing returns nothing
local unit target = null
local boolean setAlly = true
// Don't launch any attack while town is threatened
if (TownThreatened()) then
call Sleep(2)
return
endif
// Target Priority #1 = Helping an ally Assault/Defence
if (target == null) then
set target = GetAllianceTarget()
if (target != null) then
set setAlly = false
endif
endif
// Target Priority #2 = Preparing an expansion
if FoodUsed() >= Food4Exp then
if (target == null) then
set target = GetExpansionFoe()
endif
endif
// Target Priority #3 = Woot, MegaTarget? (MegaTarget is the enemy's main)
if FoodUsed() >= Food4Attack then
if (target == null) then
set target = GetMegaTarget()
endif
// Target Priority #4 = Either enemy expansions or an enemy base
if (target == null) then
set target = GetEnemyExpansion()
if (target == null) then
call StartGetEnemyBase()
loop
exitwhen (not WaitGetEnemyBase())
call SuicideSleep(1)
endloop
set target = GetEnemyBase()
endif
endif
endif
// Target Priority #5 = Small creep camps
if FoodUsed() < Food4Attack then
if target == null then
set target = GetCreepCamp(0, 9, false)
endif
endif
// Target Priority #6 = Huge creep camps
if FoodUsed() >= Food4Attack then
if (target == null) then
set target = GetCreepCamp(10, 100, true)
endif
endif
// Target Priority #7 = Goblin Zeppelin
// if ((GetUnitCount('nzep') < 1)) then
// if (target == null) then
// call PurchaseZeppelin()
// return
// endif
// endif
// Attack the target and increment attack wave
if (target != null) then
call AttackTarget(target, setAlly)
call AttackWaveUpdate()
else
// If no target was found, sleep a bit before trying again
call Sleep(20)
endif
endfunction
//===========================================================================
// Determines all attacking assignments
//===========================================================================
function AttackAssignment takes nothing returns nothing
local integer n = 0
call StaggerSleep(0, 2)
if (attackWave == 1) then
call AttackWaveDelay(0)
endif
loop
call UpdateConditions()
if (HaveMinimumAttackers() and not CaptainRetreating()) then
if n == 2 then
call Sleep(2)
set n = 0
else
set n = n + 1
call RemoveInjuries()
call InitAssaultGroup()
call PrepareForces()
call LaunchAttack()
endif
else
call Sleep(2)
endif
endloop
endfunction
//***************************************************************************
//*
//* Main Entry Point
//*
//***************************************************************************
//===========================================================================
function main takes nothing returns nothing
set ai_player = Player(GetAiPlayer())
set MinesToOwn = 1 + MeleeDifficulty()
set DifficultyName[1] = "(Easy)"
set DifficultyName[2] = "(Normal)"
set DifficultyName[3] = "(Insane)"
if WantName then
if WantDifficultyInName then
call SetPlayerName(ai_player, Name + " " + DifficultyName[MeleeDifficulty(Normal)])
else
call SetPlayerName(ai_player, Name)
endif
endif
call InitOptions()
call PickRacialHero()
call SetSkills()
call CreateCaptains()
call StandardAI(function SkillArrays, function GuysAtWork, function AttackAssignment)
if IsAmphibious then
call SetAmphibious()
endif
call PlayGame()
endfunction