-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Award XPs to oppositing team if player tries to prevent ghost cap #556
Award XPs to oppositing team if player tries to prevent ghost cap #556
Conversation
Some edge cases to consider:
|
@Rainyan Updated it to check for those edge-cases now |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested and all seems to work well.
We could probably do without needing to track state in member variables, something like below (untested), but I'm ok with merging what we've got.
diff --git a/mp/src/game/shared/neo/neo_gamerules.cpp b/mp/src/game/shared/neo/neo_gamerules.cpp
index e2f14702..03728fcc 100644
--- a/mp/src/game/shared/neo/neo_gamerules.cpp
+++ b/mp/src/game/shared/neo/neo_gamerules.cpp
@@ -449,9 +449,6 @@ void CNEORules::ResetMapSessionCommon()
m_flNeoNextRoundStartTime = 0.0f;
#ifdef GAME_DLL
m_pRestoredInfos.Purge();
- m_bTeamBeenAwardedDueToCapPrevent = false;
- V_memset(m_arrayiEntPrevCap, 0, sizeof(m_arrayiEntPrevCap));
- m_iEntPrevCapSize = 0;
#endif
}
@@ -974,9 +971,6 @@ void CNEORules::StartNextRound()
m_flIntermissionEndTime = 0;
m_flRestartGameTime = 0;
m_bCompleteReset = false;
- m_bTeamBeenAwardedDueToCapPrevent = false;
- V_memset(m_arrayiEntPrevCap, 0, sizeof(m_arrayiEntPrevCap));
- m_iEntPrevCapSize = 0;
if (clearXP)
{
m_pRestoredInfos.Purge();
@@ -1632,14 +1626,7 @@ void CNEORules::SetWinningTeam(int team, int iWinReason, bool bForceMapReset, bo
}
else if (iWinReason == NEO_VICTORY_TEAM_ELIMINATION)
{
- if (m_bTeamBeenAwardedDueToCapPrevent)
- {
- V_sprintf_safe(victoryMsg, "Team %s wins and is awarded rank ups by ghost cap prevention!\n", (team == TEAM_JINRAI ? "Jinrai" : "NSF"));
- }
- else
- {
- V_sprintf_safe(victoryMsg, "Team %s wins by eliminating the other team!\n", (team == TEAM_JINRAI ? "Jinrai" : "NSF"));
- }
+ V_sprintf_safe(victoryMsg, "Team %s wins by eliminating the other team!\n", (team == TEAM_JINRAI ? "Jinrai" : "NSF"));
}
else if (iWinReason == NEO_VICTORY_TIMEOUT_WIN_BY_NUMBERS)
{
@@ -1679,7 +1666,6 @@ void CNEORules::SetWinningTeam(int team, int iWinReason, bool bForceMapReset, bo
soundParams.m_bEmitCloseCaption = false;
const int winningTeamNum = winningTeam->GetTeamNumber();
- int iRankupCapPrev = 0;
for (int i = 1; i <= gpGlobals->maxClients; ++i)
{
@@ -1708,17 +1694,8 @@ void CNEORules::SetWinningTeam(int team, int iWinReason, bool bForceMapReset, bo
int xpAward = 1; // Base reward for being on winning team
if (player->IsAlive())
{
- if (m_bTeamBeenAwardedDueToCapPrevent)
- {
- AwardRankUp(player);
- xpAward = 0; // Already been rewarded rank-up XPs
- ++iRankupCapPrev;
- }
- else
- {
- ++xpAward;
- xpAward += static_cast<int>(player->IsCarryingGhost());
- }
+ ++xpAward;
+ xpAward += static_cast<int>(player->IsCarryingGhost());
}
player->m_iXP.GetForModify() += xpAward;
}
@@ -1731,16 +1708,6 @@ void CNEORules::SetWinningTeam(int team, int iWinReason, bool bForceMapReset, bo
}
}
- if (m_bTeamBeenAwardedDueToCapPrevent && iWinReason != NEO_VICTORY_GHOST_CAPTURE)
- {
- UTIL_ClientPrintAll(HUD_PRINTTALK, "Last player of %s1 suicided vs. ghost carrier; awarding capture to team %s2.",
- (team == TEAM_JINRAI ? "NSF" : "Jinrai"), (team == TEAM_JINRAI ? "Jinrai" : "NSF"));
- char szHudChatPrint[128];
- V_sprintf_safe(szHudChatPrint, "Awarding capture rank-up to %d player%s.",
- iRankupCapPrev, iRankupCapPrev == 1 ? "" : "s");
- UTIL_ClientPrintAll(HUD_PRINTTALK, szHudChatPrint);
- }
-
if (gotMatchWinner)
{
GoToIntermission();
@@ -1778,53 +1745,19 @@ static CNEO_Player* FetchAssists(CNEO_Player* attacker, CNEO_Player* victim)
}
#ifdef GAME_DLL
-void CNEORules::CheckIfCapPrevent(CNEO_Player *capPreventerPlayer)
+bool CNEORules::CheckIfCapPrevent(CNEO_Player *capPreventerPlayer) const
{
- // If this is the only player alive left before the suicide/disconnect and the other team was holding
- // the ghost, reward the other team an XP to the next rank as a ghost cap was prevented.
- if (neo_sv_suicide_prevent_cap_punish.GetBool() && m_nRoundStatus == NeoRoundStatus::RoundLive &&
- !m_bTeamBeenAwardedDueToCapPrevent)
- {
- bool bOtherTeamPlayingGhost = false;
- int iTallyAlive[TEAM__TOTAL] = {};
- const int iPreventerTeam = capPreventerPlayer->GetTeamNumber();
- // Sanity check: Make sure it's only Jinrai/NSF players
- const bool bValidTeam = iPreventerTeam == TEAM_JINRAI || iPreventerTeam == TEAM_NSF;
- Assert(bValidTeam);
- if (bValidTeam)
- {
- const int iCapPreventerEntIdx = capPreventerPlayer->entindex();
-
- // Sanity check: Prevent duplication just in-case
- bool bContainsEntIdx = false;
- for (int i = 0; i < m_iEntPrevCapSize; ++i)
- {
- bContainsEntIdx = (m_arrayiEntPrevCap[i] == iCapPreventerEntIdx);
- if (bContainsEntIdx) break;
- }
- if (!bContainsEntIdx) m_arrayiEntPrevCap[m_iEntPrevCapSize++] = iCapPreventerEntIdx;
-
- for (int i = 1; i <= gpGlobals->maxClients; ++i)
- {
- auto *player = static_cast<CNEO_Player*>(UTIL_PlayerByIndex(i));
- if (!player || player->entindex() == iCapPreventerEntIdx)
- {
- continue;
- }
-
- const int iPlayerTeam = player->GetTeamNumber();
- iTallyAlive[iPlayerTeam] += player->IsAlive();
- if (iPlayerTeam != iPreventerTeam && player->IsCarryingGhost())
- {
- bOtherTeamPlayingGhost = true;
- }
- }
-
- const int iOppositeTeam = (iPreventerTeam == TEAM_JINRAI) ? TEAM_NSF : TEAM_JINRAI;
- m_bTeamBeenAwardedDueToCapPrevent = (bOtherTeamPlayingGhost &&
- iTallyAlive[iPreventerTeam] == 0 && iTallyAlive[iOppositeTeam] > 0);
- }
+ if (!neo_sv_suicide_prevent_cap_punish.GetBool() ||
+ m_nRoundStatus != NeoRoundStatus::RoundLive ||
+ ghosterTeam() == TEAM_UNASSIGNED ||
+ ghosterTeam() == capPreventerPlayer->GetTeamNumber())
+ {
+ return false;
}
+
+ // -1 because the preventer's death hasn't gone through yet.
+ const auto numAlive = capPreventerPlayer->GetTeam()->GetAliveMembers() - 1;
+ return numAlive == 0;
}
#endif
@@ -1840,41 +1773,45 @@ void CNEORules::PlayerKilled(CBasePlayer *pVictim, const CTakeDamageInfo &info)
return;
}
- // Suicide (or suicide by environment)
- if (attacker == victim || !attacker)
+ // Suicide or teamkill
+ if (attacker == victim || (!attacker || attacker->GetTeamNumber() == victim->GetTeamNumber()))
{
victim->m_iXP.GetForModify() -= 1;
#ifdef GAME_DLL
- CheckIfCapPrevent(victim);
-#endif
- }
- else if (attacker)
- {
- // Team kill
- if (attacker->GetTeamNumber() == victim->GetTeamNumber())
+ if (CheckIfCapPrevent(victim))
{
- attacker->m_iXP.GetForModify() -= 1;
-#ifdef GAME_DLL
- for (int i = 0; i < m_iEntPrevCapSize; ++i)
+ Assert(GetOpposingTeam(victim) == ghosterTeam());
+
+ UTIL_ClientPrintAll(HUD_PRINTTALK, "Last player of %s1 suicided vs. ghost carrier; awarding capture to team %s2.",
+ GetGlobalTeam(victim->GetTeamNumber())->GetName(),
+ GetGlobalTeam(ghosterTeam())->GetName());
+
+ int n_rankups = 0;
+ const auto ghoster_team = GetGlobalTeam(ghosterTeam());
+ for (int i = 0; i < ghoster_team->GetNumPlayers(); ++i)
{
- if (m_arrayiEntPrevCap[i] == attacker->entindex())
+ const auto player = static_cast<CNEO_Player*>(ghoster_team->GetPlayer(i));
+ if (player->IsAlive())
{
- // Posthumous teamkill to prevent ghost cap scenario:
- // Player-A throws nade at Player-B, Player-A suicides right after,
- // Player-B gets killed from the nade - This dodges the general case
- // as Player-A is not the final player, but it was Player-A's intention
- // to prevent the ghost cap.
- CheckIfCapPrevent(victim);
- break;
+ AwardRankUp(player);
+ // Won the round, survived, and possibly is carrying the ghost.
+ player->m_iXP.GetForModify() -= 2 + (GetGhosterPlayer() == player->entindex() ? 1 : 0);
+
+ ++n_rankups;
}
}
-#endif
- }
- // Enemy kill
- else
- {
- attacker->m_iXP.GetForModify() += 1;
+
+ char szHudChatPrint[128];
+ V_sprintf_safe(szHudChatPrint, "Awarding capture rank-up to %d player%s.",
+ n_rankups, n_rankups == 1 ? "" : "s");
+ UTIL_ClientPrintAll(HUD_PRINTTALK, szHudChatPrint);
}
+#endif
+ }
+ // Enemy kill
+ else if (attacker)
+ {
+ attacker->m_iXP.GetForModify() += 1;
if (auto *assister = FetchAssists(attacker, victim))
{
diff --git a/mp/src/game/shared/neo/neo_gamerules.h b/mp/src/game/shared/neo/neo_gamerules.h
index 9de903e3..2ac9f3e9 100644
--- a/mp/src/game/shared/neo/neo_gamerules.h
+++ b/mp/src/game/shared/neo/neo_gamerules.h
@@ -179,7 +179,7 @@ public:
float GetRoundRemainingTime();
#ifdef GAME_DLL
- void CheckIfCapPrevent(CNEO_Player *capPreventerPlayer);
+ bool CheckIfCapPrevent(CNEO_Player* capPreventerPlayer) const;
#endif
virtual void PlayerKilled(CBasePlayer *pVictim, const CTakeDamageInfo &info) OVERRIDE;
@@ -265,9 +265,6 @@ private:
#ifdef GAME_DLL
CUtlVector<int> m_pGhostCaps;
- bool m_bTeamBeenAwardedDueToCapPrevent = false;
- int m_arrayiEntPrevCap[MAX_PLAYERS + 1]; // This is to check for cap-prevention workaround attempts
- int m_iEntPrevCapSize = 0;
#endif
CNetworkVar(int, m_nRoundStatus); // NEO TODO (Rain): probably don't need to network this
CNetworkVar(int, m_iRoundNumber);
In the posthumous teamkill to prevent a ghost cap scenario if Player A is on the team controlling the ghost, they can throw a grenade at the last member of the non-ghosting team and then immediately disconnect to force the suicide to prevent ghost cap system to kick in I think this is a genuine thing that could happen when the person throwing the grenade is probably receiving ghost calls but the ghost carrier is unable to capture the ghost due to the last enemy positioning themselves between the ghost carrier and cap point |
1acf4d9
to
8255d82
Compare
8255d82
to
9a35cc0
Compare
@AdamTadeusz I've altered the code now to deal with disconnect enemy-grenade causes trigger issue now. It seems ok from the test between two machines. |
Can confirm this is fixed now |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, left some notes but I'd be happy to merge.
* If it's like EX: 1v3 alives, the 3-person team is playing the ghost then the single-alive player decides to suicide, this will reward the ghost playing/winning team a rank up since the suicide player tries to prevent a ghost cap. * New convar: * neo_sv_suicide_prevent_cap_punish - Default: 1 to enable this feature * Add environment suicide as a suicide, add disconnect check * Also check for posthumanus teamkill prevent cap scenario * fixes NeotokyoRebuild#215
d07a836
9a35cc0
to
d07a836
Compare
Description
Toolchain
Linked Issues