• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.
  • It's time for the first HD Modeling Contest of 2025. Join the theme discussion for Hive's HD Modeling Contest #7! Click here to post your idea!

[JASS] Help with custom race melee Ai

I was wondering if someone could help me with my custom race-melee AI. I currently have 2 AIS.

The first one (FWC) was based on another AI. The AI builds everything in the workflow, with the expectation that it builds a new "town hall" every time it upgrades a Teir.

JASS:
//===========================================================================
//
// Cult of the Flesh Weavers
//
//   Warcraft III AI script
//   Generated by the Warcraft III World Editor
//
//===========================================================================

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

globals
    integer                 attackWave                 = 1
    integer                 nextDelay                  = 0
    integer                 awGold                     = 0
    integer                 awWood                     = 0

    // Conditions
    boolean                 gCond_NeedGrotesque        = false
    boolean                 gCond_NeedAbhorrent        = false
    boolean                 gCond_NeedWitch            = false
    boolean                 gCond_NeedUndertaker       = false
    boolean                 gCond_NeedNosferatu        = false
    boolean                 gCond_NeedHarpyVulture     = false
    boolean                 gCond_NeedStitched         = 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 == 'h000') then
        set awGold = awGold + minQty
    endif

    // Track attacking wood workers
    if (unitID == 'h000') then
        set awWood = awWood + minQty
    endif

    call SetAssaultGroup( minQty, maxQty, unitID )
endfunction

//***************************************************************************
//*
//*  Basic Options
//*
//***************************************************************************

//===========================================================================
function InitOptions takes nothing returns nothing
    call SetMeleeAI(  )
    call SetDefendPlayer( true )
    call SetRandomPaths( true )
    call SetTargetHeroes( false )
    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
    set gCond_NeedGrotesque = ( GetUnitCount( 'o000' ) <= 2 )
    set gCond_NeedAbhorrent = ( GetUnitCount( 'o001' ) <= 2 )
    set gCond_NeedWitch = ( GetUnitCount( 'o002' ) <= 2 )
    set gCond_NeedUndertaker = ( GetUnitCount( 'u003' ) <= 2 )
    set gCond_NeedNosferatu = ( GetUnitCount( 'h003' ) <= 2 )
    set gCond_NeedHarpyVulture = ( GetUnitCount( 'e000' ) <= 2 )
    set gCond_NeedStitched = ( GetUnitCount( 'o00N' ) <= 2 )
endfunction

//***************************************************************************
//*
//*  Heroes
//*
//***************************************************************************

//===========================================================================
// Stores hero ID and skills
//===========================================================================
function SetHero takes integer order, integer heroid returns nothing
    if (order == 1) then
        set hero_id = heroid
        if (heroid == 'H001') then
            set skills1[ 1] = 'A01X'
            set skills1[ 2] = 'A01U'
            set skills1[ 3] = 'A01S'
            set skills1[ 4] = 'A01X'
            set skills1[ 5] = 'A01U'
            set skills1[ 6] = 'A027'
            set skills1[ 7] = 'A01S'
            set skills1[ 8] = 'A01X'
            set skills1[ 9] = 'A01U'
            set skills1[10] = 'A01S'
        elseif (heroid == 'U007') then
            set skills1[ 1] = 'A01I'
            set skills1[ 2] = 'A01L'
            set skills1[ 3] = 'A01N'
            set skills1[ 4] = 'A01I'
            set skills1[ 5] = 'A01L'
            set skills1[ 6] = 'A01K'
            set skills1[ 7] = 'A01N'
            set skills1[ 8] = 'A01I'
            set skills1[ 9] = 'A01L'
            set skills1[10] = 'A01N'
        elseif (heroid == 'O005') then
            set skills1[ 1] = 'A00D'
            set skills1[ 2] = 'A01T'
            set skills1[ 3] = 'A023'
            set skills1[ 4] = 'A00D'
            set skills1[ 5] = 'A01T'
            set skills1[ 6] = 'A026'
            set skills1[ 7] = 'A023'
            set skills1[ 8] = 'A00D'
            set skills1[ 9] = 'A01T'
            set skills1[10] = 'A023'
        endif
    elseif (order == 2) then
        set hero_id2 = heroid
        if (heroid == 'H001') then
            set skills2[ 1] = 'A01X'
            set skills2[ 2] = 'A01U'
            set skills2[ 3] = 'A01S'
            set skills2[ 4] = 'A01X'
            set skills2[ 5] = 'A01U'
            set skills2[ 6] = 'A027'
            set skills2[ 7] = 'A01S'
            set skills2[ 8] = 'A01X'
            set skills2[ 9] = 'A01U'
            set skills2[10] = 'A01S'
        elseif (heroid == 'U007') then
            set skills2[ 1] = 'A01I'
            set skills2[ 2] = 'A01L'
            set skills2[ 3] = 'A01N'
            set skills2[ 4] = 'A01I'
            set skills2[ 5] = 'A01L'
            set skills2[ 6] = 'A01K'
            set skills2[ 7] = 'A01N'
            set skills2[ 8] = 'A01I'
            set skills2[ 9] = 'A01L'
            set skills2[10] = 'A01N'
        elseif (heroid == 'O005') then
            set skills2[ 1] = 'A00D'
            set skills2[ 2] = 'A01T'
            set skills2[ 3] = 'A023'
            set skills2[ 4] = 'A00D'
            set skills2[ 5] = 'A01T'
            set skills2[ 6] = 'A026'
            set skills2[ 7] = 'A023'
            set skills2[ 8] = 'A00D'
            set skills2[ 9] = 'A01T'
            set skills2[10] = 'A023'
        endif
    elseif (order == 3) then
        set hero_id3 = heroid
        if (heroid == 'H001') then
            set skills3[ 1] = 'A01X'
            set skills3[ 2] = 'A01U'
            set skills3[ 3] = 'A01S'
            set skills3[ 4] = 'A01X'
            set skills3[ 5] = 'A01U'
            set skills3[ 6] = 'A027'
            set skills3[ 7] = 'A01S'
            set skills3[ 8] = 'A01X'
            set skills3[ 9] = 'A01U'
            set skills3[10] = 'A01S'
        elseif (heroid == 'U007') then
            set skills3[ 1] = 'A01I'
            set skills3[ 2] = 'A01L'
            set skills3[ 3] = 'A01N'
            set skills3[ 4] = 'A01I'
            set skills3[ 5] = 'A01L'
            set skills3[ 6] = 'A01K'
            set skills3[ 7] = 'A01N'
            set skills3[ 8] = 'A01I'
            set skills3[ 9] = 'A01L'
            set skills3[10] = 'A01N'
        elseif (heroid == 'O005') then
            set skills3[ 1] = 'A00D'
            set skills3[ 2] = 'A01T'
            set skills3[ 3] = 'A023'
            set skills3[ 4] = 'A00D'
            set skills3[ 5] = 'A01T'
            set skills3[ 6] = 'A026'
            set skills3[ 7] = 'A023'
            set skills3[ 8] = 'A00D'
            set skills3[ 9] = 'A01T'
            set skills3[10] = 'A023'
        endif
    endif
