Warcraft III: MapsModelsSkinsIconsSpellsToolsTutorials
WC3 JASS: Code SnippetsJASS and vJASS Spells and SystemsJass Tutorials
Chat @Discord

Author Topic: How to make a Campaign AI  (Read 14462 times)

  • Site Owner
  • Administrator
  • Starter - level 4
  • *
  • Posts: 987
  • WC3 Models: 43
  • WC3 Tutorials: 13
  • WC3 Tools: 10
  • WC3 Maps: 11
  • WC3 Skins: 6
  • WC3 Icons: 2
  • WC3 Spells: 5
  • Reputation: 1153
  • Site Admin - I love fix things
    • View Profile
    • Blizzard Modding Information Center
How to make a Campaign AI
« on: January 14, 2011, 09:19:32 AM »
HOW TO MAKE A CAMPAIGN AI.
By Moyack

Index.


Introduction.

The main objective with this tutorial is to give an introduction in the development of a simple AI, focused in attack one player following an attack sequence, a building sequence and an upgrade sequence.


AI Types

Before starting, I want to clarify that there are two kind of AI: Campaign AI and Standard AI. The Campaign AI is the simplest AI that can be made, because it follows a rigid and predictable behaviour. An standard AI, in the other hand, is focused in simulate the human behaviour, so it will be more random, sometimes more agressive and many times extremely difficult to debug. :P

So if we want to begin with JASS AI, it's recommended to start working with a campaign AI, that is easy to debug.


Tools needed.

If you want to make an Standard AI, you have the WE with the AI editor, with its easy but slow interface, but if you want to do a Campaign AI, you can do it with notepad.

I strongly suggest to use JASSCRAFT because this program let us access the common.ai commands easily, the syntax highlithing, etc.


What is JASS AI??

JASS AI is the language used by BLIZZARD to make AI programming. JASS AI uses the same JASS syntaxis and variable types, so if you are familiar with JASS, you will understand JASS AI perfectly.

The commands focused in AI are contained in the file common.ai file that can be found in the war3.mpq and war3x.mpq pack files. It's important to clarify that this functions are not the only that can be used to work with this scripting, you can use perfectly functions from common.j (well, it's the base file for programming with JASS language after all). Anyways, I've found that some functions from common.j just don't work in a JASS AI script, and the only way to get those functions is by practice.


Let's start

Well, I think I've talked a lot, so let's start the AI.

Open JASSCRAFT or JASS SHOP PRO and open a new document. Before begin writing, we must know how the code is arranged in JASS.

JASS Structure
Code: jass  [Select]
  1. globals
  2.     // We put the globals variables here
  3. endglobals
  4.  
  5. function blabla takes blabla returns blabla
  6.     // Custom function stuff
  7. endfunction
  8.  
  9. ...
  10.  
  11. function main takes nothing returns nothing
  12.     //The main code goes here
  13. endfunction

For people who are new with JASS, the code is arranged in a global section, where we declare the global variables, then we put the custom functions that will be used in the script and the last function called main, which will use the globals and the functions that we have writen before and will be the function that will be executed by the game.


With those definitions, we can put to work with this script. First we're going to begin the AI code creating at the global section a global variable that will point the player which will be attacked by the AI, we will call it MyVictim

Global variables
Code: jass  [Select]
  1. globals
  2.     player MyVictim = Player(0) // This is the player 1 (red)
  3. endglobals

Now we will create the main function
Code: jass  [Select]
  1. function main takes nothing returns nothing
  2.     call CampaignAI( <Farm ID>, null )
  3. endfunction

The CampaignAI function initializes and configures the AI in order to have a behaviour that fits with campaign maps. This function has two arguments, the farm unitID, which help the function to define the food provider unit, and the hero code which makes reference to a function that will manage the hero abilities that a hero will have when it increases its level. This option will be treated later, so at the moment we are going to set this parameter as null.

now we're going to set some parameters into the AI. Campaign AIs have this caracteristics by default:

  • They don't give attack priority to heroes.
  • Units don't flee
  • Peons only repair buildings in insane mode
  • Gather resources very slowly (each peon gather 1 gold and 1 lumber to the town hall)

This characteristics are given in this way to the AI because in campaign maps, you need the AI player keeps alive in the game until it's destroyed, so the AI will "simulate" a gathering, and you will control the AI resources via triggers. Other thing is units can't flee because the function of this kind of AI is to put difficulty or taunting the user player.

So if you need to change these behaviours you need to configure them with some ai functions. I'm going to list some of the most used:

table: Basic configuration functions
  • SetTargetHeroes(Boolean): makes the AI to give attack priority toward heroes
  • SetUnitsFlee(Boolean): If units are seriously damaged, they will retreat
  • SetHeroesFlee(Boolean): The same but with heroes
  • SetGroupsFlee(Boolean): The same but with the attacking group in general (I really don't recommend to set true this option, the AI behaves like a chicken)
  • SetSlowChopping(Boolean): Workers gather very few resources
  • SetPeonsRepair(Boolean): Workers will repair damaged mechanical units
  • SetHeroesBuyItems(Boolean): Make heroes buy items from their racial shop and sell items.
  • SetHeroesTakeItems(Boolean): Make heroes to take items on the ground.
For testing, I'm going to set some options in the main code.

Now we will create the main function

main function
Code: jass  [Select]
  1. function main takes nothing returns nothing
  2.     call CampaignAI( MOON_WELL, null ) // I like the Night elf race,
  3.                                        // so this AI will train NE
  4.     call SetSlowChopping( false ) //AI will do a normal harvesting
  5.     call SetPeonsRepair( true ) //AI will repair damaged structures
  6. endfunction

table: Note
probably you've noticed that in the function call CampaignAI( MOON_WELL, null ) we set the name of the unit instead of its rawcode. All the units used in the Warcraft Campaigns have this constant names. If you create a modified race with custom units, you have to use the rawcode. This function can be written in this way:
call CampaignAI( 'emow', null )
And is perfectly equivalent. I will use this constant names in all this tutorial so it can be more readable.

How to get the unit, ability, buff and upgrade rawcode?? easy, open the object editor and press CTRL+D, you will see that all the units , items, abilities, upgrades names are shown by their rawcode. To change again pres again CTRL+D

If you want to be more organized, we can create a custom configuration function and then we will call it in the main function:

main function
Code: jass  [Select]
  1. function ConfigureAI takes nothing returns nothing
  2.     call SetSlowChopping( false )
  3.     call SetPeonsRepair( true )
  4. endfunction
  5.  
  6. function main takes nothing returns nothing
  7.     call CampaignAI( MOON_WELL, null )
  8.     call ConfigureAI( )
  9. endfunction


Building Strategy.

It's time to put this AI to build structures. First we must take in account the order and the dependencies, for example, in the case of this Night Elf AI, we can't build an ancient protector without have built a Huntress Hall.

With this idea in mind, we're going to set the building order in the script.

NE Campaign AI - only Buildings
Code: jass  [Select]
  1. globals
  2.     player MyVictim = Player( 0 )
  3. endglobals
  4.  
  5. function ConfigureAI takes nothing returns nothing
  6.     call SetSlowChopping( false )
  7.     call SetPeonsRepair( true )
  8. endfunction
  9.  
  10. function main takes nothing returns nothing
  11.     call CampaignAI( MOON_WELL, null )
  12.     call ConfigureAI( )
  13.     // **********************************
  14.     // *      Building Strategy         *
  15.     // **********************************
  16.     call SetBuildUnitEx( 1, 1, 1, TREE_LIFE )
  17.     call SetBuildUnit( 15, WISP )
  18.     call SetBuildUnitEx( 1, 2, 3, MOON_WELL )
  19.     call SetBuildUnitEx( 1, 1, 2, ANCIENT_WAR )
  20.     call SetBuildUnit( 1, ELF_ALTAR )
  21.     call SetBuildUnit( 1, HUNTERS_HALL )
  22.     // **********************************
  23.     // *    End Building Strategy       *
  24.     // **********************************
  25. endfunction

Now we've done the basic tier 1 buildings. :emote_grin:  Let's see the new functions. SetBuildUnit( n, UnitID ) is easy to read, this function orders to AI to build or train n units of type UnitID. SetBuildUnitEx( e, n, i, UnitID ) is the same but better, becasue it lets you set how many units will be trained in easy, normal and insane mode.

Now we need to build the units that will defend our town, so we're going to train this units adding this functions to the AI.

NE Campaign AI - Buildings and defensive units
Code: jass  [Select]
  1. globals
  2.     player MyVictim = Player( 0 )
  3. endglobals
  4.  
  5. function ConfigureAI takes nothing returns nothing
  6.     call SetSlowChopping( false )
  7.     call SetPeonsRepair( true )
  8. endfunction
  9.  
  10. function main takes nothing returns nothing
  11.     call CampaignAI( MOON_WELL, null )
  12.     call ConfigureAI( )
  13.     // **********************************
  14.     // *      Building Strategy         *
  15.     // **********************************
  16.     call SetReplacements( 1, 2, 3 ) // <==(1)
  17.     call SetBuildUnitEx( 1, 1, 1, TREE_LIFE )
  18.     call SetBuildUnit( 15, WISP )
  19.     call SetBuildUnitEx( 1, 2, 3, MOON_WELL )
  20.     call SetBuildUnitEx( 1, 1, 2, ANCIENT_WAR )
  21.     call SetBuildUnit( 1, ELF_ALTAR )
  22.     call SetBuildUnit( 1, HUNTERS_HALL )
  23.     call SetBuildUnitEx( 0, 1, 2, ANCIENT_PROTECT )
  24.     call CampaignDefenderEx( 2, 2, 3, ARCHER ) // <==(2)
  25.     call CampaignDefenderEx( 1, 1, 1, HUNTRESS )
  26.     // **********************************
  27.     // *    End Building Strategy       *
  28.     // **********************************
  29. endfunction

Let's explain the new functions:
  • SetReplacements(e, n, i): Set how many times the AI replaces preplaced units of the same type, in the code above, it makes this replacement up to one unit, up to 2 units for normal mode and up to 3 units of a type in insane mode. (thanks Starquizer for the discovery :) )
  • CampaignDefenderEx(e, n, i, UnitID): similar to SetUnitBuild, but the units trained with this function will be replaced if they're killed n times according with the function SetReplacements.
