• 🏆 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!

[JASS] Help with an AI Trigger

Status
Not open for further replies.
Level 2
Joined
Aug 22, 2013
Messages
21
Ok, I am having trouble with this AI system, and my problem is I am not sure how to set the AI difficulty. I assume that is why I am getting Jasshelper errors currently when I save the map. I believe it is the strong array for the difficulty or that I have not defined it or called it at all.


JASS:
 Difficulty-dependant variables (to change them, look in "main")
    integer MinesToOwn = 2 //(2 for Newb AI, 3 for Normal, 4 for Insane)
    string array DifficultyName //"(Easy)", "(Normal)", "(Insane)"


JASS:
function main takes nothing returns nothing
    set ai_player = Player(GetAiPlayer())
    set MinesToOwn = 1 + MeleeDifficulty()
    set DifficultyName[1] = "(Easy)"
    set DifficultyName[2] = "(Normal)"
    set DifficultyName[3] = "(Insane)"
    if WantName then
        if WantDifficultyInName then
            call SetPlayerName(ai_player, Name + "" + DifficultyName[MeleeDifficulty()])
        else
            call SetPlayerName(ai_player, Name)
        endif

Also, I am having this these errors in Jasshelper with the current trigger in jass
Errors:
Code:
Line 4153: Function redeclared: main
Line 3915: ---- Previous declaration.
JASS:
function main takes nothing returns nothing
 
Last edited:
Level 2
Joined
Aug 22, 2013
Messages
21
Ok, well, I honestly would like some help with this as I am new to jass and trying to figure it out, when I don't redeclare it, it causes another error that quotes 'takes' now, instead of main.
 
Level 18
Joined
Sep 14, 2012
Messages
3,413
You have to not declare a function named main it will automatically bug !


You have to finish your function
JASS:
function MyFunction takes nothing returns nothing
    //Do some stuff
enfunction

If your using variable declared in the variable editor you have to put the prefix udg_
 
Level 2
Joined
Aug 22, 2013
Messages
21
Ok, this is the entire thing, I am trying to implement it. You said not to redeclare the function, and its at the very bottom of this code, I am not sure what to do, because if I do as you instructed the code still doesn't work.


JASS:
//===========================================================================
//
// Michael Peppers's Melee AI template (v0.4.1)
// - Automatized Tiering system added
// - Clever Upgrading system! (clever, but not automatized...)
// - Now the AI will handle ALL the worker creation stuff automatically
//
//===========================================================================

//---
// FYI, as long as you can try to make a complete template, you'll still have to make
// most of the BuildPriorities and UpgradePriorities yourself...
//---

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

globals

    // Standard AI globals, DON'T TOUCH!!
    integer attackWave = 1
    integer nextDelay = 0
    //misc common.ai and standard global infos:
    //"attackWave" can be used to know the current attack wave
    //"nextDelay" is used to delay the attack waves
    //"take_exp" is a common.ai boolean global, can be used to store/retrieve the need of an expansion
    //If you need to know the current gold/wood harvesters, check "AddAttackUnit" in a AI Editor ".ai" file

    // Town Hall
    constant integer Hall = 'h000'
    constant integer Mine = '' //Only with mines that have to be built (UD), in any other case = Hall
    constant integer HallTier2 = 'h001'
    constant integer HallTier3 = 'h002'

    // Workers
    constant integer GoldHarvester = 'n000'
    constant integer WoodHarvester = 'n000' //In most AIs = GoldHarvester

// Highly volatile globals section

    // Buildings
    constant integer House = 'h005'
    constant integer Altar = 'h004'
    constant integer Barracks = 'h006'
    constant integer Blacksmith = 'h00A'
    constant integer LumberMill = 'h00B' //In most AIs = Blacksmith
    constant integer Shop = '0' //No shops = set to 0
    constant integer CasterBarracks = 'h00D'
    constant integer Tower = 'net1'
    constant integer SpecializedBarracks = 'h00N' //Workshop/Beastiary/AncientOfWind/SlaughterHouse etc.
    constant integer FlyingBarracks = 'h00I'

    // Units
    constant integer BasicMelee = 'h007'
    constant integer BasicRanged = 'h008' //I hope for my AI's sanity that BasicMelee + BasicRanged >= 5 food. =P
    constant integer T2Melee = 'h009' //Specialized Melee, if it doesn't exist, T2MeleeExists MUST be set to false
    constant integer MainCaster = 'h00F' //Ala Sorceress
    constant integer SupportCaster = 'h00E' //Ala Priest
    constant integer OwnageMelee = 'n004' //Ala Knight/Tauren/Abo etc.
    constant integer AirAir = 'h00J' //ala Gargoyle
    constant integer AirGround = 'h00J' //ala Gryphon
    constant integer SiegeRanged = 'h00M'
    constant integer MiscUnit1 = '' //Not used as of now
    constant integer MiscUnit2 = '' //Not used as of now

    // Upgrades
    constant integer AttackUpgrade1 = 'R002'
    constant integer AttackUpgrade2 = 'R001'
    constant integer DefenseUpgrade1 = 'R003'
    constant integer DefenseUpgrade2 = 'R004'
    constant integer BasicMeleeUpgrade = '0'
    constant integer BasicRangedUpgrade = 'R000'
    constant integer MainCasterUpgrade = 'R009'
    constant integer SupportCasterUpgrade = 'R008'
    constant integer LumberHarvestUpgrade = 'R005'
    constant integer BuildingDefenseUpgrade = 'R006'
    constant integer MiscUpgrade1 = 'R00B'
    constant integer MiscUpgrade2 = 'R00A'
    constant integer MiscUpgrade3 = 'R00C'
    constant integer MiscUpgrade4 = 'R007'
    constant integer MiscUpgrade5 = '0'
    constant integer MiscUpgrade6 = '0'
    constant integer MiscUpgrade7 = '0'
    constant integer MiscUpgrade8 = '0'
    constant integer MiscUpgrade9 = '0'
    constant integer MiscUpgrade10 = '0'
    constant integer MiscUpgrade11 = '0'
    constant integer MiscUpgrade12 = '' //Not used as of now

