How can I clear a Player Reference Device when the player changes teams?

Hi!

I’m trying to check if a player is registered on the Player Reference Device and get the player that did registere and have a loop to keep checking if that player is still on Team (team_settings_and_inventory_device) if(not Team.IsOnTeam[Player]) if not then I want to clear the reference device.

I tried few things but I keep getting errors!

Thanks in advance

Hey, try pairing them with attribute evaluators, the attribute evaluator will give you a pass or fail on various things including team, so when it fails a team check, you can use it’s on fail event to clear the player reference device it’s paired with

hey @_H121 how are you?!

I took this post as a challenge and tried to implemente it in the best way possible. My approach uses more Verse and less devices (only the Reference Devices, actually).

First of all, instead of looping to check if the player is still on a team, you should identify the cases where the player leaves the team. For example, the player leaves the team when disconnecting from the game, or you can change the players team when it dies.

Then you references your Reference Devices in arrays that corresponds to differente teams, something like this:

# Editable arrays of reference devices for each team
    @editable
    MyReferenceTeam1 : []player_reference_device = array{}
    @editable
    MyReferenceTeam2 : []player_reference_device = array{}

You also need a map to store the players and their teams, so you can keep track of the changes:

# MAP variable to store the current team for each player
    var PlayersTeams : [agent]int = map{}

After that, you will need to initialize that map with all the players that are in your island, as well as subscribe to players joining and leaving it:

OnBegin<override>()<suspends>:void=

        # Iterate over all players currently in the playspace
        for ( Agent : GetPlayspace().GetPlayers() ):
            # Add all players to Players' Teams map
            InitializePlayersMap( Agent )
            # Register all players to available Reference Devices
            RegisterToEmptyReferenceDevice( Agent )
        
        # Subscribe to new players joining the game
        GetPlayspace().PlayerAddedEvent().Subscribe( OnPlayerAdded )
        # Subscribe to players leaving the game
        GetPlayspace().PlayerRemovedEvent().Subscribe( RemoveIfNotInTeam )

The functions to populate the map and add players to that map when joining the game are:

    # Triggered when a new player joins        
    OnPlayerAdded ( Agent : agent ) : void =
        # Add new player to Players' Teams map
        InitializePlayersMap( Agent )
        # Register new player to available Reference Device
        RegisterToEmptyReferenceDevice( Agent )
    # Adds a player and their team to the PlayersTeams map
    InitializePlayersMap( Agent : agent ) : void =
        # Get all the teams in the island
        TeamCollection := GetPlayspace().GetTeamCollection()
        # Create teams array
        Teams := TeamCollection.GetTeams()
        # Check Agent's current team
        if ( PlayersTeam := TeamCollection.GetTeam[Agent] ):
            # Compare against each team to find the correct index
            for ( TeamIndex := 0..Teams.Length - 1 ):
                if ( Team := Teams[ TeamIndex ] ):
                    if ( PlayersTeam = Team ):
                        # Store player -> team index in the map
                        if ( set PlayersTeams[ Agent ] = TeamIndex ):