endfunction

//===========================================================================
// Selects hero IDs for three possible heroes
//===========================================================================
function SelectHeroes takes nothing returns nothing
    local integer roll = GetRandomInt(1,100)
    if (roll <= 33) then
        call SetHero( 1, 'H001' )
        call SetHero( 2, 'U007' )
        call SetHero( 3, 'O005' )
    elseif (roll <= 67) then
        call SetHero( 1, 'U007' )
        call SetHero( 2, 'H001' )
        call SetHero( 3, 'O005' )
    else
        call SetHero( 1, 'O005' )
        call SetHero( 2, 'H001' )
        call SetHero( 3, 'U007' )
    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, 'o00B', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'h000', -1 )
    call SetBuildAll( BUILD_UNIT, 2, 'h000', -1 )
    call SetBuildAll( BUILD_UNIT, 3, 'h000', -1 )
    call SetBuildAll( BUILD_UNIT, 4, 'h000', -1 )
    call SetBuildAll( BUILD_UNIT, 5, 'h000', -1 )
    call SetBuildAll( BUILD_UNIT, 6, 'h000', -1 )
    call SetBuildAll( BUILD_UNIT, 7, 'h000', -1 )
    call SetBuildAll( BUILD_UNIT, 8, 'h000', -1 )
    call SetBuildAll( BUILD_UNIT, 9, 'h000', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'o009', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'o006', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'o007', -1 )
    if (gCond_NeedGrotesque) then
        call SetBuildAll( BUILD_UNIT, 1, 'o000', -1 )
        call SetBuildAll( BUILD_UNIT, 2, 'o000', -1 )
        call SetBuildAll( BUILD_UNIT, 3, 'o000', -1 )
        call SetBuildAll( BUILD_UNIT, 4, 'o000', -1 )
    endif
    call SetBuildAll( BUILD_UNIT, 1, 'o00G', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'h002', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'o00F', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'R003', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'R004', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'R005', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'R008', -1 )
    call SetBuildAll( BUILD_UPGRADE, 2, 'R008', -1 )
    call SetBuildAll( BUILD_UNIT, 1, hero_id, -1 )
    call SetBuildAll( BUILD_UNIT, 2, 'o009', -1 )
    if (gCond_NeedAbhorrent) then
        call SetBuildAll( BUILD_UNIT, 1, 'o001', -1 )
        call SetBuildAll( BUILD_UNIT, 2, 'o001', -1 )
    endif
    call BuildExpansion( 'o00B', 'o00B' )
    call SetBuildAll( BUILD_UNIT, 1, 'o00D', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'o00H', -1 )
    call SetBuildAll( BUILD_UNIT, 2, 'o00H', -1 )
    call SetBuildAll( BUILD_UNIT, 3, 'o00H', -1 )
    call SetBuildAll( BUILD_UNIT, 4, 'o00H', -1 )
    call SetBuildAll( BUILD_UNIT, 2, 'o007', -1 )
    if (gCond_NeedAbhorrent) then
        call SetBuildAll( BUILD_UNIT, 3, 'o001', -1 )
        call SetBuildAll( BUILD_UNIT, 4, 'o001', -1 )
        call SetBuildAll( BUILD_UNIT, 5, 'o001', -1 )
        call SetBuildAll( BUILD_UNIT, 6, 'o001', -1 )
    endif
    call SetBuildAll( BUILD_UNIT, 1, 'o00C', -1 )
    call SetBuildAll( BUILD_UNIT, 3, 'o009', -1 )
    call SetBuildAll( BUILD_UNIT, 4, 'o009', -1 )
    call SetBuildAll( BUILD_UNIT, 5, 'o009', -1 )
    call SetBuildAll( BUILD_UNIT, 6, 'o009', -1 )
    if (gCond_NeedWitch) then
        call SetBuildAll( BUILD_UNIT, 1, 'o002', -1 )
        call SetBuildAll( BUILD_UNIT, 2, 'o002', -1 )
    endif
    if (gCond_NeedUndertaker) then
        call SetBuildAll( BUILD_UNIT, 1, 'u003', -1 )
        call SetBuildAll( BUILD_UNIT, 2, 'u003', -1 )
    endif
    if (gCond_NeedAbhorrent) then
        call SetBuildAll( BUILD_UNIT, 7, 'o001', -1 )
        call SetBuildAll( BUILD_UNIT, 8, 'o001', -1 )
    endif
    call SetBuildAll( BUILD_UNIT, 1, hero_id2, -1 )
    call SetBuildAll( BUILD_UPGRADE, 2, 'R003', -1 )
    call SetBuildAll( BUILD_UPGRADE, 2, 'R004', -1 )
    call SetBuildAll( BUILD_UPGRADE, 2, 'R005', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'R006', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'R001', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'R00A', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'R00J', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'R00K', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'o00A', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'o00E', -1 )
    call SetBuildAll( BUILD_UNIT, 1, hero_id3, -1 )
    if (gCond_NeedHarpyVulture) then
        call SetBuildAll( BUILD_UNIT, 1, 'e000', -1 )
        call SetBuildAll( BUILD_UNIT, 2, 'e000', -1 )
    endif
    if (gCond_NeedNosferatu) then
        call SetBuildAll( BUILD_UNIT, 1, 'h003', -1 )
        call SetBuildAll( BUILD_UNIT, 2, 'h003', -1 )
    endif
    if (gCond_NeedStitched) then
        call SetBuildAll( BUILD_UNIT, 1, 'o00N', -1 )
        call SetBuildAll( BUILD_UNIT, 2, 'o00N', -1 )
    endif
    call SetBuildAll( BUILD_UPGRADE, 3, 'R003', -1 )
    call SetBuildAll( BUILD_UPGRADE, 3, 'R004', -1 )
    call SetBuildAll( BUILD_UPGRADE, 3, 'R005', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'R00B', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'R00L', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'R00O', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'R00D', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'R00C', -1 )
    call SetBuildAll( BUILD_UPGRADE, 2, 'R00K', -1 )
    call SetBuildAll( BUILD_UPGRADE, 2, 'R00J', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'R000', -1 )
    call BuildExpansion( 'o00B', 'o00B' )