//End of highly volatile globals =P
    
    // Heroes
    constant integer Heroes = 4 //Number of heroes in the racial altar
    constant integer H1 = 'Hblm'
    constant integer H2 = 'N003' //Set to 0 if it doesn't exists, shouldn't cause problems, though
    constant integer H3 = 'H00C' //Read above
    constant integer H4 = '0' //Idem

    // Hero Skills
    
    // First Hero
    constant integer H1A1 = 'AHfs'
    constant integer H1A2 = 'AHbn'
    constant integer H1A3 = 'AHdr'
    constant integer H1U = 'AHpx'
    
    // Second Hero
    constant integer H2A1 = 'ANic'
    constant integer H2A2 = 'ANso'
    constant integer H2A3 = 'ANlm'
    constant integer H2U = 'ANvc'

    // Third Hero
    constant integer H3A1 = 'AUau'
    constant integer H3A2 = 'ANso'
    constant integer H3A3 = 'ANrf'
    constant integer H3U = 'A000'
    
    // Fourth Hero (yes, the AI supports 4 racial heroes =D)
    constant integer H4A1 = '0'
    constant integer H4A2 = '0'
    constant integer H4A3 = '0'
    constant integer H4U = '0'

    // Food Conditions for assaults
    constant integer Food4Attack = 80 //Food usage needed for assaulting Main Bases
    constant integer Food4Exp = 42 //Food usage needed for creating Expansions
    
    // Harvest priorities
    constant integer GoldGuys1 = 5 //How many people will gather gold at the 1st mine
    constant integer WoodGuys1 = 20 //How many people will gather wood at the base
    constant integer GoldGuys2 = 5 //How many people will gather gold at the 2nd mine, 0 to disable
    constant integer WoodGuys2 = 20 //How many other people will gather wood at the base, 0 to disable

    //Automatized housing values
    constant integer HousesToBuild = 2 //How many houses will the AI build at a time
    constant integer MaxFoodUsedByUnit = 5 //The food value of the most expensive unit, food-wise
    constant integer MaxFood = 100 //The maximum number of food that can be produced

    //Automatized tiering values
    constant integer GoldForT2 = 600 //When this Gold value is reached, the AI will go to T2
    constant integer WoodForT2 = 400 //When this Wood value is reached, the AI will go to T2
    constant integer GoldForT3 = 800 //When this Gold value is reached, the AI will go to T3
    constant integer WoodForT3 = 600 //When this Wood value is reached, the AI will go to T3

    // Misc stuff
    constant boolean WantName = true
    constant boolean WantDifficultyInName = true
    constant string Name = "Test"
    constant boolean IsAmphibious = false //Naga-like race?
    constant boolean WannaKeepBasicMelee = false //Self-explainatory, I hope =)
    constant integer KeepBasicMeleeFoodCap = 34 //As soon as the AI surpasses this food cap it will stop training basic melee units
    constant boolean T2MeleeExists = true //No T2 Melee? = set to false
    constant integer MinimumForceBasicMelee = 4 //Use wisely: 2 food each = 4, 3 food each = 3
    constant integer MinimumForceBasicRanged = 3 //Use wisely: 2 food each = 4, 3 food each = 3
    constant integer MinimumForceT2Melee = 3
    constant integer MinimumForceOwnageMelee = 3
    constant integer AIHasT2Melee = 52 //When this food cap is reached, the AI will use T2Melee too (if enabled) in Minimum Attack
    constant integer AIHasOwnageMelee = 72 //When this food cap is reached, the AI will use OwnageMelee too in Minimum Attack

    // Difficulty-dependant variables (to change them, look in "main")
    integer MinesToOwn = 2 //(2 for Newb AI, 3 for Normal, 4 for Insane)
    string array DifficultyName  //"(Easy)", "(Normal)", "(Insane)"

    // Conditions (Do not touch!!! These are changed by "UpdateConditions" anyway...)
    boolean KeepBasicMelee = true
    boolean CanAttack = false //Has enough units to help allies/launch small attacks?
endglobals

//***************************************************************************
//*
//*  Utility Functions
//*
//***************************************************************************

