• 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] Leaderboard

Level 6
Joined
Mar 9, 2023
Messages
75
Hi! I have created a Leaderboard which rolls a die for the triggering player then displays the result next to their hero's name. Each player can only roll once while the leaderboard is active. Every player that rolls should add an entry to the list, which is then rearranged. I learned how to create Leaderboards today and I couldn't find a guide, so I'm really clueless on most many functions. The issue is that after the first player's entry has been added, the second one will replace the first entry. No subsequent players can type -roll. Meaning that it only has one hero with a roll in the end.

My hypothesis is that I'm using AddItem() incorrectly or that I've set the Style wrong. Perhaps I am adding categories and not the entries. Still doesn't explain the weirdness of only one subsequent roll being available.

JASS:
globals
    leaderboard rollBoard = null
    boolean array hasPlayerRolled
    timer cleanupTimer = null
endglobals

function HideBoard takes nothing returns nothing
    local integer i = 0
    call PauseTimer(cleanupTimer)
    call DestroyTimer(cleanupTimer)
    set cleanupTimer = null
    
    if IsLeaderboardDisplayed(rollBoard) then
        call LeaderboardDisplay(rollBoard, false)
        call LeaderboardClear(rollBoard)
    endif
    
    loop
        set hasPlayerRolled[i] = false
        set i = i + 1
        exitwhen i >= 8
    endloop
endfunction

function SetPlayerRoll takes player p, integer r, integer pid returns nothing
    set hasPlayerRolled[pid] = true

    call LeaderboardAddItem(rollBoard, GetUnitName(udg_HERO[pid + 1]), r, p)
    call LeaderboardSortItemsByValue(rollBoard, false)
    if rollBoard != null then
    call PauseTimer(cleanupTimer)
    call DestroyTimer(cleanupTimer)
    endif
    set cleanupTimer = CreateTimer()
    call TimerStart(cleanupTimer, 12.0, false, function HideBoard)
endfunction

function Trig_RollLeaderboard_Actions takes nothing returns nothing
    local player p = GetTriggerPlayer()
    local integer pid = GetPlayerId(p)
    local string chatMessage = GetEventPlayerChatString()
    local string rollLabel
    local integer r = GetRandomInt(1, 100)
        if not hasPlayerRolled[pid] then
    if StringLength(chatMessage) > 6 then
        set rollLabel = "Roll for: " + SubString(chatMessage, 6, StringLength(chatMessage))
    else
        set rollLabel = "Roll Result"
    endif

    if rollBoard == null then
        set rollBoard = CreateLeaderboardBJ(GetPlayersAll(), rollLabel)
        call LeaderboardSetStyle(rollBoard, true, true, true, true)
    endif

    if not IsLeaderboardDisplayed(rollBoard) then
        call LeaderboardDisplay(rollBoard, true)
    call LeaderboardSetLabel(rollBoard, rollLabel)
    endif

    call SetPlayerRoll(p, r, pid)
    endif 
    set p = null
endfunction

//===========================================================================
function InitTrig_RollLeaderboard takes nothing returns nothing
    set gg_trg_RollLeaderboard = CreateTrigger(  )
    call TriggerRegisterPlayerChatEvent( gg_trg_RollLeaderboard, Player(0), "-roll", false )
    call TriggerRegisterPlayerChatEvent( gg_trg_RollLeaderboard, Player(1), "-roll", false )
    call TriggerRegisterPlayerChatEvent( gg_trg_RollLeaderboard, Player(2), "-roll", false )
    call TriggerRegisterPlayerChatEvent( gg_trg_RollLeaderboard, Player(3), "-roll", false )
    call TriggerRegisterPlayerChatEvent( gg_trg_RollLeaderboard, Player(4), "-roll", false )
    call TriggerRegisterPlayerChatEvent( gg_trg_RollLeaderboard, Player(5), "-roll", false )
    call TriggerRegisterPlayerChatEvent( gg_trg_RollLeaderboard, Player(6), "-roll", false )
    call TriggerRegisterPlayerChatEvent( gg_trg_RollLeaderboard, Player(7), "-roll", false )
    call TriggerAddAction( gg_trg_RollLeaderboard, function Trig_RollLeaderboard_Actions )
endfunction

