Skip to content

Commit f52b556

Browse files
tilgepVauff
andauthored
Entwatch dropped item glow (#360)
* Add item weapon glow on drop - Cvar `entwatch_glow` to toggle - glowrange of 1000 so items far away aren't visible * Adjust colours * Change cvar from toggle to a distance * Add team-only glow cvar + no glow on empty items - might need to add a cvar for setting if a handler is rechargeable for better 'empty' detection * Fix missing glow colour initialisation * Glow the weapon model - Remove glowing prop ngl feels like it could break at any moment but has worked in testing * Remove random alpha Works without it :) * Fix unsafe timer args --------- Co-authored-by: Alex <mctehkitti@gmail.com>
1 parent e92db96 commit f52b556

File tree

5 files changed

+204
-4
lines changed

5 files changed

+204
-4
lines changed

cfg/cs2fixes/cs2fixes.cfg

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,3 +147,5 @@ entwatch_enable 0 // INCOMPATIBLE WITH CS#. Whether to enable EntWatch feat
147147
entwatch_auto_filter 1 // Whether to automatically block non-item holders from triggering uses
148148
entwatch_clantag 1 // Whether to set item holder's clantag and set 9999 score
149149
entwatch_score 9999 // Score to give item holders (0 = dont change score at all) Requires entwatch_clantag 1
150+
entwatch_glow 1000 // Distance that dropped item weapon glow will be visible (0 = glow disabled)
151+
entwatch_glow_team 0 // Whether dropped item glow is only visible to the team the item belongs to (0 = glow to all players)

src/cs2_sdk/entity/ccsweaponbase.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
#pragma once
2121

22-
#include "cbaseentity.h"
22+
#include "cbasemodelentity.h"
2323

2424
extern CGlobalVars* GetGlobals();
2525

@@ -61,7 +61,7 @@ class CAttributeContainer
6161
SCHEMA_FIELD(CEconItemView, m_Item)
6262
};
6363

64-
class CEconEntity : public CBaseEntity
64+
class CEconEntity : public CBaseModelEntity
6565
{
6666
public:
6767
DECLARE_SCHEMA_CLASS(CEconEntity)

src/cs2_sdk/entity/globaltypes.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,5 +224,8 @@ class CGlowProperty
224224
SCHEMA_FIELD(int, m_nGlowRangeMin)
225225
SCHEMA_FIELD(Color, m_glowColorOverride)
226226
SCHEMA_FIELD(bool, m_bFlashing)
227+
SCHEMA_FIELD(float, m_flGlowTime)
228+
SCHEMA_FIELD(float, m_flGlowStartTime)
229+
SCHEMA_FIELD(bool, m_bEligibleForScreenHighlight)
227230
SCHEMA_FIELD(bool, m_bGlowing)
228231
};

src/entwatch.cpp

Lines changed: 189 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,37 @@ SH_DECL_MANUALHOOK1_void(CTriggerMultiple_EndTouch, 0, 0, 0, CBaseEntity*);
7575
CConVar<bool> g_cvarEnableEntWatch("entwatch_enable", FCVAR_NONE, "INCOMPATIBLE WITH CS#. Whether to enable EntWatch features", false);
7676
CConVar<bool> g_cvarEnableFiltering("entwatch_auto_filter", FCVAR_NONE, "Whether to automatically block non-item holders from triggering uses", true);
7777
CConVar<bool> g_cvarUseEntwatchClantag("entwatch_clantag", FCVAR_NONE, "Whether to set item holder's clantag and set score", true);
78-
7978
CConVar<int> g_cvarItemHolderScore("entwatch_score", FCVAR_NONE, "Score to give item holders (0 = dont change score at all) Requires entwatch_clantag 1", 9999, true, 0, false, 0);
8079

