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

simple JASS script help

Status
Not open for further replies.
Level 8
Joined
Dec 29, 2006
Messages
359
So, i just started learning JASS, so im still not an expert at recognizing my mistakes like syntax errors and such. This script that im using is for a tower defense, and it compares the clicked dialog button with the StageOne dialog button, and if the clicked button was the StageOne button, it pans the camera to the center of the stage, limits the camera bounds to that stage, then creates the builder for the player. Or rather, thats what it should do. I cant seem to put my finger on the error(s) that is/are making this code not work.

So i ask: could someone point out my errors and tell me what i SHOULD have done?

JASS:
function WhichButton takes nothing returns integer 
    if(GetClickedButton() == udg_StageOne) then
        return 1
    endif
    return 1
endfunction

function GameStart takes nothing returns nothing
    if WhichButton == 1 then 
     set udg_Stage = gg_rct_Stage_1
     set udg_loc = GetRectCenter(udg_Stage)
     local rect r = udg_Stage
     local location x = GetLocationX(udg_loc)
     local location y = GetLocationY(udg_loc)
        call PanCameraTo(x, y)
        call SetCameraBoundsToRect(r)
        call CreateUnitAtLoc(Player(1), u000:uaco, udg_loc, 270.0)
        call DisplayTimedTextToPlayer(Player(1), x, y, 5.00, "Welcome to Xzife Tower Defense! This is a solo tower defense coded entirely in JASS script. There is currently 1 stage, and the game is in the very early Alpha stage of development.")
        call KillUnit(Peasant 0000)
     r = null  
     x = null
     y = null
endfunction
        
//=============================================================
function Init_Trig_Start_Game takes nothing returns nothing
 local trigger gamestart = CreateTrigger()
    call TriggerRegisterDialogButtonEvent(gamestart, udg_StageOne)
    call TriggerAddAction(gamestart, function WhichButton)
    call TriggerAddAction(gamestart, function GameStart)
 set gamestart = null
endfunction
 
Level 8
Joined
Aug 4, 2006
Messages
357
okay, several simple problems here. let's see...

JASS:
function WhichButton takes nothing returns integer 
    if(GetClickedButton() == udg_StageOne) then
        return 1
    endif
    return 1
endfunction
//this function always returns 1, even if the clicked button is not stage one! there is a better way to make this a condition

function GameStart takes nothing returns nothing
    if WhichButton == 1 then 
     set udg_Stage = gg_rct_Stage_1
     set udg_loc = GetRectCenter(udg_Stage)
//unnecessary location variable, but not a big deal (see my solution below)
     local rect r = udg_Stage
     local location x = GetLocationX(udg_loc)
     local location y = GetLocationY(udg_loc)
//all locals need to be declared at the beginning of the function
//also, you want x and y to be real variables since x and y coordinates are numbers and not points.
        call PanCameraTo(x, y)
        call SetCameraBoundsToRect(r)
        call CreateUnitAtLoc(Player(1), u000:uaco, udg_loc, 270.0)
//bad syntax for the unit type
        call DisplayTimedTextToPlayer(Player(1), x, y, 5.00, "Welcome to Xzife Tower Defense! This is a solo tower defense coded entirely in JASS script. There is currently 1 stage, and the game is in the very early Alpha stage of development.")
//Player(1) is blue, Player(0) is red. not sure which you meant to use
        call KillUnit(Peasant 0000)
//you need to create a new trigger, make a GUI action to kill "Peasant 0000," convert it to JASS, and then paste the variable name of that peasant in place of "Peasant 0000"
     r = null  
     x = null
     y = null
endfunction
        
//=============================================================
function Init_Trig_Start_Game takes nothing returns nothing
 local trigger gamestart = CreateTrigger()
    call TriggerRegisterDialogButtonEvent(gamestart, udg_StageOne)
    call TriggerAddAction(gamestart, function WhichButton)
    call TriggerAddAction(gamestart, function GameStart)
 set gamestart = null
//you don't need to null triggers, but not a big deal.
endfunction

ok here's my solution:
JASS:
function isStageOneButton takes nothing returns boolean
    return (GetClickedButton() == udg_StageOne)
endfunction

function GameStart takes nothing returns nothing
    local real x
    local real y
    set udg_Stage = gg_rct_Stage_1
    set x = GetRectCenterX(udg_Stage)
    set y = GetRectCenterY(udg_Stage)
    call PanCameraTo(x, y)
    call SetCameraBoundsToRect(udg_Stage)
    call CreateUnit(Player(0), 'u000', x, y, 270.0)
    call DisplayTimedTextToPlayer(Player(0), x, y, 5.00, "Welcome to Xzife Tower Defense! This is a solo tower defense coded entirely in JASS script. There is currently 1 stage, and the game is in the very early Alpha stage of development.")
    call KillUnit(gg_unit_hpea_0000)
