• Check out the results of the Techtree Contest #19!
  • Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.
  • Create a void inspired texture for Warcraft 3 and enter Hive's 34th Texturing Contest: Void! Click here to enter!
  • The Hive's 22nd Icon Contest: Creep Abilities is now concluded, time to vote for your favourite set of icons! Click here to vote!

AI Script not working

Level 7
Joined
Oct 7, 2024
Messages
25
Hiya again,
I recently made an AI script for a mission but it isn't working. I will provide as much detail as I can, and I think I know where the issue is, but who knows.

This is what I have for my program. The enemy I am making is an Orange Orc and the player is Red. I am currently only making 1 "difficulty". Everything is using standard melee calls except for 'OGut' which is a modified version of a far seer saved as a custom unit in the mission with that tag. I have a screenshot below showing how it is saved.


JASS:
globals
    player user = PlayerEx(0)
endglobals

 function main takes nothing returns nothing
    call CampaignAI(otrb, null)
    call DoCampaignFarms(false)
    call SetPeonsRepair(true)
    call SetHeroesFlee(false)
    call SetGroupsFlee(false)
 
 //Accounts all preplaced units 
    call SetBuildUnit(1, ogre)
    call SetBuildUnit(4, opeo)
    call SetBuildUnit(1, obar)
    call SetBuildUnit(1, ostr)
    call SetBuildUnit(1, oalt)
    call SetBuildUnit(1, osld)
    call SetBuildUnit(1, ofor)
    call SetBuildUnit(4, otrb)
    call SetBuildUnit(5, ogru)
    call SetBuildUnit(4, ohun)
    call SetBuildUnit(3, oshm)
  
//Defenders
    call CampaignDefenderEx(5, 5, 5, ogru)
    call CampaignDefenderEx(4, 4, 4, ohun)
    call CampaignDefenderEx(3, 3, 3, oshm)
  
//Wave system
    call WaitForSignal()
  
    //*** WAVE 1: 7 minutes ***
    call Sleep(M4)
    call InitAssaultGroup()
    call CampaignAttackerEx(3, 3, 3, ogru)
    call CampaignAttackerEx(2, 2, 2, ohun)
    call CampaignAttackerEx(1, 1, 1, oshm)
    call SuicideOnPlayer(M4, user)

    //*** WAVE 2: 11 minutes ***
    call Sleep(M4)
    call InitAssaultGroup()
    call CampaignAttackerEx(1, 1, 1, OGut)
    call CampaignAttackerEx(2, 2, 2, ogru)
    call CampaignAttackerEx(2, 2, 2, ohun)
    call SuicideOnPlayer(M4, user)

    //*** WAVE 3: 15 minutes ***
    call Sleep(M4)
    call InitAssaultGroup()
    call CampaignAttackerEx(3, 3, 3, ogru)
    call CampaignAttackerEx(5, 5, 5, ohun)
    call SuicideOnPlayer(M4, user)

    //*** WAVE 4: 19 minutes ***
    call Sleep(M4)
    call InitAssaultGroup()
    call CampaignAttackerEx(1, 1, 1, OGut)
    call CampaignAttackerEx(3, 3, 3, ogru)
    call CampaignAttackerEx(1, 1, 1, oshm)
    call SuicideOnPlayer(M4, user)

    loop
        //*** WAVE 5+: repeating ***
        call Sleep(M4)
        call InitAssaultGroup()
        call CampaignAttackerEx(3, 3, 3, ogru)
        call CampaignAttackerEx(3, 3, 3, ohun)
        call CampaignAttackerEx(2, 2, 2, oshm)
        call SuicideOnPlayer(M4, user)
    endloop

endfunction

====

This is the object editor. From my understanding, you can't directly place any campaign versions, so I saved a copy into the mission.

1775506111075.png



I didn't do any kinds of importing for the heroes since I reasoned that the script would just read it off the mission.


For actually saving, I made the script above in Jasscraft (.j file), then copied into Notepad ++ and saved as a .ai file, which I imported into the mission.

1775506127505.png



As for actually calling it, here is what I did. The action in the 2nd image is to send something so WaitforSignal actually works, but I'm not sure how to actually write it. This could also be something that is causing the issue.

1775506145591.png

1775506165961.png