80+
void ItemGlowDistanceChanged(CConVar<int>* ref, CSplitScreenSlot nSlot, const int* pNewValue, const int* pOldValue)
81+
{
82+
if (!g_pEWHandler || !g_pEWHandler->IsConfigLoaded() || g_pEWHandler->vecItems.size() < 1)
83+
return;
84+
85+
int newValue = *pNewValue;
86+
for (int i = 0; i < g_pEWHandler->vecItems.size(); i++)
87+
{
88+
std::shared_ptr<EWItemInstance> item = g_pEWHandler->vecItems[i];
89+
CCSWeaponBase* pItemWeapon = (CCSWeaponBase*)g_pEntitySystem->GetEntityInstance((CEntityIndex)item->iWeaponEnt);
90+
if (!pItemWeapon)
91+
continue;
92+
93+
if (pItemWeapon->m_Glow().m_bGlowing)
94+
{
95+
if (newValue > 0)
96+
pItemWeapon->m_Glow().m_nGlowRange = newValue;
97+
else
98+
item->EndGlow();
99+
}
100+
else if (item->bShouldGlow && newValue > 0)
101+
{
102+
item->StartGlow();
103+
}
104+
}
105+
}
106+
CConVar<int> g_cvarItemDroppedGlow("entwatch_glow", FCVAR_NONE, "Distance that dropped item weapon glow will be visible (0 = glow disabled)", 1000, true, 0, false, 0, ItemGlowDistanceChanged);
107+
CConVar<bool> g_cvarItemDroppedGlowTeam("entwatch_glow_team", FCVAR_NONE, "Whether dropped item glow is only visible to the team the item belongs to (0 = glow to all players)", false);
108+
81109
void EWItemHandler::SetDefaultValues()
82110
{
83111
type = EWHandlerType::Other;
@@ -462,6 +490,7 @@ void EWItem::SetDefaultValues()
462490
szShortName = "";
463491
/* no default hammerid */
464492
V_strcpy(sChatColor, "\x01");
493+
colorGlow = Color(255, 255, 255, 255);
465494
bShowPickup = true;
466495
bShowHud = true;
467496
transfer = EWCfg_Auto;
@@ -473,36 +502,81 @@ void EWItem::SetDefaultValues()
473502
void EWItem::ParseColor(std::string value)
474503
{
475504
if (value == "white" || value == "default")
505+
{
476506
V_strcpy(sChatColor, "\x01");
507+
colorGlow = Color(255, 255, 255, 255);
508+
}
477509
else if (value == "darkred")
510+
{
478511
V_strcpy(sChatColor, "\x02");
512+
colorGlow = Color(220, 0, 0, 255);
513+
}
479514
else if (value == "team")
515+
{
480516
V_strcpy(sChatColor, "\x03");
517+
colorGlow = Color(184, 130, 242, 255);
518+
}
481519
else if (value == "green")
520+
{
482521
V_strcpy(sChatColor, "\x04");
522+
colorGlow = Color(30, 255, 30, 255);
523+
}
483524
else if (value == "lightgreen")
525+
{
484526
V_strcpy(sChatColor, "\x05");
527+
colorGlow = Color(178, 255, 145, 255);
528+
}
485529
else if (value == "olive")
530+
{
486531
V_strcpy(sChatColor, "\x06");
532+
colorGlow = Color(184, 220, 63, 255);
533+
}
487534
else if (value == "red")
535+
{
488536
V_strcpy(sChatColor, "\x07");
537+
colorGlow = Color(255, 65, 65, 255);
538+
}
489539
else if (value == "gray" || value == "grey")
540+
{
490541
V_strcpy(sChatColor, "\x08");
542+
colorGlow = Color(175, 180, 180, 255);
543+
}
491544
else if (value == "yellow")
545+
{
492546
V_strcpy(sChatColor, "\x09");
547+
colorGlow = Color(250, 250, 25, 255);
548+
}
493549
else if (value == "silver")
550+
{
494551
V_strcpy(sChatColor, "\x0A");
552+
colorGlow = Color(165, 180, 210, 255);
553+
}
495554
else if (value == "blue")
555+
{
496556
V_strcpy(sChatColor, "\x0B");
557+
colorGlow = Color(114, 188, 255, 255);
558+
}
497559
else if (value == "darkblue")
560+
{
498561
V_strcpy(sChatColor, "\x0C");
562+
colorGlow = Color(45, 75, 255, 255);
563+
}
499564
// \x0D is the same as \x0A
500565
else if (value == "purple" || value == "pink")
566+
{
501567
V_strcpy(sChatColor, "\x0E");
568+
colorGlow = Color(210, 43, 229, 255);
569+
}
502570
else if (value == "red2")
571+
{
503572
V_strcpy(sChatColor, "\x0F");
573+
colorGlow = Color(230, 120, 120, 255);
574+
}
504575
else if (value == "orange" || value == "gold")
576+
{
505577
V_strcpy(sChatColor, "\x10");
578+
colorGlow = Color(235, 145, 46, 255);
579+
}
506580
}
507581

508582
EWItem::EWItem(std::shared_ptr<EWItem> pItem)
@@ -512,6 +586,7 @@ EWItem::EWItem(std::shared_ptr<EWItem> pItem)
512586
szShortName = pItem->szShortName;
513587
szHammerid = pItem->szHammerid;
514588
V_strcpy(sChatColor, pItem->sChatColor);
589+
colorGlow = pItem->colorGlow;
515590
bShowPickup = pItem->bShowPickup;
516591
bShowHud = pItem->bShowHud;
517592
transfer = pItem->transfer;
@@ -740,6 +815,9 @@ void EWItemInstance::Pickup(int slot)
740815
}
741816
}
742817

