• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[AI] Two Custom Campaign AIs (Examples)

Status
Not open for further replies.
Level 6
Joined
Jun 16, 2004
Messages
237
I made two custom campaign AIs for a new version of Defenders of Dwarvenkind (not yet released).

Lich King's Chosen AI
This AI does not build units. It waits until a unit owned by player 1 is in a specified region and then attacks it with all its units. The AI includes a set of functions for determining all units of the AI player and thus you don't need to know them beforehand, nor make changes if you add more preplaced units to the AI player. If you added more units to the AI player through triggers during the game, you would need to move call PrepareAssaultGroup() in function AttackAssignment before call AttackMoveKill(u).

Code:
//===========================================================================
// 
//  Lich King's Chosen AI
//  Defenders of Dwarvenkind
//
//  By Tommi Gustafsson
//
//===========================================================================

globals
    integer array CountedID
    integer array CountedNumber
    integer array Command
	integer array Data
    integer FirstFree = 0
endglobals

//===========================================================================
// CountUnit, ClearCount, and AddCountedToAssault functions
//===========================================================================

function CountUnit takes integer unitid returns nothing
    local integer i = 0

    loop
        if i == FirstFree then
            set CountedID[i] = unitid
            set CountedNumber[i] = 1
            set FirstFree = FirstFree + 1
            return
        endif
        if CountedID[i] == unitid then
            set CountedNumber[i] = CountedNumber[i] + 1 
            return
        endif
        set i = i + 1
    endloop

endfunction

function ClearCount takes nothing returns nothing
    set FirstFree = 0
endfunction

function AddCountedToAssault takes nothing returns nothing
    local integer i = 0

    loop
        exitwhen i == FirstFree
        call AddAssault(CountedNumber[i],CountedID[i])
        set i = i + 1
    endloop
endfunction


//===========================================================================
//  Basic Options
//===========================================================================
function InitOptions takes nothing returns nothing
    call SetCampaignAI(  )
    call SetDefendPlayer( false )
    call SetRandomPaths( false )
    call SetTargetHeroes( false )
    call SetPeonsRepair( true )
    call SetHeroesFlee( false )
    call SetHeroesBuyItems( true )
    call SetUnitsFlee( false )
    call SetGroupsFlee( false )
    call SetWatchMegaTargets( false )
    call SetIgnoreInjured( false )
    call SetHeroesTakeItems( true )
    call SetSlowChopping( false )
    call SetCaptainChanges( true )
    call SetSmartArtillery( true )
endfunction

//===========================================================================
// Prepares an assault group
//===========================================================================
function PrepareAssault takes nothing returns nothing
    local group g = CreateGroup()
    local unit u = null
    local integer id

    call ClearCount()
    call GroupEnumUnitsOfPlayer(g, ai_player, null)

    set u = FirstOfGroup(g)
    loop
        exitwhen u == null
        set id = GetUnitTypeId(u)

        //If the unit is not hidden, building, or worker, assign it to the attack group
        if (not IsUnitType(u, UNIT_TYPE_STRUCTURE) and not IsUnitType(u, UNIT_TYPE_PEON) and not IsUnitHidden(u) and GetUnitState(u, UNIT_STATE_LIFE) > 0) then
            call CountUnit(id)
        endif
        call GroupRemoveUnit(g, u)
        set u = FirstOfGroup(g)
    endloop
    call DestroyGroup(g)
   	call AddCountedToAssault()

endfunction

//===========================================================================
// Determines all attacking assignments
//===========================================================================
function AttackAssignment takes nothing returns nothing
    local group g = CreateGroup()
    local rect r = Rect(-2700.0,-13100.0,5700.0,-7900.0)
    local unit u = null
    local boolean targetfound = false

    call StaggerSleep( 0, 2 )

   	call PrepareAssault()

    loop
	    call GroupEnumUnitsInRect(g, r, null)
		set u = FirstOfGroup(g)
    	loop
    	    exitwhen u == null
    	    if (GetOwningPlayer(u) == Player(0) and GetUnitState(u, UNIT_STATE_LIFE) > 0) then
				set targetfound = true
    	    endif
    	    exitwhen targetfound == true
    	    call GroupRemoveUnit(g, u)
    	    set u = FirstOfGroup(g)
    	endloop
    	
    	if targetfound == true then
			//call DisplayTimedTextToPlayer(Player(0),0,0,5,"Target Found\n")
    		set targetfound = false
			call AttackMoveKill(u)
        elseif not CaptainIsHome() then
			//call DisplayTimedTextToPlayer(Player(0),0,0,5,"Returning Home\n")
			call AttackMoveXY(-1150, -10000)
		endif

        call Sleep(2)

    endloop
