Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/game/client/game_controls/SpectatorGUI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -865,7 +865,9 @@ void CSpectatorGUI::UpdatePlayerLabel()
V_wcsncpy(playerText, L"Unable to find #Spec_PlayerItem*", sizeof(playerText));
memset(playerName, 0x0, sizeof(playerName));

g_pVGuiLocalize->ConvertANSIToUnicode(UTIL_SafeName(gr->GetPlayerName(playernum)), playerName, sizeof(playerName));
C_NEO_Player* pNeoPlayer = ToNEOPlayer(UTIL_PlayerByIndex(playernum));
const char* pPlayerDisplayName = pNeoPlayer ? pNeoPlayer->GetPlayerNameWithTakeoverContext(playernum) : gr->GetPlayerName(playernum);
g_pVGuiLocalize->ConvertANSIToUnicode(UTIL_SafeName(pPlayerDisplayName), playerName, sizeof(playerName));
int healthMode = cl_neo_hud_health_mode.GetInt();
int iHealth = gr->GetDisplayedHealth(playernum, healthMode);
if (iHealth > 0 && gr->IsAlive(playernum))
Expand Down
61 changes: 48 additions & 13 deletions src/game/client/neo/c_neo_player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "takedamageinfo.h"
#include "neo_gamerules.h"
#include "in_buttons.h"
#include "c_playerresource.h"
#include "iviewrender_beams.h" // flashlight beam
#include "r_efx.h"
#include "dlight.h"
Expand Down Expand Up @@ -71,6 +72,7 @@ IMPLEMENT_CLIENTCLASS_DT(C_NEO_Player, DT_NEO_Player, CNEO_Player)
RecvPropInt(RECVINFO(m_iNeoClass)),
RecvPropInt(RECVINFO(m_iNeoSkin)),
RecvPropInt(RECVINFO(m_iNeoStar)),
RecvPropInt(RECVINFO(m_iClassBeforeTakeover)),

RecvPropBool(RECVINFO(m_bShowTestMessage)),
RecvPropString(RECVINFO(m_pszTestMessage)),
Expand Down Expand Up @@ -106,6 +108,9 @@ IMPLEMENT_CLIENTCLASS_DT(C_NEO_Player, DT_NEO_Player, CNEO_Player)
RecvPropBool(RECVINFO(m_bClientWantNeoName)),

RecvPropTime(RECVINFO(m_flDeathTime)),

RecvPropEHandle(RECVINFO(m_hSpectatorTakeoverPlayerTarget)),
RecvPropEHandle(RECVINFO(m_hSpectatorTakeoverPlayerImpersonatingMe))
END_RECV_TABLE()

BEGIN_PREDICTION_DATA(C_NEO_Player)
Expand Down Expand Up @@ -1992,28 +1997,27 @@ void __MsgFunc_CSpectatorTakeoverPlayer(bf_read &msg)
C_NEO_Player* pPlayerTakeoverTarget = USERID2NEOPLAYER(playerTakeoverTargetUserID);


if (!pPlayerTakeoverTarget || !pSpectatorTakingOver)
if (pPlayerTakeoverTarget && pSpectatorTakingOver)
{
return;
// Save for later in C_NEO_Player::OnDataChanged
pSpectatorTakingOver->m_hSpectatorTakeoverPlayerTarget = pPlayerTakeoverTarget;
pSpectatorTakingOver->m_bCopyOverTakeoverPlayerDetails = true;
}

// Save for later in C_NEO_Player::OnDataChanged
pSpectatorTakingOver->m_hSpectatorTakeoverTarget = pPlayerTakeoverTarget;
}

CUserMessageRegister CSpectatorTakeoverPlayerRegistration("CSpectatorTakeoverPlayer", __MsgFunc_CSpectatorTakeoverPlayer);

void C_NEO_Player::CSpectatorTakeoverPlayerUpdateOnDataChanged()
{
if ( C_NEO_Player* pTarget = m_hSpectatorTakeoverTarget.Get() )
if (m_bCopyOverTakeoverPlayerDetails)
{
// Check if our model is stable from server & matches the target
if (GetModel() && (GetModel() == pTarget->GetModel()))
{
CSpectatorTakeoverPlayerUpdate(pTarget);
m_hSpectatorTakeoverTarget = nullptr;
}
}
m_bCopyOverTakeoverPlayerDetails = false;

if (C_NEO_Player* pTarget = m_hSpectatorTakeoverPlayerTarget.Get())
{
CSpectatorTakeoverPlayerUpdate(pTarget);
}
}
}

