Updating Player Reference devices via Sorting

Dearest all!

I got a bit too adventurous with Verse: I’m building a podium-leaderboard:
I’m trying to

  • Use Player Reference Devices to create a podium displaying the three players with most eliminations
  • sort players by eliminations
  • update the leaderboard at each kill

This is the last iteration of the code… and I’m getting quite humbled by the experience :smiley:

Any help would be greatly appreciated!

using { /Fortnite.com/Devices }  # Importing necessary modules for devices
using { /Verse.org/Simulation }  # Importing necessary modules for simulation
using { /UnrealEngine.com/Temporary/Diagnostics }  # Importing necessary modules for diagnostics
using { /Fortnite.com/Characters }  # Importing necessary modules for characters
using { /Fortnite.com/Game }  # Importing necessary modules for game

# EN_Podium : Class to manage the winner podium
winner_podium := class(creative_device):
    @editable
    PlayerReference1 : player_reference_device = player_reference_device{}  # Editable player reference device 1
    @editable
    PlayerReference2 : player_reference_device = player_reference_device{}  # Editable player reference device 2
    @editable
    PlayerReference3 : player_reference_device = player_reference_device{}  # Editable player reference device 3

    var PlayerEliminations : [agent]int = map{}  # Map to keep track of player eliminations

    # Event to handle when the device starts
    OnBegin<override>()<suspends>:void=
        if (Playspace := GetPlayspace()):  # Get the playspace (no square brackets as it doesn't have the 'decides' effect)
            if (AllPlayers := Playspace.GetPlayers()):  # Get all players in the playspace (no square brackets as it doesn't have the 'decides' effect)
                for (Player : AllPlayers):  # Iterate over all players
                    if (FortCharacter := Player.GetFortCharacter[]):  # Get the fort character of the player (square brackets as it has the 'decides' effect)
                        FortCharacter.EliminatedEvent().Subscribe(OnPlayerEliminated)  # Subscribe to the eliminated event

    # Function to handle player eliminations
    OnPlayerEliminated(Result:elimination_result):void=
        if (EliminatingCharacter := Result.EliminatingCharacter?):  # Check if there is an eliminating character
            if (EliminatingAgent := EliminatingCharacter.GetAgent[]):  # Get the agent of the eliminating character (square brackets as it has the 'decides' effect)
                if (EliminationCount := PlayerEliminations[EliminatingAgent]):  # Check if the agent is already in the map
                    set PlayerEliminations[EliminatingAgent] = EliminationCount + 1  # Increment the elimination count
                else:
                    set PlayerEliminations[EliminatingAgent] = 1  # Initialize the elimination count
                UpdatePlayerReferences()  # Update the player references

    # Function to update the player reference devices
    UpdatePlayerReferences():void=
        var PlayerList:[]tuple(agent, int) = for {Agent -> Eliminations : PlayerEliminations} do {Agent, Eliminations}  # Create a list of players and their eliminations
        SortPlayerList(PlayerList)  # Sort the player list by eliminations
        
        if (PlayerList.Length >= 1):  # Check if there is at least one player
            PlayerReference1.SetPlayer(option{PlayerList[0][0]})  # Set the first player reference
        if (PlayerList.Length >= 2):  # Check if there are at least two players
            PlayerReference2.SetPlayer(option{PlayerList[1][0]})  # Set the second player reference
        if (PlayerList.Length >= 3):  # Check if there are at least three players
            PlayerReference3.SetPlayer(option{PlayerList[2][0]})  # Set the third player reference

    # Function to sort the player list by eliminations
    SortPlayerList(PlayerList:[]tuple(agent, int)):void=
        var Swapped:logic = false  # Variable to track if a swap was made
        for (I := 0..PlayerList.Length - 1):  # Outer loop for bubble sort
            set Swapped = false  # Reset the swapped variable
            for (J := 0..PlayerList.Length - I - 2):  # Inner loop for bubble sort
                if (PlayerList[J][1] < PlayerList[J + 1][1]):  # Compare the eliminations
                    Temp := PlayerList[J]  # Swap the elements
                    set PlayerList[J] = PlayerList[J + 1]  # Swap the elements
                    set PlayerList[J + 1] = Temp  # Swap the elements
                    set Swapped = true  # Set the swapped variable to true
            if (not Swapped):  # If no swaps were made, the list is sorted
                break  # Exit the loop```

