• 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.

JASS - Complete noob needs help

Level 4
Joined
Aug 8, 2019
Messages
37
THIS POST WAS MOVED HERE. Someone told me to post in this forum instead of "Programming"

I am learning JASS to make a campaign. I've watched/read a couple of tutorials and I started by making a VERY simple AI, just to dip my toe. However, I can't get it to work. I need 3 things from it:
Slow gathering
2 workers on trees, 3 on gold
An attack wave of 10 custom units every 2 minutes on Player 1

When I import and give the AI to a computer, with Fixed Player Settings turned on, I can tell the Script is not runing, simply because slow gathering is not active.
Can anyone help a noob? Thank you
 

Attachments

  • Captura.PNG
    Captura.PNG
    34.1 KB · Views: 18
Level 30
Joined
Aug 29, 2012
Messages
1,382
I can see two issues I think

First in your integer declarations, you only need the first part, e.g.

JASS:
integer HALBERDIER = "h600"

What's after the colon is just the unit that serves as a base, your code doesn't need it

Second, this line

JASS:
call CampaignAI(ESTFARM, null)

One of the quirks is that using a custom building doesn't work for reasons beyond my comprehension, so you need to use one of the defaults, e.g. HOUSE

It doesn't seem to have any importance though, your workers can still build custom farms when ordered to, it's just this one function in particular that acts this way
 
Level 45
Joined
Feb 27, 2007
Messages
5,578
Someone told me to post in this forum instead of "Programming"
For context, Programming is for literally everything else that isn't wc3-related code. By far the 2 most active and appropriate places to post are here in the WEHZ and T&S.
Here you can talk freely about programming languages outside of the Blizzard universe. Talk about languages, ask for help or just show off. This is the right place for you.
 
Level 4
Joined
Aug 8, 2019
Messages
37
I can see two issues I think

First in your integer declarations, you only need the first part, e.g.

JASS:
integer HALBERDIER = "h600"

What's after the colon is just the unit that serves as a base, your code doesn't need it

Second, this line

JASS:
call CampaignAI(ESTFARM, null)

One of the quirks is that using a custom building doesn't work for reasons beyond my comprehension, so you need to use one of the defaults, e.g. HOUSE

It doesn't seem to have any importance though, your workers can still build custom farms when ordered to, it's just this one function in particular that acts this way
Thank you for the corrections. I changed what you mentioned (attachment 1) but it is still not working.
- Slow Gathering is not working
- The peasants are all going to the mine
- No attack waves
- etc. (simply put, the AI is not beign used)

Maybe my triggers are wrong? Second attachment.
Thanks!
 

Attachments

  • 1741442956231.png
    1741442956231.png
    33.5 KB · Views: 8
  • 1741442986941.png
    1741442986941.png
    24.9 KB · Views: 8
Level 4
Joined
Aug 8, 2019
Messages
37
I type the script and gave it to my syntax checker and apparently CampaignAttacker is the problem, try
JASS:
CampaignAttackerEx(10,10,10, HALBERDIER)

Should be the same result anyway
Part of it is working right now, thank you so much.
-Slow Harvest works
It is still sending all custom workers to the mine, though, instead of 3 to gold and 2 to lumber. And the attack wave work weirdly. It is not suiciding on Player 1 Red. Instead, they send all 10 halberdier to fight creep camps. Once they have killed the creep camps, the go back to their base. The timer is also off. The waves should attack every 2 minutes, but they take around 6 before they start moving out.
Thanks for help me getting it started, at least.

EDIT: Player 1 is marked as neutral. Maybe that is why they don't suicide on it?
 
Level 28
Joined
Dec 3, 2020
Messages
970
1741447611750.png


this function accepts only 1 integer inside the brackets
for what reason have you put (1, 3) ???
if you want 3 workers on gold then do -> call HarvestGold(3)

I'm not trying to be mean but you would not have this written incorrectly if you took a minute to open the JASS documentation and searched for the HarvestGold function and saw how it works.
 
Level 4
Joined
Aug 8, 2019
Messages
37
View attachment 516653

this function accepts only 1 integer inside the brackets
for what reason have you put (1, 3) ???
if you want 3 workers on gold then do -> call HarvestGold(3)