void C_NEO_Player::CSpectatorTakeoverPlayerUpdate(C_NEO_Player* pPlayerTakeoverTarget)
Expand Down Expand Up @@ -2052,3 +2056,34 @@ void C_NEO_Player::CSpectatorTakeoverPlayerUpdate(C_NEO_Player* pPlayerTakeoverT
pl.v_angle = pPlayerTakeoverTarget->pl.v_angle; // mimic SnapEyeAngles in neo_player
}

const char* C_NEO_Player::GetPlayerNameWithTakeoverContext(int player_index)
{
if (player_index == 0)
return "";

const char* base_name = g_PR->GetPlayerName(player_index);
if (!base_name)
base_name = "";

// Does not factor in clan tag since original display did not use clan tag
C_NEO_Player* pPlayer = ToNEOPlayer(UTIL_PlayerByIndex(player_index));
if (pPlayer)
{
C_NEO_Player* pTakeoverTarget = ToNEOPlayer(pPlayer->m_hSpectatorTakeoverPlayerTarget.Get());
if (pTakeoverTarget)
{
const char* pTakeoverTargetName = pTakeoverTarget->GetPlayerName();
if (!pTakeoverTargetName)
pTakeoverTargetName = "";

int len = V_sprintf_safe(m_sNameWithTakeoverContextProcessingBuffer, "%s (%s)", pTakeoverTargetName, base_name);
if (len >= sizeof(m_sNameWithTakeoverContextProcessingBuffer))
{
m_sNameWithTakeoverContextProcessingBuffer[sizeof(m_sNameWithTakeoverContextProcessingBuffer) - 2] = ')'; // cap off ()
}
return m_sNameWithTakeoverContextProcessingBuffer;
}
}
return base_name;
}

8 changes: 7 additions & 1 deletion src/game/client/neo/c_neo_player.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,14 +175,19 @@ class C_NEO_Player : public C_HL2MP_Player
virtual void TeamChange(int iNewTeam) override;

// Spectator takeover
bool m_bCopyOverTakeoverPlayerDetails{ false };
CNetworkHandle(C_NEO_Player, m_hSpectatorTakeoverPlayerTarget);
CNetworkHandle(C_NEO_Player, m_hSpectatorTakeoverPlayerImpersonatingMe);
void CSpectatorTakeoverPlayerUpdateOnDataChanged();
void CSpectatorTakeoverPlayerUpdate(C_NEO_Player* pPlayerTakeoverTarget);
CHandle<C_NEO_Player> m_hSpectatorTakeoverTarget;
const char* GetPlayerNameWithTakeoverContext(int player_index);
#ifdef GLOWS_ENABLE
void UpdateGlowEffects(int iNewTeam);
#endif // GLOWS_ENABLE


private:
char m_sNameWithTakeoverContextProcessingBuffer[MAX_PLAYER_NAME_LENGTH];
void CheckThermOpticButtons();
void CheckVisionButtons();
void CheckLeanButtons();
Expand Down Expand Up @@ -224,6 +229,7 @@ class C_NEO_Player : public C_HL2MP_Player
CNetworkVar(int, m_iNeoClass);
CNetworkVar(int, m_iNeoSkin);
CNetworkVar(int, m_iNeoStar);
CNetworkVar(int, m_iClassBeforeTakeover);

CNetworkString(m_szNeoName, MAX_PLAYER_NAME_LENGTH);
CNetworkString(m_szNeoClantag, NEO_MAX_CLANTAG_LENGTH);
Expand Down
38 changes: 23 additions & 15 deletions src/game/client/neo/ui/neo_hud_deathnotice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ class CNEOHud_DeathNotice : public CNEOHud_ChildElement, public CHudElement, pub
void SetColorForNoticePlayer( int iTeamNumber );
void RetireExpiredDeathNotices( void );