//HallCount Replicates and enhances common.ai's TownCountEx function, to make it work with custom halls =D
function HallCount takes integer unitid, boolean done returns integer
local integer have_qty
if (not done) then
    set have_qty = GetUnitCount(unitid)
    if unitid == Hall then
        set have_qty = have_qty + GetUnitCount(HallTier2) + GetUnitCount(HallTier3)
    elseif unitid == HallTier2 then
        set have_qty = have_qty  + GetUnitCount(HallTier3)
    endif
else
    set have_qty = GetUnitCountDone(unitid)
    if unitid == Hall then
        set have_qty = have_qty + GetUnitCountDone(HallTier2) + GetUnitCountDone(HallTier3)
    elseif unitid == HallTier2 then
        set have_qty = have_qty  + GetUnitCountDone(HallTier3)
    endif
endif
return have_qty        
endfunction

//===========================================================================
function CheckLastCommand takes boolean pop returns integer
    local integer cmd = GetLastCommand()
    if (pop) then
        call PopLastCommand()
    endif
    return cmd
endfunction

//===========================================================================
function CheckLastCommandData takes boolean pop returns integer
    local integer data = GetLastData()
    if (pop) then
        call PopLastCommand()
    endif
    return data
endfunction

//===========================================================================
function BuildExpansion takes boolean build_it returns nothing
    if build_it and HallsCompleted(Hall) then
        call SetBuildExpa(HallCount(Hall, false) + 1, Hall)
    endif
endfunction

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

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

//***************************************************************************
//*
//*  Conditions
//*
//***************************************************************************

//===========================================================================
// Updates the values of all preset conditions
//===========================================================================
function UpdateConditions takes nothing returns nothing
    if (not WannaKeepBasicMelee) then
        set KeepBasicMelee = (FoodCap() < KeepBasicMeleeFoodCap)
    endif
    if T2MeleeExists then
        set CanAttack = (GetUnitCountDone(BasicMelee) >= MinimumForceBasicMelee or GetUnitCountDone(T2Melee) >= MinimumForceT2Melee) and GetUnitCountDone(BasicRanged) >= MinimumForceBasicRanged
    else
        set CanAttack = (GetUnitCountDone(BasicMelee) >= MinimumForceBasicMelee or GetUnitCountDone(OwnageMelee) >= MinimumForceOwnageMelee) and GetUnitCountDone(BasicRanged) >= MinimumForceBasicRanged
    endif
endfunction

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

function SetSkills takes nothing returns nothing

    set skill[ 1] = H1A1
    set skill[ 2] = H1A2
    set skill[ 3] = H1A3
    set skill[ 4] = H1A1
    set skill[ 5] = H1A2
    set skill[ 6] = H1U
    set skill[ 7] = H1A3
    set skill[ 8] = H1A1
    set skill[ 9] = H1A2
    set skill[10] = H1A3

if hero_id == H1 then
    call SetSkillArray(1, H1)
elseif hero_id2 == H1 then
    call SetSkillArray(2, H1)
elseif hero_id3 == H1 then
    call SetSkillArray(3, H1)
endif

if Heroes > 1 then
    set skill[ 1] = H2A1
    set skill[ 2] = H2A2
    set skill[ 3] = H2A3
    set skill[ 4] = H2A1
    set skill[ 5] = H2A2
    set skill[ 6] = H2U
    set skill[ 7] = H2A3
    set skill[ 8] = H2A1
    set skill[ 9] = H2A2
    set skill[10] = H2A3

    if hero_id == H2 then
        call SetSkillArray(1, H2)
    elseif hero_id2 == H2 then
        call SetSkillArray(2, H2)
    elseif hero_id3 == H2 then
        call SetSkillArray(3, H2)
    endif
endif

if Heroes > 2 then
    set skill[ 1] = H3A1
    set skill[ 2] = H3A2
    set skill[ 3] = H3A3
    set skill[ 4] = H3A1
    set skill[ 5] = H3A2
    set skill[ 6] = H3U
    set skill[ 7] = H3A3
    set skill[ 8] = H3A1
    set skill[ 9] = H3A2
    set skill[10] = H3A3

    if hero_id == H3 then
        call SetSkillArray(1, H3)
    elseif hero_id2 == H3 then
        call SetSkillArray(2, H3)
    elseif hero_id3 == H3 then
        call SetSkillArray(3, H3)
    endif
endif

if Heroes > 3 then
    set skill[ 1] = H4A1
    set skill[ 2] = H4A2
    set skill[ 3] = H4A3
    set skill[ 4] = H4A1
    set skill[ 5] = H4A2
    set skill[ 6] = H4U
    set skill[ 7] = H4A3
    set skill[ 8] = H4A1
    set skill[ 9] = H4A2
    set skill[10] = H4A3

    if hero_id == H4 then
        call SetSkillArray(1, H4)
    elseif hero_id2 == H4 then
        call SetSkillArray(2, H4)
    elseif hero_id3 == H4 then
        call SetSkillArray(3, H4)
    endif
endif

endfunction