endfunction
        
//=============================================================
function Init_Trig_Start_Game takes nothing returns nothing
     local trigger gamestart = CreateTrigger()
     call TriggerRegisterDialogButtonEvent(gamestart, udg_StageOne)
     call TriggerAddCondition(gamestart, Condition(function isStageOneButton))
     call TriggerAddAction(gamestart, function GameStart)
endfunction
 
Level 16
Joined
Oct 12, 2008
Messages
1,570
Well, first,, That first function:
Whatever it is, it will always return 1! Shouldnt it return something else under the if/then/else? Or something else after the if/then/else? Cuz now it is always 1!

Then. if WhichButton() == 1 then You call a function for it, so it has to has () behind it.

Then, Locals can only be declared at the top of the function. You declare 2 local locations, and you give them a real value (real = number with decimals),,

PanCameraTo() takes 2 reals, you tried to create them, but, as stated above, you named them locations. Change it to real.

In the CreateUnitAtLoc(....) you have: u000:uaco

That is wrong. In Object editor, the value behind the ':' is an indication of what unit u based it off. but do NOT use it in code, just use the 'u000'

call KillUnit(Peasant 0000) is also wrong. the 'Peasant 0000' is the name that Warcraft gives that peasant in WE,
But it actually has an other code. Try to make a GUI trigger that kills the unit, convert it to JASS (Edit>Convert to custom text) then you will see the real code of the unit.

Last, you forgot the 'endif', but as WhichButton() always returns 1, it is not needed.

<Above code should work>
 
Level 8
Joined
Dec 29, 2006
Messages
359
oh ya, i probably should mention that the reason i tried to make function WhichButton return an integer instead of a boolean is because i plan to have more than one stage, but only have a single stage at this point. So later the code will include buttons StageOne, StageTwo, StageThree, etc up to five. What would be the best way to make a function that reads which button is pressed?
 
Level 16
Joined
Oct 12, 2008
Messages
1,570
JASS:
function isStageOneButton takes nothing returns integer
    if GetClickedButton() == udg_StageOne then
        return 1
    elseif GetClickedButton() == udg_StageTwo then
        return 2
    elseif GetClickedButton() == udg_StageThree then
        // until you reach the 5
    endif
    return 0
endfunction
 
function GameStart takes nothing returns nothing
    local real x
    local real y
    set udg_Stage = gg_rct_Stage_1
    // i think there will be a big if/then/else to chech which area?
    // then this is ok,,
    set x = GetRectCenterX(udg_Stage)
    set y = GetRectCenterY(udg_Stage)
    call PanCameraTo(x, y)
    call SetCameraBoundsToRect(udg_Stage)
    call CreateUnit(Player(0), 'u000', x, y, 270.0)
    call DisplayTimedTextToPlayer(Player(0), x, y, 5.00, "Welcome to Xzife Tower Defense! This is a solo tower defense coded entirely in JASS script. There is currently 1 stage, and the game is in the very early Alpha stage of development.")
    call KillUnit(gg_unit_hpea_0000)
endfunction
 
//=============================================================
function Init_Trig_Start_Game takes nothing returns nothing
     local trigger gamestart = CreateTrigger()
     call TriggerRegisterDialogButtonEvent(gamestart, udg_StageOne)
     call TriggerAddCondition(gamestart, Condition(function isStageOneButton))
     call TriggerAddAction(gamestart, function GameStart)
endfunction

Should be working,,
That will return the 'number' of the stage,,

BTW: I took maskedpoptart's function, since it is clean and good,,
 
Level 8
Joined
Aug 4, 2006
Messages
357
hmm i kind of missed a mistake. anyway, here's how i would make what you want:
JASS:
function GameStart takes nothing returns nothing
    local real x
    local real y
    local button clickedButton = GetClickedButton()
    if (clickedButton == udg_StageOne) then
        set udg_Stage = gg_rct_Stage_1
    elseif (clickedButton == udg_StageTwo) then
        set udg_Stage = gg_rct_Stage_2
    elseif (clickedButton == udg_StageThree) then
         set udg_Stage = gg_rct_Stage_3
    elseif (clickedButton == udg_StageFour) then
         set udg_Stage = gg_rct_Stage_4
    else
         set udg_Stage = gg_rct_Stage_5
    endif
    set x = GetRectCenterX(udg_Stage)
    set y = GetRectCenterY(udg_Stage)
    call PanCameraTo(x, y)
    call SetCameraBoundsToRect(udg_Stage)
    call CreateUnit(Player(0), 'u000', x, y, 270.0)
    call DisplayTimedTextToPlayer(Player(0), x, y, 5.00, "Welcome to Xzife Tower Defense! This is a solo tower defense coded entirely in JASS script. There is currently 1 stage, and the game is in the very early Alpha stage of development.")
    call KillUnit(gg_unit_hpea_0000)
