haxis/Source/UnrealProject/GameState/GameStateBase.cpp

201 lines
4.6 KiB
C++

#include "UnrealProject.h"
#include "GameStateBase.h"
#include "PlayerStateBase.h"
#include "DefaultPlayerController.h"
#include "DefaultGameInstance.h"
#include "MapData.h"
AGameStateBase::AGameStateBase()
{
m_mapTeamCount = 4;
m_hasWarnedFrank = false;
}
void AGameStateBase::BeginPlay()
{
Super::BeginPlay();
mapPath = GetWorld()->GetPathName();
m_LoadActiveMapInfo();
}
void AGameStateBase::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
Super::EndPlay(EndPlayReason);
OnPlayerStateChange.Clear();
}
void AGameStateBase::RegisterPlayer(APlayerControllerBase* player)
{
check(Role == ROLE_Authority);
check(player);
APlayerStateBase* state = Cast<APlayerStateBase>(player->PlayerState);
check(state);
m_playersByController.Add(player, state);
m_players.Add(state);
// More than 1 player in editor means multiplayer in PIE mode
if(m_players.Num() > 1)
{
EnterLobby();
}
OnPlayerStateChange.Broadcast(nullptr);
}
void AGameStateBase::DeregisterPlayer(APlayerControllerBase* player)
{
check(Role == ROLE_Authority);
m_playersByController.Remove(player);
m_players.SetNum(0);
for(auto it = m_playersByController.CreateIterator(); it; ++it)
{
m_players.Add(it->Value);
}
OnPlayerStateChange.Broadcast(nullptr);
}
void AGameStateBase::EnterLobby()
{
check(Role == ROLE_Authority);
for(auto it = m_playersByController.CreateIterator(); it; ++it)
{
it->Key->EnterLobby();
}
}
void AGameStateBase::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(AGameStateBase, m_players);
DOREPLIFETIME(AGameStateBase, m_mapTeamCount);
DOREPLIFETIME(AGameStateBase, mapPath);
}
TArray<class APlayerStateBase*>& AGameStateBase::GetPlayers()
{
return m_players;
}
TArray<TArray<class APlayerStateBase*>> AGameStateBase::GetPlayersByTeam()
{
TArray<TArray<class APlayerStateBase*>> ret;
for(int32 i = 0; i < m_players.Num(); i++)
{
APlayerStateBase* player = m_players[i];
if(!player)
continue;
int32 team = player->GetTeam();
if(team >= ret.Num())
{
ret.SetNum(team + 1);
}
TArray<class APlayerStateBase*>& dstArray = ret[team];
dstArray.Add(player);
}
return ret;
}
TArray<int32> AGameStateBase::GetTeamSizes()
{
TArray<int32> teamSizes;
teamSizes.SetNumZeroed(m_mapTeamCount);
for(int32 i = 0; i < m_players.Num(); i++)
{
if(!m_players[i])
continue;
int32 team = m_players[i]->GetTeam() - 1;
if(team < 0 || team >= m_mapTeamCount)
continue;
teamSizes[team]++;
}
return TArray<int32>(teamSizes);
}
int32 AGameStateBase::GetOptimalAutoJoinTeam()
{
if(GetWorld()->IsPlayInEditor())
{
// PIE uses different assignment, default to 2 players per team and then move to the next team
TArray<int32> teamSize = GetTeamSizes();
int32 optimalTeam = -1;
for(int32 i = 0; i < m_mapTeamCount; i++)
{
if(teamSize[i] < 2)
{
optimalTeam = i;
break;
}
}
return optimalTeam + 1;
}
else
{
TArray<int32> teamSize = GetTeamSizes();
int32 smallestSize = 2;
int32 optimalTeam = -1;
for(int32 i = 0; i < m_mapTeamCount; i++)
{
if(teamSize[i] < smallestSize)
{
optimalTeam = i;
smallestSize = teamSize[i];
}
}
return optimalTeam + 1;
}
}
int32 AGameStateBase::GetMapTeamCount() const
{
return m_mapTeamCount;
}
UMapData* AGameStateBase::GetMapData() const
{
return m_mapData;
}
void AGameStateBase::m_OnRep_MapPath()
{
GPRINT("Map changed to " + mapPath);
m_LoadActiveMapInfo();
if(m_mapData)
GPRINT("Found attached map data " + m_mapData->GetName());
else
GERROR("No attached map data found.");
}
void AGameStateBase::OnPlayerStateChange_Multi_Implementation()
{
if (m_playersByController.Num() > 0)
OnPlayerStateChange.Broadcast(nullptr);
}
TMap<APlayerControllerBase*, APlayerStateBase*> AGameStateBase::GetPlayersByController()
{
return m_playersByController;
}
bool AGameStateBase::m_LoadActiveMapInfo()
{
UDefaultGameInstance* gameInstance = Cast<UDefaultGameInstance>(GetGameInstance());
if(!gameInstance)
return false;
m_mapData = gameInstance->GetMapData(mapPath);
if(!m_mapData)
{
if(!m_hasWarnedFrank)
{
GWERROR(L"Failed to load map info, Create a map info asset with the name formated as I_ + map name in the same folder and add the I_<map_name> file to the map list frank!!!");
m_hasWarnedFrank = true;
}
m_mapTeamCount = 4;
}
else
{
m_mapTeamCount = m_mapData->maxTeamCount;
}
return true;
}