That's pretty much anything I could think of that would be helpful for troubleshooting. I tested in both the map-editor and saved as a campaign and tested directly inside the game, but neither worked (I also ran into other a few other bugs like the UI showing as undead instead of human when launched from in the game but that's another unrelated problem).
Hopefully y'all can help me out, as all the other resources that y'all provided have been really helpful, so thanks :wthumbsup:

Edit: I also want to clarify that nothing is happening. Peons don't go to harvest gold, no troops are trained. I think I see an issue with there not being anything calling new units to be trained (everything in the build order section is already placed and units are assigned to be defenders, working on it).
 
Last edited:
Here's the issue:

1775508469615.png


:p Two options, either you use the variants that Blizzard declared in common.ai and type PEON, GRUNT etc, or you need to use single quotes and type 'opeo' and 'ogru' , right now all of those in your script as considered as new undeclared units so that's why nothing is happening :)

Edit: you also need to declare your custom unit in the globals at the very beginning, using the raw code on something that's not a base unit won't be recognized, so you can do something like this

1775508773883.png


The label in white can be anything you want, then you can reuse it for attack waves and the game will know that it corresponds to your custom unit
 
Here's the issue:

View attachment 583541

:p Two options, either you use the variants that Blizzard declared in common.ai and type PEON, GRUNT etc, or you need to use single quotes and type 'opeo' and 'ogru' , right now all of those in your script as considered as new undeclared units so that's why nothing is happening :)
I see that makes sense. On my question for the hero, would what I have make it work since it is declared inside the map, or is there some kind of other steps people take to make it work? Thanks for the help.
 
I edited my reply, there's a little variable to declare first indeed
This is what I have now. I changed stuff up to be a bit simpler and just have surplus pre-placed units I will just draw from for my attack waves. I also changed it so the script starts running at map initialization and just added more wait time to the 1st wave (I also got rid of the WaitforSignal trigger). The syntax checker no longer said undeclared variables, but it still said I had undeclared functions but I'm guessing that's because they are natives to the game itself.

JASS:
globals
    player user = PlayerEx(0)
    integer GUTHRIL = 'OGut'
endglobals

function main takes nothing returns nothing
    call CampaignAI('otrb', null)
    call SetReplacements(8, 8, 8)
    call DoCampaignFarms(false)
    call SetPeonsRepair(true)
    call SetHeroesFlee(false)
    call SetGroupsFlee(false)

    //Buildings
    call SetBuildUnit(1, 'ogre')
    call SetBuildUnit(1, 'obar')
    call SetBuildUnit(1, 'ostr')
    call SetBuildUnit(1, 'oalt')
    call SetBuildUnit(1, 'osld')
    call SetBuildUnit(1, 'ofor')
    call SetBuildUnit(4, 'otrb')

    //Defenders
    call CampaignDefenderEx(3, 3, 3, 'ogru')
    call CampaignDefenderEx(2, 2, 2, 'ohun')
    call CampaignDefenderEx(1, 1, 1, 'oshm')

    //*** WAVE 1: 7 minutes ***
    call Sleep(M7)
    call InitAssaultGroup()
    call CampaignAttackerEx(2, 2, 2, 'ogru')
    call CampaignAttackerEx(1, 1, 1, 'ohun')
    call CampaignAttackerEx(1, 1, 1, 'oshm')
    call SuicideOnPlayer(M4, user)

    //*** WAVE 2: 11 minutes ***
    call Sleep(M4)
    call InitAssaultGroup()
    call CampaignAttackerEx(1, 1, 1, GUTHRIL)
    call CampaignAttackerEx(2, 2, 2, 'ogru')
    call CampaignAttackerEx(2, 2, 2, 'ohun')
    call SuicideOnPlayer(M4, user)

    //*** WAVE 3: 15 minutes ***
    call Sleep(M4)
    call InitAssaultGroup()
    call CampaignAttackerEx(3, 3, 3, 'ogru')
    call CampaignAttackerEx(3, 3, 3, 'ohun')
    call SuicideOnPlayer(M4, user)

    //*** WAVE 4: 19 minutes ***
    call Sleep(M4)
    call InitAssaultGroup()
    call CampaignAttackerEx(1, 1, 1, GUTHRIL)
    call CampaignAttackerEx(3, 3, 3, 'ogru')
    call CampaignAttackerEx(1, 1, 1, 'ohun')
    call CampaignAttackerEx(1, 1, 1, 'oshm')
    call SuicideOnPlayer(M4, user)

    loop
        //*** WAVE 5+: repeating ***
        call Sleep(M4)
        call InitAssaultGroup()
        call CampaignAttackerEx(3, 3, 3, 'ogru')
        call CampaignAttackerEx(3, 3, 3, 'ohun')
        call CampaignAttackerEx(2, 2, 2, 'oshm')
        call SuicideOnPlayer(M4, user)
    endloop