const char* GetPlayerNameWithTakeoverContext(int player_index);
virtual void FireGameEvent( IGameEvent * event );
void AddPlayerDeath(IGameEvent* event);
void AddPlayerRankChange(IGameEvent* event);
Expand Down Expand Up @@ -775,6 +776,18 @@ void CNEOHud_DeathNotice::AddPlayerDeath(IGameEvent* event)
if (!victim_name)
victim_name = "";

// Override killer/victim name if they took over another player
C_NEO_Player* pKiller = ToNEOPlayer(UTIL_PlayerByIndex(killer));
C_NEO_Player* pVictim = ToNEOPlayer(UTIL_PlayerByIndex(victim));
C_NEO_Player* pAssist = ToNEOPlayer(UTIL_PlayerByIndex(assist));

if (pKiller)
killer_name = pKiller->GetPlayerNameWithTakeoverContext(killer);
if (pVictim)
victim_name = pVictim->GetPlayerNameWithTakeoverContext(victim);
if (pAssist)
assists_name = pAssist->GetPlayerNameWithTakeoverContext(assist);

// Make a new death notice
DeathNoticeItem deathMsg;
deathMsg.Killer.iEntIndex = killer;
Expand Down Expand Up @@ -863,9 +876,8 @@ void CNEOHud_DeathNotice::AddPlayerRankChange(IGameEvent* event)
const int newRank = event->GetInt("newRank");

// Get the name of the player
const char* playerRankChangeName = g_PR->GetPlayerName(playerRankChange);
if (!playerRankChangeName)
playerRankChangeName = "";
C_NEO_Player* pPlayer = ToNEOPlayer(UTIL_PlayerByIndex(playerRankChange));
const char* playerRankChangeName = pPlayer ? pPlayer->GetPlayerNameWithTakeoverContext(playerRankChange) : "";

// Make a new death notice
DeathNoticeItem deathMsg;
Expand Down Expand Up @@ -896,9 +908,8 @@ void CNEOHud_DeathNotice::AddPlayerGhostCapture(IGameEvent* event)
const int playerCapturedGhost = engine->GetPlayerForUserID(event->GetInt("userid"));

// Get the name of the player
const char* playerCapturedGhostName = g_PR->GetPlayerName(playerCapturedGhost);
if (!playerCapturedGhostName)
playerCapturedGhostName = "";
C_NEO_Player* pPlayer = ToNEOPlayer(UTIL_PlayerByIndex(playerCapturedGhost));
const char* playerCapturedGhostName = pPlayer ? pPlayer->GetPlayerNameWithTakeoverContext(playerCapturedGhost) : "";

// Make a new death notice
DeathNoticeItem deathMsg;
Expand All @@ -925,9 +936,8 @@ void CNEOHud_DeathNotice::AddVIPExtract(IGameEvent* event)
const int playerExtracted = engine->GetPlayerForUserID(event->GetInt("userid"));

// Name of VIP
const char* playerExtractedName = g_PR->GetPlayerName(playerExtracted);
if (!playerExtractedName)
playerExtractedName = "";
C_NEO_Player* pPlayer = ToNEOPlayer(UTIL_PlayerByIndex(playerExtracted));
const char* playerExtractedName = pPlayer ? pPlayer->GetPlayerNameWithTakeoverContext(playerExtracted) : "";

// Make a new death notice
DeathNoticeItem deathMsg;
Expand Down Expand Up @@ -955,12 +965,10 @@ void CNEOHud_DeathNotice::AddVIPDeath(IGameEvent* event)
const int VIPKiller = engine->GetPlayerForUserID(event->GetInt("attacker"));

// Names of vip and killer
const char* playerKilledName = g_PR->GetPlayerName(playerKilled);
if (!playerKilledName)
playerKilledName = "";
const char* VIPKillerName = g_PR->GetPlayerName(VIPKiller);
if (!VIPKillerName)
VIPKillerName = "";
C_NEO_Player* pPlayerKilled = ToNEOPlayer(UTIL_PlayerByIndex(playerKilled));
const char* playerKilledName = pPlayerKilled ? pPlayerKilled->GetPlayerNameWithTakeoverContext(playerKilled) : "";
C_NEO_Player* pVIPKiller = ToNEOPlayer(UTIL_PlayerByIndex(VIPKiller));
const char* VIPKillerName = pVIPKiller ? pVIPKiller->GetPlayerNameWithTakeoverContext(VIPKiller) : "";

