//===========================================================================
//
// Undead Empire
//
// Warcraft III AI script
// Generated by the Warcraft III World Editor
// Date: Fri Oct 19 16:26:12 2018
//
//===========================================================================
//***************************************************************************
//*
//* Global Variables
//*
//***************************************************************************
globals
integer attackWave = 1
integer nextDelay = 0
integer awGold = 0
integer awWood = 0
// Conditions
boolean gCond_Reisser_Max = false
boolean gCond_build_cond = false
boolean gCond_Necro_1 = false
boolean gCond_Necro_2 = false
boolean gCond_Necro_3 = false
boolean gCond_attack_cond = false
endglobals
//***************************************************************************
//*
//* Utility Functions
//*
//***************************************************************************
//===========================================================================
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 TotalFoodProduced takes nothing returns integer
return GetPlayerState(ai_player,PLAYER_STATE_RESOURCE_FOOD_CAP)
endfunction
//===========================================================================
function ExpansionNeeded takes nothing returns boolean
return take_exp
endfunction
//===========================================================================
function BuildExpansion takes integer hallID, integer mineID returns nothing
if (HallsCompleted(hallID)) then
call SetBuildExpa( TownCount(hallID) + 1, mineID )
endif
endfunction
//===========================================================================
function CurrentAttackWave takes nothing returns integer
return attackWave
endfunction
//===========================================================================
function ResetAttackUnits takes nothing returns nothing
set awGold = 0
set awWood = 0
call InitAssaultGroup( )
endfunction
//===========================================================================
function AddAttackUnit takes integer minQty, integer maxQty, integer unitID returns nothing
// Track attacking gold workers
if (unitID == 'u000') then
set awGold = awGold + minQty
endif
// Track attacking wood workers
if (unitID == 'u000') then
set awWood = awWood + minQty
endif
call SetAssaultGroup( minQty, maxQty, unitID )
endfunction
//***************************************************************************
//*
//* Basic Options
//*
//***************************************************************************
//===========================================================================
function InitOptions takes nothing returns nothing
call SetCampaignAI( )
call SetDefendPlayer( false )
call SetRandomPaths( true )
call SetTargetHeroes( false )
call SetPeonsRepair( true )
call SetHeroesFlee( false )
call SetHeroesBuyItems( false )
call SetUnitsFlee( false )
call SetGroupsFlee( false )
call SetWatchMegaTargets( true )
call SetIgnoreInjured( true )
call SetHeroesTakeItems( false )
call SetSlowChopping( false )
call SetCaptainChanges( false )
call SetSmartArtillery( true )
endfunction
//***************************************************************************
//*
//* Conditions
//*
//***************************************************************************
//===========================================================================
// Updates the values of all preset conditions
//===========================================================================
function UpdateConditions takes nothing returns nothing
set gCond_Reisser_Max = ( GetUnitCount( 'u00E' ) <= 12 )
set gCond_build_cond = ( TownThreatened( ) == false )
set gCond_Necro_1 = ( ( GetUnitCount( 'u003' ) <= 1 ) and ( GetUpgradeLevel( 'Rune' ) < 2 ) )
set gCond_Necro_2 = ( GetUnitCount( 'u005' ) <= 2 )
set gCond_Necro_3 = ( GetUnitCount( 'u007' ) <= 3 )
set gCond_attack_cond = ( ( FoodUsed( ) >= ( 40 * GetUpgradeLevel( 'R007' ) ) ) and ( GetUnitCount( 'u00E' ) >= 6 ) )
endfunction
//***************************************************************************
//*
//* Heroes
//*
//***************************************************************************
//===========================================================================
// Stores hero ID and skills
//===========================================================================
function SetHero takes integer order, integer heroid returns nothing
endfunction
//===========================================================================
// Selects hero IDs for three possible heroes
//===========================================================================
function SelectHeroes takes nothing returns nothing
local integer roll = GetRandomInt(1,100)
if (roll <= 17) then
elseif (roll <= 34) then
elseif (roll <= 50) then
elseif (roll <= 67) then
elseif (roll <= 84) then
else
endif
endfunction
//===========================================================================
// Returns the hero skill for the given hero and level
//===========================================================================
function ChooseHeroSkill takes nothing returns integer
local integer curHero = GetHeroId()
local integer level = GetHeroLevelAI()
if (level > max_hero_level) then
set max_hero_level = level
endif
if (curHero == hero_id) then
return skills1[level]
elseif (curHero == hero_id2) then
return skills2[level]
elseif (curHero == hero_id3) then
return skills3[level]
endif
return 0
endfunction
//***************************************************************************
//*
//* Building and Harvesting
//*
//***************************************************************************
//===========================================================================
// Specifies building priorities for workers
//===========================================================================
function BuildPriorities takes nothing returns nothing
local integer mine = TownWithMine()
call SetBuildAll( BUILD_UNIT, 1, 'e008', 0 )
if (gCond_build_cond) then
call SetBuildAll( BUILD_UNIT, 1, 'u000', 0 )
call SetBuildAll( BUILD_UNIT, 2, 'u000', 0 )
call SetBuildAll( BUILD_UNIT, 3, 'u000', 0 )
call SetBuildAll( BUILD_UNIT, 4, 'u000', 0 )
call SetBuildAll( BUILD_UNIT, 5, 'u000', 0 )
call SetBuildAll( BUILD_UNIT, 6, 'u000', 0 )
call SetBuildAll( BUILD_UNIT, 7, 'u000', 0 )
call SetBuildAll( BUILD_UNIT, 8, 'u000', 0 )
call SetBuildAll( BUILD_UNIT, 9, 'u000', 0 )
call SetBuildAll( BUILD_UNIT, 10, 'u000', 0 )
call SetBuildAll( BUILD_UNIT, 11, 'u000', 0 )
call SetBuildAll( BUILD_UNIT, 12, 'u000', 0 )
call SetBuildAll( BUILD_UNIT, 13, 'u000', 0 )
call SetBuildAll( BUILD_UNIT, 14, 'u000', 0 )
call SetBuildAll( BUILD_UNIT, 15, 'u000', 0 )
endif
call SetBuildAll( BUILD_UNIT, 1, 'u00B', -1 )
call SetBuildAll( BUILD_UPGRADE, 1, 'R007', -1 )
call SetBuildAll( BUILD_UNIT, 1, 'u001', 0 )
if (gCond_build_cond) then
call SetBuildAll( BUILD_UNIT, 16, 'u000', 0 )
call SetBuildAll( BUILD_UNIT, 17, 'u000', 0 )
call SetBuildAll( BUILD_UNIT, 18, 'u000', 0 )
call SetBuildAll( BUILD_UNIT, 19, 'u000', 0 )
call SetBuildAll( BUILD_UNIT, 20, 'u000', 0 )
call SetBuildAll( BUILD_UNIT, 21, 'u000', 0 )
endif
call SetBuildAll( BUILD_UNIT, 1, 'u00J', 1 )
call SetBuildAll( BUILD_UNIT, 1, 'u00D', 0 )
call SetBuildAll( BUILD_UNIT, 2, 'u00D', 0 )
call SetBuildAll( BUILD_UPGRADE, 1, 'R00A', -1 )
call SetBuildAll( BUILD_UNIT, 2, 'u001', 0 )
call SetBuildAll( BUILD_UNIT, 22, 'u000', 0 )
if (gCond_Necro_1) then
call SetBuildAll( BUILD_UNIT, 1, 'u003', 0 )
endif
call SetBuildAll( BUILD_UNIT, 1, 'u00I', -1 )
call SetBuildAll( BUILD_UNIT, 2, 'u00I', -1 )
call SetBuildAll( BUILD_UNIT, 3, 'u00I', -1 )
call SetBuildAll( BUILD_UPGRADE, 2, 'R007', -1 )
call SetBuildAll( BUILD_UNIT, 4, 'u00I', -1 )
if (gCond_Reisser_Max) then
call SetBuildAll( BUILD_UNIT, 1, 'u00E', 0 )
endif
if (gCond_build_cond) then
call SetBuildAll( BUILD_UNIT, 23, 'u000', 0 )
call SetBuildAll( BUILD_UNIT, 24, 'u000', 0 )
call SetBuildAll( BUILD_UNIT, 25, 'u000', 0 )
call SetBuildAll( BUILD_UNIT, 26, 'u000', 0 )
call SetBuildAll( BUILD_UNIT, 27, 'u000', 0 )
endif
call SetBuildAll( BUILD_UPGRADE, 2, 'R00A', -1 )
call SetBuildAll( BUILD_UNIT, 5, 'u00I', -1 )
call SetBuildAll( BUILD_UNIT, 6, 'u00I', -1 )
if (gCond_Necro_2) then
call SetBuildAll( BUILD_UNIT, 1, 'u005', 0 )
endif
call SetBuildAll( BUILD_UNIT, 7, 'u00I', -1 )
call SetBuildAll( BUILD_UNIT, 8, 'u00I', -1 )
if (gCond_Necro_2) then
call SetBuildAll( BUILD_UNIT, 2, 'u005', 0 )
endif
call SetBuildAll( BUILD_UPGRADE, 3, 'R007', -1 )
call SetBuildAll( BUILD_UPGRADE, 1, 'R010', -1 )
call SetBuildAll( BUILD_UNIT, 9, 'u00I', -1 )
call SetBuildAll( BUILD_UNIT, 10, 'u00I', -1 )
if (gCond_Reisser_Max) then
call SetBuildAll( BUILD_UNIT, 2, 'u00E', 0 )
endif
call SetBuildAll( BUILD_UNIT, 3, 'u001', 0 )
call SetBuildAll( BUILD_UPGRADE, 4, 'R007', -1 )
call SetBuildAll( BUILD_UNIT, 11, 'u00I', -1 )
call SetBuildAll( BUILD_UNIT, 12, 'u00I', -1 )
if (gCond_Necro_3) then
call SetBuildAll( BUILD_UNIT, 1, 'u007', 0 )
call SetBuildAll( BUILD_UNIT, 2, 'u007', 0 )
endif
call SetBuildAll( BUILD_UNIT, 3, 'u00D', 0 )
call SetBuildAll( BUILD_UNIT, 13, 'u00I', -1 )
call SetBuildAll( BUILD_UNIT, 14, 'u00I', -1 )
call SetBuildAll( BUILD_UNIT, 1, 'u00F', 0 )
call SetBuildAll( BUILD_UNIT, 15, 'u00I', -1 )
call SetBuildAll( BUILD_UNIT, 16, 'u00I', -1 )
call SetBuildAll( BUILD_UNIT, 17, 'u00I', -1 )
call SetBuildAll( BUILD_UNIT, 18, 'u00I', -1 )
call SetBuildAll( BUILD_UNIT, 2, 'u00F', 0 )
call SetBuildAll( BUILD_UNIT, 4, 'u00D', 0 )
call SetBuildAll( BUILD_UNIT, 19, 'u00I', -1 )
call SetBuildAll( BUILD_UNIT, 3, 'u00F', 0 )
call SetBuildAll( BUILD_UNIT, 20, 'u00I', -1 )
call SetBuildAll( BUILD_UNIT, 4, 'u00F', 0 )
call SetBuildAll( BUILD_UNIT, 4, 'u001', 0 )
call SetBuildAll( BUILD_UNIT, 21, 'u00I', -1 )
call SetBuildAll( BUILD_UNIT, 22, 'u00I', -1 )
call SetBuildAll( BUILD_UNIT, 1, 'u009', -1 )
call SetBuildAll( BUILD_UNIT, 23, 'u00I', -1 )
call SetBuildAll( BUILD_UNIT, 24, 'u00I', -1 )
call SetBuildAll( BUILD_UNIT, 25, 'u00I', -1 )
call SetBuildAll( BUILD_UNIT, 2, 'u009', -1 )
call SetBuildAll( BUILD_UPGRADE, 1, 'R009', -1 )
call SetBuildAll( BUILD_UNIT, 26, 'u00I', -1 )
call SetBuildAll( BUILD_UNIT, 27, 'u00I', -1 )
call SetBuildAll( BUILD_UNIT, 28, 'u00I', -1 )
call SetBuildAll( BUILD_UNIT, 29, 'u00I', -1 )
call SetBuildAll( BUILD_UNIT, 3, 'u009', -1 )
call SetBuildAll( BUILD_UNIT, 30, 'u00I', -1 )
call SetBuildAll( BUILD_UNIT, 31, 'u00I', -1 )
call SetBuildAll( BUILD_UPGRADE, 1, 'R011', -1 )
call SetBuildAll( BUILD_UNIT, 5, 'u00D', 0 )
call SetBuildAll( BUILD_UNIT, 1, 'u011', -1 )
call SetBuildAll( BUILD_UNIT, 32, 'u00I', -1 )
call SetBuildAll( BUILD_UNIT, 2, 'u011', -1 )
call SetBuildAll( BUILD_UNIT, 33, 'u00I', -1 )
call SetBuildAll( BUILD_UNIT, 34, 'u00I', -1 )
call SetBuildAll( BUILD_UNIT, 35, 'u00I', -1 )
call SetBuildAll( BUILD_UNIT, 36, 'u00I', -1 )
call SetBuildAll( BUILD_UNIT, 37, 'u00I', -1 )
call SetBuildAll( BUILD_UNIT, 1, 'u00C', -1 )
call SetBuildAll( BUILD_UNIT, 1, 'u00H', -1 )
call SetBuildAll( BUILD_UNIT, 1, 'u00W', -1 )
call SetBuildAll( BUILD_UPGRADE, 1, 'R00X', -1 )
call SetBuildAll( BUILD_UPGRADE, 2, 'R00X', -1 )
call SetBuildAll( BUILD_UPGRADE, 3, 'R00X', -1 )
call SetBuildAll( BUILD_UPGRADE, 1, 'R008', -1 )
call SetBuildAll( BUILD_UNIT, 38, 'u00I', -1 )
call SetBuildAll( BUILD_UNIT, 39, 'u00I', -1 )
call SetBuildAll( BUILD_UNIT, 40, 'u00I', -1 )
call SetBuildAll( BUILD_UNIT, 41, 'u00I', -1 )
call SetBuildAll( BUILD_UNIT, 42, 'u00I', -1 )
endfunction
//===========================================================================
// Specifies harvesting priorities for workers
//===========================================================================
function HarvestPriorities takes nothing returns nothing
local integer mine = TownWithMine()
local integer allGold = GetUnitCountDone('u000')
local integer allWood = GetUnitCountDone('u000')
local integer numWorkers
set numWorkers = 5
call HarvestGold( 0, numWorkers )
set numWorkers = 22
call HarvestWood( 0, numWorkers )
endfunction
//===========================================================================
// Determines all building and harvesting assignments for workers
//===========================================================================
function WorkerAssignment takes nothing returns nothing
loop
call UpdateConditions( )
// Harvesting
call ClearHarvestAI( )
call HarvestPriorities( )
// Building
call InitBuildArray( )
call BuildPriorities( )
call Sleep( 2 )
endloop
endfunction
//***************************************************************************
//*
//* Attacking
//*
//***************************************************************************
//===========================================================================
// Returns true if the minimum forces for an attack exist
//===========================================================================
function HaveMinimumAttackers takes nothing returns boolean
local integer count
// Check for attack wave limit
if (attackWave > 1) then
return false
endif
// Attack Group: Alle Einheiten
// No specific minimums exist, checking for at least one unit
set count = 0
set count = count + GetUnitCountDone('u004')
set count = count + GetUnitCountDone('u011')
set count = count + GetUnitCountDone('u006')
set count = count + GetUnitCountDone('u00E')
set count = count + GetUnitCountDone('u00R')
set count = count + GetUnitCountDone('u00H')
set count = count + GetUnitCountDone('u00A')
set count = count + GetUnitCountDone('u008')
set count = count + GetUnitCountDone('u00Q')
set count = count + GetUnitCountDone('u00F')
set count = count + GetUnitCountDone('u003')
set count = count + GetUnitCountDone('u007')
set count = count + GetUnitCountDone('u009')
set count = count + GetUnitCountDone('u005')
if (( 0 == 1 )) then
set count = count + GetUnitCountDone('h038')
if (count < 1) then
return false
endif
endif
return true
endfunction
//===========================================================================
// Assigns units to attack based on the given attack group
//===========================================================================
function PrepareAttackGroup takes integer groupID returns nothing
local integer all
// Attack Group #1: Alle Einheiten
if (groupID == 1) then
set all = GetUnitCountDone( 'u004' )
call AddAttackUnit( all, all, 'u004' )
set all = GetUnitCountDone( 'u011' )
call AddAttackUnit( all, all, 'u011' )
set all = GetUnitCountDone( 'u006' )
call AddAttackUnit( all, all, 'u006' )
set all = GetUnitCountDone( 'u00E' )
call AddAttackUnit( all, all, 'u00E' )
set all = GetUnitCountDone( 'u00R' )
call AddAttackUnit( all, all, 'u00R' )
set all = GetUnitCountDone( 'u00H' )
call AddAttackUnit( all, all, 'u00H' )
set all = GetUnitCountDone( 'u00A' )
call AddAttackUnit( all, all, 'u00A' )
set all = GetUnitCountDone( 'u008' )
call AddAttackUnit( all, all, 'u008' )
set all = GetUnitCountDone( 'u00Q' )
call AddAttackUnit( all, all, 'u00Q' )
set all = GetUnitCountDone( 'u00F' )
call AddAttackUnit( all, all, 'u00F' )
set all = GetUnitCountDone( 'u003' )
call AddAttackUnit( all, all, 'u003' )
set all = GetUnitCountDone( 'u007' )
call AddAttackUnit( all, all, 'u007' )
set all = GetUnitCountDone( 'u009' )
call AddAttackUnit( all, all, 'u009' )
set all = GetUnitCountDone( 'u005' )
call AddAttackUnit( all, all, 'u005' )
if (( 0 == 1 )) then
call AddAttackUnit( 0, 0, 'h038' )
endif
// Attack Group #2:
elseif (groupID == 2) then
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 )
endif
endfunction
//===========================================================================
// Sleep delays for each attack wave
//===========================================================================
function AttackWaveDelay takes integer inWave returns nothing
if (inWave < nextDelay) then
return
endif
if (inWave == 0) then
call Sleep( 420 )
elseif (inWave == 1) then
call Sleep( 360 )
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 > 1) then
set attackWave = 1
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
if (gCond_attack_cond) then
if (target == null) then
set target = GetMegaTarget()
endif
// Target Priority #2
if (target == null) then
set target = GetEnemyExpansion()
endif
// Target Priority #3
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
// 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
call StaggerSleep( 0, 2 )
if (attackWave == 1) then
call AttackWaveDelay( 0 )
endif
loop
loop
call UpdateConditions( )
exitwhen (HaveMinimumAttackers() and not CaptainRetreating())
call Sleep( 2 )
endloop
call RemoveInjuries( )
call ResetAttackUnits( )
call PrepareForces( )
call LaunchAttack( )
endloop
endfunction
//***************************************************************************
//*
//* Main Entry Point
//*
//***************************************************************************
//===========================================================================
function main takes nothing returns nothing
call InitAI( )
call SetPlayerName( ai_player, "Undead Empire" )
call InitOptions( )
call SelectHeroes( )
call CreateCaptains( )
call SetHeroLevels( function ChooseHeroSkill )
call Sleep( 0.1 )
call StartThread( function WorkerAssignment )
call StartThread( function AttackAssignment )
call PlayGame( )
endfunction