Now the defensive strategy for this AI is arranged (at the moment) as:
table: Defensive Strategy
EasyNormalInsane
Archers223
Huntress111
Ancient Protector012


Attacking Strategy

Now this baby is ready to fight, so we need to make the AI takes some units and order them to attack a target. The function structure is as follows:

Attack Function Arrangement
Code: jass  [Select]
  1. function main takes nothing returns nothing
  2.  
  3. // Building code goes here
  4.  
  5. //*** WAVE 1 ***
  6.     call InitAssaultGroup() // <==(1)
  7.     call CampaignAttackerEx( 2, 3, 3, ARCHER ) // <==(2)
  8.     call CampaignAttackerEx( 0, 1, 2, HUNTRESS )
  9.     call CampaignAttackerEx( 0, 1, 1, BALLISTA )
  10.     call SuicideOnPlayerEx( M2, M3, M3, MyVictim ) // <==(3)
  11. endfunction

These functions do the following:
  • InitAssaultGroup(): Clear any previous assault group and creates a new empty one.
  • CampaignAttackerEx( e, n, i, UnitID ): Like SetBuildUnitEx but adds these units to the assault group.
  • SuicideOnPlayerEx( te, tn, ti, TargetPlayer ): Waits te seconds in easy mode, tn seconds in normal mode and ti seconds in insane mode to attack the specified player.
One question is: what does it mean M2, M3??? well, M2 is two minutes (2*60 sec.), M3 is three minutes (3*60 sec.) an so on. We can use values from M1 to M15. You can check it out these constants in the common.ai file.

table: Note
There are other ways to get enemies to attack. SuicideOnPlayerEx gets the main player town hall (player start location), but probably you want to take a specific unit, so you will need to use a function like AttackMoveKillA( TargetUnit ). as an example, this script will attack a creep camp, targeting a specific creep:

Attack script for creeping
Code: jass  [Select]
  1. function main takes nothing returns nothing
  2.     local unit crp
  3. // Building code goes here
  4.  
  5. //*** WAVE 1 ***
  6.     call InitAssaultGroup()
  7.     set crp = GetCreepCamp(0,9,false) // Stores the target unit
  8.     call CampaignAttackerEx( 2, 3, 3, ARCHER )
  9.     call CampaignAttackerEx( 0, 1, 2, HUNTRESS )
  10.     call Sleep( M3 ) // Waits 3 minutes before attacking
  11.     call AttackMoveKillA(crp) // Order assault group to attack that unit
  12. endfunction

Where:
  • GetCreepCamp( min, max, flyers ): Get a creep unit in a camp with a strength between min and max including (flyers=true) or not including (flyers=false) flying creeps.
  • Sleep( n ): put the script to wait n seconds.
  • AttackMoveKillA( Unit ): Order assault group to attack that unit.

Now we have this wave working. the idea is to add more waves, incrementing the amount of units or their type (for example one wave with tier 1 units, other with more tier 1 units, the next with tier 1 and 2 units and casters, etc). check this example:

