From b2deb884817a22009a6164ee26b736885b903dea Mon Sep 17 00:00:00 2001 From: wootguy Date: Sun, 6 Oct 2024 17:14:09 -0700 Subject: [PATCH] more status bar + killfeed fixes - npc name switching to red-colored player name when killed - status bar disappearing too fast - long killer names not clipping properly for assists (hiding "+X players" or other player's name) - player name replaced with an npc name in scoreboard if attacking an npc when a game_end was triggered also gave explosive breakables/pushables a more descriptive default name --- dlls/CBasePlayer.cpp | 220 ++++++++++++++++++----------------- dlls/func/CBreakable.cpp | 7 ++ dlls/func/CBreakable.h | 2 +- dlls/func/CPushable.cpp | 9 +- dlls/multiplay_gamerules.cpp | 35 ++++-- 5 files changed, 155 insertions(+), 118 deletions(-) diff --git a/dlls/CBasePlayer.cpp b/dlls/CBasePlayer.cpp index 0e4b6574..13878e20 100644 --- a/dlls/CBasePlayer.cpp +++ b/dlls/CBasePlayer.cpp @@ -1997,144 +1997,148 @@ void CBasePlayer::UpdateStatusBar() fakePlayerInfo.name = "\\no name\\"; std::string name; + bool lookingAtStatusEnt = false; - if (tr.flFraction != 1.0) + if (tr.flFraction != 1.0 && !FNullEnt( tr.pHit ) ) { - if ( !FNullEnt( tr.pHit ) ) - { - CBaseEntity *pEntity = CBaseEntity::Instance( tr.pHit ); + CBaseEntity *pEntity = CBaseEntity::Instance( tr.pHit ); - bool ignoreMonster = FClassnameIs(pEntity->pev, "monster_furniture"); + bool ignoreMonster = FClassnameIs(pEntity->pev, "monster_furniture"); - if (pEntity->Classify() == CLASS_PLAYER ) - { - newSBarState[ SBAR_ID_TARGETNAME ] = ENTINDEX( pEntity->edict() ); - strcpy_safe( sbuf1, "1 %p1", SBAR_STRING_SIZE ); - strcpy_safe( sbuf0, "2 Health: %i2\n3 Armor: %i3", SBAR_STRING_SIZE); + if (pEntity->Classify() == CLASS_PLAYER ) + { + newSBarState[ SBAR_ID_TARGETNAME ] = ENTINDEX( pEntity->edict() ); + strcpy_safe( sbuf1, "1 %p1", SBAR_STRING_SIZE ); + strcpy_safe( sbuf0, "2 Health: %i2\n3 Armor: %i3", SBAR_STRING_SIZE); - newSBarState[ SBAR_ID_TARGETHEALTH ] = pEntity->pev->health; - newSBarState[ SBAR_ID_TARGETARMOR ] = pEntity->pev->armorvalue; + newSBarState[ SBAR_ID_TARGETHEALTH ] = pEntity->pev->health; + newSBarState[ SBAR_ID_TARGETARMOR ] = pEntity->pev->armorvalue; - m_flStatusBarDisappearDelay = gpGlobals->time + 1.0; - } - else if (pEntity->IsMonster() && pEntity->IsAlive() && !ignoreMonster) { - name = replaceString(pEntity->DisplayName(), "\n", " "); - int hp = roundf(pEntity->pev->health); + m_flStatusBarDisappearDelay = gpGlobals->time + 1.0; + lookingAtStatusEnt = true; + } + else if (pEntity->IsMonster() && pEntity->IsAlive() && !ignoreMonster) { + name = replaceString(pEntity->DisplayName(), "\n", " "); + int hp = roundf(pEntity->pev->health); - int irel = IRelationship(pEntity); + int irel = IRelationship(pEntity); - fakePlayerInfo.enabled = true; - fakePlayerInfo.color = NEUTRAL_TEAM_COLOR; - fakePlayerInfo.name = name.c_str(); + fakePlayerInfo.enabled = true; + fakePlayerInfo.color = NEUTRAL_TEAM_COLOR; + fakePlayerInfo.name = name.c_str(); - if (irel == R_AL) { - fakePlayerInfo.color = FRIEND_TEAM_COLOR; - } - else if (irel == R_DL || irel == R_HT || irel == R_NM) { - fakePlayerInfo.color = ENEMY_TEAM_COLOR; - } - - std::string desc = ""; - if (name.size() > 32) { - // player names can only be 32 chars long - desc = name.substr(31).c_str(); - } - - strcpy_safe(sbuf1, UTIL_VarArgs("1 %%p1%s", desc.c_str()), SBAR_STRING_SIZE); + if (irel == R_AL) { + fakePlayerInfo.color = FRIEND_TEAM_COLOR; + } + else if (irel == R_DL || irel == R_HT || irel == R_NM) { + fakePlayerInfo.color = ENEMY_TEAM_COLOR; + } - if ((pEntity->pev->flags & FL_GODMODE) || (pEntity->pev->takedamage == DAMAGE_NO) || pEntity->pev->health > 2147483647) { - strcpy_safe(sbuf0, "2 Health: Invincible", SBAR_STRING_SIZE); - hp = 1; // client won't show health text if this is an insane value - } - else if (hp == 0) { - strcpy_safe(sbuf0, "2 Health: 0", SBAR_STRING_SIZE); - hp = 1; // client won't show health text if this is 0 - } - else { - strcpy_safe(sbuf0, UTIL_VarArgs("2 Health: %d", hp), SBAR_STRING_SIZE); - } + std::string desc = ""; + if (name.size() > 32) { + // player names can only be 32 chars long + desc = name.substr(31).c_str(); + } - newSBarState[SBAR_ID_TARGETNAME] = entindex(); - newSBarState[SBAR_ID_TARGETHEALTH] = hp; + strcpy_safe(sbuf1, UTIL_VarArgs("1 %%p1%s", desc.c_str()), SBAR_STRING_SIZE); - m_flStatusBarDisappearDelay = gpGlobals->time + 1.0; + if ((pEntity->pev->flags & FL_GODMODE) || (pEntity->pev->takedamage == DAMAGE_NO) || pEntity->pev->health > 2147483647) { + strcpy_safe(sbuf0, "2 Health: Invincible", SBAR_STRING_SIZE); + hp = 1; // client won't show health text if this is an insane value + } + else if (hp == 0) { + strcpy_safe(sbuf0, "2 Health: 0", SBAR_STRING_SIZE); + hp = 1; // client won't show health text if this is 0 + } + else { + strcpy_safe(sbuf0, UTIL_VarArgs("2 Health: %d", hp), SBAR_STRING_SIZE); } - else if (pEntity->IsBreakable() && !(pEntity->pev->spawnflags & SF_BREAK_TRIGGER_ONLY)) { - - name = replaceString(pEntity->DisplayName(), "\n", " "); - int hp = roundf(pEntity->pev->health); - int irel = IRelationship(pEntity); - const char* hint = ""; - if (irel == R_AL) { - hint = " (wrench repairs)"; - } - else if (pEntity->pev->spawnflags & SF_BREAK_EXPLOSIVES_ONLY) { - hint = " (explosives only)"; - } - else if (pEntity->pev->spawnflags & SF_BREAK_INSTANT) { - CBreakable* breakable = (CBreakable*)pEntity; + newSBarState[SBAR_ID_TARGETNAME] = entindex(); + newSBarState[SBAR_ID_TARGETHEALTH] = hp; - if (breakable->m_instantBreakWeapon == BREAK_INSTANT_WRENCH) { - hint = " (use wrench)"; - } - else { - hint = " (use crowbar)"; - } - } + m_flStatusBarDisappearDelay = gpGlobals->time + 1.0; + lookingAtStatusEnt = true; + } + else if (pEntity->IsBreakable() && !(pEntity->pev->spawnflags & SF_BREAK_TRIGGER_ONLY)) { - if (irel == R_AL) { - // use fake player info - fakePlayerInfo.enabled = true; - fakePlayerInfo.color = FRIEND_TEAM_COLOR; - fakePlayerInfo.name = name.c_str(); + name = replaceString(pEntity->DisplayName(), "\n", " "); + int hp = roundf(pEntity->pev->health); + int irel = IRelationship(pEntity); - std::string desc = ""; - if (name.size() > 32) { - // player names can only be 32 chars long - desc = name.substr(31).c_str(); - } + const char* hint = ""; + if (irel == R_AL) { + hint = " (wrench repairs)"; + } + else if (pEntity->pev->spawnflags & SF_BREAK_EXPLOSIVES_ONLY) { + hint = " (explosives only)"; + } + else if (pEntity->pev->spawnflags & SF_BREAK_INSTANT) { + CBreakable* breakable = (CBreakable*)pEntity; - newSBarState[SBAR_ID_TARGETNAME] = entindex(); - strcpy_safe(sbuf1, UTIL_VarArgs("1 %%p1%s", desc.c_str()), SBAR_STRING_SIZE); + if (breakable->m_instantBreakWeapon == BREAK_INSTANT_WRENCH) { + hint = " (use wrench)"; } else { - strcpy_safe(sbuf1, UTIL_VarArgs("1 %s%s", name.c_str(), hint), SBAR_STRING_SIZE); - newSBarState[SBAR_ID_TARGETNAME] = ENTINDEX(pEntity->edict()); + hint = " (use crowbar)"; } - - strcpy_safe(sbuf0, UTIL_VarArgs("2 Health: %d", hp), SBAR_STRING_SIZE); - newSBarState[SBAR_ID_TARGETHEALTH] = hp; - - m_flStatusBarDisappearDelay = gpGlobals->time + 1.0; } - else if (FClassnameIs(pEntity->pev, "func_pushable")) { - name = replaceString(pEntity->DisplayName(), "\n", " "); + if (irel == R_AL) { + // use fake player info + fakePlayerInfo.enabled = true; + fakePlayerInfo.color = FRIEND_TEAM_COLOR; + fakePlayerInfo.name = name.c_str(); - const char* hint = ""; - if (pEntity->pev->spawnflags & SF_PUSH_LIFTABLE) { - strcpy_safe(sbuf0, "2 Press USE key to lift", SBAR_STRING_SIZE); - } - else { - strcpy_safe(sbuf0, "2 Cannot lift", SBAR_STRING_SIZE); + std::string desc = ""; + if (name.size() > 32) { + // player names can only be 32 chars long + desc = name.substr(31).c_str(); } + newSBarState[SBAR_ID_TARGETNAME] = entindex(); + strcpy_safe(sbuf1, UTIL_VarArgs("1 %%p1%s", desc.c_str()), SBAR_STRING_SIZE); + } + else { strcpy_safe(sbuf1, UTIL_VarArgs("1 %s%s", name.c_str(), hint), SBAR_STRING_SIZE); - newSBarState[SBAR_ID_TARGETNAME] = ENTINDEX(pEntity->edict()); - newSBarState[SBAR_ID_TARGETHEALTH] = 1; - - m_flStatusBarDisappearDelay = gpGlobals->time + 1.0; } + + strcpy_safe(sbuf0, UTIL_VarArgs("2 Health: %d", hp), SBAR_STRING_SIZE); + newSBarState[SBAR_ID_TARGETHEALTH] = hp; + + m_flStatusBarDisappearDelay = gpGlobals->time + 1.0; + lookingAtStatusEnt = true; } - else if ( m_flStatusBarDisappearDelay > gpGlobals->time ) - { - // hold the values for a short amount of time after viewing the object - newSBarState[ SBAR_ID_TARGETNAME ] = m_izSBarState[ SBAR_ID_TARGETNAME ]; - newSBarState[ SBAR_ID_TARGETHEALTH ] = m_izSBarState[ SBAR_ID_TARGETHEALTH ]; - newSBarState[ SBAR_ID_TARGETARMOR ] = m_izSBarState[ SBAR_ID_TARGETARMOR ]; + else if (FClassnameIs(pEntity->pev, "func_pushable")) { + + name = replaceString(pEntity->DisplayName(), "\n", " "); + + const char* hint = ""; + if (pEntity->pev->spawnflags & SF_PUSH_LIFTABLE) { + strcpy_safe(sbuf0, "2 Press USE key to lift", SBAR_STRING_SIZE); + } + else { + strcpy_safe(sbuf0, "2 Cannot lift", SBAR_STRING_SIZE); + } + + strcpy_safe(sbuf1, UTIL_VarArgs("1 %s%s", name.c_str(), hint), SBAR_STRING_SIZE); + + newSBarState[SBAR_ID_TARGETNAME] = ENTINDEX(pEntity->edict()); + newSBarState[SBAR_ID_TARGETHEALTH] = 1; + + m_flStatusBarDisappearDelay = gpGlobals->time + 1.0; + lookingAtStatusEnt = true; } + + } + + if ( !lookingAtStatusEnt && m_flStatusBarDisappearDelay > gpGlobals->time ) + { + // hold the values for a short amount of time after viewing the object + newSBarState[ SBAR_ID_TARGETNAME ] = m_izSBarState[ SBAR_ID_TARGETNAME ]; + newSBarState[ SBAR_ID_TARGETHEALTH ] = m_izSBarState[ SBAR_ID_TARGETHEALTH ]; + newSBarState[ SBAR_ID_TARGETARMOR ] = m_izSBarState[ SBAR_ID_TARGETARMOR ]; } BOOL bForceResend = FALSE; @@ -2158,7 +2162,7 @@ void CBasePlayer::UpdateStatusBar() tempNameActive++; } - bool statusChanged = false; + bool statusChanged = bForceResend; for (int i = 1; i < SBAR_END; i++) { if (newSBarState[i] != m_izSBarState[i]) { statusChanged = true; diff --git a/dlls/func/CBreakable.cpp b/dlls/func/CBreakable.cpp index b34a1e17..69c78215 100644 --- a/dlls/func/CBreakable.cpp +++ b/dlls/func/CBreakable.cpp @@ -426,6 +426,13 @@ void CBreakable::DamageSound(void) EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, rgpsz[RANDOM_LONG(0, i - 1)], fvol, ATTN_NORM, 0, pitch); } +const char* CBreakable::DisplayName() { + if (m_displayName) { + return STRING(m_displayName); + } + return Explodable() ? "Explosives" : "Breakable"; +} + void CBreakable::BreakTouch(CBaseEntity* pOther) { float flDamage; diff --git a/dlls/func/CBreakable.h b/dlls/func/CBreakable.h index 3f21e79a..f655f4dd 100644 --- a/dlls/func/CBreakable.h +++ b/dlls/func/CBreakable.h @@ -18,7 +18,7 @@ class CBreakable : public CBaseDelay void EXPORT BreakTouch(CBaseEntity* pOther); void Use(CBaseEntity* pActivator, CBaseEntity* pCaller, USE_TYPE useType, float value); void DamageSound(void); - const char* DisplayName() { return m_displayName ? STRING(m_displayName) : "Breakable"; } + const char* DisplayName(); virtual Vector GetTargetOrigin() { return Center(); } // breakables use an overridden takedamage diff --git a/dlls/func/CPushable.cpp b/dlls/func/CPushable.cpp index dff4250c..86c1960b 100644 --- a/dlls/func/CPushable.cpp +++ b/dlls/func/CPushable.cpp @@ -38,7 +38,7 @@ class CPushable : public CBreakable // virtual void SetActivator( CBaseEntity *pActivator ) { m_pPusher = pActivator; } BOOL IsBreakable() { return pev->spawnflags & SF_PUSH_BREAKABLE; } - const char* DisplayName() { return m_displayName ? STRING(m_displayName) : "Pushable"; } + const char* DisplayName(); virtual int ObjectCaps(void) { return (CBaseEntity::ObjectCaps() & ~FCAP_ACROSS_TRANSITION) | FCAP_CONTINUOUS_USE | FCAP_ONOFF_USE; } virtual int Save(CSave& save); @@ -361,6 +361,13 @@ void CPushable::PostMove(bool clampSpeed) { } } +const char* CPushable::DisplayName() { + if (m_displayName) { + return STRING(m_displayName); + } + return Explodable() ? "Pushable Explosives" : "Pushable"; +} + void CPushable::Lift() { CBasePlayer* plr = (CBasePlayer*)m_hLifter.GetEntity(); diff --git a/dlls/multiplay_gamerules.cpp b/dlls/multiplay_gamerules.cpp index cf8c5611..b053d1c3 100644 --- a/dlls/multiplay_gamerules.cpp +++ b/dlls/multiplay_gamerules.cpp @@ -783,9 +783,6 @@ void CHalfLifeMultiplay::DeathNotice( CBaseMonster *pVictim, entvars_t *pKiller, killerName = "Mortar"; } else if (pVictim->m_lastDamageType & DMG_BLAST) { - if (Killer->IsBreakable()) { - killerName = "Explosives"; - } //killerName = "Explosion"; // entity name should be better } @@ -839,12 +836,25 @@ void CHalfLifeMultiplay::DeathNotice( CBaseMonster *pVictim, entvars_t *pKiller, if (attackerCount > 1 && Killer->IsPlayer() && otherAttacker) { CBasePlayer* plr = (CBasePlayer*)Killer; originalKillerName = plr->DisplayName(); - + + static char killerName[40]; // max name length is 32 chars + snprintf(killerName, 40, "%s", Killer->DisplayName()); + killerName[39] = 0; + if (attackerCount == 2) { - plr->Rename(UTIL_VarArgs("%s + %s", Killer->DisplayName(), otherAttacker), true); + int killerNameLen = strlen(killerName); + int assistNameLen = strlen(otherAttacker); + if (killerNameLen > 14 && (killerNameLen + assistNameLen) > 31) { + int cutoff = V_max(14, 31 - (assistNameLen + 3)); + killerName[cutoff] = '\0'; + } + + plr->Rename(UTIL_VarArgs("%s + %s", killerName, otherAttacker), true); } else { - plr->Rename(UTIL_VarArgs("%s + %d players", Killer->DisplayName(), attackerCount-1), true); + killerName[19] = '\0'; // leave room for the player count + + plr->Rename(UTIL_VarArgs("%s + %d players", killerName, attackerCount-1), true); } } @@ -965,8 +975,7 @@ void CHalfLifeMultiplay::DeathNotice( CBaseMonster *pVictim, entvars_t *pKiller, if (Killer->IsPlayer()) { CBasePlayer* plr = (CBasePlayer*)Killer; if (plr->tempNameActive && plr != hackedPlayer1 && plr != hackedPlayer2) { - if (!originalKillerName) - plr->Rename(plr->m_tempName, false, MSG_ONE, plr->edict()); + plr->Rename(plr->m_tempName, false, MSG_ONE, plr->edict()); plr->UpdateTeamInfo(plr->m_tempTeam, MSG_ONE, plr->edict()); } } @@ -1293,6 +1302,16 @@ void CHalfLifeMultiplay :: GoToIntermission( void ) if ( g_fGameOver ) return; // intermission has already been triggered, so ignore. + // undo status bar name changes so scoreboard looks correct + for (int i = 1; i <= gpGlobals->maxClients; i++) { + CBasePlayer* pEnt = UTIL_PlayerByIndex(i); + + if (pEnt && pEnt->tempNameActive) { + pEnt->Rename(pEnt->DisplayName(), false, MSG_ONE, pEnt->edict()); + pEnt->UpdateTeamInfo(-1, MSG_ONE, pEnt->edict()); + } + } + MESSAGE_BEGIN(MSG_ALL, SVC_INTERMISSION); MESSAGE_END();