Skip to content

Commit

Permalink
tweak spectator mode and disabled spawns handling
Browse files Browse the repository at this point in the history
- players first entering the server, or trying to respawn, enter spectate mode if there are no enabled spawn points. Players spawn as soon as a spawn point is available.
- leaving spectate mode is instant (no more falling to the floor)
- trigger_respawn and player_respawn_zone ignore spectators

Also fixed "game_playerjoin" being triggered on spawns instead of when the player first entered the server.
  • Loading branch information
wootguy committed Sep 11, 2024
1 parent 7db1546 commit 11e2e97
Show file tree
Hide file tree
Showing 9 changed files with 66 additions and 18 deletions.
4 changes: 2 additions & 2 deletions dlls/CBaseDMStart.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ EntSelectSpawnPoint
Returns the entity to spawn at
============
*/
edict_t* EntSelectSpawnPoint(CBaseEntity* pPlayer)
edict_t* EntSelectSpawnPoint(CBaseEntity* pPlayer, bool includeDisabledSpawns)
{
CBaseEntity* pSpot;

Expand All @@ -69,7 +69,7 @@ edict_t* EntSelectSpawnPoint(CBaseEntity* pPlayer)
for (int i = 0; i < SPAWN_ENT_TYPES; i++) {
pSpot = NULL;
while (!FNullEnt(pSpot = UTIL_FindEntityByClassname(pSpot, spawn_ent_names[i]))) {
if (pSpot->IsTriggered(pPlayer)) {
if (pSpot->IsTriggered(pPlayer) || includeDisabledSpawns) {
if (i == 0) {
legacySpawns.push_back(pSpot);
continue;
Expand Down
2 changes: 1 addition & 1 deletion dlls/CBaseDMStart.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#pragma once

edict_t* EntSelectSpawnPoint(CBaseEntity* pPlayer);
edict_t* EntSelectSpawnPoint(CBaseEntity* pPlayer, bool includeDisabledSpawns=false);

BOOL IsSpawnPointClear(CBaseEntity* pPlayer, CBaseEntity* pSpot);

Expand Down
34 changes: 28 additions & 6 deletions dlls/CBasePlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1703,6 +1703,12 @@ void CBasePlayer::LeaveObserver()
WRITE_SHORT(0);
WRITE_SHORT(GetNameColor());
MESSAGE_END();

// fixes scoreboard
m_fInitHUD = true;
m_fGameHUDInitialized = false;

Spawn();
}

//
Expand Down Expand Up @@ -2238,6 +2244,22 @@ void CBasePlayer::PreThink(void)
Observer_CheckTarget();
Observer_CheckProperties();
pev->impulse = 0;

static float lastCheck = 0;

if (m_wantToExitObserver && (lastCheck > gpGlobals->time || gpGlobals->time - lastCheck > 1.0f)) {
lastCheck = gpGlobals->time;
edict_t* pentSpawnSpot = g_pGameRules->GetPlayerSpawnSpot(this);

if (!FNullEnt(pentSpawnSpot)) {
LeaveObserver();
m_wantToExitObserver = false;
}
else {
UTIL_ClientPrint(edict(), print_center, "Waiting to spawn...\n");
}
}

return;
}

Expand Down Expand Up @@ -3243,8 +3265,13 @@ void CBasePlayer::Spawn( void )
SET_VIEW(edict(), edict());
}

g_pGameRules->PlayerSpawn(this);

g_pGameRules->PlayerSpawn( this );
if (FNullEnt(pentSpawnSpot)) {
edict_t* anySpawnPoint = EntSelectSpawnPoint(this, true);
StartObserver(anySpawnPoint->v.origin, anySpawnPoint->v.angles);
m_wantToExitObserver = true;
}
}

void CBasePlayer :: Precache( void )
Expand Down Expand Up @@ -4207,11 +4234,6 @@ void CBasePlayer :: UpdateClientData( void )
m_fGameHUDInitialized = TRUE;

m_iObserverLastMode = OBS_ROAMING;

if ( g_pGameRules->IsMultiplayer() )
{
FireTargets( "game_playerjoin", this, this, USE_TOGGLE, 0 );
}
}

FireTargets( "game_playerspawn", this, this, USE_TOGGLE, 0 );
Expand Down
1 change: 1 addition & 0 deletions dlls/CBasePlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ class EXPORT CBasePlayer : public CBaseMonster
int m_iObserverLastMode;// last used observer mode
bool m_isObserver;
float m_lastObserverSwitch;
bool m_wantToExitObserver; // set to true if the player should spawn as soon as a spawn point is available
int IsObserver() { return m_isObserver; };
BOOL IsFirstPerson() { return m_hViewEntity.GetEdict() == edict(); }
virtual int GetEntindexPriority() { return ENTIDX_PRIORITY_HIGH; }
Expand Down
10 changes: 9 additions & 1 deletion dlls/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,9 @@ void respawn(entvars_t* pev, BOOL fCopyCorpse)
}