I'm not trying to be mean but you would not have this written incorrectly if you took a minute to open the JASS documentation and searched for the HarvestGold function and saw how it works.
Don't worry about sounding mean, I get it. I wrote 2 numbers because when I use JassCraft it tells me that the first number is "integer town" and the second one is peons. I found online that someone used it like I did, so I copied that, basically. I'll try to change it and see if it works. Btw, where are these JASS documents? Do they come with JassCraft?

Thanks!
 
Level 28
Joined
Dec 3, 2020
Messages
970
Don't worry about sounding mean, I get it. I wrote 2 numbers because when I use JassCraft it tells me that the first number is "integer town" and the second one is peons. I found online that someone used it like I did, so I copied that, basically. I'll try to change it and see if it works. Btw, where are these JASS documents? Do they come with JassCraft?

Thanks!

I understand why you actually got confused.
1741448500003.png

It says it has 2 parameters, but in reality you just need to put how many "peons" (workers) you want to be harvesting gold (same for lumber) for a basic AI that will have 1 base, as is the case in basically every single AI you'll write for campaigns. (if you want the AI to have an "outpost" then it's better to make it a different player).

I assume you'd need to put the integer of the "town" when the AI has an an actual expansion. Perhaps you'd want it to have 5 peons harvesting gold in the main base, but only 3 in the expansion. This is out of my reach and I cannot tell you how to do that. Perhaps if you take a look at the melee AI you might figure it out.

I recommend writing simple AI like Blizzard did for the campaigns. As a matter of fact, just look at how the scripts were written for the campaigns. It's a good start.

EDIT:

also, I just took a look and you should use this -> SetGoldPeons(3)
NOT HarvestGold(integer town, integer peons).

Use SetGoldPeons(integer count)
 
Level 4
Joined
Aug 8, 2019
Messages
37
View attachment 516653

this function accepts only 1 integer inside the brackets
for what reason have you put (1, 3) ???
if you want 3 workers on gold then do -> call HarvestGold(3)

I'm not trying to be mean but you would not have this written incorrectly if you took a minute to open the JASS documentation and searched for the HarvestGold function and saw how it works.
UPDATE:
I tried taking the first number out, but the script just does not work without it. I mean the WHOLE script. No slow harvest no waves, nothing. I guess it does need that number there, but I just can't get it to do what I need.
 
Level 28
Joined
Dec 3, 2020
Messages
970
UPDATE:
I tried taking the first number out, but the script just does not work without it. I mean the WHOLE script. No slow harvest no waves, nothing. I guess it does need that number there, but I just can't get it to do what I need.
Sorry, I just looked it up (this will work for sure):

set campaign_gold_peons = 2
set campaign_wood_peons = 2

These work for sure since I use them in scripts that I use in my maps!

EDIT: this is where I place it ->
1741449254143.png
 
Last edited:
Level 4
Joined
Aug 8, 2019
Messages
37
Sorry, I just looked it up (this will work for sure):

set campaign_gold_peons = 2
set campaign_wood_peons = 2

These work for sure since I use them in scripts that I use in my maps!

EDIT: this is where I place it ->
View attachment 516655
I really appreciate all your help.
I can't get those to work with JassCraft.
1741449966169.png