// Make a new death notice
DeathNoticeItem deathMsg;
Expand Down
2 changes: 1 addition & 1 deletion src/game/client/neo/ui/neo_hud_friendly_marker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ void CNEOHud_FriendlyMarker::DrawPlayer(Color teamColor, C_NEO_Player *player, c
vgui::surface()->DrawSetTextColor(FadeColour(teamColor, fadeTextMultiplier));

if (settings->bShowName) {
auto playerName = player->GetNeoPlayerName();
auto playerName = player->GetPlayerNameWithTakeoverContext(player->entindex());
const char *playerClantag = player->GetNeoClantag();

if (settings->bPrependClantagToName && playerClantag && playerClantag[0])
Expand Down
26 changes: 24 additions & 2 deletions src/game/client/neo/ui/neo_hud_round_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -722,16 +722,38 @@ int CNEOHud_RoundState::DrawPlayerRow(int playerIndex, const int yOffset, bool s
const char* squadMateClass = GetNeoClassName(g_PR->GetClass(playerIndex));
const bool isAlive = g_PR->IsAlive(playerIndex);

C_NEO_Player* pNeoPlayer = ToNEOPlayer(UTIL_PlayerByIndex(playerIndex));
if (isAlive)
{
const char* pPlayerDisplayName = pNeoPlayer ?
pNeoPlayer->GetPlayerNameWithTakeoverContext(playerIndex)
: g_PR->GetPlayerName(playerIndex);

const char* displayRankName = squadMateRankName;
if (pNeoPlayer)
{
C_NEO_Player* pTakeoverTarget = ToNEOPlayer(pNeoPlayer->m_hSpectatorTakeoverPlayerTarget.Get());
if (pTakeoverTarget)
{
displayRankName = GetRankName(g_PR->GetXP(pTakeoverTarget->entindex()), true);
}
}

const int healthMode = cl_neo_hud_health_mode.GetInt();
char playerHealth[7]; // 4 digits + 2 letters
V_snprintf(playerHealth, sizeof(playerHealth), healthMode ? "%dhp" : "%d%%", g_PR->GetDisplayedHealth(playerIndex, healthMode));
V_snprintf(squadMateText, SQUAD_MATE_TEXT_LENGTH, "%s %s [%s] %s", g_PR->GetPlayerName(playerIndex), squadMateRankName, squadMateClass, playerHealth);
V_snprintf(squadMateText, SQUAD_MATE_TEXT_LENGTH, "%s %s [%s] %s", pPlayerDisplayName, squadMateRankName, squadMateClass, playerHealth);
}
else
{
V_snprintf(squadMateText, SQUAD_MATE_TEXT_LENGTH, "%s [%s] DEAD", g_PR->GetPlayerName(playerIndex), squadMateClass);
auto* pImpersonator = pNeoPlayer ? pNeoPlayer->m_hSpectatorTakeoverPlayerImpersonatingMe.Get() : nullptr;

const char* pPlayerDisplayName = pImpersonator ?
pImpersonator->GetPlayerName()
: g_PR->GetPlayerName(playerIndex);

const char* displayClass = pImpersonator ? GetNeoClassName(pImpersonator->m_iClassBeforeTakeover) : squadMateClass;
V_snprintf(squadMateText, SQUAD_MATE_TEXT_LENGTH, "%s [%s] DEAD", pPlayerDisplayName, displayClass);
}
g_pVGuiLocalize->ConvertANSIToUnicode(squadMateText, wSquadMateText, sizeof(wSquadMateText));

Expand Down
52 changes: 44 additions & 8 deletions src/game/client/neo/ui/neo_scoreboard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

#include "vgui_avatarimage.h"

#include "c_neo_player.h"
#include "neo_player_shared.h"
#include "neo_gamerules.h"

Expand Down Expand Up @@ -617,7 +618,11 @@ void CNEOScoreBoard::UpdatePlayerInfo()
pPlayerList->ModifyItem( itemID, sectionID, playerData );
}

if ( gr->IsLocalPlayer( i ) )
C_NEO_Player *pPlayer = ToNEOPlayer(UTIL_PlayerByIndex(i));
C_NEO_Player *pImpersonator = pPlayer ? ToNEOPlayer(pPlayer->m_hSpectatorTakeoverPlayerImpersonatingMe.Get()) : nullptr;
bool isImpersonatedByLocalPlayer = pImpersonator && (pImpersonator->entindex() == GetLocalPlayerIndex());

if ( gr->IsLocalPlayer( i ) || isImpersonatedByLocalPlayer )
{
Color color = bPlayerInDM ? COLOR_NEO_WHITE : gr->GetTeamColor(team);
color.SetColor(color.r(), color.g(), color.b(), 16);
Expand Down Expand Up @@ -740,17 +745,29 @@ void CNEOScoreBoard::GetPlayerScoreInfo(int playerIndex, KeyValues *kv)
kv->SetInt("playerIndex", playerIndex);
const int neoTeam = g_PR->GetTeam(playerIndex);
kv->SetInt("team", neoTeam);
const char *pClantag = g_PR->GetClanTag(playerIndex);
if (pClantag && pClantag[0] && (!cl_neo_streamermode.GetBool() || g_PR->IsLocalPlayer(playerIndex)))

C_NEO_Player *pPlayer = ToNEOPlayer(UTIL_PlayerByIndex(playerIndex));
C_NEO_Player *pImpersonator = pPlayer ? ToNEOPlayer(pPlayer->m_hSpectatorTakeoverPlayerImpersonatingMe.Get()) : nullptr;

if (pImpersonator)
{
char szClanTagWName[NEO_MAX_DISPLAYNAME];
V_sprintf_safe(szClanTagWName, "[%s] %s", pClantag, g_PR->GetPlayerName(playerIndex));
kv->SetString("name", szClanTagWName);
kv->SetString("name", pImpersonator->GetPlayerNameWithTakeoverContext(pImpersonator->entindex()));
}
else
{
kv->SetString("name", g_PR->GetPlayerName(playerIndex));
const char *pClantag = g_PR->GetClanTag(playerIndex);
if (pClantag && pClantag[0] && (!cl_neo_streamermode.GetBool() || g_PR->IsLocalPlayer(playerIndex)))
{
char szClanTagWName[NEO_MAX_DISPLAYNAME];
V_sprintf_safe(szClanTagWName, "[%s] %s", pClantag, g_PR->GetPlayerName(playerIndex));
kv->SetString("name", szClanTagWName);
}
else
{
kv->SetString("name", g_PR->GetPlayerName(playerIndex));
}
}

kv->SetInt("deaths", g_PR->GetDeaths( playerIndex ));

const int xp = g_PR->GetXP(playerIndex);
Expand All @@ -764,13 +781,32 @@ void CNEOScoreBoard::GetPlayerScoreInfo(int playerIndex, KeyValues *kv)
((playerNeoTeam == TEAM_JINRAI || playerNeoTeam == TEAM_NSF) && (neoTeam != playerNeoTeam)) :
(!g_PR->IsLocalPlayer(playerIndex));

bool isImpersonated = pImpersonator != nullptr;
bool isImpersonating = pPlayer && pPlayer->m_hSpectatorTakeoverPlayerTarget.Get() != nullptr;
int statusIcon = -1;
if (neoTeam == TEAM_JINRAI || neoTeam == TEAM_NSF)
{
statusIcon = ((!SHOW_ENEMY_STATUS && oppositeTeam) || g_PR->IsAlive(playerIndex)) ? -1 : m_iDeadIcon;

if (isImpersonating)
{
// Former spectators impersonating other players are (un)dead
statusIcon = m_iDeadIcon;
}
else if (isImpersonated)
{
// Do not show death icon for players being impersonated
statusIcon = -1;
}
}
kv->SetInt("status", statusIcon);
kv->SetString("class", oppositeTeam ? "" : GetNeoClassName(neoClassIdx));

int classToDisplay = neoClassIdx;
if (isImpersonating)
{
classToDisplay = pPlayer->m_iClassBeforeTakeover;
}
kv->SetString("class", oppositeTeam ? "" : GetNeoClassName(classToDisplay));

if ( g_PR->IsFakePlayer( playerIndex ) )
{
Expand Down
Loading