• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[JASS] Dialog Triggers for Race Selection Not Working (SOLVED)

Level 1
Joined
Aug 15, 2023
Messages
2
Hi all,

I'm making a custom race (Centaur) and decided to use the classic dialog technique for the selection of the race. I've incorporated a displayed 3 second countdown (by text) that activates when everyone has selected a race or 12 seconds have passed (meaning the game will start automatically (town halls and units spawn) at 15 seconds in).

JASS:
globals
    integer udg_countdown
    boolean udg_countdownStarted
    integer udg_playerCount
    integer array udg_playerRace
    force udg_players
    button array udg_raceButton
    dialog udg_raceSelection
endglobals

function GameStart takes nothing returns nothing//***this function counts down after multiple clicks of buttons instead of from a timer???
    local timer expiredTimer
    if udg_countdown == 0 then//when timer has finished counting down then start the game
        if IsPlayerInForce(GetLocalPlayer(), udg_players) then
            call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "Game has started!")
        endif
        //will hide dialog for those who haven't selected a race
        //stuff
        //create town halls and units here
        //other stuff
        set expiredTimer = GetExpiredTimer()
        call PauseTimer(expiredTimer)//stops this timer
        call DestroyTimer(expiredTimer)
        set expiredTimer = null
    else//continue counting down if not finished
        if IsPlayerInForce(GetLocalPlayer(), udg_players) then
            call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "Game starting in " + I2S(udg_countdown) + "...")
        endif
        set udg_countdown = udg_countdown - 1
    endif
endfunction

function InitiateCountdown takes nothing returns boolean
    if udg_countdownStarted == false then//start countdown if not already started
        if IsPlayerInForce(GetLocalPlayer(), udg_players) then
            call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "Game starting in 3...")//displays text to human players
        endif
        set udg_countdown = 2
        call TimerStart(CreateTimer(), 1, true, function GameStart)//starts countdown timer***this does not work???
        set udg_countdownStarted = true
    endif
    return false
endfunction

function RaceChosen takes nothing returns boolean//***function is immediately called when dialog is shown???
    local button clickedButton = GetClickedButton()//***returns null when dialog is initially shown to players???
    local integer raceIndex = 0
    loop
        exitwhen clickedButton == udg_raceButton[raceIndex]//finds the button clicked
        set raceIndex = raceIndex + 1
    endloop
    set udg_playerRace[GetPlayerId(GetTriggerPlayer())] = raceIndex//stores the race chosen (an integer value) in a variable for later use
    set udg_playerCount = udg_playerCount - 1
    if udg_playerCount == 0 then//if all human players have clicked a button then starts countdown early
        call InitiateCountdown()
    endif
    set clickedButton = null
    return false
endfunction

function RaceSelection takes nothing returns boolean
    local player indexPlayer
    local integer playerIndex = 0
    call DialogSetMessage(udg_raceSelection, "Race Selection")//creating the dialog and buttons
    set udg_raceButton[0] = DialogAddButton(udg_raceSelection, "Random", 0)//***these buttons get added again each time a player clicks a button???
    set udg_raceButton[1] = DialogAddButton(udg_raceSelection, "Human", 0)
    set udg_raceButton[2] = DialogAddButton(udg_raceSelection, "Orc", 0)
    set udg_raceButton[3] = DialogAddButton(udg_raceSelection, "Undead", 0)
    set udg_raceButton[4] = DialogAddButton(udg_raceSelection, "Night Elf", 0)
    set udg_raceButton[5] = DialogAddButton(udg_raceSelection, "Centaur", 0)
    loop
        set indexPlayer = Player(playerIndex)
        if GetPlayerController(indexPlayer) == MAP_CONTROL_USER then
            call DialogDisplay(indexPlayer, udg_raceSelection, true)//displays dialog to all human players
            call ForceAddPlayer(udg_players, indexPlayer)//stores human players in a group
            set udg_playerCount = udg_playerCount + 1//keeps count of number of human players
        endif
        set playerIndex = playerIndex + 1
        exitwhen playerIndex > 11
    endloop
    set indexPlayer = null
    return false
endfunction

//=====================================================================================
function InitTrig_Custom_Initialisation takes nothing returns nothing
    local trigger t1 = CreateTrigger()
    local trigger t2 = t1
    local trigger t3 = t1
    call TriggerRegisterTimerEvent(t1, 0, false)
    call TriggerRegisterDialogEvent(t2, udg_raceSelection)
    call TriggerRegisterTimerEvent(t3, 12, false)
    call TriggerAddCondition(t1, Condition(function RaceSelection))//displays race selection at the start of the game
    call TriggerAddCondition(t2, Condition(function RaceChosen))//calls this function whenever a button from the race selection dialog is clicked
    call TriggerAddCondition(t3, Condition(function InitiateCountdown))//starts countdown automatically after 12 seconds***not sure if this works???
    set t1 = null
    set t2 = null
    set t3 = null