Building + Attacking script. All tiers
Code: jass  [Select]
  1. globals
  2.     player MyVictim = Player( 0 )
  3. endglobals
  4.  
  5. function ConfigureAI takes nothing returns nothing
  6.     call SetSlowChopping( false )
  7.     call SetPeonsRepair( true )
  8. endfunction
  9.  
  10. function main takes nothing returns nothing
  11.     call CampaignAI( MOON_WELL, null )
  12.     call ConfigureAI( )
  13.     // **********************************
  14.     // *      Building Strategy         *
  15.     // **********************************
  16.     //
  17.     // Tier 1 Buildings
  18.     call SetReplacements( 1, 2, 3 )
  19.     call SetBuildUnitEx( 1, 1, 1, TREE_LIFE )
  20.     call SetBuildUnit( 15, WISP )
  21.     call SetBuildUnitEx( 1, 2, 3, MOON_WELL )
  22.     call SetBuildUnitEx( 1, 1, 2, ANCIENT_WAR )
  23.     call SetBuildUnit( 1, ELF_ALTAR )
  24.     call SetBuildUnit( 1, HUNTERS_HALL )
  25.     call CampaignDefenderEx( 2, 2, 3, ARCHER )
  26.     call CampaignDefenderEx( 1, 1, 1, HUNTRESS )
  27.     call CampaignDefenderEx( 0, 1, 2, ANCIENT_PROTECT )
  28.     // Tier 2 buildings
  29.     call SetBuildUnit( 1, TREE_AGES )
  30.     call SetBuildUnitEx( 1, 1, 2, ANCIENT_LORE )
  31.     call SetBuildUnit( 1, ANCIENT_WIND )
  32.     // Tier 3 buildings
  33.     call SetBuildUnit( 1, TREE_ETERNITY )
  34.     call SetBuildUnitEx( 0, 1, 1, CHIMAERA_ROOST )
  35.     // **********************************
  36.     // *    End Building Strategy       *
  37.     // **********************************
  38.     // **********************************
  39.     // *       Attack Strategy          *
  40.     // **********************************
  41.     //*** WAVE 1 ***
  42.     call InitAssaultGroup()
  43.     call CampaignAttackerEx( 2, 3, 3, ARCHER )
  44.     call CampaignAttackerEx( 0, 1, 2, HUNTRESS )  
  45.     call SuicideOnPlayerEx( M3, M2, M2, MyVictim )
  46.     //*** WAVE 2 *** Between 2 or 3 minutes after Wave 1
  47.     call InitAssaultGroup()
  48.     call CampaignAttackerEx( 3, 4, 4, ARCHER )
  49.     call CampaignAttackerEx( 1, 2, 3, HUNTRESS )  
  50.     call SuicideOnPlayerEx( M3, M2, M2, MyVictim )
  51.     //*** WAVE 3 *** Between 2 or 3 minutes after Wave 2
  52.     call InitAssaultGroup()
  53.     call CampaignAttackerEx( 3, 4, 4, ARCHER )
  54.     call CampaignAttackerEx( 1, 2, 3, HUNTRESS )
  55.     call CampaignAttackerEx( 1, 1, 1, DEMON_HUNTER )
  56.     call SuicideOnPlayerEx( M3, M2, M2, MyVictim )
  57.     //*** WAVE 4 *** Between 2 or 3 minutes after Wave 3
  58.     call InitAssaultGroup()
  59.     call CampaignAttackerEx( 3, 4, 4, ARCHER )
  60.     call CampaignAttackerEx( 1, 2, 3, HUNTRESS )
  61.     call CampaignAttackerEx( 1, 1, 1, DEMON_HUNTER )
  62.     call SuicideOnPlayerEx( M3, M2, M2, MyVictim )
  63.     //*** WAVE 5 *** Between 3 or 4 minutes after Wave 4
  64.     call InitAssaultGroup()
  65.     call CampaignAttackerEx( 3, 3, 3, ARCHER )
  66.     call CampaignAttackerEx( 2, 2, 2, HUNTRESS )
  67.     call CampaignAttackerEx( 1, 1, 1, DEMON_HUNTER )
  68.     call CampaignAttackerEx( 0, 1, 2, DRYAD )
  69.     call SuicideOnPlayerEx( M4, M3, M3, MyVictim )
  70.     //*** WAVE 6 *** Between 3 or 4 minutes after Wave 5
  71.     call InitAssaultGroup()
  72.     call CampaignAttackerEx( 2, 2, 2, HUNTRESS )
  73.     call CampaignAttackerEx( 1, 1, 1, DEMON_HUNTER )
  74.     call CampaignAttackerEx( 1, 1, 1, MOON_CHICK )
  75.     call CampaignAttackerEx( 1, 2, 3, DRYAD )
  76.     call CampaignAttackerEx( 0, 1, 2, DRUID_CLAW )
  77.     call SuicideOnPlayerEx( M4, M3, M3, MyVictim )
  78.     //*** WAVE 7 *** Between 3 or 5 minutes after Wave 6
  79.     call InitAssaultGroup()
  80.     call CampaignAttackerEx( 2, 2, 2, HUNTRESS )
  81.     call CampaignAttackerEx( 1, 1, 1, DEMON_HUNTER )
  82.     call CampaignAttackerEx( 1, 1, 1, MOON_CHICK )
  83.     call CampaignAttackerEx( 1, 2, 3, DRYAD )
  84.     call CampaignAttackerEx( 0, 1, 2, DRUID_CLAW )
  85.     call CampaignAttackerEx( 0, 1, 2, MOUNTAIN_GIANT )
  86.     call SuicideOnPlayerEx( M5, M4, M3, MyVictim )
  87.     //*** WAVE 8 *** Between 3 or 5 minutes after Wave 7
  88.     call InitAssaultGroup()
  89.     call CampaignAttackerEx( 2, 2, 2, HUNTRESS )
  90.     call CampaignAttackerEx( 1, 1, 1, DEMON_HUNTER )
  91.     call CampaignAttackerEx( 1, 1, 1, MOON_CHICK )
  92.     call CampaignAttackerEx( 1, 2, 3, DRYAD )
  93.     call CampaignAttackerEx( 0, 1, 2, DRUID_CLAW )
  94.     //*** WAVE 9 *** Between 4 or 6 minutes after Wave 8
  95.     call InitAssaultGroup()
  96.     call CampaignAttackerEx( 2, 2, 2, HUNTRESS )
  97.     call CampaignAttackerEx( 1, 1, 1, DEMON_HUNTER )
  98.     call CampaignAttackerEx( 1, 1, 1, MOON_CHICK )
  99.     call CampaignAttackerEx( 1, 2, 3, DRYAD )
  100.     call CampaignAttackerEx( 0, 1, 2, DRUID_CLAW )
  101.     call CampaignAttackerEx( 0, 1, 2, MOUNTAIN_GIANT )
  102.     call CampaignAttackerEx( 1, 1, 2, FAERIE_DRAGON )
  103.     call CampaignAttackerEx( 0, 1, 2, CHIMAERA )
  104.     call SuicideOnPlayerEx( M6, M5, M4, MyVictim )
  105.     // **********************************
  106.     // *      End Attack Strategy       *
  107.     // **********************************
  108. endfunction

After training the last wave, the script is finished and the AI won't send more units to attack the target player. If you require the the attack never ends we can add a loop to the script, so it will repeat for example the last three waves. The scripts will look like this:

Building + Attacking script with infinite loop. All tiers
Code: jass  [Select]
  1. globals
  2.     player MyVictim = Player( 0 )
  3. endglobals
  4.  
  5. function ConfigureAI takes nothing returns nothing
  6.     call SetSlowChopping( false )
  7.     call SetPeonsRepair( true )
  8. endfunction
  9.  
  10. function main takes nothing returns nothing
  11.     call CampaignAI( MOON_WELL, null )
  12.     call ConfigureAI( )
  13.     // **********************************
  14.     // *      Building Strategy         *
  15.     // **********************************
  16.     //
  17.     // Tier 1 Buildings
  18.     call SetReplacements( 1, 2, 3 )
  19.     call SetBuildUnitEx( 1, 1, 1, TREE_LIFE )
  20.     call SetBuildUnit( 15, WISP )
  21.     call SetBuildUnitEx( 1, 2, 3, MOON_WELL )
  22.     call SetBuildUnitEx( 1, 1, 2, ANCIENT_WAR )
  23.     call SetBuildUnit( 1, ELF_ALTAR )
  24.     call SetBuildUnit( 1, HUNTERS_HALL )
  25.     call CampaignDefenderEx( 2, 2, 3, ARCHER )
  26.     call CampaignDefenderEx( 1, 1, 1, HUNTRESS )
  27.     call CampaignDefenderEx( 0, 1, 2, ANCIENT_PROTECT )
  28.     // Tier 2 buildings
  29.     call SetBuildUnit( 1, TREE_AGES )
  30.     call SetBuildUnitEx( 1, 1, 2, ANCIENT_LORE )
  31.     call SetBuildUnit( 1, ANCIENT_WIND )
  32.     // Tier 3 buildings
  33.     call SetBuildUnit( 1, TREE_ETERNITY )
  34.     call SetBuildUnitEx( 0, 1, 1, CHIMAERA_ROOST )
  35.     // **********************************
  36.     // *    End Building Strategy       *
  37.     // **********************************
  38.     // **********************************
  39.     // *       Attack Strategy          *
  40.     // **********************************
  41.     //*** WAVE 1 ***
  42.     call InitAssaultGroup()
  43.     call CampaignAttackerEx( 2, 3, 3, ARCHER )
  44.     call CampaignAttackerEx( 0, 1, 2, HUNTRESS )  
  45.     call SuicideOnPlayerEx( M3, M2, M2, MyVictim )
  46.     //*** WAVE 2 *** Between 2 or 3 minutes after Wave 1
  47.     call InitAssaultGroup()
  48.     call CampaignAttackerEx( 3, 4, 4, ARCHER )
  49.     call CampaignAttackerEx( 1, 2, 3, HUNTRESS )  
  50.     call SuicideOnPlayerEx( M3, M2, M2, MyVictim )
  51.     //*** WAVE 3 *** Between 2 or 3 minutes after Wave 2
  52.     call InitAssaultGroup()
  53.     call CampaignAttackerEx( 3, 4, 4, ARCHER )
  54.     call CampaignAttackerEx( 1, 2, 3, HUNTRESS )
  55.     call CampaignAttackerEx( 1, 1, 1, DEMON_HUNTER )
  56.     call SuicideOnPlayerEx( M3, M2, M2, MyVictim )
  57.     //*** WAVE 4 *** Between 2 or 3 minutes after Wave 3
  58.     call InitAssaultGroup()
  59.     call CampaignAttackerEx( 3, 4, 4, ARCHER )
  60.     call CampaignAttackerEx( 1, 2, 3, HUNTRESS )
  61.     call CampaignAttackerEx( 1, 1, 1, DEMON_HUNTER )
  62.     call SuicideOnPlayerEx( M3, M2, M2, MyVictim )
  63.     //*** WAVE 5 *** Between 3 or 4 minutes after Wave 4
  64.     call InitAssaultGroup()
  65.     call CampaignAttackerEx( 3, 3, 3, ARCHER )
  66.     call CampaignAttackerEx( 2, 2, 2, HUNTRESS )
  67.     call CampaignAttackerEx( 1, 1, 1, DEMON_HUNTER )
  68.     call CampaignAttackerEx( 0, 1, 2, DRYAD )
  69.     call SuicideOnPlayerEx( M4, M3, M3, MyVictim )
  70.     //*** WAVE 6 *** Between 3 or 4 minutes after Wave 5
  71.     call InitAssaultGroup()
  72.     call CampaignAttackerEx( 2, 2, 2, HUNTRESS )
  73.     call CampaignAttackerEx( 1, 1, 1, DEMON_HUNTER )
  74.     call CampaignAttackerEx( 1, 1, 1, MOON_CHICK )
  75.     call CampaignAttackerEx( 1, 2, 3, DRYAD )
  76.     call CampaignAttackerEx( 0, 1, 2, DRUID_CLAW )
  77.     call SuicideOnPlayerEx( M4, M3, M3, MyVictim )
  78.     loop //Init the infinite attack loop
  79.     //*** WAVE 7 *** Between 3 or 5 minutes after Wave 6
  80.         call InitAssaultGroup()
  81.         call CampaignAttackerEx( 2, 2, 2, HUNTRESS )
  82.         call CampaignAttackerEx( 1, 1, 1, DEMON_HUNTER )
  83.         call CampaignAttackerEx( 1, 1, 1, MOON_CHICK )
  84.         call CampaignAttackerEx( 1, 2, 3, DRYAD )
  85.         call CampaignAttackerEx( 0, 1, 2, DRUID_CLAW )
  86.         call CampaignAttackerEx( 0, 1, 2, MOUNTAIN_GIANT )
  87.         call SuicideOnPlayerEx( M5, M4, M3, MyVictim )
  88.         //*** WAVE 8 *** Between 3 or 5 minutes after Wave 7
  89.         call InitAssaultGroup()
  90.         call CampaignAttackerEx( 2, 2, 2, HUNTRESS )
  91.         call CampaignAttackerEx( 1, 1, 1, DEMON_HUNTER )
  92.         call CampaignAttackerEx( 1, 1, 1, MOON_CHICK )
  93.         call CampaignAttackerEx( 1, 2, 3, DRYAD )
  94.         call CampaignAttackerEx( 0, 1, 2, DRUID_CLAW )
  95.         //*** WAVE 9 *** Between 4 or 6 minutes after Wave 8
  96.         call InitAssaultGroup()
  97.         call CampaignAttackerEx( 2, 2, 2, HUNTRESS )
  98.         call CampaignAttackerEx( 1, 1, 1, DEMON_HUNTER )
  99.         call CampaignAttackerEx( 1, 1, 1, MOON_CHICK )
  100.         call CampaignAttackerEx( 1, 2, 3, DRYAD )
  101.         call CampaignAttackerEx( 0, 1, 2, DRUID_CLAW )
  102.         call CampaignAttackerEx( 0, 1, 2, MOUNTAIN_GIANT )
  103.         call CampaignAttackerEx( 1, 1, 2, FAERIE_DRAGON )
  104.         call CampaignAttackerEx( 0, 1, 2, CHIMAERA )
  105.         call SuicideOnPlayerEx( M6, M5, M4, MyVictim )
  106.     endloop
  107.     // **********************************
  108.     // *   Attack Strategy never ends   *
  109.     // **********************************
  110. endfunction



Upgrading Strategy.

We have almost all the AI. Now it's time to add the upgrades. They can be put in any place inside the code, but I suggest to put this upgrades between each wave, so the AI has a progressive evolution in damage and looks more natural.

Let's see the functions that we're going to use:

  • SetBuildUpgrEx( e, n, i, UpgradeID ): Sets the levels of the upgrade that will be done by the AI in easy, normal and insane mode.
The script now will look in this way:

Building + Attacking script with infinite loop + Upgrading scripts. All tiers
Code: jass  [Select]
  1. globals
  2.     player MyVictim = Player( 0 )
  3. endglobals
  4.  
  5. function ConfigureAI takes nothing returns nothing
  6.     call SetSlowChopping( false )
  7.     call SetPeonsRepair( true )
  8. endfunction
  9.  
  10. function main takes nothing returns nothing
  11.     call CampaignAI( MOON_WELL, null )
  12.     call ConfigureAI( )
  13.     // **********************************
  14.     // *      Building Strategy         *
  15.     // **********************************
  16.     //
  17.     // Tier 1 Buildings
  18.     call SetReplacements( 1, 2, 3 )
  19.     call SetBuildUnitEx( 1, 1, 1, TREE_LIFE )
  20.     call SetBuildUnit( 15, WISP )
  21.     call SetBuildUnitEx( 1, 2, 3, MOON_WELL )
  22.     call SetBuildUnitEx( 1, 1, 2, ANCIENT_WAR )
  23.     call SetBuildUnit( 1, ELF_ALTAR )
  24.     call SetBuildUnit( 1, HUNTERS_HALL )
  25.     call CampaignDefenderEx( 2, 2, 3, ARCHER )
  26.     call CampaignDefenderEx( 1, 1, 1, HUNTRESS )
  27.     call SetBuildUnitEx( 0, 1, 2, ANCIENT_PROTECT )
  28.     // Tier 2 buildings
  29.     call SetBuildUnit( 1, TREE_AGES )
  30.     call SetBuildUnitEx( 1, 1, 2, ANCIENT_LORE )
  31.     call SetBuildUnit( 1, ANCIENT_WIND )
  32.     // Tier 3 buildings
  33.     call SetBuildUnit( 1, TREE_ETERNITY )
  34.     call SetBuildUnitEx( 0, 1, 1, CHIMAERA_ROOST )
  35.     // **********************************
  36.     // *    End Building Strategy       *
  37.     // **********************************
  38.     // **********************************
  39.     // *       Attack Strategy          *
  40.     // **********************************
  41.     //*** WAVE 1 *** AI will begin to attack in 5 minutes
  42.     call InitAssaultGroup()
  43.     call CampaignAttackerEx( 2, 3, 3, ARCHER )
  44.     call CampaignAttackerEx( 0, 1, 2, HUNTRESS )  
  45.     call SuicideOnPlayerEx( M5, M5, M5, MyVictim )
  46.     //*** Basic upgrades from HUNTERS HALL ***
  47.     call SetBuildUpgrEx( 1, 2, 3, UPG_STR_MOON )
  48.     call SetBuildUpgrEx( 1, 2, 3, UPG_MOON_ARMOR )
  49.     call SetBuildUpgrEx( 1, 2, 3, UPG_STR_WILD )
  50.     call SetBuildUpgrEx( 1, 2, 3, UPG_HIDES )
  51.     //*** WAVE 2 *** Between 2 or 3 minutes after Wave 1
  52.     call InitAssaultGroup()
  53.     call CampaignAttackerEx( 3, 4, 4, ARCHER )
  54.     call CampaignAttackerEx( 1, 2, 3, HUNTRESS )  
  55.     call SuicideOnPlayerEx( M3, M2, M2, MyVictim )
  56.     //*** WAVE 3 *** Between 2 or 3 minutes after Wave 2
  57.     call InitAssaultGroup()
  58.     call CampaignAttackerEx( 3, 4, 4, ARCHER )
  59.     call CampaignAttackerEx( 1, 2, 3, HUNTRESS )
  60.     call CampaignAttackerEx( 1, 1, 1, DEMON_HUNTER )
  61.     call SuicideOnPlayerEx( M3, M2, M2, MyVictim )
  62.     //*** WAVE 4 *** Between 2 or 3 minutes after Wave 3
  63.     call InitAssaultGroup()
  64.     call CampaignAttackerEx( 3, 4, 4, ARCHER )
  65.     call CampaignAttackerEx( 1, 2, 3, HUNTRESS )
  66.     call CampaignAttackerEx( 0, 1, 1, BALLISTA )
  67.     call CampaignAttackerEx( 1, 1, 1, DEMON_HUNTER )
  68.     call SuicideOnPlayerEx( M3, M2, M2, MyVictim )
  69.     //*** Dryad Upgrade
  70.     call SetBuildUpgrEx( 1, 1, 1, UPG_ABOLISH )
  71.     //*** WAVE 5 *** Between 3 or 4 minutes after Wave 4
  72.     call InitAssaultGroup()
  73.     call CampaignAttackerEx( 3, 3, 3, ARCHER )
  74.     call CampaignAttackerEx( 2, 2, 2, HUNTRESS )
  75.     call CampaignAttackerEx( 1, 1, 1, DEMON_HUNTER )
  76.     call CampaignAttackerEx( 0, 1, 2, DRYAD )
  77.     call SuicideOnPlayerEx( M4, M3, M3, MyVictim )
  78.     //*** Druid of the Claw Upgrade
  79.     call SetBuildUpgrEx( 0, 1, 2, UPG_DRUID_CLAW )
  80.     //*** WAVE 6 *** Between 3 or 4 minutes after Wave 5
  81.     call InitAssaultGroup()
  82.     call CampaignAttackerEx( 2, 2, 2, HUNTRESS )
  83.     call CampaignAttackerEx( 1, 1, 1, DEMON_HUNTER )
  84.     call CampaignAttackerEx( 1, 1, 1, MOON_CHICK )
  85.     call CampaignAttackerEx( 1, 2, 3, DRYAD )
  86.     call CampaignAttackerEx( 0, 1, 2, DRUID_CLAW )
  87.     call SuicideOnPlayerEx( M4, M3, M3, MyVictim )
  88.     //*** chimaera Upgrade
  89.     call SetBuildUpgrEx( 0, 0, 1, UPG_CHIM_ACID )
  90.     loop //Init the infinite attack loop
  91.     //*** WAVE 7 *** Between 3 or 5 minutes after Wave 6
  92.         call InitAssaultGroup()
  93.         call CampaignAttackerEx( 2, 2, 2, HUNTRESS )
  94.         call CampaignAttackerEx( 1, 1, 1, DEMON_HUNTER )
  95.         call CampaignAttackerEx( 1, 1, 1, MOON_CHICK )
  96.         call CampaignAttackerEx( 1, 2, 3, DRYAD )
  97.         call CampaignAttackerEx( 0, 1, 2, DRUID_CLAW )
  98.         call CampaignAttackerEx( 0, 1, 2, MOUNTAIN_GIANT )
  99.         call SuicideOnPlayerEx( M5, M4, M3, MyVictim )
  100.         //*** WAVE 8 *** Between 3 or 5 minutes after Wave 7
  101.         call InitAssaultGroup()
  102.         call CampaignAttackerEx( 2, 2, 2, HUNTRESS )
  103.         call CampaignAttackerEx( 1, 1, 1, DEMON_HUNTER )
  104.         call CampaignAttackerEx( 1, 1, 1, MOON_CHICK )
  105.         call CampaignAttackerEx( 1, 2, 3, DRYAD )
  106.         call CampaignAttackerEx( 0, 1, 2, DRUID_CLAW )
  107.         //*** WAVE 9 *** Between 4 or 6 minutes after Wave 8
  108.         call InitAssaultGroup()
  109.         call CampaignAttackerEx( 2, 2, 2, HUNTRESS )
  110.         call CampaignAttackerEx( 1, 1, 1, DEMON_HUNTER )
  111.         call CampaignAttackerEx( 1, 1, 1, MOON_CHICK )
  112.         call CampaignAttackerEx( 1, 2, 3, DRYAD )
  113.         call CampaignAttackerEx( 0, 1, 2, DRUID_CLAW )
  114.         call CampaignAttackerEx( 0, 1, 2, MOUNTAIN_GIANT )
  115.         call CampaignAttackerEx( 1, 1, 2, FAERIE_DRAGON )
  116.         call CampaignAttackerEx( 0, 1, 2, CHIMAERA )
  117.         call SuicideOnPlayerEx( M6, M5, M4, MyVictim )
  118.     endloop
  119.     // **********************************
  120.     // *   Attack Strategy never ends   *
  121.     // **********************************
  122. endfunction



Hero Abilities.

If we test this AI, we can notice that heroes don't learn any abilities, the question is how can we make that??? the answer is adding the ability learning script to the function CampaignAI. This function will have an effect when the hero has ability levels avaliable. I made this script so it can fix with the example, which trains a Demon Hunter and a Priestress of the Moon.

Hero Leveling Script
Code: jass  [Select]
  1. function hero_levels takes nothing returns integer
  2.     local integer hero  = GetHeroId()
  3.     local integer level = GetHeroLevelAI()
  4.     local integer a = 0
  5.     if hero == DEMON_HUNTER then
  6.         if level == 1 or level == 3 or level == 5 then
  7.             set a = IMMOLATION
  8.         endif
  9.         if level == 2 or level == 4 or level == 7 then
  10.             set a = MANA_BURN
  11.         endif
  12.         if level >= 8 then
  13.             set a = EVASION
  14.         endif
  15.         if level == 6 then
  16.             set a = METAMORPHOSIS
  17.         endif
  18.     endif
  19.     if hero == MOON_CHICK then
  20.         if level == 1 or level == 3 or level == 5 then
  21.             set a = TRUESHOT
  22.         endif
  23.         if level == 2 or level == 4 or level == 7 then
  24.             set a = SEARING_ARROWS
  25.         endif
  26.         if level >= 8 then
  27.             set a = SCOUT
  28.         endif
  29.         if level == 6 then
  30.             set a = STARFALL
  31.         endif
  32.     endif
  33.     return a
  34. endfunction

As you can see, this function takes nothing and returns the ability Rawcode that the hero must learn. REMEMBER: This function MUST return an integer ALWAYS.

Now that we have this function configured, we are going to add to the script, remeber that it must be put bafore the main function so it can call it. To set the function in the main script, we write it in this way:
call CampaignAI( MOON_WELL, function hero_levels )
And the whole code will llook like this:

Building + Attacking script with infinite loop + Upgrading (including heroes) scripts. All tiers
Code: jass  [Select]
  1. globals
  2.     player MyVictim = Player( 0 )
  3. endglobals
  4.  
  5. function ConfigureAI takes nothing returns nothing
  6.     call SetSlowChopping( false )
  7.     call SetPeonsRepair( true )
  8. endfunction
  9.  
  10. function hero_levels takes nothing returns integer
  11.     local integer hero  = GetHeroId()
  12.     local integer level = GetHeroLevelAI()
  13.     local integer a = 0
  14.     if hero == DEMON_HUNTER then
  15.         if level == 1 or level == 3 or level == 5 then
  16.             set a = IMMOLATION
  17.         endif
  18.         if level == 2 or level == 4 or level == 7 then
  19.             set a = MANA_BURN
  20.         endif
  21.         if level >= 8 then
  22.             set a = EVASION
  23.         endif
  24.         if level == 6 then
  25.             set a = METAMORPHOSIS
  26.         endif
  27.     endif
  28.     if hero == MOON_CHICK then
  29.         if level == 1 or level == 3 or level == 5 then
  30.             set a = TRUESHOT
  31.         endif
  32.         if level == 2 or level == 4 or level == 7 then
  33.             set a = SEARING_ARROWS
  34.         endif
  35.         if level >= 8 then
  36.             set a = SCOUT
  37.         endif
  38.         if level == 6 then
  39.             set a = STARFALL
  40.         endif
  41.     endif
  42.     return a
  43. endfunction
  44.  
  45. function main takes nothing returns nothing
  46.     call CampaignAI( MOON_WELL, function hero_levels ) //<== Now this function upgrades heroes
  47.     call ConfigureAI( )
  48.     // **********************************
  49.     // *      Building Strategy         *
  50.     // **********************************
  51.     //
  52.     // Tier 1 Buildings
  53.     call SetReplacements( 1, 2, 3 )
  54.     call SetBuildUnitEx( 1, 1, 1, TREE_LIFE )
  55.     call SetBuildUnit( 15, WISP )
  56.     call SetBuildUnitEx( 1, 2, 3, MOON_WELL )
  57.     call SetBuildUnitEx( 1, 2, 2, ANCIENT_WAR )
  58.     call SetBuildUnit( 1, ELF_ALTAR )
  59.     call SetBuildUnit( 1, HUNTERS_HALL )
  60.     call CampaignDefenderEx( 2, 2, 3, ARCHER )
  61.     call CampaignDefenderEx( 1, 1, 1, HUNTRESS )
  62.     call SetBuildUnitEx( 1, 2, 3, ANCIENT_PROTECT )
  63.     // Tier 2 buildings
  64.     call SetBuildUnit( 1, TREE_AGES )
  65.     call SetBuildUnitEx( 1, 2, 2, ANCIENT_LORE )
  66.     call SetBuildUnit( 1, ANCIENT_WIND )
  67.     // Tier 3 buildings
  68.     call SetBuildUnit( 1, TREE_ETERNITY )
  69.     call SetBuildUnitEx( 0, 1, 1, CHIMAERA_ROOST )
  70.     // **********************************
  71.     // *    End Building Strategy       *
  72.     // **********************************
  73.     // **********************************
  74.     // *       Attack Strategy          *
  75.     // **********************************
  76.     //*** WAVE 1 *** AI will begin to attack in 5 minutes
  77.     call InitAssaultGroup()
  78.     call CampaignAttackerEx( 2, 3, 3, ARCHER )
  79.     call CampaignAttackerEx( 0, 1, 2, HUNTRESS )  
  80.     call SuicideOnPlayerEx( M5, M5, M5, MyVictim )
  81.     //*** Basic upgrades from HUNTERS HALL ***
  82.     call SetBuildUpgrEx( 1, 2, 3, UPG_STR_MOON )
  83.     call SetBuildUpgrEx( 1, 2, 3, UPG_MOON_ARMOR )
  84.     call SetBuildUpgrEx( 1, 2, 3, UPG_STR_WILD )
  85.     call SetBuildUpgrEx( 1, 2, 3, UPG_HIDES )
  86.     //*** WAVE 2 *** Between 2 or 3 minutes after Wave 1
  87.     call InitAssaultGroup()
  88.     call CampaignAttackerEx( 3, 4, 4, ARCHER )
  89.     call CampaignAttackerEx( 1, 2, 3, HUNTRESS )  
  90.     call SuicideOnPlayerEx( M3, M2, M2, MyVictim )
  91.     //*** WAVE 3 *** Between 2 or 3 minutes after Wave 2
  92.     call InitAssaultGroup()
  93.     call CampaignAttackerEx( 3, 4, 4, ARCHER )
  94.     call CampaignAttackerEx( 1, 2, 3, HUNTRESS )
  95.     call CampaignAttackerEx( 1, 1, 1, DEMON_HUNTER )
  96.     call SuicideOnPlayerEx( M3, M2, M2, MyVictim )
  97.     //*** WAVE 4 *** Between 2 or 3 minutes after Wave 3
  98.     call InitAssaultGroup()
  99.     call CampaignAttackerEx( 3, 4, 4, ARCHER )
  100.     call CampaignAttackerEx( 1, 2, 3, HUNTRESS )
  101.     call CampaignAttackerEx( 0, 1, 1, BALLISTA )
  102.     call CampaignAttackerEx( 1, 1, 1, DEMON_HUNTER )
  103.     call SuicideOnPlayerEx( M3, M2, M2, MyVictim )
  104.     //*** Dryad Upgrade
  105.     call SetBuildUpgrEx( 1, 1, 1, UPG_ABOLISH )
  106.     //*** WAVE 5 *** Between 3 or 4 minutes after Wave 4
  107.     call InitAssaultGroup()
  108.     call CampaignAttackerEx( 3, 3, 3, ARCHER )
  109.     call CampaignAttackerEx( 2, 2, 2, HUNTRESS )
  110.     call CampaignAttackerEx( 1, 1, 1, DEMON_HUNTER )
  111.     call CampaignAttackerEx( 0, 1, 2, DRYAD )
  112.     call SuicideOnPlayerEx( M4, M3, M3, MyVictim )
  113.     //*** Druid of the Claw Upgrade
  114.     call SetBuildUpgrEx( 0, 1, 2, UPG_DRUID_CLAW )
  115.     //*** WAVE 6 *** Between 3 or 4 minutes after Wave 5
  116.     call InitAssaultGroup()
  117.     call CampaignAttackerEx( 2, 2, 2, HUNTRESS )
  118.     call CampaignAttackerEx( 1, 1, 1, DEMON_HUNTER )
  119.     call CampaignAttackerEx( 1, 1, 1, MOON_CHICK )
  120.     call CampaignAttackerEx( 1, 2, 3, DRYAD )
  121.     call CampaignAttackerEx( 0, 1, 2, DRUID_CLAW )
  122.     call SuicideOnPlayerEx( M4, M3, M3, MyVictim )
  123.     //*** chimaera Upgrade
  124.     call SetBuildUpgrEx( 0, 0, 1, UPG_CHIM_ACID )
  125.     loop //Init the infinite attack loop
  126.     //*** WAVE 7 *** Between 3 or 5 minutes after Wave 6
  127.         call InitAssaultGroup()
  128.         call CampaignAttackerEx( 2, 2, 2, HUNTRESS )
  129.         call CampaignAttackerEx( 1, 1, 1, DEMON_HUNTER )
  130.         call CampaignAttackerEx( 1, 1, 1, MOON_CHICK )
  131.         call CampaignAttackerEx( 1, 2, 3, DRYAD )
  132.         call CampaignAttackerEx( 0, 1, 2, DRUID_CLAW )
  133.         call CampaignAttackerEx( 0, 1, 2, MOUNTAIN_GIANT )
  134.         call SuicideOnPlayerEx( M5, M4, M3, MyVictim )
  135.         //*** WAVE 8 *** Between 3 or 5 minutes after Wave 7
  136.         call InitAssaultGroup()
  137.         call CampaignAttackerEx( 2, 2, 2, HUNTRESS )
  138.         call CampaignAttackerEx( 1, 1, 1, DEMON_HUNTER )
  139.         call CampaignAttackerEx( 1, 1, 1, MOON_CHICK )
  140.         call CampaignAttackerEx( 1, 2, 3, DRYAD )
  141.         call CampaignAttackerEx( 0, 1, 2, DRUID_CLAW )
  142.         //*** WAVE 9 *** Between 4 or 6 minutes after Wave 8
  143.         call InitAssaultGroup()
  144.         call CampaignAttackerEx( 2, 2, 2, HUNTRESS )
  145.         call CampaignAttackerEx( 1, 1, 1, DEMON_HUNTER )
  146.         call CampaignAttackerEx( 1, 1, 1, MOON_CHICK )
  147.         call CampaignAttackerEx( 1, 2, 3, DRYAD )
  148.         call CampaignAttackerEx( 0, 1, 2, DRUID_CLAW )
  149.         call CampaignAttackerEx( 0, 1, 2, MOUNTAIN_GIANT )
  150.         call CampaignAttackerEx( 1, 1, 2, FAERIE_DRAGON )
  151.         call CampaignAttackerEx( 0, 1, 2, CHIMAERA )
  152.         call SuicideOnPlayerEx( M6, M5, M4, MyVictim )
  153.     endloop
  154.     // **********************************
  155.     // *   Attack Strategy never ends   *
  156.     // **********************************
  157. endfunction