endfunction
 
And it still does nothing?
Yeah. I tested it again in both the editor and from in-game and nothing. The only thing I'm thinking could be the issue is no call WaitforSignal() but I don't think I need that unless I'm waiting for something to occur which would activate the AI (and since it is launching from Map Init that wouldn't be necessary).
 
Hmm, try removing "call DoCampaignFarms(false)", and another thing worth trying is adding the peons in the build order, it might be just stubborn and gets stuck because it can't build without peons, add at least 1 before the line that calls to build the great hall
Finally, I'm not sure those "call Sleep(M7)" are necessary, at least I don't recall seeing them in Blizzard scripts for attack waves
 
Hmm, try removing "call DoCampaignFarms(false)", and another thing worth trying is adding the peons in the build order, it might be just stubborn and gets stuck because it can't build without peons, add at least 1 before the line that calls to build the great hall
Finally, I'm not sure those "call Sleep(M7)" are necessary, at least I don't recall seeing them in Blizzard scripts for attack waves
I tried both but still nothing. What I'm wondering is whether I actually need to port the common.ai file into my script, since it might not recognize language like "M4" by itself, but I thought that it would be able to refer to it in the engine itself. That's kinda similar to what you pointed out with the unknown tags, but I never saw any guide saying "you must always port common.ai at the top of any AI you write"

As for Sleep, I have the first because I want the first attack to start at the 7th minute rather than waiting on any particular signal triggering WaitforSignal, which is what Blizzard does afaik. Ig I don't need the ones after it, but the first is intentional.

Edit: This might be a cause, but in my trigger I am importing it as a campaignAI. I don't think it is, but I don't have the experience to be able to say what the difference between importing as campaign vs. melee AI is on a technical/functional level.
1775522623893.png
 
I can guarantee you don't need to port common.ai, it's already baked in, so you can use M1 M2 etc without prior setup

If you do this "call SuicideOnPlayer(M7, user)" in the first attack wave, it should wait until 7 minutes (give or take) before attacking anyway, that's why I wouldn't bother with Sleeps

In your case I'd import it as campaign AI anyway, although it wouldn't make such a big difference as in not running at all. Last thing I can think of is starting the AI after time elapsed = 1 second instead of map init, who knows...

Oh one last thing, if I'm not mistaken "player user = PlayerEx(0)" may be problematic, IIRC when you use Player you need to offset the number by 1 (so Player(0) is player 1 red), but not with PlayerEx (where PlayerEx(1) = player 1 red), I'd address that too
 
I can guarantee you don't need to port common.ai, it's already baked in, so you can use M1 M2 etc without prior setup

If you do this "call SuicideOnPlayer(M7, user)" in the first attack wave, it should wait until 7 minutes (give or take) before attacking anyway, that's why I wouldn't bother with Sleeps

In your case I'd import it as campaign AI anyway, although it wouldn't make such a big difference as in not running at all. Last thing I can think of is starting the AI after time elapsed = 1 second instead of map init, who knows...

Oh one last thing, if I'm not mistaken "player user = PlayerEx(0)" may be problematic, IIRC when you use Player you need to offset the number by 1 (so Player(0) is player 1 red), but not with PlayerEx (where PlayerEx(1) = player 1 red), I'd address that too
I just gave all these a shot but still not working :/ I did a test run without the hero part to see if it was the hero messing it up but still nothing. I'm really at a loss here since this looks just like the Blizzard scripts. I've even reimported the files just in case something wasn't working there. Quite confusing innit.
 
(I also ran into other a few other bugs like the UI showing as undead instead of human when launched from in the game but that's another unrelated problem).
This is exactly the problem. AI does not work for non-computer players. To fix this, check "Use Custom Forces" and "Fixed Player Settings" under Scenario > Force Properties.
 
Back
Top