From 8bbdee5c28eebc0785afa71476474ea6242cc3a6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 30 Jan 2019 01:15:32 +0100 Subject: [PATCH] - redirect most references to the global players array through FLevelLocals. The Map loader may not access any global state at all - everything it can touch must be exchangable. Furthermore, if we want to sandbox each level, there may be no direct access to any kind of global state whatsoever from the play code. --- src/actorptrselect.cpp | 11 +++-- src/fragglescript/t_cmd.cpp | 8 ++-- src/fragglescript/t_func.cpp | 62 ++++++++++++++-------------- src/fragglescript/t_script.cpp | 2 +- src/g_inventory/a_keys.cpp | 2 +- src/g_level.cpp | 44 ++++++++++---------- src/g_levellocals.h | 47 ++++++++++++++++++++- src/g_shared/a_quake.cpp | 4 +- src/maploader/maploader.cpp | 4 +- src/p_acs.cpp | 75 ++++++++++++++++++---------------- src/p_actionfunctions.cpp | 34 ++++++++------- src/p_conversation.cpp | 2 +- src/p_effect.cpp | 4 -- src/p_enemy.cpp | 33 ++++++++------- src/p_interaction.cpp | 13 +++--- src/p_lnspec.cpp | 43 ++++++++++--------- src/p_mobj.cpp | 27 +++++++----- src/p_saveg.cpp | 12 +++--- src/p_setup.cpp | 21 +++++----- 19 files changed, 259 insertions(+), 189 deletions(-) diff --git a/src/actorptrselect.cpp b/src/actorptrselect.cpp index 8c9057ca7b..5cf3264805 100644 --- a/src/actorptrselect.cpp +++ b/src/actorptrselect.cpp @@ -35,6 +35,7 @@ #include "actor.h" #include "d_player.h" #include "p_local.h" +#include "g_levellocals.h" //========================================================================== // @@ -61,14 +62,18 @@ Only one selector of each type can be used. */ -#define AAPTR_RESOLVE_PLAYERNUM(playernum) (playeringame[playernum] ? players[playernum].mo : NULL) - AActor *COPY_AAPTR(AActor *origin, int selector) { if (selector == AAPTR_DEFAULT) return origin; FTranslatedLineTarget t; + auto Level = origin->Level; + auto AAPTR_RESOLVE_PLAYERNUM = [=](int playernum) -> AActor* + { + return (Level->PlayerInGame(playernum) ? Level->Players[playernum]->mo : nullptr); + }; + if (origin) { if (origin->player) @@ -97,7 +102,7 @@ AActor *COPY_AAPTR(AActor *origin, int selector) return t.linetarget; } } - + switch (selector & AAPTR_STATIC_SELECTORS) { case AAPTR_PLAYER1: return AAPTR_RESOLVE_PLAYERNUM(0); diff --git a/src/fragglescript/t_cmd.cpp b/src/fragglescript/t_cmd.cpp index 593b72e036..905c47c992 100644 --- a/src/fragglescript/t_cmd.cpp +++ b/src/fragglescript/t_cmd.cpp @@ -154,12 +154,12 @@ void FS_EmulateCmd(FLevelLocals *Level, char * string) { sc.MustGetFloat(); double playerviewheight = sc.Float; - for(int i=0;iPlayers) { // No, this is not correct. But this is the way Legacy WADs expect it to be handled! - if (players[i].mo != NULL) players[i].mo->FloatVar(NAME_ViewHeight) = playerviewheight; - players[i].viewheight = playerviewheight; - players[i].Uncrouch(); + if (p->mo != nullptr) p->mo->FloatVar(NAME_ViewHeight) = playerviewheight; + p->viewheight = playerviewheight; + p->Uncrouch(); } while (sc.GetString()) { diff --git a/src/fragglescript/t_func.cpp b/src/fragglescript/t_func.cpp index 1dccf3f35c..4ebd0b1e94 100644 --- a/src/fragglescript/t_func.cpp +++ b/src/fragglescript/t_func.cpp @@ -278,7 +278,7 @@ int FParser::T_GetPlayerNum(const svalue_t &arg) { return -1; } - if(!playeringame[playernum]) // no error, just return -1 + if(!Level->PlayerInGame(playernum)) // no error, just return -1 { return -1; } @@ -288,7 +288,7 @@ int FParser::T_GetPlayerNum(const svalue_t &arg) AActor *FParser::T_GetPlayerActor(const svalue_t &arg) { int num = T_GetPlayerNum(arg); - return num == -1 ? nullptr : players[num].mo; + return num == -1 ? nullptr : Level->Players[num]->mo; } PClassActor *T_ClassType(const svalue_t &arg) @@ -659,7 +659,7 @@ void FParser::SF_PlayerTip(void) if (CheckArgs(1)) { int plnum = T_GetPlayerNum(t_argv[0]); - if (plnum!=-1 && players[plnum].mo->CheckLocalView(consoleplayer)) + if (plnum!=-1 && Level->Players[plnum]->mo->CheckLocalView(consoleplayer)) { C_MidPrint(SmallFont, GetFormatString(1).GetChars()); } @@ -692,7 +692,7 @@ void FParser::SF_PlayerMsg(void) if (CheckArgs(1)) { int plnum = T_GetPlayerNum(t_argv[0]); - if (plnum!=-1 && players[plnum].mo->CheckLocalView(consoleplayer)) + if (plnum!=-1 && Level->Players[plnum]->mo->CheckLocalView(consoleplayer)) { Printf(PRINT_HIGH, "%s\n", GetFormatString(1).GetChars()); } @@ -714,7 +714,7 @@ void FParser::SF_PlayerInGame(void) if (plnum!=-1) { t_return.type = svt_int; - t_return.value.i = playeringame[plnum]; + t_return.value.i = Level->PlayerInGame(plnum); } } } @@ -742,7 +742,7 @@ void FParser::SF_PlayerName(void) if(plnum !=-1) { t_return.type = svt_string; - t_return.string = players[plnum].userinfo.GetName(); + t_return.string = Level->Players[plnum]->userinfo.GetName(); } else { @@ -773,7 +773,7 @@ void FParser::SF_PlayerObj(void) if(plnum !=-1) { t_return.type = svt_mobj; - t_return.value.mobj = players[plnum].mo; + t_return.value.mobj = Level->Players[plnum]->mo; } else { @@ -1402,8 +1402,8 @@ void FParser::SF_SetCamera(void) if (CheckArgs(1)) { - player=Script->trigger->player; - if (!player) player=&players[0]; + player = Script->trigger->player; + if (!player) player = Level->Players[0]; newcamera = actorvalue(t_argv[0]); if(!newcamera) @@ -1435,8 +1435,8 @@ void FParser::SF_SetCamera(void) void FParser::SF_ClearCamera(void) { player_t * player; - player=Script->trigger->player; - if (!player) player=&players[0]; + player = Script->trigger->player; + if (!player) player = Level->Players[0]; AActor * cam=player->camera; if (cam) @@ -2419,13 +2419,13 @@ void FParser::SF_PlayerKeys(void) if(t_argc == 2) { t_return.type = svt_int; - t_return.value.i = CheckInventory(players[playernum].mo, keyname); + t_return.value.i = CheckInventory(Level->Players[playernum]->mo, keyname); return; } else { givetake = intvalue(t_argv[2]); - ScriptUtil::Exec(givetake?NAME_GiveInventory : NAME_TakeInventory, ScriptUtil::Pointer, players[playernum].mo, ScriptUtil::Int, keyname.GetIndex(), ScriptUtil::Int, 1, ScriptUtil::End); + ScriptUtil::Exec(givetake?NAME_GiveInventory : NAME_TakeInventory, ScriptUtil::Pointer, Level->Players[playernum]->mo, ScriptUtil::Int, keyname.GetIndex(), ScriptUtil::Int, 1, ScriptUtil::End); t_return.type = svt_int; t_return.value.i = 0; } @@ -2504,14 +2504,14 @@ void FParser::SF_PlayerWeapon() if (t_argc == 2) { - AActor * wp = players[playernum].mo->FindInventory(ti); + AActor * wp = Level->Players[playernum]->mo->FindInventory(ti); t_return.type = svt_int; t_return.value.i = wp!=NULL; return; } else { - AActor * wp = players[playernum].mo->FindInventory(ti); + AActor * wp = Level->Players[playernum]->mo->FindInventory(ti); newweapon = !!intvalue(t_argv[2]); if (!newweapon) @@ -2520,14 +2520,14 @@ void FParser::SF_PlayerWeapon() { wp->Destroy(); // If the weapon is active pick a replacement. Legacy didn't do this! - if (players[playernum].PendingWeapon==wp) players[playernum].PendingWeapon=WP_NOCHANGE; - if (players[playernum].ReadyWeapon==wp) + if (Level->Players[playernum]->PendingWeapon==wp) Level->Players[playernum]->PendingWeapon=WP_NOCHANGE; + if (Level->Players[playernum]->ReadyWeapon==wp) { - players[playernum].ReadyWeapon=nullptr; + Level->Players[playernum]->ReadyWeapon=nullptr; IFVM(PlayerPawn, PickNewWeapon) { - VMValue param[] = { players[playernum].mo, (void*)nullptr }; + VMValue param[] = { Level->Players[playernum]->mo, (void*)nullptr }; VMCall(func, param, 2, nullptr, 0); } } @@ -2537,9 +2537,9 @@ void FParser::SF_PlayerWeapon() { if (!wp) { - auto pw=players[playernum].PendingWeapon; - players[playernum].mo->GiveInventoryType(ti); - players[playernum].PendingWeapon=pw; + auto pw=Level->Players[playernum]->PendingWeapon; + Level->Players[playernum]->mo->GiveInventoryType(ti); + Level->Players[playernum]->PendingWeapon=pw; } } @@ -2588,13 +2588,13 @@ void FParser::SF_PlayerSelectedWeapon() return; } - players[playernum].PendingWeapon = players[playernum].mo->FindInventory(ti); + Level->Players[playernum]->PendingWeapon = Level->Players[playernum]->mo->FindInventory(ti); } t_return.type = svt_int; for(int i=0;i<9;i++) { - if (players[playernum].ReadyWeapon->GetClass ()->TypeName == FName(WeaponNames[i])) + if (Level->Players[playernum]->ReadyWeapon->GetClass ()->TypeName == FName(WeaponNames[i])) { t_return.value.i=i; break; @@ -2620,7 +2620,7 @@ void FParser::SF_GiveInventory(void) if(t_argc == 2) count=1; else count=intvalue(t_argv[2]); - ScriptUtil::Exec(NAME_GiveInventory, ScriptUtil::Pointer, players[playernum].mo, ScriptUtil::Int, FName(stringvalue(t_argv[1])).GetIndex(), ScriptUtil::Int, count, ScriptUtil::End); + ScriptUtil::Exec(NAME_GiveInventory, ScriptUtil::Pointer, Level->Players[playernum]->mo, ScriptUtil::Int, FName(stringvalue(t_argv[1])).GetIndex(), ScriptUtil::Int, count, ScriptUtil::End); t_return.type = svt_int; t_return.value.i = 0; } @@ -2643,7 +2643,7 @@ void FParser::SF_TakeInventory(void) if(t_argc == 2) count=32767; else count=intvalue(t_argv[2]); - ScriptUtil::Exec(NAME_TakeInventory, ScriptUtil::Pointer, players[playernum].mo, ScriptUtil::Int, FName(stringvalue(t_argv[1])).GetIndex(), ScriptUtil::Int, count, ScriptUtil::End); + ScriptUtil::Exec(NAME_TakeInventory, ScriptUtil::Pointer, Level->Players[playernum]->mo, ScriptUtil::Int, FName(stringvalue(t_argv[1])).GetIndex(), ScriptUtil::Int, count, ScriptUtil::End); t_return.type = svt_int; t_return.value.i = 0; } @@ -2668,7 +2668,7 @@ void FParser::SF_CheckInventory(void) return; } t_return.type = svt_int; - t_return.value.i = CheckInventory(players[playernum].mo, stringvalue(t_argv[1])); + t_return.value.i = CheckInventory(Level->Players[playernum]->mo, stringvalue(t_argv[1])); } } @@ -3221,10 +3221,10 @@ void FParser::SF_PlayerAddFrag() { playernum1 = T_GetPlayerNum(t_argv[0]); - players[playernum1].fragcount++; + Level->Players[playernum1]->fragcount++; t_return.type = svt_int; - t_return.value.f = players[playernum1].fragcount; + t_return.value.f = Level->Players[playernum1]->fragcount; } else @@ -3232,10 +3232,10 @@ void FParser::SF_PlayerAddFrag() playernum1 = T_GetPlayerNum(t_argv[0]); playernum2 = T_GetPlayerNum(t_argv[1]); - players[playernum1].frags[playernum2]++; + Level->Players[playernum1]->frags[playernum2]++; t_return.type = svt_int; - t_return.value.f = players[playernum1].frags[playernum2]; + t_return.value.f = Level->Players[playernum1]->frags[playernum2]; } } } diff --git a/src/fragglescript/t_script.cpp b/src/fragglescript/t_script.cpp index 2eb6df9d6b..fd2cbcefcc 100644 --- a/src/fragglescript/t_script.cpp +++ b/src/fragglescript/t_script.cpp @@ -616,7 +616,7 @@ void T_PreprocessScripts(FLevelLocals *Level) // get the other scripts // levelscript started by player 0 'superplayer' - th->LevelScript->trigger = players[0].mo; + th->LevelScript->trigger = Level->Players[0]->mo; th->LevelScript->Preprocess(Level); th->LevelScript->ParseScript(nullptr, th); diff --git a/src/g_inventory/a_keys.cpp b/src/g_inventory/a_keys.cpp index 8173405791..ad0e85404d 100644 --- a/src/g_inventory/a_keys.cpp +++ b/src/g_inventory/a_keys.cpp @@ -494,7 +494,7 @@ int P_CheckKeys (AActor *owner, int keynum, bool remote, bool quiet) // If we get here, that means the actor isn't holding an appropriate key. - if (owner == players[consoleplayer].camera) + if (owner->CheckLocalView(consoleplayer)) { PrintMessage(failtext); diff --git a/src/g_level.cpp b/src/g_level.cpp index 94a9850666..60f38ea5e0 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -835,12 +835,12 @@ bool FLevelLocals::DoCompleted (FString nextlevel, wbstartstruct_t &wminfo) for (i=0 ; ikillcount; + wminfo.plyr[i].sitems = Players[i]->itemcount; + wminfo.plyr[i].ssecret = Players[i]->secretcount; wminfo.plyr[i].stime = time; - memcpy (wminfo.plyr[i].frags, players[i].frags, sizeof(wminfo.plyr[i].frags)); - wminfo.plyr[i].fragcount = players[i].fragcount; + memcpy (wminfo.plyr[i].frags, Players[i]->frags, sizeof(wminfo.plyr[i].frags)); + wminfo.plyr[i].fragcount = Players[i]->fragcount; } // [RH] If we're in a hub and staying within that hub, take a snapshot. @@ -1035,11 +1035,11 @@ void FLevelLocals::DoLoadLevel(const FString &nextmapname, int position, bool au for (i = 0; i < MAXPLAYERS; i++) { - if (playeringame[i] && (deathmatch || players[i].playerstate == PST_DEAD)) - players[i].playerstate = PST_ENTER; // [BC] - memset (players[i].frags,0,sizeof(players[i].frags)); + if (PlayerInGame(i) && (deathmatch || Players[i]->playerstate == PST_DEAD)) + Players[i]->playerstate = PST_ENTER; // [BC] + memset (Players[i]->frags,0,sizeof(Players[i]->frags)); if (!(dmflags2 & DF2_YES_KEEPFRAGS) && (alwaysapplydmflags || deathmatch)) - players[i].fragcount = 0; + Players[i]->fragcount = 0; } if (changeflags & CHANGELEVEL_NOMONSTERS) @@ -1093,19 +1093,19 @@ void FLevelLocals::DoLoadLevel(const FString &nextmapname, int position, bool au { for (int i = 0; imo != nullptr) + P_PlayerStartStomp(Players[i]->mo); } } // For each player, if they are viewing through a player, make sure it is themselves. for (int ii = 0; ii < MAXPLAYERS; ++ii) { - if (playeringame[ii]) + if (PlayerInGame(ii)) { - if (players[ii].camera == NULL || players[ii].camera->player != NULL) + if (Players[ii]->camera == nullptr || Players[ii]->camera->player != nullptr) { - players[ii].camera = players[ii].mo; + Players[ii]->camera = Players[ii]->mo; } if (savegamerestore) @@ -1119,7 +1119,7 @@ void FLevelLocals::DoLoadLevel(const FString &nextmapname, int position, bool au if (fromSnapshot) { // ENTER scripts are being handled when the player gets spawned, this cannot be changed due to its effect on voodoo dolls. - Behaviors.StartTypedScripts(SCRIPT_Return, players[ii].mo, true); + Behaviors.StartTypedScripts(SCRIPT_Return, Players[ii]->mo, true); } } } @@ -1181,8 +1181,8 @@ void FLevelLocals::WorldDone (void) // Strife needs a special case here to choose between good and sad ending. Bad is handled elsewhere. if (endsequence == NAME_Inter_Strife) { - if (players[0].mo->FindInventory (NAME_QuestItem25) || - players[0].mo->FindInventory (NAME_QuestItem28)) + if (Players[0]->mo->FindInventory (NAME_QuestItem25) || + Players[0]->mo->FindInventory (NAME_QuestItem28)) { endsequence = NAME_Inter_Strife_Good; } @@ -1317,12 +1317,12 @@ void FLevelLocals::StartTravel () { if (playeringame[i]) { - AActor *pawn = players[i].mo; + AActor *pawn = Players[i]->mo; AActor *inv; - players[i].camera = nullptr; + Players[i]->camera = nullptr; // Only living players travel. Dead ones get a new body on the new level. - if (players[i].health > 0) + if (Players[i]->health > 0) { pawn->UnlinkFromWorld (nullptr); int tid = pawn->tid; // Save TID @@ -1721,14 +1721,14 @@ void FLevelLocals::UnSnapshotLevel (bool hubLoad) while ((pawn = next) != 0) { next = it.Next(); - if (pawn->player == NULL || pawn->player->mo == NULL || !playeringame[pawn->player - players]) + if (pawn->player == nullptr || pawn->player->mo == nullptr || !PlayerInGame(pawn->player)) { int i; // If this isn't the unmorphed original copy of a player, destroy it, because it's extra. for (i = 0; i < MAXPLAYERS; ++i) { - if (playeringame[i] && players[i].morphTics && players[i].mo->alternative == pawn) + if (PlayerInGame(i) && Players[i]->morphTics && Players[i]->mo->alternative == pawn) { break; } diff --git a/src/g_levellocals.h b/src/g_levellocals.h index 79f72c23f9..471d7b655d 100644 --- a/src/g_levellocals.h +++ b/src/g_levellocals.h @@ -48,6 +48,7 @@ #include "p_spec.h" #include "actor.h" #include "p_effect.h" +#include "d_player.h" #include "p_destructible.h" #include "r_data/r_sections.h" #include "r_data/r_canvastexture.h" @@ -102,7 +103,15 @@ struct FLevelLocals { void *level; void *Level; // bug catchers. - FLevelLocals() : Behaviors(this), tagManager(this) {} + FLevelLocals() : Behaviors(this), tagManager(this) + { + // Make sure that these point to the right data all the time. + // This will be needed for as long as it takes to completely separate global UI state from per-level play state. + for (int i = 0; i < MAXPLAYERS; i++) + { + Players[i] = &players[i]; + } + } friend class MapLoader; @@ -493,6 +502,42 @@ public: TObjPtr bodyque[BODYQUESIZE]; TObjPtr automap = nullptr; int bodyqueslot; + + // For now this merely points to the global player array, but with this in place, access to this array can be moved over to the level. + // As things progress each level needs to be able to point to different players, + // but even then the level will not own the player - the player merely links to the level. + // This should also be made a real object eventually. + player_t *Players[MAXPLAYERS]; + + // This is to allow refactoring without refactoring the data right away. + bool PlayerInGame(int pnum) + { + return playeringame[pnum]; + } + + // This needs to be done better, but for now it should be good enough. + bool PlayerInGame(player_t *player) + { + for (int i = 0; i < MAXPLAYERS; i++) + { + if (player == Players[i]) return PlayerInGame(i); + } + return false; + } + + int PlayerNum(player_t *player) + { + for (int i = 0; i < MAXPLAYERS; i++) + { + if (player == Players[i]) return i; + } + return -1; + } + + bool isPrimaryLevel() const + { + return true; + } int NumMapSections; diff --git a/src/g_shared/a_quake.cpp b/src/g_shared/a_quake.cpp index a00307f7e5..4eff8a4376 100644 --- a/src/g_shared/a_quake.cpp +++ b/src/g_shared/a_quake.cpp @@ -122,9 +122,9 @@ void DEarthquake::Tick () { for (i = 0; i < MAXPLAYERS; i++) { - if (playeringame[i] && !(players[i].cheats & CF_NOCLIP)) + if (Level->PlayerInGame(i) && !(Level->Players[i]->cheats & CF_NOCLIP)) { - AActor *victim = players[i].mo; + AActor *victim = Level->Players[i]->mo; double dist; dist = m_Spot->Distance2D(victim, true); diff --git a/src/maploader/maploader.cpp b/src/maploader/maploader.cpp index a224910098..ca141bb011 100644 --- a/src/maploader/maploader.cpp +++ b/src/maploader/maploader.cpp @@ -3247,8 +3247,8 @@ void MapLoader::LoadLevel(MapData *map, const char *lumpname, int position) for (int i = 0; i < MAXPLAYERS; ++i) { - if (playeringame[i] && players[i].mo != nullptr) - players[i].health = players[i].mo->health; + if (Level->PlayerInGame(i) && Level->Players[i]->mo != nullptr) + Level->Players[i]->health = Level->Players[i]->mo->health; } if (!map->HasBehavior && !map->isText) TranslateTeleportThings(); // [RH] Assign teleport destination TIDs diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 6a45adb38b..8b54e9798d 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -1725,7 +1725,7 @@ static bool DoUseInv (AActor *actor, PClassActor *info) // //============================================================================ -static int UseInventory (AActor *activator, const char *type) +static int UseInventory (FLevelLocals *Level, AActor *activator, const char *type) { PClassActor *info; int ret = 0; @@ -1743,8 +1743,8 @@ static int UseInventory (AActor *activator, const char *type) { for (int i = 0; i < MAXPLAYERS; ++i) { - if (playeringame[i]) - ret += DoUseInv (players[i].mo, info); + if (Level->PlayerInGame(i)) + ret += DoUseInv (Level->Players[i]->mo, info); } } else @@ -1759,6 +1759,7 @@ static int UseInventory (AActor *activator, const char *type) // CheckInventory // // Returns how much of a particular item an actor has. +// This also gets called from FraggleScript. // //============================================================================ @@ -3672,7 +3673,7 @@ int DLevelScript::CountPlayers () int count = 0, i; for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i]) + if (Level->PlayerInGame(i)) count++; return count; @@ -3850,9 +3851,9 @@ void DLevelScript::DoFadeRange (int r1, int g1, int b1, int a1, { for (i = 0; i < MAXPLAYERS; ++i) { - if (playeringame[i]) + if (Level->PlayerInGame(i)) { - viewer = &players[i]; + viewer = Level->Players[i]; showme: if (ftime <= 0.f) { @@ -3965,7 +3966,7 @@ int DoGetMasterTID (AActor *self) if (self->master) return self->master->tid; else if (self->FriendPlayer) { - player_t *player = &players[(self->FriendPlayer)-1]; + player_t *player = self->Level->Players[(self->FriendPlayer)-1]; return player->mo->tid; } else return 0; @@ -4504,13 +4505,13 @@ int DLevelScript::GetPlayerInput(int playernum, int inputnum) } p = activator->player; } - else if (playernum >= MAXPLAYERS || !playeringame[playernum]) + else if (playernum >= MAXPLAYERS || !Level->PlayerInGame(playernum)) { return 0; } else { - p = &players[playernum]; + p = Level->Players[playernum]; } if (p == NULL) { @@ -4961,11 +4962,11 @@ static int DoGetCVar(FBaseCVar *cvar, bool is_string) int DLevelScript::SetUserCVar(int playernum, const char *cvarname, int value, bool is_string) { - if ((unsigned)playernum >= MAXPLAYERS || !playeringame[playernum]) + if ((unsigned)playernum >= MAXPLAYERS || !Level->PlayerInGame(playernum)) { return 0; } - FBaseCVar **cvar_p = players[playernum].userinfo.CheckKey(FName(cvarname, true)); + FBaseCVar **cvar_p = Level->Players[playernum]->userinfo.CheckKey(FName(cvarname, true)); FBaseCVar *cvar; // Only mod-created cvars may be set. if (cvar_p == NULL || (cvar = *cvar_p) == NULL || (cvar->GetFlags() & CVAR_IGNORE) || !(cvar->GetFlags() & CVAR_MOD)) @@ -4975,7 +4976,7 @@ int DLevelScript::SetUserCVar(int playernum, const char *cvarname, int value, bo DoSetCVar(cvar, value, is_string); // If we are this player, then also reflect this change in the local version of this cvar. - if (playernum == consoleplayer) + if (playernum == consoleplayer && Level->isPrimaryLevel()) { FBaseCVar *cvar = FindCVar(cvarname, NULL); // If we can find it in the userinfo, then we should also be able to find it in the normal cvar list, @@ -5004,7 +5005,9 @@ int DLevelScript::SetCVar(AActor *activator, const char *cvarname, int value, bo { return 0; } - return SetUserCVar(int(activator->player - players), cvarname, value, is_string); + auto pnum = Level->PlayerNum(activator->player); + if (pnum < 0) return 0; + return SetUserCVar(pnum, cvarname, value, is_string); } DoSetCVar(cvar, value, is_string); return 1; @@ -5388,25 +5391,25 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args) case ACSF_GetAirSupply: { - if (args[0] < 0 || args[0] >= MAXPLAYERS || !playeringame[args[0]]) + if (args[0] < 0 || args[0] >= MAXPLAYERS || !Level->PlayerInGame(args[0])) { return 0; } else { - return players[args[0]].air_finished - Level->time; + return Level->Players[args[0]]->air_finished - Level->time; } } case ACSF_SetAirSupply: { - if (args[0] < 0 || args[0] >= MAXPLAYERS || !playeringame[args[0]]) + if (args[0] < 0 || args[0] >= MAXPLAYERS || !Level->PlayerInGame(args[0])) { return 0; } else { - players[args[0]].air_finished = args[1] + Level->time; + Level->Players[args[0]]->air_finished = args[1] + Level->time; return 1; } } @@ -5420,14 +5423,14 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args) case ACSF_GetArmorType: { - if (args[1] < 0 || args[1] >= MAXPLAYERS || !playeringame[args[1]]) + if (args[1] < 0 || args[1] >= MAXPLAYERS || !Level->PlayerInGame(args[1])) { return 0; } else { FName p(Level->Behaviors.LookupString(args[0])); - auto armor = players[args[1]].mo->FindInventory(NAME_BasicArmor); + auto armor = Level->Players[args[1]]->mo->FindInventory(NAME_BasicArmor); if (armor && armor->NameVar(NAME_ArmorType) == p) return armor->IntVar(NAME_Amount); } return 0; @@ -8454,9 +8457,9 @@ scriptwait: player = activator->player; } } - else if (playeringame[STACK(1)-1]) + else if (Level->PlayerInGame(STACK(1)-1)) { - player = &players[STACK(1)-1]; + player = Level->Players[STACK(1)-1]; } else { @@ -8610,6 +8613,7 @@ scriptwait: { optstart = sp; } + if (Level->isPrimaryLevel()) { AActor *screen = activator; if (screen != NULL && @@ -9198,7 +9202,7 @@ scriptwait: break; case PCD_USEINVENTORY: - STACK(1) = UseInventory (activator, Level->Behaviors.LookupString (STACK(1))); + STACK(1) = UseInventory (Level, activator, Level->Behaviors.LookupString (STACK(1))); break; case PCD_USEACTORINVENTORY: @@ -9207,7 +9211,7 @@ scriptwait: const char *type = Level->Behaviors.LookupString(STACK(1)); if (STACK(2) == 0) { - ret = UseInventory(NULL, type); + ret = UseInventory(Level, NULL, type); } else { @@ -9215,7 +9219,7 @@ scriptwait: AActor *actor; for (actor = it.Next(); actor != NULL; actor = it.Next()) { - ret += UseInventory(actor, type); + ret += UseInventory(Level, actor, type); } } STACK(2) = ret; @@ -9655,18 +9659,18 @@ scriptwait: } else { - STACK(1) = playeringame[STACK(1)]; + STACK(1) = Level->PlayerInGame(STACK(1)); } break; case PCD_PLAYERISBOT: - if (STACK(1) < 0 || STACK(1) >= MAXPLAYERS || !playeringame[STACK(1)]) + if (STACK(1) < 0 || STACK(1) >= MAXPLAYERS || !Level->PlayerInGame(STACK(1))) { STACK(1) = false; } else { - STACK(1) = (players[STACK(1)].Bot != NULL); + STACK(1) = (Level->Players[STACK(1)]->Bot != nullptr); } break; @@ -9858,24 +9862,24 @@ scriptwait: break; case PCD_PLAYERCLASS: // [GRB] - if (STACK(1) < 0 || STACK(1) >= MAXPLAYERS || !playeringame[STACK(1)]) + if (STACK(1) < 0 || STACK(1) >= MAXPLAYERS || !Level->PlayerInGame(STACK(1))) { STACK(1) = -1; } else { - STACK(1) = players[STACK(1)].CurrentPlayerClass; + STACK(1) = Level->Players[STACK(1)]->CurrentPlayerClass; } break; case PCD_GETPLAYERINFO: // [GRB] - if (STACK(2) < 0 || STACK(2) >= MAXPLAYERS || !playeringame[STACK(2)]) + if (STACK(2) < 0 || STACK(2) >= MAXPLAYERS || !Level->PlayerInGame(STACK(2))) { STACK(2) = -1; } else { - player_t *pl = &players[STACK(2)]; + player_t *pl = Level->Players[STACK(2)]; userinfo_t *userinfo = &pl->userinfo; switch (STACK(1)) { @@ -9973,13 +9977,14 @@ scriptwait: { int playernum = STACK(1); - if (playernum < 0 || playernum >= MAXPLAYERS || !playeringame[playernum] || players[playernum].camera == NULL || players[playernum].camera->player != NULL) + if (playernum < 0 || playernum >= MAXPLAYERS || !Level->PlayerInGame(playernum) || + Level->Players[playernum]->camera == nullptr || Level->Players[playernum]->camera->player != nullptr) { STACK(1) = -1; } else { - STACK(1) = players[playernum].camera->tid; + STACK(1) = Level->Players[playernum]->camera->tid; } } break; @@ -10301,8 +10306,8 @@ void FLevelLocals::DoDeferedScripts () if (scriptdata) { P_GetScriptGoing (this, (unsigned)def->playernum < MAXPLAYERS && - playeringame[def->playernum] ? players[def->playernum].mo : NULL, - NULL, def->script, + PlayerInGame(def->playernum) ? Players[def->playernum]->mo : nullptr, + nullptr, def->script, scriptdata, module, def->args, 3, def->type == acsdefered_t::defexealways ? ACS_ALWAYS : 0); diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 913a42bc5e..3983436339 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -1684,18 +1684,20 @@ DEFINE_ACTION_FUNCTION(AActor, CheckIfSeen) { PARAM_SELF_PROLOGUE(AActor); + auto Level = self->Level; for (int i = 0; i < MAXPLAYERS; i++) { - if (playeringame[i]) + if (Level->PlayerInGame(i)) { + auto p = Level->Players[i]; // Always check sight from each player. - if (P_CheckSight(players[i].mo, self, SF_IGNOREVISIBILITY)) + if (P_CheckSight(p->mo, self, SF_IGNOREVISIBILITY)) { ACTION_RETURN_BOOL(false); } // If a player is viewing from a non-player, then check that too. - if (players[i].camera != NULL && players[i].camera->player == NULL && - P_CheckSight(players[i].camera, self, SF_IGNOREVISIBILITY)) + if (p->camera != nullptr && p->camera->player == NULL && + P_CheckSight(p->camera, self, SF_IGNOREVISIBILITY)) { ACTION_RETURN_BOOL(false); } @@ -1755,18 +1757,20 @@ DEFINE_ACTION_FUNCTION(AActor, CheckSightOrRange) PARAM_BOOL(twodi); range *= range; - for (int i = 0; i < MAXPLAYERS; ++i) + auto Level = self->Level; + for (int i = 0; i < MAXPLAYERS; i++) { - if (playeringame[i]) + if (Level->PlayerInGame(i)) { + auto p = Level->Players[i]; // Always check from each player. - if (DoCheckSightOrRange(self, players[i].mo, range, twodi, true)) + if (DoCheckSightOrRange(self, p->mo, range, twodi, true)) { ACTION_RETURN_BOOL(false); } // If a player is viewing from a non-player, check that too. - if (players[i].camera != NULL && players[i].camera->player == NULL && - DoCheckSightOrRange(self, players[i].camera, range, twodi, true)) + if (p->camera != nullptr && p->camera->player == nullptr && + DoCheckSightOrRange(self, p->camera, range, twodi, true)) { ACTION_RETURN_BOOL(false); } @@ -1783,18 +1787,20 @@ DEFINE_ACTION_FUNCTION(AActor, CheckRange) PARAM_BOOL(twodi); range *= range; - for (int i = 0; i < MAXPLAYERS; ++i) + auto Level = self->Level; + for (int i = 0; i < MAXPLAYERS; i++) { - if (playeringame[i]) + if (Level->PlayerInGame(i)) { + auto p = Level->Players[i]; // Always check from each player. - if (DoCheckSightOrRange(self, players[i].mo, range, twodi, false)) + if (DoCheckSightOrRange(self, p->mo, range, twodi, false)) { ACTION_RETURN_BOOL(false); } // If a player is viewing from a non-player, check that too. - if (players[i].camera != NULL && players[i].camera->player == NULL && - DoCheckSightOrRange(self, players[i].camera, range, twodi, false)) + if (p->camera != nullptr && p->camera->player == nullptr && + DoCheckSightOrRange(self, p->camera, range, twodi, false)) { ACTION_RETURN_BOOL(false); } diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index 5265b1010d..e2185104a9 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -738,7 +738,7 @@ void P_StartConversation (AActor *npc, AActor *pc, bool facetalker, bool saveang int i; // Make sure this is actually a player. - if (pc == nullptr || pc->player == nullptr || npc == nullptr) return; + if (pc == nullptr || pc->player == nullptr || npc == nullptr || pc->Level != currentUILevel) return; auto Level = pc->Level; // [CW] If an NPC is talking to a PC already, then don't let diff --git a/src/p_effect.cpp b/src/p_effect.cpp index 20312ced39..ce93fcdead 100644 --- a/src/p_effect.cpp +++ b/src/p_effect.cpp @@ -324,10 +324,6 @@ void P_SpawnParticle(FLevelLocals *Level, const DVector3 &pos, const DVector3 &v // void P_RunEffects (FLevelLocals *Level) { - if (players[consoleplayer].camera == NULL) return; - - int pnum = players[consoleplayer].camera->Sector->Index() * Level->sectors.Size(); - AActor *actor; auto iterator = Level->GetThinkerIterator(); diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index f976285108..6997cd738d 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -1005,12 +1005,12 @@ void P_RandomChaseDir (AActor *actor) { i = 0; } - else for (i = pr_newchasedir() & (MAXPLAYERS-1); !playeringame[i]; i = (i+1) & (MAXPLAYERS-1)) + else for (i = pr_newchasedir() & (MAXPLAYERS-1); !actor->Level->PlayerInGame(i); i = (i+1) & (MAXPLAYERS-1)) { } - player = players[i].mo; + player = actor->Level->Players[i]->mo; } - if (player != NULL && playeringame[i]) + if (player != NULL && actor->Level->PlayerInGame(i)) { if (pr_newchasedir() & 1 || !P_CheckSight (actor, player)) { @@ -1203,7 +1203,7 @@ int P_LookForMonsters (AActor *actor) AActor *mo; auto iterator = actor->Level->GetThinkerIterator(); - if (!P_CheckSight (players[0].mo, actor, SF_SEEPASTBLOCKEVERYTHING)) + if (!P_CheckSight (actor->Level->Players[0]->mo, actor, SF_SEEPASTBLOCKEVERYTHING)) { // Player can't see monster return false; } @@ -1592,11 +1592,13 @@ int P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params) // Go back to a player, no matter whether it's visible or not for (int anyone=0; anyone<=1; anyone++) { + auto Level = actor->Level; for (int c=0; cIsFriend(players[c].mo) && - (anyone || P_IsVisible(actor, players[c].mo, allaround))) + auto p = Level->Players[i]; + if (Level->PlayerInGame(c) && p->playerstate==PST_LIVE && + actor->IsFriend(p->mo) && + (anyone || P_IsVisible(actor, p->mo, allaround))) { actor->target = players[c].mo; @@ -1623,8 +1625,9 @@ int P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params) } // [SP] if false, and in deathmatch, intentional fall-through if (!(gameinfo.gametype & (GAME_DoomStrifeChex)) && + actor->Level->isPrimaryLevel() && !multiplayer && - players[0].health <= 0 && + actor->Level->Players[0]->health <= 0 && actor->goal == NULL && gamestate != GS_TITLELEVEL ) @@ -1648,7 +1651,7 @@ int P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params) if (c++ < MAXPLAYERS) { pnum = (pnum + 1) & (MAXPLAYERS - 1); - if (!playeringame[pnum]) + if (!actor->Level->PlayerInGame(pnum)) continue; if (actor->TIDtoHate == 0) @@ -1686,12 +1689,12 @@ int P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params) return actor->target == actor->goal && actor->goal != NULL; } - player = &players[pnum]; + player = actor->Level->Players[pnum]; if (!(player->mo->flags & MF_SHOOTABLE)) continue; // not shootable (observer or dead) - if (!((actor->flags ^ player->mo->flags) & MF_FRIENDLY)) + if (actor->IsFriend(player->mo)) continue; // same +MF_FRIENDLY, ignore if (player->cheats & CF_NOTARGET) @@ -2284,7 +2287,7 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi if (actor->FriendPlayer != 0) { - player = &players[actor->FriendPlayer - 1]; + player = actor->Level->Players[actor->FriendPlayer - 1]; } else { @@ -2293,10 +2296,10 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi { i = 0; } - else for (i = pr_newchasedir() & (MAXPLAYERS-1); !playeringame[i]; i = (i+1) & (MAXPLAYERS-1)) + else for (i = pr_newchasedir() & (MAXPLAYERS-1); !actor->Level->PlayerInGame(i); i = (i+1) & (MAXPLAYERS-1)) { } - player = &players[i]; + player = actor->Level->Players[i]; } if (player->attacker && player->attacker->health > 0 && player->attacker->flags & MF_SHOOTABLE && pr_newchasedir() < 80) { @@ -3037,7 +3040,7 @@ int CheckBossDeath (AActor *actor) // make sure there is a player alive for victory for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].health > 0) + if (actor->Level->PlayerInGame(i) && actor->Level->Players[i]->health > 0) break; if (i == MAXPLAYERS) diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 448892cf3f..d1f23094f9 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -547,11 +547,11 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags, FName MeansOf } } } - else if (!multiplayer && CountsAsKill()) + else if (!multiplayer && CountsAsKill() && Level->isPrimaryLevel()) { // count all monster deaths, // even those caused by other monsters - players[0].killcount++; + Level->Players[0]->killcount++; } if (player) @@ -577,11 +577,12 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags, FName MeansOf //Added by MC: Discard enemies. for (int i = 0; i < MAXPLAYERS; i++) { - if (players[i].Bot != NULL && this == players[i].Bot->enemy) + DBot *Bot = Level->Players[i]->Bot; + if (Bot != nullptr && this == Bot->enemy) { - if (players[i].Bot->dest == players[i].Bot->enemy) - players[i].Bot->dest = nullptr; - players[i].Bot->enemy = nullptr; + if (Bot->dest == Bot->enemy) + Bot->dest = nullptr; + Bot->enemy = nullptr; } } diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index fbb2dc8735..2b180955f4 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -2835,24 +2835,25 @@ FUNC(LS_ChangeCamera) for (i = 0; i < MAXPLAYERS; i++) { - if (!playeringame[i]) + if (!Level->PlayerInGame(i)) continue; - AActor *oldcamera = players[i].camera; + auto p = Level->Players[i]; + AActor *oldcamera = p->camera; if (camera) { - players[i].camera = camera; + p->camera = camera; if (arg2) - players[i].cheats |= CF_REVERTPLEASE; + p->cheats |= CF_REVERTPLEASE; } else { - players[i].camera = players[i].mo; - players[i].cheats &= ~CF_REVERTPLEASE; + p->camera = p->mo; + p->cheats &= ~CF_REVERTPLEASE; } - if (oldcamera != players[i].camera) + if (oldcamera != p->camera) { - R_ClearPastViewer (players[i].camera); + R_ClearPastViewer (p->camera); } } } @@ -2977,14 +2978,15 @@ FUNC(LS_SetPlayerProperty) for (i = 0; i < MAXPLAYERS; i++) { - if (!playeringame[i] || players[i].mo == NULL) + auto p = Level->Players[i]; + if (!Level->PlayerInGame(i) || p->mo == nullptr) continue; if (arg1) { // Give power if (power != 4) { - auto item = players[i].mo->GiveInventoryType ((PClass::FindActor(powers[power]))); + auto item = p->mo->GiveInventoryType ((PClass::FindActor(powers[power]))); if (item != NULL && power == 0 && arg1 == 1) { item->ColorVar(NAME_BlendColor) = MakeSpecialColormap(INVERSECOLORMAP); @@ -2999,7 +3001,7 @@ FUNC(LS_SetPlayerProperty) { // Take power if (power != 4) { - auto item = players[i].mo->FindInventory (PClass::FindActor(powers[power])); + auto item = p->mo->FindInventory (PClass::FindActor(powers[power])); if (item != NULL) { item->Destroy (); @@ -3072,25 +3074,26 @@ FUNC(LS_SetPlayerProperty) for (i = 0; i < MAXPLAYERS; i++) { - if (!playeringame[i]) + if (!Level->PlayerInGame(i)) continue; + auto p = Level->Players[i]; if (arg1) { - players[i].cheats |= mask; + p->cheats |= mask; if (arg2 == PROP_FLY) { - players[i].mo->flags2 |= MF2_FLY; - players[i].mo->flags |= MF_NOGRAVITY; + p->mo->flags2 |= MF2_FLY; + p->mo->flags |= MF_NOGRAVITY; } } else { - players[i].cheats &= ~mask; + p->cheats &= ~mask; if (arg2 == PROP_FLY) { - players[i].mo->flags2 &= ~MF2_FLY; - players[i].mo->flags &= ~MF_NOGRAVITY; + p->mo->flags2 &= ~MF2_FLY; + p->mo->flags &= ~MF_NOGRAVITY; } } } @@ -3310,9 +3313,9 @@ FUNC(LS_GlassBreak) { for (int i = 0; i < MAXPLAYERS; ++i) { - if (playeringame[i]) + if (Level->PlayerInGame(i)) { - it = players[i].mo; + it = Level->Players[i]->mo; break; } } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 57216d5e31..6b11446600 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -945,16 +945,17 @@ DEFINE_ACTION_FUNCTION(AActor, GiveBody) bool AActor::CheckLocalView (int playernum) const { - if (players[playernum].camera == this) + auto p = &players[playernum]; + if (p->camera == this) { return true; } - if (players[playernum].mo != this || players[playernum].camera == NULL) + if (p->mo != this || p->camera == nullptr) { return false; } - if (players[playernum].camera->player == NULL && - !(players[playernum].camera->flags3 & MF3_ISMONSTER)) + if (p->camera->player == NULL && + !(p->camera->flags3 & MF3_ISMONSTER)) { return true; } @@ -985,6 +986,10 @@ bool AActor::IsInsideVisibleAngles() const if (players[consoleplayer].camera == nullptr) return true; + // Not detectable. + if (!Level->isPrimaryLevel()) + return true; + DAngle anglestart = VisibleStartAngle; DAngle angleend = VisibleEndAngle; DAngle pitchstart = VisibleStartPitch; @@ -3264,7 +3269,7 @@ bool AActor::IsOkayToAttack (AActor *link) AActor * Friend; if (flags5 & MF5_SUMMONEDMONSTER) Friend = tracer; else if (flags2 & MF2_SEEKERMISSILE) Friend = target; - else if ((flags & MF_FRIENDLY) && FriendPlayer) Friend = players[FriendPlayer-1].mo; + else if ((flags & MF_FRIENDLY) && FriendPlayer) Friend = Level->Players[FriendPlayer-1]->mo; else Friend = this; // Friend checks @@ -5052,9 +5057,9 @@ AActor *FLevelLocals::SpawnPlayer (FPlayerStart *mthing, int playernum, int flag for (int ii = 0; ii < MAXPLAYERS; ++ii) { - if (playeringame[ii] && players[ii].camera == oldactor) + if (PlayerInGame(ii) && Players[ii]->camera == oldactor) { - players[ii].camera = mobj; + Players[ii]->camera = mobj; } } @@ -6825,13 +6830,13 @@ bool AActor::IsFriend (AActor *other) if (deathmatch && teamplay) return IsTeammate(other) || (FriendPlayer != 0 && other->FriendPlayer != 0 && - players[FriendPlayer-1].mo->IsTeammate(players[other->FriendPlayer-1].mo)); + Level->Players[FriendPlayer-1]->mo->IsTeammate(Level->Players[other->FriendPlayer-1]->mo)); return !deathmatch || FriendPlayer == other->FriendPlayer || FriendPlayer == 0 || other->FriendPlayer == 0 || - players[FriendPlayer-1].mo->IsTeammate(players[other->FriendPlayer-1].mo); + Level->Players[FriendPlayer-1]->mo->IsTeammate(Level->Players[other->FriendPlayer-1]->mo); } // [SP] If friendly flags match, then they are on the same team. /*if (!((flags ^ other->flags) & MF_FRIENDLY)) @@ -6858,13 +6863,13 @@ bool AActor::IsHostile (AActor *other) if (deathmatch && teamplay) return !IsTeammate(other) && !(FriendPlayer != 0 && other->FriendPlayer != 0 && - players[FriendPlayer-1].mo->IsTeammate(players[other->FriendPlayer-1].mo)); + Level->Players[FriendPlayer-1]->mo->IsTeammate(Level->Players[other->FriendPlayer-1]->mo)); return deathmatch && FriendPlayer != other->FriendPlayer && FriendPlayer !=0 && other->FriendPlayer != 0 && - !players[FriendPlayer-1].mo->IsTeammate(players[other->FriendPlayer-1].mo); + !Level->Players[FriendPlayer-1]->mo->IsTeammate(Level->Players[other->FriendPlayer-1]->mo); } return true; } diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index a2378b3166..b11de948c7 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -573,7 +573,7 @@ void P_SerializePlayers(FLevelLocals *Level, FSerializer &arc, bool skipload) // Count the number of players present right now. for (numPlayersNow = 0, i = 0; i < MAXPLAYERS; ++i) { - if (playeringame[i]) + if (Level->PlayerInGame(i)) { ++numPlayersNow; } @@ -879,16 +879,16 @@ void FLevelLocals::SpawnExtraPlayers() // be sure to spawn the extra players. int i; - if (deathmatch) + if (deathmatch || !isPrimaryLevel()) { return; } for (i = 0; i < MAXPLAYERS; ++i) { - if (playeringame[i] && players[i].mo == NULL) + if (PlayerInGame(i) && Players[i]->mo == NULL) { - players[i].playerstate = PST_ENTER; + Players[i]->playerstate = PST_ENTER; SpawnPlayer(&playerstarts[i], i, (flags2 & LEVEL2_PRERAISEWEAPON) ? SPF_WEAPONFULLYUP : 0); } } @@ -1019,9 +1019,9 @@ void FLevelLocals::Serialize(FSerializer &arc, bool hubload) } for (int i = 0; i < MAXPLAYERS; ++i) { - if (playeringame[i] && players[i].mo != nullptr) + if (PlayerInGame(i) && Players[i]->mo != nullptr) { - FWeaponSlots::SetupWeaponSlots(players[i].mo); + FWeaponSlots::SetupWeaponSlots(Players[i]->mo); } } RecreateAllAttachedLights(); diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 83724cd21a..cee9f639bb 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -378,13 +378,13 @@ void P_SetupLevel(FLevelLocals *Level, int position, bool newGame) Level->SetMusicVolume(Level->MusicVolume); for (i = 0; i < MAXPLAYERS; ++i) { - players[i].killcount = players[i].secretcount - = players[i].itemcount = 0; + Level->Players[i]->killcount = Level->Players[i]->secretcount + = Level->Players[i]->itemcount = 0; } } for (i = 0; i < MAXPLAYERS; ++i) { - players[i].mo = nullptr; + Level->Players[i]->mo = nullptr; } // [RH] Clear any scripted translation colors the previous level may have set. for (i = 0; i < int(translationtables[TRANSLATION_LevelScripted].Size()); ++i) @@ -439,9 +439,9 @@ void P_SetupLevel(FLevelLocals *Level, int position, bool newGame) { for (i = 0; i < MAXPLAYERS; i++) { - if (playeringame[i]) + if (Level->PlayerInGame(i)) { - players[i].mo = nullptr; + Level->Players[i]->mo = nullptr; Level->DeathMatchSpawnPlayer(i); } } @@ -451,9 +451,9 @@ void P_SetupLevel(FLevelLocals *Level, int position, bool newGame) { for (i = 0; i < MAXPLAYERS; ++i) { - if (playeringame[i]) + if (Level->PlayerInGame(i)) { - players[i].mo = nullptr; + Level->Players[i]->mo = nullptr; FPlayerStart *mthing = Level->PickPlayerStart(i); Level->SpawnPlayer(mthing, i, (Level->flags2 & LEVEL2_PRERAISEWEAPON) ? SPF_WEAPONFULLYUP : 0); } @@ -466,11 +466,12 @@ void P_SetupLevel(FLevelLocals *Level, int position, bool newGame) { for (i = 0; i < MAXPLAYERS; ++i) { - if (playeringame[i] && players[i].mo != nullptr) + auto p = Level->Players[i]; + if (Level->PlayerInGame(i) && p->mo != nullptr) { - if (!(players[i].mo->flags & MF_FRIENDLY)) + if (!(p->mo->flags & MF_FRIENDLY)) { - AActor * oldSpawn = players[i].mo; + AActor * oldSpawn = p->mo; Level->DeathMatchSpawnPlayer(i); oldSpawn->Destroy(); }