Controlling the AI via triggers.

when we're creating a campaign, we need to keep the AI controlled in some way, for example we need that the AI attacks when an unit enters on a region or the player kills some unit. As an example, We are going to create a trigger that will start the AI attacks when an unit enters in one region.

Trigger: Test 792365505
   
           
  • Start AI attack
  •     Events
  •         Unit - A unit enters Militia birth1 <gen>
  •     Conditions
  •         (Owner of (Triggering unit)) Equal to Player 1 (Red)
  •     Actions
  •         AI - Send Player 2 (Blue) the AI Command (0, 0)
  •         Custom script:   call DestroyTrigger( GetTriggeringTrigger() )
           

And now we need that the AI begins when it receives this AI Command, it can be done putting the function WaitForSignal() before the attacking script in the AI. This function takes nothing and returns an integer that is the command received. So we can use this function in two ways.

Code: jass  [Select]
  1. function main takes nothing returns nothing
  2.     local integer cmd // <==Only set it if you are going to use the option 2
  3.     ... // Your building code here
  4.     // Option 1
  5.     call WaitForSignal() // <== Just waits until the map sends a command
  6.  
  7.     // Option 2
  8.     set cmd = WaitForSignal() // <== Get the command received and makes react the AI accordingly.
  9.     if cmd == 0 then
  10.         //do option 0
  11.     elseif cmd == 1 then
  12.         //do option 1. etc
  13.     ...
  14.     endif
  15. endfunction
  • The second option is the most interesting because we can make react the AI in different ways (for example, that one time attack the player 1 and in other time attack the player 3, etc.)



Testing the AI.