endfunction

//===========================================================================
// Specifies harvesting priorities for workers
//===========================================================================
function HarvestPriorities takes nothing returns nothing
    local integer mine = TownWithMine()
    local integer allGold = GetUnitCountDone('h000')
    local integer allWood = GetUnitCountDone('h000')
    local integer numWorkers
    set numWorkers = 5
    call HarvestGold( 0, numWorkers )
    set numWorkers = 5
    call HarvestWood( 0, numWorkers )
    set numWorkers = 5
    call HarvestGold( 1, numWorkers )
    set numWorkers = 4
    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 > 16) then
        return false
    endif

    // First Hero Only
    if (GetUnitCountDone(hero_id) < 1) then
        return false
    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: Large
    if (groupID == 1) then
        set all = GetUnitCountDone( 'o000' )
        call AddAttackUnit( all, all, 'o000' )
        call AddAttackUnit( 1,   1,   hero_id2 )
        call AddAttackUnit( 3,   3,   'e000' )
        call AddAttackUnit( 1,   1,   hero_id )
        call AddAttackUnit( 2,   2,   'o002' )
        call AddAttackUnit( 1,   1,   hero_id3 )
        set all = GetUnitCountDone( 'o001' )
        call AddAttackUnit( all, all, 'o001' )

        // Attack Group #2: Massive
    elseif (groupID == 2) then
        set all = GetUnitCountDone( 'o000' )
        call AddAttackUnit( all, all, 'o000' )
        call AddAttackUnit( 1,   1,   hero_id2 )
        set all = GetUnitCountDone( 'h00D' )
        call AddAttackUnit( all, all, 'h00D' )
        set all = GetUnitCountDone( 'e000' )
        call AddAttackUnit( all, all, 'e000' )
        call AddAttackUnit( 1,   1,   hero_id )
        set all = GetUnitCountDone( 'o00N' )
        call AddAttackUnit( all, all, 'o00N' )
        call AddAttackUnit( 1,   1,   hero_id3 )
        set all = GetUnitCountDone( 'u003' )
        call AddAttackUnit( all, all, 'u003' )
        set all = GetUnitCountDone( 'o002' )
        call AddAttackUnit( all, all, 'o002' )
        set all = GetUnitCountDone( 'o001' )
        call AddAttackUnit( all, all, 'o001' )

        // Attack Group #3: Medium
    elseif (groupID == 3) then
        call AddAttackUnit( 2,   2,   'o000' )
        call AddAttackUnit( 1,   1,   hero_id2 )
        call AddAttackUnit( 1,   1,   'e000' )
        call AddAttackUnit( 1,   1,   hero_id )
        call AddAttackUnit( 1,   1,   hero_id3 )
        set all = GetUnitCountDone( 'u003' )
        call AddAttackUnit( all, all, 'u003' )
        set all = GetUnitCountDone( 'o002' )
        call AddAttackUnit( all, all, 'o002' )
        set all = GetUnitCountDone( 'o001' )
        call AddAttackUnit( all, all, 'o001' )

        // Attack Group #4: Medium 2
    elseif (groupID == 4) then
        set all = GetUnitCountDone( 'o000' )
        call AddAttackUnit( all, all, 'o000' )
        call AddAttackUnit( 1,   1,   hero_id2 )
        call AddAttackUnit( 1,   1,   'e000' )
        call AddAttackUnit( 1,   1,   hero_id )
        call AddAttackUnit( 1,   1,   hero_id3 )
        set all = GetUnitCountDone( 'u003' )
        call AddAttackUnit( all, all, 'u003' )
        set all = GetUnitCountDone( 'o002' )
        call AddAttackUnit( all, all, 'o002' )
        call AddAttackUnit( 3,   3,   'o001' )

        // Attack Group #5: Small
    elseif (groupID == 5) then
        call AddAttackUnit( 3,   3,   'o000' )
        call AddAttackUnit( 1,   1,   hero_id )

        // Attack Group #6: Small2
    elseif (groupID == 6) then
        call AddAttackUnit( 3,   3,   'o000' )
        call AddAttackUnit( 1,   1,   hero_id )
        call AddAttackUnit( 3,   3,   'o001' )

        // Attack Group #7: Small3
    elseif (groupID == 7) then
        call AddAttackUnit( 3,   3,   'o000' )
        call AddAttackUnit( 1,   1,   hero_id )
        set all = GetUnitCountDone( 'u003' )
        call AddAttackUnit( all, all, 'u003' )
        set all = GetUnitCountDone( 'o002' )
        call AddAttackUnit( all, all, 'o002' )
        call AddAttackUnit( 3,   3,   'o001' )

    endif
endfunction