endfunction

//***************************************************************************
//*  Main Entry Point
//***************************************************************************
function main takes nothing returns nothing
    call InitAI(  )
    call InitOptions(  )
    call CreateCaptains(  )
    call SetCaptainHome(BOTH_CAPTAINS, -1150.0, -10000.0)

    call Sleep( 0.1 )
    call StartThread( function AttackAssignment )
    call PlayGame(  )
endfunction

Undead Wave AI
The AI builds building, upgrades, and units. The AI sends them to attack two targets (the Dwarven Gate and the Vault of the Dwarven Kings) in queue after receiving Attack Order 1 through the trigger action "AI - Send AI Command." The attack waves vary; they are defined in SetWave function.

The undead army includes three heros: Doomlord (custom hero), Death Knight, and Lich. Their skill order is defined in function SelectHeroes.

Code:
//===========================================================================
// 
//   Custom WarCraft III Undead AI Script
//   Defenders of Dwarvenkind
//   Dwarf Campaign - Chapter 1
// 
//   By Tommi Gustafsson
// 
//===========================================================================

//***************************************************************************
//*
//*  Global Variables
//*
//***************************************************************************

globals
	unit array				TargetQueue
	integer array			WaveUnit
	integer array			WaveQuantity
	
	integer 				WaveUnits					= 0
	integer					CurrentWave					= 1
	
    integer                 Difficulty                  = 1
    integer                 AttackOrder                 = 0
	integer					harvestingghouls            = 5

endglobals

//============================================================================
//  Utility Functions
//	Dig2Str and Int2Str
//  By AIAndy
//============================================================================
function Dig2Str takes integer i returns string
  if i == 1 then
    return "1"
  elseif i == 2 then
    return "2"
  elseif i == 3 then
    return "3"
  elseif i == 4 then
    return "4"
  elseif i == 5 then
    return "5"
  elseif i == 6 then
    return "6"
  elseif i == 7 then
    return "7"
  elseif i == 8 then
    return "8"
  elseif i == 9 then
    return "9"
  else
    return "0"
  endif
endfunction

function Int2Str takes integer ic returns string
    local string s = ""
    local integer i = ic
    local integer ialt = 0
    local boolean neg = false

    if i == 0 then
      return "0"
    endif
    if i < 0 then
      set neg = true
      set i = (-1)*i
    endif
    loop
      exitwhen i == 0
      set ialt = i
      set i = i / 10
      set s = Dig2Str( ialt - 10*i ) + s
    endloop
    if neg then
      set s = "-"+s
    endif
    return s
endfunction

//===========================================================================
// Initializes TargetQueue
//===========================================================================
function SetTargetUnits takes nothing returns nothing
    local group g = CreateGroup()
    local unit u = null
    local integer id

	call GroupEnumUnitsOfPlayer(g, Player(0), null)

    set u = FirstOfGroup(g)
    loop
    	exitwhen u == null
		set id = GetUnitTypeId(u)
    	if(id == 'h000') then
			set TargetQueue[0] = u
		elseif(id == 'nmgv') then
			set TargetQueue[1] = u
		endif

    	call GroupRemoveUnit(g, u)
		set u = FirstOfGroup(g)
	endloop

    call DestroyGroup(g)

	set TargetQueue[2] = null

endfunction

//===========================================================================
// SuicideOnQueue
//
// Description: Attacks units on a queue, prioritizing earlier targets on the
// queue over later ones. Will reattack the targets, if they are revived.
//
// Returns true when all units on the queue are destroyed or hidden
// Returns false when the attack group is destroyed
//===========================================================================
function SuicideOnQueue takes nothing returns boolean
	local unit target = null
	local integer i = 0

	loop
		//looks for a valid target, beginning from the start of the queue every 2 seconds

		set target = null
		set i = 0

		loop
			set target = TargetQueue[i]

			//Exit when all targets have been destroyed
		    if target == null then
        		return true
		    endif

			//Exit when a target that is alive and not hidden is found
			exitwhen (UnitAlive(target) and not IsUnitHidden(target))

			set i = i + 1
		endloop

		//exit if the attack group has been destroyed
        if CaptainIsEmpty() then
			return false
		endif

		//call DisplayTimedTextToPlayer(Player(0),0,0,5,"CaptainReadiness: "+Int2Str(CaptainReadiness())+"\n")

		if CaptainReadiness() < 10 then
			call CaptainGoHome()
			return false
		endif

		//Attack the target
        call AttackMoveKill(target)

		//Sleep for 2 seconds before performing any other actions
        call Sleep(2)

    endloop

	//Necessary to add because of the return check
	return false

