I’ve stepped through this documentation twice now, from scratch, and the Join In Progress functionality is incomplete.
I’ve copied the script exactly from the final result page.
I’ve recruited a friend, and added them to my Team so they can join. When they join the game in progress, it loads them in, and the logs indicate that everything worked correctly, but they are not granted a weapon when they spawn. And they can’t get a kill because they don’t spawn with a weapon.
I’ve fiddled with the code, but I’m stuck.
Have I done something wrong, or is this documentation missing something?
logs from player joining the game (last 5 lines are from killing a sentry, see time code 13:49 - 13:55 for relevant logs)
I checked out that tutorial but have not tried it with multiplayer yet and new players joining. But could it be that in the “OnPlayerAdded” function you get a player in, while the “Grantweapon” expects an agent to work? so if you try to convert the player to agent it might work?
Its confusing me a little when they use InPlayer but its to be an agent etc. I think one place this was wrong in the tutorial code as well. But i’m still new to this verse coding. It might be that player and agent are interchangeable, but if its not I think one should be careful to make the difference in var names in code as well.
edit : I did some testing and you can probably ignore everything I have said But the problem seems to be something with how it registers joining and addind to a team. If you start off with 2 people it all works as it should. If one leaves and then joins again this also works fine. If you start with just one and then someone joins some weird stuff happens.
Ok, so tested some more and seems that the issue is with when the player gets assigned to a team. If you handle the team assignment manually in the “OnPlayerAdded” it should be ok.
I tested with handling the new player within the “OnPlayerSpawn”, just checked if the player who spawns was stored in the “TeamMap”, if not I created a new entry for that player and granted the starter weapon.
Things seems to work fine but I have had some weird stuff still happening when the new player first spawns in and use a different team spawner though so who knows.
Would you be able to provide your edited script, if it does indeed fix the issue?
Then I can provide the fixed code and mark this question as resolved.
Not sure if it fixes the issue exactly or even is correctly set up so cant guarantee anything there, but maybe it can help you figure out a better way. I have not had the time to do any further testing or refactoring so the code is messy. What I did to test it was this:
OnPlayerAdded function changed to:
OnPlayerAdded(InPlayer : player) : void =
Print("A New Player Joined!")
if:
FortCharacter := InPlayer.GetFortCharacter[]
then:
FortCharacter.EliminatedEvent().Subscribe(OnPlayerEliminated)
OnPlayerSpawn function changed to:
OnPlayerSpawn(Agent : agent) : void =
Print("A player just spawned!")
if(PlayerTeam := GetPlayspace().GetTeamCollection().GetTeam[Agent]):
if(TeamPlayer := player[Agent]):
var WeaponTier : int = 0
if(TeamMap[PlayerTeam][TeamPlayer]):
if(set WeaponTier = TeamMap[PlayerTeam][TeamPlayer]):
GrantWeapon(option{Agent}, WeaponTier)
else:
if (var PlayerMap : player_map = TeamMap[PlayerTeam]):
if(set PlayerMap[TeamPlayer] = 0):
if(set TeamMap[PlayerTeam] = PlayerMap):
GrantWeapon(option{Agent}, WeaponTier)
For any why might find this useful, here is the final script. It is the same as in the tutorial, but with two updated methods, thanks to @borgb
using { /Fortnite.com/Characters }
using { /Fortnite.com/Devices }
using { /Fortnite.com/Game }
using { /Fortnite.com/Teams }
using { /Verse.org/Simulation }
player_map := [player]int # This is a type alias!
team_elimination_game := class(creative_device):
@editable
EndGameDevice : end_game_device = end_game_device{}
@editable
var WeaponGranters : []item_granter_device = array{}
@editable
var PlayerSpawners : []player_spawner_device = array{}
@editable
var Sentries : []sentry_device = array{}
var EliminationsToEndGame : int = 0
var Teams : []team = array{}
# Map of Team Maps, where the key is the team and the value is a map of
# player->int key-value pairs
var TeamMap : [team]player_map = map{}
OnBegin<override>()<suspends> : void =
set Teams = GetPlayspace().GetTeamCollection().GetTeams()
set EliminationsToEndGame = WeaponGranters.Length
Print("Beginning to assign players")
PopulateTeamsAndPlayers()
for (Spawner : PlayerSpawners):
Spawner.SpawnedEvent.Subscribe(OnPlayerSpawn) # Subscribe to each player spawn pad
for (Sentry : Sentries):
Sentry.EliminatedEvent.Subscribe(TestPlayerEliminated) # Subscribe to each Sentry
# Subscribe to new players joining the game
GetPlayspace().PlayerAddedEvent().Subscribe(OnPlayerAdded)
PopulateTeamsAndPlayers() : void =
Print("Beginning to populate players")
for (Team : Teams, TeamPlayers := GetPlayspace().GetTeamCollection().GetAgents[Team]):
var PlayerMap : player_map = map {}
for (Agent : TeamPlayers, TeamPlayer := player[Agent], FortCharacter := Agent.GetFortCharacter[]):
if(set PlayerMap[TeamPlayer] = 0, WeaponTier := PlayerMap[TeamPlayer]):
Print("Assigned Player to PlayerMap with Tier {WeaponTier}")
FortCharacter.EliminatedEvent().Subscribe(OnPlayerEliminated)
if(set TeamMap[Team] = PlayerMap):
Print("Successfully set this team in the TeamMap")
# Handles a new player joining the game
OnPlayerAdded(InPlayer : player) : void =
Print("A New Player Joined!")
if:
FortCharacter := InPlayer.GetFortCharacter[]
then:
FortCharacter.EliminatedEvent().Subscribe(OnPlayerEliminated)
# Grants players weapons based on their WeaponTier when they spawn
OnPlayerSpawn(Agent : agent) : void =
Print("A player just spawned!")
if(PlayerTeam := GetPlayspace().GetTeamCollection().GetTeam[Agent]):
if(TeamPlayer := player[Agent]):
var WeaponTier : int = 0
if(TeamMap[PlayerTeam][TeamPlayer]):
if(set WeaponTier = TeamMap[PlayerTeam][TeamPlayer]):
GrantWeapon(option{Agent}, WeaponTier)
else:
if (var PlayerMap : player_map = TeamMap[PlayerTeam]):
if(set PlayerMap[TeamPlayer] = 0):
if(set TeamMap[PlayerTeam] = PlayerMap):
GrantWeapon(option{Agent}, WeaponTier)
OnPlayerEliminated(Result : elimination_result) : void =
Print("A Player was eliminated!")
Eliminator := Result.EliminatingCharacter
if (FortCharacter := Eliminator?, EliminatorAgent := FortCharacter.GetAgent[]):
GiveNextWeapon(EliminatorAgent)
# Allows testing of GiveNextWeapon by spoofing Sentries as Players
TestPlayerEliminated(Agent: ?agent) : void =
Print("Sentry Down!")
if(TeamPlayer := Agent?):
GiveNextWeapon(TeamPlayer)
GiveNextWeapon(EliminatingPlayer : agent) : void =
Print("Finding a player to promote")
var WeaponTier : int = 0
var MaybePlayerToGrant : ?agent = option{EliminatingPlayer} # The player to grant a gun to
var MaybePlayerTeam : ?team = option{GetPlayspace().GetTeamCollection().GetTeam[EliminatingPlayer]} # The team this player is on
if(PlayerTeam := MaybePlayerTeam?, set WeaponTier = TeamMap[PlayerTeam][EliminatingPlayer]):
for(Teammate -> TeammateTier : TeamMap[PlayerTeam], TeammateTier < WeaponTier):
Print("Found a Teammate with a lower Tier at Tier {TeammateTier}")
if(set WeaponTier = TeamMap[PlayerTeam][Teammate]):
set MaybePlayerToGrant = option{Teammate}
set WeaponTier = WeaponTier + 1
if(PlayerTeam := MaybePlayerTeam?, PlayerToGrant := player[MaybePlayerToGrant?], set TeamMap[PlayerTeam][PlayerToGrant] = WeaponTier):
Print("Eliminating Player Tier is now {WeaponTier}")
if(WeaponTier >= EliminationsToEndGame):
EndGame(EliminatingPlayer)
GrantWeapon(MaybePlayerToGrant, WeaponTier)
GrantWeapon(InPlayer : ?agent, WeaponTier : int) : void =
Print("Promoting Player to Tier {WeaponTier}")
if(ItemGranter := WeaponGranters[WeaponTier], GrantedPlayer := InPlayer?):
ItemGranter.GrantItem(GrantedPlayer)
EndGame(InPlayer : agent) : void =
Print("Player reached final Weapon Tier, activating EndGameDevice")
EndGameDevice.Activate(InPlayer)
I have noticed that a player gets a point and a new weapon when he killed himself?
I tried to use in OnPlayerEliminated this to prevent this:
if (Result.EliminatingCharacter = Result.EliminatedCharacter):
But it doesn’t fix that
You are going to want to get the eliminated agent and eliminating agent and compare them like this:
if(KilledAgent := Result.EliminatedCharacter.GetAgent[]): #Attempt to get the Agent for the eliminated fort_char
if(KillerChar := Result.EliminatingCharacter?): #A optional agent is returned here so we need to check its not false using ?
if(KillerAgent := KillerChar.GetAgent[]): #Once we know we have a killing char, we then get its agent.
#Now we know the player was killed by another player here and we have both of them!
#So lets start by checking if the Killer is also the Killed! Self elimination
if(KillerAgent <> KilledAgent): #Check the killer agent and killed agent are not the same
Also the reason this script is having issues with the join in progress using the PlayerAddedEvent but works when switching to the PlayerSpawned function and checking if the player exists in the map is because when the PlayerAddedEvent is triggered it is not a guarntee that the player is actually fully loaded in. It seems like there is a psudeo agent players get assigned to when first loading in and then that gets replaced with the real agent once they are fully loaded. The PlayerAddedEvent gets a hold of the “fake agent” and runs with it, your item granter fails to give the player the items because they don’t actually exist yet. You can either make a loop that waits for the joining agents FortCharacter to pass IsValid or simply do the setup in the OnSpawned because by that point you know the agent is safe to use.