//===========================================================================
// Prepares an attack group based on the current attack wave
//===========================================================================
function PrepareForces takes nothing returns nothing
    if (attackWave == 1) then
        call PrepareAttackGroup( 5 )
    elseif (attackWave == 2) then
        call PrepareAttackGroup( 6 )
    elseif (attackWave == 3) then
        call PrepareAttackGroup( 6 )
    elseif (attackWave == 4) then
        call PrepareAttackGroup( 7 )
    elseif (attackWave == 5) then
        call PrepareAttackGroup( 3 )
    elseif (attackWave == 6) then
        call PrepareAttackGroup( 3 )
    elseif (attackWave == 7) then
        call PrepareAttackGroup( 3 )
    elseif (attackWave == 8) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 9) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 10) then
        call PrepareAttackGroup( 2 )
    elseif (attackWave == 11) then
        call PrepareAttackGroup( 2 )
    elseif (attackWave == 12) then
        call PrepareAttackGroup( 2 )
    elseif (attackWave == 13) then
        call PrepareAttackGroup( 2 )
    elseif (attackWave == 14) then
        call PrepareAttackGroup( 2 )
    elseif (attackWave == 15) then
        call PrepareAttackGroup( 2 )
    elseif (attackWave == 16) 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 == 0) then
        call Sleep( 400 )
    elseif (inWave == 1) then
        call Sleep( 120 )
    elseif (inWave == 2) then
        call Sleep( 140 )
    elseif (inWave == 3) then
        call Sleep( 160 )
    elseif (inWave == 4) then
        call Sleep( 130 )
    elseif (inWave == 5) then
        call Sleep( 130 )
    elseif (inWave == 6) then
        call Sleep( 130 )
    elseif (inWave == 7) then
        call Sleep( 130 )
    elseif (inWave == 8) then
        call Sleep( 130 )
    elseif (inWave == 9) then
        call Sleep( 130 )
    elseif (inWave == 10) then
        call Sleep( 65 )
    elseif (inWave == 11) then
        call Sleep( 65 )
    elseif (inWave == 12) then
        call Sleep( 65 )
    elseif (inWave == 13) then
        call Sleep( 65 )
    elseif (inWave == 14) then
        call Sleep( 65 )
    elseif (inWave == 15) then
        call Sleep( 65 )
    elseif (inWave == 16) then
        call Sleep( 65 )
    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 > 16) then
        set attackWave = 16
        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 (target == null) then
        set target = GetAllianceTarget()
        if (target != null) then
            set setAlly = false
        endif
    endif

    // Target Priority #2
    if (target == null) then
        set target = GetExpansionFoe()
        if (target != null) then
            set take_exp = false
        endif
    endif

    // Target Priority #3
    if (target == null) then
        set target = GetMegaTarget()
    endif

    // Target Priority #4
    if (target == null) then
        set target = GetEnemyExpansion()
    endif

    // Target Priority #5
    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

    // Target Priority #6
    if (target == null) then
        set target = GetCreepCamp( 0, 9, false )
    endif

    // Target Priority #7
    if (target == null) then
        set target = GetCreepCamp( 10, 100, true )
    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, "Cult of the Flesh Weavers" )
    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



The second (CWF) I made from scratch and is meant to be an improvement, but It will not build or train any after it creates a hero and three combat units and attacks the closest high level expansion.

JASS:
//===========================================================================
//
// Cult of the Flesh Weavers
//
//   Warcraft III AI script
//   Generated by the Warcraft III World Editor
//
//===========================================================================

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

globals
    integer                 attackWave                 = 1
    integer                 nextDelay                  = 0
    integer                 awGold                     = 0
    integer                 awWood                     = 0

    // Conditions
    boolean                 gCond_NeedAbhorrent        = false
    boolean                 gCond_NeedGrotesque        = false
    boolean                 gCond_NeedHarpyVulture     = false
    boolean                 gCond_NeedUndertaker       = false
    boolean                 gCond_NeedWitchHag         = false
    boolean                 gCond_NeedGiantBat         = false
    boolean                 gCond_NeedTrebuchet        = false
    boolean                 gCond_NeedCorpseCart       = false
    boolean                 gCond_NeedWickerman        = false
    boolean                 gCond_NeedNosferatu        = false
    boolean                 gCond_NeedStitchedGiant    = false
    boolean                 gCond_CreepAttack          = 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 == 'h000') then
        set awGold = awGold + minQty
    endif

    // Track attacking wood workers
    if (unitID == 'h000') then
        set awWood = awWood + minQty
    endif

    call SetAssaultGroup( minQty, maxQty, unitID )
endfunction

//***************************************************************************
//*
//*  Basic Options
//*
//***************************************************************************

//===========================================================================
function InitOptions takes nothing returns nothing
    call SetMeleeAI(  )
    call SetDefendPlayer( false )
    call SetRandomPaths( true )
    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
    set gCond_NeedAbhorrent = ( GetUnitCount( 'o001' ) <= 2 )
    set gCond_NeedGrotesque = ( GetUnitCount( 'o000' ) <= 2 )
    set gCond_NeedHarpyVulture = ( GetUnitCount( 'e000' ) <= 2 )
    set gCond_NeedUndertaker = ( GetUnitCount( 'u003' ) <= 2 )
    set gCond_NeedWitchHag = ( GetUnitCount( 'o002' ) <= 2 )
    set gCond_NeedGiantBat = ( GetUnitCount( 'h004' ) <= 2 )
    set gCond_NeedTrebuchet = ( GetUnitCount( 'o004' ) <= 2 )
    set gCond_NeedCorpseCart = ( GetUnitCount( 'u005' ) <= 2 )
    set gCond_NeedWickerman = ( GetUnitCount( 'u008' ) <= 2 )
    set gCond_NeedNosferatu = ( GetUnitCount( 'h003' ) <= 2 )
    set gCond_NeedStitchedGiant = ( GetUnitCount( 'o00N' ) <= 2 )
    set gCond_CreepAttack = ( CaptainGroupSize(  ) == 7 )
endfunction

//***************************************************************************
//*
//*  Heroes
//*
//***************************************************************************