The whole script stops working if I add those. I also could not found those functions on the manual you linked (thanks for that, btw, but I can't make heads or tails of it, I wished each function explained what it does)
 
Level 28
Joined
Dec 3, 2020
Messages
970
I really appreciate all your help.
I can't get those to work with JassCraft.
View attachment 516656
The whole script stops working if I add those. I also could not found those functions on the manual you linked (thanks for that, btw, but I can't make heads or tails of it, I wished each function explained what it does)
Uh, I honestly have no clue about JassCraft, I write my scripts in a notepad lol
Code:
//============================================================================
//  Human 04 -- green player -- AI Script
//============================================================================

globals
    player user = Player(1)
endglobals

//============================================================================
//  main
//============================================================================
function main takes nothing returns nothing

    call CampaignAI(ZIGGURAT_1,null)
    set campaign_wood_peons = 2
    call SetReplacements(1,1,3)

    call SetBuildUnitEx( 1,1,1, ACOLYTE           )
    call SetBuildUnitEx( 0,0,1, NECROPOLIS_1      )
    call SetBuildUnitEx( 0,0,1, CRYPT             )
    call SetBuildUnitEx( 0,0,1, GRAVEYARD         )
    call SetBuildUnitEx( 0,0,6, ZIGGURAT_1        )
    call SetBuildUnitEx( 0,0,1, NECROPOLIS_2      )
    call SetBuildUnitEx( 0,0,6, ZIGGURAT_2        )
    call SetBuildUnitEx( 5,5,5, ACOLYTE           )

    call CampaignDefenderEx (1,1,3, GHOUL    )
    call CampaignDefenderEx (0,0,2, NECRO    )

    call WaitForSignal()

    // *** WAVE 1 ***
    call InitAssaultGroup()
    call CampaignAttackerEx( 3,3,6, GHOUL   )
    call CampaignAttackerEx( 0,0,1, NECRO   )
    call SuicideOnPlayerEx(M5,M5,M1,user)

    call SetBuildUpgrEx( 0,0,1, UPG_CANNIBALIZE )
    call SetBuildUpgrEx( 0,0,1, UPG_SKEL_LIFE   )

    // *** WAVE 2 ***
    call InitAssaultGroup()
    call CampaignAttackerEx( 4,4,7, GHOUL    )
    call CampaignAttackerEx( 0,0,2, NECRO   )
    call SuicideOnPlayerEx(M6,M6,M3,user)

    call SetBuildUpgrEx( 0,0,1, UPG_UNHOLY_STR  )

    // *** WAVE 3 ***
    call InitAssaultGroup()
    call CampaignAttackerEx( 1,1,12, GHOUL    )
    call CampaignAttackerEx( 2,2,0, NECRO    )
    call SuicideOnPlayerEx(M5,M5,M3,user)

    call SetBuildUpgrEx( 0,0,1, UPG_NECROS        )
    call SetBuildUpgrEx( 0,0,1, UPG_UNHOLY_ARMOR)

    // *** WAVE 4 ***
    call InitAssaultGroup()
    call CampaignAttackerEx( 5,5,2, GHOUL   )
    call CampaignAttackerEx( 0,0,6, NECRO   )
    call SuicideOnPlayerEx(M5,M5,M4,user)

    call SetBuildUpgrEx( 0,0,2, UPG_UNHOLY_STR  )

    // *** WAVE 5 ***
    call InitAssaultGroup()
    call CampaignAttackerEx( 3,3,12, GHOUL  )
    call CampaignAttackerEx( 2,2,2, NECRO   )
    call SuicideOnPlayerEx(M6,M6,M3,user)

    call SetBuildUpgrEx( 0,0,2, UPG_UNHOLY_ARMOR)

    loop
        // *** WAVE 6+ ***
        call InitAssaultGroup()
        call CampaignAttackerEx( 6,6,6, GHOUL   )
        call CampaignAttackerEx( 0,0,6, NECRO   )
        call SuicideOnPlayerEx(M5,M5,M4,user)

        // *** WAVE 7+ ***
        call InitAssaultGroup()
        call CampaignAttackerEx( 4,4,12, GHOUL    )
        call CampaignAttackerEx( 2,2,2, NECRO    )
        call SuicideOnPlayerEx(M6,M6,M3,user)
    endloop
endfunction

This is the exact script used on the 4th human reign of chaos mission by the green undead base, the one guarding the entrance to Andorhal.
"set campaign_wood_peons = 2" is used in it and it works perfectly.
I suggest using an already existing script like this one and adapting it to your needs. And before using any fancy tools, just write the code in notepad or a text editor and make sure it works.
I find it hard to believe that the script does not work because of that (set campaign_wood_peons = 2), but I cannot be certain, since JassCraft might be somehow against it (again, I have 0 clue about JassCraft or what it is and what it does), but I can guarantee you that this script works since it is directly extracted from the game files and has not been touched by me in any way.
 
Level 30
Joined
Aug 29, 2012
Messages
1,382
About your attack wave issue, remember that player numbers are offset by 1 between code and world editor. Player 0 in code is actually player 1 (red) in the editor, so in your case they're ordered to attack player 23 (emerald), and if there is no such player, they attack randomly toward players they're not allied with
 
Level 4
Joined
Aug 8, 2019
Messages
37
Uh, I honestly have no clue about JassCraft, I write my scripts in a notepad lol
Code:
//============================================================================
//  Human 04 -- green player -- AI Script
//============================================================================

globals
    player user = Player(1)
endglobals

//============================================================================
//  main
//============================================================================
function main takes nothing returns nothing

    call CampaignAI(ZIGGURAT_1,null)
    set campaign_wood_peons = 2
    call SetReplacements(1,1,3)

    call SetBuildUnitEx( 1,1,1, ACOLYTE           )
    call SetBuildUnitEx( 0,0,1, NECROPOLIS_1      )
    call SetBuildUnitEx( 0,0,1, CRYPT             )
    call SetBuildUnitEx( 0,0,1, GRAVEYARD         )
    call SetBuildUnitEx( 0,0,6, ZIGGURAT_1        )
    call SetBuildUnitEx( 0,0,1, NECROPOLIS_2      )
    call SetBuildUnitEx( 0,0,6, ZIGGURAT_2        )
    call SetBuildUnitEx( 5,5,5, ACOLYTE           )

    call CampaignDefenderEx (1,1,3, GHOUL    )
    call CampaignDefenderEx (0,0,2, NECRO    )

    call WaitForSignal()

    // *** WAVE 1 ***
    call InitAssaultGroup()
    call CampaignAttackerEx( 3,3,6, GHOUL   )
    call CampaignAttackerEx( 0,0,1, NECRO   )
    call SuicideOnPlayerEx(M5,M5,M1,user)

    call SetBuildUpgrEx( 0,0,1, UPG_CANNIBALIZE )
    call SetBuildUpgrEx( 0,0,1, UPG_SKEL_LIFE   )

    // *** WAVE 2 ***
    call InitAssaultGroup()
    call CampaignAttackerEx( 4,4,7, GHOUL    )
    call CampaignAttackerEx( 0,0,2, NECRO   )
    call SuicideOnPlayerEx(M6,M6,M3,user)

    call SetBuildUpgrEx( 0,0,1, UPG_UNHOLY_STR  )

    // *** WAVE 3 ***
    call InitAssaultGroup()
    call CampaignAttackerEx( 1,1,12, GHOUL    )
    call CampaignAttackerEx( 2,2,0, NECRO    )
    call SuicideOnPlayerEx(M5,M5,M3,user)

    call SetBuildUpgrEx( 0,0,1, UPG_NECROS        )
    call SetBuildUpgrEx( 0,0,1, UPG_UNHOLY_ARMOR)

    // *** WAVE 4 ***
    call InitAssaultGroup()
    call CampaignAttackerEx( 5,5,2, GHOUL   )
    call CampaignAttackerEx( 0,0,6, NECRO   )
    call SuicideOnPlayerEx(M5,M5,M4,user)

    call SetBuildUpgrEx( 0,0,2, UPG_UNHOLY_STR  )

    // *** WAVE 5 ***
    call InitAssaultGroup()
    call CampaignAttackerEx( 3,3,12, GHOUL  )
    call CampaignAttackerEx( 2,2,2, NECRO   )
    call SuicideOnPlayerEx(M6,M6,M3,user)

    call SetBuildUpgrEx( 0,0,2, UPG_UNHOLY_ARMOR)

    loop
        // *** WAVE 6+ ***
        call InitAssaultGroup()
        call CampaignAttackerEx( 6,6,6, GHOUL   )
        call CampaignAttackerEx( 0,0,6, NECRO   )
        call SuicideOnPlayerEx(M5,M5,M4,user)

        // *** WAVE 7+ ***
        call InitAssaultGroup()
        call CampaignAttackerEx( 4,4,12, GHOUL    )
        call CampaignAttackerEx( 2,2,2, NECRO    )
        call SuicideOnPlayerEx(M6,M6,M3,user)
    endloop
endfunction

This is the exact script used on the 4th human reign of chaos mission by the green undead base, the one guarding the entrance to Andorhal.
"set campaign_wood_peons = 2" is used in it and it works perfectly.
I suggest using an already existing script like this one and adapting it to your needs. And before using any fancy tools, just write the code in notepad or a text editor and make sure it works.
I find it hard to believe that the script does not work because of that (set campaign_wood_peons = 2), but I cannot be certain, since JassCraft might be somehow against it (again, I have 0 clue about JassCraft or what it is and what it does), but I can guarantee you that this script works since it is directly extracted from the game files and has not been touched by me in any way.
You are helping me progress!

I got it to work, kinda. Now it is sending 1 peasant to harvest wood, and the other 4 to harvest gold. Don't know why. If I can't fix it, I'll just leave it as is. It's all for show anyway, since I'll give the computer the resources it needs through triggers.
 
Level 28
Joined
Dec 3, 2020
Messages
970
You are helping me progress!

I got it to work, kinda. Now it is sending 1 peasant to harvest wood, and the other 4 to harvest gold. Don't know why. If I can't fix it, I'll just leave it as is. It's all for show anyway, since I'll give the computer the resources it needs through triggers.
add -> set campaign_gold_peons = 3
on the line above or below -> set campaign_wood_peons = 2
 
Level 4
Joined
Aug 8, 2019
Messages
37
I got it to work. I just place the peasants farther from the base so that the AI would not immediatly send them to the mines. Thank you all!
 
Level 4
Joined
Aug 8, 2019
Messages
37
Since you all have been so useful, I have another question. How do I break out of the loop when a signal is sent? I want the waves to stop (and new ones to start) when a quest is completed. Can I just use "waitforsignal" and send the same signal again?
 
Level 45
Joined
Feb 27, 2007
Messages
5,578
I can't answer that as am not familiar with AI, but the way you would break a loop in jass is the exitwhen keyword followed by the boolean true like: exitwhen true. The other thing to add is that you can post jass code here directly with formatting using the code tags like this (to avoid screenshots):

[code=jass]
function somefunc takes nothing returns nothing
call Boo()
call Home()
endfunction
[/code]
 
Level 4
Joined
Aug 8, 2019
Messages
37
I can't answer that as am not familiar with AI, but the way you would break a loop in jass is the exitwhen keyword followed by the boolean true like: exitwhen true. The other thing to add is that you can post jass code here directly with formatting using the code tags like this (to avoid screenshots):

[code=jass]
function somefunc takes nothing returns nothing
call Boo()
call Home()
endfunction
[/code]
I think I get the idea, but there should be something else, right? Like:

Exitwhen SOMETHING = true

Isn't that so? I want to find that if that SOMETHING can be an AI Command from a trigger, aka a signal, and how to write it. If not, what CAN I write?

Thanks!
 
Level 45
Joined
Feb 27, 2007
Messages
5,578
Well what comes after the exitwhen is a boolean. True and false are both boolean values. Comparing another value to see if it's equal to true is the same thing as just asking what the value is, so it's kind of redundant. 'Normally' something like:
JASS:
exitwhen checkIfEndHappens() //a function that returns a boolean
exitwhen TimerGetElapsed(t)>2.0
exitwhen (i > N) or (SomeVal[i] == 0) //comparing multiple things
exitwhen true //always exit when this line is hit
exitwhen false //a truly redundant statement that will never exit anything
In this instance you might compare something that is happening over the loop or break the loop manually with an exitwhen true or neither of those things because they're irrelevant. I don't know.
 
Level 4
Joined
Aug 8, 2019
Messages
37
Well what comes after the exitwhen is a boolean. True and false are both boolean values. Comparing another value to see if it's equal to true is the same thing as just asking what the value is, so it's kind of redundant. 'Normally' something like:
JASS:
exitwhen checkIfEndHappens() //a function that returns a boolean
exitwhen TimerGetElapsed(t)>2.0
exitwhen (i > N) or (SomeVal[i] == 0) //comparing multiple things
exitwhen true //always exit when this line is hit
exitwhen false //a truly redundant statement that will never exit anything
In this instance you might compare something that is happening over the loop or break the loop manually with an exitwhen true or neither of those things because they're irrelevant. I don't know.
Thanks. I guess I'll have to find out how to write a check for a quest completed and use the first example you gave.
 
Top