endfunction

//===========================================================================
//  Basic Options
//===========================================================================
function InitOptions takes nothing returns nothing
    call SetMeleeAI(  )
    call SetDefendPlayer( false )
    call SetRandomPaths( false )
    call SetTargetHeroes( false )
    call SetPeonsRepair( true )
    call SetHeroesFlee( false )
    call SetHeroesBuyItems( true )
    call SetUnitsFlee( false )
    call SetGroupsFlee( false )
    call SetWatchMegaTargets( true )
    call SetIgnoreInjured( false )
    call SetHeroesTakeItems( true )
    call SetSlowChopping( false )
    call SetCaptainChanges( true )
    call SetSmartArtillery( true )
endfunction

//===========================================================================
// Updates AttackOrder and Difficulty
//===========================================================================
function UpdateConditions takes nothing returns nothing
	if CommandsWaiting() != 0 then
	    set AttackOrder = GetLastCommand()
    	set Difficulty = GetLastData()
		call PopLastCommand()
	endif
endfunction

//===========================================================================
// Stores hero ID and skills
//===========================================================================
function SelectHeroes takes nothing returns nothing
	//First Hero = Doomlord
    set hero_id = 'U000'
    set skills1[ 1] = 'AHfs'
    set skills1[ 2] = 'AEmb'
    set skills1[ 3] = 'AUav'
    set skills1[ 4] = 'AHfs'
    set skills1[ 5] = 'AUav'
    set skills1[ 6] = 'ANdo'
    set skills1[ 7] = 'AHfs'
    set skills1[ 8] = 'AUav'
    set skills1[ 9] = 'AEmb'
    set skills1[10] = 'AEmb'

	//Second Hero = Death Knight
    set hero_id2 = 'Udea'
    set skills2[ 1] = 'AUdc'
    set skills2[ 2] = 'AUau'
    set skills2[ 3] = 'AUdc'
    set skills2[ 4] = 'AUau'
    set skills2[ 5] = 'AUdc'
    set skills2[ 6] = 'AUan'
    set skills2[ 7] = 'AUau'
    set skills2[ 8] = 'AUdp'
    set skills2[ 9] = 'AUdp'
    set skills2[10] = 'AUdp'

	//Third Hero = Lich
    set hero_id3 = 'Ulic'
    set skills3[ 1] = 'AUfn'
    set skills3[ 2] = 'AUdr'
    set skills3[ 3] = 'AUfn'
    set skills3[ 4] = 'AUdr'
    set skills3[ 5] = 'AUfn'
    set skills3[ 6] = 'AUdd'
    set skills3[ 7] = 'AUdr'
    set skills3[ 8] = 'AUfa'
    set skills3[ 9] = 'AUfa'
    set skills3[10] = 'AUfa'

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 AttackWaves
//===========================================================================
function SetWave takes integer wave returns nothing
	if wave == 1 then
		set WaveUnits = 2
		set WaveUnit[0] = 'ugho'
		set WaveQuantity[0] = 18
		set WaveUnit[1] = hero_id
		set WaveQuantity[1] = 1
	elseif wave == 2 then
		set WaveUnits = 2
		set WaveUnit[0] = 'ucry'
		set WaveQuantity[0] = 13
		set WaveUnit[1] = hero_id2
		set WaveQuantity[1] = 1
	elseif wave == 3 then
		set WaveUnits = 2
		set WaveUnit[0] = 'umtw'
		set WaveQuantity[0] = 11
		set WaveUnit[1] = hero_id3
		set WaveQuantity[1] = 1
	elseif wave == 4 then
		set WaveUnits = 2
		set WaveUnit[0] = 'uabo'
		set WaveQuantity[0] = 12
		set WaveUnit[1] = hero_id
		set WaveQuantity[1] = 1
	elseif wave == 5 then
		set WaveUnits = 4
		set WaveUnit[0] = 'ugho'
		set WaveQuantity[0] = 16
		set WaveUnit[1] = 'unec'
		set WaveQuantity[1] = 8
		set WaveUnit[2] = hero_id
		set WaveQuantity[2] = 1
		set WaveUnit[3] = hero_id3
		set WaveQuantity[3] = 1
	elseif wave == 6 then
		set WaveUnits = 4
		set WaveUnit[0] = 'uabo'
		set WaveQuantity[0] = 7
		set WaveUnit[1] = 'ucry'
		set WaveQuantity[1] = 8
		set WaveUnit[2] = hero_id
		set WaveQuantity[2] = 1
		set WaveUnit[3] = hero_id2
		set WaveQuantity[3] = 1
	elseif wave == 7 then
		set WaveUnits = 4
		set WaveUnit[0] = 'ugho'
		set WaveQuantity[0] = 16
		set WaveUnit[1] = 'umtw'
		set WaveQuantity[1] = 6
		set WaveUnit[2] = hero_id
		set WaveQuantity[2] = 1
		set WaveUnit[3] = hero_id2
		set WaveQuantity[3] = 1
	elseif wave == 8 then
		set WaveUnits = 4
		set WaveUnit[0] = 'uabo'
		set WaveQuantity[0] = 12
		set WaveUnit[1] = 'unec'
		set WaveQuantity[1] = 6
		set WaveUnit[2] = hero_id
		set WaveQuantity[2] = 1
		set WaveUnit[3] = hero_id3
		set WaveQuantity[3] = 1
	elseif wave == 9 then
		set WaveUnits = 6
		set WaveUnit[0] = 'ugho'
		set WaveQuantity[0] = 12
		set WaveUnit[1] = 'unec'
		set WaveQuantity[1] = 6
		set WaveUnit[2] = 'umtw'
		set WaveQuantity[2] = 6
		set WaveUnit[3] = hero_id
		set WaveQuantity[3] = 1
		set WaveUnit[4] = hero_id2
		set WaveQuantity[4] = 1
		set WaveUnit[5] = hero_id3
		set WaveQuantity[5] = 1
	elseif wave == 10 then
		set WaveUnits = 6
		set WaveUnit[0] = 'uabo'
		set WaveQuantity[0] = 7
		set WaveUnit[1] = 'ucry'
		set WaveQuantity[1] = 8
		set WaveUnit[2] = 'unec'
		set WaveQuantity[2] = 6
		set WaveUnit[3] = hero_id
		set WaveQuantity[3] = 1
		set WaveUnit[4] = hero_id2
		set WaveQuantity[4] = 1
		set WaveUnit[5] = hero_id3
		set WaveQuantity[5] = 1
	elseif wave == 11 or wave == 13 or wave == 15 then
		set WaveUnits = 6
		set WaveUnit[0] = 'ugho'
		set WaveQuantity[0] = 12
		set WaveUnit[1] = 'unec'
		set WaveQuantity[1] = 6
		set WaveUnit[2] = 'umtw'
		set WaveQuantity[2] = 8
		set WaveUnit[3] = hero_id
		set WaveQuantity[3] = 1
		set WaveUnit[4] = hero_id2
		set WaveQuantity[4] = 1
		set WaveUnit[5] = hero_id3
		set WaveQuantity[5] = 1
	else
		set WaveUnits = 6
		set WaveUnit[0] = 'uabo'
		set WaveQuantity[0] = 7
		set WaveUnit[1] = 'ucry'
		set WaveQuantity[1] = 8
		set WaveUnit[2] = 'unec'
		set WaveQuantity[2] = 8
		set WaveUnit[3] = hero_id
		set WaveQuantity[3] = 1
		set WaveUnit[4] = hero_id2
		set WaveQuantity[4] = 1
		set WaveUnit[5] = hero_id3
		set WaveQuantity[5] = 1
	endif
endfunction

//===========================================================================
// Specifies building priorities
//===========================================================================

//Builds necropolis, first workers and goldmine
function BuildBasics takes nothing returns nothing
	//Necropolis, 0/10
    call SetBuildAll( BUILD_UNIT, 1, 'unpl', -1 )

	//2 Gold Mines
    call SetBuildAll( BUILD_UNIT, 2, 'ugol', -1 )

	//5 Acolytes, 5/10
    call SetBuildAll( BUILD_UNIT, 5, 'uaco', -1 )

	//Crypt
    call SetBuildAll( BUILD_UNIT, 1, 'usep', -1 )

	//Altar
    call SetBuildAll( BUILD_UNIT, 1, 'uaod', -1 )

	//3 ziggurats, 5/40
    call SetBuildAll( BUILD_UNIT, 3, 'uzig', -1 )

	//Graveyard
    call SetBuildAll( BUILD_UNIT, 1, 'ugrv', -1 )

	//5 acolytes, 10/40
    call SetBuildAll( BUILD_UNIT, 10, 'uaco', -1 )

	// Hero 15/40
    call SetBuildAll( BUILD_UNIT, 1, hero_id, -1 )

	//5 lumber ghouls,  25/30
    call SetBuildAll( BUILD_UNIT, 5, 'ugho', -1 )