//===========================================================================
// Stores hero ID and skills
//===========================================================================
function SetHero takes integer order, integer heroid returns nothing
    if (order == 1) then
        set hero_id = heroid
        if (heroid == 'H001') then
            set skills1[ 1] = 'A01X'
            set skills1[ 2] = 'A01U'
            set skills1[ 3] = 'A01S'
            set skills1[ 4] = 'A01X'
            set skills1[ 5] = 'A01U'
            set skills1[ 6] = 'A027'
            set skills1[ 7] = 'A01S'
            set skills1[ 8] = 'A01X'
            set skills1[ 9] = 'A01U'
            set skills1[10] = 'A01S'
        elseif (heroid == 'U007') then
            set skills1[ 1] = 'A01I'
            set skills1[ 2] = 'A01L'
            set skills1[ 3] = 'A01N'
            set skills1[ 4] = 'A01I'
            set skills1[ 5] = 'A01L'
            set skills1[ 6] = 'A01K'
            set skills1[ 7] = 'A01N'
            set skills1[ 8] = 'A01I'
            set skills1[ 9] = 'A01L'
            set skills1[10] = 'A01N'
        elseif (heroid == 'O005') then
            set skills1[ 1] = 'A00D'
            set skills1[ 2] = 'A01T'
            set skills1[ 3] = 'A023'
            set skills1[ 4] = 'A00D'
            set skills1[ 5] = 'A01T'
            set skills1[ 6] = 'A026'
            set skills1[ 7] = 'A023'
            set skills1[ 8] = 'A00D'
            set skills1[ 9] = 'A01T'
            set skills1[10] = 'A023'
        endif
    elseif (order == 2) then
        set hero_id2 = heroid
        if (heroid == 'H001') then
            set skills2[ 1] = 'A01X'
            set skills2[ 2] = 'A01U'
            set skills2[ 3] = 'A01S'
            set skills2[ 4] = 'A01X'
            set skills2[ 5] = 'A01U'
            set skills2[ 6] = 'A027'
            set skills2[ 7] = 'A01S'
            set skills2[ 8] = 'A01X'
            set skills2[ 9] = 'A01U'
            set skills2[10] = 'A01S'
        elseif (heroid == 'U007') then
            set skills2[ 1] = 'A01I'
            set skills2[ 2] = 'A01L'
            set skills2[ 3] = 'A01N'
            set skills2[ 4] = 'A01I'
            set skills2[ 5] = 'A01L'
            set skills2[ 6] = 'A01K'
            set skills2[ 7] = 'A01N'
            set skills2[ 8] = 'A01I'
            set skills2[ 9] = 'A01L'
            set skills2[10] = 'A01N'
        elseif (heroid == 'O005') then
            set skills2[ 1] = 'A00D'
            set skills2[ 2] = 'A01T'
            set skills2[ 3] = 'A023'
            set skills2[ 4] = 'A00D'
            set skills2[ 5] = 'A01T'
            set skills2[ 6] = 'A026'
            set skills2[ 7] = 'A023'
            set skills2[ 8] = 'A00D'
            set skills2[ 9] = 'A01T'
            set skills2[10] = 'A023'
        endif
    elseif (order == 3) then
        set hero_id3 = heroid
        if (heroid == 'H001') then
            set skills3[ 1] = 'A01X'
            set skills3[ 2] = 'A01U'
            set skills3[ 3] = 'A01S'
            set skills3[ 4] = 'A01X'
            set skills3[ 5] = 'A01U'
            set skills3[ 6] = 'A027'
            set skills3[ 7] = 'A01S'
            set skills3[ 8] = 'A01X'
            set skills3[ 9] = 'A01U'
            set skills3[10] = 'A01S'
        elseif (heroid == 'U007') then
            set skills3[ 1] = 'A01I'
            set skills3[ 2] = 'A01L'
            set skills3[ 3] = 'A01N'
            set skills3[ 4] = 'A01I'
            set skills3[ 5] = 'A01L'
            set skills3[ 6] = 'A01K'
            set skills3[ 7] = 'A01N'
            set skills3[ 8] = 'A01I'
            set skills3[ 9] = 'A01L'
            set skills3[10] = 'A01N'
        elseif (heroid == 'O005') then
            set skills3[ 1] = 'A00D'
            set skills3[ 2] = 'A01T'
            set skills3[ 3] = 'A023'
            set skills3[ 4] = 'A00D'
            set skills3[ 5] = 'A01T'
            set skills3[ 6] = 'A026'
            set skills3[ 7] = 'A023'
            set skills3[ 8] = 'A00D'
            set skills3[ 9] = 'A01T'
            set skills3[10] = 'A023'
        endif
    endif
endfunction

