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

Why does this timer not run?

Status
Not open for further replies.
Level 12
Joined
Dec 2, 2016
Messages
733
Code:
function UpdateMultiboardTimed takes nothing returns nothing
local timer newTimer = CreateTimer()
  call TimerStart(newTimer, 1.0, true, function UpdateMultiboard) // change true to false
  call DisplayTextToForce( GetPlayersAll(), "UpdateMiltuBoardTimed Ran" )
endfunction

It never runs at all in my script. Any idea what I'm doing wrong?
 
Level 12
Joined
Dec 2, 2016
Messages
733
Ok, and would this cause a desync?

call DisplayTextToPlayer( Player(0),0,0, "StartMultiBoard" )

I'm not positive it's the text causing it, but I'm pretty sure it is. And if this does cause a desync how do I send a message to a player without causing a desync?
 
Level 12
Joined
Dec 2, 2016
Messages
733
Ok so I have this now


JASS:
function UpdateMultiboardTimed takes nothing returns nothing
local timer newTimer = CreateTimer()
  call TimerStart(newTimer, 1.0, true, function UpdateMultiboard) // change true to false
  call DisplayTextToForce( GetPlayersAll(), "UpdateMiltuBoardTimed Ran" )
endfunction

The above ^ only runs once and doesn't loop. Not sure why?
JASS:
private function OnGameStarted takes nothing returns boolean
  local timer timerD = CreateTimer()
  call DisplayTextToPlayer( Player(0),0,0, "OnGameStarted()" )
  call TimerStart(timerD, 0.0, false, function StartMultiboard) // true = loop crash
  call TimerStart(timerD, 0.0, false, function UpdateMultiboardTimed) // true = loop crash
  set timerD = null

  return false
endfunction
 
Did you actually try to queue the handler functions? It seems to behave so in your code, which is quite not the same within the game.

However, the StartMultiboard function is something else. I don't know what it does, but I assume it creates the multiboard. Try attaching a debug message onto that function.

Now, for UpdateMultiboardTimed, it has been declared to run only once in the OnGameStarted function, with a 0-second delay as specified. Instead try changing that 0-second into 1 second and change false to true.

In your callback function, the UpdateMultiboardTimed, you don't need to create a timer that updates the multiboard on every callback. That just eats up a lot of precious memory in the long run.

In short, your UpdateMultiboardTimed functions runs once, after a 0-second delay instead of a periodic 1-second loop.

 
Level 13
Joined
May 10, 2009
Messages
868
call TimerStart(timerD, 0.0, false, function StartMultiboard) // true = loop crash
This line is basically overridden, because the following one uses the same timer. Also, yes, setting its boolean flag to true would crash, because you're telling the game to periodically run a function every 0. seconds

call TimerStart(timerD, 0.0, false, function UpdateMultiboardTimed) // true = loop crash
UpdateMultiboardTimed is then executed. However, I don't see a reason for attaching a timer to that function.

call UpdateMultiboardTimed() would be enough here.


EDIT: Or even better
JASS:
private function OnGameStarted takes nothing returns boolean
    call DisplayTextToPlayer( Player(0),0,0, "OnGameStarted()" )
    call TimerStart(CreateTimer(), .0, false, function StartMultiboard)
    call TimerStart(CreateTimer(), 1., true, function UpdateMultiboard)
    return false
endfunction
Then remove "UpdateMultiboardTimed".
 
Last edited:
Level 12
Joined
Dec 2, 2016
Messages
733
This is on start function

JASS:
private function InitMultiboard takes nothing returns nothing
  local trigger trg = TriggerCreateOnGameStart()
    call DisplayTextToPlayer( Player(0),0,0, "ThisIsATest3" )
  call TriggerAddCondition(trg, Condition(function OnGameStarted))
endfunction

The goal is for "UpdateMultiboardTimed" function to continuously run every 1 second. Is that not what should be happening, if I run the function wouldn't it keep running the function which is a recurring timer that runs every second?
 
Ahh, I see your plight now.

Just change the following from this

JASS:
function UpdateMultiboardTimed takes nothing returns nothing
    local timer newTimer = CreateTimer()
    call TimerStart(newTimer, 1.0, true, function UpdateMultiboard) // change true to false
  call DisplayTextToForce( GetPlayersAll(), "UpdateMiltuBoardTimed Ran" )
endfunction

// ....

private function OnGameStarted takes nothing returns boolean
    call DisplayTextToPlayer( Player(0),0,0, "OnGameStarted()" )
    call TimerStart(CreateTimer(), .0, false, function StartMultiboard)
    call TimerStart(CreateTimer(), 1., true, function UpdateMultiboard)
    return false
endfunction

to this...

JASS:
function UpdateMultiboardTimed takes nothing returns nothing
    call UpdateMultiboard()
endfunction

function StartMultiboard takes nothing returns nothing
    // Your code here...
    call DestroyTimer(GetExpiredTimer())
endfunction
// ....

private function OnGameStarted takes nothing returns boolean
    call DisplayTextToPlayer( Player(0),0,0, "OnGameStarted()" )
    call TimerStart(CreateTimer(), .0, false, function StartMultiboard)
    call TimerStart(CreateTimer(), 1., true, function UpdateMultiboard)
    return false
endfunction
 
Level 12
Joined
Dec 2, 2016
Messages
733
Thank you that part is working now, now this part is the part that creates and updates the multiboard to current statistics.

