201 lines
4.6 KiB
C++
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;
|
|
} |