//===========================================================================
// Selects hero IDs for three possible heroes
//===========================================================================
function SelectHeroes takes nothing returns nothing
    local integer roll = GetRandomInt(1,100)
    if (roll <= 34) then
        call SetHero( 1, 'H001' )
        call SetHero( 2, 'U007' )
        call SetHero( 3, 'O005' )
    elseif (roll <= 67) then
        call SetHero( 1, 'U007' )
        call SetHero( 2, 'H001' )
        call SetHero( 3, 'O005' )
    else
        call SetHero( 1, 'O005' )
        call SetHero( 2, 'H001' )
        call SetHero( 3, 'U007' )
    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, 'o00B', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'h000', -1 )
    call SetBuildAll( BUILD_UNIT, 2, 'h000', -1 )
    call SetBuildAll( BUILD_UNIT, 3, 'h000', -1 )
    call SetBuildAll( BUILD_UNIT, 4, 'h000', -1 )
    call SetBuildAll( BUILD_UNIT, 5, 'h000', -1 )
    call SetBuildAll( BUILD_UNIT, 6, 'h000', -1 )
    call SetBuildAll( BUILD_UNIT, 7, 'h000', -1 )
    call SetBuildAll( BUILD_UNIT, 8, 'h000', -1 )
    call SetBuildAll( BUILD_UNIT, 9, 'h000', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'o006', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'o007', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'o009', -1 )
    call SetBuildAll( BUILD_UNIT, 1, hero_id, -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'o000', -1 )
    if (gCond_NeedGrotesque) then
        call SetBuildAll( BUILD_UNIT, 2, 'o000', -1 )
        call SetBuildAll( BUILD_UNIT, 3, 'o000', -1 )
    endif
    call SetBuildAll( BUILD_UNIT, 2, 'o009', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'o00H', -1 )
    call SetBuildAll( BUILD_UNIT, 3, 'o009', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'o00G', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'h002', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'o00F', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'o001', -1 )
    if (gCond_NeedAbhorrent) then
        call SetBuildAll( BUILD_UNIT, 2, 'o001', -1 )
        call SetBuildAll( BUILD_UNIT, 3, 'o001', -1 )
    endif
    call BuildExpansion( 'o00B', 'o00B' )
    call SetBuildAll( BUILD_UPGRADE, 1, 'R003', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'R004', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'R005', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'R00A', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'o00D', -1 )
    call SetBuildAll( BUILD_UNIT, 2, 'o00H', -1 )
    call SetBuildAll( BUILD_UNIT, 3, 'o00H', -1 )
    call SetBuildAll( BUILD_UNIT, 2, 'o007', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'o00C', -1 )
    call SetBuildAll( BUILD_UNIT, 4, 'o00H', -1 )
    call SetBuildAll( BUILD_UNIT, 1, hero_id2, -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'o002', -1 )
    if (gCond_NeedWitchHag) then
        call SetBuildAll( BUILD_UNIT, 2, 'o002', -1 )
    endif
    call SetBuildAll( BUILD_UNIT, 1, 'o008', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'u003', -1 )
    if (gCond_NeedUndertaker) then
        call SetBuildAll( BUILD_UNIT, 2, 'u003', -1 )
    endif
    call SetBuildAll( BUILD_UNIT, 1, 'h004', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'u005', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'R00G', -1 )
    if (gCond_NeedGrotesque) then
        call SetBuildAll( BUILD_UNIT, 4, 'o000', -1 )
    endif
    if (gCond_NeedAbhorrent) then
        call SetBuildAll( BUILD_UNIT, 4, 'o001', -1 )
        call SetBuildAll( BUILD_UNIT, 5, 'o001', -1 )
    endif
    call SetBuildAll( BUILD_UNIT, 4, 'o009', -1 )
    call SetBuildAll( BUILD_UNIT, 5, 'o009', -1 )
    call SetBuildAll( BUILD_UPGRADE, 2, 'R003', -1 )
    call SetBuildAll( BUILD_UPGRADE, 2, 'R004', -1 )
    call SetBuildAll( BUILD_UPGRADE, 2, 'R005', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'R006', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'R001', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'R008', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'R00K', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'R00J', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'R00L', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'R00H', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'R00E', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'R002', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'u008', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'e000', -1 )
    call SetBuildAll( BUILD_UNIT, 2, 'h004', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'o00A', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'o00E', -1 )
    call SetBuildAll( BUILD_UNIT, 5, 'o00H', -1 )
    call SetBuildAll( BUILD_UNIT, 6, 'o00H', -1 )
    call SetBuildAll( BUILD_UNIT, 7, 'o00H', -1 )
    call SetBuildAll( BUILD_UNIT, 8, 'o00H', -1 )
    call SetBuildAll( BUILD_UNIT, 6, 'o009', -1 )
    call SetBuildAll( BUILD_UNIT, 1, hero_id3, -1 )
    call SetBuildAll( BUILD_UNIT, 7, 'o009', -1 )
    call SetBuildAll( BUILD_UNIT, 1, 'h003', -1 )
    if (gCond_NeedNosferatu) then
        call SetBuildAll( BUILD_UNIT, 2, 'h003', -1 )
        call SetBuildAll( BUILD_UNIT, 3, 'h003', -1 )
    endif
    call SetBuildAll( BUILD_UNIT, 1, 'o00N', -1 )
    if (gCond_NeedStitchedGiant) then
        call SetBuildAll( BUILD_UNIT, 2, 'o00N', -1 )
        call SetBuildAll( BUILD_UNIT, 3, 'o00N', -1 )
        call SetBuildAll( BUILD_UNIT, 4, 'o00N', -1 )
    endif
    call SetBuildAll( BUILD_UPGRADE, 3, 'R003', -1 )
    call SetBuildAll( BUILD_UPGRADE, 3, 'R004', -1 )
    call SetBuildAll( BUILD_UPGRADE, 3, 'R005', -1 )
    call SetBuildAll( BUILD_UPGRADE, 2, 'R00K', -1 )
    call SetBuildAll( BUILD_UPGRADE, 2, 'R00J', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'R00D', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'R00C', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'R00F', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'R00M', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'R00O', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'R00B', -1 )
    call SetBuildAll( BUILD_UPGRADE, 1, 'R009', -1 )
    call BuildExpansion( 'o00B', 'o00B' )
    call BuildExpansion( 'o00B', 'o00B' )
    if (gCond_NeedGrotesque) then
        call SetBuildAll( BUILD_UNIT, 5, 'o000', -1 )
        call SetBuildAll( BUILD_UNIT, 6, 'o000', -1 )
        call SetBuildAll( BUILD_UNIT, 7, 'o000', -1 )
    endif
    if (gCond_NeedAbhorrent) then
        call SetBuildAll( BUILD_UNIT, 6, 'o001', -1 )
        call SetBuildAll( BUILD_UNIT, 7, 'o001', -1 )
        call SetBuildAll( BUILD_UNIT, 8, 'o001', -1 )
    endif
    call SetBuildAll( BUILD_UNIT, 9, 'o00H', -1 )
    call SetBuildAll( BUILD_UNIT, 10, 'o00H', -1 )
    call SetBuildAll( BUILD_UNIT, 11, 'o00H', -1 )
    call SetBuildAll( BUILD_UNIT, 12, 'o00H', -1 )
    call SetBuildAll( BUILD_UNIT, 13, 'o00H', -1 )
    call SetBuildAll( BUILD_UNIT, 14, 'o00H', -1 )
endfunction