function PickRacialHero takes nothing returns nothing
    local integer first
    local integer second
    local integer third
    local integer last
    local integer array heroes

        set heroes[1] = H1
        set heroes[2] = H2
        set heroes[3] = H3
        set heroes[4] = H4
    if Heroes > 3 then
        if VersionCompatible(VERSION_FROZEN_THRONE) then
            set last = 4
        else
            set last = 3
        endif
    else
        set last = Heroes
    endif

    if last >= 1 then
        set first  = GetRandomInt(1,last)
        if last >= 2 then
            set second = GetRandomInt(1,last-1)
            if last >= 3 then
               set third  = GetRandomInt(1,last-2)
            else
               set third = 3
            endif
        else
            set second = 2
        endif
    endif

    set hero_id        = heroes[first]
    set heroes[first]  = heroes[last]
    set hero_id2       = heroes[second]
    set heroes[second] = heroes[last-1]
    set hero_id3       = heroes[third]
endfunction

//***************************************************************************
//*
//*  Building and Harvesting
//*
//***************************************************************************

//===========================================================================
// Specifies building priorities for workers
//===========================================================================
function BuildPriorities takes nothing returns nothing
    local integer mine = TownWithMine()
    local boolean twoharvs = false
    call InitBuildArray()    
    call MeleeTownHall(0, Hall)
    call MeleeTownHall(1, Hall)
    if Hall != Mine and GetGold() < 1500 then //In case of a custom mine
        call SecondaryTown(mine, 1, Mine)
    endif
    call SetBuildUnit(GoldGuys1, GoldHarvester)
    if GoldHarvester != WoodHarvester then
        set twoharvs = true
    endif
    if HallCount(HallTier2, false) == 0 and GetGold() >= GoldForT2 and GetWood() >= WoodForT2 then
        call SetBuildUnit(1, HallTier2)
    elseif HallCount(HallTier3, false) == 0 and GetGold() >= GoldForT3 and GetWood() >= WoodForT3 then
        call SetBuildUnit(1, HallTier3)
    endif
    if FoodCap() < MaxFood and FoodCap() <= (FoodUsed() + MaxFoodUsedByUnit) and GetUnitCount(House) < (GetUnitCountDone(House) + HousesToBuild) and HallCount(Hall, false) <= (HallCount(Hall, true) + (1 + (HallCount(HallTier2, false) - HallCount(HallTier2, true)))) then
        call SetBuildUnit(GetUnitCount(House) + 1, House)
    endif
    if twoharvs = true then
        call SetBuildUnit(WoodGuys1 - 1, WoodHarvester)
    else
        call SetBuildUnit(GoldGuys1 + (WoodGuys1 - 1), WoodHarvester)
    endif
    call SetBuildUnit(1, Altar)
    call SetBuildUnit(1, Barracks)
    if twoharvs = true then
        call SetBuildUnit(WoodGuys1, WoodHarvester)
    else
        call SetBuildUnit(GoldGuys1 + WoodGuys1, WoodHarvester)
    endif
    call SetBuildUnit(1, hero_id)
    if KeepBasicMelee then
        call SetBuildUnit(3, BasicMelee)
    endif
    call SetBuildUnit(1, Blacksmith)
    call SetBuildUnit(2, BasicRanged)
    if Blacksmith != LumberMill then
        call SetBuildUnit(1, LumberMill)
    endif
    call SetBuildUnit(3, BasicRanged)
    if KeepBasicMelee then
        call SetBuildUnit(5, BasicMelee)
    endif
    if Shop != 0 then
        call SetBuildUnit(1, Shop)
    endif
    call SetBuildUnit(5, BasicRanged)
    call BuildExpansion(GetMinesOwned() < MinesToOwn)
    if WoodGuys2 > 0 then
        if twoharvs = true then
            call SetBuildUnit(WoodGuys1 + WoodGuys2, WoodHarvester)
        else
            call SetBuildUnit(GoldGuys1 + WoodGuys1 + WoodGuys2, WoodHarvester)
        endif
    endif
    call SetBuildUnit(1, Tower)
    call SetBuildUnit(1, CasterBarracks)
    if MeleeDifficulty() != MELEE_NEWBIE and Heroes > 1 then //2 heroes? kthxbai
        call SetBuildUnit(1, hero_id2)
    else //Adding some cannon fodder, >= 5 food in total, I hope...
        if KeepBasicMelee then
            call SetBuildUnit(6, BasicMelee)
        else
            call SetBuildUnit(1, BasicMelee)
        endif
        call SetBuildUnit(6, BasicRanged)
    endif
    call SetBuildUnit(2, Tower)
    if T2MeleeExists then
        call SetBuildUnit(3, T2Melee)
    endif
    if T2MeleeExists then
        call SetBuildUnit(4, T2Melee)
        if (not KeepBasicMelee) then
            call SetBuildUnit(6, T2Melee)
        endif
    endif
    call SetBuildUnit(1, SupportCaster)
    call SetBuildUnit(3, Tower)
    call SetBuildUnit(1, MainCaster)
    call SetBuildUnit(1, SpecializedBarracks)
    if GoldGuys2 > 0 then
        if twoharvs = true then
            call SetBuildUnit(GoldGuys1 + GoldGuys2, GoldHarvester)
        else
            if WoodGuys2 > 0 then
                call SetBuildUnit(GoldGuys1 + GoldGuys2 + WoodGuys1 + WoodGuys2, GoldHarvester)
            else
                call SetBuildUnit(GoldGuys1 + GoldGuys2 + WoodGuys1, GoldHarvester)
            endif
        endif
    endif
    call SetBuildUnit(2, SiegeRanged)
    call SetBuildUnit(5, OwnageMelee)
    if (not KeepBasicMelee) then
        call SetBuildUnit(6, OwnageMelee)
    endif
    if MeleeDifficulty() == MELEE_INSANE and Heroes > 2 then //3 heroes? 1337sauce
        call SetBuildUnit(1, hero_id3)
        if (not KeepBasicMelee) then
            call SetBuildUnit(7, OwnageMelee)
        else
            call SetBuildUnit(6, OwnageMelee)
        endif
    endif
    call SetBuildUnit(1, FlyingBarracks)
    call SetBuildUnit(3, AirGround)
    call SetBuildUnit(3, AirAir)