818+
bShouldGlow = false;
819+
EndGlow();
820+
743821
if (bShowPickup)
744822
ClientPrintAll(HUD_PRINTTALK, EW_PREFIX "\x03%s \x05has picked up %s%s", pController->GetPlayerName(), sChatColor, szItemName.c_str());
745823
}
@@ -753,6 +831,9 @@ void EWItemInstance::Drop(EWDropReason reason, CCSPlayerController* pController)
753831
return;
754832
}
755833

834+
if (bAllowDrop)
835+
bShouldGlow = true;
836+
756837
if (g_cvarUseEntwatchClantag.Get() && bShowHud && bHasThisClantag)
757838
{
758839
bool bSetAnotherClantag = false;
@@ -845,10 +926,16 @@ void EWItemInstance::Drop(EWDropReason reason, CCSPlayerController* pController)
845926
}
846927
break;
847928
case EWDropReason::Deleted:
929+
bShouldGlow = false;
930+
break;
848931
default:
849932
break;
850933
}
851934

935+
// Start glowing
936+
if (g_cvarItemDroppedGlow.Get() > 0 && reason != EWDropReason::Deleted && bAllowDrop)
937+
StartGlow();
938+
852939
iOwnerSlot = -1;
853940
}
854941

@@ -877,6 +964,107 @@ std::string EWItemInstance::GetHandlerStateText()
877964
return sText;
878965
}
879966