endfunction

function BuildBuildings takes nothing returns nothing
	local integer i = 0

	// build to 9 ziggurats	
    call SetBuildAll( BUILD_UNIT, 9, 'uzig', -1 )
	
	//Halls of the Dead
    call SetBuildAll( BUILD_UNIT, 1, 'unp1', -1 )

	//Tomb of Relics
    call SetBuildAll( BUILD_UNIT, 1, 'utom', -1 )

	//2nd crypt
    call SetBuildAll( BUILD_UNIT, 2, 'usep', -1 )

	//2 Temples of the Damned
    call SetBuildAll( BUILD_UNIT, 2, 'utod', -1 )

	//Upgrade to Black Citadel
    call SetBuildAll( BUILD_UNIT, 1, 'unp2', -1 )

	//Build 3 Slaughterhouses
    call SetBuildAll( BUILD_UNIT, 3, 'uslh', -1 )

	//Altar 2
    call SetBuildAll( BUILD_UNIT, 2, 'uaod', -1 )

endfunction

//Builds heroes 2 and 3
function BuildExtraHeroes takes nothing returns nothing
    call SetBuildAll( BUILD_UNIT, 1, hero_id2, -1 )
    call SetBuildAll( BUILD_UNIT, 1, hero_id3, -1 )
endfunction

//Builds upgrades
function BuildUpgrades takes nothing returns nothing
	local integer i = 0
	
	//1/1 upgrades, if Experienced
    if (Difficulty>=2) then
        call SetBuildAll( BUILD_UPGRADE, 1, 'Rume', -1 )
        call SetBuildAll( BUILD_UPGRADE, 1, 'Ruar', -1 )
        call SetBuildAll( BUILD_UPGRADE, 1, 'Rura', -1 )
        call SetBuildAll( BUILD_UPGRADE, 1, 'Rucr', -1 )
    endif

	//Necro upgrades
    call SetBuildAll( BUILD_UPGRADE, 1, 'Rune', -1 )
    call SetBuildAll( BUILD_UPGRADE, 2, 'Rune', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'Rusm', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'Rusl', -1 )

	//2/2 upgrades, if Professional
    if (Difficulty>=3) then
        call SetBuildAll( BUILD_UPGRADE, 2, 'Rume', -1 )
        call SetBuildAll( BUILD_UPGRADE, 2, 'Ruar', -1 )
        call SetBuildAll( BUILD_UPGRADE, 2, 'Rura', -1 )
        call SetBuildAll( BUILD_UPGRADE, 2, 'Rucr', -1 )
    endif

	//Exhume & Disease cloud
    call SetBuildAll( BUILD_UPGRADE, 1, 'Ruex', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'Rupc', -1 )

	//3/3 if Champion (not available)
    if (Difficulty>=4) then
        call SetBuildAll( BUILD_UPGRADE, 3, 'Rume', -1 )
        call SetBuildAll( BUILD_UPGRADE, 3, 'Ruar', -1 )
        call SetBuildAll( BUILD_UPGRADE, 3, 'Rura', -1 )
        call SetBuildAll( BUILD_UPGRADE, 3, 'Rucr', -1 )
    endif

	call SetBuildAll( BUILD_UNIT, 8, 'uzg1', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'uzg2', -1 )

endfunction