endfunction

function UpgradePriorities takes nothing returns nothing

//Blacksmith upgrades
if GetUnitCountDone(Blacksmith) > 0 then
    if HallCount(HallTier3, true) > 0 then
        call SetBuildUpgr(3, AttackUpgrade1)
        call SetBuildUpgr(3, AttackUpgrade2)
        call SetBuildUpgr(3, DefenseUpgrade1)
        call SetBuildUpgr(3, DefenseUpgrade2)
        call SetBuildUpgr(3, BuildingDefenseUpgrade)
        call SetBuildUpgr(2, LumberHarvestUpgrade)
    elseif HallCount(HallTier2, true) > 0 then
        call SetBuildUpgr(2, AttackUpgrade1)
        call SetBuildUpgr(2, AttackUpgrade2)
        call SetBuildUpgr(2, DefenseUpgrade1)
        call SetBuildUpgr(2, DefenseUpgrade2)
        call SetBuildUpgr(2, BuildingDefenseUpgrade)
        call SetBuildUpgr(1, LumberHarvestUpgrade)
    else
        call SetBuildUpgr(1, AttackUpgrade1)
        call SetBuildUpgr(1, AttackUpgrade2)
        call SetBuildUpgr(1, DefenseUpgrade1)
        call SetBuildUpgr(1, DefenseUpgrade2)
        call SetBuildUpgr(1, BuildingDefenseUpgrade)
    endif
endif

//Barracks upgrades
if GetUnitCountDone(Barracks) > 0 then
    if GetUnitCountDone(BasicMelee) > 2 then
        call SetBuildUpgr(1, BasicMeleeUpgrade)
    endif
    if HallCount(HallTier2, true) > 0 and GetUnitCountDone(BasicRanged) > 2 and GetUnitCountDone(Blacksmith) > 0 then
        call SetBuildUpgr(1, BasicRangedUpgrade)
    endif
    if HallCount(HallTier3, true) > 0 and GetUnitCountDone(OwnageMelee) > 2 and GetUnitCountDone(Blacksmith) > 0 and GetUnitCountDone(CasterBarracks) > 0 then
        call SetBuildUpgr(1, MiscUpgrade3)
    endif
endif

//CasterBarracks upgrades
if GetUnitCountDone(CasterBarracks) > 0 then
    if HallCount(HallTier3, true) > 0 then
        if GetUnitCountDone(MainCaster) > 0 then
            call SetBuildUpgr(2, MainCasterUpgrade)
        endif
        if GetUnitCountDone(SupportCaster) > 0 then
            call SetBuildUpgr(2, SupportCasterUpgrade)
        endif
        if GetUnitCountDone(Shop) > 0 and GetUnitCountDone(T2Melee) > 2 then
            call SetBuildUpgr(1, MiscUpgrade2)
        endif
    else
        if GetUnitCountDone(MainCaster) > 0 then
            call SetBuildUpgr(1, MainCasterUpgrade)
        endif
        if GetUnitCountDone(SupportCaster) > 0 then
            call SetBuildUpgr(1, SupportCasterUpgrade)
        endif
    endif
    if GetUnitCountDone(T2Melee) > 2 then
        call SetBuildUpgr(1, MiscUpgrade1)
    endif
endif

//FlyingBarracks upgrades
if GetUnitCountDone(FlyingBarracks) > 0 then
    if HallCount(HallTier3, true) > 0 then
        if GetUnitCountDone(CasterBarracks) > 0 then
            if GetUnitCountDone(Blacksmith) > 0 and GetUnitCountDone(AirGround) > 0 then
                call SetBuildUpgr(1, MiscUpgrade5)
            endif
            if GetUnitCountDone(Shop) > 0 then
                if GetUnitCountDone(AirAir) > 0 then
                    call SetBuildUpgr(1, MiscUpgrade4)
                endif
                if GetUnitCountDone(AirGround) > 0 then
                    call SetBuildUpgr(1, MiscUpgrade6)
                endif
            endif
        endif
    endif
endif