Then you have the functions to register the players to the reference devices. You should call the main function (RegisterToEmptyReferenceDevice) whenever you want to add a player to a new device:

    # Assigns a player to the first empty reference device of their team
    RegisterToEmptyReferenceDevice( Agent : agent ) : void =
        # Get all the teams in the island
        TeamCollection := GetPlayspace().GetTeamCollection()
        # Create teams array
        Teams := TeamCollection.GetTeams()
        # Check Agent's current team
        if ( PlayersTeam := TeamCollection.GetTeam[Agent] ):
            # Check which team the player belongs to and register accordingly
            for ( TeamIndex := 0..Teams.Length - 1 ):
                if ( Team := Teams[ TeamIndex ] ):
                    if ( PlayersTeam = Team ):
                        # Match team index to corresponding reference device array
                        case ( TeamIndex ): # You should add as many "cases" as Reference Devices arrays you have
                            0 => RegisterToTeam( Agent, TeamIndex, MyReferenceTeam1 )
                            1 => RegisterToTeam( Agent, TeamIndex, MyReferenceTeam2 )
                            _ => {} # Do nothing for other team indices

    # Helper function that registers a player to a specific team's reference device
    RegisterToTeam( Agent : agent, TeamIndex : int, ReferenceDevices : []player_reference_device ) : void =
        var Index : int = 0
        # Iterate over all Reference Devices of the corresponding team
        loop:
            if (Index >= ReferenceDevices.Length):
                break
            
            # Get the current reference device
            if(RefDevice := ReferenceDevices[Index]):
                # Check if it's already holding a player
                HasReference := RefDevice.GetAgent()
                if ( HasReference = false ):
                    # If empty, register this player
                    RefDevice.Register( Agent )
                    break
            
            set Index += 1

Lastly, you need to add the functions to remove the players from the corresponding Reference Devices. You only need to call “RemoveIfNotInTeam” when you want to remove a player:

    # Triggered when a player leaves or changes teams
    RemoveIfNotInTeam( Agent : agent ) : void =
        # Get all the teams in the island
        TeamCollection := GetPlayspace().GetTeamCollection()
        # Create teams array
        Teams := TeamCollection.GetTeams()
        # Check Agent's current team
        if ( PlayersTeam := TeamCollection.GetTeam[Agent] ):
            if (PlayersPreviousTeamInt := PlayersTeams[ Agent ] ):
                # Get the team they previously belonged to
                if ( PreviousTeam := Teams[PlayersPreviousTeamInt] ):
                    # If their team has changed
                    if ( PlayersTeam <> PreviousTeam ):
                        # Clear from old reference device
                        case ( PlayersPreviousTeamInt ):
                            0 => ClearRefDevice( Agent, PlayersPreviousTeamInt, MyReferenceTeam1, PlayersTeam )
                            1 => ClearRefDevice( Agent, PlayersPreviousTeamInt, MyReferenceTeam2, PlayersTeam )
                            _ => {} # Do nothing for other team indices / Keep adding teams avobe this line

    # Clears a player's reference device when they leave or switch teams
    ClearRefDevice( Agent : agent, TeamIndex : int, ReferenceDevices : []player_reference_device, CurrentTeam : team ) : void =
        # Search through all Reference Devices of the team
        for ( RefDevice : ReferenceDevices ):
            ReferencedAgent := RefDevice.GetAgent()
            if(ActualAgent := ReferencedAgent?):
                if ( ActualAgent = Agent ):
                    # Clear the device if it belongs to this agent
                    RefDevice.Clear()
                    # Check if the player's character still exists and is active
                    if ( Char := Agent.GetFortCharacter[] ):
                        if ( Char.IsActive[] ):
                            # Re-register the player into a free reference device
                            RegisterToEmptyReferenceDevice( Agent )
                            # Get all the teams in the island
                            TeamCollection := GetPlayspace().GetTeamCollection()
                            # Create teams array
                            Teams := TeamCollection.GetTeams()
                            for ( Index := 0..Teams.Length - 1 ):
                                if ( Team := Teams[ Index ] ):
                                    if ( CurrentTeam = Team ):
                                        # Update their new team index in the map
                                        if ( set PlayersTeams[ Agent ] = Index ):
                        else:
                            # If player is gone, rebuild the map without them
                            var NewMap : [agent]int = map{}
                            for ( Key -> Value : PlayersTeams ):
                                if ( Key <> Agent ):
                                    if ( set NewMap[Key] = Value ):
                            set PlayersTeams = NewMap

And that’s it. You only need to call the corresponding functions when someone leaves a team or joins the island. This way you don’t need to check in a loop. And you don’t need a lot of devices!

Hope this helps you! Let me know if you need more help with this! I’ll be glad to give you a hand!

2 Likes

thank you so much! helpful

1 Like