//Builds the appropriate Attack Wave
function BuildWave takes nothing returns nothing
	local boolean unitsbuilt = false
	local integer i = 0
	local integer qty = 1
			
	loop
		if WaveQuantity[i] >= qty then
			if WaveUnit[i] == 'ugho' then
		    	call SetBuildAll( BUILD_UNIT, qty + harvestingghouls, WaveUnit[i], -1 )
		    else
		    	call SetBuildAll( BUILD_UNIT, qty, WaveUnit[i], -1 )
			endif	    	
	    	set unitsbuilt=true
	    endif
		
		set i = i + 1
		exitwhen (i == WaveUnits and unitsbuilt == false)

		if i == WaveUnits then
			set i = 0
			set unitsbuilt = false
			set qty = qty + 1
		endif
	endloop
endfunction

//Calls all building functions
function BuildPriorities takes nothing returns nothing
	call BuildBasics()
	call BuildBuildings()
	call BuildExtraHeroes()
	call BuildUpgrades()
	call BuildWave()
endfunction

//===========================================================================
// Specifies harvesting priorities for workers
//===========================================================================
function HarvestPriorities takes nothing returns nothing
    local integer mine = TownWithMine()
    local integer allGold = GetUnitCountDone('uaco')
    local integer allWood = GetUnitCountDone('ugho')
	local integer goldacos1 = 0
	local integer goldacos2 = 0
	local integer lumberghouls = 0

	if allGold < 5 then
		set goldacos1 = allGold
		set goldacos2 = 0
	elseif allGold < 10 then
		set goldacos1 = 5
		set goldacos2 = allGold - 5
	else
		set goldacos1 = 5
		set goldacos2 = 5
	endif

	if allWood < harvestingghouls then
		set lumberghouls = allWood
	else
		set lumberghouls = harvestingghouls
	endif

    call HarvestGold( mine + 0, goldacos1 )
    call HarvestGold( mine + 1, goldacos2 )
    call HarvestWood( 0, lumberghouls )

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

//===========================================================================
// Returns true if the minimum forces for an attack exist
//===========================================================================
function HaveMinimumAttackers takes nothing returns boolean
	local integer i = 0
	local integer tempqty = 0

	if (GetUnitCountDone( hero_id ) < 1 or GetUnitCountDone( hero_id2 ) < 1 or GetUnitCountDone( hero_id3 ) < 1) then
		return false
	endif
	
	loop
		exitwhen i == WaveUnits
		if WaveUnit[i] == 'ugho' then
			set tempqty = WaveQuantity[i] + harvestingghouls
		else
			set tempqty = WaveQuantity[i]
		endif
		if GetUnitCountDone(WaveUnit[i]) < tempqty then
			return false
		endif
		set i = i + 1
	endloop
	
    return true
    
endfunction

//===========================================================================
// Assigns units to attack
//===========================================================================
function PrepareAttackGroup takes nothing returns nothing
	local integer i = 0

	loop
		exitwhen i == WaveUnits
	    call SetAssaultGroup(WaveQuantity[i], WaveQuantity[i], WaveUnit[i] )
	    set i = i + 1
	endloop
endfunction

//===========================================================================
// Determines all attacking assignments
//===========================================================================
function AttackAssignment takes nothing returns nothing
    local boolean AttackSuccess = false
    
	call StaggerSleep( 0, 2 )
	
    loop
    	loop
            call UpdateConditions(  )
            exitwhen ( AttackOrder > 0 and HaveMinimumAttackers() and not CaptainRetreating() and not CaptainInCombat(true) and not TownThreatened())
            call Sleep( 3 )
		endloop

		//Launch Attack
	    call InitAssaultGroup(  )
	    call PrepareAttackGroup( )
	    
	    //Immediately begin to construct the next attack wave
		set CurrentWave = CurrentWave + 1
		call SetWave(CurrentWave)
		
		//Form the attack group
	    call FormGroup( 3, true )

		//Attack Units on the Queue; the return value is not used here
   		set AttackSuccess = SuicideOnQueue()

		call Sleep(3)
    endloop
endfunction

//***************************************************************************
//*
//*  Main Entry Point
//*
//***************************************************************************

//===========================================================================
function main takes nothing returns nothing
    call InitAI(  )
    call InitOptions(  )
    call SelectHeroes(  )
    call CreateCaptains(  )
    call SetHeroLevels( function ChooseHeroSkill )

    // Define Target Units (Gate & Vault)
    call SetTargetUnits()
    
    // Define the first attack wave
    call SetWave(CurrentWave)

    call Sleep( 0.1 )
    call StartThread( function WorkerAssignment )
    call StartThread( function AttackAssignment )
    call PlayGame(  )
endfunction

Cheers!
 
Status
Not open for further replies.
Top