//===========================================================================
// Specifies harvesting priorities for workers
//===========================================================================
function HarvestPriorities takes nothing returns nothing
    local integer mine = TownWithMine()
    local integer allGold = GetUnitCountDone('h000')
    local integer allWood = GetUnitCountDone('h000')
    local integer numWorkers
    set numWorkers = 5
    call HarvestGold( 0, numWorkers )
    set numWorkers = 5
    call HarvestWood( 0, numWorkers )
    set numWorkers = 5
    call HarvestGold( 1, numWorkers )
    set numWorkers = 4
    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 > 30) then
        return false
    endif

    // First Hero Only
    if (GetUnitCountDone(hero_id) < 1) then
        return false
    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: Large
    if (groupID == 1) then
        call AddAttackUnit( 1,   1,   hero_id2 )
        call AddAttackUnit( 4,   4,   'o000' )
        call AddAttackUnit( 5,   5,   'o001' )
        call AddAttackUnit( 2,   2,   'u003' )
        call AddAttackUnit( 1,   1,   hero_id )
        call AddAttackUnit( 2,   2,   'o002' )
        call AddAttackUnit( 2,   2,   'h004' )
        call AddAttackUnit( 1,   1,   'e000' )

        // Attack Group #2: Large2
    elseif (groupID == 2) then
        call AddAttackUnit( 1,   1,   hero_id2 )
        call AddAttackUnit( 4,   4,   'o000' )
        call AddAttackUnit( 5,   5,   'o001' )
        call AddAttackUnit( 2,   2,   'u003' )
        call AddAttackUnit( 1,   1,   'u005' )
        call AddAttackUnit( 1,   1,   hero_id )
        call AddAttackUnit( 2,   2,   'o002' )
        call AddAttackUnit( 2,   2,   'h004' )
        call AddAttackUnit( 1,   1,   'e000' )
        call AddAttackUnit( 1,   1,   'u008' )
        call AddAttackUnit( 1,   1,   hero_id3 )

        // Attack Group #3: Massive
    elseif (groupID == 3) then
        call AddAttackUnit( 1,   1,   hero_id2 )
        set all = GetUnitCountDone( 'o000' )
        call AddAttackUnit( all, all, 'o000' )
        set all = GetUnitCountDone( 'o001' )
        call AddAttackUnit( all, all, 'o001' )
        set all = GetUnitCountDone( 'u003' )
        call AddAttackUnit( all, all, 'u003' )
        set all = GetUnitCountDone( 'u005' )
        call AddAttackUnit( all, all, 'u005' )
        call AddAttackUnit( 1,   1,   hero_id )
        set all = GetUnitCountDone( 'o002' )
        call AddAttackUnit( all, all, 'o002' )
        set all = GetUnitCountDone( 'h004' )
        call AddAttackUnit( all, all, 'h004' )
        set all = GetUnitCountDone( 'u008' )
        call AddAttackUnit( all, all, 'u008' )
        call AddAttackUnit( 1,   1,   hero_id3 )
        set all = GetUnitCountDone( 'e000' )
        call AddAttackUnit( all, all, 'e000' )
        set all = GetUnitCountDone( 'h003' )
        call AddAttackUnit( all, all, 'h003' )
        set all = GetUnitCountDone( 'o00N' )
        call AddAttackUnit( all, all, 'o00N' )

        // Attack Group #4: Medium
    elseif (groupID == 4) then
        call AddAttackUnit( 1,   1,   hero_id )
        call AddAttackUnit( 3,   3,   'o000' )
        call AddAttackUnit( 3,   3,   'o001' )
        call AddAttackUnit( 1,   1,   'u003' )
        call AddAttackUnit( 1,   1,   'o002' )

        // Attack Group #5: Medium2
    elseif (groupID == 5) then
        call AddAttackUnit( 1,   1,   hero_id )
        call AddAttackUnit( 3,   3,   'o000' )
        call AddAttackUnit( 3,   3,   'o001' )
        call AddAttackUnit( 2,   2,   'u003' )
        call AddAttackUnit( 2,   2,   'o002' )
        call AddAttackUnit( 1,   1,   hero_id2 )

        // Attack Group #6: Medium3
    elseif (groupID == 6) then
        call AddAttackUnit( 1,   1,   hero_id2 )
        call AddAttackUnit( 4,   4,   'o000' )
        call AddAttackUnit( 5,   5,   'o001' )
        call AddAttackUnit( 2,   2,   'u003' )
        call AddAttackUnit( 2,   2,   'o002' )
        call AddAttackUnit( 1,   1,   hero_id )
        call AddAttackUnit( 1,   1,   'h004' )

        // Attack Group #7: Small
    elseif (groupID == 7) then
        call AddAttackUnit( 1,   1,   hero_id )
        call AddAttackUnit( 3,   3,   'o000' )

        // Attack Group #8: Small2
    elseif (groupID == 8) then
        call AddAttackUnit( 1,   1,   hero_id )
        call AddAttackUnit( 3,   3,   'o000' )
        call AddAttackUnit( 3,   3,   'o001' )

    endif
endfunction