967+
void EWItemInstance::StartGlow()
968+
{
969+
if (IsEmpty())
970+
return;
971+
972+
if (!GetGlobals())
973+
{
974+
Message("Failed to get globals while glowing dropped item\n");
975+
return;
976+
}
977+
978+
CCSWeaponBase* pItemWeapon = (CCSWeaponBase*)g_pEntitySystem->GetEntityInstance((CEntityIndex)iWeaponEnt);
979+
if (!pItemWeapon)
980+
{
981+
Message("Error getting weapon entity while creating item glow.\n");
982+
return;
983+
}
984+
985+
int r = colorGlow.r();
986+
int g = colorGlow.g();
987+
int b = colorGlow.b();
988+
int a = colorGlow.a();
989+
int iTeam = iTeamNum;
990+
CHandle<CCSWeaponBase> hWep = pItemWeapon->GetHandle();
991+
new CTimer(0.1f, false, false, [hWep, iTeam, r, g, b, a] {
992+
CCSWeaponBase* pWep = hWep.Get();
993+
if (pWep)
994+
{
995+
pWep->m_Glow().m_glowColorOverride = Color(r, g, b, a);
996+
997+
int team = g_cvarItemDroppedGlowTeam.Get() ? iTeam : -1;
998+
pWep->m_Glow().m_iGlowTeam = team;
999+
1000+
pWep->m_Glow().m_iGlowType = 3;
1001+
pWep->m_Glow().m_flGlowStartTime = GetGlobals()->curtime;
1002+
pWep->m_Glow().m_flGlowTime = 0;
1003+
pWep->m_Glow().m_nGlowRange = g_cvarItemDroppedGlow.Get();
1004+
pWep->m_Glow().m_bGlowing = true;
1005+
}
1006+
return -1.0f;
1007+
});
1008+
}
1009+
1010+
void EWItemInstance::EndGlow()
1011+
{
1012+
CCSWeaponBase* pItemWeapon = (CCSWeaponBase*)g_pEntitySystem->GetEntityInstance((CEntityIndex)iWeaponEnt);
1013+
if (pItemWeapon)
1014+
{
1015+
pItemWeapon->m_Glow().m_glowColorOverride = Color(0, 0, 0, 0);
1016+
pItemWeapon->m_Glow().m_iGlowType = 0;
1017+
pItemWeapon->m_Glow().m_iGlowTeam = -1;
1018+
pItemWeapon->m_Glow().m_flGlowStartTime = 0;
1019+
pItemWeapon->m_Glow().m_flGlowTime = 0;
1020+
pItemWeapon->m_Glow().m_nGlowRange = 0;
1021+
pItemWeapon->m_Glow().m_bGlowing = false;
1022+
}
1023+
}
1024+
1025+
bool EWItemInstance::IsEmpty()
1026+
{
1027+
// Empty items don't glow when dropped, so have to be careful since some items can recharge
1028+
// Only return true if ALL handlers that appear in any way (chat/ui) are empty (non-counter max-uses)
1029+
// If it has no visible handlers, its not empty
1030+
//
1031+
// TODO: maybe add an optional config setting for whether a handler is rechargable (depends if people complain)
1032+
1033+
if (vecHandlers.size() < 1)
1034+
return false;
1035+
1036+
// True until proven otherwise
1037+
bool bAllInvisible = true;
1038+
bool bAllEmpty = true;
1039+
1040+
for (int i = 0; i < vecHandlers.size(); i++)
1041+
{
1042+
// Any visible counter or non-maxuses handlers are never empty
1043+
if ((vecHandlers[i]->bShowHud || vecHandlers[i]->bShowUse) && vecHandlers[i]->szOutput != "")
1044+
{
1045+
if (vecHandlers[i]->IsCounter() || vecHandlers[i]->mode != EWHandlerMode::MaxUses)
1046+
{
1047+
return false;
1048+
}
1049+
1050+
// Maxuses handler (can be empty)
1051+
// Check if it is empty
1052+
bAllInvisible = false;
1053+
if (vecHandlers[i]->iCurrentUses < vecHandlers[i]->iMaxUses)
1054+
bAllEmpty = false;
1055+
}
1056+
else
1057+
{
1058+
// Invisible handler / no ouput
1059+
}
1060+
}
1061+
1062+
if (bAllInvisible)
1063+
return false;
1064+
1065+
return bAllEmpty;
1066+
}
1067+
8801068
void CEWHandler::UnLoadConfig()
8811069
{
8821070
if (!bConfigLoaded)

src/entwatch.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ struct EWItemHandler
115115
float flLastUsed; // For tracking cd on the hud
116116
float flLastShownUse; // To prevent too much chat spam
117117

118+
bool IsCounter() { return (type == EWHandlerType::CounterDown || type == EWHandlerType::CounterUp); }
118119
void SetDefaultValues();
119120
void Print();
120121

@@ -136,6 +137,7 @@ struct EWItem
136137
std::string szShortName; /* Name to show on hud/scoreboard */
137138
std::string szHammerid; /* Hammerid of the weapon */
138139
char sChatColor[2];
140+
Color colorGlow;
139141
bool bShowPickup; /* Whether to show pickup/drop messages in chat */
140142
bool bShowHud; /* Whether to show this item on hud/scoreboard */
141143
EWAutoConfigOption transfer; /* Can this item be transferred */
@@ -161,6 +163,7 @@ struct EWItemInstance : EWItem /* Current instance of defined items */
161163
bool bHasThisClantag;
162164
int iTeamNum;
163165
std::string sLastOwnerName; // For etransfer info
166+
bool bShouldGlow;
164167

165168
public:
166169
EWItemInstance(int iWeapon, std::shared_ptr<EWItem> pItem) :
@@ -171,7 +174,8 @@ struct EWItemInstance : EWItem /* Current instance of defined items */
171174
bAllowDrop(true),
172175
sClantag(""),
173176
bHasThisClantag(false),
174-
iTeamNum(CS_TEAM_NONE){};
177+
iTeamNum(CS_TEAM_NONE),
178+
bShouldGlow(false) {};
175179
bool RegisterHandler(CBaseEntity* pEnt, int iHandlerTemplateNum);
176180
bool RemoveHandler(CBaseEntity* pEnt);
177181
int FindHandlerByEntIndex(int indexToFind);
@@ -180,6 +184,9 @@ struct EWItemInstance : EWItem /* Current instance of defined items */
180184
void Pickup(int slot);
181185
void Drop(EWDropReason reason, CCSPlayerController* pController);
182186
std::string GetHandlerStateText();
187+
void StartGlow();
188+
void EndGlow();
189+
bool IsEmpty();
183190
};
184191

185192
struct ETransferInfo

0 commit comments

Comments
 (0)