Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
5933096
Remove map system KeyValues config converter
Vauff Aug 18, 2025
9b323bc
Remove leftover patch
Vauff Aug 18, 2025
45ba3da
More std migrations + timer refactor
Vauff Aug 21, 2025
63dfc87
Use smart pointers to store our commands
Vauff Aug 21, 2025
16b1188
Clean up extern usage, move them all into respective headers
Vauff Aug 22, 2025
f981a47
Automatically reload map config at map change if edits were made
Vauff Aug 22, 2025
02e54da
Wait/retry when map downloads get rate limited?
Vauff Aug 22, 2025
b73cea2
Refactor most map access to be object oriented
Vauff Aug 30, 2025
79a96fd
Fix map names that appeared in other map names being unselectable
Vauff Aug 30, 2025
69b6e1b
Migrate saved cooldowns storage to JSON
Vauff Aug 30, 2025
cf1beda
Query workshop ID's in HandlePlayerMapLookup for various information
Vauff Aug 31, 2025
6b4f854
Fix jump bug when subtick movement was disabled
Vauff Sep 2, 2025
921b7dd
Fix HandlePlayerMapLookup crash
Vauff Sep 3, 2025
c5305be
Teleport flashlight whenever toggled on
xen-000 Sep 10, 2025
cb97e36
Send rcon output to the player
xen-000 Sep 10, 2025
e71a7aa
Fix gcc complain about missing std::optional (#382)
hzqst Sep 10, 2025
56802bf
Fix timing of map vote end detection
Vauff Sep 14, 2025
59869e6
Reset default ZR class scales
Vauff Sep 17, 2025
fcd7d90
Update signatures for 2025-09-16 CS2 update
Vauff Sep 17, 2025
f984e1e
Update SDK
Vauff Sep 17, 2025
038a01d
Update offsets for 2025-09-16 CS2 update
Vauff Sep 17, 2025
2120b66
Additional fixes for previous update + WIP 2025-09-17 update fixes
Vauff Sep 18, 2025
1e45e84
Update movement unlocker patch for Windows
xen-000 Sep 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cfg/cs2fixes/cs2fixes.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ cs2f_flashlight_shadows 1 // Whether to enable flashlight shadows
cs2f_flashlight_transmit_others 0 // Whether to transmit other players' flashlights, recommended to have shadows disabled with this
cs2f_flashlight_brightness 1.0 // How bright should flashlights be
cs2f_flashlight_distance 54 // How far flashlights should be from the player's head (the default is such that an equipped awp doesn't block the light if shadows are enabled)
cs2f_flashlight_angle 45.0 // How wide should the flashlight be in degrees
cs2f_flashlight_color "255 255 255 0" // What color to use for flashlights
cs2f_flashlight_attachment axis_of_intent // Which attachment to parent a flashlight to. If the player model is not properly setup, you might have to use clip_limit here instead

Expand Down
4 changes: 2 additions & 2 deletions configs/zr/playerclass.jsonc.example
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
]
}
],
"scale": 1.05,
"scale": 1.0,
"speed": 1.0,
"gravity": 1.0,
"knockback": 1.0,
Expand All @@ -91,7 +91,7 @@
]
}
],
"scale": 1.15,
"scale": 1.0,
"speed": 1.0,
"gravity": 1.0,
"admin_flag": "",
Expand Down
45 changes: 20 additions & 25 deletions gamedata/cs2fixes.games.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@
"ServerMovementUnlock"
{
"library" "server"
"windows" "\x76\x2A\xF2\x0F\x10\x4E\x2A\x41\x0F\x28\xD2\x0F\x28\xC1"
"linux" "\x0F\x87\x2A\x2A\x2A\x2A\x49\x8B\x7C\x24\x2A\x48\x85\xFF"
"windows" "\x0F\x86\xB8\x2A\x2A\x2A\xF3\x0F\x58\xD4"
"linux" "\x0F\x87\x2A\x2A\x2A\x2A\xF3\x0F\x10\x3D\x2A\x2A\x2A\x2A\xF3\x0F\x11\xBD"
}
// String: "CCSPlayerPawnBase::SwitchTeam", just keep in mind this is actually CCSPlayerController::SwitchTeam
"CCSPlayerController_SwitchTeam"
Expand All @@ -57,7 +57,7 @@
{
"library" "server"
"windows" "\xC8\x42\xEB\x2A\x4C\x39\x67\x30"
"linux" "\xC8\x42\xEB\x2A\x48\x89\xDF\xE8\x2A\x2A\x2A\x2A"
"linux" "\xC8\x42\x41\xC7\x85\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\xE9\x2A\x2A\x2A\x2A\x4C\x89\xE7"
}
// Called right after "Removed %s(%s)\n"
"UTIL_Remove"
Expand Down Expand Up @@ -102,7 +102,7 @@
{
"library" "server"
"windows" "\x48\x83\xEC\x68\x45\x33\xC9"
"linux" "\x55\x45\x31\xC0\x31\xC9\x48\x89\xE5\x53"
"linux" "\x55\x45\x31\xC0\x31\xC9\x48\x89\xE5\x53\x48\x8D\x5D\x2A\x48\x83\xEC\x2A\x48\x89\xDF"
}
// "commentary_semaphore" is passed to this
"CGameEntitySystem_FindEntityByName"
Expand Down Expand Up @@ -161,7 +161,7 @@
{
"library" "server"
"windows" "\x48\x89\x5C\x24\x2A\x44\x89\x4C\x24\x2A\x48\x89\x54\x24\x2A\x48\x89\x4C\x24\x2A\x55\x56\x57\x41\x54\x41\x55\x41\x56\x41\x57\x48\x8D\xAC\x24"
"linux" "\x55\x48\x8D\x05\x2A\x2A\x2A\x2A\x48\x89\xE5\x41\x57\x4D\x89\xC7"
"linux" "\x55\x48\x8D\x05\x2A\x2A\x2A\x2A\x48\x89\xE5\x41\x57\x41\x56\x41\x55\x49\x89\xD5\x41\x54\x4C\x8D\x25"
}
// Search "Changes's player's model", look for a function containing 'models/%s.vmdl'. Below V_snprintf is the one
// This matches 2 functions, however they're literally identical
Expand Down Expand Up @@ -199,7 +199,7 @@
{
"library" "server"
"windows" "\x48\x89\x5C\x24\x10\x57\x48\x83\xEC\x30\x48\x8B\xDA\x48\x8B\xF9\x48\x85\xC9"
"linux" "\x48\x85\xFF\x74\x2A\x55\x48\x89\xE5\x41\x55\x41\x54\x49\x89\xFC"
"linux" "\x48\x85\xFF\x74\x2A\x55\x48\x89\xE5\x41\x55\x49\x89\xFD"
}
// Look for "SetEntityName", that will be the vscript binding definition
// Scroll a bit down and you'll find something like this (note the offset): *(_QWORD *)(v453 + 64) = sub_1807B0350;
Expand Down Expand Up @@ -251,7 +251,7 @@
"CNetworkStringTable_DeleteAllStrings"
{
"library" "engine"
"windows" "\x48\x89\x5C\x24\x2A\x48\x89\x6C\x24\x2A\x48\x89\x74\x24\x2A\x48\x89\x7C\x24\x2A\x41\x56\x48\x83\xEC\x2A\x45\x33\xF6\x48\x8B\xD9"
"windows" "\x48\x89\x5C\x24\x2A\x48\x89\x7C\x24\x2A\x41\x56\x48\x83\xEC\x2A\x45\x33\xF6"
"linux" "\x55\x48\x89\xE5\x41\x57\x41\x56\x41\x55\x41\x54\x45\x31\xE4\x53\x48\x89\xFB\x48\x83\xEC\x2A\x48\x83\x7F"
}
// "PlayerMovementTraces"
Expand Down Expand Up @@ -321,7 +321,7 @@
{
"library" "server"
"windows" "\x4C\x89\x44\x24\x2A\xF3\x0F\x11\x4C\x24\x2A\x55\x53\x56"
"linux" "\x55\x48\x89\xE5\x41\x57\x49\x89\xFF\x41\x56\x48\x8D\x3D\x2A\x2A\x2A\x2A\x41\x55\x41\x54\x53\x48\x81\xEC"
"linux" "\x55\x48\x89\xE5\x41\x57\x41\x56\x41\x55\x49\x89\xFD\x41\x54\x48\x8D\x3D\x2A\x2A\x2A\x2A\x53\x48\x81\xEC"
}
"TraceFunc"
{
Expand All @@ -334,7 +334,7 @@
{
"library" "server"
"windows" "\x48\x89\x5C\x24\x2A\x48\x89\x4C\x24\x2A\x55\x57"
"linux" "\x55\x48\x89\xE5\x41\x57\x49\x89\xCF\x41\x56\x41\x55\x4D\x89\xC5\x41\x54\x49\x89\xD4\x53\x4C\x89\xCB"
"linux" "\x55\x48\x89\xE5\x41\x57\x49\x89\xCF\x41\x56\x49\x89\xF6\x41\x55\x4D\x89\xC5"
}
"CBasePlayerPawn_GetEyePosition"
{
Expand Down Expand Up @@ -459,28 +459,28 @@
}
"CCSPlayerController_Respawn"
{
"windows" "274"
"linux" "276"
"windows" "275"
"linux" "277"
}
// CBaseTrigger
"PassesTriggerFilters"
{
"windows" "268"
"linux" "269"
"windows" "269"
"linux" "270"
}
// Long function with "player_hurt" in the middle and then inserts userid, health, priority, attacker strings
"CBasePlayerPawn::OnTakeDamage_Alive"
{
"windows" "251"
"linux" "252"
"windows" "252"
"linux" "253"
}
// Look for the kill command, go through its callback and you should a find call like this, with v9 being a pawn pointer:
// return (*(*v9 + 2976LL))(v9, v27, 0LL);
// 2976 (372 * 8) is the offset
"CBasePlayerPawn_CommitSuicide"
{
"windows" "403"
"linux" "403"
"windows" "408"
"linux" "408"
}
"GameEntitySystem"
{
Expand All @@ -495,8 +495,8 @@
}
"CCSGameRules_GoToIntermission"
{
"windows" "124"
"linux" "125"
"windows" "127"
"linux" "128"
}
"CheckTransmitPlayerSlot"
{
Expand Down Expand Up @@ -544,19 +544,14 @@
// Server
"ServerMovementUnlock"
{
"windows" "\xEB"
"windows" "\xE9\xB9\x00\x00\x00\x90"
"linux" "\x90\x90\x90\x90\x90\x90"
}
"FixWaterFloorJump"
{
"windows" "\x11\x43"
"linux" "\x11\x43"
}
"WaterLevelGravity"
{
"windows" "\x3C\x02"
"linux" "\x3C\x02"
}
// Jumping over a check for nav mesh
"BotNavIgnore"
{
Expand Down
2 changes: 0 additions & 2 deletions src/addresses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@

#include "tier0/memdbgon.h"

extern CGameConfig* g_GameConfig;

#define RESOLVE_SIG(gameConfig, name, variable) \
variable = (decltype(variable))gameConfig->ResolveSignature(name); \
if (!variable) \
Expand Down
64 changes: 57 additions & 7 deletions src/adminsystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,6 @@
#undef snprintf
#include "vendor/nlohmann/json.hpp"

extern IVEngineServer2* g_pEngineServer2;
extern CGameEntitySystem* g_pEntitySystem;
extern CGlobalVars* GetGlobals();
extern CCSGameRules* g_pGameRules;
extern CPlayerManager* g_playerManager;
extern CUtlVector<CServerSideClient*>* GetClientList();

CAdminSystem* g_pAdminSystem = nullptr;

void ParseInfraction(const CCommand& args, CCSPlayerController* pAdmin, bool bAdding, CInfractionBase::EInfractionType infType);
Expand Down Expand Up @@ -584,6 +577,8 @@ CON_COMMAND_CHAT_FLAGS(hsay, "<message> - Say something as a hud hint", ADMFLAG_
EscapeHTMLSpecialCharacters(args.ArgS()).c_str());
}

CLoggingListener g_LoggingListener;

CON_COMMAND_CHAT_FLAGS(rcon, "<command> - Send a command to server console", ADMFLAG_RCON)
{
if (!player)
Expand All @@ -598,7 +593,62 @@ CON_COMMAND_CHAT_FLAGS(rcon, "<command> - Send a command to server console", ADM
return;
}

// Normally this should be done on plugin init, but for whatever reason "log_flags <channel> +donotecho" crashes AFTER this
ExecuteOnce
(
LoggingSystem_RegisterBackdoorLoggingListener(&g_LoggingListener);
LoggingSystem_EnableBackdoorLoggingListeners(true);
);

// We don't have the equivalent of ServerExecute (to immediately execute commands) in source2, so manually find and execute the command

ConCommandRef cmdRef(args[1], true);

if (cmdRef.IsValidRef())
{
CCommandContext context(CT_FIRST_SPLITSCREEN_CLIENT, player->GetPlayerSlot());

CCommand newArgs;
newArgs.Tokenize(args.ArgS());

ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Command executed, see console for output (if any)");

g_LoggingListener.SetPlayer(player);
cmdRef.Dispatch(context, newArgs);
g_LoggingListener.SetPlayer(nullptr);

return;
}

ConVarRefAbstract cvarRef(args[1], true);

if (cvarRef.IsValidRef())
{
ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Command executed, see console for output (if any)");

if (args.ArgC() == 2)
{
g_LoggingListener.SetPlayer(player);
ConVar_PrintDescription(&cvarRef);
g_LoggingListener.SetPlayer(nullptr);

return;
}

CCommand newArgs;
newArgs.Tokenize(args.ArgS());

g_LoggingListener.SetPlayer(player);
cvarRef.SetString(newArgs.ArgS());
g_LoggingListener.SetPlayer(nullptr);

return;
}

// Just in case it's not an actual ConCommand (for example an alias)
g_pEngineServer2->ServerCommand(args.ArgS());

ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Command executed");
}

CON_COMMAND_CHAT_FLAGS(extend, "<minutes> - Extend current map (negative value reduces map duration)", ADMFLAG_CHANGEMAP)
Expand Down
2 changes: 1 addition & 1 deletion src/buttonwatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ void ButtonWatch(const CEntityIOOutput* pThis, CEntityInstance* pActivator, CEnt
// Limit each button to only printing out at most once every 5 seconds
int iIndex = pCaller->GetEntityIndex().Get();
mapRecentEnts[iIndex] = true;
new CTimer(5.0f, true, true, [iIndex]() {
CTimer::Create(5.0f, TIMERFLAG_NONE, [iIndex]() {
mapRecentEnts.erase(iIndex);
return -1.0f;
});
Expand Down
4 changes: 2 additions & 2 deletions src/cdetour.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ class CDetourBase
virtual void DisableDetour() = 0;
};

extern CUtlVector<CDetourBase*> g_vecDetours;

template <typename T>
class CDetour : public CDetourBase
{
Expand Down Expand Up @@ -72,8 +74,6 @@ class CDetour : public CDetourBase
bool m_bInstalled;
};

extern CUtlVector<CDetourBase*> g_vecDetours;

template <typename T>
CDetour<T>::CDetour(T* pfnDetour, const char* pszName) :
m_pfnDetour(pfnDetour), m_pszName(pszName)
Expand Down
31 changes: 13 additions & 18 deletions src/commands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,17 @@

using json = nlohmann::json;

extern IGameEventSystem* g_gameEventSystem;
extern CGameEntitySystem* g_pEntitySystem;
extern IVEngineServer2* g_pEngineServer2;
extern ISteamHTTP* g_http;
extern CConVar<CUtlString> g_cvarFlashLightAttachment;

CConVar<bool> g_cvarEnableCommands("cs2f_commands_enable", FCVAR_NONE, "Whether to enable chat commands", false);
CConVar<bool> g_cvarEnableAdminCommands("cs2f_admin_commands_enable", FCVAR_NONE, "Whether to enable admin chat commands", false);
CConVar<bool> g_cvarEnableWeapons("cs2f_weapons_enable", FCVAR_NONE, "Whether to enable weapon commands", false);

// We need to use a helper function to avoid command macros accessing command list before its initialized
std::map<uint32, std::shared_ptr<CChatCommand>>& CommandList()
{
static std::map<uint32, std::shared_ptr<CChatCommand>> commandList;
return commandList;
}

int GetGrenadeAmmo(CCSPlayer_WeaponServices* pWeaponServices, const WeaponInfo_t* pWeaponInfo)
{
if (!pWeaponServices || pWeaponInfo->m_eSlot != GEAR_SLOT_GRENADES)
Expand Down Expand Up @@ -245,7 +246,7 @@ void RegisterWeaponCommands()
{
for (const auto& alias : aliases)
{
new CChatCommand(alias.c_str(), ParseWeaponCommand, "- Buys this weapon", ADMFLAG_NONE, CMDFLAG_NOHELP);
CChatCommand::Create(alias.c_str(), ParseWeaponCommand, "- Buys this weapon", ADMFLAG_NONE, CMDFLAG_NOHELP);

char cmdName[64];
V_snprintf(cmdName, sizeof(cmdName), "%s%s", COMMAND_PREFIX, alias.c_str());
Expand All @@ -255,12 +256,6 @@ void RegisterWeaponCommands()
}
}

std::map<uint32, CChatCommand*>& CommandList()
{
static std::map<uint32, CChatCommand*> commandList;
return commandList;
}

void ParseChatCommand(const char* pMessage, CCSPlayerController* pController)
{
if (!pController || !pController->IsConnected())
Expand Down Expand Up @@ -496,7 +491,7 @@ void PrintHelp(const CCommand& args, CCSPlayerController* player)

for (const auto& cmdPair : CommandList())
{
CChatCommand* cmd = cmdPair.second;
auto cmd = cmdPair.second;

if (!cmd->IsCommandFlagSet(CMDFLAG_NOHELP))
rgstrCommands.push_back(std::string("c_") + cmd->GetName() + " " + cmd->GetDescription());
Expand All @@ -511,7 +506,7 @@ void PrintHelp(const CCommand& args, CCSPlayerController* player)

for (const auto& cmdPair : CommandList())
{
CChatCommand* cmd = cmdPair.second;
auto cmd = cmdPair.second;
uint64 flags = cmd->GetAdminFlags();

if ((pZEPlayer->IsAdminFlagSet(flags) || ((flags & FLAG_LEADER) == FLAG_LEADER && pZEPlayer->IsLeader()))
Expand Down Expand Up @@ -543,7 +538,7 @@ void PrintHelp(const CCommand& args, CCSPlayerController* player)
{
for (const auto& cmdPair : CommandList())
{
CChatCommand* cmd = cmdPair.second;
auto cmd = cmdPair.second;

if (!cmd->IsCommandFlagSet(CMDFLAG_NOHELP)
&& ((!bOnlyCheckStart && V_stristr(cmd->GetName(), pszSearchTerm))
Expand All @@ -557,7 +552,7 @@ void PrintHelp(const CCommand& args, CCSPlayerController* player)

for (const auto& cmdPair : CommandList())
{
CChatCommand* cmd = cmdPair.second;
auto cmd = cmdPair.second;
uint64 flags = cmd->GetAdminFlags();

if ((pZEPlayer->IsAdminFlagSet(flags) || ((flags & FLAG_LEADER) == FLAG_LEADER && pZEPlayer->IsLeader()))
Expand Down Expand Up @@ -650,7 +645,7 @@ CON_COMMAND_CHAT(spec, "[name] - Spectate another player or join spectators")
// 1 frame delay as observer services will be null on same frame as spectator team switch
CHandle<CCSPlayerController> hPlayer = player->GetHandle();
CHandle<CCSPlayerController> hTarget = pTarget->GetHandle();
new CTimer(0.0f, false, false, [hPlayer, hTarget]() {
CTimer::Create(0.0f, TIMERFLAG_MAP | TIMERFLAG_ROUND, [hPlayer, hTarget]() {
CCSPlayerController* pPlayer = hPlayer.Get();
CCSPlayerController* pTargetPlayer = hTarget.Get();
if (!pPlayer || !pTargetPlayer)
Expand Down
Loading
Loading