endfunction
 
//=============================================================
function Init_Trig_Start_Game takes nothing returns nothing
     local trigger gamestart = CreateTrigger()
     call TriggerRegisterDialogButtonEvent(gamestart, udg_StageDialog)
  //i replaced udg_StageOne with udg_StageDialog because the second parameter needs to be a dialog window, not a dialog button. I am not sure what you named your dialog window, but you should put that as the second parameter
     call TriggerAddAction(gamestart, function GameStart)
endfunction
 
Level 8
Joined
Dec 29, 2006
Messages
359
lol now that you guys pointed my errors out im wondering how i didnt catch some of em. Either way, you were both very helpful, thanks and +rep :D
 
Level 8
Joined
Dec 29, 2006
Messages
359
i just got a chance to try the script. For whatever reason, im getting a message that says, invalid argument type (dialog), on the second to last line of the code. The one that has the "call TriggerAddAction(gamestart, function GameStart)" What does that mean and how do i fix it?

Oh also, i didnt use jass tags cuz my internet is horrible atm and i wrote this reply with the quick reply thing at the bottom.
 
Level 8
Joined
Dec 29, 2006
Messages
359
i changed the name of the dialog where u pick a stage to StageDialog, to fit your script, idk if im just not catching it or something, but why do i need a global dialog variable called GameStart?
 
Level 8
Joined
Aug 4, 2006
Messages
357
why do i need a global dialog variable called GameStart?

you don't. in fact, you shouldn't have one. the only reason i said "do you have a global dialog variable called "GameStart" or "gamestart"?" is because that is what could have been causing the error message.

SWEET! i just found the problem. change the last part to this:
JASS:
function InitTrig_Start_Game takes nothing returns nothing
    local trigger gamestart = CreateTrigger()
    call TriggerRegisterDialogEvent(gamestart, udg_StageDialog)
    call TriggerAddAction(gamestart, function GameStart)
endfunction
i forgot to change the event registration to TriggerRegisterDialogEvent instead of TriggerRegisterDialogButtonEvent. we need this event because we want the trigger to execute whenever ANY button is clicked for the StageDialog. also, you should change the function name to "InitTrig_..." instead of "Init_Trig_..." so that warcraft knows to execute this function on initialization.
 
Level 8
Joined
Dec 29, 2006
Messages
359
there is one final problem, for whatever reason, the text is not being displayed. The camera is being panned just fine, the unit is being spawned, and the peasant is killed, but its as though the function for displaying the text was completely skipped.
 
Level 16
Joined
Oct 12, 2008
Messages
1,570
try to do: call DisplayTimedTextToPlayer(Player(0),0,0,5, "Your Text")

That should work. Because the 'x' and 'y' you put there, are coordinates of the screen not on the map. And idk exactly from what range they go, but not that far at least,, Just try with 0,0
 
Level 8
Joined
Dec 29, 2006
Messages
359
Simple enough solution, text works fine. I noticed one other thing, idk if its supposed to do this or not but, it seems to me that since the camera pan and the unit creation functions use the same real values for the location, the camera should be centered on the unit when it is done panning, for whatever reason, the camera ends up in the upper-left section of the region. Is that supposed to happen?

Additionally, i tried making a visibility modifier for the stage using
call CreateFogModifierRect(Player(0), FOG_OF_WAR_VISIBLE, udg_Stage, true, true)
However, the area becomes fogged, not visible. The only visibility in the area was emitted from the created unit.

EDIT: Sorry to keep creating problems for u guys but i am insanely confused now.

Is this script correct?
JASS:
function MoveCondition takes nothing returns boolean
    return GetOwningPlayer(GetTriggerUnit()) == Player(11)
endfunction

function StageOneMoveOne takes nothing returns nothing 
    local real x = GetRectCenterX(gg_rct_Stage_1_Move_1)
    local real y = GetRectCenterY(gg_rct_Stage_1_Move_1)
    call IssuePointOrder(GetTriggerUnit(), "move", x, y)
endfunction

//===========================================================================
function InitTrig_S1M1 takes nothing returns nothing
    local trigger s1m1 = CreateTrigger()
    call TriggerRegisterEnterRectSimple(s1m1, gg_rct_Stage_1_Spawn)
    call TriggerAddCondition(s1m1, Condition(function MoveCondition))
    call TriggerAddAction(s1m1, function StageOneMoveOne)
