- 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.
This commit is contained in:
Christoph Oelckers 2019-02-01 17:02:10 +01:00
parent 2903025268
commit d358e401ee
16 changed files with 102 additions and 111 deletions

View file

@ -151,7 +151,6 @@ void DBot::Tick ()
}
CVAR (Int, bot_next_color, 11, 0)
CVAR (Bool, bot_observer, false, 0)
CCMD (addbot)
{

View file

@ -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__

View file

@ -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)
{

View file

@ -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;

View file

@ -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;

View file

@ -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());
}

View file

@ -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)
{

View file

@ -631,12 +631,12 @@ void P_DrawRailTrail(AActor *source, TArray<SPortalHit> &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<double>(r, 0., 1.);
seg.soundpos = seg.start + r * seg.dir;
@ -656,32 +656,36 @@ void P_DrawRailTrail(AActor *source, TArray<SPortalHit> &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);
}
}
}

View file

@ -606,7 +606,7 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags, FName MeansOf
VMCall(func, &param, 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);
}

View file

@ -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;
}

View file

@ -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);

View file

@ -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

View file

@ -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)
{

View file

@ -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();
}
}

View file

@ -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();

View file

@ -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 ||*/