forked from Mirrors/openclonk
Add InitializePlayers callback after all initial players have joined
parent
319392a779
commit
f4ea3359d0
|
@ -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>
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue