diff --git a/mp/src/game/server/neo/neo_client.cpp b/mp/src/game/server/neo/neo_client.cpp index 87e36d7cd..c32e904e8 100644 --- a/mp/src/game/server/neo/neo_client.cpp +++ b/mp/src/game/server/neo/neo_client.cpp @@ -50,6 +50,8 @@ void FinishClientPutInServer( CNEO_Player *pPlayer ) const CNEORules::RestoreInfo &restoreInfo = restoredInfos.Element(hdl); pPlayer->m_iXP.Set(restoreInfo.xp); pPlayer->IncrementDeathCount(restoreInfo.deaths); + pPlayer->SetDeathTime(restoreInfo.deathTime); + pPlayer->m_bSpawnedThisRound = restoreInfo.spawnedThisRound; ClientPrint(pPlayer, HUD_PRINTTALK, "Your XP and death count have been restored.\n"); } } diff --git a/mp/src/game/server/neo/neo_player.cpp b/mp/src/game/server/neo/neo_player.cpp index 72f56d177..5e6bf9e7b 100644 --- a/mp/src/game/server/neo/neo_player.cpp +++ b/mp/src/game/server/neo/neo_player.cpp @@ -503,6 +503,17 @@ void CNEO_Player::Spawn(void) if (teamNumber == TEAM_JINRAI || teamNumber == TEAM_NSF) { + if (NEORules()->GetRoundStatus() == NeoRoundStatus::PreRoundFreeze) + { + AddFlag(FL_GODMODE); + AddNeoFlag(NEO_FL_FREEZETIME); + } + + if (NEORules()->IsRoundOn()) + { // NEO TODO (Adam) should people who were spectating at the start of the match and potentially have unfair information about the enemy team be allowed to join the game? + m_bSpawnedThisRound = true; + } + State_Transition(STATE_ACTIVE); } diff --git a/mp/src/game/server/neo/neo_player.h b/mp/src/game/server/neo/neo_player.h index d0449aa36..aebda3b14 100644 --- a/mp/src/game/server/neo/neo_player.h +++ b/mp/src/game/server/neo/neo_player.h @@ -199,6 +199,8 @@ class CNEO_Player : public CHL2MP_Player AttackersTotals GetAttackersTotals() const; void StartShowDmgStats(const CTakeDamageInfo *info); + inline void SetDeathTime(const float deathTime) { m_flDeathTime.Set(deathTime); } + IMPLEMENT_NETWORK_VAR_FOR_DERIVED(m_EyeAngleOffset); private: @@ -258,6 +260,7 @@ class CNEO_Player : public CHL2MP_Player CNetworkVar(bool, m_bClientWantNeoName); bool m_bIsPendingSpawnForThisRound; + bool m_bSpawnedThisRound = false; bool m_bKilledInflicted = false; // Server-side var only int m_iTeamDamageInflicted = 0; int m_iTeamKillsInflicted = 0; diff --git a/mp/src/game/shared/neo/neo_gamerules.cpp b/mp/src/game/shared/neo/neo_gamerules.cpp index ff8d8e127..5e1789d9e 100644 --- a/mp/src/game/shared/neo/neo_gamerules.cpp +++ b/mp/src/game/shared/neo/neo_gamerules.cpp @@ -2012,6 +2012,11 @@ void CNEORules::StartNextRound() continue; } + if (pPlayer->GetTeamNumber() == TEAM_SPECTATOR) + { + continue; + } + pPlayer->m_bKilledInflicted = false; if (pPlayer->GetActiveWeapon()) { @@ -2019,11 +2024,6 @@ void CNEORules::StartNextRound() } pPlayer->RemoveAllItems(true); pPlayer->Spawn(); - if (gpGlobals->curtime < m_flNeoRoundStartTime + mp_neo_preround_freeze_time.GetFloat()) - { - pPlayer->AddFlag(FL_GODMODE); - pPlayer->AddNeoFlag(NEO_FL_FREEZETIME); - } pPlayer->m_bInAim = false; pPlayer->m_bInThermOpticCamo = false; @@ -2121,6 +2121,11 @@ bool CNEORules::IsRoundLive() const return m_nRoundStatus == NeoRoundStatus::RoundLive; } +bool CNEORules::IsRoundOn() const +{ + return (m_nRoundStatus == NeoRoundStatus::PreRoundFreeze) || (m_nRoundStatus == NeoRoundStatus::RoundLive) || (m_nRoundStatus == NeoRoundStatus::PostRound); +} + void CNEORules::CreateStandardEntities(void) { BaseClass::CreateStandardEntities(); @@ -3387,9 +3392,11 @@ void CNEORules::ClientDisconnected(edict_t* pClient) const RestoreInfo restoreInfo{ .xp = pNeoPlayer->m_iXP.Get(), .deaths = pNeoPlayer->DeathCount(), + .spawnedThisRound = pNeoPlayer->m_bSpawnedThisRound, + .deathTime = pNeoPlayer->IsAlive() ? gpGlobals->curtime : pNeoPlayer->GetDeathTime(), // NEOTODO (Adam) prevent players abusing retry command to save themselves in games with respawns. Should award xp to whoever did most damage to disconnecting player, for now simply ensure they can't respawn too quickly }; - if (restoreInfo.xp == 0 && restoreInfo.deaths == 0) + if (restoreInfo.xp == 0 && restoreInfo.deaths == 0 && restoreInfo.deathTime == 0.f && restoreInfo.spawnedThisRound == false) { m_pRestoredInfos.Remove(accountID); } @@ -3441,11 +3448,16 @@ bool CNEORules::FPlayerCanRespawn(CBasePlayer* pPlayer) if (jinrai && nsf) { - if (m_nRoundStatus == NeoRoundStatus::Warmup || m_nRoundStatus == NeoRoundStatus::Idle || - m_nRoundStatus == NeoRoundStatus::Pause) + if (!IsRoundOn()) { return true; } + + CNEO_Player* pNeoPlayer = ToNEOPlayer(pPlayer); + if (pNeoPlayer->m_bSpawnedThisRound) + { + return false; + } } else { @@ -3511,6 +3523,28 @@ void CNEORules::SetRoundStatus(NeoRoundStatus status) #endif } +#ifdef GAME_DLL + if (status == NeoRoundStatus::PostRound) + { + for (int i = 1; i < gpGlobals->maxClients; i++) + { + if (auto player = static_cast(UTIL_PlayerByIndex(i))) + { + player->m_bSpawnedThisRound = false; + player->SetDeathTime(0.f); + } + } + + auto currentHandle = m_pRestoredInfos.FirstHandle(); + while (m_pRestoredInfos.IsValidHandle(currentHandle)) + { + m_pRestoredInfos[currentHandle].spawnedThisRound = false; + m_pRestoredInfos[currentHandle].deathTime = 0.f; + currentHandle = m_pRestoredInfos.NextHandle(currentHandle); + } + } +#endif // GAME_DLL + m_nRoundStatus = status; } diff --git a/mp/src/game/shared/neo/neo_gamerules.h b/mp/src/game/shared/neo/neo_gamerules.h index 21ae48054..fa4e7bc78 100644 --- a/mp/src/game/shared/neo/neo_gamerules.h +++ b/mp/src/game/shared/neo/neo_gamerules.h @@ -246,6 +246,7 @@ class CNEORules : public CHL2MPRules, public CGameEventListener #endif bool IsRoundPreRoundFreeze() const; bool IsRoundLive() const; + bool IsRoundOn() const; bool IsRoundOver() const; #ifdef GAME_DLL void GatherGameTypeVotes(); @@ -349,6 +350,8 @@ class CNEORules : public CHL2MPRules, public CGameEventListener { int xp; int deaths; + bool spawnedThisRound; + float deathTime; }; // AccountID_t <- CSteamID::GetAccountID CUtlHashtable m_pRestoredInfos;