Now the most important part. If we want to test this AI there's two ways, the slowest but the most accurate, which we attach the AI file inside the map and run it to check how it bahaves (check this tutorial from Av3n about AI importing) or the fastest one. I'll explain the fastest one.


  • Save your AI script as an *.AI file.
  • Open WE
  • Press F8 or make click on the button AI Editor.
  • With the AI Editor open, select the fourth tab Test Configuration
  • Here, set the game speed in 3X (Now you understand why it's the fastest way)
  • Set the map where you want to test your AI. By default, WE sets the PlunderIsle map. You can change it pressing the button [BUTTON]Set Map[/BUTTON].
  • Set your Players. Remember that if you configure the AI to attack player 1 (Player(0) in JASS) you MUST use a slot different to 1 so it can works. it sounds redundant, but sometimes we forget it.
  • Set the race of your AI accordingly (don't put human or random race in a Night Elf AI fr example).
  • for the slot where our AI will work, change in the AI option to Custom. when you do that, it activates a button with label [BUTTON]Set[/BUTTON]. Press it, and you can select the AI file that you have created.
  • Set the target player as a computer with a current AI.
  • Ensure that your AI player and the target player are in different teams.
  • Set an user player as an observer in the team selection.
  • Press CTRL + F9 or the button Test AI
Here's an AI Editor screenshot that shows how you should have configured this test:
And the test will run. If the AI works fine you will see the workers starting buildings. :emote_grin:

If you see workers only gathering resources and don't do anything else, it means that you have a JASS error in you file, check the syntax, save and test again, remember that JASS is case sensitive so a lower case letter will do the AI fail.

table: Final Thoughts
I Hope this tutorial can be helpful to everybody. If I have time, I'll try to do other tutorial about Standard AI. Suggestions and questions are welcome.

Meanwhile, play with this AI, change the units, do experiments with it, it is the only way to get more knowledge about the Wacraft AI.
PS: Because I'm still learning English, I could have commited some mistakes, please let me know about that and I will fix them ASAP.


"Campaign Complete"
Campaign script complete
Code: jass  [Select]
  1. //******************************************************************************
  2. //*                           Night Elf Campaign AI                            *
  3. //*                                 By Moyack                                  *
  4. //******************************************************************************
  5. //*
  6. globals
  7.     player MyVictim = Player( 0 )
  8. endglobals
  9.  
  10. function ConfigureAI takes nothing returns nothing
  11.     call SetSlowChopping( false )
  12.     call SetPeonsRepair( true )
  13. endfunction
  14.  
  15. function hero_levels takes nothing returns integer
  16.     local integer hero  = GetHeroId()
  17.     local integer level = GetHeroLevelAI()
  18.     local integer a = 0
  19.     if hero == DEMON_HUNTER then
  20.         if level == 1 or level == 3 or level == 5 then
  21.             set a = IMMOLATION
  22.         endif
  23.         if level == 2 or level == 4 or level == 7 then
  24.             set a = MANA_BURN
  25.         endif
  26.         if level >= 8 then
  27.             set a = EVASION
  28.         endif
  29.         if level == 6 then
  30.             set a = METAMORPHOSIS
  31.         endif
  32.     endif
  33.     if hero == MOON_CHICK then
  34.         if level == 1 or level == 3 or level == 5 then
  35.             set a = TRUESHOT
  36.         endif
  37.         if level == 2 or level == 4 or level == 7 then
  38.             set a = SEARING_ARROWS
  39.         endif
  40.         if level >= 8 then
  41.             set a = SCOUT
  42.         endif
  43.         if level == 6 then
  44.             set a = STARFALL
  45.         endif
  46.     endif
  47.     return a
  48. endfunction
  49.  
  50. function main takes nothing returns nothing
  51.     call CampaignAI( MOON_WELL, function hero_levels )
  52.     call ConfigureAI( )
  53.     // **********************************
  54.     // *      Building Strategy         *
  55.     // **********************************
  56.     //
  57.     // Tier 1 Buildings
  58.     call SetReplacements( 1, 2, 3 )
  59.     call SetBuildUnitEx( 1, 1, 1, TREE_LIFE )
  60.     call SetBuildUnit( 15, WISP )
  61.     call SetBuildUnitEx( 1, 2, 3, MOON_WELL )
  62.     call SetBuildUnitEx( 1, 2, 2, ANCIENT_WAR )
  63.     call SetBuildUnit( 1, ELF_ALTAR )
  64.     call SetBuildUnit( 1, HUNTERS_HALL )
  65.     call CampaignDefenderEx( 2, 2, 3, ARCHER )
  66.     call CampaignDefenderEx( 1, 1, 1, HUNTRESS )
  67.     call SetBuildUnitEx( 1, 2, 3, ANCIENT_PROTECT )
  68.     // Tier 2 buildings
  69.     call SetBuildUnit( 1, TREE_AGES )
  70.     call SetBuildUnitEx( 1, 2, 2, ANCIENT_LORE )
  71.     call SetBuildUnit( 1, ANCIENT_WIND )
  72.     // Tier 3 buildings
  73.     call SetBuildUnit( 1, TREE_ETERNITY )
  74.     call SetBuildUnitEx( 0, 1, 1, CHIMAERA_ROOST )
  75.     // **********************************
  76.     // *    End Building Strategy       *
  77.     // **********************************
  78.     // **********************************
  79.     // *       Attack Strategy          *
  80.     // **********************************
  81.     //*** WAVE 1 *** AI will begin to attack in 5 minutes
  82.     call InitAssaultGroup()
  83.     call CampaignAttackerEx( 2, 3, 3, ARCHER )
  84.     call CampaignAttackerEx( 0, 1, 2, HUNTRESS )  
  85.     call SuicideOnPlayerEx( M5, M5, M5, MyVictim )
  86.     //*** Basic upgrades from HUNTERS HALL ***
  87.     call SetBuildUpgrEx( 1, 2, 3, UPG_STR_MOON )
  88.     call SetBuildUpgrEx( 1, 2, 3, UPG_MOON_ARMOR )
  89.     call SetBuildUpgrEx( 1, 2, 3, UPG_STR_WILD )
  90.     call SetBuildUpgrEx( 1, 2, 3, UPG_HIDES )
  91.     //*** WAVE 2 *** Between 2 or 3 minutes after Wave 1
  92.     call InitAssaultGroup()
  93.     call CampaignAttackerEx( 3, 4, 4, ARCHER )
  94.     call CampaignAttackerEx( 1, 2, 3, HUNTRESS )  
  95.     call SuicideOnPlayerEx( M3, M2, M2, MyVictim )
  96.     //*** WAVE 3 *** Between 2 or 3 minutes after Wave 2
  97.     call InitAssaultGroup()
  98.     call CampaignAttackerEx( 3, 4, 4, ARCHER )
  99.     call CampaignAttackerEx( 1, 2, 3, HUNTRESS )
  100.     call CampaignAttackerEx( 1, 1, 1, DEMON_HUNTER )
  101.     call SuicideOnPlayerEx( M3, M2, M2, MyVictim )
  102.     //*** WAVE 4 *** Between 2 or 3 minutes after Wave 3
  103.     call InitAssaultGroup()
  104.     call CampaignAttackerEx( 3, 4, 4, ARCHER )
  105.     call CampaignAttackerEx( 1, 2, 3, HUNTRESS )
  106.     call CampaignAttackerEx( 0, 1, 1, BALLISTA )
  107.     call CampaignAttackerEx( 1, 1, 1, DEMON_HUNTER )
  108.     call SuicideOnPlayerEx( M3, M2, M2, MyVictim )
  109.     //*** Dryad Upgrade
  110.     call SetBuildUpgrEx( 1, 1, 1, UPG_ABOLISH )
  111.     //*** WAVE 5 *** Between 3 or 4 minutes after Wave 4
  112.     call InitAssaultGroup()
  113.     call CampaignAttackerEx( 3, 3, 3, ARCHER )
  114.     call CampaignAttackerEx( 2, 2, 2, HUNTRESS )
  115.     call CampaignAttackerEx( 1, 1, 1, DEMON_HUNTER )
  116.     call CampaignAttackerEx( 0, 1, 2, DRYAD )
  117.     call SuicideOnPlayerEx( M4, M3, M3, MyVictim )
  118.     //*** Druid of the Claw Upgrade
  119.     call SetBuildUpgrEx( 0, 1, 2, UPG_DRUID_CLAW )
  120.     //*** WAVE 6 *** Between 3 or 4 minutes after Wave 5
  121.     call InitAssaultGroup()
  122.     call CampaignAttackerEx( 2, 2, 2, HUNTRESS )
  123.     call CampaignAttackerEx( 1, 1, 1, DEMON_HUNTER )
  124.     call CampaignAttackerEx( 1, 1, 1, MOON_CHICK )
  125.     call CampaignAttackerEx( 1, 2, 3, DRYAD )
  126.     call CampaignAttackerEx( 0, 1, 2, DRUID_CLAW )
  127.     call SuicideOnPlayerEx( M4, M3, M3, MyVictim )
  128.     //*** chimaera Upgrade
  129.     call SetBuildUpgrEx( 0, 0, 1, UPG_CHIM_ACID )
  130.     loop //Init the infinite attack loop
  131.     //*** WAVE 7 *** Between 3 or 5 minutes after Wave 6
  132.         call InitAssaultGroup()
  133.         call CampaignAttackerEx( 2, 2, 2, HUNTRESS )
  134.         call CampaignAttackerEx( 1, 1, 1, DEMON_HUNTER )
  135.         call CampaignAttackerEx( 1, 1, 1, MOON_CHICK )
  136.         call CampaignAttackerEx( 1, 2, 3, DRYAD )
  137.         call CampaignAttackerEx( 0, 1, 2, DRUID_CLAW )
  138.         call CampaignAttackerEx( 0, 1, 2, MOUNTAIN_GIANT )
  139.         call SuicideOnPlayerEx( M5, M4, M3, MyVictim )
  140.         //*** WAVE 8 *** Between 3 or 5 minutes after Wave 7
  141.         call InitAssaultGroup()
  142.         call CampaignAttackerEx( 2, 2, 2, HUNTRESS )
  143.         call CampaignAttackerEx( 1, 1, 1, DEMON_HUNTER )
  144.         call CampaignAttackerEx( 1, 1, 1, MOON_CHICK )
  145.         call CampaignAttackerEx( 1, 2, 3, DRYAD )
  146.         call CampaignAttackerEx( 0, 1, 2, DRUID_CLAW )
  147.         call SuicideOnPlayerEx( M5, M4, M3, MyVictim )
  148.         //*** WAVE 9 *** Between 4 or 6 minutes after Wave 8
  149.         call InitAssaultGroup()
  150.         call CampaignAttackerEx( 2, 2, 2, HUNTRESS )
  151.         call CampaignAttackerEx( 1, 1, 1, DEMON_HUNTER )
  152.         call CampaignAttackerEx( 1, 1, 1, MOON_CHICK )
  153.         call CampaignAttackerEx( 1, 2, 3, DRYAD )
  154.         call CampaignAttackerEx( 0, 1, 2, DRUID_CLAW )
  155.         call CampaignAttackerEx( 0, 1, 2, MOUNTAIN_GIANT )
  156.         call CampaignAttackerEx( 1, 1, 2, FAERIE_DRAGON )
  157.         call CampaignAttackerEx( 0, 1, 2, CHIMAERA )
  158.         call SuicideOnPlayerEx( M6, M5, M4, MyVictim )
  159.     endloop
  160.     // **********************************
  161.     // *   Attack Strategy never ends   *
  162.     // **********************************
  163. endfunction
« Last Edit: January 27, 2013, 10:29:02 AM by moyack »

We can give you full hosting for your projects, a complete page!!

A custom altered melee map where you can play Naga and Demons. Check it out!!
Use Dropbox...

  • Site Owner
  • Administrator
  • Starter - level 4
  • *
  • Posts: 987
  • WC3 Models: 43
  • WC3 Tutorials: 13
  • WC3 Tools: 10
  • WC3 Maps: 11
  • WC3 Skins: 6
  • WC3 Icons: 2
  • WC3 Spells: 5
  • Reputation: 1153
  • Site Admin - I love fix things
    • View Profile
    • Blizzard Modding Information Center
How to make a Campaign AI
« Reply #1 on: January 20, 2013, 10:35:54 PM »
Updated with a fix in the definition of a function. Thanks Starquizer :D
« Last Edit: June 24, 2017, 11:44:43 PM by moyack »

We can give you full hosting for your projects, a complete page!!

A custom altered melee map where you can play Naga and Demons. Check it out!!
Use Dropbox...

 

Make a Map Work for Patch 1.24

Started by PurgeandfireBoard Tutorial Zone

Replies: 0
Views: 122
Last post November 20, 2010, 09:02:35 PM
by Purgeandfire
How to make a decent melee map

Started by SonofJayBoard Tutorial Zone

Replies: 10
Views: 11558
Last post July 11, 2013, 04:35:36 PM
by Naoto Shirogane
Blizzard Modding Information Center Starcraft II Modding Information Center Wacraft III Modding Information Center WC3JASS.com - The JASS Vault Chronicles of Darkness - A Warcraft III mod Jetcraft - A Starcraft II mod Troll Smash - A Warcraft III Arena
  Mod DB - Change the Game Power of Corruption - A Warcraft III altered melee map Chaos Realm - The world of Game modders and wc3 addicts Follow us on Facebook!!