//SpecializedBarracks upgrades
if GetUnitCountDone(SpecializedBarracks) > 0 then
    if HallCount(HallTier3, true) > 0 then
        if GetUnitCountDone(Blacksmith) > 0 and GetUnitCountDone(SiegeRanged) > 0 then
            call SetBuildUpgr(1, MiscUpgrade7)
        endif
        if GetUnitCountDone(CasterBarracks) > 0 and GetUnitCountDone(MiscUnit1) > 0 then
            call SetBuildUpgr(1, MiscUpgrade9)
        endif
        if GetUnitCountDone(Shop) > 0 and GetUnitCountDone(MiscUnit2) > 0 then
            call SetBuildUpgr(1, MiscUpgrade10)
        endif
    endif
endif

//Misc upgrades
if HallCount(Hall, true) > 0 then
    if HallCount(HallTier2, true) > 0 and GetUnitCountDone(Shop) > 0 then
        call SetBuildUpgr(1, MiscUpgrade8)
    endif
    if GetUnitCountDone(Shop) > 0 then
        call SetBuildUpgr(1, MiscUpgrade11)
    endif
endif
endfunction

function GuysAtWork takes nothing returns nothing
    local integer mine
    loop
        call UpdateConditions()
        call ClearHarvestAI()
        set mine = TownWithMine()
        call HarvestGold(mine + 0, GoldGuys1)
        call HarvestWood(0, WoodGuys1)
        if GoldGuys2 != 0 and GetMinesOwned() >= 2 then
            call HarvestGold(mine + 1, GoldGuys2)
        endif
        if WoodGuys2 != 0 then
            call HarvestWood(0, WoodGuys2)
        endif
        call BuildPriorities()
        call UpgradePriorities()
        call Sleep(2)
    endloop
endfunction

//***************************************************************************
//*
//*  Attacking
//*
//***************************************************************************

//===========================================================================
// Returns true if the minimum forces for an attack exist
//===========================================================================
function HaveMinimumAttackers takes nothing returns boolean

    // Check for attack wave limit
    if (attackWave > 2) then
        return false
    endif

    return CanAttack
endfunction

//===========================================================================
// Assigns units to attack based on the given attack group
//===========================================================================
function PrepareAttackGroup takes integer groupID returns nothing

    // Attack Group #1: Minimum Attack
    if (groupID == 1) then
        call SetAssaultGroup(GetUnitCountDone(hero_id), -1, hero_id)
        call SetAssaultGroup(GetUnitCountDone(BasicRanged), -1, BasicRanged)
        call SetAssaultGroup(GetUnitCountDone(BasicMelee), -1, BasicMelee)
        if (FoodCap() >= AIHasOwnageMelee) then
            call SetAssaultGroup(MinimumForceOwnageMelee, MinimumForceOwnageMelee, OwnageMelee)
        endif
        if (FoodCap() >= AIHasT2Melee) and T2MeleeExists then
            call SetAssaultGroup(MinimumForceT2Melee, MinimumForceT2Melee, T2Melee)
        endif

    // Attack Group #2: All Units
    elseif (groupID == 2) then
        call SetAssaultGroup(GetUnitCountDone(hero_id), -1, hero_id)
        if Heroes > 1 then //Just in case =)
            call SetAssaultGroup(GetUnitCountDone(hero_id2), -1, hero_id2)
            if Heroes > 2 then
                call SetAssaultGroup(GetUnitCountDone(hero_id3), -1, hero_id3)
            endif
        endif
        call SetAssaultGroup(GetUnitCountDone(BasicRanged), -1, BasicRanged)
        call SetAssaultGroup(GetUnitCountDone(BasicMelee), -1, BasicMelee)
        call SetAssaultGroup(GetUnitCountDone(OwnageMelee), -1, OwnageMelee)
        call SetAssaultGroup(GetUnitCountDone(SupportCaster), -1, SupportCaster)
        call SetAssaultGroup(GetUnitCountDone(MainCaster), -1, MainCaster)
        if T2MeleeExists then
            call SetAssaultGroup(GetUnitCountDone(T2Melee), -1, T2Melee)
        endif
        call SetAssaultGroup(GetUnitCountDone(AirGround), -1, AirGround)
        call SetAssaultGroup(GetUnitCountDone(AirAir), -1, AirAir)
        call SetAssaultGroup(GetUnitCountDone(SiegeRanged), -1, SiegeRanged)
        call SetAssaultGroup(GetUnitCountDone(MiscUnit1), -1, MiscUnit1)
        call SetAssaultGroup(GetUnitCountDone(MiscUnit2), -1, MiscUnit2)
    endif
endfunction

//===========================================================================
// Prepares an attack group based on the current attack wave
//===========================================================================
function PrepareForces takes nothing returns nothing
    if (attackWave == 1) then
        call PrepareAttackGroup(1)
    elseif (attackWave == 2) then
        call PrepareAttackGroup(2)
    endif
endfunction

//===========================================================================
// Sleep delays for each attack wave
//===========================================================================
function AttackWaveDelay takes integer inWave returns nothing
    if (inWave < nextDelay) then
        return
    endif

    if (inWave == 1) then
        call Sleep(2)
    endif

    set nextDelay = inWave + 1
endfunction

//===========================================================================
// Advances attack wave counter
//===========================================================================
function AttackWaveUpdate takes nothing returns nothing
    call AttackWaveDelay(attackWave)
    set attackWave = attackWave + 1
    if (attackWave > 2) then
        set attackWave = 2
        set nextDelay = attackWave + 1
    endif