endfunction

These triggers won't work when they are combined like this and I have no idea why. When testing the map, you are greeted with the dialog as intended, however the countdown for the game beginning starts immediately before a race has been selected. More specifically, the "InitiateCountdown" function gets called and the countdown timer within the function doesn't even start, meaning you are shown the text "Game starting in 3..." and nothing more.

I've identified 4 problems within these triggers:
  • Clicking a button from the dialog results in a new set of buttons added to the dialog, meaning it adds 6 more buttons each time you click a button. Additionally, the dialog doesn't disappear when a button is clicked (or it disappears and reappears instantly with those extra buttons).
  • The automatic timer that starts after 12 seconds doesn't appear to work (although this may be because the "InitiateCountdown" function was already called at the start, meaning it will do nothing if called again). However, when I tried splitting the triggers into different initialisation triggers it still didn't work.
  • The "RaceChosen" function gets called right after the "RaceSelection" function for some unknown reason. "RaceChosen" should only get called if a button is clicked and when I checked to see which button got clicked, "GetClickedButton()" returned null. And because of this, "InitiateCountdown" gets called.
  • The timer within "InitiateCountdown" doesn't start and "GameStart" doesn't get called as a result.
In the meantime I'll be looking for alternative ways to get these triggers to work (like splitting up the triggers), but in my eyes there is no reason for these triggers not to work the way that it is now. Is there a bug that I'm unaware of? Perhaps I'm just not looking hard enough and I've done something wrong.

Edit: Haha, I solved this myself. My bad y'all, I didn't realise triggers (and groups) functioned the same way as units. The above statement is true, I did do something wrong.

Here is the corrected initialisation trigger:
JASS:
//=====================================================================================
function InitTrig_Custom_Initialisation takes nothing returns nothing
    local trigger t1 = CreateTrigger()
    local trigger t2 = CreateTrigger()
    local trigger t3 = CreateTrigger()
    call TriggerRegisterTimerEvent(t1, 0, false)
    call TriggerRegisterDialogEvent(t2, udg_raceSelection)
    call TriggerRegisterTimerEvent(t3, 12, false)
    call TriggerAddCondition(t1, Condition(function RaceSelection))
    call TriggerAddCondition(t2, Condition(function RaceChosen))
    call TriggerAddCondition(t3, Condition(function InitiateCountdown))
    set t1 = null
    set t2 = null
    set t3 = null
endfunction

Since I was setting each subsequent trigger to the first trigger, it was like I was setting multiple unit variables to the same unit. This meant that by adding events to the trigger held in one variable, the other trigger variables get that event because it is the same trigger they are pointing to. This is like how killing the unit stored in a unit variable will affect all other unit variables that store (point to) that unit.

I thought by setting the other trigger variables to the first I was "duplicating" it like how integer variables work. So I thought this was efficient because I wasn't calling the same function ("CreateTrigger()") multiple times. I didn't realise this when making my other triggers the same way because they had conditions that were unique to the given event, which prevented me from seeing that they would've performed their functions' actions had the condition not been there.

Also the timer event that automatically starts the countdown after 12 seconds wasn't working because the game is paused during the dialog due to me playing single player, LOL.
 
Last edited:

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,543
What exactly are you trying to do here?
vJASS:
    local trigger t1 = CreateTrigger()
    local trigger t2 = t1
    local trigger t3 = t1
I think you meant to create three separate triggers:
vJASS:
    local trigger t1 = CreateTrigger()
    local trigger t2 = CreateTrigger()
    local trigger t3 = CreateTrigger()
Otherwise, t2 and t3 are pointless.
 
Level 1
Joined
Aug 15, 2023
Messages
2
What exactly are you trying to do here?
vJASS:
    local trigger t1 = CreateTrigger()
    local trigger t2 = t1
    local trigger t3 = t1
I think you meant to create three separate triggers:
vJASS:
    local trigger t1 = CreateTrigger()
    local trigger t2 = CreateTrigger()
    local trigger t3 = CreateTrigger()
Otherwise, t2 and t3 are pointless.

Yeah, you're absolutely right. I found it out myself and was editing my post while you replied haha. Thanks anyway!
 
Top