diff --git a/src/game/shared/neo/neo_gamerules.cpp b/src/game/shared/neo/neo_gamerules.cpp index 8f8f16217..433b42f8c 100644 --- a/src/game/shared/neo/neo_gamerules.cpp +++ b/src/game/shared/neo/neo_gamerules.cpp @@ -580,6 +580,47 @@ CON_COMMAND( sv_neo_score_set_nsf, "Set point count for team NSF" ) nsf->SetRoundsWon( atoi( args[1] ) ); } +CON_COMMAND(sv_neo_round_set, "Set the next round number") +{ + if (2 != args.ArgC()) + { + Msg( "Usage: %s \n", __FUNCTION__ ); + return; + } + + NEORules()->SetNextRoundNumber(atoi(args[1])); +} + +CON_COMMAND(sv_neo_xp_deaths_set, "Set xp and number of deaths next round for player by SteamID, UserID or partial name match (if unique)") +{ + if (!IN_BETWEEN_EQ(3, args.ArgC(), 4)) + { + Msg("Usage: %s \n", __FUNCTION__); + return; + } + + const int deaths = args.ArgC() == 4 ? atoi(args[3]) : -1; + if (atoi(args[3]) < 0) + { + Msg("Usage: %s \n", __FUNCTION__); + return; + } + + CNEO_Player* pPlayer = static_cast(UTIL_PlayerByCommandArg(args[1])); + if (!pPlayer) + { + Warning("%s: Cannot find player by argument %s\n", __FUNCTION__, args[1]); + return; + } + + const int xp = atoi(args[2]); + if (deaths == -1) + Msg("%s: Setting player: %s xp: %i next round\n", __FUNCTION__, pPlayer->GetPlayerName(), xp); + else + Msg("%s: Setting player: %s xp: %i deaths: %i next round\n", __FUNCTION__, pPlayer->GetPlayerName(), xp, deaths); + NEORules()->SetNextRoundPlayerXPDeaths(pPlayer->GetUserID(), xp, deaths); +} + static void CvarChanged_WeaponStay(IConVar* convar, const char* pOldVal, float flOldVal) { auto wep = gEntList.NextEntByClass((CNEOBaseCombatWeapon*)NULL); @@ -2716,7 +2757,15 @@ void CNEORules::StartNextRound() // NEO TODO (nullsystem): There should be a more sophisticated logic to be able to restore XP // for when moving from idle to preroundfreeze, or in the future, competitive with whatever // extra stuff in there. But to keep it simple: just clear if it was a warmup. - ++m_iRoundNumber; + if (m_inextRoundNumber == -1) + { + ++m_iRoundNumber; + } + else + { + m_iRoundNumber = m_inextRoundNumber; + m_inextRoundNumber = -1; + } SetRoundStatus(NeoRoundStatus::PreRoundFreeze); for (int i = 1; i <= gpGlobals->maxClients; i++) @@ -2744,6 +2793,17 @@ void CNEORules::StartNextRound() } } + const int userID = pPlayer->GetUserID(); + if (const auto hdl = m_pNextRoundXPDeaths.Find(userID); m_pNextRoundXPDeaths.IsValidHandle(hdl)) + { + pPlayer->m_iXP.Set(m_pNextRoundXPDeaths[hdl].xp); + if (m_pNextRoundXPDeaths[hdl].deaths != -1) + { + pPlayer->ResetDeathCount(); + pPlayer->IncrementDeathCount(m_pNextRoundXPDeaths[hdl].deaths); + } + } + pPlayer->SpectatorTakeoverPlayerRevert(); // hard reset: round restart if (pPlayer->GetTeamNumber() == TEAM_SPECTATOR) @@ -2770,6 +2830,7 @@ void CNEORules::StartNextRound() pPlayer->SetTestMessageVisible(false); } + m_pNextRoundXPDeaths.Purge(); m_flPrevThinkKick = 0.0f; m_flPrevThinkMirrorDmg = 0.0f; m_flIntermissionEndTime = 0; @@ -4831,6 +4892,17 @@ void CNEORules::InitDefaultAIRelationships( void ) CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_PLAYER_ALLY, D_HT, 0); CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_PLAYER_ALLY_VITAL,D_HT, 0); } + +void CNEORules::SetNextRoundPlayerXPDeaths(int iEntityIndex, int iNextRoundXP, int iNextRoundDeaths) +{ + bool didInsert = false; + const NextRoundXPDeaths info { iNextRoundXP, iNextRoundDeaths }; + const UtlHashHandle_t hdl = m_pNextRoundXPDeaths.Insert(iEntityIndex, info, &didInsert); + if (!didInsert) + { + m_pNextRoundXPDeaths[hdl] = info; + } +} #endif #ifdef CLIENT_DLL diff --git a/src/game/shared/neo/neo_gamerules.h b/src/game/shared/neo/neo_gamerules.h index f93031468..c2b0bc031 100644 --- a/src/game/shared/neo/neo_gamerules.h +++ b/src/game/shared/neo/neo_gamerules.h @@ -407,7 +407,10 @@ class CNEORules : public CHL2MPRules, public CGameEventListener const char *GetTeamClantag(const int iTeamNum) const; #ifdef GAME_DLL void OnNavMeshLoad() override; -#endif // GAME_DL: + + void SetNextRoundNumber(int iNextRoundNum) { m_inextRoundNumber = iNextRoundNum; }; + void SetNextRoundPlayerXPDeaths(int iEntityIndex, int iNextRoundXP, int iNextRoundDeaths = -1); +#endif // GAME_DLL public: #ifdef GAME_DLL @@ -423,6 +426,13 @@ class CNEORules : public CHL2MPRules, public CGameEventListener // AccountID_t <- CSteamID::GetAccountID CUtlHashtable m_pRestoredInfos; + struct NextRoundXPDeaths + { + int xp; + int deaths; + }; + CUtlHashtable m_pNextRoundXPDeaths; + float m_flPauseDur = 0.0f; int m_iPausingTeam = 0; int m_iPausingRound = 0; @@ -491,6 +501,7 @@ class CNEORules : public CHL2MPRules, public CGameEventListener Vector m_vecPreviousJuggernautSpawn = vec3_origin; bool m_bGotMatchWinner = false; int m_iMatchWinner = TEAM_UNASSIGNED; + int m_inextRoundNumber = -1; #endif CNetworkVar(int, m_nRoundStatus); CNetworkVar(int, m_iHiddenHudElements);