Help pl0z.
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,875
Hi! I have created a Leaderboard which rolls a die for the triggering player then displays the result next to their hero's name. Each player can only roll once while the leaderboard is active. Every player that rolls should add an entry to the list, which is then rearranged. I learned how to create Leaderboards today and I couldn't find a guide, so I'm really clueless on most many functions. The issue is that after the first player's entry has been added, the second one will replace the first entry. No subsequent players can type -roll. Meaning that it only has one hero with a roll in the end.

My hypothesis is that I'm using AddItem() incorrectly or that I've set the Style wrong. Perhaps I am adding categories and not the entries. Still doesn't explain the weirdness of only one subsequent roll being available.
I was having trouble seeing the issue so I tried to create my own setup based on yours. Here's what I came up with, which seems to work:
vJASS:
library RollLeaderboard initializer Init

    globals
        private integer cleanupTicksDefault = 12 // One tick per second
        private integer cleanupTicks = 0
        private player winner
        private timer cleanupTimer = null
        private leaderboard board = null
        private string boardTitle = ""
        private boolean array hasPlayerRolled
    endglobals

    private function Display_Roll_Winner takes nothing returns nothing
        // Optional, let's display who was in first place.
        // This does not care about ties.
        set winner = LeaderboardGetIndexedPlayerBJ(1, board)
        call DisplayTimedTextToForce(GetPlayersAll(), 8.00, "Roll winner: " + GetPlayerName(winner))
    endfunction

    private function Update_Label takes nothing returns nothing
        call LeaderboardSetLabel(board, "[" + I2S(cleanupTicks) + "] " + boardTitle)
    endfunction

    private function Clear_Board takes nothing returns nothing
        local integer i = 0
        loop
            set hasPlayerRolled[i] = false
            set i = i + 1
            exitwhen i >= 8
        endloop

        if cleanupTimer != null then
            call PauseTimer(cleanupTimer)
            call DestroyTimer(cleanupTimer)
            set cleanupTimer = null
        endif

        if board != null then
            call Display_Roll_Winner()
            call DestroyLeaderboard(board)
            set board = null
        endif
    endfunction

    private function Timer_Expired takes nothing returns nothing
        set cleanupTicks = cleanupTicks - 1
        call Update_Label()
        if cleanupTicks == 0 then
            call Clear_Board()
        endif
    endfunction

    private function Determine_Player_Roll takes player p returns nothing
        local integer pid = GetPlayerId(p)
        local integer roll

        // Prevent multiple rolls per session
        if hasPlayerRolled[pid] then
            return
        endif

        set hasPlayerRolled[pid] = true
        set roll = GetRandomInt(1, 100)
        call LeaderboardAddItem(board, GetUnitName(udg_HERO[pid + 1]), roll, p)

        // Prolong the cleanup timer
        set cleanupTicks = cleanupTicksDefault
    endfunction

    private function Create_Leaderboard takes nothing returns nothing
        // Cleanup the board after a delay
        set cleanupTimer = CreateTimer()
        set cleanupTicks = cleanupTicksDefault
        call TimerStart(cleanupTimer, 1.0, true, function Timer_Expired)

        // The board didn't exist, create a new one
        set board = CreateLeaderboardBJ(GetPlayersAll(), "")
        call LeaderboardSetStyle(board, true, true, true, true)
        call LeaderboardSortItemsByValue(board, false)
        call Update_Label()
    endfunction

    private function Player_Typed_Roll takes nothing returns nothing
        local player p = GetTriggerPlayer()
        local string msg

        // Create a new board if none exists
        if board == null then
            set msg = GetEventPlayerChatString()
            if StringLength(msg) > 6 then
                set boardTitle = "Roll for: " + SubString(msg, 6, StringLength(msg))
            else
                set boardTitle = "Roll Results"
            endif
            call Create_Leaderboard()
        endif

        // Try to roll a random number
        call Determine_Player_Roll(p)
    
        set p = null
        set msg = null
    endfunction

    private function Init takes nothing returns nothing
        local trigger t = CreateTrigger()
        local integer i = 0
        loop
            call TriggerRegisterPlayerChatEvent(t, Player(i), "-roll", false)
            set i = i + 1
            exitwhen i >= 8
        endloop
        call TriggerAddAction(t, function Player_Typed_Roll)
        set t = null
    endfunction
endlibrary
I also added the Timer to the title of the Leaderboard so you can see it countdown -> [12]... [11]... [10]... Because why not, lol.
 

Attachments

  • Leaderboard Roll 1.w3m
    19.6 KB · Views: 2
Last edited:
Top