From 29caf0d4f799f4be83f8473eb8704d5bdfb5deba Mon Sep 17 00:00:00 2001 From: ywgATustcbbs Date: Fri, 4 Jul 2025 17:18:32 +0800 Subject: [PATCH 01/13] Add trace for a marine (Pure client effects). This will help new players to find where a marine goes. You can mark a player in lobby as your tracing target. This is still a WIP --- src/game/client/swarm/c_asw_marine.cpp | 34 +++++++- src/game/client/swarm/c_asw_marine.h | 16 ++++ src/game/client/swarm/vgui/asw_hud_emotes.cpp | 86 +++++++++++++++++++ 3 files changed, 135 insertions(+), 1 deletion(-) diff --git a/src/game/client/swarm/c_asw_marine.cpp b/src/game/client/swarm/c_asw_marine.cpp index 96f9278bb..abe575418 100644 --- a/src/game/client/swarm/c_asw_marine.cpp +++ b/src/game/client/swarm/c_asw_marine.cpp @@ -49,6 +49,10 @@ #include #include "stats_report.h" #include "asw_weapon_night_vision.h" +#ifdef CLIENT_DLL +#include +#include +#endif // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" @@ -103,6 +107,11 @@ extern ConVar rd_team_color_ally; extern ConVar rd_team_color_enemy; extern float g_fMarinePoisonDuration; +#ifdef CLIENT_DLL +std::vector g_bShouldTracePlayer = std::vector(MAX_PLAYERS, true); // whether we have a trace position for this player +const float TRACE_FADE_TIME = 60.0f; // how long to keep the trace positions for +#endif + #define FLASHLIGHT_DISTANCE 1000 #define ASW_PROJECTOR_FLASHLIGHT 1 @@ -859,6 +868,8 @@ void C_ASW_Marine::ClientThink() TickEmotes( deltatime ); TickRedName( deltatime ); + TickTracePlayerMovement(deltatime); + UpdateFireEmitters(); UpdateJumpJetEffects(); UpdateElectrifiedArmor(); @@ -973,7 +984,28 @@ void C_ASW_Marine::DoWaterRipples() DispatchEffect( "aswwatersplash", data ); //static Vector s_MarineWaterSplashColor( 0.5, 0.5, 0.5 ); //FX_ASWWaterRipple(data.m_vOrigin, 1.0f, &s_MarineWaterSplashColor, 1.5f, 0.1f); - } + } +} + +void C_ASW_Marine::TickTracePlayerMovement(float d) +{ + // insert current time marine position + struct TracePlayerMovement_t movement; + //get current time + movement.m_flTraceTime = TRACE_FADE_TIME; + movement.m_vecPosition = GetAbsOrigin() + Vector(0, 0, 5); + m_lstTracePlayerMovementList.push_back(movement); + + // update the trace time for each movement trace + for (auto iter = m_lstTracePlayerMovementList.begin(); iter != m_lstTracePlayerMovementList.end(); ++iter) + { + iter->m_flTraceTime -= d; + } + + // remove any traces that have expired + m_lstTracePlayerMovementList.remove_if([](const auto& item) { + return item.m_flTraceTime <= 0; + }); } void C_ASW_Marine::CreateWeaponEmitters() diff --git a/src/game/client/swarm/c_asw_marine.h b/src/game/client/swarm/c_asw_marine.h index 8ba1f94d8..2fa85e939 100644 --- a/src/game/client/swarm/c_asw_marine.h +++ b/src/game/client/swarm/c_asw_marine.h @@ -16,6 +16,18 @@ #include "asw_deathmatch_mode.h" #include "dlight.h" #include "rd_inventory_shared.h" +#ifdef CLIENT_DLL +#include +#include + +struct TracePlayerMovement_t +{ + float m_flTraceTime; + Vector m_vecPosition; +}; +#endif + + class C_ASW_Player; class C_ASW_Marine_Resource; @@ -293,6 +305,10 @@ class C_ASW_Marine : public C_ASW_VPhysics_NPC, public IASWPlayerAnimStateHelper // emote system void TickEmotes( float d ); bool TickEmote( float d, int bit, float &fEmoteTime ); +#ifdef CLIENT_DLL + void TickTracePlayerMovement(float d); + std::list m_lstTracePlayerMovementList = std::list(); // list of positions and times for the last few frames +#endif CNetworkVar( int, m_iEmote ); int m_iClientEmote; float m_fEmoteMedicTime; diff --git a/src/game/client/swarm/vgui/asw_hud_emotes.cpp b/src/game/client/swarm/vgui/asw_hud_emotes.cpp index 81b03726a..461a55ac3 100644 --- a/src/game/client/swarm/vgui/asw_hud_emotes.cpp +++ b/src/game/client/swarm/vgui/asw_hud_emotes.cpp @@ -30,6 +30,10 @@ #include "engine/IVDebugOverlay.h" #include "vguimatsurface/imatsystemsurface.h" #include "tier1/fmtstr.h" +#ifdef CLIENT_DLL +#include +#include +#endif // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" @@ -38,6 +42,11 @@ using namespace vgui; extern ConVar asw_draw_hud; +#ifdef CLIENT_DLL +extern std::vector g_bShouldTracePlayer; +extern const float TRACE_FADE_TIME; +#endif + //----------------------------------------------------------------------------- // Purpose: Shows the marines emote graphics //----------------------------------------------------------------------------- @@ -56,6 +65,9 @@ class CASWHudEmotes : public CASW_HudElement, public vgui::Panel virtual void PaintEmote( C_BaseEntity *pEnt, float fTime, int iTexture, float fScale = 1.0f ); virtual bool ShouldDraw( void ) { return asw_draw_hud.GetBool() && CASW_HudElement::ShouldDraw(); } + virtual void PaintTraces(); + virtual void PaintTracesFor(C_ASW_Marine* pMarine); + CPanelAnimationVarAliasType( int, m_nMedicTexture, "MedicEmoteTexture", "vgui/swarm/Emotes/EmoteMedic", "textureid" ); CPanelAnimationVarAliasType( int, m_nAmmoTexture, "AmmoEmoteTexture", "vgui/swarm/Emotes/EmoteAmmo", "textureid" ); CPanelAnimationVarAliasType( int, m_nSmileTexture, "SmileEmoteTexture", "vgui/swarm/Emotes/EmoteSmile", "textureid" ); @@ -100,6 +112,7 @@ void CASWHudEmotes::Paint() VPROF_BUDGET( "CASWHudEmotes::Paint", VPROF_BUDGETGROUP_ASW_CLIENT ); BaseClass::Paint(); PaintEmotes(); + PaintTraces(); } void CASWHudEmotes::PaintEmotes() @@ -276,3 +289,76 @@ void CASWHudEmotes::PaintEmote( C_BaseEntity *pEnt, float fTime, int iTexture, f } } } + +void CASWHudEmotes::PaintTraces() +{ + C_ASW_Game_Resource* pGameResource = ASWGameResource(); + if (!pGameResource) + return; + + for (int i = 0; i < pGameResource->GetMaxMarineResources(); i++) + { + C_ASW_Marine_Resource* pMR = pGameResource->GetMarineResource(i); + if (!pMR) + continue; + + C_ASW_Marine* marine = pMR->GetMarineEntity(); + if (!pMR->IsInhabited() || !marine || !g_bShouldTracePlayer[pMR->GetCommanderIndex()]) + continue; + + PaintTracesFor(marine); + } +} + +void CASWHudEmotes::PaintTracesFor(C_ASW_Marine* pMarine) +{ + for (auto iter = pMarine->m_lstTracePlayerMovementList.begin(); iter != pMarine->m_lstTracePlayerMovementList.end(); ++iter) + { + float fTime = (*iter).m_flTraceTime; + Vector vecPosition = (*iter).m_vecPosition; + + if (fTime <= 0) + { + continue; // no trace to draw + } + + // draw a circle at the position of the trace in world space + // and fade it out over time + float fAlpha = pow(((fTime / 3.0) - (int)(fTime / 3.0)),4); + fAlpha = clamp(fAlpha, 0.0f, 1.0f); + int iTexture = m_nSmileTexture; + + Vector screenPos; + // 将世界坐标转换为屏幕坐标 + if (!debugoverlay->ScreenPosition(vecPosition, screenPos)) + { + float xPos = screenPos[0]; + float yPos = screenPos[1]; + + if (iTexture != -1) + { + // 计算大小,随时间略微变化 + float fSize = 0.9f + 0.1f * fAlpha; + + // 应用屏幕高度比例和自定义缩放 + float fScale = (ScreenHeight() / 768.0f); + float HalfW = 16.0f * fScale * fSize; + float HalfH = 16.0f * fScale * fSize; + + // 设置颜色和纹理 + surface()->DrawSetColor(Color(255, 255, 255, fAlpha * 255.0f)); + surface()->DrawSetTexture(iTexture); + + // 绘制纹理多边形 + Vertex_t points[4] = + { + Vertex_t(Vector2D(xPos - HalfW, yPos - HalfH), Vector2D(0, 0)), + Vertex_t(Vector2D(xPos + HalfW, yPos - HalfH), Vector2D(1, 0)), + Vertex_t(Vector2D(xPos + HalfW, yPos + HalfH), Vector2D(1, 1)), + Vertex_t(Vector2D(xPos - HalfW, yPos + HalfH), Vector2D(0, 1)) + }; + surface()->DrawTexturedPolygon(4, points); + } + } + } +} \ No newline at end of file From c5d3fa30244f59d140e9aa9b99c9ea92bee4a7c2 Mon Sep 17 00:00:00 2001 From: ywgATustcbbs Date: Sun, 6 Jul 2025 06:09:53 +0800 Subject: [PATCH 02/13] Add trace buttons to lobby menu --- src/game/client/swarm/asw_briefing.cpp | 13 ++ src/game/client/swarm/asw_briefing.h | 1 + src/game/client/swarm/c_asw_marine.cpp | 2 +- src/game/client/swarm/ibriefing.h | 1 + src/game/client/swarm/vgui/nb_lobby_row.cpp | 163 ++++++++++++++++---- src/game/client/swarm/vgui/nb_lobby_row.h | 19 +-- src/game/shared/swarm/rd_lobby_utils.cpp | 38 +++++ 7 files changed, 198 insertions(+), 39 deletions(-) diff --git a/src/game/client/swarm/asw_briefing.cpp b/src/game/client/swarm/asw_briefing.cpp index d6c14e311..f4d035cc1 100644 --- a/src/game/client/swarm/asw_briefing.cpp +++ b/src/game/client/swarm/asw_briefing.cpp @@ -1083,3 +1083,16 @@ const CRD_ItemInstance &CASW_Briefing::GetEquippedWeapon( int nLobbySlot, int nW return instance; } + +int CASW_Briefing::GetPlayerIndex(int nLobbySlot) +{ + if (nLobbySlot < 0 || nLobbySlot >= NUM_BRIEFING_LOBBY_SLOTS || !IsLobbySlotOccupied(nLobbySlot)) + return -1; + + C_ASW_Player* pPlayer = m_LobbySlotMapping[nLobbySlot].m_hPlayer.Get(); + if (pPlayer) + { + return pPlayer->entindex(); + } + return -1; // not found, or not a player +} diff --git a/src/game/client/swarm/asw_briefing.h b/src/game/client/swarm/asw_briefing.h index ccf77dd4f..d7cc991af 100644 --- a/src/game/client/swarm/asw_briefing.h +++ b/src/game/client/swarm/asw_briefing.h @@ -79,6 +79,7 @@ class CASW_Briefing : public IBriefing int LobbySlotToMarineResourceIndex( int nLobbySlot ); void UpdateLobbySlotMapping(); + virtual int GetPlayerIndex(int nLobbySlot); int m_nLastLobbySlotMappingFrame; LobbySlotMapping_t m_LobbySlotMapping[ NUM_BRIEFING_LOBBY_SLOTS ]; diff --git a/src/game/client/swarm/c_asw_marine.cpp b/src/game/client/swarm/c_asw_marine.cpp index abe575418..963c54e95 100644 --- a/src/game/client/swarm/c_asw_marine.cpp +++ b/src/game/client/swarm/c_asw_marine.cpp @@ -108,7 +108,7 @@ extern ConVar rd_team_color_enemy; extern float g_fMarinePoisonDuration; #ifdef CLIENT_DLL -std::vector g_bShouldTracePlayer = std::vector(MAX_PLAYERS, true); // whether we have a trace position for this player +std::vector g_bShouldTracePlayer = std::vector(MAX_PLAYERS, false); // whether we have a trace position for this player const float TRACE_FADE_TIME = 60.0f; // how long to keep the trace positions for #endif diff --git a/src/game/client/swarm/ibriefing.h b/src/game/client/swarm/ibriefing.h index 359614e2b..3559cb0c8 100644 --- a/src/game/client/swarm/ibriefing.h +++ b/src/game/client/swarm/ibriefing.h @@ -71,6 +71,7 @@ abstract_class IBriefing virtual const IBriefing_ItemInstance &GetEquippedMedal( int nLobbySlot, int nMedalIndex ) = 0; virtual const IBriefing_ItemInstance &GetEquippedSuit( int nLobbySlot ) = 0; virtual const IBriefing_ItemInstance &GetEquippedWeapon( int nLobbySlot, int nWeaponSlot ) = 0; + virtual int GetPlayerIndex(int nLobbySlot) { return -1; }; }; #define NUM_BRIEFING_LOBBY_SLOTS ( ASW_MAX_MARINE_RESOURCES + MAX_PLAYERS - 1 ) // was 9, was 4 diff --git a/src/game/client/swarm/vgui/nb_lobby_row.cpp b/src/game/client/swarm/vgui/nb_lobby_row.cpp index d7940278b..d568a0511 100644 --- a/src/game/client/swarm/vgui/nb_lobby_row.cpp +++ b/src/game/client/swarm/vgui/nb_lobby_row.cpp @@ -20,11 +20,15 @@ #include "gameui/swarm/vdropdownmenu.h" #include "gameui/swarm/vhybridbutton.h" #include "rd_inventory_shared.h" +#include // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" extern ConVar rd_legacy_ui; +#ifdef CLIENT_DLL +extern std::vector g_bShouldTracePlayer; +#endif using namespace BaseModUI; @@ -98,10 +102,22 @@ CNB_Lobby_Row::CNB_Lobby_Row( vgui::Panel *parent, const char *name ) : BaseClas m_pXPBar->m_flBorder = 1.5f; m_nLobbySlot = 0; + // Create the TraceMe button + m_pTraceMeButton = new CBitmapButton( this, "TraceMeButton", ""); + m_pTraceMeButton->AddActionSignalTarget( this ); + m_pTraceMeButton->SetCommand( "TraceMePressed" ); + + // Create and initialize TracePlayerButton + m_pTracePlayerButton = new CBitmapButton( this, "TracePlayerButton", "" ); + m_pTracePlayerButton->AddActionSignalTarget( this ); + m_pTracePlayerButton->SetCommand( "TracePlayerPressed" ); + GetControllerFocus()->AddToFocusList( m_pPortraitButton ); GetControllerFocus()->AddToFocusList( m_pWeaponButton0 ); GetControllerFocus()->AddToFocusList( m_pWeaponButton1 ); GetControllerFocus()->AddToFocusList( m_pWeaponButton2 ); + GetControllerFocus()->AddToFocusList( m_pTraceMeButton ); + GetControllerFocus()->AddToFocusList( m_pTracePlayerButton ); } CNB_Lobby_Row::~CNB_Lobby_Row() @@ -110,6 +126,8 @@ CNB_Lobby_Row::~CNB_Lobby_Row() GetControllerFocus()->RemoveFromFocusList( m_pWeaponButton0 ); GetControllerFocus()->RemoveFromFocusList( m_pWeaponButton1 ); GetControllerFocus()->RemoveFromFocusList( m_pWeaponButton2 ); + GetControllerFocus()->RemoveFromFocusList( m_pTraceMeButton ); + GetControllerFocus()->RemoveFromFocusList( m_pTracePlayerButton ); } void CNB_Lobby_Row::ApplySchemeSettings( vgui::IScheme *pScheme ) @@ -140,6 +158,8 @@ void CNB_Lobby_Row::OnThink() UpdateDetails(); UpdateChangingSlot(); + UpdateTraceMeButton(); // Update the TraceMe button state + UpdateTracePlayerButton(); // Update the TracePlayer button state } void CNB_Lobby_Row::UpdateDetails() @@ -426,6 +446,16 @@ void CNB_Lobby_Row::UpdateDetails() pSilhouette->SetVisible( false ); } } + + // Set the images for the TraceMe button + const char* szTraceMeButtonEnabled = "vgui/swarm/Emotes/EmoteSmile"; + const char* szTraceMeButtonDisabled = "vgui/swarm/Emotes/EmoteStop"; + const char* szTraceMeButtonPressed = "vgui/swarm/Emotes/EmoteAmmo"; + const char* szTraceMeButtonMouseOver = "vgui/swarm/Emotes/EmoteMedic"; + m_pTraceMeButton->SetImage(CBitmapButton::BUTTON_ENABLED, szTraceMeButtonEnabled, lightblue); + m_pTraceMeButton->SetImage(CBitmapButton::BUTTON_DISABLED, szTraceMeButtonDisabled, lightblue); + m_pTraceMeButton->SetImage(CBitmapButton::BUTTON_PRESSED, szTraceMeButtonPressed, white); + m_pTraceMeButton->SetImage(CBitmapButton::BUTTON_ENABLED_MOUSE_OVER, szTraceMeButtonMouseOver, white); } void CNB_Lobby_Row::CheckTooltip( CNB_Lobby_Tooltip *pTooltip ) @@ -465,61 +495,69 @@ void CNB_Lobby_Row::CheckTooltip( CNB_Lobby_Tooltip *pTooltip ) extern ConVar developer; -void CNB_Lobby_Row::OnCommand( const char *command ) +void CNB_Lobby_Row::OnCommand(const char* command) { - CNB_Main_Panel *pMainPanel = GetMainPanel(); - if ( !pMainPanel ) + CNB_Main_Panel* pMainPanel = GetMainPanel(); + if (!pMainPanel) return; - if ( !Q_stricmp( command, "ChangeMarine" ) ) + if (!Q_stricmp(command, "ChangeMarine")) { - pMainPanel->ChangeMarine( m_nLobbySlot ); + pMainPanel->ChangeMarine(m_nLobbySlot); } - else if ( !Q_stricmp( command, "ChangeWeapon0" ) ) + else if (!Q_stricmp(command, "ChangeWeapon0")) { - pMainPanel->ChangeWeapon( m_nLobbySlot, 0 ); - } - else if ( !Q_stricmp( command, "ChangeWeapon1" ) ) + pMainPanel->ChangeWeapon(m_nLobbySlot, 0); + } + else if (!Q_stricmp(command, "ChangeWeapon1")) { - pMainPanel->ChangeWeapon( m_nLobbySlot, 1 ); + pMainPanel->ChangeWeapon(m_nLobbySlot, 1); } - else if ( !Q_stricmp( command, "ChangeWeapon2" ) ) + else if (!Q_stricmp(command, "ChangeWeapon2")) { - pMainPanel->ChangeWeapon( m_nLobbySlot, 2 ); + pMainPanel->ChangeWeapon(m_nLobbySlot, 2); } - else if ( !Q_stricmp( command, "PlayerFlyout" ) ) + else if (!Q_stricmp(command, "PlayerFlyout")) { - if ( !Briefing()->IsLobbySlotBot( m_nLobbySlot ) && Briefing()->GetCommanderSteamID( m_nLobbySlot ).IsValid() ) + if (!Briefing()->IsLobbySlotBot(m_nLobbySlot) && Briefing()->GetCommanderSteamID(m_nLobbySlot).IsValid()) { OpenPlayerFlyout(); } } - else if ( !Q_stricmp( command, "#L4D360UI_SendMessage" ) ) + else if (!Q_stricmp(command, "#L4D360UI_SendMessage")) { - BaseModUI::CUIGameData::Get()->ExecuteOverlayCommand( "chat", pMainPanel->m_FlyoutSteamID ); + BaseModUI::CUIGameData::Get()->ExecuteOverlayCommand("chat", pMainPanel->m_FlyoutSteamID); } - else if ( !Q_stricmp( command, "#L4D360UI_ViewSteamID" ) ) + else if (!Q_stricmp(command, "#L4D360UI_ViewSteamID")) { - BaseModUI::CUIGameData::Get()->ExecuteOverlayCommand( "steamid", pMainPanel->m_FlyoutSteamID ); + BaseModUI::CUIGameData::Get()->ExecuteOverlayCommand("steamid", pMainPanel->m_FlyoutSteamID); } - else if ( !Q_stricmp( command, "#L4D360UI_ViewSteamStats" ) ) + else if (!Q_stricmp(command, "#L4D360UI_ViewSteamStats")) { #if !defined( _X360 ) && !defined( NO_STEAM ) - if ( SteamUser() ) + if (SteamUser()) { - if ( developer.GetBool() ) + if (developer.GetBool()) { - Msg( "Local player SteamID = %I64u\n", SteamUser()->GetSteamID().ConvertToUint64() ); - Msg( "Activating stats for SteamID = %I64u\n", Briefing()->GetCommanderSteamID( m_nLobbySlot ).ConvertToUint64() ); + Msg("Local player SteamID = %I64u\n", SteamUser()->GetSteamID().ConvertToUint64()); + Msg("Activating stats for SteamID = %I64u\n", Briefing()->GetCommanderSteamID(m_nLobbySlot).ConvertToUint64()); } char statsWeb[256]; - Q_snprintf( statsWeb, sizeof( statsWeb ), "https://stats.reactivedrop.com/profiles/%I64u?lang=%s&utm_source=briefing", - Briefing()->GetCommanderSteamID( m_nLobbySlot ).ConvertToUint64(), - SteamApps()->GetCurrentGameLanguage() ); - BaseModUI::CUIGameData::Get()->ExecuteOverlayUrl( statsWeb ); + Q_snprintf(statsWeb, sizeof(statsWeb), "https://stats.reactivedrop.com/profiles/%I64u?lang=%s&utm_source=briefing", + Briefing()->GetCommanderSteamID(m_nLobbySlot).ConvertToUint64(), + SteamApps()->GetCurrentGameLanguage()); + BaseModUI::CUIGameData::Get()->ExecuteOverlayUrl(statsWeb); } #endif } + else if (!Q_stricmp(command, "TraceMePressed")) + { + TraceMePressed(); + } + else if (!Q_stricmp(command, "TracePlayerPressed")) + { + TracePlayerPressed(); + } } void CNB_Lobby_Row::OpenPlayerFlyout() @@ -578,3 +616,74 @@ void CNB_Lobby_Row::UpdateChangingSlot() m_pChangingSlot[ 2 ]->SetVisible( nSlot == 3 ); m_pChangingSlot[ 3 ]->SetVisible( nSlot == 4 ); } + +void CNB_Lobby_Row::UpdateTraceMeButton() +{ + if (!m_pTraceMeButton) + return; + + // Check if the TraceMe button should be enabled or not + // It should be enabled if it's an online game, the slot is the local player's slot, the slot is not a bot, the slot is occupied, and the marine profile exists + if (!Briefing() + || Briefing()->IsOfflineGame() + || !Briefing()->IsLobbySlotLocal(m_nLobbySlot) + || Briefing()->IsLobbySlotBot(m_nLobbySlot) + || !Briefing()->IsLobbySlotOccupied(m_nLobbySlot) + || Briefing()->GetMarineProfile(m_nLobbySlot) == NULL) + { + m_pTraceMeButton->SetVisible(false); + return; + } + m_pTraceMeButton->SetVisible(true); +} + +void CNB_Lobby_Row::TraceMePressed() +{ + // Get the local player index + int localPlayerIndex = -1; + if (engine && engine->IsInGame()) + { + localPlayerIndex = engine->GetLocalPlayer(); + if (localPlayerIndex < 0 || localPlayerIndex >= gpGlobals->maxClients) + { + return; // Invalid player index + } + + char cmd[128]; + Q_snprintf(cmd, sizeof(cmd), "rd_lobby_suggest_trace_player %d", localPlayerIndex); + // Send a message in chat to all other players to suggest them to trace this player + engine->ClientCmd_Unrestricted(cmd); + } +} + +void CNB_Lobby_Row::UpdateTracePlayerButton() +{ + if (!m_pTracePlayerButton) + return; + + // In online games, show the button only for other players (not local player, not bot, and occupied slot) + if (!Briefing() + || Briefing()->IsOfflineGame() + || Briefing()->IsLobbySlotLocal(m_nLobbySlot) + || Briefing()->IsLobbySlotBot(m_nLobbySlot) + || !Briefing()->IsLobbySlotOccupied(m_nLobbySlot)) + { + m_pTracePlayerButton->SetVisible(false); + return; + } + + m_pTracePlayerButton->SetVisible(true); +} + +void CNB_Lobby_Row::TracePlayerPressed() +{ + int playerIndex = Briefing()->GetPlayerIndex(m_nLobbySlot); + if (playerIndex < 0 || playerIndex >= gpGlobals->maxClients) + { + Msg("Invalid player index for lobby slot %d\n", m_nLobbySlot); + return; // Invalid player index + } + // flip the trace state for this player + g_bShouldTracePlayer[playerIndex] = !g_bShouldTracePlayer[playerIndex]; + Msg("Trace player %d : %s\n", playerIndex, g_bShouldTracePlayer[playerIndex] ? "true" : "false"); +} diff --git a/src/game/client/swarm/vgui/nb_lobby_row.h b/src/game/client/swarm/vgui/nb_lobby_row.h index d17ea0995..b58a25728 100644 --- a/src/game/client/swarm/vgui/nb_lobby_row.h +++ b/src/game/client/swarm/vgui/nb_lobby_row.h @@ -43,6 +43,11 @@ class CNB_Lobby_Row : public vgui::EditablePanel virtual void CheckTooltip( CNB_Lobby_Tooltip *pTooltip ); void UpdateChangingSlot(); + + void UpdateTraceMeButton(); + void TraceMePressed(); + void UpdateTracePlayerButton(); + void TracePlayerPressed(); // == MANAGED_MEMBER_POINTERS_START: Do not edit by hand == vgui::ImagePanel *m_pBackground; @@ -79,16 +84,8 @@ class CNB_Lobby_Row : public vgui::EditablePanel SteamItemDef_t m_lastMedal[RD_STEAM_INVENTORY_NUM_MEDAL_SLOTS]; int m_nLobbySlot; + CBitmapButton *m_pTraceMeButton; + CBitmapButton* m_pTracePlayerButton; }; -#endif // _INCLUDED_NB_LOBBY_ROW_H - - - - - - - - - - +#endif // _INCLUDED_NB_LOBBY_ROW_H \ No newline at end of file diff --git a/src/game/shared/swarm/rd_lobby_utils.cpp b/src/game/shared/swarm/rd_lobby_utils.cpp index 5b5cd3692..f890d2a34 100644 --- a/src/game/shared/swarm/rd_lobby_utils.cpp +++ b/src/game/shared/swarm/rd_lobby_utils.cpp @@ -583,6 +583,44 @@ CON_COMMAND( rd_lobby_debug_filter_distance, "1: close, 2: default, 3: far, 4: w } } +CON_COMMAND(rd_lobby_suggest_trace_player, "notify server to send a trace player suggestion to all clients.") +{ + if (args.ArgC() < 2) + { + Msg("Usage: rd_lobby_suggest_trace_player \n"); + return; + } + + int iPlayerIndex = atoi(args[1]); + if (iPlayerIndex < 1 || iPlayerIndex > gpGlobals->maxClients) + { + Msg("Invalid playerIndex\n"); + return; + } + + CBasePlayer* pPlayer = UTIL_PlayerByIndex(iPlayerIndex); + if (!pPlayer) + { + Msg("Can't find a player with index <%d>.\n", iPlayerIndex); + return; + } + // Send the message to all players + for (int i = 1; i <= gpGlobals->maxClients; i++) + { + CBasePlayer* pRecipient = UTIL_PlayerByIndex(i); + if (!pRecipient) + continue; + if (pRecipient == pPlayer) + { + ClientPrint(pRecipient, HUD_PRINTTALK, "asw_trace_me_msg_to_self"); + } + else + { + ClientPrint(pRecipient, HUD_PRINTTALK, "asw_trace_me_msg_to_others", pPlayer->GetPlayerName()); + } + } +} + CReactiveDropServerListHelper::CReactiveDropServerListHelper( const char *szDebugName ) { m_pszDebugName = szDebugName; From 4aaf68a3144335090bbfbad51c7c020fceafd513 Mon Sep 17 00:00:00 2001 From: ywgATustcbbs Date: Sun, 6 Jul 2025 23:25:07 +0800 Subject: [PATCH 03/13] some layouts --- src/game/client/swarm/c_asw_marine.cpp | 1 + src/game/client/swarm/vgui/nb_lobby_row.cpp | 56 ++++++++++++++------- src/game/client/swarm/vgui/nb_lobby_row.h | 2 + 3 files changed, 42 insertions(+), 17 deletions(-) diff --git a/src/game/client/swarm/c_asw_marine.cpp b/src/game/client/swarm/c_asw_marine.cpp index 963c54e95..047ddbba6 100644 --- a/src/game/client/swarm/c_asw_marine.cpp +++ b/src/game/client/swarm/c_asw_marine.cpp @@ -110,6 +110,7 @@ extern float g_fMarinePoisonDuration; #ifdef CLIENT_DLL std::vector g_bShouldTracePlayer = std::vector(MAX_PLAYERS, false); // whether we have a trace position for this player const float TRACE_FADE_TIME = 60.0f; // how long to keep the trace positions for +ConVar cl_trace_player_max_targets("cl_trace_player_max_targets", "3", FCVAR_ARCHIVE | FCVAR_CLIENTDLL, "Maximum number of players to trace positions for in the client.", true, 1.0f, true, 7.0f); #endif #define FLASHLIGHT_DISTANCE 1000 diff --git a/src/game/client/swarm/vgui/nb_lobby_row.cpp b/src/game/client/swarm/vgui/nb_lobby_row.cpp index d568a0511..56e9ccff9 100644 --- a/src/game/client/swarm/vgui/nb_lobby_row.cpp +++ b/src/game/client/swarm/vgui/nb_lobby_row.cpp @@ -28,6 +28,7 @@ extern ConVar rd_legacy_ui; #ifdef CLIENT_DLL extern std::vector g_bShouldTracePlayer; +extern ConVar cl_trace_player_max_targets; #endif using namespace BaseModUI; @@ -102,15 +103,28 @@ CNB_Lobby_Row::CNB_Lobby_Row( vgui::Panel *parent, const char *name ) : BaseClas m_pXPBar->m_flBorder = 1.5f; m_nLobbySlot = 0; + color32 lightblue; + lightblue.r = 66; + lightblue.g = 142; + lightblue.b = 192; + lightblue.a = 255; + // Create the TraceMe button m_pTraceMeButton = new CBitmapButton( this, "TraceMeButton", ""); - m_pTraceMeButton->AddActionSignalTarget( this ); - m_pTraceMeButton->SetCommand( "TraceMePressed" ); + m_pTraceMeButton->AddActionSignalTarget(this); + m_pTraceMeButton->SetCommand("TraceMePressed"); + m_pTraceMeButton->SetImage(CBitmapButton::BUTTON_ENABLED, "vgui/briefing/trace_me_icon_on", lightblue); + m_pTraceMeButton->SetImage(CBitmapButton::BUTTON_PRESSED, "vgui/briefing/trace_me_icon_pressed", lightblue); + m_pTraceMeButton->SetImage(CBitmapButton::BUTTON_ENABLED_MOUSE_OVER, "vgui/briefing/trace_me_icon_mouse_over", lightblue); - // Create and initialize TracePlayerButton + // Create the TracePlayerButton m_pTracePlayerButton = new CBitmapButton( this, "TracePlayerButton", "" ); m_pTracePlayerButton->AddActionSignalTarget( this ); m_pTracePlayerButton->SetCommand( "TracePlayerPressed" ); + m_pTracePlayerButton->SetImage(CBitmapButton::BUTTON_ENABLED, "vgui/briefing/trace_player_icon_off", lightblue); + m_pTracePlayerButton->SetImage(CBitmapButton::BUTTON_PRESSED, "vgui/briefing/trace_player_icon_pressed", lightblue); + m_pTracePlayerButton->SetImage(CBitmapButton::BUTTON_ENABLED_MOUSE_OVER, "vgui/briefing/trace_player_icon_mouse_over", lightblue); + GetControllerFocus()->AddToFocusList( m_pPortraitButton ); GetControllerFocus()->AddToFocusList( m_pWeaponButton0 ); @@ -145,6 +159,15 @@ void CNB_Lobby_Row::ApplySchemeSettings( vgui::IScheme *pScheme ) } m_szLastPortraitImage[ 0 ] = 0; m_lastSteamID.Set( 0, k_EUniverseInvalid, k_EAccountTypeInvalid ); + + // place the button + m_pTraceMeButton->SetPos(XRES(4), YRES(35)); + m_pTracePlayerButton->SetPos(XRES(4), YRES(35)); + // set width and height + m_pTraceMeButton->SetWide(XRES(12)); + m_pTraceMeButton->SetTall(YRES(12)); + m_pTracePlayerButton->SetWide(XRES(12)); + m_pTracePlayerButton->SetTall(YRES(12)); } void CNB_Lobby_Row::PerformLayout() @@ -446,16 +469,6 @@ void CNB_Lobby_Row::UpdateDetails() pSilhouette->SetVisible( false ); } } - - // Set the images for the TraceMe button - const char* szTraceMeButtonEnabled = "vgui/swarm/Emotes/EmoteSmile"; - const char* szTraceMeButtonDisabled = "vgui/swarm/Emotes/EmoteStop"; - const char* szTraceMeButtonPressed = "vgui/swarm/Emotes/EmoteAmmo"; - const char* szTraceMeButtonMouseOver = "vgui/swarm/Emotes/EmoteMedic"; - m_pTraceMeButton->SetImage(CBitmapButton::BUTTON_ENABLED, szTraceMeButtonEnabled, lightblue); - m_pTraceMeButton->SetImage(CBitmapButton::BUTTON_DISABLED, szTraceMeButtonDisabled, lightblue); - m_pTraceMeButton->SetImage(CBitmapButton::BUTTON_PRESSED, szTraceMeButtonPressed, white); - m_pTraceMeButton->SetImage(CBitmapButton::BUTTON_ENABLED_MOUSE_OVER, szTraceMeButtonMouseOver, white); } void CNB_Lobby_Row::CheckTooltip( CNB_Lobby_Tooltip *pTooltip ) @@ -649,10 +662,18 @@ void CNB_Lobby_Row::TraceMePressed() return; // Invalid player index } - char cmd[128]; - Q_snprintf(cmd, sizeof(cmd), "rd_lobby_suggest_trace_player %d", localPlayerIndex); - // Send a message in chat to all other players to suggest them to trace this player - engine->ClientCmd_Unrestricted(cmd); + if (lastTraceMePressedTime < 0 || (lastTraceMePressedTime + 30.0) <= gpGlobals->curtime) + { + lastTraceMePressedTime = gpGlobals->curtime; // Prevent spamming the command + char cmd[128]; + Q_snprintf(cmd, sizeof(cmd), "rd_lobby_suggest_trace_player %d", localPlayerIndex); + // Send a message in chat to all other players to suggest them to trace this player + engine->ClientCmd_Unrestricted(cmd); + } + else + { + ClientPrint(CBasePlayer::GetLocalPlayer(), HUD_PRINTTALK, "asw_trace_me_cooling_down"); + } } } @@ -685,5 +706,6 @@ void CNB_Lobby_Row::TracePlayerPressed() } // flip the trace state for this player g_bShouldTracePlayer[playerIndex] = !g_bShouldTracePlayer[playerIndex]; + m_pTracePlayerButton->SetImage(CBitmapButton::BUTTON_ENABLED, g_bShouldTracePlayer[playerIndex] ? "vgui/briefing/trace_player_icon_on" : "vgui/briefing/trace_player_icon_off", color32{ 66, 142, 192, 255 }); Msg("Trace player %d : %s\n", playerIndex, g_bShouldTracePlayer[playerIndex] ? "true" : "false"); } diff --git a/src/game/client/swarm/vgui/nb_lobby_row.h b/src/game/client/swarm/vgui/nb_lobby_row.h index b58a25728..e20b03df2 100644 --- a/src/game/client/swarm/vgui/nb_lobby_row.h +++ b/src/game/client/swarm/vgui/nb_lobby_row.h @@ -84,6 +84,8 @@ class CNB_Lobby_Row : public vgui::EditablePanel SteamItemDef_t m_lastMedal[RD_STEAM_INVENTORY_NUM_MEDAL_SLOTS]; int m_nLobbySlot; + + float lastTraceMePressedTime = -1.0f; CBitmapButton *m_pTraceMeButton; CBitmapButton* m_pTracePlayerButton; }; From 6f99832a6a63e8e67970ea60eb7310c71eb2e13d Mon Sep 17 00:00:00 2001 From: ywgATustcbbs Date: Mon, 7 Jul 2025 01:25:21 +0800 Subject: [PATCH 04/13] vfx tweeks --- src/game/client/swarm/c_asw_marine.cpp | 3 +- src/game/client/swarm/vgui/asw_hud_emotes.cpp | 24 ++++-- src/game/shared/swarm/rd_lobby_utils.cpp | 78 ++++++++++--------- 3 files changed, 59 insertions(+), 46 deletions(-) diff --git a/src/game/client/swarm/c_asw_marine.cpp b/src/game/client/swarm/c_asw_marine.cpp index 047ddbba6..31efe51c8 100644 --- a/src/game/client/swarm/c_asw_marine.cpp +++ b/src/game/client/swarm/c_asw_marine.cpp @@ -109,8 +109,9 @@ extern float g_fMarinePoisonDuration; #ifdef CLIENT_DLL std::vector g_bShouldTracePlayer = std::vector(MAX_PLAYERS, false); // whether we have a trace position for this player -const float TRACE_FADE_TIME = 60.0f; // how long to keep the trace positions for +float TRACE_FADE_TIME = 60.0f; // how long to keep the trace positions for ConVar cl_trace_player_max_targets("cl_trace_player_max_targets", "3", FCVAR_ARCHIVE | FCVAR_CLIENTDLL, "Maximum number of players to trace positions for in the client.", true, 1.0f, true, 7.0f); +ConVar cl_trace_player_opacity("cl_trace_player_opacity", "0.5", FCVAR_ARCHIVE | FCVAR_CLIENTDLL, "Opacity of the player trace positions in the client. 0.0 means fully transparent, 1.0 means fully opaque.", true, 0.0f, true, 1.0f); #endif #define FLASHLIGHT_DISTANCE 1000 diff --git a/src/game/client/swarm/vgui/asw_hud_emotes.cpp b/src/game/client/swarm/vgui/asw_hud_emotes.cpp index 461a55ac3..d824e5e51 100644 --- a/src/game/client/swarm/vgui/asw_hud_emotes.cpp +++ b/src/game/client/swarm/vgui/asw_hud_emotes.cpp @@ -44,7 +44,8 @@ extern ConVar asw_draw_hud; #ifdef CLIENT_DLL extern std::vector g_bShouldTracePlayer; -extern const float TRACE_FADE_TIME; +extern float TRACE_FADE_TIME; +extern ConVar cl_trace_player_opacity; #endif //----------------------------------------------------------------------------- @@ -312,20 +313,29 @@ void CASWHudEmotes::PaintTraces() void CASWHudEmotes::PaintTracesFor(C_ASW_Marine* pMarine) { + float fTimeRatio = 1.0 - gpGlobals->curtime/3.0 + (int)(gpGlobals->curtime / 3.0); // current time + float fOpacity = cl_trace_player_opacity.GetFloat(); // default opacity for traces for (auto iter = pMarine->m_lstTracePlayerMovementList.begin(); iter != pMarine->m_lstTracePlayerMovementList.end(); ++iter) { - float fTime = (*iter).m_flTraceTime; + float fTraceRatio = (*iter).m_flTraceTime/TRACE_FADE_TIME; Vector vecPosition = (*iter).m_vecPosition; - if (fTime <= 0) + if (fTraceRatio <= 0) { continue; // no trace to draw } // draw a circle at the position of the trace in world space // and fade it out over time - float fAlpha = pow(((fTime / 3.0) - (int)(fTime / 3.0)),4); - fAlpha = clamp(fAlpha, 0.0f, 1.0f); + float fAlpha = (fTraceRatio + fTimeRatio) - (int)(fTraceRatio + fTimeRatio); + if (fAlpha > 1.0/3.0 || fAlpha <= 0.01) + { + continue; + } + else + { + fAlpha = pow(3.0 * fAlpha, 2.2); + } int iTexture = m_nSmileTexture; Vector screenPos; @@ -338,7 +348,7 @@ void CASWHudEmotes::PaintTracesFor(C_ASW_Marine* pMarine) if (iTexture != -1) { // 计算大小,随时间略微变化 - float fSize = 0.9f + 0.1f * fAlpha; + float fSize = 0.5f + 0.1f * fAlpha; // 应用屏幕高度比例和自定义缩放 float fScale = (ScreenHeight() / 768.0f); @@ -346,7 +356,7 @@ void CASWHudEmotes::PaintTracesFor(C_ASW_Marine* pMarine) float HalfH = 16.0f * fScale * fSize; // 设置颜色和纹理 - surface()->DrawSetColor(Color(255, 255, 255, fAlpha * 255.0f)); + surface()->DrawSetColor(Color(255, 255, 255, fAlpha * fOpacity * 255.0f)); surface()->DrawSetTexture(iTexture); // 绘制纹理多边形 diff --git a/src/game/shared/swarm/rd_lobby_utils.cpp b/src/game/shared/swarm/rd_lobby_utils.cpp index f890d2a34..4a67c4212 100644 --- a/src/game/shared/swarm/rd_lobby_utils.cpp +++ b/src/game/shared/swarm/rd_lobby_utils.cpp @@ -583,44 +583,6 @@ CON_COMMAND( rd_lobby_debug_filter_distance, "1: close, 2: default, 3: far, 4: w } } -CON_COMMAND(rd_lobby_suggest_trace_player, "notify server to send a trace player suggestion to all clients.") -{ - if (args.ArgC() < 2) - { - Msg("Usage: rd_lobby_suggest_trace_player \n"); - return; - } - - int iPlayerIndex = atoi(args[1]); - if (iPlayerIndex < 1 || iPlayerIndex > gpGlobals->maxClients) - { - Msg("Invalid playerIndex\n"); - return; - } - - CBasePlayer* pPlayer = UTIL_PlayerByIndex(iPlayerIndex); - if (!pPlayer) - { - Msg("Can't find a player with index <%d>.\n", iPlayerIndex); - return; - } - // Send the message to all players - for (int i = 1; i <= gpGlobals->maxClients; i++) - { - CBasePlayer* pRecipient = UTIL_PlayerByIndex(i); - if (!pRecipient) - continue; - if (pRecipient == pPlayer) - { - ClientPrint(pRecipient, HUD_PRINTTALK, "asw_trace_me_msg_to_self"); - } - else - { - ClientPrint(pRecipient, HUD_PRINTTALK, "asw_trace_me_msg_to_others", pPlayer->GetPlayerName()); - } - } -} - CReactiveDropServerListHelper::CReactiveDropServerListHelper( const char *szDebugName ) { m_pszDebugName = szDebugName; @@ -832,3 +794,43 @@ bool CReactiveDropServerList::IsHoIAFServerIP( uint32_t ip ) return HoIAF()->IsRankedServerIP( ip ); } #endif + +#ifndef CLIENT_DLL +CON_COMMAND(rd_lobby_suggest_trace_player, "notify server to send a trace player suggestion to all clients.") +{ + if (args.ArgC() < 2) + { + Msg("Usage: rd_lobby_suggest_trace_player \n"); + return; + } + + int iPlayerIndex = atoi(args[1]); + if (iPlayerIndex < 1 || iPlayerIndex > gpGlobals->maxClients) + { + Msg("Invalid playerIndex\n"); + return; + } + + CBasePlayer* pPlayer = UTIL_PlayerByIndex(iPlayerIndex); + if (!pPlayer) + { + Msg("Can't find a player with index <%d>.\n", iPlayerIndex); + return; + } + // Send the message to all players + for (int i = 1; i <= gpGlobals->maxClients; i++) + { + CBasePlayer* pRecipient = UTIL_PlayerByIndex(i); + if (!pRecipient) + continue; + if (pRecipient == pPlayer) + { + ClientPrint(pRecipient, HUD_PRINTTALK, "asw_trace_me_msg_to_self"); + } + else + { + ClientPrint(pRecipient, HUD_PRINTTALK, "asw_trace_me_msg_to_others", pPlayer->GetPlayerName()); + } + } +} +#endif From 78dbdba0b16d47f786cff0cfb57819348ade0d25 Mon Sep 17 00:00:00 2001 From: ywgATustcbbs Date: Tue, 8 Jul 2025 07:55:03 +0800 Subject: [PATCH 05/13] tracer ui icons and vfx tweaks --- .../briefing/trace_me_icon_mouse_over.vmt | 10 + .../briefing/trace_me_icon_mouse_over.vtf | Bin 0 -> 4304 bytes .../vgui/briefing/trace_me_icon_on.vmt | 10 + .../vgui/briefing/trace_me_icon_on.vtf | Bin 0 -> 4304 bytes .../vgui/briefing/trace_me_icon_pressed.vmt | 10 + .../vgui/briefing/trace_me_icon_pressed.vtf | Bin 0 -> 4304 bytes .../briefing/trace_player_icon_mouse_over.vmt | 10 + .../briefing/trace_player_icon_mouse_over.vtf | Bin 0 -> 4304 bytes .../vgui/briefing/trace_player_icon_off.vmt | 10 + .../vgui/briefing/trace_player_icon_off.vtf | Bin 0 -> 4304 bytes .../vgui/briefing/trace_player_icon_on.vmt | 10 + .../vgui/briefing/trace_player_icon_on.vtf | Bin 0 -> 4304 bytes .../briefing/trace_player_icon_pressed.vmt | 10 + .../briefing/trace_player_icon_pressed.vtf | Bin 0 -> 4304 bytes .../resource/ui/nb_lobby_row.res | 441 +++++++++++++++++ .../resource/ui/nb_lobby_row_2024.res | 455 ++++++++++++++++++ .../resource/ui/nb_lobby_row_small.res | 441 +++++++++++++++++ .../resource/ui/nb_lobby_row_small_2024.res | 441 +++++++++++++++++ .../resource/ui/nb_main_panel.res | 300 ++++++++++++ .../resource/ui/nb_main_panel_2024.res | 301 ++++++++++++ src/game/client/swarm/c_asw_marine.cpp | 13 +- src/game/client/swarm/c_asw_marine.h | 1 + src/game/client/swarm/vgui/asw_hud_emotes.cpp | 73 ++- src/game/client/swarm/vgui/nb_lobby_row.cpp | 114 +---- src/game/client/swarm/vgui/nb_lobby_row.h | 75 ++- .../client/swarm/vgui/nb_lobby_row_small.cpp | 29 +- src/game/client/swarm/vgui/nb_main_panel.cpp | 162 +++++-- src/game/client/swarm/vgui/nb_main_panel.h | 4 + 28 files changed, 2709 insertions(+), 211 deletions(-) create mode 100644 reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_me_icon_mouse_over.vmt create mode 100644 reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_me_icon_mouse_over.vtf create mode 100644 reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_me_icon_on.vmt create mode 100644 reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_me_icon_on.vtf create mode 100644 reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_me_icon_pressed.vmt create mode 100644 reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_me_icon_pressed.vtf create mode 100644 reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_player_icon_mouse_over.vmt create mode 100644 reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_player_icon_mouse_over.vtf create mode 100644 reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_player_icon_off.vmt create mode 100644 reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_player_icon_off.vtf create mode 100644 reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_player_icon_on.vmt create mode 100644 reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_player_icon_on.vtf create mode 100644 reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_player_icon_pressed.vmt create mode 100644 reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_player_icon_pressed.vtf create mode 100644 reactivedrop/content/trace_player_ui/resource/ui/nb_lobby_row.res create mode 100644 reactivedrop/content/trace_player_ui/resource/ui/nb_lobby_row_2024.res create mode 100644 reactivedrop/content/trace_player_ui/resource/ui/nb_lobby_row_small.res create mode 100644 reactivedrop/content/trace_player_ui/resource/ui/nb_lobby_row_small_2024.res create mode 100644 reactivedrop/content/trace_player_ui/resource/ui/nb_main_panel.res create mode 100644 reactivedrop/content/trace_player_ui/resource/ui/nb_main_panel_2024.res diff --git a/reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_me_icon_mouse_over.vmt b/reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_me_icon_mouse_over.vmt new file mode 100644 index 000000000..e83c3b05b --- /dev/null +++ b/reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_me_icon_mouse_over.vmt @@ -0,0 +1,10 @@ +UnlitGeneric +{ +$baseTexture "vgui\briefing\trace_me_icon_mouse_over" +$translucent 1 +$alpha 1 +$vertexalpha 1 +$ignorez 1 +$no_fullbright 1 +$vertexcolor 1 +} diff --git a/reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_me_icon_mouse_over.vtf b/reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_me_icon_mouse_over.vtf new file mode 100644 index 0000000000000000000000000000000000000000..493cb0a73c121c4960d3e120f0e0a4e25e2f8958 GIT binary patch literal 4304 zcmeHKZ%kWN6u&J&X<5UTrNOLUHnb6MGZ$a&FvG1_%*=QsfP1%nlBY2I;B?@S_Y$ide1%g{LVS|ocn^xZt@@@#0sxkcvZk3d6*CjeCOi}?XjKCh4{{6PgLwm|I+C% zf-e>ayscl4V(BS(za%|FZd=F3BHAk(*tw!YMcciBB^T!|N`Zog#;U6CH4hD4EqgSg z$emSFE+!5$5os?-$K?MxC zgpfSO82=>jS)KXhxD_xO&J6>|WU^=Ikv&62MV=IPRHd+$oc5+L`LE;0t0r5nO@4g- zO4{E2x%_hR#-+)9qi-JkX$a&a?tF{+{)SX+CcGYMC2GhtQ;-aKDdiscxA2qCdg%B# zb1c&*f&Sn!yte)3QmL7-_Y7P2d(Z7@|Lx}%l`W*c>b3D){+5Ng!Q?lCOGDl*1r|$J z5AI(mQEH|}n*VC?t!58pQKu92y`?uxjF2(JF{5ykt-Es^al-JFw0Bd1<6%l!sC^pe zSGzyTzx|te^PIWh=kc@H9F7(I6F@%2-(K=HjJ57prh~nVZN>Fvx<_(4Ba4XRVOeUs-Dqg)4yPFW7H7@R$tx(;FV_`e!Z*}2-@4K9u5MrV9^!-{OAU>)vxx6Ce{O%2MMb=MJhi<&BEP{O zmHxp%0PW%Ym1X>deVO{g^9Az9hw=&Ik~G?tcO0>HSg($_NeAMm59>;+8WjGB0slao zs^PrQznb{Z%*?D#z}yAbh+t}BWX6#ZvPucrO8vtmDf{*&Nsloxz6_6q#BRaYto^SmF`63^9{7wHZ5q}3$STQ#mqM!46f5GP*#`zf3 z3l<8Be9qN3WylotiT=y$>9%cyHMl-*Tq!q~=C5b5M^f9Ggnx7O3A~E<{}ul);e0V@ z=(s<(@A^Vq)ccrmNb0`vyo&RQa0K$Vz7Dagmr_k_YeSssmv{6JU8$>A#Qle#w?JF1 z(8u%b)4sj|Tpte~EthL94aR2MJSZt`T&dd2` z>krR=XCzx+ru0+N*k-G!H#~nes93n3^BwKm8by2->~Ct#)~gSp-}#o+$C%M9(b7%> z<=YKA)q+`l3D6&QpAq^;bPu)npKm~U&L7T;IA29+`<<>^W}>5G{xa|@uv$ASa{K>F z$?Z)pxH7*{PDs9!u}ur+C#L%HHGUuNgbV3{3C{zh@!AC7@qd8%^TYD>_X>OAg!pay pz~0ToPCD5GUlnOTaDMPS)2Oa|-pTdHeVneZ_&j*uAOCNE`~l(6x5oeg literal 0 HcmV?d00001 diff --git a/reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_me_icon_on.vmt b/reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_me_icon_on.vmt new file mode 100644 index 000000000..8e94572d5 --- /dev/null +++ b/reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_me_icon_on.vmt @@ -0,0 +1,10 @@ +UnlitGeneric +{ +$baseTexture "vgui\briefing\trace_me_icon_on" +$translucent 1 +$alpha 1 +$vertexalpha 1 +$ignorez 1 +$no_fullbright 1 +$vertexcolor 1 +} diff --git a/reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_me_icon_on.vtf b/reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_me_icon_on.vtf new file mode 100644 index 0000000000000000000000000000000000000000..2a53de6302304ff35f35212727bc58fa45c96d80 GIT binary patch literal 4304 zcmeHKPmB{)7=JTOv9mZSWG#qX7POZ)i6k=?4}h&(vqEPMC7IVwHcc7eVj{-DWH@LH zW%uO4ury3>h8Ql`%_au2doj_vdr>2jNKli#?8QXk0H#^9hGmEEP5a)|!Ma@th8W&% z|NQ#B_r34;z2E!Zo02((o4B94n_lbuQp+ac ziy*_>mMyGX#{};`s1u20@zNz{-`Eb)+_Txqk8LH*m6faNC^}*n3RC+OTqQ(?M!lFgc(71#GzI_E*mi;bUa>y-aM;lC@mpX1tmDZ<4w|wXp%@`V zhffswbO5u!Xp0y0E_5~7GU(G_pK~y& zJ9_cdyT8_*7%(AEJYEW<*^PIWJp0$=z4`3DH|yF6 zvh3VMl)unkI=lAG+10wX3kkxRNycxpim@NG4*y5Rr%a3qnHHIU7xcWG&LV~z)LvcU z_&KnH94pNJu=Brv+h6|5Z)fTH36d;7!2d3ghyRn>w>!>2d(`>*jdu+Ni{dS=ABqur zHO>0FhOQ!HmqLuOQwsH_t3z}>R+)X^eB43e2>f3G{xYsz&RErz4FO*ntRYRx{v_XqVKmqeZq%HJ}}TwmP(M))r*EcA=_ zD%1nmk11xS>yZ{jzP_&6Fq+L~4}S&L3-Nf{dN6*4jpy+({XqV_v=n1@*KFrSI5s&3 zesJ2_z1XgX`y=X)Kj7Se0_e*V{D$^&i&E-)5bWs0PZ<&2C>5O}>k4Cf`(JCns9^-uF3`zWkGZ^L;8hcmR!eTn8H zo(b*repBf=&!hfm|Jr=mKWcBo{z!SDoz8E=1)j|p?Vs$#pW6ASfA{q1JJ;URP(l=I zx#;;{UE6zXCtR5i!+k%VBIJd(f5EqoFVg#P4T+@f!}9>L7cT>D!UgzYF@1jM9sjtn u_J{9hrK1q<2pU2)vgwOttBd_2V+{j%r5r}_AQ=i@#>f|9)e literal 0 HcmV?d00001 diff --git a/reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_me_icon_pressed.vmt b/reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_me_icon_pressed.vmt new file mode 100644 index 000000000..9043b79f5 --- /dev/null +++ b/reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_me_icon_pressed.vmt @@ -0,0 +1,10 @@ +UnlitGeneric +{ +$baseTexture "vgui\briefing\trace_me_icon_pressed" +$translucent 1 +$alpha 1 +$vertexalpha 1 +$ignorez 1 +$no_fullbright 1 +$vertexcolor 1 +} diff --git a/reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_me_icon_pressed.vtf b/reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_me_icon_pressed.vtf new file mode 100644 index 0000000000000000000000000000000000000000..493cb0a73c121c4960d3e120f0e0a4e25e2f8958 GIT binary patch literal 4304 zcmeHKZ%kWN6u&J&X<5UTrNOLUHnb6MGZ$a&FvG1_%*=QsfP1%nlBY2I;B?@S_Y$ide1%g{LVS|ocn^xZt@@@#0sxkcvZk3d6*CjeCOi}?XjKCh4{{6PgLwm|I+C% zf-e>ayscl4V(BS(za%|FZd=F3BHAk(*tw!YMcciBB^T!|N`Zog#;U6CH4hD4EqgSg z$emSFE+!5$5os?-$K?MxC zgpfSO82=>jS)KXhxD_xO&J6>|WU^=Ikv&62MV=IPRHd+$oc5+L`LE;0t0r5nO@4g- zO4{E2x%_hR#-+)9qi-JkX$a&a?tF{+{)SX+CcGYMC2GhtQ;-aKDdiscxA2qCdg%B# zb1c&*f&Sn!yte)3QmL7-_Y7P2d(Z7@|Lx}%l`W*c>b3D){+5Ng!Q?lCOGDl*1r|$J z5AI(mQEH|}n*VC?t!58pQKu92y`?uxjF2(JF{5ykt-Es^al-JFw0Bd1<6%l!sC^pe zSGzyTzx|te^PIWh=kc@H9F7(I6F@%2-(K=HjJ57prh~nVZN>Fvx<_(4Ba4XRVOeUs-Dqg)4yPFW7H7@R$tx(;FV_`e!Z*}2-@4K9u5MrV9^!-{OAU>)vxx6Ce{O%2MMb=MJhi<&BEP{O zmHxp%0PW%Ym1X>deVO{g^9Az9hw=&Ik~G?tcO0>HSg($_NeAMm59>;+8WjGB0slao zs^PrQznb{Z%*?D#z}yAbh+t}BWX6#ZvPucrO8vtmDf{*&Nsloxz6_6q#BRaYto^SmF`63^9{7wHZ5q}3$STQ#mqM!46f5GP*#`zf3 z3l<8Be9qN3WylotiT=y$>9%cyHMl-*Tq!q~=C5b5M^f9Ggnx7O3A~E<{}ul);e0V@ z=(s<(@A^Vq)ccrmNb0`vyo&RQa0K$Vz7Dagmr_k_YeSssmv{6JU8$>A#Qle#w?JF1 z(8u%b)4sj|Tpte~EthL94aR2MJSZt`T&dd2` z>krR=XCzx+ru0+N*k-G!H#~nes93n3^BwKm8by2->~Ct#)~gSp-}#o+$C%M9(b7%> z<=YKA)q+`l3D6&QpAq^;bPu)npKm~U&L7T;IA29+`<<>^W}>5G{xa|@uv$ASa{K>F z$?Z)pxH7*{PDs9!u}ur+C#L%HHGUuNgbV3{3C{zh@!AC7@qd8%^TYD>_X>OAg!pay pz~0ToPCD5GUlnOTaDMPS)2Oa|-pTdHeVneZ_&j*uAOCNE`~l(6x5oeg literal 0 HcmV?d00001 diff --git a/reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_player_icon_mouse_over.vmt b/reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_player_icon_mouse_over.vmt new file mode 100644 index 000000000..3101af921 --- /dev/null +++ b/reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_player_icon_mouse_over.vmt @@ -0,0 +1,10 @@ +UnlitGeneric +{ +$baseTexture "vgui\briefing\trace_player_icon_mouse_over" +$translucent 1 +$alpha 1 +$vertexalpha 1 +$ignorez 1 +$no_fullbright 1 +$vertexcolor 1 +} diff --git a/reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_player_icon_mouse_over.vtf b/reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_player_icon_mouse_over.vtf new file mode 100644 index 0000000000000000000000000000000000000000..a1182722fe105798a7cc99d9d3bc6b0e788ece9c GIT binary patch literal 4304 zcmeHKZAe>J7(Pi?>c^t8R=N!o*D0(w#B4VPT#7SIMbqHCfVD8B*;C6(NkU z+KT(J8noH6LF;9OEh0JxR`gf8I_;0i7FfFm3pGsoclh0`mTB(ZWAfg(l(p%GFh);4 zpS=k<@<4%|ElN+jH)Jq`(p22Zc|)busnYH?#DOQ0|th5f20qwF4e6x%0Yqlb?te#V!KqQ<+Q$pMRrB&G=UARHR=5%&cnfMtT%)HMwF>>T2Y2RNQkyNEbo$m+bu>oZ1a{_pzrU(VkDGGKUx z95jfgG?H86R1)`5D`u9l@liNEth4b|S$5DHO6LIGG+2ZJuyj&}<)-rqM zYBZWm{;EHKJUj!2ynWxp$o4#@Uo=>3#Q7Vci#EUYL>uCmR434=u>x^v|4L&Vk_O@p zY2E^SClJRZkIi3UEJi%O8Rt&LAF}0(>y`OSL|q2YQQ!~sAH!dGD*p90jx!q5`j+;4 zY;7>`{Ft<0f#Vc^DE&4e4Z=V_@iBk5$q56o!Y37tWuUjX-C z9E?U$znC=QIAM+KL|om~ZK{1R<3_v@idcvmGC)fIKIt3NoX@S`uvBo!sMB0Pd3&qC zi!N6K;;i{*+9zxN!`wj_*`BudJ_MR^$Z^Lf1<#L0S;fGslWRo49doCU@s z>r?x+fPR0icM*$DrC&l#r-*QAOgInVFj;~VC$00mY`@h&#CoH)k zU8XSOJNMC`67M&`zR_qJv;D1+E+zh0K4@@0S}#Xs>!q))m)>Um9Mq%S%=*9o;lkp^ z;SaQDp#M{;a+Ul&3iBbq%%MIWK@0T`!Y`#?B2*`+htm8Kp?ZM~J`UGq$p0;#H<7_~ zJsELmIZ=f0OX|K+SdE{6X0<<*BhMrfH? zKTOn=uF6(5K@1J>KgFycXB{`L-!5!emOm{5eXp|fIw;+B7%g5Psfb;yAcih&==eDWvhC&x)F?l}oEM8-prsj1UR?;uVv1q^bmrgN-^|6h15np5Va8qNL8r^5I2yh6NN%649mhsU~^PBhHd^58%vxE8}*1#B(;PX6uRCuvHjQQX<4l&f!eRDbAo%!gi?#e&8o=4$_ zF9cuVFo{*B;CoFu9axeU7RHVQTg91k?_7@m*en*yHxqm$V5q8E;+*Tc{!QmppECRF zD^~kUoDU7Xd1*=cAkYV6_kk#%n|r)Fl;Fx6rB4}NXU-jD2|f{kWAK=d-MeYs^@bGb1Ugm~&iEH$K1>kS~zD@_Ljn z3c(1+QZ_z8*o^IP|9a#<5u)jredVv;`uROG_7pp;PDoz<(v9n-^5?VV<=9AIe0*|} z^l4H!x9m}|M=hM0;~eNlXniKnmC*O8B;o!%=L;_TW%5yFqN{4pj;W}UOr?8CzSep5 z&aZD+n?2T658Age6bgCy`+fuR@HS(?)(bH1_56O|GouY>Xg%;%gpghK7~OvZk_OEq zf00V7gmL|JM3xE9j-ovWb;9-X{fqntlUm?i1pYw(F8mXJi$D51o6X+F-|zQ#kv{WR zTG%2C!YF?}ci!P2p5k1FLGxc^?Y#G&;g9|v*4C!o`pd3(hk4GVYP=&(4^=VRqboAK zM(aZ_0RLol{{H)aiTA>w^LKh)cq+&v^7;?79_^9TjS<4${W`(lLaaOS0a)ohW_(QY z&mF<}YQAi*;2h0+_q!vmJN|dZKOeXCbK*6VPbiZEMvC+^=eV*ODG0*oUy;1pN*MY2 zFQgrL%m;o~ydZYhn||1z?P+$-!}~=f>&Oo~;s10zPWs)^p4;^i4Q$b z_pa{%eH&f;M)wDK`7ZV4rvbEY!QqSb!Ti#2@&VQxJ!QODQ{TGz&+s^mn)|u zK7Vc6Px4;<2p27F{`xQYR>hE{7{}S{= zpdKUKpMOn}KCJ2sn6t%y5%eHe}VebDNy^vWObD6~^%9 z?=R<`d(ZEjd(S!Pk8dW;gb+Kt-iB8I9;BNP8+_-Z`?)rM%U7%3e1F|(f9034-ZuDR zbHQ7CJ5H;J;JqN6cNFX=*1bIB>0yPP5}NpZ zz&N}^5mKprmkPq?jtGn|<9+nl>easKcv0Lr(Mc}FH8Cf=PF~qK?ogCnyH317$O^{T z1^6U2pZxb>!0jZQUmMOpbAv94J67I0mA?AX`Nh1K;~o+*0F%kJGfSBK=kfZV!QNGi zy%l?Rk>>XRpIUR}RnHQ?BnFBH0_Zb?T%3CLwRSt_>u$2y45Jd7yw^iXGQliNDOY$5 z)={3@GAJ0Vya90`lMaEp9dUFgm+zlLJh_nyge8)Q^APt2_ItEFvy8R=wqfzd{dYdi zdtV}30|)K({O#q18;chv7EgM&I}RKeAIJS$1xk&jQSnDTmINorPxs>d?}ijnFZ*4H zOKMhXxh5wptVkzn{1?qA5^?LM{XLm%aA0)q9L|qOl(Iy>jJSUPMzMa=xYcXi?&bb$ zak*Ue{B3^#d3ff%&aQ7^G`b%RQL0aM_;7w9qs4OJZ6kDvW?}X^I7&TsG2k~GV(6k z&-pYpHP!H+&uB1EzMwkeXU?24`A0KZsRIVekHC47VIXca-Ve-QCjL%{f5()r<9sxoqsqF#BSw}dDR&jPSs*X^0^O{P=EK1h#;p1O#S8OU!a>{;Qo)> zkDq@A2OQ`3sO!ZZ|LI>4r`3p<+IRCBVwf*5mN4V_>t4tg`m7)2xy<$0raj3!h^K)+ zc+b2q9D}#UP@awP{Ts*+4afh<_$x9MW@l&3^IcFC>ENEEnZJ87N^rc*Uq*YOeoL(X zN*CfZ+z;2eVbdRl{aLZiu+BqCEe469Go1fDJnDXYHndU78M3hGZU`PbKj zI1T3`|3fm481jWEkB$x_uGFLZutZ(GYM6hH24Os)UtMoE*jHQccs$)T_thDvLQ?+e z8`LkTRAgo2Fk)U0*#|4WM(oOHK{l|s5^+?`icB}=5T`T682dP2o+m995jx*EdJN?` z$T#ndY%}lc^&q8*M8D}DGky*7pMm;!_UzeDIh| z8svk1SvLKJ_RkpM<6nf2zs37GD1R;W^?&`{g&X%a4|(=L|7WwcG~xa;Fdy=Z8IRqP z2kISMzpA|@RSMasEqmwHz7WwKg{3sPgp_dASDwHglM>^;f%8)K~bvjfoor>}B;a2#1Z|EHM8rSkt3-1F2w)qm*t|M35QKK=xHqT65q literal 0 HcmV?d00001 diff --git a/reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_player_icon_pressed.vmt b/reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_player_icon_pressed.vmt new file mode 100644 index 000000000..12484db06 --- /dev/null +++ b/reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_player_icon_pressed.vmt @@ -0,0 +1,10 @@ +UnlitGeneric +{ +$baseTexture "vgui\briefing\trace_player_icon_pressed" +$translucent 1 +$alpha 1 +$vertexalpha 1 +$ignorez 1 +$no_fullbright 1 +$vertexcolor 1 +} diff --git a/reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_player_icon_pressed.vtf b/reactivedrop/content/trace_player_ui/materials/vgui/briefing/trace_player_icon_pressed.vtf new file mode 100644 index 0000000000000000000000000000000000000000..a1182722fe105798a7cc99d9d3bc6b0e788ece9c GIT binary patch literal 4304 zcmeHKZAe>J7(Pi?>c^t8R=N!o*D0(w#B4VPT#7SIMbqHCfVD8B*;C6(NkU z+KT(J8noH6LF;9OEh0JxR`gf8I_;0i7FfFm3pGsoclh0`mTB(ZWAfg(l(p%GFh);4 zpS=k<@<4%|ElN+jH)Jq`(p22Zc|)busnYH?#DOQ0|th5f20qwF4e6x%0Yqlb?te#V!KqQ<+Q$pMRrB&G=UARHR=5%&cnfMtT%)HMwF>>T2Y2RNQkyNEbo$m+bu>oZ1a{_pzrU(VkDGGKUx z95jfgG?H86R1)`5D`u9l@liNEth4b|S$5DHO6LIGG+2ZJuyj&}<)-rqM zYBZWm{;EHKJUj!2ynWxp$o4#@Uo=>3#Q7Vci#EUYL>uCmR434=u>x^v|4L&Vk_O@p zY2E^SClJRZkIi3UEJi%O8Rt&LAF}0(>y`OSL|q2YQQ!~sAH!dGD*p90jx!q5`j+;4 zY;7>`{Ft<0f#Vc^DE&4e4Z=V_@iBk5$q56o!Y37tWuUjX-C z9E?U$znC=QIAM+KL|om~ZK{1R<3_v@idcvmGC)fIKIt3NoX@S`uvBo!sMB0Pd3&qC zi!N6K;;i{*+9zxN!`wj_*`BudJ_MR^$Z^Lf1<#L0S;fGslWRo49doCU@s z>r?x+fPR0icM*$DrC&l#r-*QAOgInVFj;~VC$00mY`@h&#CoH)k zU8XSOJNMC`67M&`zR_qJv;D1+E+zh0K4@@0S}#Xs>!q))m)>Um9Mq%S%=*9o;lkp^ z;SaQDp#M{;a+Ul&3iBbq%%MIWK@0T`!Y`#?B2*`+htm8Kp?ZM~J`UGq$p0;#H<7_~ zJsELmIZ=f0OX|K+SdE{6X0<<*BhMrfH? zKTOn=uF6(5K@1J>KgFycXB{`L-!5!emOm{5eXp|fIw;+B g_bShouldTracePlayer = std::vector(MAX_PLAYERS, false); // whether we have a trace position for this player +std::vector g_bShouldTracePlayer = std::vector(MAX_PLAYERS, true); // whether we have a trace position for this player float TRACE_FADE_TIME = 60.0f; // how long to keep the trace positions for ConVar cl_trace_player_max_targets("cl_trace_player_max_targets", "3", FCVAR_ARCHIVE | FCVAR_CLIENTDLL, "Maximum number of players to trace positions for in the client.", true, 1.0f, true, 7.0f); ConVar cl_trace_player_opacity("cl_trace_player_opacity", "0.5", FCVAR_ARCHIVE | FCVAR_CLIENTDLL, "Opacity of the player trace positions in the client. 0.0 means fully transparent, 1.0 means fully opaque.", true, 0.0f, true, 1.0f); @@ -991,17 +991,20 @@ void C_ASW_Marine::DoWaterRipples() void C_ASW_Marine::TickTracePlayerMovement(float d) { - // insert current time marine position + m_nTraceSkip--; + if ( m_nTraceSkip > 0 ) + return; + m_nTraceSkip = 20; + // get current marine position struct TracePlayerMovement_t movement; - //get current time movement.m_flTraceTime = TRACE_FADE_TIME; - movement.m_vecPosition = GetAbsOrigin() + Vector(0, 0, 5); + movement.m_vecPosition = GetAbsOrigin(); m_lstTracePlayerMovementList.push_back(movement); // update the trace time for each movement trace for (auto iter = m_lstTracePlayerMovementList.begin(); iter != m_lstTracePlayerMovementList.end(); ++iter) { - iter->m_flTraceTime -= d; + iter->m_flTraceTime -= 20 * d; } // remove any traces that have expired diff --git a/src/game/client/swarm/c_asw_marine.h b/src/game/client/swarm/c_asw_marine.h index 2fa85e939..c906d9789 100644 --- a/src/game/client/swarm/c_asw_marine.h +++ b/src/game/client/swarm/c_asw_marine.h @@ -306,6 +306,7 @@ class C_ASW_Marine : public C_ASW_VPhysics_NPC, public IASWPlayerAnimStateHelper void TickEmotes( float d ); bool TickEmote( float d, int bit, float &fEmoteTime ); #ifdef CLIENT_DLL + int m_nTraceSkip = 10; void TickTracePlayerMovement(float d); std::list m_lstTracePlayerMovementList = std::list(); // list of positions and times for the last few frames #endif diff --git a/src/game/client/swarm/vgui/asw_hud_emotes.cpp b/src/game/client/swarm/vgui/asw_hud_emotes.cpp index d824e5e51..203632714 100644 --- a/src/game/client/swarm/vgui/asw_hud_emotes.cpp +++ b/src/game/client/swarm/vgui/asw_hud_emotes.cpp @@ -31,8 +31,11 @@ #include "vguimatsurface/imatsystemsurface.h" #include "tier1/fmtstr.h" #ifdef CLIENT_DLL -#include -#include + #include + #include + #include "c_basetempentity.h" + #include "c_te_legacytempents.h" + #include "tempent.h" #endif // memdbgon must be the last include file in a .cpp file!!! @@ -83,6 +86,7 @@ class CASWHudEmotes : public CASW_HudElement, public vgui::Panel CPanelAnimationVarAliasType( int, m_nHackTexture, "HackTexture", "vgui/swarm/ClassIcons/HackIcon", "textureid" ); CPanelAnimationVarAliasType( int, m_nWeldTexture, "WeldTexture", "vgui/swarm/ClassIcons/WeldIcon", "textureid" ); CPanelAnimationVarAliasType( int, m_nReviveMarineTexture, "ReviveMarineTexture", "vgui/swarm/ClassIcons/revivemarine", "textureid" ); + CPanelAnimationVarAliasType(int, m_nTraceTexture, "TraceTexture", "vgui/icon_arrow_down", "textureid"); }; DECLARE_HUDELEMENT( CASWHudEmotes ); @@ -313,12 +317,19 @@ void CASWHudEmotes::PaintTraces() void CASWHudEmotes::PaintTracesFor(C_ASW_Marine* pMarine) { - float fTimeRatio = 1.0 - gpGlobals->curtime/3.0 + (int)(gpGlobals->curtime / 3.0); // current time + float fTimeRatio = 1.0 - gpGlobals->curtime / 3.0 + (int)(gpGlobals->curtime / 3.0); // current time float fOpacity = cl_trace_player_opacity.GetFloat(); // default opacity for traces - for (auto iter = pMarine->m_lstTracePlayerMovementList.begin(); iter != pMarine->m_lstTracePlayerMovementList.end(); ++iter) + auto iter = pMarine->m_lstTracePlayerMovementList.begin(); + auto iterNext = iter; + if (pMarine->m_lstTracePlayerMovementList.size() > 1) { - float fTraceRatio = (*iter).m_flTraceTime/TRACE_FADE_TIME; + iterNext++; + } + for (; iter != pMarine->m_lstTracePlayerMovementList.end() && iterNext != pMarine->m_lstTracePlayerMovementList.end(); ++iter, ++iterNext) + { + float fTraceRatio = (*iter).m_flTraceTime / TRACE_FADE_TIME; Vector vecPosition = (*iter).m_vecPosition; + Vector vecPositionNext = (*iterNext).m_vecPosition; if (fTraceRatio <= 0) { @@ -328,7 +339,7 @@ void CASWHudEmotes::PaintTracesFor(C_ASW_Marine* pMarine) // draw a circle at the position of the trace in world space // and fade it out over time float fAlpha = (fTraceRatio + fTimeRatio) - (int)(fTraceRatio + fTimeRatio); - if (fAlpha > 1.0/3.0 || fAlpha <= 0.01) + if (fAlpha > 1.0 / 3.0 || fAlpha <= 0.01) { continue; } @@ -336,37 +347,55 @@ void CASWHudEmotes::PaintTracesFor(C_ASW_Marine* pMarine) { fAlpha = pow(3.0 * fAlpha, 2.2); } - int iTexture = m_nSmileTexture; - + int iTexture = m_nTraceTexture; Vector screenPos; - // 将世界坐标转换为屏幕坐标 - if (!debugoverlay->ScreenPosition(vecPosition, screenPos)) + Vector screenPosNext; + if (!debugoverlay->ScreenPosition(vecPosition, screenPos) && !debugoverlay->ScreenPosition(vecPositionNext, screenPosNext)) { float xPos = screenPos[0]; float yPos = screenPos[1]; + Vector vecTargetDirection = vecPositionNext - vecPosition; + vecTargetDirection.z = 0; + if (vecTargetDirection.NormalizeInPlace() < 0.01) + { + continue; // no direction to draw + } if (iTexture != -1) { - // 计算大小,随时间略微变化 - float fSize = 0.5f + 0.1f * fAlpha; - - // 应用屏幕高度比例和自定义缩放 float fScale = (ScreenHeight() / 768.0f); - float HalfW = 16.0f * fScale * fSize; - float HalfH = 16.0f * fScale * fSize; + float HalfW = 16.0f * fScale; + float HalfH = 16.0f * fScale; - // 设置颜色和纹理 surface()->DrawSetColor(Color(255, 255, 255, fAlpha * fOpacity * 255.0f)); surface()->DrawSetTexture(iTexture); - // 绘制纹理多边形 + float fFacingYaw = -UTIL_VecToYaw(vecTargetDirection); + Vector vecCornerTL(-HalfW, -HalfH, 0); + Vector vecCornerTR(HalfW, -HalfH, 0); + Vector vecCornerBR(HalfW, HalfH, 0); + Vector vecCornerBL(-HalfW, HalfH, 0); + Vector vecCornerTL_rotated, vecCornerTR_rotated, vecCornerBR_rotated, vecCornerBL_rotated; + + // rotate it by our facing yaw + QAngle angFacing(0, -fFacingYaw, 0); + VectorRotate(vecCornerTL, angFacing, vecCornerTL_rotated); + VectorRotate(vecCornerTR, angFacing, vecCornerTR_rotated); + VectorRotate(vecCornerBR, angFacing, vecCornerBR_rotated); + VectorRotate(vecCornerBL, angFacing, vecCornerBL_rotated); + Vertex_t points[4] = { - Vertex_t(Vector2D(xPos - HalfW, yPos - HalfH), Vector2D(0, 0)), - Vertex_t(Vector2D(xPos + HalfW, yPos - HalfH), Vector2D(1, 0)), - Vertex_t(Vector2D(xPos + HalfW, yPos + HalfH), Vector2D(1, 1)), - Vertex_t(Vector2D(xPos - HalfW, yPos + HalfH), Vector2D(0, 1)) + Vertex_t(Vector2D(xPos + vecCornerTL_rotated.x, yPos + vecCornerTL_rotated.y), + Vector2D(0,0)), + Vertex_t(Vector2D(xPos + vecCornerTR_rotated.x, yPos + vecCornerTR_rotated.y), + Vector2D(1,0)), + Vertex_t(Vector2D(xPos + vecCornerBR_rotated.x, yPos + vecCornerBR_rotated.y), + Vector2D(1,1)), + Vertex_t(Vector2D(xPos + vecCornerBL_rotated.x, yPos + vecCornerBL_rotated.y), + Vector2D(0,1)) }; + surface()->DrawTexturedPolygon(4, points); } } diff --git a/src/game/client/swarm/vgui/nb_lobby_row.cpp b/src/game/client/swarm/vgui/nb_lobby_row.cpp index 56e9ccff9..b1c298396 100644 --- a/src/game/client/swarm/vgui/nb_lobby_row.cpp +++ b/src/game/client/swarm/vgui/nb_lobby_row.cpp @@ -108,14 +108,10 @@ CNB_Lobby_Row::CNB_Lobby_Row( vgui::Panel *parent, const char *name ) : BaseClas lightblue.g = 142; lightblue.b = 192; lightblue.a = 255; - - // Create the TraceMe button - m_pTraceMeButton = new CBitmapButton( this, "TraceMeButton", ""); - m_pTraceMeButton->AddActionSignalTarget(this); - m_pTraceMeButton->SetCommand("TraceMePressed"); - m_pTraceMeButton->SetImage(CBitmapButton::BUTTON_ENABLED, "vgui/briefing/trace_me_icon_on", lightblue); - m_pTraceMeButton->SetImage(CBitmapButton::BUTTON_PRESSED, "vgui/briefing/trace_me_icon_pressed", lightblue); - m_pTraceMeButton->SetImage(CBitmapButton::BUTTON_ENABLED_MOUSE_OVER, "vgui/briefing/trace_me_icon_mouse_over", lightblue); + lightblue.r = 255; + lightblue.g = 255; + lightblue.b = 255; + lightblue.a = 255; // Create the TracePlayerButton m_pTracePlayerButton = new CBitmapButton( this, "TracePlayerButton", "" ); @@ -130,44 +126,40 @@ CNB_Lobby_Row::CNB_Lobby_Row( vgui::Panel *parent, const char *name ) : BaseClas GetControllerFocus()->AddToFocusList( m_pWeaponButton0 ); GetControllerFocus()->AddToFocusList( m_pWeaponButton1 ); GetControllerFocus()->AddToFocusList( m_pWeaponButton2 ); - GetControllerFocus()->AddToFocusList( m_pTraceMeButton ); GetControllerFocus()->AddToFocusList( m_pTracePlayerButton ); } CNB_Lobby_Row::~CNB_Lobby_Row() { - GetControllerFocus()->RemoveFromFocusList( m_pPortraitButton ); - GetControllerFocus()->RemoveFromFocusList( m_pWeaponButton0 ); - GetControllerFocus()->RemoveFromFocusList( m_pWeaponButton1 ); - GetControllerFocus()->RemoveFromFocusList( m_pWeaponButton2 ); - GetControllerFocus()->RemoveFromFocusList( m_pTraceMeButton ); - GetControllerFocus()->RemoveFromFocusList( m_pTracePlayerButton ); + GetControllerFocus()->RemoveFromFocusList(m_pPortraitButton); + GetControllerFocus()->RemoveFromFocusList(m_pWeaponButton0); + GetControllerFocus()->RemoveFromFocusList(m_pWeaponButton1); + GetControllerFocus()->RemoveFromFocusList(m_pWeaponButton2); + GetControllerFocus()->RemoveFromFocusList(m_pTracePlayerButton); } -void CNB_Lobby_Row::ApplySchemeSettings( vgui::IScheme *pScheme ) +void CNB_Lobby_Row::ApplySchemeSettings(vgui::IScheme* pScheme) { - BaseClass::ApplySchemeSettings( pScheme ); - - if ( rd_legacy_ui.GetString()[0] != '\0' ) - LoadControlSettings( "resource/ui/nb_lobby_row.res" ); - else - LoadControlSettings( "resource/ui/nb_lobby_row_2024.res" ); + BaseClass::ApplySchemeSettings(pScheme); - for ( int i = 0;i < ASW_NUM_INVENTORY_SLOTS; i++ ) + // Unless we have clearly specified a correct scheme, we will use the default scheme for the game. + auto currentScheme = rd_legacy_ui.GetString(); + if (!Q_stricmp(currentScheme, "'2004") + || !Q_stricmp(currentScheme, "'2010") + || !Q_stricmp(currentScheme, "'2017")) + { + LoadControlSettings("resource/ui/nb_lobby_row.res"); + } + else + { + LoadControlSettings("resource/ui/nb_lobby_row_2024.res"); + } + for (int i = 0; i < ASW_NUM_INVENTORY_SLOTS; i++) { m_szLastWeaponImage[i][0] = 0; } - m_szLastPortraitImage[ 0 ] = 0; - m_lastSteamID.Set( 0, k_EUniverseInvalid, k_EAccountTypeInvalid ); - - // place the button - m_pTraceMeButton->SetPos(XRES(4), YRES(35)); - m_pTracePlayerButton->SetPos(XRES(4), YRES(35)); - // set width and height - m_pTraceMeButton->SetWide(XRES(12)); - m_pTraceMeButton->SetTall(YRES(12)); - m_pTracePlayerButton->SetWide(XRES(12)); - m_pTracePlayerButton->SetTall(YRES(12)); + m_szLastPortraitImage[0] = 0; + m_lastSteamID.Set(0, k_EUniverseInvalid, k_EAccountTypeInvalid); } void CNB_Lobby_Row::PerformLayout() @@ -181,7 +173,6 @@ void CNB_Lobby_Row::OnThink() UpdateDetails(); UpdateChangingSlot(); - UpdateTraceMeButton(); // Update the TraceMe button state UpdateTracePlayerButton(); // Update the TracePlayer button state } @@ -563,10 +554,6 @@ void CNB_Lobby_Row::OnCommand(const char* command) } #endif } - else if (!Q_stricmp(command, "TraceMePressed")) - { - TraceMePressed(); - } else if (!Q_stricmp(command, "TracePlayerPressed")) { TracePlayerPressed(); @@ -630,58 +617,10 @@ void CNB_Lobby_Row::UpdateChangingSlot() m_pChangingSlot[ 3 ]->SetVisible( nSlot == 4 ); } -void CNB_Lobby_Row::UpdateTraceMeButton() -{ - if (!m_pTraceMeButton) - return; - - // Check if the TraceMe button should be enabled or not - // It should be enabled if it's an online game, the slot is the local player's slot, the slot is not a bot, the slot is occupied, and the marine profile exists - if (!Briefing() - || Briefing()->IsOfflineGame() - || !Briefing()->IsLobbySlotLocal(m_nLobbySlot) - || Briefing()->IsLobbySlotBot(m_nLobbySlot) - || !Briefing()->IsLobbySlotOccupied(m_nLobbySlot) - || Briefing()->GetMarineProfile(m_nLobbySlot) == NULL) - { - m_pTraceMeButton->SetVisible(false); - return; - } - m_pTraceMeButton->SetVisible(true); -} - -void CNB_Lobby_Row::TraceMePressed() -{ - // Get the local player index - int localPlayerIndex = -1; - if (engine && engine->IsInGame()) - { - localPlayerIndex = engine->GetLocalPlayer(); - if (localPlayerIndex < 0 || localPlayerIndex >= gpGlobals->maxClients) - { - return; // Invalid player index - } - - if (lastTraceMePressedTime < 0 || (lastTraceMePressedTime + 30.0) <= gpGlobals->curtime) - { - lastTraceMePressedTime = gpGlobals->curtime; // Prevent spamming the command - char cmd[128]; - Q_snprintf(cmd, sizeof(cmd), "rd_lobby_suggest_trace_player %d", localPlayerIndex); - // Send a message in chat to all other players to suggest them to trace this player - engine->ClientCmd_Unrestricted(cmd); - } - else - { - ClientPrint(CBasePlayer::GetLocalPlayer(), HUD_PRINTTALK, "asw_trace_me_cooling_down"); - } - } -} - void CNB_Lobby_Row::UpdateTracePlayerButton() { if (!m_pTracePlayerButton) return; - // In online games, show the button only for other players (not local player, not bot, and occupied slot) if (!Briefing() || Briefing()->IsOfflineGame() @@ -707,5 +646,4 @@ void CNB_Lobby_Row::TracePlayerPressed() // flip the trace state for this player g_bShouldTracePlayer[playerIndex] = !g_bShouldTracePlayer[playerIndex]; m_pTracePlayerButton->SetImage(CBitmapButton::BUTTON_ENABLED, g_bShouldTracePlayer[playerIndex] ? "vgui/briefing/trace_player_icon_on" : "vgui/briefing/trace_player_icon_off", color32{ 66, 142, 192, 255 }); - Msg("Trace player %d : %s\n", playerIndex, g_bShouldTracePlayer[playerIndex] ? "true" : "false"); } diff --git a/src/game/client/swarm/vgui/nb_lobby_row.h b/src/game/client/swarm/vgui/nb_lobby_row.h index e20b03df2..56961d7c5 100644 --- a/src/game/client/swarm/vgui/nb_lobby_row.h +++ b/src/game/client/swarm/vgui/nb_lobby_row.h @@ -27,66 +27,63 @@ namespace BaseModUI class CNB_Lobby_Row : public vgui::EditablePanel { - DECLARE_CLASS_SIMPLE( CNB_Lobby_Row, vgui::EditablePanel ); + DECLARE_CLASS_SIMPLE(CNB_Lobby_Row, vgui::EditablePanel); public: - CNB_Lobby_Row( vgui::Panel *parent, const char *name ); + CNB_Lobby_Row(vgui::Panel* parent, const char* name); virtual ~CNB_Lobby_Row(); - - virtual void ApplySchemeSettings( vgui::IScheme *pScheme ); + + virtual void ApplySchemeSettings(vgui::IScheme* pScheme); virtual void PerformLayout(); virtual void OnThink(); - virtual void OnCommand( const char *command ); + virtual void OnCommand(const char* command); void OpenPlayerFlyout(); - CNB_Main_Panel *GetMainPanel(); + CNB_Main_Panel* GetMainPanel(); virtual void UpdateDetails(); - virtual void CheckTooltip( CNB_Lobby_Tooltip *pTooltip ); + virtual void CheckTooltip(CNB_Lobby_Tooltip* pTooltip); void UpdateChangingSlot(); - void UpdateTraceMeButton(); - void TraceMePressed(); void UpdateTracePlayerButton(); void TracePlayerPressed(); - + // == MANAGED_MEMBER_POINTERS_START: Do not edit by hand == - vgui::ImagePanel *m_pBackground; - vgui::Panel *m_pBackgroundWeapon0; - vgui::Panel *m_pBackgroundWeapon1; - vgui::Panel *m_pBackgroundWeapon2; - vgui::Panel *m_pBackgroundInnerWeapon0; - vgui::Panel *m_pBackgroundInnerWeapon1; - vgui::Panel *m_pBackgroundInnerWeapon2; - vgui::ImagePanel *m_pSilhouetteWeapon0; - vgui::ImagePanel *m_pSilhouetteWeapon1; - vgui::ImagePanel *m_pSilhouetteWeapon2; - vgui::Panel *m_pAvatarBackground; - CAvatarImagePanel *m_pAvatarImage; - vgui::ImagePanel *m_pClassImage; - BaseModUI::DropDownMenu *m_pNameDropdown; - vgui::Label *m_pLevelLabel; - StatsBar *m_pXPBar; - vgui::Label *m_pClassLabel; + vgui::ImagePanel* m_pBackground; + vgui::Panel* m_pBackgroundWeapon0; + vgui::Panel* m_pBackgroundWeapon1; + vgui::Panel* m_pBackgroundWeapon2; + vgui::Panel* m_pBackgroundInnerWeapon0; + vgui::Panel* m_pBackgroundInnerWeapon1; + vgui::Panel* m_pBackgroundInnerWeapon2; + vgui::ImagePanel* m_pSilhouetteWeapon0; + vgui::ImagePanel* m_pSilhouetteWeapon1; + vgui::ImagePanel* m_pSilhouetteWeapon2; + vgui::Panel* m_pAvatarBackground; + CAvatarImagePanel* m_pAvatarImage; + vgui::ImagePanel* m_pClassImage; + BaseModUI::DropDownMenu* m_pNameDropdown; + vgui::Label* m_pLevelLabel; + StatsBar* m_pXPBar; + vgui::Label* m_pClassLabel; // == MANAGED_MEMBER_POINTERS_END == - CBitmapButton *m_pPortraitButton; - CBitmapButton *m_pWeaponButton0; - CBitmapButton *m_pWeaponButton1; - CBitmapButton *m_pWeaponButton2; - vgui::ImagePanel *m_pVoiceIcon; - vgui::ImagePanel *m_pPromotionIcon; - vgui::ImagePanel *m_pMedalIcon[RD_STEAM_INVENTORY_NUM_MEDAL_SLOTS]; - vgui::ImagePanel *m_pChangingSlot[ 4 ]; + CBitmapButton* m_pPortraitButton; + CBitmapButton* m_pWeaponButton0; + CBitmapButton* m_pWeaponButton1; + CBitmapButton* m_pWeaponButton2; + vgui::ImagePanel* m_pVoiceIcon; + vgui::ImagePanel* m_pPromotionIcon; + vgui::ImagePanel* m_pMedalIcon[RD_STEAM_INVENTORY_NUM_MEDAL_SLOTS]; + vgui::ImagePanel* m_pChangingSlot[4]; - char m_szLastWeaponImage[ ASW_NUM_INVENTORY_SLOTS ][ 255 ]; - char m_szLastPortraitImage[ 255 ]; + char m_szLastWeaponImage[ASW_NUM_INVENTORY_SLOTS][255]; + char m_szLastPortraitImage[255]; CSteamID m_lastSteamID; int m_nLastPromotion; SteamItemDef_t m_lastMedal[RD_STEAM_INVENTORY_NUM_MEDAL_SLOTS]; int m_nLobbySlot; - float lastTraceMePressedTime = -1.0f; - CBitmapButton *m_pTraceMeButton; + CBitmapButton* m_pTracePlayerButton; }; diff --git a/src/game/client/swarm/vgui/nb_lobby_row_small.cpp b/src/game/client/swarm/vgui/nb_lobby_row_small.cpp index e44befe14..696e0dcdd 100644 --- a/src/game/client/swarm/vgui/nb_lobby_row_small.cpp +++ b/src/game/client/swarm/vgui/nb_lobby_row_small.cpp @@ -24,23 +24,32 @@ CNB_Lobby_Row_Small::~CNB_Lobby_Row_Small() } -void CNB_Lobby_Row_Small::ApplySchemeSettings( vgui::IScheme *pScheme ) +void CNB_Lobby_Row_Small::ApplySchemeSettings(vgui::IScheme* pScheme) { - BaseClass::BaseClass::ApplySchemeSettings( pScheme ); - - if ( rd_legacy_ui.GetString()[0] != '\0' ) - LoadControlSettings( "resource/ui/nb_lobby_row_small.res" ); + BaseClass::BaseClass::ApplySchemeSettings(pScheme); + + // Unless we have clearly specified a correct scheme, we will use the default scheme for the game. + auto currentScheme = rd_legacy_ui.GetString(); + if (!Q_stricmp(currentScheme, "'2004") + || !Q_stricmp(currentScheme, "'2010") + || !Q_stricmp(currentScheme, "'2017")) + { + LoadControlSettings("resource/ui/nb_lobby_row_small.res"); + } else - LoadControlSettings( "resource/ui/nb_lobby_row_small_2024.res" ); + { + LoadControlSettings("resource/ui/nb_lobby_row_small_2024.res"); + } + - for ( int i = 0;i < ASW_NUM_INVENTORY_SLOTS; i++ ) + for (int i = 0; i < ASW_NUM_INVENTORY_SLOTS; i++) { m_szLastWeaponImage[i][0] = 0; } - m_szLastPortraitImage[ 0 ] = 0; - m_lastSteamID.Set( 0, k_EUniverseInvalid, k_EAccountTypeInvalid ); + m_szLastPortraitImage[0] = 0; + m_lastSteamID.Set(0, k_EUniverseInvalid, k_EAccountTypeInvalid); - SetTall( m_pBackroundPlain->GetTall() ); + SetTall(m_pBackroundPlain->GetTall()); } void CNB_Lobby_Row_Small::PerformLayout() diff --git a/src/game/client/swarm/vgui/nb_main_panel.cpp b/src/game/client/swarm/vgui/nb_main_panel.cpp index 06290cae9..7425f4bde 100644 --- a/src/game/client/swarm/vgui/nb_main_panel.cpp +++ b/src/game/client/swarm/vgui/nb_main_panel.cpp @@ -39,7 +39,6 @@ // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" - #define CHAT_BUTTON_ICON "vgui/briefing/chat_icon" #define VOTE_BUTTON_ICON "vgui/briefing/vote_icon" #define LEADERBOARD_BUTTON_ICON "vgui/briefing/leaderboard_icon" @@ -131,9 +130,15 @@ CNB_Main_Panel::CNB_Main_Panel( vgui::Panel *parent, const char *name ) : BaseCl m_bLobbyValidityChecked = false; + // Create the TraceMe button + m_pTraceMeButton = new CBitmapButton(this, "TraceMeButton", ""); + m_pTraceMeButton->AddActionSignalTarget(this); + m_pTraceMeButton->SetCommand("TraceMePressed"); + GetControllerFocus()->AddToFocusList( m_pChatButton ); GetControllerFocus()->AddToFocusList( m_pVoteButton ); GetControllerFocus()->AddToFocusList( m_pLeaderboardButton ); + GetControllerFocus()->AddToFocusList(m_pTraceMeButton); GetControllerFocus()->AddToFocusList( m_pAddBotButton ); GetControllerFocus()->AddToFocusList( m_pDeselectMarinesButton ); } @@ -143,6 +148,7 @@ CNB_Main_Panel::~CNB_Main_Panel() GetControllerFocus()->RemoveFromFocusList( m_pChatButton ); GetControllerFocus()->RemoveFromFocusList( m_pVoteButton ); GetControllerFocus()->RemoveFromFocusList( m_pLeaderboardButton ); + GetControllerFocus()->RemoveFromFocusList(m_pTraceMeButton); GetControllerFocus()->RemoveFromFocusList( m_pAddBotButton ); GetControllerFocus()->RemoveFromFocusList( m_pDeselectMarinesButton ); } @@ -161,14 +167,22 @@ void CNB_Main_Panel::OnFinishedSpendingSkillPoints() ProcessSkillSpendQueue(); } -void CNB_Main_Panel::ApplySchemeSettings( vgui::IScheme *pScheme ) +void CNB_Main_Panel::ApplySchemeSettings(vgui::IScheme* pScheme) { - BaseClass::ApplySchemeSettings( pScheme ); - - if ( rd_legacy_ui.GetString()[0] != '\0' ) - LoadControlSettings( "resource/ui/nb_main_panel.res" ); + BaseClass::ApplySchemeSettings(pScheme); + + // Unless we have clearly specified a correct scheme, we will use the default scheme for the game. + auto currentScheme = rd_legacy_ui.GetString(); + if (!Q_stricmp(currentScheme, "'2004") + || !Q_stricmp(currentScheme, "'2010") + || !Q_stricmp(currentScheme, "'2017")) + { + LoadControlSettings("resource/ui/nb_main_panel.res"); + } else - LoadControlSettings( "resource/ui/nb_main_panel_2024.res" ); + { + LoadControlSettings("resource/ui/nb_main_panel_2024.res"); + } color32 white; white.r = 255; @@ -182,20 +196,25 @@ void CNB_Main_Panel::ApplySchemeSettings( vgui::IScheme *pScheme ) grey.b = 190; grey.a = 255; - m_pChatButton->SetImage( CBitmapButton::BUTTON_ENABLED, CHAT_BUTTON_ICON, grey ); - m_pChatButton->SetImage( CBitmapButton::BUTTON_DISABLED, CHAT_BUTTON_ICON, grey ); - m_pChatButton->SetImage( CBitmapButton::BUTTON_PRESSED, CHAT_BUTTON_ICON, white ); - m_pChatButton->SetImage( CBitmapButton::BUTTON_ENABLED_MOUSE_OVER, CHAT_BUTTON_ICON, white ); + m_pChatButton->SetImage(CBitmapButton::BUTTON_ENABLED, CHAT_BUTTON_ICON, grey); + m_pChatButton->SetImage(CBitmapButton::BUTTON_DISABLED, CHAT_BUTTON_ICON, grey); + m_pChatButton->SetImage(CBitmapButton::BUTTON_PRESSED, CHAT_BUTTON_ICON, white); + m_pChatButton->SetImage(CBitmapButton::BUTTON_ENABLED_MOUSE_OVER, CHAT_BUTTON_ICON, white); - m_pVoteButton->SetImage( CBitmapButton::BUTTON_ENABLED, VOTE_BUTTON_ICON, grey ); - m_pVoteButton->SetImage( CBitmapButton::BUTTON_DISABLED, VOTE_BUTTON_ICON, grey ); - m_pVoteButton->SetImage( CBitmapButton::BUTTON_PRESSED, VOTE_BUTTON_ICON, white ); - m_pVoteButton->SetImage( CBitmapButton::BUTTON_ENABLED_MOUSE_OVER, VOTE_BUTTON_ICON, white ); + m_pVoteButton->SetImage(CBitmapButton::BUTTON_ENABLED, VOTE_BUTTON_ICON, grey); + m_pVoteButton->SetImage(CBitmapButton::BUTTON_DISABLED, VOTE_BUTTON_ICON, grey); + m_pVoteButton->SetImage(CBitmapButton::BUTTON_PRESSED, VOTE_BUTTON_ICON, white); + m_pVoteButton->SetImage(CBitmapButton::BUTTON_ENABLED_MOUSE_OVER, VOTE_BUTTON_ICON, white); - m_pLeaderboardButton->SetImage( CBitmapButton::BUTTON_ENABLED, LEADERBOARD_BUTTON_ICON, grey ); - m_pLeaderboardButton->SetImage( CBitmapButton::BUTTON_DISABLED, LEADERBOARD_BUTTON_ICON, grey ); - m_pLeaderboardButton->SetImage( CBitmapButton::BUTTON_PRESSED, LEADERBOARD_BUTTON_ICON, white ); - m_pLeaderboardButton->SetImage( CBitmapButton::BUTTON_ENABLED_MOUSE_OVER, LEADERBOARD_BUTTON_ICON, white ); + m_pLeaderboardButton->SetImage(CBitmapButton::BUTTON_ENABLED, LEADERBOARD_BUTTON_ICON, grey); + m_pLeaderboardButton->SetImage(CBitmapButton::BUTTON_DISABLED, LEADERBOARD_BUTTON_ICON, grey); + m_pLeaderboardButton->SetImage(CBitmapButton::BUTTON_PRESSED, LEADERBOARD_BUTTON_ICON, white); + m_pLeaderboardButton->SetImage(CBitmapButton::BUTTON_ENABLED_MOUSE_OVER, LEADERBOARD_BUTTON_ICON, white); + + m_pTraceMeButton->SetImage(CBitmapButton::BUTTON_ENABLED, "vgui/briefing/trace_me_icon_on", grey); + m_pTraceMeButton->SetImage(CBitmapButton::BUTTON_DISABLED, "vgui/briefing/trace_me_icon_on", grey); + m_pTraceMeButton->SetImage(CBitmapButton::BUTTON_PRESSED, "vgui/briefing/trace_me_icon_pressed", white); + m_pTraceMeButton->SetImage(CBitmapButton::BUTTON_ENABLED_MOUSE_OVER, "vgui/briefing/trace_me_icon_mouse_over", white); m_pAddBotButton->SetImage(CBitmapButton::BUTTON_ENABLED, ADDBOT_BUTTON_ICON, grey); m_pAddBotButton->SetImage(CBitmapButton::BUTTON_DISABLED, ADDBOT_BUTTON_ICON, grey); @@ -326,6 +345,23 @@ void CNB_Main_Panel::OnThink() } } } + if (m_pTraceMeButton) + { + // Check if the TraceMe button should be enabled or not + // It should be enabled if it's an online game, the slot is the local player's slot, the slot is not a bot, the slot is occupied, and the marine profile exists + int m_nLobbySlot = m_pLobbyRow0->m_nLobbySlot; + if (!Briefing() + || Briefing()->IsOfflineGame() + || !Briefing()->IsLobbySlotLocal(m_nLobbySlot) + || Briefing()->IsLobbySlotBot(m_nLobbySlot) + || !Briefing()->IsLobbySlotOccupied(m_nLobbySlot) + || Briefing()->GetMarineProfile(m_nLobbySlot) == NULL) + { + m_pTraceMeButton->SetVisible(false); + return; + } + m_pTraceMeButton->SetVisible(true); + } } void CNB_Main_Panel::OnTick() @@ -497,36 +533,36 @@ void CNB_Main_Panel::SpendSkillPointsOnMarine( int nProfileIndex ) extern vgui::DHANDLE g_hBriefingFrame; -void CNB_Main_Panel::OnCommand( const char *command ) +void CNB_Main_Panel::OnCommand(const char* command) { - if ( !Q_stricmp( command, "ReadyButton" ) ) + if (!Q_stricmp(command, "ReadyButton")) { // Firstly check if we are in the deathmatch - if ( ASWDeathmatchMode() ) + if (ASWDeathmatchMode()) { // because briefing frame fades out slowly a user can click the // Ready button one more time and get a crash here, so we do this check - if ( g_hBriefingFrame.Get() ) + if (g_hBriefingFrame.Get()) { // for DM we only close the briefing panel - g_hBriefingFrame->SetDeleteSelfOnClose( true ); + g_hBriefingFrame->SetDeleteSelfOnClose(true); g_hBriefingFrame->Close(); g_hBriefingFrame = NULL; } } - else if ( m_bLocalLeader ) + else if (m_bLocalLeader) { - if ( Briefing()->CheckMissionRequirements() ) + if (Briefing()->CheckMissionRequirements()) { - if ( Briefing()->AreOtherPlayersReady() ) + if (Briefing()->AreOtherPlayersReady()) { Briefing()->StartMission(); } else { // force other players to be ready? - engine->ClientCmd( "cl_wants_start" ); // notify other players that we're waiting on them - new ForceReadyPanel( GetParent(), "ForceReady", "#asw_force_startm", ASW_FR_BRIEFING ); // TODO: this breaks the IBriefing abstraction, fix it if we need that + engine->ClientCmd("cl_wants_start"); // notify other players that we're waiting on them + new ForceReadyPanel(GetParent(), "ForceReady", "#asw_force_startm", ASW_FR_BRIEFING); // TODO: this breaks the IBriefing abstraction, fix it if we need that } } } @@ -535,55 +571,59 @@ void CNB_Main_Panel::OnCommand( const char *command ) Briefing()->ToggleLocalPlayerReady(); } } - else if ( !Q_stricmp( command, "FriendsButton" ) ) + else if (!Q_stricmp(command, "FriendsButton")) { #ifndef _X360 - if ( BaseModUI::CUIGameData::Get() ) + if (BaseModUI::CUIGameData::Get()) { - BaseModUI::CUIGameData::Get()->OpenInviteUI( "friends" ); + BaseModUI::CUIGameData::Get()->OpenInviteUI("friends"); } #endif } - else if ( !Q_stricmp( command, "ChangeMissionButton" ) ) + else if (!Q_stricmp(command, "ChangeMissionButton")) { - engine->ClientCmd( "asw_mission_chooser callvote" ); + engine->ClientCmd("asw_mission_chooser callvote"); } - else if ( !Q_stricmp( command, "MissionDetailsButton" ) ) + else if (!Q_stricmp(command, "MissionDetailsButton")) { ShowMissionDetails(); } - else if ( !Q_stricmp( command, "ChatButton" ) ) + else if (!Q_stricmp(command, "ChatButton")) { - if ( GetClientModeASW() ) + if (GetClientModeASW()) { GetClientModeASW()->ToggleMessageMode(); } } - else if ( !Q_stricmp( command, "VoteButton" ) ) + else if (!Q_stricmp(command, "VoteButton")) { - engine->ClientCmd( "playerlist" ); + engine->ClientCmd("playerlist"); } - else if ( !Q_stricmp( command, "LeaderboardButton" ) ) + else if (!Q_stricmp(command, "LeaderboardButton")) { ShowLeaderboard(); } - else if ( !Q_stricmp( command, "AddBotButton" ) ) + else if (!Q_stricmp(command, "AddBotButton")) { AddBot(); } - else if ( !Q_stricmp( command, "DeselectMarines" ) ) + else if (!Q_stricmp(command, "DeselectMarines")) { - engine->ClientCmd( "cl_dselectallm" ); + engine->ClientCmd("cl_dselectallm"); } - else if ( !Q_stricmp( command, "PromotionButton" ) ) + else if (!Q_stricmp(command, "PromotionButton")) { ShowPromotionPanel(); } - else if ( !Q_stricmp( command, "TeamChangeButton" ) ) + else if (!Q_stricmp(command, "TeamChangeButton")) + { + engine->ServerCmd("rd_team_change"); + } + else if (!Q_stricmp(command, "TraceMePressed")) { - engine->ServerCmd( "rd_team_change" ); + TraceMePressed(); } - BaseClass::OnCommand( command ); + BaseClass::OnCommand(command); } @@ -626,3 +666,31 @@ void CNB_Main_Panel::ShowLeaderboard() m_hSubScreen = pPanel; } + +void CNB_Main_Panel::TraceMePressed() +{ + // Get the local player index + int localPlayerIndex = -1; + if (engine && engine->IsInGame()) + { + localPlayerIndex = engine->GetLocalPlayer(); + if (localPlayerIndex < 0 || localPlayerIndex >= gpGlobals->maxClients) + { + return; // Invalid player index + } + + if (lastTraceMePressedTime < 0 || (lastTraceMePressedTime + 30.0) <= gpGlobals->curtime) + { + lastTraceMePressedTime = gpGlobals->curtime; // Prevent spamming the command + char cmd[128]; + Q_snprintf(cmd, sizeof(cmd), "rd_lobby_suggest_trace_player %d", localPlayerIndex); + // Send a message in chat to all other players to suggest them to trace this player + engine->ClientCmd_Unrestricted(cmd); + } + else + { + ClientPrint(CBasePlayer::GetLocalPlayer(), HUD_PRINTTALK, "asw_trace_me_cooling_down"); + } + } +} + diff --git a/src/game/client/swarm/vgui/nb_main_panel.h b/src/game/client/swarm/vgui/nb_main_panel.h index 7b9c6ee21..40bb1f27d 100644 --- a/src/game/client/swarm/vgui/nb_main_panel.h +++ b/src/game/client/swarm/vgui/nb_main_panel.h @@ -45,6 +45,7 @@ class CNB_Main_Panel : public vgui::EditablePanel void ShowMissionDetails(); void ShowPromotionPanel(); void ShowLeaderboard(); + void TraceMePressed(); vgui::DHANDLE m_hSubScreen; @@ -72,6 +73,9 @@ class CNB_Main_Panel : public vgui::EditablePanel CBitmapButton *m_pAddBotButton; CBitmapButton *m_pDeselectMarinesButton; + float lastTraceMePressedTime = -1.0f; + CBitmapButton* m_pTraceMeButton; + bool m_bLocalLeader; uint64 m_FlyoutSteamID; From a237d6021a2fb2e005804634c38f5d60a6c1a8e2 Mon Sep 17 00:00:00 2001 From: ywgATustcbbs Date: Tue, 8 Jul 2025 09:16:56 +0800 Subject: [PATCH 06/13] use arrow for tracing --- src/game/client/swarm/c_asw_marine.cpp | 2 +- src/game/client/swarm/vgui/asw_hud_emotes.cpp | 45 +++++++++++-------- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/game/client/swarm/c_asw_marine.cpp b/src/game/client/swarm/c_asw_marine.cpp index 5bb62d4d6..9d1fa94bd 100644 --- a/src/game/client/swarm/c_asw_marine.cpp +++ b/src/game/client/swarm/c_asw_marine.cpp @@ -994,7 +994,7 @@ void C_ASW_Marine::TickTracePlayerMovement(float d) m_nTraceSkip--; if ( m_nTraceSkip > 0 ) return; - m_nTraceSkip = 20; + m_nTraceSkip = 30; // get current marine position struct TracePlayerMovement_t movement; movement.m_flTraceTime = TRACE_FADE_TIME; diff --git a/src/game/client/swarm/vgui/asw_hud_emotes.cpp b/src/game/client/swarm/vgui/asw_hud_emotes.cpp index 203632714..f99a43f7f 100644 --- a/src/game/client/swarm/vgui/asw_hud_emotes.cpp +++ b/src/game/client/swarm/vgui/asw_hud_emotes.cpp @@ -1,4 +1,3 @@ - #include "cbase.h" #include "hud.h" #include "hud_macros.h" @@ -86,7 +85,7 @@ class CASWHudEmotes : public CASW_HudElement, public vgui::Panel CPanelAnimationVarAliasType( int, m_nHackTexture, "HackTexture", "vgui/swarm/ClassIcons/HackIcon", "textureid" ); CPanelAnimationVarAliasType( int, m_nWeldTexture, "WeldTexture", "vgui/swarm/ClassIcons/WeldIcon", "textureid" ); CPanelAnimationVarAliasType( int, m_nReviveMarineTexture, "ReviveMarineTexture", "vgui/swarm/ClassIcons/revivemarine", "textureid" ); - CPanelAnimationVarAliasType(int, m_nTraceTexture, "TraceTexture", "vgui/icon_arrow_down", "textureid"); + CPanelAnimationVarAliasType(int, m_nTraceTexture, "TraceTexture", "vgui/arrow_right", "textureid"); }; DECLARE_HUDELEMENT( CASWHudEmotes ); @@ -325,6 +324,19 @@ void CASWHudEmotes::PaintTracesFor(C_ASW_Marine* pMarine) { iterNext++; } + + int omx, omy; + float fAlpha, fTraceRatio, xPos, yPos, angleRad, angleDeg; + float fScale = (ScreenHeight() / 768.0f); + float HalfW = 16.0f * fScale; + float HalfH = 16.0f * fScale; + Vector vecPosition, vecPositionNext, screenPos, screenPosNext, vecTargetDirection; + + Vector vecCameraFocus; + QAngle cameraAngle; + + ASWInput()->ASW_GetCameraLocation(C_ASW_Player::GetLocalASWPlayer(), vecCameraFocus, cameraAngle, omx, omy, false); + for (; iter != pMarine->m_lstTracePlayerMovementList.end() && iterNext != pMarine->m_lstTracePlayerMovementList.end(); ++iter, ++iterNext) { float fTraceRatio = (*iter).m_flTraceTime / TRACE_FADE_TIME; @@ -338,7 +350,7 @@ void CASWHudEmotes::PaintTracesFor(C_ASW_Marine* pMarine) // draw a circle at the position of the trace in world space // and fade it out over time - float fAlpha = (fTraceRatio + fTimeRatio) - (int)(fTraceRatio + fTimeRatio); + fAlpha = (fTraceRatio + fTimeRatio) - (int)(fTraceRatio + fTimeRatio); if (fAlpha > 1.0 / 3.0 || fAlpha <= 0.01) { continue; @@ -347,30 +359,28 @@ void CASWHudEmotes::PaintTracesFor(C_ASW_Marine* pMarine) { fAlpha = pow(3.0 * fAlpha, 2.2); } - int iTexture = m_nTraceTexture; - Vector screenPos; - Vector screenPosNext; + if (!debugoverlay->ScreenPosition(vecPosition, screenPos) && !debugoverlay->ScreenPosition(vecPositionNext, screenPosNext)) { - float xPos = screenPos[0]; - float yPos = screenPos[1]; - Vector vecTargetDirection = vecPositionNext - vecPosition; + xPos = screenPos[0]; + yPos = screenPos[1]; + vecTargetDirection = vecPositionNext - vecPosition; vecTargetDirection.z = 0; if (vecTargetDirection.NormalizeInPlace() < 0.01) { continue; // no direction to draw } - if (iTexture != -1) + if (m_nTraceTexture != -1) { - float fScale = (ScreenHeight() / 768.0f); - float HalfW = 16.0f * fScale; - float HalfH = 16.0f * fScale; - surface()->DrawSetColor(Color(255, 255, 255, fAlpha * fOpacity * 255.0f)); - surface()->DrawSetTexture(iTexture); + surface()->DrawSetTexture(m_nTraceTexture); + + angleRad = atan2(vecTargetDirection.y, vecTargetDirection.x); + angleDeg = RAD2DEG(angleRad); + + QAngle angFacing(0, -angleDeg + cameraAngle.y - 90, 0); - float fFacingYaw = -UTIL_VecToYaw(vecTargetDirection); Vector vecCornerTL(-HalfW, -HalfH, 0); Vector vecCornerTR(HalfW, -HalfH, 0); Vector vecCornerBR(HalfW, HalfH, 0); @@ -378,12 +388,11 @@ void CASWHudEmotes::PaintTracesFor(C_ASW_Marine* pMarine) Vector vecCornerTL_rotated, vecCornerTR_rotated, vecCornerBR_rotated, vecCornerBL_rotated; // rotate it by our facing yaw - QAngle angFacing(0, -fFacingYaw, 0); VectorRotate(vecCornerTL, angFacing, vecCornerTL_rotated); VectorRotate(vecCornerTR, angFacing, vecCornerTR_rotated); VectorRotate(vecCornerBR, angFacing, vecCornerBR_rotated); VectorRotate(vecCornerBL, angFacing, vecCornerBL_rotated); - + Vertex_t points[4] = { Vertex_t(Vector2D(xPos + vecCornerTL_rotated.x, yPos + vecCornerTL_rotated.y), From fd134f6e19414deed582cc0d82ef4b24ec981e35 Mon Sep 17 00:00:00 2001 From: ywgATustcbbs Date: Wed, 9 Jul 2025 02:19:54 +0800 Subject: [PATCH 07/13] fix mistakes in ApplySchemeSettings() --- src/game/client/swarm/c_asw_marine.cpp | 2 +- src/game/client/swarm/vgui/nb_lobby_row.cpp | 310 +++++++++--------- src/game/client/swarm/vgui/nb_lobby_row.h | 4 +- .../client/swarm/vgui/nb_lobby_row_small.cpp | 6 +- src/game/client/swarm/vgui/nb_main_panel.cpp | 6 +- 5 files changed, 158 insertions(+), 170 deletions(-) diff --git a/src/game/client/swarm/c_asw_marine.cpp b/src/game/client/swarm/c_asw_marine.cpp index 9d1fa94bd..ce3f1e65b 100644 --- a/src/game/client/swarm/c_asw_marine.cpp +++ b/src/game/client/swarm/c_asw_marine.cpp @@ -108,7 +108,7 @@ extern ConVar rd_team_color_enemy; extern float g_fMarinePoisonDuration; #ifdef CLIENT_DLL -std::vector g_bShouldTracePlayer = std::vector(MAX_PLAYERS, true); // whether we have a trace position for this player +std::vector g_bShouldTracePlayer = std::vector(MAX_PLAYERS, false); // whether we have a trace position for this player float TRACE_FADE_TIME = 60.0f; // how long to keep the trace positions for ConVar cl_trace_player_max_targets("cl_trace_player_max_targets", "3", FCVAR_ARCHIVE | FCVAR_CLIENTDLL, "Maximum number of players to trace positions for in the client.", true, 1.0f, true, 7.0f); ConVar cl_trace_player_opacity("cl_trace_player_opacity", "0.5", FCVAR_ARCHIVE | FCVAR_CLIENTDLL, "Opacity of the player trace positions in the client. 0.0 means fully transparent, 1.0 means fully opaque.", true, 0.0f, true, 1.0f); diff --git a/src/game/client/swarm/vgui/nb_lobby_row.cpp b/src/game/client/swarm/vgui/nb_lobby_row.cpp index b1c298396..493b11300 100644 --- a/src/game/client/swarm/vgui/nb_lobby_row.cpp +++ b/src/game/client/swarm/vgui/nb_lobby_row.cpp @@ -103,23 +103,13 @@ CNB_Lobby_Row::CNB_Lobby_Row( vgui::Panel *parent, const char *name ) : BaseClas m_pXPBar->m_flBorder = 1.5f; m_nLobbySlot = 0; - color32 lightblue; - lightblue.r = 66; - lightblue.g = 142; - lightblue.b = 192; - lightblue.a = 255; - lightblue.r = 255; - lightblue.g = 255; - lightblue.b = 255; - lightblue.a = 255; - // Create the TracePlayerButton m_pTracePlayerButton = new CBitmapButton( this, "TracePlayerButton", "" ); m_pTracePlayerButton->AddActionSignalTarget( this ); m_pTracePlayerButton->SetCommand( "TracePlayerPressed" ); - m_pTracePlayerButton->SetImage(CBitmapButton::BUTTON_ENABLED, "vgui/briefing/trace_player_icon_off", lightblue); - m_pTracePlayerButton->SetImage(CBitmapButton::BUTTON_PRESSED, "vgui/briefing/trace_player_icon_pressed", lightblue); - m_pTracePlayerButton->SetImage(CBitmapButton::BUTTON_ENABLED_MOUSE_OVER, "vgui/briefing/trace_player_icon_mouse_over", lightblue); + m_pTracePlayerButton->SetImage(CBitmapButton::BUTTON_ENABLED, "vgui/briefing/trace_player_icon_off", color32{ 255, 255, 255, 255 }); + m_pTracePlayerButton->SetImage(CBitmapButton::BUTTON_PRESSED, "vgui/briefing/trace_player_icon_pressed", color32{ 255, 255, 255, 255 }); + m_pTracePlayerButton->SetImage(CBitmapButton::BUTTON_ENABLED_MOUSE_OVER, "vgui/briefing/trace_player_icon_mouse_over", color32{ 255, 255, 255, 255 }); GetControllerFocus()->AddToFocusList( m_pPortraitButton ); @@ -144,9 +134,9 @@ void CNB_Lobby_Row::ApplySchemeSettings(vgui::IScheme* pScheme) // Unless we have clearly specified a correct scheme, we will use the default scheme for the game. auto currentScheme = rd_legacy_ui.GetString(); - if (!Q_stricmp(currentScheme, "'2004") - || !Q_stricmp(currentScheme, "'2010") - || !Q_stricmp(currentScheme, "'2017")) + if (!Q_stricmp(currentScheme, "2004") + || !Q_stricmp(currentScheme, "2010") + || !Q_stricmp(currentScheme, "2017")) { LoadControlSettings("resource/ui/nb_lobby_row.res"); } @@ -160,6 +150,10 @@ void CNB_Lobby_Row::ApplySchemeSettings(vgui::IScheme* pScheme) } m_szLastPortraitImage[0] = 0; m_lastSteamID.Set(0, k_EUniverseInvalid, k_EAccountTypeInvalid); + + m_pTracePlayerButton->SetImage(CBitmapButton::BUTTON_ENABLED, "vgui/briefing/trace_player_icon_off", color32{ 255, 255, 255, 255 }); + m_pTracePlayerButton->SetImage(CBitmapButton::BUTTON_PRESSED, "vgui/briefing/trace_player_icon_pressed", color32{ 255, 255, 255, 255 }); + m_pTracePlayerButton->SetImage(CBitmapButton::BUTTON_ENABLED_MOUSE_OVER, "vgui/briefing/trace_player_icon_mouse_over", color32{ 255, 255, 255, 255 }); } void CNB_Lobby_Row::PerformLayout() @@ -173,7 +167,6 @@ void CNB_Lobby_Row::OnThink() UpdateDetails(); UpdateChangingSlot(); - UpdateTracePlayerButton(); // Update the TracePlayer button state } void CNB_Lobby_Row::UpdateDetails() @@ -184,44 +177,44 @@ void CNB_Lobby_Row::UpdateDetails() white.b = 255; white.a = 255; - m_pVoiceIcon->SetVisible( Briefing()->IsCommanderSpeaking( m_nLobbySlot ) ); + m_pVoiceIcon->SetVisible(Briefing()->IsCommanderSpeaking(m_nLobbySlot)); - if ( m_nLobbySlot == -1 || !Briefing()->IsLobbySlotOccupied( m_nLobbySlot ) ) + if (m_nLobbySlot == -1 || !Briefing()->IsLobbySlotOccupied(m_nLobbySlot)) { - m_pXPBar->SetVisible( false ); - m_pLevelLabel->SetVisible( false ); - m_pPromotionIcon->SetVisible( false ); - for ( int i = 0; i < NELEMS( m_pMedalIcon ); i++ ) + m_pXPBar->SetVisible(false); + m_pLevelLabel->SetVisible(false); + m_pPromotionIcon->SetVisible(false); + for (int i = 0; i < NELEMS(m_pMedalIcon); i++) { - m_pMedalIcon[i]->SetVisible( false ); + m_pMedalIcon[i]->SetVisible(false); m_lastMedal[i] = 0; } - m_pNameDropdown->SetVisible( false ); - m_pAvatarImage->SetVisible( false ); - m_pClassLabel->SetVisible( false ); - m_pClassImage->SetVisible( false ); + m_pNameDropdown->SetVisible(false); + m_pAvatarImage->SetVisible(false); + m_pClassLabel->SetVisible(false); + m_pClassImage->SetVisible(false); - if ( Briefing()->IsOfflineGame() ) + if (Briefing()->IsOfflineGame()) { // in singleplayer, empty slots show the empty portrait button - const char *szEmptyFace = "vgui/briefing/face_empty"; - const char *szEmptyFaceLit = "vgui/briefing/face_empty_lit"; - if ( Q_strcmp( szEmptyFace, m_szLastPortraitImage ) ) + const char* szEmptyFace = "vgui/briefing/face_empty"; + const char* szEmptyFaceLit = "vgui/briefing/face_empty_lit"; + if (Q_strcmp(szEmptyFace, m_szLastPortraitImage)) { - Q_snprintf( m_szLastPortraitImage, sizeof( m_szLastPortraitImage ), "%s", szEmptyFace ); - m_pPortraitButton->SetImage( CBitmapButton::BUTTON_ENABLED, szEmptyFace, white ); - m_pPortraitButton->SetImage( CBitmapButton::BUTTON_PRESSED, szEmptyFace, white ); + Q_snprintf(m_szLastPortraitImage, sizeof(m_szLastPortraitImage), "%s", szEmptyFace); + m_pPortraitButton->SetImage(CBitmapButton::BUTTON_ENABLED, szEmptyFace, white); + m_pPortraitButton->SetImage(CBitmapButton::BUTTON_PRESSED, szEmptyFace, white); - if ( Briefing()->IsLobbySlotLocal( m_nLobbySlot ) ) + if (Briefing()->IsLobbySlotLocal(m_nLobbySlot)) { - m_pPortraitButton->SetImage( CBitmapButton::BUTTON_ENABLED_MOUSE_OVER, szEmptyFaceLit, white ); + m_pPortraitButton->SetImage(CBitmapButton::BUTTON_ENABLED_MOUSE_OVER, szEmptyFaceLit, white); } else { - m_pPortraitButton->SetImage( CBitmapButton::BUTTON_ENABLED_MOUSE_OVER, szEmptyFace, white ); + m_pPortraitButton->SetImage(CBitmapButton::BUTTON_ENABLED_MOUSE_OVER, szEmptyFace, white); } } - m_pPortraitButton->SetVisible( true ); + m_pPortraitButton->SetVisible(true); } else { @@ -241,43 +234,43 @@ void CNB_Lobby_Row::UpdateDetails() lightblue.b = 192; lightblue.a = 255; - BaseModHybridButton *pButton = m_pNameDropdown->GetButton(); - if ( pButton ) + BaseModHybridButton* pButton = m_pNameDropdown->GetButton(); + if (pButton) { - pButton->SetText( Briefing()->GetMarineOrPlayerName( m_nLobbySlot ) ); + pButton->SetText(Briefing()->GetMarineOrPlayerName(m_nLobbySlot)); } - m_pNameDropdown->SetVisible( true ); + m_pNameDropdown->SetVisible(true); #if !defined(NO_STEAM) - CSteamID steamID = Briefing()->GetCommanderSteamID( m_nLobbySlot ); - if ( steamID.IsValid() ) + CSteamID steamID = Briefing()->GetCommanderSteamID(m_nLobbySlot); + if (steamID.IsValid()) { - if ( steamID.ConvertToUint64() != m_lastSteamID.ConvertToUint64() ) + if (steamID.ConvertToUint64() != m_lastSteamID.ConvertToUint64()) { - m_pAvatarImage->SetAvatarBySteamID( &steamID ); + m_pAvatarImage->SetAvatarBySteamID(&steamID); - for ( int i = 0; i < NELEMS( m_pMedalIcon ); i++ ) + for (int i = 0; i < NELEMS(m_pMedalIcon); i++) { - m_pMedalIcon[i]->SetVisible( false ); + m_pMedalIcon[i]->SetVisible(false); m_lastMedal[i] = 0; } } m_lastSteamID = steamID; - for ( int i = 0; i < NELEMS( m_pMedalIcon ); i++ ) + for (int i = 0; i < NELEMS(m_pMedalIcon); i++) { - const C_RD_ItemInstance &medal = Briefing()->GetEquippedMedal( m_nLobbySlot, i ); - if ( medal.m_iItemDefID != m_lastMedal[i] ) + const C_RD_ItemInstance& medal = Briefing()->GetEquippedMedal(m_nLobbySlot, i); + if (medal.m_iItemDefID != m_lastMedal[i]) { - if ( !medal.IsSet() ) + if (!medal.IsSet()) { - m_pMedalIcon[i]->SetVisible( false ); + m_pMedalIcon[i]->SetVisible(false); m_lastMedal[i] = medal.m_iItemDefID; } else { - m_pMedalIcon[i]->SetImage( medal.GetIcon() ); - m_pMedalIcon[i]->SetVisible( true ); + m_pMedalIcon[i]->SetImage(medal.GetIcon()); + m_pMedalIcon[i]->SetVisible(true); m_lastMedal[i] = medal.m_iItemDefID; } } @@ -285,181 +278,196 @@ void CNB_Lobby_Row::UpdateDetails() } #endif - int nLevel = Briefing()->GetCommanderLevel( m_nLobbySlot ) + 1; // levels start from 0 in code, but present as 1 - int nXP = Briefing()->GetCommanderXP( m_nLobbySlot ); - int nPromotion = Briefing()->GetCommanderPromotion( m_nLobbySlot ); + int nLevel = Briefing()->GetCommanderLevel(m_nLobbySlot) + 1; // levels start from 0 in code, but present as 1 + int nXP = Briefing()->GetCommanderXP(m_nLobbySlot); + int nPromotion = Briefing()->GetCommanderPromotion(m_nLobbySlot); - if ( nPromotion <= 0 || nPromotion > ASW_PROMOTION_CAP ) + if (nPromotion <= 0 || nPromotion > ASW_PROMOTION_CAP) { - m_pPromotionIcon->SetVisible( false ); + m_pPromotionIcon->SetVisible(false); m_nLastPromotion = 0; } else { - m_pPromotionIcon->SetVisible( true ); - m_pPromotionIcon->SetImage( VarArgs( "briefing/promotion_%d", nPromotion ) ); + m_pPromotionIcon->SetVisible(true); + m_pPromotionIcon->SetImage(VarArgs("briefing/promotion_%d", nPromotion)); m_nLastPromotion = nPromotion; } m_pXPBar->ClearMinMax(); - m_pXPBar->AddMinMax( 0, g_iLevelExperience[0] * g_flPromotionXPScale[m_nLastPromotion] ); - for ( int i = 0; i < ASW_NUM_EXPERIENCE_LEVELS - 1; i++ ) + m_pXPBar->AddMinMax(0, g_iLevelExperience[0] * g_flPromotionXPScale[m_nLastPromotion]); + for (int i = 0; i < ASW_NUM_EXPERIENCE_LEVELS - 1; i++) { - m_pXPBar->AddMinMax( g_iLevelExperience[i] * g_flPromotionXPScale[m_nLastPromotion], g_iLevelExperience[i + 1] * g_flPromotionXPScale[m_nLastPromotion] ); + m_pXPBar->AddMinMax(g_iLevelExperience[i] * g_flPromotionXPScale[m_nLastPromotion], g_iLevelExperience[i + 1] * g_flPromotionXPScale[m_nLastPromotion]); } - if ( !Briefing()->IsFullyConnected( m_nLobbySlot ) ) + if (!Briefing()->IsFullyConnected(m_nLobbySlot)) { - m_pXPBar->SetVisible( false ); - m_pLevelLabel->SetVisible( true ); - m_pLevelLabel->SetText( "#nb_commander_connecting" ); + m_pXPBar->SetVisible(false); + m_pLevelLabel->SetVisible(true); + m_pLevelLabel->SetText("#nb_commander_connecting"); } - else if ( nLevel == -1 || nXP == -1 ) + else if (nLevel == -1 || nXP == -1) { - m_pXPBar->SetVisible( false ); - m_pLevelLabel->SetVisible( false ); + m_pXPBar->SetVisible(false); + m_pLevelLabel->SetVisible(false); } else { - m_pXPBar->SetVisible( true ); - m_pLevelLabel->SetVisible( true ); + m_pXPBar->SetVisible(true); + m_pLevelLabel->SetVisible(true); - m_pXPBar->Init( nXP, nXP, 1.0, true, false ); + m_pXPBar->Init(nXP, nXP, 1.0, true, false); wchar_t szLevelNum[16] = L""; - V_snwprintf( szLevelNum, ARRAYSIZE( szLevelNum ), L"%i", nLevel ); + V_snwprintf(szLevelNum, ARRAYSIZE(szLevelNum), L"%i", nLevel); wchar_t wzLevelLabel[64]; - g_pVGuiLocalize->ConstructString( wzLevelLabel, sizeof( wzLevelLabel ), g_pVGuiLocalize->Find( "#nb_commander_level" ), 1, szLevelNum ); - m_pLevelLabel->SetText( wzLevelLabel ); + g_pVGuiLocalize->ConstructString(wzLevelLabel, sizeof(wzLevelLabel), g_pVGuiLocalize->Find("#nb_commander_level"), 1, szLevelNum); + m_pLevelLabel->SetText(wzLevelLabel); } - ASW_Marine_Class nMarineClass = Briefing()->GetMarineClass( m_nLobbySlot ); - m_pClassLabel->SetText( nMarineClass > MARINE_CLASS_UNDEFINED && nMarineClass < NUM_MARINE_CLASSES ? g_szMarineClassLabel[nMarineClass] : "" ); - m_pClassLabel->SetVisible( true ); - if ( nMarineClass > MARINE_CLASS_UNDEFINED && nMarineClass < NUM_MARINE_CLASSES ) + ASW_Marine_Class nMarineClass = Briefing()->GetMarineClass(m_nLobbySlot); + m_pClassLabel->SetText(nMarineClass > MARINE_CLASS_UNDEFINED && nMarineClass < NUM_MARINE_CLASSES ? g_szMarineClassLabel[nMarineClass] : ""); + m_pClassLabel->SetVisible(true); + if (nMarineClass > MARINE_CLASS_UNDEFINED && nMarineClass < NUM_MARINE_CLASSES) { - m_pClassImage->SetImage( g_szMarineClassImage[nMarineClass] ); - m_pClassImage->SetVisible( true ); + m_pClassImage->SetImage(g_szMarineClassImage[nMarineClass]); + m_pClassImage->SetVisible(true); } else { - m_pClassImage->SetVisible( false ); + m_pClassImage->SetVisible(false); } - if ( Briefing()->IsOfflineGame() && m_nLobbySlot != 0 ) + if (Briefing()->IsOfflineGame() && m_nLobbySlot != 0) { // AI slots - m_pLevelLabel->SetVisible( false ); - m_pPromotionIcon->SetVisible( false ); - for ( int i = 0; i < NELEMS( m_pMedalIcon ); i++ ) + m_pLevelLabel->SetVisible(false); + m_pPromotionIcon->SetVisible(false); + for (int i = 0; i < NELEMS(m_pMedalIcon); i++) { - m_pMedalIcon[i]->SetVisible( false ); + m_pMedalIcon[i]->SetVisible(false); m_lastMedal[i] = 0; } - m_pAvatarImage->SetVisible( false ); + m_pAvatarImage->SetVisible(false); int nAvatarX, nAvatarY; - m_pAvatarImage->GetPos( nAvatarX, nAvatarY ); + m_pAvatarImage->GetPos(nAvatarX, nAvatarY); int nNameX, nNameY; - m_pNameDropdown->GetPos( nNameX, nNameY ); + m_pNameDropdown->GetPos(nNameX, nNameY); - m_pNameDropdown->SetPos( nAvatarX + YRES( 5 ), nNameY ); + m_pNameDropdown->SetPos(nAvatarX + YRES(5), nNameY); } else { - m_pAvatarImage->SetVisible( true ); + m_pAvatarImage->SetVisible(true); } - CASW_Marine_Profile *pProfile = Briefing()->GetMarineProfile( m_nLobbySlot ); - if ( !pProfile ) + CASW_Marine_Profile* pProfile = Briefing()->GetMarineProfile(m_nLobbySlot); + if (!pProfile) { // Set to some blank image - const char *szEmptyFace = "vgui/briefing/face_empty"; - const char *szEmptyFaceLit = "vgui/briefing/face_empty_lit"; - if ( Q_strcmp( szEmptyFace, m_szLastPortraitImage ) ) + const char* szEmptyFace = "vgui/briefing/face_empty"; + const char* szEmptyFaceLit = "vgui/briefing/face_empty_lit"; + if (Q_strcmp(szEmptyFace, m_szLastPortraitImage)) { - Q_snprintf( m_szLastPortraitImage, sizeof( m_szLastPortraitImage ), "%s", szEmptyFace ); - m_pPortraitButton->SetImage( CBitmapButton::BUTTON_ENABLED, szEmptyFace, white ); - m_pPortraitButton->SetImage( CBitmapButton::BUTTON_PRESSED, szEmptyFace, white ); + Q_snprintf(m_szLastPortraitImage, sizeof(m_szLastPortraitImage), "%s", szEmptyFace); + m_pPortraitButton->SetImage(CBitmapButton::BUTTON_ENABLED, szEmptyFace, white); + m_pPortraitButton->SetImage(CBitmapButton::BUTTON_PRESSED, szEmptyFace, white); - if ( Briefing()->IsLobbySlotLocal( m_nLobbySlot ) ) + if (Briefing()->IsLobbySlotLocal(m_nLobbySlot)) { - m_pPortraitButton->SetImage( CBitmapButton::BUTTON_ENABLED_MOUSE_OVER, szEmptyFaceLit, white ); + m_pPortraitButton->SetImage(CBitmapButton::BUTTON_ENABLED_MOUSE_OVER, szEmptyFaceLit, white); } else { - m_pPortraitButton->SetImage( CBitmapButton::BUTTON_ENABLED_MOUSE_OVER, szEmptyFace, white ); + m_pPortraitButton->SetImage(CBitmapButton::BUTTON_ENABLED_MOUSE_OVER, szEmptyFace, white); } } } else { char imagename[255]; - Q_snprintf( imagename, sizeof( imagename ), "vgui/briefing/face_%s", pProfile->m_PortraitName ); - if ( Q_strcmp( imagename, m_szLastPortraitImage ) ) + Q_snprintf(imagename, sizeof(imagename), "vgui/briefing/face_%s", pProfile->m_PortraitName); + if (Q_strcmp(imagename, m_szLastPortraitImage)) { - Q_snprintf( m_szLastPortraitImage, sizeof( m_szLastPortraitImage ), "%s", imagename ); - m_pPortraitButton->SetImage( CBitmapButton::BUTTON_ENABLED, imagename, white ); - m_pPortraitButton->SetImage( CBitmapButton::BUTTON_PRESSED, imagename, white ); + Q_snprintf(m_szLastPortraitImage, sizeof(m_szLastPortraitImage), "%s", imagename); + m_pPortraitButton->SetImage(CBitmapButton::BUTTON_ENABLED, imagename, white); + m_pPortraitButton->SetImage(CBitmapButton::BUTTON_PRESSED, imagename, white); - if ( Briefing()->IsLobbySlotLocal( m_nLobbySlot ) ) + if (Briefing()->IsLobbySlotLocal(m_nLobbySlot)) { - Q_snprintf( imagename, sizeof( imagename ), "vgui/briefing/face_%s_lit", pProfile->m_PortraitName ); + Q_snprintf(imagename, sizeof(imagename), "vgui/briefing/face_%s_lit", pProfile->m_PortraitName); } - m_pPortraitButton->SetImage( CBitmapButton::BUTTON_ENABLED_MOUSE_OVER, imagename, white ); + m_pPortraitButton->SetImage(CBitmapButton::BUTTON_ENABLED_MOUSE_OVER, imagename, white); } } - for ( int i = 0; i < ASW_NUM_INVENTORY_SLOTS; i++ ) + for (int i = 0; i < ASW_NUM_INVENTORY_SLOTS; i++) { bool bSetButtonImage = false; - CBitmapButton *pButton = NULL; - vgui::ImagePanel *pSilhouette = NULL; - switch ( i ) + CBitmapButton* pButton = NULL; + vgui::ImagePanel* pSilhouette = NULL; + switch (i) { case ASW_INVENTORY_SLOT_PRIMARY: pButton = m_pWeaponButton0; pSilhouette = m_pSilhouetteWeapon0; break; case ASW_INVENTORY_SLOT_SECONDARY: pButton = m_pWeaponButton1; pSilhouette = m_pSilhouetteWeapon1; break; case ASW_INVENTORY_SLOT_EXTRA: pButton = m_pWeaponButton2; pSilhouette = m_pSilhouetteWeapon2; break; } - Assert( pButton && pSilhouette ); + Assert(pButton && pSilhouette); - int nWeapon = Briefing()->GetMarineSelectedWeapon( m_nLobbySlot, i ); - if ( nWeapon != -1 ) + int nWeapon = Briefing()->GetMarineSelectedWeapon(m_nLobbySlot, i); + if (nWeapon != -1) { - CASW_EquipItem *pItem = g_ASWEquipmentList.GetItemForSlot( i, nWeapon ); - Assert( pItem ); - if ( pItem ) + CASW_EquipItem* pItem = g_ASWEquipmentList.GetItemForSlot(i, nWeapon); + Assert(pItem); + if (pItem) { bSetButtonImage = true; char imagename[255]; - Q_snprintf( imagename, sizeof( imagename ), "vgui/%s", pItem->m_szEquipIcon ); - if ( Q_strcmp( imagename, m_szLastWeaponImage[i] ) ) + Q_snprintf(imagename, sizeof(imagename), "vgui/%s", pItem->m_szEquipIcon); + if (Q_strcmp(imagename, m_szLastWeaponImage[i])) { - Q_snprintf( m_szLastWeaponImage[i], sizeof( m_szLastWeaponImage[i] ), "%s", imagename ); - pButton->SetImage( CBitmapButton::BUTTON_ENABLED, imagename, lightblue ); - pButton->SetImage( CBitmapButton::BUTTON_ENABLED_MOUSE_OVER, imagename, Briefing()->IsLobbySlotLocal( m_nLobbySlot ) ? white : lightblue ); - pButton->SetImage( CBitmapButton::BUTTON_PRESSED, imagename, lightblue ); + Q_snprintf(m_szLastWeaponImage[i], sizeof(m_szLastWeaponImage[i]), "%s", imagename); + pButton->SetImage(CBitmapButton::BUTTON_ENABLED, imagename, lightblue); + pButton->SetImage(CBitmapButton::BUTTON_ENABLED_MOUSE_OVER, imagename, Briefing()->IsLobbySlotLocal(m_nLobbySlot) ? white : lightblue); + pButton->SetImage(CBitmapButton::BUTTON_PRESSED, imagename, lightblue); } } } - if ( !bSetButtonImage ) + if (!bSetButtonImage) { - if ( Q_strcmp( "vgui/white", m_szLastWeaponImage[i] ) ) + if (Q_strcmp("vgui/white", m_szLastWeaponImage[i])) { - Q_snprintf( m_szLastWeaponImage[i], sizeof( m_szLastWeaponImage[i] ), "%s", "vgui/white" ); - pButton->SetImage( CBitmapButton::BUTTON_ENABLED, "vgui/white", invisible ); - pButton->SetImage( CBitmapButton::BUTTON_ENABLED_MOUSE_OVER, "vgui/white", invisible ); - pButton->SetImage( CBitmapButton::BUTTON_PRESSED, "vgui/white", invisible ); + Q_snprintf(m_szLastWeaponImage[i], sizeof(m_szLastWeaponImage[i]), "%s", "vgui/white"); + pButton->SetImage(CBitmapButton::BUTTON_ENABLED, "vgui/white", invisible); + pButton->SetImage(CBitmapButton::BUTTON_ENABLED_MOUSE_OVER, "vgui/white", invisible); + pButton->SetImage(CBitmapButton::BUTTON_PRESSED, "vgui/white", invisible); } - pSilhouette->SetVisible( true ); + pSilhouette->SetVisible(true); } else { - pSilhouette->SetVisible( false ); + pSilhouette->SetVisible(false); } } + + if (m_pTracePlayerButton) { + // In online games, show the button only for other players (not local player, not bot, and occupied slot) + if (!Briefing() + || Briefing()->IsOfflineGame() + || Briefing()->IsLobbySlotLocal(m_nLobbySlot) + || Briefing()->IsLobbySlotBot(m_nLobbySlot) + || !Briefing()->IsLobbySlotOccupied(m_nLobbySlot)) + { + m_pTracePlayerButton->SetVisible(true); + return; + } + + m_pTracePlayerButton->SetVisible(true); + } } void CNB_Lobby_Row::CheckTooltip( CNB_Lobby_Tooltip *pTooltip ) @@ -556,7 +564,7 @@ void CNB_Lobby_Row::OnCommand(const char* command) } else if (!Q_stricmp(command, "TracePlayerPressed")) { - TracePlayerPressed(); + OnTracePlayerPressed(); } } @@ -617,25 +625,7 @@ void CNB_Lobby_Row::UpdateChangingSlot() m_pChangingSlot[ 3 ]->SetVisible( nSlot == 4 ); } -void CNB_Lobby_Row::UpdateTracePlayerButton() -{ - if (!m_pTracePlayerButton) - return; - // In online games, show the button only for other players (not local player, not bot, and occupied slot) - if (!Briefing() - || Briefing()->IsOfflineGame() - || Briefing()->IsLobbySlotLocal(m_nLobbySlot) - || Briefing()->IsLobbySlotBot(m_nLobbySlot) - || !Briefing()->IsLobbySlotOccupied(m_nLobbySlot)) - { - m_pTracePlayerButton->SetVisible(false); - return; - } - - m_pTracePlayerButton->SetVisible(true); -} - -void CNB_Lobby_Row::TracePlayerPressed() +void CNB_Lobby_Row::OnTracePlayerPressed() { int playerIndex = Briefing()->GetPlayerIndex(m_nLobbySlot); if (playerIndex < 0 || playerIndex >= gpGlobals->maxClients) @@ -645,5 +635,5 @@ void CNB_Lobby_Row::TracePlayerPressed() } // flip the trace state for this player g_bShouldTracePlayer[playerIndex] = !g_bShouldTracePlayer[playerIndex]; - m_pTracePlayerButton->SetImage(CBitmapButton::BUTTON_ENABLED, g_bShouldTracePlayer[playerIndex] ? "vgui/briefing/trace_player_icon_on" : "vgui/briefing/trace_player_icon_off", color32{ 66, 142, 192, 255 }); + m_pTracePlayerButton->SetImage(CBitmapButton::BUTTON_ENABLED, g_bShouldTracePlayer[playerIndex] ? "vgui/briefing/trace_player_icon_on" : "vgui/briefing/trace_player_icon_off", color32{ 255, 255, 255, 255 }); } diff --git a/src/game/client/swarm/vgui/nb_lobby_row.h b/src/game/client/swarm/vgui/nb_lobby_row.h index 56961d7c5..1a834b2ff 100644 --- a/src/game/client/swarm/vgui/nb_lobby_row.h +++ b/src/game/client/swarm/vgui/nb_lobby_row.h @@ -43,9 +43,7 @@ class CNB_Lobby_Row : public vgui::EditablePanel virtual void CheckTooltip(CNB_Lobby_Tooltip* pTooltip); void UpdateChangingSlot(); - - void UpdateTracePlayerButton(); - void TracePlayerPressed(); + void OnTracePlayerPressed(); // == MANAGED_MEMBER_POINTERS_START: Do not edit by hand == vgui::ImagePanel* m_pBackground; diff --git a/src/game/client/swarm/vgui/nb_lobby_row_small.cpp b/src/game/client/swarm/vgui/nb_lobby_row_small.cpp index 696e0dcdd..86e78dde9 100644 --- a/src/game/client/swarm/vgui/nb_lobby_row_small.cpp +++ b/src/game/client/swarm/vgui/nb_lobby_row_small.cpp @@ -30,9 +30,9 @@ void CNB_Lobby_Row_Small::ApplySchemeSettings(vgui::IScheme* pScheme) // Unless we have clearly specified a correct scheme, we will use the default scheme for the game. auto currentScheme = rd_legacy_ui.GetString(); - if (!Q_stricmp(currentScheme, "'2004") - || !Q_stricmp(currentScheme, "'2010") - || !Q_stricmp(currentScheme, "'2017")) + if (!Q_stricmp(currentScheme, "2004") + || !Q_stricmp(currentScheme, "2010") + || !Q_stricmp(currentScheme, "2017")) { LoadControlSettings("resource/ui/nb_lobby_row_small.res"); } diff --git a/src/game/client/swarm/vgui/nb_main_panel.cpp b/src/game/client/swarm/vgui/nb_main_panel.cpp index 7425f4bde..eb9af1d99 100644 --- a/src/game/client/swarm/vgui/nb_main_panel.cpp +++ b/src/game/client/swarm/vgui/nb_main_panel.cpp @@ -173,9 +173,9 @@ void CNB_Main_Panel::ApplySchemeSettings(vgui::IScheme* pScheme) // Unless we have clearly specified a correct scheme, we will use the default scheme for the game. auto currentScheme = rd_legacy_ui.GetString(); - if (!Q_stricmp(currentScheme, "'2004") - || !Q_stricmp(currentScheme, "'2010") - || !Q_stricmp(currentScheme, "'2017")) + if (!Q_stricmp(currentScheme, "2004") + || !Q_stricmp(currentScheme, "2010") + || !Q_stricmp(currentScheme, "2017")) { LoadControlSettings("resource/ui/nb_main_panel.res"); } From 9c0aa5fe46bd02c24f729ff51724d3b442174a69 Mon Sep 17 00:00:00 2001 From: ywgATustcbbs Date: Thu, 10 Jul 2025 02:20:52 +0800 Subject: [PATCH 08/13] new tracer algorithm --- src/game/client/swarm/c_asw_marine.cpp | 129 ++++++++++++++++-- src/game/client/swarm/c_asw_marine.h | 15 +- src/game/client/swarm/vgui/asw_hud_emotes.cpp | 59 ++++---- 3 files changed, 154 insertions(+), 49 deletions(-) diff --git a/src/game/client/swarm/c_asw_marine.cpp b/src/game/client/swarm/c_asw_marine.cpp index ce3f1e65b..8d1dcaef3 100644 --- a/src/game/client/swarm/c_asw_marine.cpp +++ b/src/game/client/swarm/c_asw_marine.cpp @@ -870,7 +870,7 @@ void C_ASW_Marine::ClientThink() TickEmotes( deltatime ); TickRedName( deltatime ); - TickTracePlayerMovement(deltatime); + TickTrace(deltatime); UpdateFireEmitters(); UpdateJumpJetEffects(); @@ -989,28 +989,127 @@ void C_ASW_Marine::DoWaterRipples() } } -void C_ASW_Marine::TickTracePlayerMovement(float d) +inline float ManhattanDistance(const Vector &a, const Vector &b) { - m_nTraceSkip--; - if ( m_nTraceSkip > 0 ) + return fabs(a.x - b.x) + fabs(a.y - b.y) + fabs(a.z - b.z); +} + +/// +/// Performs Catmull-Rom interpolation on the player movement traces stored in lstIn and outputs the interpolated positions to vecOut vector. +/// +/// List of player movement traces to interpolate. +/// Output vector to store the interpolated positions. +/// Number of interpolation steps between each pair of points. +void CatmullRomInterp(std::list& lstIn, std::vector& vecOut, int interpCount) +{ + vecOut.clear(); + std::vector vecPoints; + vecPoints.reserve(lstIn.size()); + for (const auto& point : lstIn) { + vecPoints.push_back(point); + } + + const size_t numPoints = vecPoints.size(); + if (numPoints == 0) { return; - m_nTraceSkip = 30; + } + if (numPoints == 1) { + vecOut.push_back(vecPoints[0]); + return; + } + + size_t totalPoints = numPoints + (numPoints - 1) * interpCount; + vecOut.reserve(totalPoints); + + // add the start point of the segment + vecOut.push_back(vecPoints[0]); + for (size_t i = 0; i < numPoints - 1; ++i) { + // get the previous, current, next and next-next points. Need to pad virtual points at the start and end to ensure we can interpolate the first and last segments correctly. + const Vector& p0 = (i == 0) ? vecPoints[0].m_vecPosition : vecPoints[i - 1].m_vecPosition; + const Vector& p1 = vecPoints[i].m_vecPosition; + const Vector& p2 = vecPoints[i + 1].m_vecPosition; + const Vector& p3 = (i + 2 < numPoints) ? vecPoints[i + 2].m_vecPosition : vecPoints[i + 1].m_vecPosition; + + // add interpolated points between p1 and p2, excluding p1 and p2 themselves + for (int j = 1; j <= interpCount; ++j) { + // calculate the interpolation parameter u, (0, 1) + float u = (float)j / (interpCount + 1); + float u2 = u * u; + float u3 = u2 * u; + + // Catmull-Rom interpolation formula for a point q(u) on the curve defined by points p0, p1, p2, p3 + // q(u) = 0.5 * ((2 * p1) + + // (-p0 + p2) * u + + // (2*p0 - 5*p1 + 4*p2 - p3) * u^2 + + // (-p0 + 3*p1 - 3*p2 + p3) * u^3) + MovementTrace_t temp; + temp.m_flTimestamp = -1; + temp.m_vecPosition = 0.5f * ((2 * p1) + (-p0 + p2) * u + (2 * p0 - 5 * p1 + 4 * p2 - p3) * u2 + (-p0 + 3 * p1 - 3 * p2 + p3) * u3); + if (j == 1) { + auto vecTargetDirection = temp.m_vecPosition - vecOut.back().m_vecPosition; + vecTargetDirection.z = 0; + float angleRad = atan2(vecTargetDirection.y, vecTargetDirection.x); + vecOut.back().m_flAngleDegree = RAD2DEG(angleRad); + } + vecOut.push_back(temp); + } + + // add the end point of the segment + vecOut.push_back(vecPoints[i + 1]); + } +} + +void C_ASW_Marine::TickTrace(float d) +{ + // Not sure if the engine is single threaded or not, meanwhile, the list is accessed form other places. Therefore, lock m_TraceLock, just in case we are accessing the list from multiple threads, preventing concurrent modification of m_lstTracePlayerMovementList. Can safely remove the lock if the engine is gauranteed to be single threaded. + std::lock_guard lock(m_TraceLock); + + m_nTraceSkip--; + + m_vecCurrentTraceOrigin = GetAbsOrigin(); + m_vecLastTraceOrigin = m_vecCurrentTraceOrigin; // get current marine position - struct TracePlayerMovement_t movement; + struct MovementTrace_t movement; + movement.m_flTimestamp = gpGlobals->curtime; movement.m_flTraceTime = TRACE_FADE_TIME; - movement.m_vecPosition = GetAbsOrigin(); - m_lstTracePlayerMovementList.push_back(movement); + movement.m_vecPosition = m_vecCurrentTraceOrigin; + m_lstTrace.push_back(movement); - // update the trace time for each movement trace - for (auto iter = m_lstTracePlayerMovementList.begin(); iter != m_lstTracePlayerMovementList.end(); ++iter) + if (m_nTraceSkip > 0) + return; + + m_nTraceSkip = 30; + for (auto iter = m_lstTrace.begin(); iter != m_lstTrace.end(); ++iter) { - iter->m_flTraceTime -= 20 * d; + // Entering the loop means list is not empty, so we can safely use rbegin() here. + auto iter2 = m_lstTrace.rbegin(); + // iterate through the list of player movement traces reversily, until we reach the iter postion. The rbegin() always stores the latest player position, so we skip it. + for (iter2++; iter2 != m_lstTrace.rend() && iter2->m_flTimestamp > iter->m_flTimestamp; ++iter2) + { + if (fabs(iter->m_vecPosition.z - iter2->m_vecPosition.z) < 20 && ManhattanDistance(iter->m_vecPosition, iter2->m_vecPosition) < 400.0f) + { + Ray_t ray; + ray.Init(iter->m_vecPosition + Vector(0, 0, 10), iter2->m_vecPosition + Vector(0, 0, 10), GetCollideable()->OBBMins(), GetCollideable()->OBBMaxs()); + + trace_t trace; + UTIL_TraceRay(ray, (CONTENTS_SOLID | CONTENTS_MOVEABLE | CONTENTS_PLAYERCLIP | CONTENTS_GRATE), this, COLLISION_GROUP_PLAYER_MOVEMENT, &trace); + + if (trace.fraction != 1.0f) + { + continue; // no ground + } + + // if the distance is less than 500 units and there is no obstacle between the two positions, we can remove the trace. It is believed as the player moves back to the same position, then we can remove the trace between the two positions + auto timeStamp1 = iter->m_flTimestamp; + auto timeStamp2 = iter2->m_flTimestamp; + m_lstTrace.remove_if([timeStamp1, timeStamp2](const MovementTrace_t& item) { + return item.m_flTimestamp > timeStamp1 && item.m_flTimestamp <= timeStamp2; + }); + } + } } - // remove any traces that have expired - m_lstTracePlayerMovementList.remove_if([](const auto& item) { - return item.m_flTraceTime <= 0; - }); + CatmullRomInterp(m_lstTrace, m_vecTraceInterpolated, 10); } void C_ASW_Marine::CreateWeaponEmitters() diff --git a/src/game/client/swarm/c_asw_marine.h b/src/game/client/swarm/c_asw_marine.h index c906d9789..4ea66c7bb 100644 --- a/src/game/client/swarm/c_asw_marine.h +++ b/src/game/client/swarm/c_asw_marine.h @@ -19,16 +19,17 @@ #ifdef CLIENT_DLL #include #include +#include -struct TracePlayerMovement_t +struct MovementTrace_t { + float m_flTimestamp; float m_flTraceTime; Vector m_vecPosition; + float m_flAngleDegree; }; #endif - - class C_ASW_Player; class C_ASW_Marine_Resource; class C_ASW_Weapon; @@ -307,8 +308,12 @@ class C_ASW_Marine : public C_ASW_VPhysics_NPC, public IASWPlayerAnimStateHelper bool TickEmote( float d, int bit, float &fEmoteTime ); #ifdef CLIENT_DLL int m_nTraceSkip = 10; - void TickTracePlayerMovement(float d); - std::list m_lstTracePlayerMovementList = std::list(); // list of positions and times for the last few frames + std::mutex m_TraceLock; + Vector m_vecCurrentTraceOrigin = vec3_origin; + Vector m_vecLastTraceOrigin = vec3_origin; + void TickTrace(float d); + std::list m_lstTrace = std::list(); // list of positions and times for the last few frames + std::vector m_vecTraceInterpolated = std::vector(); #endif CNetworkVar( int, m_iEmote ); int m_iClientEmote; diff --git a/src/game/client/swarm/vgui/asw_hud_emotes.cpp b/src/game/client/swarm/vgui/asw_hud_emotes.cpp index f99a43f7f..1edc6f3d4 100644 --- a/src/game/client/swarm/vgui/asw_hud_emotes.cpp +++ b/src/game/client/swarm/vgui/asw_hud_emotes.cpp @@ -316,70 +316,58 @@ void CASWHudEmotes::PaintTraces() void CASWHudEmotes::PaintTracesFor(C_ASW_Marine* pMarine) { + // Not sure if the engine is single threaded or not, meanwhile, the list is accessed form other places. Therefore, lock m_TraceLock, just in case we are accessing the list from multiple threads, preventing concurrent modification of m_lstTracePlayerMovementList. Can safely remove the lock if the engine is gauranteed to be single threaded. + std::lock_guard lock(pMarine->m_TraceLock); + float fTimeRatio = 1.0 - gpGlobals->curtime / 3.0 + (int)(gpGlobals->curtime / 3.0); // current time float fOpacity = cl_trace_player_opacity.GetFloat(); // default opacity for traces - auto iter = pMarine->m_lstTracePlayerMovementList.begin(); - auto iterNext = iter; - if (pMarine->m_lstTracePlayerMovementList.size() > 1) - { - iterNext++; - } - int omx, omy; - float fAlpha, fTraceRatio, xPos, yPos, angleRad, angleDeg; + float fAlpha, fTraceRatio, xPos, yPos; float fScale = (ScreenHeight() / 768.0f); float HalfW = 16.0f * fScale; float HalfH = 16.0f * fScale; - Vector vecPosition, vecPositionNext, screenPos, screenPosNext, vecTargetDirection; - + Vector vecPosition, vecPositionNext, screenPos, screenPosNext; Vector vecCameraFocus; QAngle cameraAngle; ASWInput()->ASW_GetCameraLocation(C_ASW_Player::GetLocalASWPlayer(), vecCameraFocus, cameraAngle, omx, omy, false); - for (; iter != pMarine->m_lstTracePlayerMovementList.end() && iterNext != pMarine->m_lstTracePlayerMovementList.end(); ++iter, ++iterNext) + // draw trace direction icons + for (auto iter = pMarine->m_vecTraceInterpolated.begin(); iter != pMarine->m_vecTraceInterpolated.end(); ++iter) { - float fTraceRatio = (*iter).m_flTraceTime / TRACE_FADE_TIME; - Vector vecPosition = (*iter).m_vecPosition; - Vector vecPositionNext = (*iterNext).m_vecPosition; + if (iter->m_flTimestamp < 0.0f || iter->m_flTimestamp + 1.0f > gpGlobals->curtime) + { + continue; + } + float fTraceRatio = iter->m_flTraceTime / TRACE_FADE_TIME; + Vector vecPosition = iter->m_vecPosition; if (fTraceRatio <= 0) { continue; // no trace to draw } - // draw a circle at the position of the trace in world space - // and fade it out over time fAlpha = (fTraceRatio + fTimeRatio) - (int)(fTraceRatio + fTimeRatio); if (fAlpha > 1.0 / 3.0 || fAlpha <= 0.01) { - continue; + //continue; } else { fAlpha = pow(3.0 * fAlpha, 2.2); } - if (!debugoverlay->ScreenPosition(vecPosition, screenPos) && !debugoverlay->ScreenPosition(vecPositionNext, screenPosNext)) + if (!debugoverlay->ScreenPosition(vecPosition, screenPos)) { xPos = screenPos[0]; yPos = screenPos[1]; - vecTargetDirection = vecPositionNext - vecPosition; - vecTargetDirection.z = 0; - if (vecTargetDirection.NormalizeInPlace() < 0.01) - { - continue; // no direction to draw - } if (m_nTraceTexture != -1) { - surface()->DrawSetColor(Color(255, 255, 255, fAlpha * fOpacity * 255.0f)); + surface()->DrawSetColor(Color(255, 255, 255, 255.0f)); surface()->DrawSetTexture(m_nTraceTexture); - angleRad = atan2(vecTargetDirection.y, vecTargetDirection.x); - angleDeg = RAD2DEG(angleRad); - - QAngle angFacing(0, -angleDeg + cameraAngle.y - 90, 0); + QAngle angFacing(0, -iter->m_flAngleDegree + cameraAngle.y - 90, 0); Vector vecCornerTL(-HalfW, -HalfH, 0); Vector vecCornerTR(HalfW, -HalfH, 0); @@ -409,4 +397,17 @@ void CASWHudEmotes::PaintTracesFor(C_ASW_Marine* pMarine) } } } + + // draw trace lines + for (int i = 0; i < pMarine->m_vecTraceInterpolated.size() - 2; i++) + { + Vector vecPosition = pMarine->m_vecTraceInterpolated[i].m_vecPosition; + Vector vecPositionNext = pMarine->m_vecTraceInterpolated[i + 1].m_vecPosition; + + if (!debugoverlay->ScreenPosition(vecPosition, screenPos) && !debugoverlay->ScreenPosition(vecPositionNext, screenPosNext)) + { + surface()->DrawSetColor(Color(255, 255, 255, 255.0f)); + surface()->DrawLine(screenPos[0], screenPos[1], screenPosNext[0], screenPosNext[1]); + } + } } \ No newline at end of file From 947c5a14bd0c76ccdcd5ccaa72c659398c717cce Mon Sep 17 00:00:00 2001 From: ywgATustcbbs Date: Sat, 12 Jul 2025 07:14:37 +0800 Subject: [PATCH 09/13] Use different colors for different player traces --- src/game/client/swarm/c_asw_marine.cpp | 90 ++++++++++++++++++- src/game/client/swarm/vgui/asw_hud_emotes.cpp | 66 +++++++------- src/game/client/swarm/vgui/nb_lobby_row.cpp | 12 ++- 3 files changed, 128 insertions(+), 40 deletions(-) diff --git a/src/game/client/swarm/c_asw_marine.cpp b/src/game/client/swarm/c_asw_marine.cpp index 8d1dcaef3..e8f50da1a 100644 --- a/src/game/client/swarm/c_asw_marine.cpp +++ b/src/game/client/swarm/c_asw_marine.cpp @@ -108,10 +108,96 @@ extern ConVar rd_team_color_enemy; extern float g_fMarinePoisonDuration; #ifdef CLIENT_DLL -std::vector g_bShouldTracePlayer = std::vector(MAX_PLAYERS, false); // whether we have a trace position for this player +Color g_TraceColorArray[8] = +{ + Color(0, 0, 0, 255), // black (unused) + Color(255, 255, 255, 255), // white + Color(255, 255, 0, 255), // yellow + Color(0, 255, 0, 255), // green + Color(255, 0, 0, 255), // red + Color(0, 0, 255, 255), // blue + Color(255, 0, 255, 255), // pink + Color(0, 255, 255, 255), // cyan +}; +std::vector g_nTracePlayer2Color = std::vector(MAX_PLAYERS, 0); +std::vector g_nTraceColor2Player = std::vector(8, 0); float TRACE_FADE_TIME = 60.0f; // how long to keep the trace positions for ConVar cl_trace_player_max_targets("cl_trace_player_max_targets", "3", FCVAR_ARCHIVE | FCVAR_CLIENTDLL, "Maximum number of players to trace positions for in the client.", true, 1.0f, true, 7.0f); -ConVar cl_trace_player_opacity("cl_trace_player_opacity", "0.5", FCVAR_ARCHIVE | FCVAR_CLIENTDLL, "Opacity of the player trace positions in the client. 0.0 means fully transparent, 1.0 means fully opaque.", true, 0.0f, true, 1.0f); +ConVar cl_trace_player_opacity("cl_trace_player_opacity", "1", FCVAR_ARCHIVE | FCVAR_CLIENTDLL, "Opacity of the player trace positions in the client. 0.0 means fully transparent, 1.0 means fully opaque.", true, 0.0f, true, 1.0f); +//ConVar cl_trace_player_line_thickness("cl_trace_player_line_thickness", "30", FCVAR_ARCHIVE | FCVAR_CLIENTDLL, "Thickness of the player trace.", true, 1.0f, true, 100.0f); +//ConVar cl_trace_player_border_thickness("cl_trace_player_border_thickness", "5", FCVAR_ARCHIVE | FCVAR_CLIENTDLL, "Thickness of the player trace border.", true, 1.0f, true, 10.0f); + +void RemoveInvalidTracePlayersAndColors() +{ + for (int i = 1; i <= 7; i++) + { + // if this color's playerIndex is not a valid player, or if the color index is greater than the max targets, reset it + if (g_nTraceColor2Player[i] <= 0 || g_nTraceColor2Player[i] >= MAX_PLAYERS || !UTIL_PlayerByIndex(g_nTraceColor2Player[i]) || i > cl_trace_player_max_targets.GetInt()) + { + g_nTraceColor2Player[i] = 0; + } + } + for (int i = 1; i < MAX_PLAYERS; i++) + { + // if this playerIndex is not a valid player, or if the player's colorIndex is greater than the max targets, reset it + if (!UTIL_PlayerByIndex(i) || g_nTracePlayer2Color[i] <= 0 || g_nTracePlayer2Color[i] > cl_trace_player_max_targets.GetInt()) + { + g_nTracePlayer2Color[i] = 0; + } + + } + // cross-check the color -> player mapping, remove any record if not match + for (int i = 1; i <= cl_trace_player_max_targets.GetInt(); i++) + { + if (g_nTracePlayer2Color[g_nTraceColor2Player[i]] != i) + { + g_nTraceColor2Player[i] = 0; + } + } + // cross-check the player -> color mapping, remove any record if not match + for (int i = 1; i < MAX_PLAYERS; i++) + { + if (g_nTraceColor2Player[g_nTracePlayer2Color[i]] != i) + { + g_nTracePlayer2Color[i] = 0; + } + } +} + +void ToggleTraceColor(int playerIndex) +{ + RemoveInvalidTracePlayersAndColors(); + if ( playerIndex < 0 || playerIndex >= MAX_PLAYERS ) + return; + int nColorIndex = g_nTracePlayer2Color[playerIndex]; + if ( nColorIndex != 0 ) + { + g_nTracePlayer2Color[playerIndex] == 0; + g_nTraceColor2Player[nColorIndex] = 0; + } + else + { + // find an available color index + bool hasAvailableColor = false; + for ( int i = 1; i <= cl_trace_player_max_targets.GetInt(); i++ ) + { + if ( g_nTraceColor2Player[i] == 0 ) + { + g_nTracePlayer2Color[playerIndex] = i; + g_nTraceColor2Player[i] = playerIndex; + hasAvailableColor = true; + break; + } + } + if(!hasAvailableColor) + { + // no available color, so replace the last one + g_nTracePlayer2Color[g_nTraceColor2Player[cl_trace_player_max_targets.GetInt()]] = 0; + g_nTraceColor2Player[cl_trace_player_max_targets.GetInt()] = playerIndex; + g_nTracePlayer2Color[playerIndex] = cl_trace_player_max_targets.GetInt(); + } + } +} #endif #define FLASHLIGHT_DISTANCE 1000 diff --git a/src/game/client/swarm/vgui/asw_hud_emotes.cpp b/src/game/client/swarm/vgui/asw_hud_emotes.cpp index 1edc6f3d4..46bd46db9 100644 --- a/src/game/client/swarm/vgui/asw_hud_emotes.cpp +++ b/src/game/client/swarm/vgui/asw_hud_emotes.cpp @@ -45,9 +45,16 @@ using namespace vgui; extern ConVar asw_draw_hud; #ifdef CLIENT_DLL -extern std::vector g_bShouldTracePlayer; extern float TRACE_FADE_TIME; extern ConVar cl_trace_player_opacity; +extern ConVar cl_trace_player_max_targets; +//extern ConVar cl_trace_player_line_thickness; +//extern ConVar cl_trace_player_border_thickness; +extern Color g_TraceColorArray[8]; +extern std::vector g_nTracePlayer2Color; +extern std::vector g_nTraceColor2Player; +extern void RemoveInvalidTracePlayersAndColors(); +extern void ToggleTraceColor(int playerIndex); #endif //----------------------------------------------------------------------------- @@ -69,7 +76,7 @@ class CASWHudEmotes : public CASW_HudElement, public vgui::Panel virtual bool ShouldDraw( void ) { return asw_draw_hud.GetBool() && CASW_HudElement::ShouldDraw(); } virtual void PaintTraces(); - virtual void PaintTracesFor(C_ASW_Marine* pMarine); + virtual void PaintTracesFor(C_ASW_Marine* pMarine, Color color); CPanelAnimationVarAliasType( int, m_nMedicTexture, "MedicEmoteTexture", "vgui/swarm/Emotes/EmoteMedic", "textureid" ); CPanelAnimationVarAliasType( int, m_nAmmoTexture, "AmmoEmoteTexture", "vgui/swarm/Emotes/EmoteAmmo", "textureid" ); @@ -296,6 +303,7 @@ void CASWHudEmotes::PaintEmote( C_BaseEntity *pEnt, float fTime, int iTexture, f void CASWHudEmotes::PaintTraces() { + RemoveInvalidTracePlayersAndColors(); C_ASW_Game_Resource* pGameResource = ASWGameResource(); if (!pGameResource) return; @@ -307,22 +315,22 @@ void CASWHudEmotes::PaintTraces() continue; C_ASW_Marine* marine = pMR->GetMarineEntity(); - if (!pMR->IsInhabited() || !marine || !g_bShouldTracePlayer[pMR->GetCommanderIndex()]) + if (!pMR->IsInhabited() || !marine || g_nTracePlayer2Color[pMR->GetCommanderIndex()] == 0) continue; - PaintTracesFor(marine); + PaintTracesFor(marine, g_TraceColorArray[g_nTracePlayer2Color[pMR->GetCommanderIndex()]]); } } -void CASWHudEmotes::PaintTracesFor(C_ASW_Marine* pMarine) +void CASWHudEmotes::PaintTracesFor(C_ASW_Marine* pMarine, Color color) { // Not sure if the engine is single threaded or not, meanwhile, the list is accessed form other places. Therefore, lock m_TraceLock, just in case we are accessing the list from multiple threads, preventing concurrent modification of m_lstTracePlayerMovementList. Can safely remove the lock if the engine is gauranteed to be single threaded. std::lock_guard lock(pMarine->m_TraceLock); float fTimeRatio = 1.0 - gpGlobals->curtime / 3.0 + (int)(gpGlobals->curtime / 3.0); // current time - float fOpacity = cl_trace_player_opacity.GetFloat(); // default opacity for traces + color[3] = 255 * pow(cl_trace_player_opacity.GetFloat(), 2.2); int omx, omy; - float fAlpha, fTraceRatio, xPos, yPos; + float xPos, yPos; float fScale = (ScreenHeight() / 768.0f); float HalfW = 16.0f * fScale; float HalfH = 16.0f * fScale; @@ -332,31 +340,35 @@ void CASWHudEmotes::PaintTracesFor(C_ASW_Marine* pMarine) ASWInput()->ASW_GetCameraLocation(C_ASW_Player::GetLocalASWPlayer(), vecCameraFocus, cameraAngle, omx, omy, false); + // draw trace lines + surface()->DrawSetColor(color); + for (int i = 0; i < pMarine->m_vecTraceInterpolated.size() - 2; i++) + { + Vector vecPosition = pMarine->m_vecTraceInterpolated[i].m_vecPosition; + Vector vecPositionNext = pMarine->m_vecTraceInterpolated[i + 1].m_vecPosition; + + if (!debugoverlay->ScreenPosition(vecPosition, screenPos) && !debugoverlay->ScreenPosition(vecPositionNext, screenPosNext)) + { + surface()->DrawLine(screenPos[0], screenPos[1], screenPosNext[0], screenPosNext[1]); + } + } + // draw trace direction icons + surface()->DrawSetColor(color); + surface()->DrawSetTexture(m_nTraceTexture); for (auto iter = pMarine->m_vecTraceInterpolated.begin(); iter != pMarine->m_vecTraceInterpolated.end(); ++iter) { if (iter->m_flTimestamp < 0.0f || iter->m_flTimestamp + 1.0f > gpGlobals->curtime) { continue; } - float fTraceRatio = iter->m_flTraceTime / TRACE_FADE_TIME; Vector vecPosition = iter->m_vecPosition; - if (fTraceRatio <= 0) + if (iter->m_flTraceTime <= 0) { continue; // no trace to draw } - fAlpha = (fTraceRatio + fTimeRatio) - (int)(fTraceRatio + fTimeRatio); - if (fAlpha > 1.0 / 3.0 || fAlpha <= 0.01) - { - //continue; - } - else - { - fAlpha = pow(3.0 * fAlpha, 2.2); - } - if (!debugoverlay->ScreenPosition(vecPosition, screenPos)) { xPos = screenPos[0]; @@ -364,9 +376,6 @@ void CASWHudEmotes::PaintTracesFor(C_ASW_Marine* pMarine) if (m_nTraceTexture != -1) { - surface()->DrawSetColor(Color(255, 255, 255, 255.0f)); - surface()->DrawSetTexture(m_nTraceTexture); - QAngle angFacing(0, -iter->m_flAngleDegree + cameraAngle.y - 90, 0); Vector vecCornerTL(-HalfW, -HalfH, 0); @@ -397,17 +406,4 @@ void CASWHudEmotes::PaintTracesFor(C_ASW_Marine* pMarine) } } } - - // draw trace lines - for (int i = 0; i < pMarine->m_vecTraceInterpolated.size() - 2; i++) - { - Vector vecPosition = pMarine->m_vecTraceInterpolated[i].m_vecPosition; - Vector vecPositionNext = pMarine->m_vecTraceInterpolated[i + 1].m_vecPosition; - - if (!debugoverlay->ScreenPosition(vecPosition, screenPos) && !debugoverlay->ScreenPosition(vecPositionNext, screenPosNext)) - { - surface()->DrawSetColor(Color(255, 255, 255, 255.0f)); - surface()->DrawLine(screenPos[0], screenPos[1], screenPosNext[0], screenPosNext[1]); - } - } } \ No newline at end of file diff --git a/src/game/client/swarm/vgui/nb_lobby_row.cpp b/src/game/client/swarm/vgui/nb_lobby_row.cpp index 493b11300..16f32d9b9 100644 --- a/src/game/client/swarm/vgui/nb_lobby_row.cpp +++ b/src/game/client/swarm/vgui/nb_lobby_row.cpp @@ -26,9 +26,14 @@ #include "tier0/memdbgon.h" extern ConVar rd_legacy_ui; + #ifdef CLIENT_DLL -extern std::vector g_bShouldTracePlayer; +extern Color g_TraceColorArray[8]; +extern std::vector g_nTracePlayer2Color; +extern std::vector g_nTraceColor2Player; extern ConVar cl_trace_player_max_targets; +extern void RemoveInvalidTracePlayersAndColors(); +extern void ToggleTraceColor(int playerIndex); #endif using namespace BaseModUI; @@ -455,6 +460,7 @@ void CNB_Lobby_Row::UpdateDetails() } if (m_pTracePlayerButton) { + RemoveInvalidTracePlayersAndColors(); // In online games, show the button only for other players (not local player, not bot, and occupied slot) if (!Briefing() || Briefing()->IsOfflineGame() @@ -634,6 +640,6 @@ void CNB_Lobby_Row::OnTracePlayerPressed() return; // Invalid player index } // flip the trace state for this player - g_bShouldTracePlayer[playerIndex] = !g_bShouldTracePlayer[playerIndex]; - m_pTracePlayerButton->SetImage(CBitmapButton::BUTTON_ENABLED, g_bShouldTracePlayer[playerIndex] ? "vgui/briefing/trace_player_icon_on" : "vgui/briefing/trace_player_icon_off", color32{ 255, 255, 255, 255 }); + ToggleTraceColor(playerIndex); + m_pTracePlayerButton->SetImage(CBitmapButton::BUTTON_ENABLED, (g_nTracePlayer2Color[playerIndex] == 0) ? "vgui/briefing/trace_player_icon_on" : "vgui/briefing/trace_player_icon_off", color32{ 255, 255, 255, 255 }); } From 7cf2eaf0a9bb67710ddb8bde89b547b2f22340f8 Mon Sep 17 00:00:00 2001 From: ywgATustcbbs Date: Sat, 12 Jul 2025 10:39:58 +0800 Subject: [PATCH 10/13] Add button to player list. Add toggle button for tracing (default off). Code clean up. --- .../resource/ui/playerlistpanel.res | 298 ++++++++++++++++++ src/game/client/swarm/c_asw_marine.cpp | 1 + src/game/client/swarm/vgui/asw_hud_emotes.cpp | 1 + src/game/client/swarm/vgui/nb_lobby_row.cpp | 14 +- src/game/client/swarm/vgui/nb_main_panel.cpp | 7 +- src/game/client/swarm/vgui/playerlistline.cpp | 121 +++++-- src/game/client/swarm/vgui/playerlistline.h | 1 + .../client/swarm/vgui/playerlistpanel.cpp | 88 +++--- src/game/client/swarm/vgui/playerlistpanel.h | 1 + 9 files changed, 457 insertions(+), 75 deletions(-) create mode 100644 reactivedrop/content/trace_player_ui/resource/ui/playerlistpanel.res diff --git a/reactivedrop/content/trace_player_ui/resource/ui/playerlistpanel.res b/reactivedrop/content/trace_player_ui/resource/ui/playerlistpanel.res new file mode 100644 index 000000000..3b9e37f8c --- /dev/null +++ b/reactivedrop/content/trace_player_ui/resource/ui/playerlistpanel.res @@ -0,0 +1,298 @@ +"Resource/UI/PlayerListPanel.res" +{ + "PlayerListPanel" + { + "fieldName" "PlayerListPanel" + "ControlName" "EditablePanel" + "xpos" "0" + "ypos" "0" + "wide" "f0" + "tall" "f0" + } +// "VoteBG" +// { +// "fieldName" "VoteBG" +// "xpos" "c-250" +// "ypos" "300" +// "wide" "500" +// "tall" "70" +// "ControlName" "Panel" +// "bgcolor_override" "0 0 0 128" +// "zpos" "1" +// } + "MissionLabel" + { + "fieldName" "MissionLabel" + "xpos" "c-210" + "ypos" "40" + "wide" "250" + "tall" "22" + "zpos" "5" + "font" "DefaultExtraLarge" + "textAlignment" "west" + "ControlName" "Label" + "fgcolor_override" "224 224 224 255" + } + "Team1Score" + { + "fieldName" "Team1Score" + "xpos" "c15" + "ypos" "40" + "wide" "150" + "tall" "25" + "zpos" "5" + "font" "DefaultLarge" + "textAlignment" "west" + "ControlName" "Label" + "fgcolor_override" "224 224 224 255" + } + "Team2Score" + { + "fieldName" "Team2Score" + "xpos" "c165" + "ypos" "40" + "wide" "150" + "tall" "25" + "zpos" "5" + "font" "DefaultLarge" + "textAlignment" "west" + "ControlName" "Label" + "fgcolor_override" "224 224 224 255" + } + "CurrentVoteTitle" + { + "fieldName" "CurrentVoteTitle" + "xpos" "c-240" + "ypos" "398" + "wide" "250" + "tall" "25" + "zpos" "5" + "font" "Default" + "textAlignment" "west" + "ControlName" "Label" + "fgcolor_override" "224 224 224 255" + } + "MapName" + { + "fieldName" "MapName" + "xpos" "c-240" + "ypos" "422" + "wide" "250" + "tall" "25" + "zpos" "5" + "font" "DefaultLarge" + "textAlignment" "west" + "ControlName" "Label" + "fgcolor_override" "83 148 192 255" + } + "VisibilityLabel" + { + "fieldName" "VisibilityLabel" + "xpos" "c-290" + "ypos" "20" + "wide" "420" + "tall" "17" + "font" "Default" + "textAlignment" "west" + "ControlName" "Label" + "fgcolor_override" "224 224 224 255" + "zpos" "5" + } + "DifficultyLabel" + { + "fieldName" "DifficultyLabel" + "xpos" "c-210" + "ypos" "60" + "wide" "420" + "tall" "17" + "font" "Default" + "textAlignment" "west" + "ControlName" "Label" + "fgcolor_override" "224 224 224 255" + "zpos" "5" + } + "ServerLabel" + { + "fieldName" "ServerLabel" + "xpos" "c-210" + "ypos" "60" + "wide" "420" + "tall" "17" + "font" "Default" + "textAlignment" "east" + "ControlName" "Label" + "fgcolor_override" "224 224 224 255" + "zpos" "5" + } + "Counter" + { + "fieldName" "Counter" + "xpos" "c-75" + "ypos" "398" + "wide" "150" + "tall" "25" + "font" "Default" + "textAlignment" "center" + "ControlName" "Label" + "fgcolor_override" "224 224 224 255" + "zpos" "5" + } + "YesCount" + { + "fieldName" "YesCount" + "xpos" "c-25" + "ypos" "398" + "wide" "150" + "tall" "25" + "font" "Default" + "textAlignment" "east" + "ControlName" "Label" + "fgcolor_override" "224 224 224 255" + "zpos" "5" + } + "NoCount" + { + "fieldName" "NoCount" + "xpos" "c-25" + "ypos" "426" + "wide" "150" + "tall" "25" + "font" "Default" + "textAlignment" "east" + "ControlName" "Label" + "fgcolor_override" "224 224 224 255" + "zpos" "5" + } + "RestartButton" + { + "fieldName" "RestartButton" + "ControlName" "CNB_Button" + "xpos" "c147" + "ypos" "r23" + "wide" "117" + "tall" "27" + "labelText" "#asw_button_restart_mis" + "textAlignment" "center" + "font" "DefaultMedium" + "fgcolor_override" "113 142 181 255" + "zpos" "3" + } + "BackButton" + { + "fieldName" "BackButton" + "ControlName" "CNB_Button" + "xpos" "c-264" + "ypos" "r23" + "wide" "117" + "tall" "27" + "labelText" "#nb_back" + "textAlignment" "center" + "font" "DefaultMedium" + "command" "Back" + "fgcolor_override" "113 142 181 255" + "zpos" "3" + } + "VisibilityButton" + { + "fieldName" "VisibilityButton" + "xpos" "c-108" + "ypos" "r23" + "wide" "117" + "tall" "27" + "ControlName" "CNB_Button" + "labelText" "#L4D360UI_Lobby_FriendsTitle" + "textAlignment" "center" + "font" "DefaultMedium" + "fgcolor_override" "113 142 181 255" + "zpos" "3" + } + "TipsLabel" + { + "fieldName" "TipsLabel" + "xpos" "c-120" + "ypos" "r39" + "wide" "420" + "tall" "17" + "font" "Default" + "textAlignment" "west" + "ControlName" "Label" + "fgcolor_override" "224 224 224 255" + "zpos" "5" + } + "CampaignVoteButton" + { + "fieldName" "CampaignVoteButton" + "ControlName" "CNB_Button" + "xpos" "c20" + "ypos" "r23" + "wide" "117" + "tall" "27" + "labelText" "#asw_campaign_vote" + "textAlignment" "center" + "font" "DefaultMedium" + "fgcolor_override" "113 142 181 255" + "zpos" "3" + } + "Yes" + { + "fieldName" "Yes" + "ControlName" "CNB_Button" + "xpos" "c132" + "ypos" "398" + "wide" "110" + "tall" "25" + "labelText" "#asw_vote_yes" + "textAlignment" "center" + "font" "DefaultMedium" + "fgcolor_override" "113 142 181 255" + "zpos" "3" + } + "No" + { + "fieldName" "No" + "ControlName" "CNB_Button" + "xpos" "c132" + "ypos" "426" + "wide" "110" + "tall" "25" + "labelText" "#asw_vote_no" + "textAlignment" "center" + "font" "DefaultMedium" + "fgcolor_override" "113 142 181 255" + "zpos" "3" + } + "PlayerListScroll" + { + "ControlName" "GenericPanelList" + "fieldName" "PlayerListScroll" + // positioning done by code + "zpos" "1" + "autoResize" "1" + "pinCorner" "0" + "visible" "1" + "enabled" "1" + "tabPosition" "1" + "proportionalToParent" "1" + "bgcolor_override" "0 0 0 0" + } + "SettingAutoReportVotes" + { + "ControlName" "CCvarToggleCheckButton" + "fieldName" "SettingAutoReportVotes" + "xpos" "c-250" + "ypos" "360" + "wide" "500" + "tall" "20" + "ResourceFile" "resource/ui/option_simple_checkbox.res" + } + "SettingTracePlayerToggle" + { + "ControlName" "CCvarToggleCheckButton" + "fieldName" "SettingTracePlayerToggle" + "xpos" "c" + "ypos" "360" + "wide" "500" + "tall" "20" + "ResourceFile" "resource/ui/option_simple_checkbox.res" + } +} diff --git a/src/game/client/swarm/c_asw_marine.cpp b/src/game/client/swarm/c_asw_marine.cpp index e8f50da1a..d42b0f6cd 100644 --- a/src/game/client/swarm/c_asw_marine.cpp +++ b/src/game/client/swarm/c_asw_marine.cpp @@ -122,6 +122,7 @@ Color g_TraceColorArray[8] = std::vector g_nTracePlayer2Color = std::vector(MAX_PLAYERS, 0); std::vector g_nTraceColor2Player = std::vector(8, 0); float TRACE_FADE_TIME = 60.0f; // how long to keep the trace positions for +ConVar cl_trace_player_enable("cl_trace_player_enable", "0", FCVAR_ARCHIVE | FCVAR_CLIENTDLL, "Show player movement traces in the client. 0 = disabled, 1 = enabled."); ConVar cl_trace_player_max_targets("cl_trace_player_max_targets", "3", FCVAR_ARCHIVE | FCVAR_CLIENTDLL, "Maximum number of players to trace positions for in the client.", true, 1.0f, true, 7.0f); ConVar cl_trace_player_opacity("cl_trace_player_opacity", "1", FCVAR_ARCHIVE | FCVAR_CLIENTDLL, "Opacity of the player trace positions in the client. 0.0 means fully transparent, 1.0 means fully opaque.", true, 0.0f, true, 1.0f); //ConVar cl_trace_player_line_thickness("cl_trace_player_line_thickness", "30", FCVAR_ARCHIVE | FCVAR_CLIENTDLL, "Thickness of the player trace.", true, 1.0f, true, 100.0f); diff --git a/src/game/client/swarm/vgui/asw_hud_emotes.cpp b/src/game/client/swarm/vgui/asw_hud_emotes.cpp index 46bd46db9..5c1ded773 100644 --- a/src/game/client/swarm/vgui/asw_hud_emotes.cpp +++ b/src/game/client/swarm/vgui/asw_hud_emotes.cpp @@ -46,6 +46,7 @@ extern ConVar asw_draw_hud; #ifdef CLIENT_DLL extern float TRACE_FADE_TIME; +extern ConVar cl_trace_player_enable; extern ConVar cl_trace_player_opacity; extern ConVar cl_trace_player_max_targets; //extern ConVar cl_trace_player_line_thickness; diff --git a/src/game/client/swarm/vgui/nb_lobby_row.cpp b/src/game/client/swarm/vgui/nb_lobby_row.cpp index 16f32d9b9..adff0328d 100644 --- a/src/game/client/swarm/vgui/nb_lobby_row.cpp +++ b/src/game/client/swarm/vgui/nb_lobby_row.cpp @@ -20,6 +20,7 @@ #include "gameui/swarm/vdropdownmenu.h" #include "gameui/swarm/vhybridbutton.h" #include "rd_inventory_shared.h" +#include "asw_deathmatch_mode.h" #include // memdbgon must be the last include file in a .cpp file!!! @@ -31,6 +32,7 @@ extern ConVar rd_legacy_ui; extern Color g_TraceColorArray[8]; extern std::vector g_nTracePlayer2Color; extern std::vector g_nTraceColor2Player; +extern ConVar cl_trace_player_enable; extern ConVar cl_trace_player_max_targets; extern void RemoveInvalidTracePlayersAndColors(); extern void ToggleTraceColor(int playerIndex); @@ -109,7 +111,7 @@ CNB_Lobby_Row::CNB_Lobby_Row( vgui::Panel *parent, const char *name ) : BaseClas m_nLobbySlot = 0; // Create the TracePlayerButton - m_pTracePlayerButton = new CBitmapButton( this, "TracePlayerButton", "" ); + m_pTracePlayerButton = new CBitmapButton( this, "TracePlayerButton", " " ); m_pTracePlayerButton->AddActionSignalTarget( this ); m_pTracePlayerButton->SetCommand( "TracePlayerPressed" ); m_pTracePlayerButton->SetImage(CBitmapButton::BUTTON_ENABLED, "vgui/briefing/trace_player_icon_off", color32{ 255, 255, 255, 255 }); @@ -462,17 +464,19 @@ void CNB_Lobby_Row::UpdateDetails() if (m_pTracePlayerButton) { RemoveInvalidTracePlayersAndColors(); // In online games, show the button only for other players (not local player, not bot, and occupied slot) + bool isDeathMatch = ASWDeathmatchMode() && (ASWDeathmatchMode()->IsDeathmatchEnabled() || ASWDeathmatchMode()->IsTeamDeathmatchEnabled()); if (!Briefing() || Briefing()->IsOfflineGame() || Briefing()->IsLobbySlotLocal(m_nLobbySlot) || Briefing()->IsLobbySlotBot(m_nLobbySlot) - || !Briefing()->IsLobbySlotOccupied(m_nLobbySlot)) + || !Briefing()->IsLobbySlotOccupied(m_nLobbySlot) + || isDeathMatch) { - m_pTracePlayerButton->SetVisible(true); + m_pTracePlayerButton->SetVisible(false); return; } - m_pTracePlayerButton->SetVisible(true); + m_pTracePlayerButton->SetVisible(cl_trace_player_enable.GetBool() ); } } @@ -641,5 +645,5 @@ void CNB_Lobby_Row::OnTracePlayerPressed() } // flip the trace state for this player ToggleTraceColor(playerIndex); - m_pTracePlayerButton->SetImage(CBitmapButton::BUTTON_ENABLED, (g_nTracePlayer2Color[playerIndex] == 0) ? "vgui/briefing/trace_player_icon_on" : "vgui/briefing/trace_player_icon_off", color32{ 255, 255, 255, 255 }); + m_pTracePlayerButton->SetImage(CBitmapButton::BUTTON_ENABLED, (g_nTracePlayer2Color[playerIndex] != 0) ? "vgui/briefing/trace_player_icon_on" : "vgui/briefing/trace_player_icon_off", color32{ 255, 255, 255, 255 }); } diff --git a/src/game/client/swarm/vgui/nb_main_panel.cpp b/src/game/client/swarm/vgui/nb_main_panel.cpp index eb9af1d99..87b4ee61c 100644 --- a/src/game/client/swarm/vgui/nb_main_panel.cpp +++ b/src/game/client/swarm/vgui/nb_main_panel.cpp @@ -50,6 +50,7 @@ extern ConVar mm_max_players; extern ConVar rd_player_bots_allowed; extern ConVar rd_legacy_ui; ConVar rd_draw_briefing_ui( "rd_draw_briefing_ui", "1", FCVAR_CHEAT ); +extern ConVar cl_trace_player_enable; using BaseModUI::GenericPanelList; @@ -350,17 +351,19 @@ void CNB_Main_Panel::OnThink() // Check if the TraceMe button should be enabled or not // It should be enabled if it's an online game, the slot is the local player's slot, the slot is not a bot, the slot is occupied, and the marine profile exists int m_nLobbySlot = m_pLobbyRow0->m_nLobbySlot; + bool isDeathMatch = ASWDeathmatchMode() && (ASWDeathmatchMode()->IsDeathmatchEnabled() || ASWDeathmatchMode()->IsTeamDeathmatchEnabled()); if (!Briefing() || Briefing()->IsOfflineGame() || !Briefing()->IsLobbySlotLocal(m_nLobbySlot) || Briefing()->IsLobbySlotBot(m_nLobbySlot) || !Briefing()->IsLobbySlotOccupied(m_nLobbySlot) - || Briefing()->GetMarineProfile(m_nLobbySlot) == NULL) + || Briefing()->GetMarineProfile(m_nLobbySlot) == NULL + || isDeathMatch) { m_pTraceMeButton->SetVisible(false); return; } - m_pTraceMeButton->SetVisible(true); + m_pTraceMeButton->SetVisible(cl_trace_player_enable.GetBool()); } } diff --git a/src/game/client/swarm/vgui/playerlistline.cpp b/src/game/client/swarm/vgui/playerlistline.cpp index 397985d87..6d0b779e5 100644 --- a/src/game/client/swarm/vgui/playerlistline.cpp +++ b/src/game/client/swarm/vgui/playerlistline.cpp @@ -33,6 +33,16 @@ ConVar rd_muted_color( "rd_muted_color", "255 66 66", FCVAR_NONE, "Color of the ConVar rd_speaking_color( "rd_speaking_color", "0 240 240", FCVAR_NONE, "Color of the speaker icon in Player List window (F9) while talking" ); ConVar rd_unmuted_color( "rd_unmuted_color", "190 190 190", FCVAR_NONE, "Color of the speaker icon in Player List window (F9) while silent" ); +#ifdef CLIENT_DLL +extern Color g_TraceColorArray[8]; +extern std::vector g_nTracePlayer2Color; +extern std::vector g_nTraceColor2Player; +extern ConVar cl_trace_player_enable; +extern ConVar cl_trace_player_max_targets; +extern void RemoveInvalidTracePlayersAndColors(); +extern void ToggleTraceColor(int playerIndex); +#endif + PlayerListLine::PlayerListLine(vgui::Panel *parent, const char *name) : vgui::Panel( parent, name ) { @@ -43,6 +53,9 @@ PlayerListLine::PlayerListLine(vgui::Panel *parent, const char *name) : m_pQuickReportButton = new CBitmapButton( this, "QuickReportButton", "#rd_quick_report_commend_or_report" ); m_pQuickReportButton->AddActionSignalTarget( this ); m_pQuickReportButton->SetCommand( "QuickReportButton" ); + m_pTracePlayerButton1 = new CBitmapButton( this, "TracePlayerButton", " " ); + m_pTracePlayerButton1->AddActionSignalTarget( this ); + m_pTracePlayerButton1->SetCommand( "plTracePlayerButton" ); m_pPlayerLabel = new vgui::Button( this, "PlayerLabel", " " ); m_pPlayerLabel->AddActionSignalTarget( this ); m_pPlayerLabel->SetCommand( "PlayerLabel" ); @@ -102,6 +115,10 @@ void PlayerListLine::ApplySchemeSettings( vgui::IScheme *pScheme ) m_pQuickReportButton->SetImage( CBitmapButton::BUTTON_PRESSED, QUICK_REPORT_BUTTON_ICON, white ); m_pQuickReportButton->SetImage( CBitmapButton::BUTTON_ENABLED_MOUSE_OVER, QUICK_REPORT_BUTTON_ICON, white ); + m_pTracePlayerButton1->SetImage( CBitmapButton::BUTTON_ENABLED, "vgui/briefing/trace_player_icon_off", grey ); + m_pTracePlayerButton1->SetImage( CBitmapButton::BUTTON_PRESSED, "vgui/briefing/trace_player_icon_pressed", white ); + m_pTracePlayerButton1->SetImage( CBitmapButton::BUTTON_ENABLED_MOUSE_OVER, "vgui/briefing/trace_player_icon_mouse_over", white ); + vgui::HFont DefaultFont = pScheme->GetFont( "Default", IsProportional() ); m_pPlayerLabel->SetFont( DefaultFont ); m_pPlayerLabel->SetPaintBackgroundEnabled( false ); @@ -141,6 +158,21 @@ void PlayerListLine::OnCommand( const char *command ) assert_cast< PlayerListPanel * >( GetParent()->GetParent()->GetParent() )->QuickReportClicked( this ); } } + else if ( !Q_stricmp( command, "plTracePlayerButton" ) ) + { + if ( pPlayer ) + { + int playerIndex = pPlayer->entindex(); + if (playerIndex <= 0 || playerIndex >= gpGlobals->maxClients) + { + Msg("Invalid player index %d\n", playerIndex); + return; // Invalid player index + } + // flip the trace state for this player + ToggleTraceColor(playerIndex); + m_pTracePlayerButton1->SetImage(CBitmapButton::BUTTON_ENABLED, (g_nTracePlayer2Color[playerIndex] == 0) ? "vgui/briefing/trace_player_icon_on" : "vgui/briefing/trace_player_icon_off", color32{ 255, 255, 255, 255 }); + } + } else if ( !Q_stricmp( command, "PlayerLabel" ) ) { if ( pPlayer ) @@ -153,36 +185,40 @@ void PlayerListLine::OnCommand( const char *command ) void PlayerListLine::PerformLayout() { - float fScale = (ScreenHeight() / 768.0f); - int top = 6.0f * fScale; - int top_line_height = 16.0f * fScale; - int bottom_line_top = top_line_height + top; - int bottom_line_height = 16.0f * fScale; - - m_pMuteButton->SetBounds( PLAYER_LIST_MUTE_ICON_X * fScale, top, PLAYER_LIST_MUTE_ICON_W * fScale, top_line_height ); - int iQuickReportX, iQuickReportWide; - vgui::surface()->GetTextSize( m_pQuickReportButton->GetFont(), g_pVGuiLocalize->Find( "#rd_quick_report_commend_or_report" ), iQuickReportX, iQuickReportWide ); - iQuickReportWide = bottom_line_height + vgui::Label::Content + iQuickReportX; - iQuickReportX = PLAYER_LIST_QUICK_REPORT_RIGHT_X * fScale - iQuickReportWide; - m_pQuickReportButton->SetBounds( iQuickReportX, bottom_line_top, iQuickReportWide, bottom_line_height ); - m_pQuickReportButton->SetTextInset( bottom_line_height + vgui::Label::Content, 0 ); - m_pQuickReportButton->SetImageBounds( 0, 0, bottom_line_height, bottom_line_height ); - - m_pPlayerLabel-> SetBounds(PLAYER_LIST_PLAYER_X * fScale, top, PLAYER_LIST_PLAYER_W * fScale, top_line_height); - m_pMarinesLabel->SetBounds(PLAYER_LIST_MARINES_X * fScale, top, PLAYER_LIST_MARINES_W * fScale, top_line_height); - m_pFragsLabel-> SetBounds(PLAYER_LIST_FRAGS_X * fScale, top, PLAYER_LIST_FRAGS_W * fScale, top_line_height); - m_pDeathsLabel-> SetBounds(PLAYER_LIST_DEATHS_X * fScale, top, PLAYER_LIST_DEATHS_W * fScale, top_line_height); - m_pPingLabel-> SetBounds(PLAYER_LIST_PING_X * fScale, top, PLAYER_LIST_PING_W * fScale, top_line_height); - m_pLeaderCheck-> SetBounds(PLAYER_LIST_LEADER_CHECK_X * fScale, bottom_line_top, PLAYER_LIST_LEADER_CHECK_W * fScale, bottom_line_height); - m_pKickCheck-> SetBounds(PLAYER_LIST_KICK_CHECK_X * fScale, bottom_line_top, PLAYER_LIST_KICK_CHECK_W * fScale, bottom_line_height); - - for (int i=0;iSetBounds((PLAYER_LIST_KICK_ICON_X + (PLAYER_LIST_KICK_ICON_W * i)) * fScale, bottom_line_top, - PLAYER_LIST_KICK_ICON_W * fScale, bottom_line_height); - m_pLeaderVoteIcon[i]->SetBounds((PLAYER_LIST_LEADER_ICON_X + (PLAYER_LIST_LEADER_ICON_W * i)) * fScale, bottom_line_top, - PLAYER_LIST_LEADER_ICON_W * fScale, bottom_line_height); - } + float fScale = (ScreenHeight() / 768.0f); + int top = 6.0f * fScale; + int top_line_height = 16.0f * fScale; + int bottom_line_top = top_line_height + top; + int bottom_line_height = 16.0f * fScale; + + m_pMuteButton->SetBounds( PLAYER_LIST_MUTE_ICON_X * fScale, top, PLAYER_LIST_MUTE_ICON_W * fScale, top_line_height ); + int iQuickReportX, iQuickReportWide; + vgui::surface()->GetTextSize( m_pQuickReportButton->GetFont(), g_pVGuiLocalize->Find( "#rd_quick_report_commend_or_report" ), iQuickReportX, iQuickReportWide ); + iQuickReportWide = bottom_line_height + vgui::Label::Content + iQuickReportX; + iQuickReportX = PLAYER_LIST_QUICK_REPORT_RIGHT_X * fScale - iQuickReportWide; + m_pQuickReportButton->SetBounds( iQuickReportX, bottom_line_top, iQuickReportWide, bottom_line_height ); + m_pQuickReportButton->SetTextInset( bottom_line_height + vgui::Label::Content, 0 ); + m_pQuickReportButton->SetImageBounds( 0, 0, bottom_line_height, bottom_line_height ); + + int trace_button_size = 20.0f * fScale; + m_pTracePlayerButton1->SetBounds((PLAYER_LIST_MUTE_ICON_X - 2) * fScale, bottom_line_top, trace_button_size, trace_button_size); + //m_pTracePlayerButton1->SetImageBounds( 0, 0, trace_button_size, trace_button_size); + + m_pPlayerLabel-> SetBounds(PLAYER_LIST_PLAYER_X * fScale, top, PLAYER_LIST_PLAYER_W * fScale, top_line_height); + m_pMarinesLabel->SetBounds(PLAYER_LIST_MARINES_X * fScale, top, PLAYER_LIST_MARINES_W * fScale, top_line_height); + m_pFragsLabel-> SetBounds(PLAYER_LIST_FRAGS_X * fScale, top, PLAYER_LIST_FRAGS_W * fScale, top_line_height); + m_pDeathsLabel-> SetBounds(PLAYER_LIST_DEATHS_X * fScale, top, PLAYER_LIST_DEATHS_W * fScale, top_line_height); + m_pPingLabel-> SetBounds(PLAYER_LIST_PING_X * fScale, top, PLAYER_LIST_PING_W * fScale, top_line_height); + m_pLeaderCheck-> SetBounds(PLAYER_LIST_LEADER_CHECK_X * fScale, bottom_line_top, PLAYER_LIST_LEADER_CHECK_W * fScale, bottom_line_height); + m_pKickCheck-> SetBounds(PLAYER_LIST_KICK_CHECK_X * fScale, bottom_line_top, PLAYER_LIST_KICK_CHECK_W * fScale, bottom_line_height); + + for (int i=0;iSetBounds((PLAYER_LIST_KICK_ICON_X + (PLAYER_LIST_KICK_ICON_W * i)) * fScale, bottom_line_top, + PLAYER_LIST_KICK_ICON_W * fScale, bottom_line_height); + m_pLeaderVoteIcon[i]->SetBounds((PLAYER_LIST_LEADER_ICON_X + (PLAYER_LIST_LEADER_ICON_W * i)) * fScale, bottom_line_top, + PLAYER_LIST_LEADER_ICON_W * fScale, bottom_line_height); + } } void PlayerListLine::OnThink() @@ -270,6 +306,20 @@ void PlayerListLine::OnThink() } } } + + RemoveInvalidTracePlayersAndColors(); + C_ASW_Player* pPlayer = ToASW_Player(UTIL_PlayerByIndex(m_iPlayerIndex)); + bool isDeathMatch = ASWDeathmatchMode() && (ASWDeathmatchMode()->IsDeathmatchEnabled() || ASWDeathmatchMode()->IsTeamDeathmatchEnabled()); + if (pPlayer && !pPlayer->IsLocalPlayer() && !pPlayer->IsAnyBot() && !ASWDeathmatchMode()->IsDeathmatchEnabled() && !isDeathMatch) + { + m_pTracePlayerButton1->SetVisible(cl_trace_player_enable.GetBool()); + m_pTracePlayerButton1->SetImage(CBitmapButton::BUTTON_ENABLED, (g_nTracePlayer2Color[pPlayer->entindex()] != 0) ? "vgui/briefing/trace_player_icon_on" : "vgui/briefing/trace_player_icon_off", color32{ 255, 255, 255, 255 }); + } + else + { + m_pTracePlayerButton1->SetVisible(false); + } + UpdateCheckBoxes(); UpdateVoteIcons(); } @@ -320,6 +370,17 @@ void PlayerListLine::UpdateCheckBoxes() m_pKickCheck->SetVisible( pPlayer && pPlayer->CanBeKicked() ); m_pLeaderCheck->SetVisible( pPlayer && pPlayer->CanBeLeader() ); m_pQuickReportButton->SetVisible( pPlayer && !pPlayer->IsAnyBot() && ( rd_debug_quick_report_local_player.GetBool() || !pPlayer->IsLocalPlayer() ) ); + + bool isDeathMatch = ASWDeathmatchMode() && (ASWDeathmatchMode()->IsDeathmatchEnabled() || ASWDeathmatchMode()->IsTeamDeathmatchEnabled()); + if (pPlayer && !pPlayer->IsLocalPlayer() && !pPlayer->IsAnyBot() && !ASWDeathmatchMode()->IsDeathmatchEnabled() && !isDeathMatch) + { + m_pTracePlayerButton1->SetVisible(cl_trace_player_enable.GetBool()); + m_pTracePlayerButton1->SetImage(CBitmapButton::BUTTON_ENABLED, (g_nTracePlayer2Color[pPlayer->entindex()] != 0) ? "vgui/briefing/trace_player_icon_on" : "vgui/briefing/trace_player_icon_off", color32{255, 255, 255, 255}); + } + else + { + m_pTracePlayerButton1->SetVisible(false); + } // make sure our selected/unselected status matches the selected index from our parent PlayerListPanel *pPanel = assert_cast< PlayerListPanel * >( GetParent()->GetParent()->GetParent() ); diff --git a/src/game/client/swarm/vgui/playerlistline.h b/src/game/client/swarm/vgui/playerlistline.h index ae810bd70..54175f3b9 100644 --- a/src/game/client/swarm/vgui/playerlistline.h +++ b/src/game/client/swarm/vgui/playerlistline.h @@ -70,6 +70,7 @@ class PlayerListLine : public vgui::Panel, BaseModUI::IGenericPanelListItem vgui::Button *m_pPlayerLabel; vgui::Label *m_pMarinesLabel; CBitmapButton *m_pQuickReportButton; + CBitmapButton *m_pTracePlayerButton1; vgui::Label *m_pFragsLabel; vgui::Label *m_pDeathsLabel; vgui::Label *m_pPingLabel; diff --git a/src/game/client/swarm/vgui/playerlistpanel.cpp b/src/game/client/swarm/vgui/playerlistpanel.cpp index 8d16d8c98..7fa86a9c4 100644 --- a/src/game/client/swarm/vgui/playerlistpanel.cpp +++ b/src/game/client/swarm/vgui/playerlistpanel.cpp @@ -43,6 +43,7 @@ int g_asw_iPlayerListOpen = 0; ConVar rd_report_voted_players( "rd_report_voted_players", "0", FCVAR_ARCHIVE, "Automatically send a report when voting or muting a player on the player list." ); extern ConVar rd_debug_quick_report_local_player; +extern ConVar cl_trace_player_enable; PlayerListPanel::PlayerListPanel(vgui::Panel *parent, const char *name) : vgui::EditablePanel(parent, name) @@ -111,6 +112,9 @@ PlayerListPanel::PlayerListPanel(vgui::Panel *parent, const char *name) : m_pSettingAutoReportVotes = new CCvarToggleCheckButton( this, "SettingAutoReportVotes", "#rd_reporting_auto_preference", "rd_report_voted_players" ); m_pSettingAutoReportVotes->Reset(); + m_pTracePlayerToggle = new CCvarToggleCheckButton(this, "SettingTracePlayerToggle", "#asw_trace_player_enable", "cl_trace_player_enable"); + m_pTracePlayerToggle->Reset(); + m_pStartSavedCampaignVoteButton->SetButtonTexture("swarm/Briefing/ShadedButton"); m_pStartSavedCampaignVoteButton->SetButtonOverTexture("swarm/Briefing/ShadedButton_over"); @@ -164,13 +168,18 @@ PlayerListPanel::~PlayerListPanel() m_pSettingAutoReportVotes->ApplyChanges(); engine->ClientCmd_Unrestricted( "host_writeconfig\n" ); } + if (m_pTracePlayerToggle->HasBeenModified()) + { + m_pTracePlayerToggle->ApplyChanges(); + engine->ClientCmd_Unrestricted("host_writeconfig\n"); + } } void PlayerListPanel::ApplySchemeSettings(vgui::IScheme *pScheme) { BaseClass::ApplySchemeSettings(pScheme); - LoadControlSettings( "resource/ui/PlayerListPanel.res" ); + LoadControlSettings( "resource/ui/PlayerListPanel_1.res" ); vgui::HFont DefaultFont = pScheme->GetFont( "Default", IsProportional() ); m_pPlayerHeader->SetFont(DefaultFont); @@ -261,9 +270,9 @@ void PlayerListPanel::OnThink() // make sure we have enough line panels per player and that each line knows the index of the player its displaying int iNumPlayersInGame = 0; bool bNeedsLayout = false; - for ( int j = 1; j <= gpGlobals->maxClients; j++ ) - { - if ( g_PR->IsConnected( j ) ) + for (int j = 1; j <= gpGlobals->maxClients; j++) + { + if (g_PR->IsConnected(j)) { iNumPlayersInGame++; while (m_PlayerLine.Count() <= iNumPlayersInGame) @@ -271,10 +280,10 @@ void PlayerListPanel::OnThink() // temp comment m_PlayerLine.AddToTail(new PlayerListLine(this, "PlayerLine")); } - if ( m_PlayerLine.Count() > ( iNumPlayersInGame - 1 ) && m_PlayerLine[ iNumPlayersInGame - 1 ] ) + if (m_PlayerLine.Count() > (iNumPlayersInGame - 1) && m_PlayerLine[iNumPlayersInGame - 1]) { - m_PlayerLine[iNumPlayersInGame-1]->SetVisible(true); - if (m_PlayerLine[iNumPlayersInGame-1]->SetPlayerIndex(j)) + m_PlayerLine[iNumPlayersInGame - 1]->SetVisible(true); + if (m_PlayerLine[iNumPlayersInGame - 1]->SetPlayerIndex(j)) { bNeedsLayout = true; } @@ -284,43 +293,43 @@ void PlayerListPanel::OnThink() m_pTipsLabel->SetText(""); - IMatchSession *pSession = g_pMatchFramework->GetMatchSession(); - if ( pSession ) + IMatchSession* pSession = g_pMatchFramework->GetMatchSession(); + if (pSession) { - KeyValues *pSettings = pSession->GetSessionSettings(); - if ( pSettings ) + KeyValues* pSettings = pSession->GetSessionSettings(); + if (pSettings) { - m_pVisibilityLabel->SetVisible( !Q_stricmp( pSettings->GetString( "options/server" ), "listen") ); - m_pVisibilityButton->SetVisible( engine->IsClientLocalToActiveServer() ); + m_pVisibilityLabel->SetVisible(!Q_stricmp(pSettings->GetString("options/server"), "listen")); + m_pVisibilityButton->SetVisible(engine->IsClientLocalToActiveServer()); const char* tip; - if ( !Q_stricmp( pSettings->GetString( "system/access"), "public" ) ) + if (!Q_stricmp(pSettings->GetString("system/access"), "public")) { - m_pVisibilityLabel->SetText( "#L4D360UI_Lobby_PublicTitle" ); - m_pVisibilityButton->SetText( "#L4D360UI_Lobby_FriendsTitle" ); + m_pVisibilityLabel->SetText("#L4D360UI_Lobby_PublicTitle"); + m_pVisibilityButton->SetText("#L4D360UI_Lobby_FriendsTitle"); tip = "#L4D360UI_Lobby_MakeFriendOnly_Tip"; } else { - m_pVisibilityLabel->SetText( "#L4D360UI_Lobby_FriendsTitle" ); - m_pVisibilityButton->SetText( "#L4D360UI_Lobby_PublicTitle" ); + m_pVisibilityLabel->SetText("#L4D360UI_Lobby_FriendsTitle"); + m_pVisibilityButton->SetText("#L4D360UI_Lobby_PublicTitle"); tip = "#L4D360UI_Lobby_OpenToPublic_Tip"; } - if ( m_pVisibilityButton->IsCursorOver() ) - m_pTipsLabel->SetText( tip ); + if (m_pVisibilityButton->IsCursorOver()) + m_pTipsLabel->SetText(tip); } } else { - m_pVisibilityLabel->SetVisible( false ); - m_pVisibilityButton->SetVisible( false ); + m_pVisibilityLabel->SetVisible(false); + m_pVisibilityButton->SetVisible(false); } //m_pPlayerListScroll->SetScrollBarVisible( IsPC() && iNumPlayersInGame > 6); // hide any extra ones we might have - for (int i=iNumPlayersInGame;iSetVisible(false); } @@ -334,18 +343,18 @@ void PlayerListPanel::OnThink() } bool is_team_game = ASWDeathmatchMode() && ASWDeathmatchMode()->IsTeamDeathmatchEnabled(); - m_pTeam1ScoreLabel->SetVisible( is_team_game ); - m_pTeam2ScoreLabel->SetVisible( is_team_game ); + m_pTeam1ScoreLabel->SetVisible(is_team_game); + m_pTeam2ScoreLabel->SetVisible(is_team_game); - if ( is_team_game ) + if (is_team_game) { - C_Team *alpha_team = GetGlobalTeam( TEAM_ALPHA ); - C_Team *beta_team = GetGlobalTeam( TEAM_BETA ); + C_Team* alpha_team = GetGlobalTeam(TEAM_ALPHA); + C_Team* beta_team = GetGlobalTeam(TEAM_BETA); - if ( alpha_team && beta_team ) + if (alpha_team && beta_team) { - const char *t1_name = alpha_team->Get_Name(); - const char *t2_name = beta_team->Get_Name(); + const char* t1_name = alpha_team->Get_Name(); + const char* t2_name = beta_team->Get_Name(); if (t1_name && t2_name) { @@ -360,30 +369,33 @@ void PlayerListPanel::OnThink() wchar_t t1_wlabel[1024]; wchar_t t2_wlabel[1024]; - g_pVGuiLocalize->ConvertANSIToUnicode( t1_label, t1_wlabel, sizeof(t1_wlabel)); - g_pVGuiLocalize->ConvertANSIToUnicode( t2_label, t2_wlabel, sizeof(t2_wlabel)); + g_pVGuiLocalize->ConvertANSIToUnicode(t1_label, t1_wlabel, sizeof(t1_wlabel)); + g_pVGuiLocalize->ConvertANSIToUnicode(t2_label, t2_wlabel, sizeof(t2_wlabel)); - m_pTeam1ScoreLabel->SetText( t1_wlabel ); - m_pTeam2ScoreLabel->SetText( t2_wlabel ); + m_pTeam1ScoreLabel->SetText(t1_wlabel); + m_pTeam2ScoreLabel->SetText(t2_wlabel); } } else { - Warning( "Cannot get the needed team for displayin in UI \n" ); + Warning("Cannot get the needed team for displayin in UI \n"); } } - C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer(); + C_ASW_Player* pPlayer = C_ASW_Player::GetLocalASWPlayer(); bool bShowRestart = pPlayer && ASWGameResource() && ASWGameResource()->GetLeader() == pPlayer; //Msg("bLeader = %d leaderentindex=%d player entindex=%d\n", bLeader, ASWGameResource()->GetLeaderEntIndex(), pPlayer->entindex()); m_pRestartMissionButton->SetVisible(bShowRestart); - m_pLeaderButtonsBackground->SetVisible(bShowRestart); + m_pLeaderButtonsBackground->SetVisible(bShowRestart); UpdateServerName(); if (bNeedsLayout) InvalidateLayout(true); + + bool isDeathMatch = ASWDeathmatchMode() && (ASWDeathmatchMode()->IsDeathmatchEnabled() || ASWDeathmatchMode()->IsTeamDeathmatchEnabled()); + m_pTracePlayerToggle->SetVisible(!isDeathMatch); } void PlayerListPanel::KickClicked( PlayerListLine *pLine ) diff --git a/src/game/client/swarm/vgui/playerlistpanel.h b/src/game/client/swarm/vgui/playerlistpanel.h index 9ed473e26..4d674ea90 100644 --- a/src/game/client/swarm/vgui/playerlistpanel.h +++ b/src/game/client/swarm/vgui/playerlistpanel.h @@ -82,6 +82,7 @@ class PlayerListPanel : public vgui::EditablePanel vgui::Label* m_pCounterLabel; CCvarToggleCheckButton *m_pSettingAutoReportVotes; + CCvarToggleCheckButton* m_pTracePlayerToggle; vgui::DHANDLE m_hQuickReportPanel; char m_szMapName[64]; From f45786c94a3a053d5e8096db2aeb67c2a31d3119 Mon Sep 17 00:00:00 2001 From: ywgATustcbbs Date: Sat, 12 Jul 2025 11:01:33 +0800 Subject: [PATCH 11/13] more clean up --- src/game/client/swarm/c_asw_marine.cpp | 5 +---- src/game/client/swarm/c_asw_marine.h | 1 - src/game/client/swarm/vgui/asw_hud_emotes.cpp | 8 -------- 3 files changed, 1 insertion(+), 13 deletions(-) diff --git a/src/game/client/swarm/c_asw_marine.cpp b/src/game/client/swarm/c_asw_marine.cpp index d42b0f6cd..6321eb006 100644 --- a/src/game/client/swarm/c_asw_marine.cpp +++ b/src/game/client/swarm/c_asw_marine.cpp @@ -121,12 +121,10 @@ Color g_TraceColorArray[8] = }; std::vector g_nTracePlayer2Color = std::vector(MAX_PLAYERS, 0); std::vector g_nTraceColor2Player = std::vector(8, 0); -float TRACE_FADE_TIME = 60.0f; // how long to keep the trace positions for ConVar cl_trace_player_enable("cl_trace_player_enable", "0", FCVAR_ARCHIVE | FCVAR_CLIENTDLL, "Show player movement traces in the client. 0 = disabled, 1 = enabled."); ConVar cl_trace_player_max_targets("cl_trace_player_max_targets", "3", FCVAR_ARCHIVE | FCVAR_CLIENTDLL, "Maximum number of players to trace positions for in the client.", true, 1.0f, true, 7.0f); +ConVar cl_trace_player_fadeout_time("cl_trace_player_fadeout_time", "-1", FCVAR_ARCHIVE | FCVAR_CLIENTDLL, "Trace fadeout time."); ConVar cl_trace_player_opacity("cl_trace_player_opacity", "1", FCVAR_ARCHIVE | FCVAR_CLIENTDLL, "Opacity of the player trace positions in the client. 0.0 means fully transparent, 1.0 means fully opaque.", true, 0.0f, true, 1.0f); -//ConVar cl_trace_player_line_thickness("cl_trace_player_line_thickness", "30", FCVAR_ARCHIVE | FCVAR_CLIENTDLL, "Thickness of the player trace.", true, 1.0f, true, 100.0f); -//ConVar cl_trace_player_border_thickness("cl_trace_player_border_thickness", "5", FCVAR_ARCHIVE | FCVAR_CLIENTDLL, "Thickness of the player trace border.", true, 1.0f, true, 10.0f); void RemoveInvalidTracePlayersAndColors() { @@ -1158,7 +1156,6 @@ void C_ASW_Marine::TickTrace(float d) // get current marine position struct MovementTrace_t movement; movement.m_flTimestamp = gpGlobals->curtime; - movement.m_flTraceTime = TRACE_FADE_TIME; movement.m_vecPosition = m_vecCurrentTraceOrigin; m_lstTrace.push_back(movement); diff --git a/src/game/client/swarm/c_asw_marine.h b/src/game/client/swarm/c_asw_marine.h index 4ea66c7bb..a686a248d 100644 --- a/src/game/client/swarm/c_asw_marine.h +++ b/src/game/client/swarm/c_asw_marine.h @@ -24,7 +24,6 @@ struct MovementTrace_t { float m_flTimestamp; - float m_flTraceTime; Vector m_vecPosition; float m_flAngleDegree; }; diff --git a/src/game/client/swarm/vgui/asw_hud_emotes.cpp b/src/game/client/swarm/vgui/asw_hud_emotes.cpp index 5c1ded773..81d1032e5 100644 --- a/src/game/client/swarm/vgui/asw_hud_emotes.cpp +++ b/src/game/client/swarm/vgui/asw_hud_emotes.cpp @@ -45,12 +45,9 @@ using namespace vgui; extern ConVar asw_draw_hud; #ifdef CLIENT_DLL -extern float TRACE_FADE_TIME; extern ConVar cl_trace_player_enable; extern ConVar cl_trace_player_opacity; extern ConVar cl_trace_player_max_targets; -//extern ConVar cl_trace_player_line_thickness; -//extern ConVar cl_trace_player_border_thickness; extern Color g_TraceColorArray[8]; extern std::vector g_nTracePlayer2Color; extern std::vector g_nTraceColor2Player; @@ -365,11 +362,6 @@ void CASWHudEmotes::PaintTracesFor(C_ASW_Marine* pMarine, Color color) } Vector vecPosition = iter->m_vecPosition; - if (iter->m_flTraceTime <= 0) - { - continue; // no trace to draw - } - if (!debugoverlay->ScreenPosition(vecPosition, screenPos)) { xPos = screenPos[0]; From d00ec4e28c2c11f2ecfa76a9de1d8c07456e81aa Mon Sep 17 00:00:00 2001 From: ywgATustcbbs Date: Sat, 12 Jul 2025 11:09:22 +0800 Subject: [PATCH 12/13] fix mistake --- src/game/client/swarm/vgui/playerlistpanel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/client/swarm/vgui/playerlistpanel.cpp b/src/game/client/swarm/vgui/playerlistpanel.cpp index 7fa86a9c4..d6b749626 100644 --- a/src/game/client/swarm/vgui/playerlistpanel.cpp +++ b/src/game/client/swarm/vgui/playerlistpanel.cpp @@ -179,7 +179,7 @@ void PlayerListPanel::ApplySchemeSettings(vgui::IScheme *pScheme) { BaseClass::ApplySchemeSettings(pScheme); - LoadControlSettings( "resource/ui/PlayerListPanel_1.res" ); + LoadControlSettings( "resource/ui/PlayerListPanel.res" ); vgui::HFont DefaultFont = pScheme->GetFont( "Default", IsProportional() ); m_pPlayerHeader->SetFont(DefaultFont); From 4b896b9e394c7074f7ba58cf3c19003a4dbf97d7 Mon Sep 17 00:00:00 2001 From: ywgATustcbbs Date: Mon, 4 Aug 2025 00:15:12 +0800 Subject: [PATCH 13/13] fix missing } --- src/game/client/swarm/vgui/asw_hud_emotes.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/game/client/swarm/vgui/asw_hud_emotes.cpp b/src/game/client/swarm/vgui/asw_hud_emotes.cpp index 381436de9..8716549b3 100644 --- a/src/game/client/swarm/vgui/asw_hud_emotes.cpp +++ b/src/game/client/swarm/vgui/asw_hud_emotes.cpp @@ -430,6 +430,9 @@ void CASWHudEmotes::PaintTracesFor(C_ASW_Marine* pMarine, Color color) surface()->DrawTexturedPolygon(4, points); } + } + } +} void CASWHudEmotes::PaintTraitorEmote(C_BaseEntity* pEnt, int iTexture, float fEmoteScale) {