//===========================================================================
// Prepares an attack group based on the current attack wave
//===========================================================================
function PrepareForces takes nothing returns nothing
    if (attackWave == 1) then
        call PrepareAttackGroup( 7 )
    elseif (attackWave == 2) then
        call PrepareAttackGroup( 7 )
    elseif (attackWave == 3) then
        call PrepareAttackGroup( 7 )
    elseif (attackWave == 4) then
        call PrepareAttackGroup( 8 )
    elseif (attackWave == 5) then
        call PrepareAttackGroup( 8 )
    elseif (attackWave == 6) then
        call PrepareAttackGroup( 8 )
    elseif (attackWave == 7) then
        call PrepareAttackGroup( 4 )
    elseif (attackWave == 8) then
        call PrepareAttackGroup( 4 )
    elseif (attackWave == 9) then
        call PrepareAttackGroup( 5 )
    elseif (attackWave == 10) then
        call PrepareAttackGroup( 5 )
    elseif (attackWave == 11) then
        call PrepareAttackGroup( 6 )
    elseif (attackWave == 12) then
        call PrepareAttackGroup( 6 )
    elseif (attackWave == 13) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 14) then
        call PrepareAttackGroup( 1 )
    elseif (attackWave == 15) then
        call PrepareAttackGroup( 2 )
    elseif (attackWave == 16) then
        call PrepareAttackGroup( 2 )
    elseif (attackWave == 17) then
        call PrepareAttackGroup( 3 )
    elseif (attackWave == 18) then
        call PrepareAttackGroup( 3 )
    elseif (attackWave == 19) then
        call PrepareAttackGroup( 3 )
    elseif (attackWave == 20) then
        call PrepareAttackGroup( 3 )
    elseif (attackWave == 21) then
        call PrepareAttackGroup( 3 )
    elseif (attackWave == 22) then
        call PrepareAttackGroup( 3 )
    elseif (attackWave == 23) then
        call PrepareAttackGroup( 3 )
    elseif (attackWave == 24) then
        call PrepareAttackGroup( 3 )
    elseif (attackWave == 25) then
        call PrepareAttackGroup( 3 )
    elseif (attackWave == 26) then
        call PrepareAttackGroup( 3 )
    elseif (attackWave == 27) then
        call PrepareAttackGroup( 3 )
    elseif (attackWave == 28) then
        call PrepareAttackGroup( 3 )
    elseif (attackWave == 29) then
        call PrepareAttackGroup( 3 )
    elseif (attackWave == 30) then
        call PrepareAttackGroup( 3 )
    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( 120 )
    elseif (inWave == 2) then
        call Sleep( 130 )
    elseif (inWave == 3) then
        call Sleep( 130 )
    elseif (inWave == 4) then
        call Sleep( 130 )
    elseif (inWave == 5) then
        call Sleep( 130 )
    elseif (inWave == 6) then
        call Sleep( 130 )
    elseif (inWave == 7) then
        call Sleep( 100 )
    elseif (inWave == 8) then
        call Sleep( 100 )
    elseif (inWave == 9) then
        call Sleep( 100 )
    elseif (inWave == 10) then
        call Sleep( 100 )
    elseif (inWave == 11) then
        call Sleep( 100 )
    elseif (inWave == 12) then
        call Sleep( 100 )
    elseif (inWave == 13) then
        call Sleep( 60 )
    elseif (inWave == 14) then
        call Sleep( 60 )
    elseif (inWave == 15) then
        call Sleep( 60 )
    elseif (inWave == 16) then
        call Sleep( 60 )
    elseif (inWave == 17) then
        call Sleep( 30 )
    elseif (inWave == 18) then
        call Sleep( 30 )
    elseif (inWave == 19) then
        call Sleep( 30 )
    elseif (inWave == 20) then
        call Sleep( 30 )
    elseif (inWave == 21) then
        call Sleep( 30 )
    elseif (inWave == 22) then
        call Sleep( 30 )
    elseif (inWave == 23) then
        call Sleep( 30 )
    elseif (inWave == 24) then
        call Sleep( 30 )
    elseif (inWave == 25) then
        call Sleep( 30 )
    elseif (inWave == 26) then
        call Sleep( 30 )
    elseif (inWave == 27) then
        call Sleep( 30 )
    elseif (inWave == 28) then
        call Sleep( 30 )
    elseif (inWave == 29) then
        call Sleep( 30 )
    elseif (inWave == 30) then
        call Sleep( 30 )
    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 > 30) then
        set attackWave = 30
        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 (target == null) then
        set target = GetAllianceTarget()
        if (target != null) then
            set setAlly = false
        endif
    endif

    // Target Priority #2
    if (target == null) then
        set target = GetExpansionFoe()
        if (target != null) then
            set take_exp = false
        endif
    endif

    // Target Priority #3
    if (target == null) then
        set target = GetMegaTarget()
    endif

    // Target Priority #4
    if (target == null) then
        set target = GetEnemyExpansion()
    endif

    // Target Priority #5
    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

    // Target Priority #6
    if (target == null) then
        set target = GetCreepCamp( 0, 9, false )
    endif

    // Target Priority #7
    if (gCond_CreepAttack) then
        if (target == null) then
            set target = GetCreepCamp( 10, 100, true )
        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, "Cult of the Flesh Weavers" )
    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
 

Attachments

  • FleshWeaverCult2.0(9)roundvillage.w3x
    8.8 MB · Views: 1
  • FWC1 AI.ai
    28.6 KB · Views: 0
  • CFW AI.ai
    32.7 KB · Views: 1
Last edited:
What exactly do you want help with? Does it have any bugs or you just want general help to make it better?
For the first one (FWC), I'd like help fixing the bug that causes it to build more refuges (town halls).

For the second one (CWF), I'd like help fixing the bug that prevents it from progressing through its work flow, and I'd also like recommendations on general improvements.

Just a heads up, I have no knowledge of JASS. I created these through the AI editor.
 
Level 20
Joined
Mar 16, 2008
Messages
820
I am similar since IDK JASS well and also used GUI AI as a template. I attached the GUI AI script that I edited for my map. Maybe you could find somethings useful to you in it. You will need to add all custom units to the variable declaration at the beginning, like you can see in my script. But don't define any of the default units as variables or it will bug out the script. Also you should download a syntax checker.

1) For the town halls, you need to use conditions and a very specific function. There are a few functions for expanding and building town halls but I found these to be the most reliable. Also this is for a melee AI and most guides on here are for campaign AIs. There is a difference.

JASS:
function UpdateConditions takes nothing returns nothing
    set gCond_Need_Town_Hall = ( ( GetUnitCount( TOWN_HALL ) ) < 2 )
endfunction
JASS:
...
    if gCond_Need_Town_Hall then
        call BuildExpansion (TOWN_HALL, TOWN_HALL)
    endif
...

So this condition checks if there are less than 2 town halls before building another. For this AI i only want it to build two town halls. You need to understand how the conditions work and how the script "thinks". So if it upgrades it's down hall to a keep then it would build another town hall, so you would want to add a condition that checks if there are no keeps and town halls, or something like that depending on what you need.

2) If it is working for the most part but has a bug getting through the workflow, then it's likely either
--a techtree requirement problem
--not enough room to build problem
--not enough money
something like that blocking it from finishing the build order just like a normal player.

Hope that helps.
 

Attachments

  • King_AI_insane.ai
    52.9 KB · Views: 4
Top