JASS:
function UpdateMultiboard takes nothing returns nothing
  local integer i = 0
  local multiboarditem it
  local integer cnt = 0
  local boolean hhu = false
  local boolean hva = false
  local boolean minimized = true
  loop
    exitwhen i > 15
    set PlayerRow[i] = 0
    set i = i + 1
  endloop
  if not allowmb then
    return
  endif
  if mb != null then
    set minimized = IsMultiboardMinimized(mb)
    call DestroyMultiboard(mb)
   call DisplayTextToPlayer( Player(0),0,0, "Multiboard has been destroyed" )
  endif
  set mb = CreateMultiboard()
  call DisplayTextToPlayer( Player(0), 0,0,"Multiboard has been created" )
  set i = 0
 
  loop
    exitwhen i > 11
   
    if players[i].state != 0 then

      if players[i].side == SIDE_HUMAN then
        set cnt = cnt + 1
        set hhu = true
       
      elseif players[i].side == SIDE_VAMPIRE or players[i].side == SIDE_MINION then
   
        set cnt = cnt + 1
        set hva = true
      endif
    endif

    set i = i + 1
  endloop
  if hhu then

    set cnt = cnt + 1
  endif
  if hva then
    set cnt = cnt + 1

  endif
 
  call MultiboardSetRowCount(mb, cnt)
  call MultiboardSetColumnCount(mb, 4)
  set i = 0

  loop
    exitwhen i >= cnt
    set it = MultiboardGetItem(mb, i, 0)
    call MultiboardSetItemStyle(it, true, false)
    call MultiboardSetItemWidth(it, 0.12)
    call MultiboardReleaseItem(it)
    set it = MultiboardGetItem(mb, i, 1)
    call MultiboardSetItemStyle(it, true, false)
    call MultiboardSetItemWidth(it, 0.04)
    call MultiboardReleaseItem(it)
    set it = MultiboardGetItem(mb, i, 2)
    call MultiboardSetItemStyle(it, true, false)
    call MultiboardSetItemWidth(it, 0.04)
    call MultiboardReleaseItem(it)
    set it = MultiboardGetItem(mb, i, 3)
    call MultiboardSetItemStyle(it, true, false)
    call MultiboardSetItemWidth(it, 0.06)
    call MultiboardReleaseItem(it)
    set i = i + 1

  endloop
  set cnt = 0
  if hhu then
    call MultiboardSetItem(0, 0, "Humans")
    call MultiboardSetItem(0, 1, "Gold")
    call MultiboardSetItem(0, 2, "Lumber")
    call MultiboardSetItem(0, 3, "Fed")
    set cnt = 1
    set i = 0
    loop
      exitwhen i > 11
      if players[i].state != 0 and players[i].side == SIDE_HUMAN then
        set PlayerRow[i] = cnt
        set cnt = cnt + 1
      endif
      set i = i + 1
    endloop
  endif
  if hva then

    call MultiboardSetItem(cnt, 0, "Vampires")
    call MultiboardSetItem(cnt, 1, "Gold")
    call MultiboardSetItem(cnt, 2, "Lumber")
    call MultiboardSetItem(cnt, 3, "Leaked")
    set cnt = cnt + 1
    set i = 0
    loop
      exitwhen i > 11
      if players[i].state != 0 and (players[i].side == SIDE_VAMPIRE or players[i].side == SIDE_MINION) then
        set PlayerRow[i] = cnt
        set cnt = cnt + 1
      endif
      set i = i + 1

    endloop
  endif

  call UpdateTime()
  call MultiboardDisplay(mb, true)

  call MultiboardMinimize(mb, minimized)
  set it = null
endfunction


The problem I seem to be having is the entire thing runs except for the last part
JASS:
  call UpdateTime()
  call MultiboardDisplay(mb, true)

  call MultiboardMinimize(mb, minimized)
^ This part doesn't run, I've tested using a message command. Removed it since. Any idea why this part wouldn't run?
 
Level 12
Joined
Dec 2, 2016
Messages
733
Alright edit:

Ignore above ^ I found the culprit, I put the message right after 'UpdateTime()' and the message doesn't run so it's UpdateTime that's screwing it up.

This is the function


JASS:
private function UpdateTime takes nothing returns nothing
  local integer i = 0
  if mb == null then
    return
  endif
  call MultiboardSetTitleText(mb, "Game time: " + TimeString(GameTime()))
  loop
    exitwhen i > 11
    call UpdateMultiboardPlayer(i)
    set i = i + 1
  endloop
endfunction

mb = the multiboard which is declared above as a global

If I'm correct if mb is null then the 'return' breaks the function? And if that's true would that then break the function that UpdateTime() is in so that anything else after wouldn't run?
 
I'm guessing that TimeString function returns a string from a real representation, of which the Game Time function returns said data type (real).

If anything, I would suspect UpdateMultiboardPlayer as a possible culprit for the thread crash. The return keyword just ends the current function and jumps back to the main thread. To give a clearer picture:

JASS:
function IsUnitAlien takes unit u, MadeUpType insertHere returns Boolean
    if u == null then
        return false
    endif
    return not insertHere.inCountry(u)
endfunction

function Actions takes nothing returns nothing
    local unit u = GetTriggerUnit()
    // Assume presence of unit indexer
    local MadeUpType id = GetUnitId(u)

    // When IsUnitAlien is called, it pauses this thread and executes the former's thread.
    // A return keyword is a breakpoint for the executed thread, which returns it to the current thread.
    if IsUnitAlien(u, id) then
        call Deport(u)
    else
        call Tax(u)
    endif
    set u = null
endfunction
 
Status
Not open for further replies.
Top