using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /Verse.org/Random }
using { /Fortnite.com/Characters }
using { /Fortnite.com/Game }
team_handler := class:
Index:int
Device:team_manager
HandlerTrigger(MaybeAgent:?agent):void=
if (Agent := MaybeAgent?):
Device.SetTeam(Agent,Index + 1)
team_manager := class(creative_device):
@editable TeamSelectors<private>:[]class_and_team_selector_device = array{}
@editable ClassCheckTriggers<private>:[]trigger_device = array{}
@editable RoundManager<private>:round_manager = round_manager{}
# Store the team number for each agent in a map
var TeamMap<private>:[agent]int = map{}
# On join in progress, go to this team
#
# ! Make sure to set ISLAND SETTING default class to 5 as well so that on the start of round 1
# everyone is put in this team using LoadTeamFromClass() !
TeamOnProgressJoin<private>:int = 5
# If 1 team remains, set this to the team number of the winners
var WinningTeam<public>:?int = false
# When set to false newly joining players will be killed and put into spectator mode
var AllowJoin<public>:logic = true
OnBegin<override>()<suspends>:void={
SubscribeAll()
LoadTeamFromClass()
}
# Get team number of agent
GetTeam<public>(Agent:agent)<transacts>:int={
if(TeamNumber := TeamMap[Agent]):
return TeamNumber
else:
return -1
}
# TODO, update function when persistance is out
# Set team for an agent using TeamSelector & update the TeamMap
SetTeam<public>(Agent:agent,Team:int):void={
if(TeamSelector := TeamSelectors[Team-1]):
TeamSelector.ChangeTeam(Agent)
if(set TeamMap[Agent] = Team){}
else:
Print("ERROR: Unable to switch agent to team {Team} in Team_Manager/SetTeam")
}
# Eliminate Agent
KillAgent<public>(InAgent:agent):void={
if(FortCharacter := InAgent.GetFortCharacter[]):
FortCharacter.Damage(200.0)
}
# Get all Agents in the Experience
GetAllAgents<public>()<transacts>:[]agent={
return Self.GetPlayspace().GetPlayers()
}
# Get a random Agent that has not been eliminated
GetRandomActiveAgent<public>()<decides><transacts>:agent={
ActiveAgents := for:
Agent:GetAllAgents()
FortCharacter := Agent.GetFortCharacter[]
FortCharacter.IsActive[]
do:
Agent
Index := GetRandomInt(0,ActiveAgents.Length)
return ActiveAgents[Index]
}
# Get a list of Agents that are on this team
GetAgentsInTeam<public>(Team:int):[]agent={
Agents := for:
Agent:GetAllAgents()
GetTeam(Agent) = Team
do:
Agent
return Agents
}
# TODO, update function when persistance is out
# Subscribe all devices
SubscribeAll<private>():void={
Self.GetPlayspace().PlayerAddedEvent().Subscribe(OnPlayerAdded)
Self.GetPlayspace().PlayerRemovedEvent().Subscribe(OnPlayerRemoved)
for(X -> Trigger:ClassCheckTriggers):
Handler := team_handler{Index := X,Device := Self}
Trigger.TriggeredEvent.Subscribe(Handler.HandlerTrigger)
for(InAgent:GetAllAgents()):
if(FortCharacter := InAgent.GetFortCharacter[]):
FortCharacter.EliminatedEvent().Subscribe(OnPlayerEliminated)
}
# Handle player joining the island
OnPlayerAdded<private>(Agent:agent):void={
if(RoundManager.RoundNumber <= 1 and AllowJoin?):
SetTeam(Agent, TeamOnProgressJoin)
else:
# Players that join after round 2 should spectate
KillAgent(Agent)
}
# Handle player leaving the island
OnPlayerRemoved<private>(Agent:agent):void={
RemoveAgentFromMap(Agent) # TODO check if it maybe already auto removes from map on leave
# Check if only 1 team remains on remove
LMS()
}
# TODO, update function when persistance is out
# On Round start set all players to the right team
LoadTeamFromClass<private>():void={
for:
Trigger:ClassCheckTriggers
Agent:GetAllAgents()
do:
Trigger.Trigger(Agent)
}
# Set member variable WinningTeam to winner. Use in main.verse to end the round
LMS<private>()<transacts>:void={
# Put the teamsize for each team in a map from TeamNumber => TeamSize
var TeamCounterMap:[int]int = map{}
for:
Agent:GetAllAgents()
FortCharacter := Agent.GetFortCharacter[]
FortCharacter.IsActive[]
do:
if(set TeamCounterMap[GetTeam(Agent)] += 1){}
# Count the teams in the map
TeamsAlive := for:
TeamSize:TeamCounterMap
TeamSize >= 1
do:
+1
# On LMS, set WinningTeam value
if(TeamsAlive = 1):
if (Agent := GetRandomActiveAgent[]):
set WinningTeam = option{GetTeam(Agent)}
}
# Check LMS on Eliminated
OnPlayerEliminated<private>(Result:elimination_result):void={
# Check if only 1 team remains on remove
LMS()
}
# Removes an element from the given map and returns a new map without that element
RemoveAgentFromMap<private>(PlayerToRemove:agent):[agent]int=
var NewMap:[agent]int = map{}
for (Player -> Team:TeamMap, Player <> PlayerToRemove):
set NewMap = ConcatenateMaps(NewMap, map{Player => Team})
return NewMap
The round manager used:
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
round_handler := class:
Index:int
Device:round_manager
HandlerRoundStart():void=
set Device.RoundNumber = Index + 1
round_manager := class(creative_device):
@editable Rounds<private>:[]round_settings_device = array{}
var RoundNumber:int = 0
OnBegin<override>()<suspends>:void={
SubscribeAll()
}
# Everything that subscribes goes here
SubscribeAll<private>():void={
for(X -> CurrentRound:Rounds){
Handler := round_handler{Index := X,Device := Self}
CurrentRound.RoundBeginEvent.Subscribe(Handler.HandlerRoundStart)
}
}
I have a custom score setup with teams in my map and I need to set which teams wins the round so I was wondering about how the WinningTeam works? Can you specify which team wins with this, and if so, how would I do that at the end of the round?
You mention in the code “# Set member variable WinningTeam to winner. Use in main.verse to end the round” but what is in main.verse?
In all my maps I always have a main.verse that contains the main game loop. It is the file where everything comes together, granting loot, grant kill rewards, end round.
I recently added this to the teammanager verse file:
# Completes on LMS, returns the Last Standing Team
AwaitLMS<public>()<suspends>:int={
loop:
if(TeamNumber := WinningTeam?):
return TeamNumber
Sleep(0.01)
}
An in my main I do this:
Onbegin:
Grant guns, teleport players, generate storm
and at the end I call:
# End the round, grant rewards etc
EndRound(WinningTeam:int)<suspends>:void={
VoteManager.GrantIDItem()
SettingsManager.GrantIDItems()
Sleep(0.0)
if(WinningAgent := TeamManager.GetRandomActiveAgent[]):
EndRoundTracker.Complete(WinningAgent)
}
# Tracker has settings to end round on complete and grant activating team the win.
WinningTeam is the team number of the last team standing, for example Team 15 gives 15.
Teams are saved as an int in TeamMap. In my map I let players select a team in round 1, when selected they will switch to a class too. I read this class at round start using triggers to set them back to the correct team, as teams reset in between rounds.
You dont need them anymore, I found a better way to set and get team:
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /Verse.org/Random }
using { /Fortnite.com/Characters }
using { /Fortnite.com/Game }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /UnrealEngine.com/Temporary/SpatialMath}
using { /Fortnite.com/FortPlayerUtilities }
using { config }
team_manager := class(creative_device):
@editable RoundManager<private>:round_manager = round_manager{}
@editable TrackerSaveTeam:tracker_device = tracker_device{}
@editable SpectateSwitch:switch_device = switch_device{}
@editable CheckSpectateStateTrigger:trigger_device = trigger_device{}
@editable NewPlayerSwitch:switch_device = switch_device{}
@editable NoClass<private>:class_and_team_selector_device = class_and_team_selector_device{}
Logger<private>:log = log{Channel:=log_device}
# If 1 team remains, set this to the team number of the winners
var WinningTeam<public>:?int = false
var PlayingAgents:[]agent = array{}
var SpectateMap:[agent]logic = map{}
OnBegin<override>()<suspends>:void={
SubscribeAll()
RoundManager.WaitForRoundBeginEvent()
for(Agent:GetAllAgents()):
if(FC := Agent.GetFortCharacter[]):
FC.EliminatedEvent().Subscribe(OnPlayerEliminated)
if(RoundManager.CurrentRound = 1):
TrackerSaveTeam.ClearPersistence(Agent)
SpectateSwitch.ClearPersistenceData(Agent)
else:
SetTeam(Agent, TrackerSaveTeam.GetValue(Agent))
SpectateSwitch.CheckState(Agent)
}
# Get team number of agent
GetTeam<public>(Agent:agent)<transacts>:int={
TeamCollection := Self.GetPlayspace().GetTeamCollection()
if(AgentTeam := TeamCollection.GetTeam[Agent]):
for(I -> Team:TeamCollection.GetTeams()):
if(AgentTeam = Team):
return I+1
return -1
}
# Set team for an agent
SetTeam<public>(Agent:agent,TeamNumber:int):void={
TeamCollection := Self.GetPlayspace().GetTeamCollection()
if(Team := TeamCollection.GetTeams()[TeamNumber-1]):
if(TeamCollection.AddToTeam[Agent, Team]){}
TrackerSaveTeam.SetValue(Agent,TeamNumber)
}
#Heal agent for Amount
HealAgent<public>(Agent:agent, Amount:float):void={
if(FortCharacter := Agent.GetFortCharacter[]):
HP := FortCharacter.GetHealth()
Shield := FortCharacter.GetShield()
HPMissing := FortCharacter.GetMaxHealth() - HP
FortCharacter.SetHealth(Clamp(HP + Amount,0.0,FortCharacter.GetMaxHealth()))
FortCharacter.SetShield(Clamp(Shield + Clamp(Amount - HPMissing,0.0,Amount),0.0,FortCharacter.GetMaxShield()))
}
# Get all Agents in the Experience, spectators too
GetAllAgents<public>()<transacts>:[]agent={
return Self.GetPlayspace().GetPlayers()
}
# Gets all active agents in these teams: Teams
GetAllActiveAgents<public>()<transacts>:[]agent={
ActiveAgents := for:
Agent:GetAllAgents()
FortCharacter := Agent.GetFortCharacter[]
FortCharacter.IsActive[]
do:
Agent
return ActiveAgents
}
GetFightingAgents<public>()<transacts>:[]agent={
Agents := for:
Agent:GetAllAgents()
FortCharacter := Agent.GetFortCharacter[]
FortCharacter.IsActive[]
#not EliminatedMap[Agent]?
do:
Agent
return Agents
}
# Returns an array with all the teams that are still alive
GetFightingTeams<public>()<transacts>:[]int={
# Put the teamsize for each team in a map from TeamNumber => TeamSize
var ActiveTeams:[]int = array{}
for:
Agent:GetFightingAgents()
FortCharacter := Agent.GetFortCharacter[]
FortCharacter.IsActive[]
do:
TeamNumber := GetTeam(Agent)
set ActiveTeams += array{TeamNumber}
return SortArray(RemoveDuplicates(ActiveTeams))
}
# Get a random Agent that has not been eliminated
GetRandomActiveAgent<public>()<decides><transacts>:agent={
ActiveAgents := GetAllActiveAgents()
Index := GetRandomInt(0,ActiveAgents.Length - 1)
return ActiveAgents[Index]
}
# Get a random Agent
GetRandomAgent<public>()<decides><transacts>:agent={
Agents := GetAllAgents()
Index := GetRandomInt(0,Agents.Length - 1)
return Agents[Index]
}
# Get a list of Agents that are on this team
GetAgentsInTeam<public>(Team:int)<transacts>:[]agent={
Agents := for:
Agent:GetAllAgents()
GetTeam(Agent) = Team
do:
Agent
return Agents
}
CheckLMS<private>()<suspends>:void={
Sleep(0.0)
LMS()
}
# Set member variable WinningTeam to winner. Use in main.verse to end the round
LMS<public>()<transacts>:?int={
# On LMS, set WinningTeam value
set WinningTeam = false
PlayingTeams := RemoveFromArray(GetFightingTeams(), SpectateTeam)
if(PlayingTeams.Length = 1):
set WinningTeam = option{PlayingTeams[0]}
else if(PlayingTeams.Length < 1):
if(RandomAgent := GetRandomAgent[]):
set WinningTeam = option{GetTeam(RandomAgent)}
return WinningTeam
}
# Completes on LMS, returns the Last Standing Team
AwaitLMS<public>()<suspends>:int={
set WinningTeam = false
spawn {CheckLMS()}
loop:
if(TeamNumber := WinningTeam?):
return TeamNumber
Sleep(0.01)
}
AwaitMaxPlayersLoaded()<suspends>:void={
loop:
Sleep(0.5)
if(PlayingAgents.Length >= MaxPlayerCount):
break
}
# Returns an array with all the teams that are still alive
GetActiveTeams<public>()<transacts>:[]int={
# Put the teamsize for each team in a map from TeamNumber => TeamSize
var ActiveTeams:[]int = array{}
for:
Agent:GetAllAgents()
FortCharacter := Agent.GetFortCharacter[]
FortCharacter.IsActive[]
do:
TeamNumber := GetTeam(Agent)
set ActiveTeams += array{TeamNumber}
return SortArray(RemoveDuplicates(ActiveTeams))
}
# TODO, update function when persistance is out
# Subscribe all devices
SubscribeAll<private>():void={
NewPlayerSwitch.TurnedOnEvent.Subscribe(OnPlayerAdded)
Self.GetPlayspace().PlayerRemovedEvent().Subscribe(OnPlayerRemoved)
SpectateSwitch.TurnedOnEvent.Subscribe(SpectateButtonTurnedOn)
SpectateSwitch.TurnedOffEvent.Subscribe(SpectateButtonTurnedOff)
}
SpectateButtonTurnedOn(Agent:agent):void={
if(set SpectateMap[Agent] = true){}
}
SpectateButtonTurnOn(MaybeAgent:?agent):void={
if(Agent := MaybeAgent?):
if(set SpectateMap[Agent] = true){}
}
SpectateButtonTurnedOff(Agent:agent):void={
if(set SpectateMap[Agent] = false){}
}
# Handle player joining the island
OnPlayerAdded<private>(Agent:agent):void={
SpectateSwitch.ClearPersistenceData(Agent)
TrackerSaveTeam.ClearPersistence(Agent)
if(FC := Agent.GetFortCharacter[]):
FC.EliminatedEvent().Subscribe(OnPlayerEliminated)
}
# Handle player leaving the island
OnPlayerRemoved<private>(Agent:agent):void={
if(Temp := PlayingAgents.RemoveFirstElement[Agent]){set PlayingAgents = Temp}
# Check if only 1 team remains on remove
spawn {CheckLMS()}
}
# Check LMS on Eliminated
OnPlayerEliminated<private>(Result:elimination_result):void={
Print("Player eliminated in team manager")
spawn {CheckLMS()}
}
RespawnAgents<public>()<suspends>:void={
for(Agent:GetAllAgents()):
#if(GetTeam(Agent) <> SpectateTeam and EliminatedMap[Agent]?):
if(GetTeam(Agent) <> SpectateTeam and not Agent.GetFortCharacter[].IsActive[]):
spawn{RespawnAgent(Agent)}
}
RespawnAgent<public>(Agent:agent)<suspends>:void={
if(FortCharacter := Agent.GetFortCharacter[]):
if(not FortCharacter.IsActive[]):
Agent.Respawn(FortCharacter.GetTransform().Translation,FortCharacter.GetViewRotation())
Sleep(0.0)
NoClass.ChangeClass(Agent)
}