if (FNullEnt(spawnSpot)) {
plr->StartObserver(plr->pev->origin, plr->pev->angles);
plr->m_wantToExitObserver = true;

if (gpGlobals->time - plr->m_lastSpawnMessage > 0.5f) {
CLIENT_PRINTF(plr->edict(), print_center, "No spawn points available");
plr->m_lastSpawnMessage = gpGlobals->time;
Expand Down Expand Up @@ -272,7 +275,12 @@ void ClientPutInServer( edict_t *pEntity )
pPlayer->pev->effects |= EF_NOINTERP;

pPlayer->pev->iuser1 = 0; // disable any spec modes
pPlayer->pev->iuser2 = 0;
pPlayer->pev->iuser2 = 0;

if (g_pGameRules->IsMultiplayer())
{
FireTargets("game_playerjoin", pPlayer, pPlayer, USE_TOGGLE, 0);
}
}

/*
Expand Down
16 changes: 12 additions & 4 deletions dlls/client_commands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -467,13 +467,21 @@ void ClientCommand(edict_t* pEntity)

// notify other clients of player switching to spectator mode
UTIL_ClientPrintAll(print_chat, UTIL_VarArgs("%s switched to spectator mode\n",
(pev->netname && STRING(pev->netname)[0] != 0) ? STRING(pev->netname) : "unconnected"));
(pev->netname && STRING(pev->netname)[0] != 0) ? STRING(pev->netname) : "\\disconnected\\"));
}
else
{
UTIL_ClientPrintAll(print_chat, UTIL_VarArgs("%s stopped spectating\n",
(pev->netname && STRING(pev->netname)[0] != 0) ? STRING(pev->netname) : "unconnected"));
pPlayer->LeaveObserver();
edict_t* pentSpawnSpot = g_pGameRules->GetPlayerSpawnSpot(pPlayer);

if (FNullEnt(pentSpawnSpot)) {
pPlayer->m_wantToExitObserver = true;
UTIL_ClientPrint(pPlayer->edict(), print_chat, "Can't stop spectating. No spawn points are available.\n");
}
else {
pPlayer->LeaveObserver();
UTIL_ClientPrintAll(print_chat, UTIL_VarArgs("%s stopped spectating\n",
(pev->netname&& STRING(pev->netname)[0] != 0) ? STRING(pev->netname) : "\\disconnected\\"));
}
}
}
else
Expand Down
3 changes: 1 addition & 2 deletions dlls/gamerules.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "CBasePlayerItem.h"
#include "PluginManager.h"
#include "game.h"
#include "CBaseDMStart.h"

#include <sstream>
#include <string>
Expand All @@ -37,8 +38,6 @@

using namespace std;

extern edict_t *EntSelectSpawnPoint( CBaseEntity *pPlayer );

DLL_GLOBAL CGameRules* g_pGameRules = NULL;
extern DLL_GLOBAL BOOL g_fGameOver;
extern int gmsgDeathMsg; // client dll messages
Expand Down
9 changes: 7 additions & 2 deletions dlls/triggers/CPlayerRespawnZone.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "cbase.h"
#include "CRuleEntity.h"
#include "CBaseDMStart.h"
#include "CBasePlayer.h"

//
// CPlayerRespawnZone / player_respawn_zone -- teleports players to active spawn points
Expand Down Expand Up @@ -51,17 +52,21 @@ void CPlayerRespawnZone::KeyValue(KeyValueData* pkvd)

void CPlayerRespawnZone::Use(CBaseEntity* pActivator, CBaseEntity* pCaller, USE_TYPE useType, float value)
{
CBaseEntity* pPlayer = NULL;
CBasePlayer* pPlayer = NULL;

bool respawnInside = zoneType == ZONE_RESPAWN_INSIDE;

for (int i = 1; i <= gpGlobals->maxClients; i++)
{
pPlayer = UTIL_PlayerByIndex(i);
pPlayer = (CBasePlayer*)UTIL_PlayerByIndex(i);

if (!pPlayer)
continue;

if (pPlayer->IsObserver()) {
continue;
}

TraceResult trace;
int hullNumber = (pPlayer->pev->flags & FL_DUCKING) ? head_hull : human_hull;

Expand Down
5 changes: 5 additions & 0 deletions dlls/triggers/CTriggerRespawn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ void CTriggerRespawn::RespawnTarget(CBaseEntity* target) {
return;
}

CBasePlayer* plr = (CBasePlayer*)target;
if (target->IsPlayer() && plr->IsObserver()) {
return;
}

// always move player entity, dead or alive
edict_t* spawnPoint = EntSelectSpawnPoint(target);
if (!FNullEnt(spawnPoint)) {
Expand Down

0 comments on commit 11e2e97

Please sign in to comment.