Add InitializePlayers callback after all initial players have joined

qteditor
Sven Eberhardt 2016-07-22 00:13:57 -04:00
parent 319392a779
commit f4ea3359d0
7 changed files with 77 additions and 46 deletions

View File

@ -27,6 +27,11 @@
<col>int player, int x, int y, object base, int team, id extra_data</col>
<col>Called after when a new player joins the game. At this point, the clonks, materials, structures etc. are already placed at the position given in the <emlink href="scenario/scenario.html#SektionenPlayer1Player2Player3Player4">Scenario.txt</emlink>. <code>x</code> and <code>y</code> specify the starting position of the player, <code>base</code> is the player's base (if any), <code>team</code> denotes the team of the player. For <code>extra_data</code>, see <funclink>CreateScriptPlayer</funclink></col>
</row>
<row id="InitializePlayers">
<literal_col>InitializePlayers</literal_col>
<col></col>
<col>Called after all initial players joined. Can be used e.g. to start intros.</col>
</row>
<row id="RelaunchPlayer">
<literal_col>RelaunchPlayer</literal_col>
<col>int player, int killed_by_player</col>

View File

@ -1063,65 +1063,71 @@ void C4ControlJoinPlayer::Execute() const
// get client
C4Client *pClient = Game.Clients.getClientByID(iAtClient);
if (!pClient) return;
// get info
C4PlayerInfo *pInfo = Game.PlayerInfos.GetPlayerInfoByID(idInfo);
if (!pInfo)
if (pClient)
{
LogF("ERROR: Ghost player join: No info for %d", idInfo);
assert(false);
return;
}
else if (LocalControl())
{
// Local player: Just join from local file
Game.JoinPlayer(szFilename, iAtClient, pClient->getName(), pInfo);
}
else if (!fByRes)
{
if (PlrData.getSize())
// get info
C4PlayerInfo *pInfo = Game.PlayerInfos.GetPlayerInfoByID(idInfo);
if (!pInfo)
{
// create temp file
StdStrBuf PlayerFilename; PlayerFilename.Format("%s-%s",pClient->getName(),GetFilename(szFilename));
PlayerFilename = Config.AtTempPath(PlayerFilename.getData());
// copy to it
if (PlrData.SaveToFile(PlayerFilename.getData()))
LogF("ERROR: Ghost player join: No info for %d", idInfo);
assert(false);
}
else if (LocalControl())
{
// Local player: Just join from local file
Game.JoinPlayer(szFilename, iAtClient, pClient->getName(), pInfo);
}
else if (!fByRes)
{
if (PlrData.getSize())
{
Game.JoinPlayer(PlayerFilename.getData(), iAtClient, pClient->getName(), pInfo);
EraseFile(PlayerFilename.getData());
// create temp file
StdStrBuf PlayerFilename; PlayerFilename.Format("%s-%s", pClient->getName(), GetFilename(szFilename));
PlayerFilename = Config.AtTempPath(PlayerFilename.getData());
// copy to it
if (PlrData.SaveToFile(PlayerFilename.getData()))
{
Game.JoinPlayer(PlayerFilename.getData(), iAtClient, pClient->getName(), pInfo);
EraseFile(PlayerFilename.getData());
}
}
else if (pInfo->GetType() == C4PT_Script)
{
// script players may join without data
Game.JoinPlayer(NULL, iAtClient, pClient->getName(), pInfo);
}
else
{
// no player data for user player present: Must not happen
LogF("ERROR: Ghost player join: No player data for %s", (const char*)pInfo->GetName());
assert(false);
}
}
else if (pInfo->GetType() == C4PT_Script)
else if (::Control.isNetwork())
{
// script players may join without data
Game.JoinPlayer(NULL, iAtClient, pClient->getName(), pInfo);
// Find resource
C4Network2Res::Ref pRes = ::Network.ResList.getRefRes(ResCore.getID());
if (pRes && pRes->isComplete())
Game.JoinPlayer(pRes->getFile(), iAtClient, pClient->getName(), pInfo);
}
else if (::Control.isReplay())
{
// Expect player in scenario file
StdStrBuf PlayerFilename; PlayerFilename.Format("%s" DirSep "%d-%s", Game.ScenarioFilename, ResCore.getID(), GetFilename(ResCore.getFileName()));
Game.JoinPlayer(PlayerFilename.getData(), iAtClient, pClient ? pClient->getName() : "Unknown", pInfo);
}
else
{
// no player data for user player present: Must not happen
LogF("ERROR: Ghost player join: No player data for %s", (const char*)pInfo->GetName());
// Shouldn't happen
assert(false);
return;
}
}
else if (::Control.isNetwork())
// After last of the initial player joins, do a game callback
if (!::Game.InitialPlayersJoined && !::Game.PlayerInfos.GetJoinPendingPlayerCount())
{
// Find resource
C4Network2Res::Ref pRes = ::Network.ResList.getRefRes(ResCore.getID());
if (pRes && pRes->isComplete())
Game.JoinPlayer(pRes->getFile(), iAtClient, pClient->getName(), pInfo);
::Game.InitialPlayersJoined = true;
::Game.GRBroadcast(PSF_InitializePlayers);
}
else if (::Control.isReplay())
{
// Expect player in scenario file
StdStrBuf PlayerFilename; PlayerFilename.Format("%s" DirSep "%d-%s", Game.ScenarioFilename, ResCore.getID(), GetFilename(ResCore.getFileName()));
Game.JoinPlayer(PlayerFilename.getData(), iAtClient, pClient ? pClient->getName() : "Unknown", pInfo);
}
else
// Shouldn't happen
assert(false);
}
void C4ControlJoinPlayer::Strip()

