From d358e401ee1af272e4802ee772461bbb8eda66e1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 1 Feb 2019 17:02:10 +0100 Subject: [PATCH] - removed all access to the consoleplayer variable from the play code There is one exception in ACS for a net arbitrator check. Aside from this the bot_observer CVAR was also removed. This was never implemented properly and could stomp upon custom player settings. --- src/b_bot.cpp | 1 - src/b_bot.h | 6 ----- src/b_func.cpp | 12 --------- src/b_game.cpp | 19 -------------- src/g_levellocals.h | 24 ++++++++++++++++-- src/p_acs.cpp | 14 +++++------ src/p_conversation.cpp | 4 +-- src/p_effect.cpp | 56 ++++++++++++++++++++++-------------------- src/p_interaction.cpp | 4 +-- src/p_lnspec.cpp | 8 +++--- src/p_map.cpp | 5 ++-- src/p_mobj.cpp | 44 +++++++++++++++++++-------------- src/p_pspr.cpp | 4 --- src/p_saveg.cpp | 3 ++- src/p_setup.cpp | 3 ++- src/p_user.cpp | 6 ++--- 16 files changed, 102 insertions(+), 111 deletions(-) diff --git a/src/b_bot.cpp b/src/b_bot.cpp index 54e8991c43..6924c9c93a 100644 --- a/src/b_bot.cpp +++ b/src/b_bot.cpp @@ -151,7 +151,6 @@ void DBot::Tick () } CVAR (Int, bot_next_color, 11, 0) -CVAR (Bool, bot_observer, false, 0) CCMD (addbot) { diff --git a/src/b_bot.h b/src/b_bot.h index b7a30d5ebe..57323aada8 100644 --- a/src/b_bot.h +++ b/src/b_bot.h @@ -159,7 +159,6 @@ private: protected: bool ctf; int t_join; - bool observer; //Consoleplayer is observer. }; class DBot : public DThinker @@ -242,10 +241,5 @@ extern cycle_t BotThinkCycles, BotSupportCycles; EXTERN_CVAR (Float, bot_flag_return_time) EXTERN_CVAR (Int, bot_next_color) -EXTERN_CVAR (Bool, bot_allow_duds) -EXTERN_CVAR (Int, bot_maxcorpses) -EXTERN_CVAR (Bool, bot_observer) -EXTERN_CVAR (Bool, bot_watersplash) -EXTERN_CVAR (Bool, bot_chat) #endif // __B_BOT_H__ diff --git a/src/b_func.cpp b/src/b_func.cpp index 9d0b015dd6..207d4454b4 100644 --- a/src/b_func.cpp +++ b/src/b_func.cpp @@ -345,7 +345,6 @@ AActor *DBot::Choose_Mate () int count; double closest_dist, test; AActor *target; - AActor *observer; //is mate alive? if (mate) @@ -365,10 +364,6 @@ AActor *DBot::Choose_Mate () target = NULL; closest_dist = FLT_MAX; - if (bot_observer) - observer = players[consoleplayer].mo; - else - observer = NULL; //Check for player friends for (count = 0; count < MAXPLAYERS; count++) @@ -380,7 +375,6 @@ AActor *DBot::Choose_Mate () && player->mo != client->mo && (player->mo->IsTeammate (client->mo) || !deathmatch) && client->mo->health > 0 - && client->mo != observer && ((player->mo->health/2) <= client->mo->health || !deathmatch) && !Level->BotInfo.IsLeader(client)) //taken? { @@ -423,7 +417,6 @@ AActor *DBot::Find_enemy () double closest_dist, temp; //To target. AActor *target; DAngle vangle; - AActor *observer; if (!deathmatch) { // [RH] Take advantage of the Heretic/Hexen code to be a little smarter @@ -439,17 +432,12 @@ AActor *DBot::Find_enemy () target = NULL; closest_dist = FLT_MAX; - if (bot_observer) - observer = players[consoleplayer].mo; - else - observer = NULL; for (count = 0; count < MAXPLAYERS; count++) { player_t *client = &players[count]; if (playeringame[count] && !player->mo->IsTeammate (client->mo) - && client->mo != observer && client->mo->health > 0 && player->mo != client->mo) { diff --git a/src/b_game.cpp b/src/b_game.cpp index 603d7ecb83..2442eea5b2 100644 --- a/src/b_game.cpp +++ b/src/b_game.cpp @@ -148,24 +148,6 @@ void FCajunMaster::Main(FLevelLocals *Level) //Check if player should go observer. Or un observe FLinkContext ctx; - if (bot_observer && !observer && !netgame) - { - Printf ("%s is now observer\n", players[consoleplayer].userinfo.GetName()); - observer = true; - players[consoleplayer].mo->UnlinkFromWorld (&ctx); - players[consoleplayer].mo->flags = MF_DROPOFF|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOTDMATCH|MF_NOGRAVITY|MF_FRIENDLY; - players[consoleplayer].mo->flags2 |= MF2_FLY; - players[consoleplayer].mo->LinkToWorld (&ctx); - } - else if (!bot_observer && observer && !netgame) //Go back - { - Printf ("%s returned to the fray\n", players[consoleplayer].userinfo.GetName()); - observer = false; - players[consoleplayer].mo->UnlinkFromWorld (&ctx); - players[consoleplayer].mo->flags = MF_SOLID|MF_SHOOTABLE|MF_DROPOFF|MF_PICKUP|MF_NOTDMATCH|MF_FRIENDLY; - players[consoleplayer].mo->flags2 &= ~MF2_FLY; - players[consoleplayer].mo->LinkToWorld (&ctx); - } } void FCajunMaster::Init () @@ -173,7 +155,6 @@ void FCajunMaster::Init () botnum = 0; firstthing = nullptr; spawn_tries = 0; - observer = false; body1 = nullptr; body2 = nullptr; diff --git a/src/g_levellocals.h b/src/g_levellocals.h index 74011f9e1e..b0229af5fc 100644 --- a/src/g_levellocals.h +++ b/src/g_levellocals.h @@ -506,8 +506,8 @@ public: 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. + // As things progress each level needs to be able to point to different players, even if they are just null if the second level is merely a skybox or camera target. + // But even if it got a real player, the level will not own it - the player merely links to the level. // This should also be made a real object eventually. player_t *Players[MAXPLAYERS]; @@ -540,6 +540,26 @@ public: { return true; } + + // Gets the console player without having the calling code be aware of the level's state. + player_t *GetConsolePlayer() const + { + return isPrimaryLevel()? Players[consoleplayer] : nullptr; + } + + bool isConsolePlayer(AActor *mo) const + { + auto p = GetConsolePlayer(); + if (!p) return false; + return p->mo == mo; + } + + bool isCamera(AActor *mo) const + { + auto p = GetConsolePlayer(); + if (!p) return false; + return p->camera == mo; + } int NumMapSections; diff --git a/src/p_acs.cpp b/src/p_acs.cpp index e4d58b23f8..6706de0c2c 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -4966,7 +4966,8 @@ int DLevelScript::SetUserCVar(int playernum, const char *cvarname, int value, bo { return 0; } - FBaseCVar **cvar_p = Level->Players[playernum]->userinfo.CheckKey(FName(cvarname, true)); + auto player = Level->Players[playernum]; + FBaseCVar **cvar_p = player->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)) @@ -4976,7 +4977,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 && Level->isPrimaryLevel()) + if (player && player == Level->GetConsolePlayer()) { 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, @@ -8623,8 +8624,7 @@ scriptwait: { screen = screen->target; } - if (Level->isPrimaryLevel() && (pcd == PCD_ENDHUDMESSAGEBOLD || screen == NULL || - players[consoleplayer].mo == screen)) + if (Level->isPrimaryLevel() && (pcd == PCD_ENDHUDMESSAGEBOLD || screen == NULL || Level->isConsolePlayer(screen))) { int type = Stack[optstart-6]; int id = Stack[optstart-5]; @@ -9307,7 +9307,7 @@ scriptwait: break; case PCD_LOCALSETMUSIC: - if (activator == players[consoleplayer].mo) + if (Level->isConsolePlayer(activator)) { S_ChangeMusic (Level->Behaviors.LookupString (STACK(3)), STACK(2)); } @@ -9315,7 +9315,7 @@ scriptwait: break; case PCD_LOCALSETMUSICDIRECT: - if (activator == players[consoleplayer].mo) + if (Level->isConsolePlayer(activator)) { S_ChangeMusic (Level->Behaviors.LookupString (TAGSTR(uallong(pc[0]))), uallong(pc[1])); } @@ -10402,7 +10402,7 @@ int P_StartScript (FLevelLocals *Level, AActor *who, line_t *where, int script, } else { - if (!(flags & ACS_NET) || (who && who->player == &players[consoleplayer])) + if (!(flags & ACS_NET) || (who && Level->isConsolePlayer(who->player->mo))) // The indirection is necessary here. { Printf("P_StartScript: Unknown %s\n", ScriptPresentation(script).GetChars()); } diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index dd84bad64d..ccf43c9d91 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -763,7 +763,7 @@ void P_StartConversation (AActor *npc, AActor *pc, bool facetalker, bool saveang FStrifeDialogueNode *CurNode = npc->Conversation; - if (pc->player == &players[consoleplayer]) + if (pc->player == Level->GetConsolePlayer()) { S_Sound (CHAN_VOICE | CHAN_UI, gameinfo.chatSound, 1, ATTN_NONE); } @@ -811,7 +811,7 @@ void P_StartConversation (AActor *npc, AActor *pc, bool facetalker, bool saveang } // The rest is only done when the conversation is actually displayed. - if (pc->player == &players[consoleplayer]) + if (pc->player == Level->GetConsolePlayer()) { if (CurNode->SpeakerVoice != 0) { diff --git a/src/p_effect.cpp b/src/p_effect.cpp index 1f3af0059b..8822868bda 100644 --- a/src/p_effect.cpp +++ b/src/p_effect.cpp @@ -631,12 +631,12 @@ void P_DrawRailTrail(AActor *source, TArray &portalhits, int color1, seg.extend = (tempvec - (seg.dir | tempvec) * seg.dir) * 3; length += seg.length; - if (source->Level->isPrimaryLevel()) + auto player = source->Level->GetConsolePlayer(); + if (player) { // Only consider sound in 2D (for now, anyway) // [BB] You have to divide by lengthsquared here, not multiply with it. - AActor *mo = players[consoleplayer].camera; - + AActor *mo = player->camera; double r = ((seg.start.Y - mo->Y()) * (-seg.dir.Y) - (seg.start.X - mo->X()) * (seg.dir.X)) / (seg.length * seg.length); r = clamp(r, 0., 1.); seg.soundpos = seg.start + r * seg.dir; @@ -656,32 +656,36 @@ void P_DrawRailTrail(AActor *source, TArray &portalhits, int color1, if (steps) { - if (!(flags & RAF_SILENT) && source->Level->isPrimaryLevel()) + if (!(flags & RAF_SILENT)) { - FSoundID sound; - - // Allow other sounds than 'weapons/railgf'! - if (!source->player) sound = source->AttackSound; - else if (source->player->ReadyWeapon) sound = source->player->ReadyWeapon->AttackSound; - else sound = 0; - if (!sound) sound = "weapons/railgf"; - - // The railgun's sound is special. It gets played from the - // point on the slug's trail that is closest to the hearing player. - AActor *mo = players[consoleplayer].camera; - - if (fabs(mo->X() - trail[0].start.X) < 20 && fabs(mo->Y() - trail[0].start.Y) < 20) - { // This player (probably) fired the railgun - S_Sound (mo, CHAN_WEAPON, sound, 1, ATTN_NORM); - } - else + auto player = source->Level->GetConsolePlayer(); + if (player) { - TrailSegment *shortest = NULL; - for (auto &seg : trail) - { - if (shortest == NULL || shortest->sounddist > seg.sounddist) shortest = &seg; + FSoundID sound; + + // Allow other sounds than 'weapons/railgf'! + if (!source->player) sound = source->AttackSound; + else if (source->player->ReadyWeapon) sound = source->player->ReadyWeapon->AttackSound; + else sound = 0; + if (!sound) sound = "weapons/railgf"; + + // The railgun's sound is special. It gets played from the + // point on the slug's trail that is closest to the hearing player. + AActor *mo = player->camera; + + if (fabs(mo->X() - trail[0].start.X) < 20 && fabs(mo->Y() - trail[0].start.Y) < 20) + { // This player (probably) fired the railgun + S_Sound (mo, CHAN_WEAPON, sound, 1, ATTN_NORM); + } + else + { + TrailSegment *shortest = NULL; + for (auto &seg : trail) + { + if (shortest == NULL || shortest->sounddist > seg.sounddist) shortest = &seg; + } + S_Sound (source->Level, DVector3(shortest->soundpos, r_viewpoint.Pos.Z), CHAN_WEAPON, sound, 1, ATTN_NORM); } - S_Sound (source->Level, DVector3(shortest->soundpos, r_viewpoint.Pos.Z), CHAN_WEAPON, sound, 1, ATTN_NORM); } } } diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index d5fb79cc38..1a6fdbe4a5 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -606,7 +606,7 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags, FName MeansOf VMCall(func, ¶m, 1, nullptr, 0); } - if (this == players[consoleplayer].camera && automapactive) + if (Level->isCamera(this) && automapactive) { // don't die in auto map, switch view prior to dying AM_Stop (); @@ -1352,7 +1352,7 @@ static int DamageMobj (AActor *target, AActor *inflictor, AActor *source, int da player->damagecount = 100; // teleport stomp does 10k points... } temp = damage < 100 ? damage : 100; - if (player == &players[consoleplayer]) + if (player == target->Level->GetConsolePlayer() ) { I_Tactile (40,10,40+temp*2); } diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index 08513304b1..63bdc8f15a 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -2951,7 +2951,7 @@ FUNC(LS_SetPlayerProperty) item->ColorVar(NAME_BlendColor) = MakeSpecialColormap(INVERSECOLORMAP); } } - else if (it->player - players == consoleplayer) + else if (it->player && it->player == Level->GetConsolePlayer()) { Level->flags2 |= LEVEL2_ALLMAP; } @@ -2966,7 +2966,7 @@ FUNC(LS_SetPlayerProperty) item->Destroy (); } } - else if (it->player - players == consoleplayer) + else if (it->player && it->player == Level->GetConsolePlayer()) { Level->flags2 &= ~LEVEL2_ALLMAP; } @@ -2992,7 +2992,7 @@ FUNC(LS_SetPlayerProperty) item->ColorVar(NAME_BlendColor) = MakeSpecialColormap(INVERSECOLORMAP); } } - else if (i == consoleplayer) + else if (p == Level->GetConsolePlayer()) { Level->flags2 |= LEVEL2_ALLMAP; } @@ -3007,7 +3007,7 @@ FUNC(LS_SetPlayerProperty) item->Destroy (); } } - else if (i == consoleplayer) + else if (p == Level->GetConsolePlayer()) { Level->flags2 &= ~LEVEL2_ALLMAP; } diff --git a/src/p_map.cpp b/src/p_map.cpp index edcc6161ea..e9639d5aa4 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -2448,7 +2448,7 @@ bool P_TryMove(AActor *thing, const DVector2 &pos, } // if this is the current camera we need to store the point where the portal was crossed and the exit // so that the renderer can properly calculate an interpolated position along the movement path. - if (thing == players[consoleplayer].camera) + if (thing->Level->isCamera(thing)) { divline_t dl1 = { besthit.Oldrefpos.X,besthit.Oldrefpos.Y, besthit.Refpos.X - besthit.Oldrefpos.X, besthit.Refpos.Y - besthit.Oldrefpos.Y }; DVector3a hit = { {dl1.x + dl1.dx * bestfrac, dl1.y + dl1.dy * bestfrac, 0.},0. }; @@ -2463,7 +2463,8 @@ bool P_TryMove(AActor *thing, const DVector2 &pos, { P_TranslatePortalXY(ld, hit.pos.X, hit.pos.Y); P_TranslatePortalZ(ld, hit.pos.Z); - players[consoleplayer].viewz += hit.pos.Z; // needs to be done here because otherwise the renderer will not catch the change. + auto p = thing->Level->GetConsolePlayer(); + if (p) p->viewz += hit.pos.Z; // needs to be done here because otherwise the renderer will not catch the change. P_TranslatePortalAngle(ld, hit.angle); } R_AddInterpolationPoint(hit); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 75a70ad5a1..d414ee8d26 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -945,7 +945,11 @@ DEFINE_ACTION_FUNCTION(AActor, GiveBody) bool AActor::CheckLocalView() const { - auto p = &players[consoleplayer]; + auto p = Level->GetConsolePlayer(); + if (p == nullptr) + { + return false; + } if (p->camera == this) { return true; @@ -982,12 +986,10 @@ bool AActor::IsInsideVisibleAngles() const // Don't bother masking if not wanted. if (!(renderflags & RF_MASKROTATION)) return true; - - if (players[consoleplayer].camera == nullptr) - return true; - // Not detectable. - if (!Level->isPrimaryLevel()) + auto p = Level->GetConsolePlayer(); + + if (p == nullptr || p->camera == nullptr) return true; DAngle anglestart = VisibleStartAngle; @@ -1010,7 +1012,7 @@ bool AActor::IsInsideVisibleAngles() const } - AActor *mo = players[consoleplayer].camera; + AActor *mo = p->camera; if (mo != nullptr) { @@ -1046,19 +1048,19 @@ bool AActor::IsInsideVisibleAngles() const bool AActor::IsVisibleToPlayer() const { - auto &p = players[consoleplayer]; + auto p = Level->GetConsolePlayer(); // [BB] Safety check. This should never be NULL. Nevertheless, we return true to leave the default ZDoom behavior unaltered. - if ( p.camera == nullptr ) + if (p == nullptr || p->camera == nullptr ) return true; if (VisibleToTeam != 0 && teamplay && - (signed)(VisibleToTeam-1) != p.userinfo.GetTeam() ) + (signed)(VisibleToTeam-1) != p->userinfo.GetTeam() ) return false; auto &vis = GetInfo()->VisibleToPlayerClass; if (vis.Size() == 0) return true; // early out for the most common case. - const player_t* pPlayer = p.camera->player; + const player_t* pPlayer = p->camera->player; if (pPlayer) { @@ -4902,7 +4904,7 @@ AActor *FLevelLocals::SpawnPlayer (FPlayerStart *mthing, int playernum, int flag return NULL; } // not playing? - if ((unsigned)playernum >= (unsigned)MAXPLAYERS || !playeringame[playernum]) + if ((unsigned)playernum >= (unsigned)MAXPLAYERS || !PlayerInGame(playernum) ) return NULL; // Old lerp data needs to go @@ -4911,7 +4913,7 @@ AActor *FLevelLocals::SpawnPlayer (FPlayerStart *mthing, int playernum, int flag P_PredictionLerpReset(); } - p = &players[playernum]; + p = Players[playernum]; if (p->cls == NULL) { @@ -5271,10 +5273,14 @@ AActor *FLevelLocals::SpawnMapThing (FMapThing *mthing, int position) // this is enabled for all games. if (!multiplayer) { // Single player - int spawnmask = players[consoleplayer].GetSpawnClass(); - if (spawnmask != 0 && (mthing->ClassFilter & spawnmask) == 0) - { // Not for current class - return NULL; + auto p = GetConsolePlayer(); + if (p) + { + int spawnmask = p->GetSpawnClass(); + if (spawnmask != 0 && (mthing->ClassFilter & spawnmask) == 0) + { // Not for current class + return nullptr; + } } } else if (!deathmatch) @@ -5282,9 +5288,9 @@ AActor *FLevelLocals::SpawnMapThing (FMapThing *mthing, int position) mask = 0; for (int i = 0; i < MAXPLAYERS; i++) { - if (playeringame[i]) + if (PlayerInGame(i)) { - int spawnmask = players[i].GetSpawnClass(); + int spawnmask = Players[i]->GetSpawnClass(); if (spawnmask != 0) mask |= spawnmask; else diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index 4a1100b2e2..97be2772c8 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -600,10 +600,6 @@ void P_BobWeapon (player_t *player, float *x, float *y, double ticfrac) static void P_CheckWeaponButtons (player_t *player) { - if (player->Bot == nullptr && bot_observer) - { - return; - } auto weapon = player->ReadyWeapon; if (weapon == nullptr) { diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index 807287f413..45b394e224 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -625,7 +625,8 @@ void P_SerializePlayers(FLevelLocals *Level, FSerializer &arc, bool skipload) Level->SpawnExtraPlayers(); } // Redo pitch limits, since the spawned player has them at 0. - players[consoleplayer].SendPitchLimits(); + auto p = Level->GetConsolePlayer(); + if (p) p->SendPitchLimits(); } } diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 20655a2237..abf4fadbd2 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -401,7 +401,8 @@ void P_SetupLevel(FLevelLocals *Level, int position, bool newGame) translationtables[TRANSLATION_LevelScripted].Clear(); // Initial height of PointOfView will be set by player think. - players[consoleplayer].viewz = NO_VALUE; + auto p = Level->GetConsolePlayer(); + if (p) p->viewz = NO_VALUE; // Make sure all sounds are stopped before Z_FreeTags. S_Start(); diff --git a/src/p_user.cpp b/src/p_user.cpp index a7ad96c275..7616d954c5 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -617,7 +617,7 @@ static int GetSoftPitch(bool down) void player_t::SendPitchLimits() const { - if (this - players == consoleplayer) + if (this == mo->Level->GetConsolePlayer()) { int uppitch, downpitch; @@ -1108,7 +1108,7 @@ void P_CheckMusicChange(player_t *player) { if (--player->MUSINFOtics < 0) { - if (player - players == consoleplayer) + if (player == player->mo->Level->GetConsolePlayer()) { if (player->MUSINFOactor->args[0] != 0) { @@ -1372,7 +1372,7 @@ void P_PredictPlayer (player_t *player) singletics || demoplayback || player->mo == NULL || - player != &players[consoleplayer] || + player != player->mo->Level->GetConsolePlayer() || player->playerstate != PST_LIVE || !netgame || /*player->morphTics ||*/