endfunction

//===========================================================================
// Basic attack functionality
//===========================================================================
function AttackTarget takes unit target, boolean addAlliance returns nothing
    if (target == null) then
        return
    endif
    if (addAlliance) then
        call SetAllianceTarget(target)
    endif
    call FormGroup(3, true)
    call AttackMoveKillA(target)
    if (not addAlliance) then
        call SetAllianceTarget(null)
    endif
endfunction

//===========================================================================
// Initiates an attack based on target priorities
//===========================================================================
function LaunchAttack takes nothing returns nothing
    local unit target = null
    local boolean setAlly = true

    // Don't launch any attack while town is threatened
    if (TownThreatened()) then
        call Sleep(2)
        return
    endif

    // Target Priority #1 = Helping an ally Assault/Defence
    if (target == null) then
        set target = GetAllianceTarget()
        if (target != null) then
            set setAlly = false
        endif
    endif

    // Target Priority #2 = Preparing an expansion
    if FoodUsed() >= Food4Exp then
        if (target == null) then
            set target = GetExpansionFoe()
        endif
    endif

    // Target Priority #3 = Woot, MegaTarget? (MegaTarget is the enemy's main)
    if FoodUsed() >= Food4Attack then
        if (target == null) then
            set target = GetMegaTarget()
        endif

    // Target Priority #4 = Either enemy expansions or an enemy base
        if (target == null) then
            set target = GetEnemyExpansion()
            if (target == null) then
                call StartGetEnemyBase()
                loop
                    exitwhen (not WaitGetEnemyBase())
                    call SuicideSleep(1)
                endloop
                set target = GetEnemyBase()
            endif
        endif
    endif

    // Target Priority #5 = Small creep camps
    if FoodUsed() < Food4Attack then
        if target == null then
            set target = GetCreepCamp(0, 9, false)
        endif
    endif

    // Target Priority #6 = Huge creep camps
    if FoodUsed() >= Food4Attack then
        if (target == null) then
            set target = GetCreepCamp(10, 100, true)
        endif
    endif

    // Target Priority #7 = Goblin Zeppelin
//    if ((GetUnitCount('nzep') < 1)) then
//        if (target == null) then
//            call PurchaseZeppelin()
//            return
//        endif
//    endif

    // Attack the target and increment attack wave
    if (target != null) then
        call AttackTarget(target, setAlly)
        call AttackWaveUpdate()
    else
        // If no target was found, sleep a bit before trying again
        call Sleep(20)
    endif
endfunction

//===========================================================================
// Determines all attacking assignments
//===========================================================================
function AttackAssignment takes nothing returns nothing
local integer n = 0
    call StaggerSleep(0, 2)
    if (attackWave == 1) then
        call AttackWaveDelay(0)
    endif
    loop
        call UpdateConditions()
        if (HaveMinimumAttackers() and not CaptainRetreating()) then
            if n == 2 then
                call Sleep(2)
                set n = 0
            else
                set n = n + 1
                call RemoveInjuries()
                call InitAssaultGroup()
                call PrepareForces()
                call LaunchAttack()
            endif
        else
            call Sleep(2)
        endif
    endloop
endfunction

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

//===========================================================================
function main takes nothing returns nothing
    set ai_player = Player(GetAiPlayer())
    set MinesToOwn = 1 + MeleeDifficulty()
    set DifficultyName[1] = "(Easy)"
    set DifficultyName[2] = "(Normal)"
    set DifficultyName[3] = "(Insane)"
    if WantName then
        if WantDifficultyInName then
            call SetPlayerName(ai_player, Name + " " + DifficultyName[MeleeDifficulty(Normal)])
        else
            call SetPlayerName(ai_player, Name)
        endif
    endif
    call InitOptions()
    call PickRacialHero()
    call SetSkills()
    call CreateCaptains()
    call StandardAI(function SkillArrays, function GuysAtWork, function AttackAssignment)
    if IsAmphibious then
        call SetAmphibious()
    endif
    call PlayGame()
endfunction
 
Level 2
Joined
Aug 22, 2013
Messages
21
Do, you have skype or something so you could help me with this? It would be very much appreciated or some form of fast chatting. I changed the name of the function, but now more errors are occurring.
 
Level 2
Joined
Aug 22, 2013
Messages
21
There is this log I found and shown below:

Code:
SFileLoadFile: 1501cf30
SFileUnloadFile: 15017d00
SFileOpenArchive: 1501d3b0
SFileCloseArchive: 1501a230
Found ModifiedOn signature at 52079c
Patch length: 10
Found ModifiedOff1 signature at 520ff1
Patch length: 10
Found ModifiedOff2 signature at 520eb0
Patch length: 10
Found NewObjectId signature at 5b645a
Patch length: 12
Found GetSLKString signature at 515673
Patch length: 38
Syntax disable address: 5bc089
Doodad limit address: 54cad8
Unit/item limit address: 554b7b
Map size limit address: 4e1ea0
Map cells limit address: 4e1ef0
Description popup address: 55d6a3
Auto disable address: 5ceff3
Always Enable address: 5c88f5
Always Enable address #2: 5c88d7
ImpPrefix address: 0
Redirected ok
Editor window caught: 1b082a
Toggling objecteditorhack
Toggling syntax checking
Toggling description nag
Toggling trigger disable on error
Toggling forced trigger enable