View File

@ -968,6 +968,21 @@ int32_t C4PlayerInfoList::GetJoinIssuedPlayerCount() const
return iCount;
}
int32_t C4PlayerInfoList::GetJoinPendingPlayerCount() const
{
// count players of all clients
int32_t iCount = 0;
for (int32_t i = 0; i<iClientCount; ++i)
{
C4ClientPlayerInfos *pClient = ppClients[i];
for (int32_t j = 0; j<pClient->GetPlayerCount(); ++j)
if (pClient->GetPlayerInfo(j)->HasJoinPending())
++iCount;
}
// return it
return iCount;
}
int32_t C4PlayerInfoList::GetActivePlayerCount(bool fCountInvisible) const
{
// count players of all clients

View File

@ -167,6 +167,7 @@ public:
bool HasJoined() const { return !!(dwFlags & PIF_Joined); } // return whether player has joined
bool IsJoined() const { return HasJoined() && !(dwFlags & PIF_Removed); } // return whether player is currently in the game
bool HasJoinIssued() const { return !!(dwFlags & (PIF_Joined | PIF_JoinIssued)); } // return whether player join is in the queue already (or performed long ago, even)
bool HasJoinPending() const { return (dwFlags & PIF_JoinIssued) && !(dwFlags & (PIF_Joined | PIF_Removed)); } // return whether player join is in the queue, bot not performed yet
bool IsUsingColor() const { return !IsRemoved() && !idSavegamePlayer; } //return whether the player is actually using the player color
bool IsUsingName() const { return !IsRemoved() && !sLeagueAccount.getLength(); } //return whether the player is actually using the player name (e.g. not if league name is used)
bool IsUsingAttribute(Attribute eAttr) const { if (eAttr == PLRATT_Color) return IsUsingColor(); else return IsUsingName(); }
@ -369,6 +370,7 @@ public:
C4PlayerInfo *GetActivePlayerInfoByName(const char *szName); // find info by name (case insensitive)
int32_t GetPlayerCount() const; // get number of players on all clients
int32_t GetJoinIssuedPlayerCount() const; // get number of players with PIF_JoinIssued-flag set
int32_t GetJoinPendingPlayerCount() const; // get number of players with PIF_JoinIssued-flag but not joined or removed flag set
int32_t GetActivePlayerCount(bool fCountInvisible) const; // get number of players that have not been removed
StdStrBuf GetActivePlayerNames(bool fCountInvisible, int32_t iAtClientID=-1) const; // get a comma-separated list of players that have not been removed yet
int32_t GetActiveScriptPlayerCount(bool fCountSavegameResumes, bool fCountInvisible) const; // get number of script players that have not been removed

View File

@ -1435,7 +1435,7 @@ void C4Game::Default()
PointersDenumerated = false;
IsRunning = false;
FrameCounter=0;
GameOver=GameOverDlgShown=false;
GameOver=GameOverDlgShown=InitialPlayersJoined=false;
ScenarioFilename[0]=0;
PlayerFilenames[0]=0;
DefinitionFilenames[0]=0;
@ -1665,6 +1665,7 @@ void C4Game::CompileFunc(StdCompiler *pComp, CompileSettings comp, C4ValueNumber
pComp->Value(mkNamingAdapt(iTick35, "Tick35", 0));
pComp->Value(mkNamingAdapt(iTick255, "Tick255", 0));
pComp->Value(mkNamingAdapt(iTick1000, "Tick1000", 0));
pComp->Value(mkNamingAdapt(InitialPlayersJoined, "InitialPlayersJoined", false));
pComp->Value(mkNamingAdapt(StartupPlayerCount, "StartupPlayerCount", 0));
pComp->Value(mkNamingAdapt(StartupTeamCount, "StartupTeamCount", 0));
pComp->Value(mkNamingAdapt(C4PropListNumbered::EnumerationIndex,"ObjectEnumerationIndex",0));

View File

@ -103,6 +103,7 @@ public:
int32_t StartupTeamCount;
int32_t FPS,cFPS;
int32_t HaltCount;
bool InitialPlayersJoined; // true after the InitializeFinal callback has been made
bool GameOver;
bool Evaluated;
bool GameOverDlgShown;

View File

@ -32,6 +32,7 @@ bool C4ValueToMatrix(const C4ValueArray& array, StdMeshMatrix* matrix);
/* Engine-Calls */
#define PSF_Initialize "~Initialize"
#define PSF_InitializePlayers "~InitializePlayers"
#define PSF_InitializeAmbience "~InitializeAmbience"
#define PSF_Construction "~Construction"
#define PSF_Destruction "~Destruction"