these are the errors so far:

  {
        "code": "3513",
        "severity": 8,
        "message": "Expected an expression that can fail in the ‘if’ condition clause",
        "startLineNumber": 20
    },
    {
        "code": "3513",
        "severity": 8,
        "message": "Expected an expression that can fail in the ‘if’ condition clause",
        "startLineNumber": 21
    },
    {
        "code": "3512",
        "severity": 8,
        "message": "This invocation calls a function that has the ‘decides’ effect, which is not allowed by its context. The ‘decides’ effect indicates that the invocation calls a function that might fail, and so must occur in a failure context that will handle the failure. Some examples of failure contexts are the condition clause of an ‘if’, the left operand of ‘or’, or the clause of the ‘logic’ macro.",
        "startLineNumber": 31
    },
    {
        "code": "3512",
        "severity": 8,
        "message": "This invocation calls a function that has the ‘decides’ effect, which is not allowed by its context. The ‘decides’ effect indicates that the invocation calls a function that might fail, and so must occur in a failure context that will handle the failure. Some examples of failure contexts are the condition clause of an ‘if’, the left operand of ‘or’, or the clause of the ‘logic’ macro.",
        "startLineNumber": 33
    },
    {
        "code": "3506",
        "severity": 8,
        "message": "Unknown member SetPlayer in player_reference_device.",
        "startLineNumber": 42
    },
    {
        "code": "3506",
        "severity": 8,
        "message": "Unknown member SetPlayer in player_reference_device.",
        "startLineNumber": 44
    },
    {
        "code": "3506",
        "severity": 8,
        "message": "Unknown member SetPlayer in player_reference_device.",
        "startLineNumber": 46
    },
    {
        "code": "3511",
        "severity": 8,
        "message": "Tuple element access uses round brackets / parentheses MyTuple(Idx) rather than square [] or curly {} brackets.",
        "startLineNumber": 54
    },
    {
        "code": "3511",
        "severity": 8,
        "message": "Tuple element access uses round brackets / parentheses MyTuple(Idx) rather than square [] or curly {} brackets.",
        "startLineNumber": 54
    },
    {
        "code": "3512",
        "severity": 8,
        "message": "This invocation calls a function that has the ‘decides’ effect, which is not allowed by its context. The ‘decides’ effect indicates that the invocation calls a function that might fail, and so must occur in a failure context that will handle the failure. Some examples of failure contexts are the condition clause of an ‘if’, the left operand of ‘or’, or the clause of the ‘logic’ macro.",
        "startLineNumber": 55
    },
    {
        "code": "3512",
        "severity": 8,
        "message": "This invocation calls a function that has the ‘decides’ effect, which is not allowed by its context. The ‘decides’ effect indicates that the invocation calls a function that might fail, and so must occur in a failure context that will handle the failure. Some examples of failure contexts are the condition clause of an ‘if’, the left operand of ‘or’, or the clause of the ‘logic’ macro.",
        "startLineNumber": 56
    },
    {
        "code": "3509",
        "severity": 8,
        "message": "The assignment’s left hand expression type tuple(agent,int) cannot be assigned to",
        "startLineNumber": 56
    },
    {
        "code": "3512",
        "severity": 8,
        "message": "This invocation calls a function that has the ‘decides’ effect, which is not allowed by its context. The ‘decides’ effect indicates that the invocation calls a function that might fail, and so must occur in a failure context that will handle the failure. Some examples of failure contexts are the condition clause of an ‘if’, the left operand of ‘or’, or the clause of the ‘logic’ macro.",
        "startLineNumber": 57
    },
    {
        "code": "3509",
        "severity": 8,
        "message": "The assignment’s left hand expression type tuple(agent,int) cannot be assigned to",
        "startLineNumber": 57
    },
    {
        "code": "3513",
        "severity": 8,
        "message": "Expected an expression that can fail in the operand of ‘not’",
        "startLineNumber": 59
    },
    {
        "code": "3581",
        "severity": 8,
        "message": "This break is not in a breakable context. break may currently only be used inside a loop.",
        "startLineNumber": 60
    }```


**Thank you in advance for grinding with me! :D**

For the first two errors

as it states you can’t use if for just setting a variable unless it has decides effect or is a comparison or something of that sorts
so you could just replace

    OnBegin<override>()<suspends>:void=
        if (Playspace := GetPlayspace()):
            if (AllPlayers := Playspace.GetPlayers())

with

    OnBegin<override>()<suspends>:void=
        Playspace := GetPlayspace()
        AllPlayers := Playspace.GetPlayers()

and for the 3rd error
you can’t do this because since it is using brackets to get something from an array/map which could be not an actual item it is something that can fail therefore you need to put the set in an if condition

so from this

set PlayerEliminations[EliminatingAgent] = EliminationCount + 1 

to this

if(set PlayerEliminations[EliminatingAgent] = EliminationCount + 1){Print("Elim Count Incremented")}

(You dont need to keep the print btw but it can help understand if the elimination count was successfully set

if you have any further questions let me know

2 Likes

@Mineblo thank you SO MUCH for this refresh!

I updated the Function to handle player elimination accordingly :slight_smile:

    # Function to handle player eliminations
    OnPlayerEliminated(Result:elimination_result):void=
        if (EliminatingCharacter := Result.EliminatingCharacter?):
            if (EliminatingAgent := EliminatingCharacter.GetAgent[]):
                # Check if the agent is already in the map
                if (EliminationCount := PlayerEliminations[EliminatingAgent]):
                    if(set PlayerEliminations[EliminatingAgent] = EliminationCount + 1):
                        Print("Elimination Count Incremented")
                else:
                    if(set PlayerEliminations[EliminatingAgent] = 1):
                        Print("Initialized Elimination Count")

        UpdatePlayerReferences() # Update the player references

now I have refreshed motivation to go and iron out the rest :smiley:

1 Like

Hey there, had a look through your code and made a few changes, but overall it was good! Some things to note are that arrays passed into parameters are immutable, so if you have passed one into a function you cannot modify it, and instead have to return a modified copy. Also, accessing tuples doesn’t require square brackets as the value is guaranteed to be there. Here’s my fixes to the code :slight_smile:

using { /Fortnite.com/Devices }  # Importing necessary modules for devices
using { /Verse.org/Simulation }  # Importing necessary modules for simulation
using { /UnrealEngine.com/Temporary/Diagnostics }  # Importing necessary modules for diagnostics
using { /Fortnite.com/Characters }  # Importing necessary modules for characters
using { /Fortnite.com/Game }  # Importing necessary modules for game

# EN_Podium : Class to manage the winner podium
winner_podium := class(creative_device):
    @editable
    PlayerReference1 : player_reference_device = player_reference_device{}  # Editable player reference device 1
    @editable
    PlayerReference2 : player_reference_device = player_reference_device{}  # Editable player reference device 2
    @editable
    PlayerReference3 : player_reference_device = player_reference_device{}  # Editable player reference device 3

    var PlayerEliminations : [agent]int = map{}  # Map to keep track of player eliminations

    # Event to handle when the device starts
    OnBegin<override>()<suspends>:void=
        for:
            Player : GetPlayspace().GetPlayers() # Get each player in the playspace
            FortCharacter := Player.GetFortCharacter[] # Get their fort character, square brackets as it has the 'decides' effect
        do:
            FortCharacter.EliminatedEvent().Subscribe(OnPlayerEliminated)  # Subscribe to the eliminated event

    # Function to handle player eliminations
    OnPlayerEliminated(Result:elimination_result):void=
        if:
            EliminatingCharacter := Result.EliminatingCharacter?  # Check if there is an eliminating character
            EliminatingAgent := EliminatingCharacter.GetAgent[]  # Get the agent of the eliminating character (square brackets as it has the 'decides' effect)
        then:
            var Eliminations: int = 1
            if:
                EliminationCount := PlayerEliminations[EliminatingAgent] # Check if the agent is already in the map
            then:
                set Eliminations = EliminationCount + 1 # If they are, set the Eliminations variable to that amount
            
            option{ set PlayerEliminations[EliminatingAgent] = Eliminations } # Update the players eliminations
            UpdatePlayerReferences() # Update the player references

    # Function to update the player reference devices
    UpdatePlayerReferences():void=
        var PlayerList:[]tuple(agent, int) = for {Agent -> Eliminations : PlayerEliminations} do {Agent, Eliminations}  # Create a list of players and their eliminations
        set PlayerList = SortPlayerList(PlayerList)  # Sort the player list by eliminations
        
        if (PlayerList1 := PlayerList[0]):  # Get the first player, will fail if there isn't one.
            PlayerReference1.Register(PlayerList1(0))  # Set the first player reference
        if (PlayerList2 := PlayerList[1]):  # Get the second player, will fail if there isn't one.
            PlayerReference2.Register(PlayerList2(0))  # Set the second player reference
        if (PlayerList3 := PlayerList[2]):  # Get the third player, will fail if there isn't one.
            PlayerReference3.Register(PlayerList3(0))  # Set the third player reference

    # Function to sort the player list by eliminations
    SortPlayerList(PlayerList:[]tuple(agent, int)):[]tuple(agent, int)=
        var NewList: []tuple(agent, int) = PlayerList
        for:
            I := 0..NewList.Length - 1  # Outer loop for bubble sort
        do:
            for:
                J := 0..NewList.Length - I - 2  # Inner loop for bubble sort
                Item := NewList[J]  # Get the first player
                SecondItem := NewList[J + 1]  # Get the second player
                Item(1) < SecondItem(1)  # Compare the eliminations
            do:
                option{ set NewList[J] = SecondItem }  # Swap the players
                option{ set NewList[J + 1] = Item }  # Could do this inside the for, but it looks nicer like this.

            # ALTERNATIVE
            # for:
            #     J := 0..NewList.Length - I - 2
            #     Item := NewList[J]
            #     SecondItem := NewList[J + 1]
            #     Item(1) < SecondItem(1)
            #     set NewList[J] = SecondItem
            #     set NewList[J + 1] = Item
            # do{}

        return NewList
1 Like

THANK YOU
SOOO MUCH @Magmaslime569 !!!

I extended it a bit, testing it now… And I’ll be sharing here the results :slight_smile:

LOVE <3

No worries :+1: One thing to note is that i made a mistake when setting Eliminations and needs to be set Eliminations = EliminationCount + 1. I have updated it in the code block above too. Hope the rest works out well :pray:

Yes Yes, thank you @Magmaslime569 I noticed that :smiley:
thank you for double checking!

The script runs but I’m currently refactoring it and extending it a bit:

trying to figure out how to pass the eliminated count to player_reference_device… (elimination count stays at 0) … somehow now eliminiations stay at 0

finding an elegant way to initialize and dynamically register players to the reference devices

making sure data persists between sessions…

I’ve been grinding through it for some hours now and I’ll post here my progress, if Any.

Thank you again for your help!

Some updates on my progress - non-progress (help!):

Long story short: the script runs, but elimination and kill values do not increment, neither on Player Reference Devices… nor on prints.

( I am aiming to allow users to choose whether they want to push to player reference device either eliminations or Kills including npcs)

This is the latest iteration of the code:

using { /Fortnite.com/Devices }  # Importing necessary modules for devices
using { /Verse.org/Simulation }  # Importing necessary modules for simulation
using { /UnrealEngine.com/Temporary/Diagnostics }  # Importing necessary modules for diagnostics
using { /Fortnite.com/Characters }  # Importing necessary modules for characters
using { /Fortnite.com/Game }  # Importing necessary modules for game

# EN_Podium : Class to manage the winner podium
winner_podium := class(creative_device):
    @editable
    PlayerReference1 : player_reference_device = player_reference_device{}  # Editable player reference device 1
    @editable
    PlayerReference2 : player_reference_device = player_reference_device{}  # Editable player reference device 2
    @editable
    PlayerReference3 : player_reference_device = player_reference_device{}  # Editable player reference device 3

    var PlayerEliminations : [agent]int = map{}  # Map to keep track of player eliminations
    var TotalKills: int = 0  # Variable to track total kills

    # Event to handle when the device starts
    OnBegin<override>()<suspends>:void=
        for:
            Player : GetPlayspace().GetPlayers() # Get each player in the playspace
            FortCharacter := Player.GetFortCharacter[] # Get their fort character, square brackets as it has the 'decides' effect
        do:
            FortCharacter.EliminatedEvent().Subscribe(OnPlayerEliminated)  # Subscribe to the eliminated event

    # Function to handle player eliminations
    OnPlayerEliminated(Result:elimination_result):void=
        if:
            EliminatingCharacter := Result.EliminatingCharacter?  # Check if there is an eliminating character
            EliminatingAgent := EliminatingCharacter.GetAgent[]  # Get the agent of the eliminating character (square brackets as it has the 'decides' effect)
        then:
            var Eliminations: int = 1
            if:
                EliminationCount := PlayerEliminations[EliminatingAgent] # Check if the agent is already in the map
            then:
                set Eliminations = EliminationCount + 1 # If they are, set the Eliminations variable to that amount
            
            option{ set PlayerEliminations[EliminatingAgent] = Eliminations } # Update the players eliminations
            set TotalKills += 1  # Increment total kills
            UpdatePlayerReferences() # Update the player references

    # Function to update the player reference devices
    UpdatePlayerReferences():void=
        var PlayerList:[]tuple(agent, int) = for {Agent -> Eliminations : PlayerEliminations} do {Agent, Eliminations}  # Create a list of players and their eliminations
        set PlayerList = SortPlayerList(PlayerList)  # Sort the player list by eliminations
        
        if (PlayerList1 := PlayerList[0]):  # Get the first player, will fail if there isn't one.
            PlayerReference1.Register(PlayerList1(0))  # Set the first player reference
            Print("{PlayerReference1.GetStatValue()}", ?Duration:=100.0)
        if (PlayerList2 := PlayerList[1]):  # Get the second player, will fail if there isn't one.
            Print("{PlayerReference2.GetStatValue()}", ?Duration:=100.0)
            PlayerReference2.Register(PlayerList2(0))  # Set the second player reference
        if (PlayerList3 := PlayerList[2]):  # Get the third player, will fail if there isn't one.
            Print("{PlayerReference1.GetStatValue()}", ?Duration:=100.0)
            PlayerReference3.Register(PlayerList3(0))  # Set the third player reference

    # Function to sort the player list by eliminations
    SortPlayerList(PlayerList:[]tuple(agent, int)):[]tuple(agent, int)=
        var NewList: []tuple(agent, int) = PlayerList
        for:
            I := 0..NewList.Length - 1  # Outer loop for bubble sort
        do:
            for:
                J := 0..NewList.Length - I - 2  # Inner loop for bubble sort
                Item := NewList[J]  # Get the first player
                SecondItem := NewList[J + 1]  # Get the second player
                Item(1) < SecondItem(1)  # Compare the eliminations
            do:
                option{ set NewList[J] = SecondItem }  # Swap the players
                option{ set NewList[J + 1] = Item }  # Could do this inside the for, but it looks nicer like this.

        return NewList

This is the last work in progress version of the dynamic podium-leaderboard based on Player Reference Device.

Unfortunately connection to Fortnite Servers is extremely spotty today for me (takes super long to connect and eventually it times out) so I can’t try it in game.

If anybody wants to give it a spin… here it is!

using { /Fortnite.com/Devices }  # Importing necessary modules for devices
using { /Verse.org/Simulation }  # Importing necessary modules for simulation
using { /UnrealEngine.com/Temporary/Diagnostics }  # Importing necessary modules for diagnostics
using { /Fortnite.com/Characters }  # Importing necessary modules for characters
using { /Fortnite.com/Game }  # Importing necessary modules for game
using { /Verse.org/Concurrency }  # Importing necessary modules for concurrency

# EN_Podium : Class to manage the winner podium
winner_podium := class(creative_device):
    @editable
    PlayerReference1 : player_reference_device = player_reference_device{}  # Editable player reference device 1
    @editable
    PlayerReference2 : player_reference_device = player_reference_device{}  # Editable player reference device 2
    @editable
    PlayerReference3 : player_reference_device = player_reference_device{}  # Editable player reference device 3

    @editable
    EliminationManager : elimination_manager_device = elimination_manager_device{}

    var PlayerEliminations : [agent]int = map{}  # Map to keep track of player eliminations
    var TotalKills: int = 0  # Variable to track total kills, initialize to zero

    # Event to handle when the device starts
    OnBegin<override>()<suspends>:void=
        for:
            Player : GetPlayspace().GetPlayers()  # Get each player in the playspace
            FortCharacter := Player.GetFortCharacter[]  # Get their fort character, square brackets as it has the 'decides' effect
        do:
            FortCharacter.EliminatedEvent().Subscribe(OnPlayerEliminated)  # Subscribe to the eliminated event

    # Function to handle player eliminations
    OnPlayerEliminated(Result:elimination_result):void=
        if:
            EliminatingCharacter := Result.EliminatingCharacter?  # Check if there is an eliminating character
            EliminatingAgent := EliminatingCharacter.GetAgent[]  # Get the agent of the eliminating character (square brackets as it has the 'decides' effect)
        then:
            var Eliminations: int = 1
            if:
                EliminationCount := PlayerEliminations[EliminatingAgent]  # Check if the agent is already in the map
            then:
                set Eliminations = EliminationCount + 1  # If they are, set the Eliminations variable to that amount
                Print("Updated Eliminations : {Eliminations}")  # Debug print

            option{ set PlayerEliminations[EliminatingAgent] = Eliminations }  # Update the players eliminations
            set TotalKills += 1  # Increment total kills
            Print("Total Kills: {TotalKills}")  # Debug print
            UpdatePlayerReferences()  # Update the player references

    # Function to update the player reference devices
    UpdatePlayerReferences():void=
        Print("Updating Player References")  # Debug print
        var PlayerList:[]tuple(agent, int) = for {Agent -> Eliminations : PlayerEliminations} do {Agent, Eliminations}  # Create a list of players and their eliminations
        set PlayerList = SortPlayerList(PlayerList)  # Sort the player list by eliminations
        
        if (PlayerList1 := PlayerList[0]):  # Get the first player, will fail if there isn't one.
            PlayerReference1.Register(PlayerList1(0))  # Set the first player reference
            Print("PlayerReference1 set with eliminations {PlayerList1(1)}")
        
        if (PlayerList2 := PlayerList[1]):  # Get the second player, will fail if there isn't one.
            PlayerReference2.Register(PlayerList2(0))  # Set the second player reference
            Print("PlayerReference2 set  with eliminations {PlayerList2(1)}")
        
        if (PlayerList3 := PlayerList[2]):  # Get the third player, will fail if there isn't one.
            PlayerReference3.Register(PlayerList3(0))  # Set the third player reference
            Print("PlayerReference3 set with eliminations {PlayerList3(1)}")

    # Function to sort the player list by eliminations
    SortPlayerList(PlayerList:[]tuple(agent, int)):[]tuple(agent, int)=
        Print("Sorting Player List")  # Debug print
        var NewList: []tuple(agent, int) = PlayerList
        for:
            I := 0..NewList.Length - 1  # Outer loop for bubble sort
        do:
            for:
                J := 0..NewList.Length - I - 2  # Inner loop for bubble sort
                Item := NewList[J]  # Get the first player
                SecondItem := NewList[J + 1]  # Get the second player
                Item(1) < SecondItem(1)  # Compare the eliminations
            do:
                option{ set NewList[J] = SecondItem }  # Swap the players
                option{ set NewList[J + 1] = Item }  # Could do this inside the for, but it looks nicer like this.

        return NewList

Esteemed Verse warriors,

In a moment of desperation, I tried to switch to tracking Score instead of eliminations… still, Score on Player reference devices does not update*… this is the script:

Since I just can’t give up… any help would be greatly appreciated!

** *EDIT : Setting Track Game Total for Stats to FALSE fixed it! Now Score is updated LIVE, hooray!

Much love,

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /Fortnite.com/Characters }
using { /Fortnite.com/Game }
using { /Verse.org/Concurrency }

# EN_Podium : Class to manage the winner podium
winner_podium := class(creative_device):
    @editable
    PlayerReference1 : player_reference_device = player_reference_device{}  # Editable player reference device 1
    @editable
    PlayerReference2 : player_reference_device = player_reference_device{}  # Editable player reference device 2
    @editable
    PlayerReference3 : player_reference_device = player_reference_device{}  # Editable player reference device 3

    @editable
    ScoreManager : score_manager_device = score_manager_device{}

    var PlayerScores : [agent]int = map{}  # Map to keep track of player scores
    var TotalScore: int = 0  # Variable to track total score, initialize to zero

    # Event to handle when the device starts
    OnBegin<override>()<suspends>:void=
        ScoreManager.Enable()  # Enable the score manager
        PlayerReference1.Enable()  # Enable player reference device 1
        PlayerReference2.Enable()  # Enable player reference device 2
        PlayerReference3.Enable()  # Enable player reference device 3

        ScoreManager.ScoreOutputEvent.Subscribe(OnPlayerScored)  # Subscribe to the score output event
        Print("PODIUM DEVICE STARTED")  # Debug print

    # Function to handle player scores
    OnPlayerScored(ScoringAgent:agent):void=
        Print("Player Scored")  # Debug print
        var Score: int = 0
        if (CurrentScore := PlayerScores[ScoringAgent]):
            set Score = CurrentScore + 1  # If they are, increment the score
            Print("Updated Score: {Score} for Player")  # Debug print
        else:
            set Score = 1  # If not, start with score of 1
            Print("New Player Scored")  # Debug print
        
        option{ set PlayerScores[ScoringAgent] = Score }  # Update the player's score in the map
        set TotalScore += 1  # Increment total score
        Print("Total Score: {TotalScore}")  # Debug print
        UpdatePlayerReferences()  # Update the player references

    # Function to update the player reference devices
    UpdatePlayerReferences():void=
        Print("Updating Player References")  # Debug print
        var PlayerList:[]tuple(agent, int) = for {Agent -> Score : PlayerScores} do {Agent, Score}  # Create a list of players and their scores
        set PlayerList = SortPlayerList(PlayerList)  # Sort the player list by scores
        
        if (PlayerList1 := PlayerList[0]):  # Get the first player, will fail if there isn't one.
            PlayerReference1.Register(PlayerList1(0))  # Set the first player reference
            Print("PlayerReference1 set with Player 1 and Score: {PlayerList1(1)}")
        
        if (PlayerList2 := PlayerList[1]):  # Get the second player, will fail if there isn't one.
            PlayerReference2.Register(PlayerList2(0))  # Set the second player reference
            Print("PlayerReference2 set with Player 2 and Score: {PlayerList2(1)}")
        
        if (PlayerList3 := PlayerList[2]):  # Get the third player, will fail if there isn't one.
            PlayerReference3.Register(PlayerList3(0))  # Set the third player reference
            Print("PlayerReference3 set with Player 3 and Score: {PlayerList3(1)}")

    # Function to sort the player list by scores
    SortPlayerList(PlayerList:[]tuple(agent, int)):[]tuple(agent, int)=
        Print("Sorting Player List")  # Debug print
        var NewList: []tuple(agent, int) = PlayerList
        for:
            I := 0..NewList.Length - 1  # Outer loop for bubble sort
        do:
            for:
                J := 0..NewList.Length - I - 2  # Inner loop for bubble sort
                Item := NewList[J]  # Get the first player
                SecondItem := NewList[J + 1]  # Get the second player
                Item(1) < SecondItem(1)  # Compare the scores
            do:
                option{ set NewList[J] = SecondItem }  # Swap the players
                option{ set NewList[J + 1] = Item }  # Swap the players

        return NewList