And this is the compile errors log below:

Code:
logs\currentmapscript.j
JASSHelper - Step 2 (structs)
Line 3462: Syntax Error, unexpected: "="?
1
 
Level 2
Joined
Aug 22, 2013
Messages
21
Ok here is a section of the code, with the error line in it below:

Code:
function BuildPriorities takes nothing returns nothing
    local integer mine = TownWithMine()
    local boolean twoharvs = false
    call InitBuildArray()    
    call MeleeTownHall(0, Hall)
    call MeleeTownHall(1, Hall)
    if Hall != Mine and GetGold() < 1500 then //In case of a custom mine
        call SecondaryTown(mine, 1, Mine)
    endif
    call SetBuildUnit(GoldGuys1, GoldHarvester)
    if GoldHarvester != WoodHarvester then
        set twoharvs = true  <------This is the line with the error
    endif
    if HallCount(HallTier2, false) == 0 and GetGold() >= GoldForT2 and GetWood() >= WoodForT2 then
        call SetBuildUnit(1, HallTier2)
    elseif HallCount(HallTier3, false) == 0 and GetGold() >= GoldForT3 and GetWood() >= WoodForT3 then
        call SetBuildUnit(1, HallTier3)
    endif
    if FoodCap() < MaxFood and FoodCap() <= (FoodUsed() + MaxFoodUsedByUnit) and GetUnitCount(House) < (GetUnitCountDone(House) + HousesToBuild) and HallCount(Hall, false) <= (HallCount(Hall, true) + (1 + (HallCount(HallTier2, false) - HallCount(HallTier2, true)))) then
        call SetBuildUnit(GetUnitCount(House) + 1, House)
    endif
    if twoharvs = true then
        call SetBuildUnit(WoodGuys1 - 1, WoodHarvester)
    else
 
Level 2
Joined
Aug 22, 2013
Messages
21
Bumping this and hoping that if anyway possible someone experienced could help me implement this into my map, it would greatly help me and I would be able to see what to do in the future with the AI and several other Jass things.
 
Level 2
Joined
Aug 22, 2013
Messages
21
So, I would just make this a .ai file using something like jasscraft and then import it and make sure to change the default .ai to this one?




Edit: And this would be how I implement it in my code correctly?
JASS:
call c.setAIScript("war3mapImported\\Bloodelf.ai")

I really wish I would have known that this was already complete, that it just needed to be filled in and saved as an .ai and imported that was not clear where I found it, lol. Also, when I run a test the heroes I added and the units show up correctly, but the AI just mines Gold and sits there.
 
Last edited:
Level 2
Joined
Aug 22, 2013
Messages
21
I will look into your tutorial, but I thought it was more based towards campaign-ai, so I decided to not use it or really try to learn from it. Is there anyway you could possibly assist me with this and help me in learning this. I feel Jass is easier than using the AI Editor, and I really want to create a unique type AI for melee.

On another note, when I debug it in Jasscraft it shows a bunch of undeclared functions, skill not an array, and other things like that.

one undeclared function is --> GetUnitCountDone


EDIT: 08/27/2013 Ok, I followed your tutorial to the letter by writing each piece myself until the end and then tried to implement it and run it, but the AI just mines gold and this jass script is having the exact same issues as the previous it is claiming undeclared functions. I even took your completed Campaign AI Script at the end of your tutorial and pasted it and tried to use it and it has the same syntax errors coming up when I check it. Its like for some reason every function and variable used is coming up undeclared. It is also saying "Comparing two variables of different primitive types (except real and integer) is not allowed. I have checked every line for spacing errors, typos, or not ending a function correctly and I can't find anything wrong. I know that there shouldn't be anything wrong with your tutorial and this error is still happening. I am starting to think some where or another, that I am missing something to make these functions and stuff work. Either that or do I need to define them somewhere? If someone could explain this or help me that would be greatly appreciated.
 
Last edited:
Level 15
Joined
Feb 15, 2006
Messages
851
Do you have Jasscraft properly setup for debugging jass ai?? check the attachment.
 

Attachments

  • jc.png
    jc.png
    17.8 KB · Views: 102
Level 2
Joined
Aug 22, 2013
Messages
21
Ok, so I got most of the code working and now I am stuck trying to figure out how to have it not target a specific player, but any player at random. And thank you linking your Tutorial Moyackx, it has helped me a lot. +rep
 
Last edited:
Level 15
Joined
Feb 15, 2006
Messages
851
Ok, so I got most of the code working and now I am stuck trying to figure out how to have it not target a specific player, but any player at random. And thank you linking your Tutorial Moyackx, it has helped me a lot. +rep
Sorry for my late answer...

Well, that can be fixed by setting a random integer when the AI is at home and not attacking.

you can put something like this at the beginning of the loop:
JASS:
//loop
    if CaptainIsHome() and not CaptainInCombat(true) then
        set player = Player(GetRandomInt(0, 11)) // 0= player 1, 11=Player 12
    endif

I hope it works :p and it helps you :)
 
Status
Not open for further replies.
Top