endfunction
cuz normally when i have finished a script and paste it in the WE to see if it works, i will disable then re-enable the trigger, to see if it works. If it is able to be re-enabled, then that means the trigger is valid right? With this trigger, (and 4 others like it, to control the movement of creeps around stage one) it will re-enable just fine, but then have tons of errors when i try to save the map.

Also, im getting other strange errors that i have no clue what to do about, for example,
JASS:
local effect e1 = AddSpecialEffectLoc("Abilities\Spells\Undead\AnimateDead\AnimateDeadTarget.mdl", loc1)
        call DestroyEffect(e1)
set e1 = null
in this script, (theres more too it than just this, i cut out this section to save space, if you need to see the whole thing, just say so, cuz theres tons of problems with that too im sure lol) anyway, in this script, im getting an error that says i have an undeclared variable e1. But i declared it in the beginning of the script. My brain is just hurting cuz i had everything up and running fine, then I added the MoveCondition function to the movement triggers, and another trigger creating the effects and performing necessary actions when a creep reaches the end of the stage, and after I put them in, a million errors popped up, and im just overwhelmed.

On a side note, thanks for putting up with me, i know that by now i might be starting to get kind of annoying >.<
 
Last edited:
Level 8
Joined
Aug 4, 2006
Messages
357
"it seems to me that since the camera pan and the unit creation functions use the same real values for the location, the camera should be centered on the unit when it is done panning, for whatever reason, the camera ends up in the upper-left section of the region. Is that supposed to happen?"
no. i think it has something to do with the fact that we change the camera bounds before the camera is able to move into the new bounds. if you use a timed pan, and wait until the pan is done before you set the camera bounds, it seems to work (see attached map).

"Additionally, i tried making a visibility modifier for the stage using
call CreateFogModifierRect(Player(0), FOG_OF_WAR_VISIBLE, udg_Stage, true, true)
However, the area becomes fogged, not visible. The only visibility in the area was emitted from the created unit."
you need to start the fog modifier after you create it. to do this, you need to save the created fog modifier in a variable. e.g:
JASS:
set udg_StageFogModifier = CreateFogModifierRect(Player(0), FOG_OF_WAR_VISIBLE, udg_Stage, true, true)
call FogModifierStart(udg_StageFogModifier)
"Is this script correct?"
looks fine to me.

"If it is able to be re-enabled, then that means the trigger is valid right?"
not necessarily. i usually don't use the method you mentioned to check if triggers will compile. i just save the map. also, if you want a better error checker/compiler, you should get the JASS New Generation Pack (http://www.thehelper.net/forums/showthread.php?t=73936). not only will this help you to debug your JASS, but also has a code highlighter, auto-complete, and introduces new features (such as vJASS). when you feel comfortable working with JASS, you should read about some of these useful features that help to organize your code.

"Also, im getting other strange errors that i have no clue what to do about, for example,
JASS:
local effect e1 = AddSpecialEffectLoc("Abilities\Spells\Undead\AnimateDead\AnimateDeadTarget.mdl", loc1)
        call DestroyEffect(e1)
set e1 = null
"
\ is what we call an "escape character." Suppose you have a string variable that you want to contain quote marks. How do you store those quote marks without world editor thinking that you are ending the string? for example,
JASS:
set stringVar = "he said, "hello," as he walked out the door."
screws up. The answer is to put a \ before each quote mark to tell world editor that the next character should be treated as part of the string. escape characters can be used for other purposes, but I only want to discuss two here.
i've already mentioned \" which allows you to put quote marks in a string.
another combination is \\ which allows you to put \ in a string.

so the solution to your above problem is to do:
JASS:
local effect e1 = AddSpecialEffectLoc("Abilities\\Spells\\Undead\\AnimateDead\\AnimateDeadTarget.mdl", loc1)
        call DestroyEffect(e1)
set e1 = null
" i simply put a \ before every \

ok so here's a test map that i made for you, that kind of puts all this crap together.
 

Attachments

  • test.w3m
    18.6 KB · Views: 64
Level 8
Joined
Dec 29, 2006
Messages
359
sweet! thanks for making a test map, that really helped. But what does this do:
JASS:
//TESH.scrollpos=0
//TESH.alwaysfold=0
Ive never heard of these before. Am i gonna need these?
 
Level 8
Joined
Dec 29, 2006
Messages
359
Alright then. Thanks everybody for helping so much. And also thanks maskedpoptart, for posting the test map, and the link to the JASS new gen pack, its really helpful.
 
Status
Not open for further replies.
Top