How do we remove player stats from weak map

Hello, I am having trouble to remove the player saved data when the player leaves the game I found these two videos

and the problem is they use a normal type of map, but I am using a weak map to keep track of the stats so is there a possible way to delete the stats when the player leaves?

OnPlayerRemoved(OutPlayer:player):void=
        if (ActualPlayer := PlayerStatsMap[OutPlayer]):
            var TempAllPlayersMap:[player]player_stats_table = map{}
            for (Key -> Value : PlayerStatsMap, Key <> OutPlayer ):
                set TempAllPlayersMap = ConcatenateMaps (TempAllPlayersMap, map{Key => Value})
            set PlayerStatsMap = TempAllPlayersMap```

If you don’t want to save player data between sessions or rounds you should use a normal map. But if you want to use a weak_map you can something like this should work

OnPlayerRemoved(OutPlayer:player):void=
            if:
                OutPlayer.IsActive[]
                set YourWeakMap[OutPlayer] = player_stats_table{}

You cannot concatenate a weak map so removing a key will not work you can also not loop over a weak map but you can remove the data by just constructing a new class or data type and basically reset the stats and then set the player data to the new created class/data type. OutPlayer.IsActive is also important because if you don’t have it, it can throw a verse runtime error.

If you wanna store data between sessions and round check out this page Using Persistable Data in Verse | Unreal Editor for Fortnite Documentation | Epic Developer Community

1 Like

I am sorry for the late answer, but thank you it did work, I have a question, when the player leaves it does delete it’s saved stats but how do i assign to him the current stats of the round?
to put you in context; I am using this persistable as a score and the only thing i found on how to do it is using persistable data and i am using the player to track that score instead of the team. I want when the player who just joined to have the same score as the current players

Something you can do is grab the team collection then check what agents is on that team so if the new player should join team 1 you get fort_playspace.GetTeamCollection().GetAgents[0] where 0 is team 1 and 1 is team 2 like a index in arrays. Then you loop over the array you get in return find a new agent(agent that isn’t the agent that just joined the team) convert them into a player player[Agent] and then get their score and set the new players score to that score you got :slight_smile:

Thank you for the idea it really helped it just had one flow in my case, if a player joins and there is no one on the team the script will probably won’t work so instead of getting the players on the same team i just grabbed all the existing players and then got their score, and I think it worked, I also noticed that when a game ends it doesnt count as players left the session and I have no idea if it actually reset the score or not but that is something I will see it later but anyway thank you for that idea :grin:

I’ve been using this “solved” snippet as reference and I’ve tried many things something is alwaysa problem for my verse code it seems, and I can’t get it to work. Perhaps there is something here that is implied that I’m not understanding? I’ve been looking at the official pages " Using Persistable Data in Verse" and " Persistent Player Statistics" and I’m still not understanding.

that snippet reset the weak map to its origianl value, all you have to do is copy and paste it as is and change YourWeakMap] to the name of your weak map and player_stats_table to the name of the class that have the default values

for (Key → Value : PlayerMap) {
if (Key <> Agent) {
set TempPlayerMap = ConcatenateMaps(TempPlayerMap, map{Key => Value})
}
}
set PlayerMap = TempPlayerMap
}
}
}‘’’

This is what I currently use how do I find the classes and name of the map?

if you are using a normal map then this is how to do it

but if you are using a weak map like this one

then the solution is that snippet

I’m using

‘’'vplayer_data := class{
StoredMoney : int = 0
StoredPistol1 : int = 0
StoredPistol2 : int = 0
StoredPistol3 : int = 0
StoredPistol4 : int = 0
StoredPistol5 : int = 0
StoredSmg1 : int = 0
StoredSmg2 : int = 0
StoredSmg3 : int = 0
StoredSmg4 : int = 0
StoredSmg5 : int = 0
StoredShotgun1 : int = 0
StoredShotgun2 : int = 0
StoredShotgun3 : int = 0
StoredShotgun4 : int = 0
StoredShotgun5 : int = 0
StoredSniper1 : int = 0
StoredSniper2 : int = 0
StoredSniper3 : int = 0
StoredSniper4 : int = 0
StoredRocketl1 : int = 0
StoredRocketl2 : int = 0
StoredRocketl3 : int = 0
StoredRocketl4 : int = 0
StoredAssaultr1 : int = 0
StoredAssaultr2 : int = 0
StoredAssaultr3 : int = 0
StoredAssaultr4 : int = 0
StoredAssaultr5 : int = 0
StoredAssaultr6 : int = 0
}

player_data_update(OldStat:player_data) := player_data{
StoredMoney := OldStat.StoredMoney
StoredPistol1 := OldStat.StoredPistol1
StoredPistol2 := OldStat.StoredPistol2
StoredPistol3 := OldStat.StoredPistol3
StoredPistol4 := OldStat.StoredPistol4
StoredPistol5 := OldStat.StoredPistol5
StoredSmg1 := OldStat.StoredSmg1
StoredSmg2 := OldStat.StoredSmg2
StoredSmg3 := OldStat.StoredSmg3
StoredSmg4 := OldStat.StoredSmg4
StoredSmg5 := OldStat.StoredSmg5
StoredShotgun1 := OldStat.StoredShotgun1
StoredShotgun2 := OldStat.StoredShotgun2
StoredShotgun3 := OldStat.StoredShotgun3
StoredShotgun4 := OldStat.StoredShotgun4
StoredShotgun5 := OldStat.StoredShotgun5
StoredSniper1 := OldStat.StoredSniper1
StoredSniper2 := OldStat.StoredSniper2
StoredSniper3 := OldStat.StoredSniper3
StoredSniper4 := OldStat.StoredSniper4
StoredRocketl1 := OldStat.StoredRocketl1
StoredRocketl2 := OldStat.StoredRocketl2
StoredRocketl3 := OldStat.StoredRocketl3
StoredRocketl4 := OldStat.StoredRocketl4
StoredAssaultr1 := OldStat.StoredAssaultr1
StoredAssaultr2 := OldStat.StoredAssaultr2
StoredAssaultr3 := OldStat.StoredAssaultr3
StoredAssaultr4 := OldStat.StoredAssaultr4
StoredAssaultr5 := OldStat.StoredAssaultr5
StoredAssaultr6 := OldStat.StoredAssaultr6
}

var Data:weak_map(player, player_data) = map{}‘’‘’

so for player_stats_table its every last one of these?

I guess what I’m not understanding is: What is the “player_stats_table{}” is it the list entirely ? like should I name or state it as a list as a whole collective category to make an array type of table? or is it each and every last one separately that is a table?

UPDATE: I think I’ve figured out that “'player_data”’ is my table. I’m eager to try it, but fortnite servers are down apparently?

I use this:

‘’‘var Data:weak_map(player, player_data) = map{}’‘’’ so weak_map is my “weakmap” and player_data is my player_stats_table right?

Possibly the only thing I need help with now is what to put for ‘’‘[OutPlayer]’‘’’

This is where I’m at now my snippet looks like this:

‘’‘OnPlayerRemoved(OutPlayer:player):void=
if:
OutPlayer.IsActive
set Data[OutPlayer] = player_data{}’‘’

and the error I am getting is posted below:

An unrecoverable Verse runtime error occurred: Verse unrecoverable error: ErrRuntime_WeakMapInvalidKey: Invalid key used to access persistent var weak_map.

Truncated callstack follows:
task’ltimate?ice$UpdateValues(:player):Update (Unknown source) (Source: Unknown(0,0, 0,0))

I have been returning back to this almost every hour to see if anyone has posted a real solution. I have spent approximately 100 hours on trying to fix this now and I’m starting to think everyone else knows that it plain can’t be done or something? I’m ready to give up I followed a few different YouTube tutorials and designed my code over on new maps a different way and it all ends in the same issue. I’ve posted on discord, this forum multiple times, reached out to old friends I have that do programming for a living and all has come up unsuccessful.

I’m going to move on and I guess try to duplicate my map and revert it back to where it was before I started using verse code because it just breaks your map.

The error you getting is when the player you trying to access is not in the fort_playspace. This is often fixed by checking if the player is active. So EVERYTIME you read or write to the Data variable you should check if the player you trying to access is active by just checking player.IsActive and if it fail you should not read or write to the Data variable. I don’t really know how your code looks but in this case the UpdateValues() function is the one crashing and not OnPlayerRemoved. So you probably write or read to the Data variable in the UpdateValues() function. So make sure you check if the player is active before reading or write to the Data variable.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.