Skip to content
5 changes: 5 additions & 0 deletions gamedata/cs2fixes.games.txt
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,11 @@
"windows" "22"
"linux" "23"
}
"CCSPlayer_WeaponServices::SelectItem"
{
"windows" "24"
"linux" "25"
}
"CCSGameRules_GoToIntermission"
{
"windows" "128"
Expand Down
1 change: 1 addition & 0 deletions src/addresses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ bool addresses::Initialize(CGameConfig *g_GameConfig)
modules::vscript = new CModule(ROOTBIN, "vscript");
modules::networksystem = new CModule(ROOTBIN, "networksystem");
modules::vphysics2 = new CModule(ROOTBIN, "vphysics2");
modules::matchmaking = new CModule(GAMEBIN, "matchmaking");
modules::client = nullptr;

if (!CommandLine()->HasParm("-dedicated"))
Expand Down
1 change: 1 addition & 0 deletions src/addresses.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ namespace modules
inline CModule *client;
inline CModule* networksystem;
inline CModule* vphysics2;
inline CModule* matchmaking;
#ifdef _WIN32
inline CModule *hammer;
#endif
Expand Down
26 changes: 3 additions & 23 deletions src/adminsystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -606,7 +606,7 @@ CON_COMMAND_CHAT_FLAGS(map, "<mapname> - Change map", ADMFLAG_CHANGEMAP)

// Check if input is numeric (workshop ID)
// Not safe to expose to all admins until crashing on failed workshop addon downloads is fixed
if ((!player || player->GetZEPlayer()->IsAdminFlagSet(ADMFLAG_RCON)) && V_StringToUint64(pszMapName, 0) != 0)
if ((!player || player->GetZEPlayer()->IsAdminFlagSet(ADMFLAG_RCON)) && V_StringToUint64(pszMapName, 0, NULL, NULL, PARSING_FLAG_SKIP_WARNING) != 0)
{
sCommand = "host_workshop_map " + sMapName;
}
Expand Down Expand Up @@ -688,28 +688,8 @@ CON_COMMAND_CHAT_FLAGS(extend, "<minutes> - Extend current map (negative value r

int iExtendTime = V_StringToInt32(args[1], 0);

ConVar* cvar = g_pCVar->GetConVar(g_pCVar->FindConVar("mp_timelimit"));

// CONVAR_TODO
// HACK: values is actually the cvar value itself, hence this ugly cast.
float flTimelimit = *(float *)&cvar->values;

if (gpGlobals->curtime - g_pGameRules->m_flGameStartTime > flTimelimit * 60)
flTimelimit = (gpGlobals->curtime - g_pGameRules->m_flGameStartTime) / 60.0f + iExtendTime;
else
{
if (flTimelimit == 1)
flTimelimit = 0;
flTimelimit += iExtendTime;
}

if (flTimelimit <= 0)
flTimelimit = 1;

// CONVAR_TODO
char buf[32];
V_snprintf(buf, sizeof(buf), "mp_timelimit %.6f", flTimelimit);
g_pEngineServer2->ServerCommand(buf);
// Call the votemanager extend function so the extend vote can be checked
ExtendMap(iExtendTime);

const char* pszCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;

Expand Down
2 changes: 1 addition & 1 deletion src/cs2_sdk/entity/cbaseplayerpawn.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class CBasePlayerPawn : public CBaseModelEntity
SCHEMA_FIELD(QAngle, v_angle)

// Drops any map-spawned weapons the pawn is holding
// NOTE: Currently very broken with map items (entities parented to weapons?) due to a game bug..? Needs further investigation/work
// NOTE: This doesn't predict correctly to the weapon holder! Looks very funky when testing, but not really an issue on live servers
void DropMapWeapons()
{
if (!m_pWeaponServices())
Expand Down
6 changes: 6 additions & 0 deletions src/cs2_sdk/entity/services.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,12 @@ class CCSPlayer_WeaponServices : public CPlayer_WeaponServices
static int offset = g_GameConfig->GetOffset("CCSPlayer_WeaponServices::DropWeapon");
CALL_VIRTUAL(void, offset, this, pWeapon, pVecTarget, pVelocity);
}

void SelectItem(CBasePlayerWeapon* pWeapon, int unk1 = 0)
{
static int offset = g_GameConfig->GetOffset("CCSPlayer_WeaponServices::SelectItem");
CALL_VIRTUAL(void, offset, this, pWeapon, unk1);
}
};

class CCSPlayerController_InGameMoneyServices
Expand Down
9 changes: 4 additions & 5 deletions src/cs2fixes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -865,11 +865,10 @@ void CS2Fixes::Hook_CheckTransmit(CCheckTransmitInfo **ppInfoList, int infoCount
if (!pController || pController->m_bIsHLTV || j == iPlayerSlot)
continue;

// Don't transmit other players' flashlights, except the one they're watching if in spec
// Don't transmit other players' flashlights
CBarnLight *pFlashLight = pController->IsConnected() ? g_playerManager->GetPlayer(j)->GetFlashLight() : nullptr;

if (!g_bFlashLightTransmitOthers && pFlashLight &&
!(pSelfController->GetPawnState() == STATE_OBSERVER_MODE && pSelfController->GetObserverTarget() == pController->GetPawn()))
if (!g_bFlashLightTransmitOthers && pFlashLight)
{
pInfo->m_pTransmitEntity->Clear(pFlashLight->entindex());
}
Expand Down Expand Up @@ -1009,9 +1008,9 @@ void CS2Fixes::Hook_PhysicsTouchShuffle(CUtlVector<TouchLinked_t>* pList, bool u

pList->Purge();

for (const auto link : touchingLinks)
for (const auto &link : touchingLinks)
pList->AddToTail(link);
for (const auto link : unTouchLinks)
for (const auto &link : unTouchLinks)
pList->AddToTail(link);
}

Expand Down
20 changes: 20 additions & 0 deletions src/events.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,26 @@ GAME_EVENT_F(player_spawn)

return -1.0f;
});

// And this needs even more delay..? Don't even know if this is enough, bug can't be reproduced
new CTimer(0.1f, false, false, [hController]()
{
CCSPlayerController* pController = hController.Get();

if (!pController)
return -1.0f;

CBasePlayerPawn* pPawn = pController->GetPawn();

if (pPawn)
{
// Fix new haunted CS2 bug? https://www.reddit.com/r/cs2/comments/1glvg9s/thank_you_for_choosing_anubis_airlines/
// We've seen this several times across different maps at this point
pPawn->m_vecAbsVelocity = Vector(0, 0, 0);
}

return -1.0f;
});
}

static bool g_bEnableTopDefender = false;
Expand Down
2 changes: 2 additions & 0 deletions src/gameconfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ CModule **CGameConfig::GetModule(const char *name)
return &modules::tier0;
else if (strcmp(library, "networksystem") == 0)
return &modules::networksystem;
else if (strcmp(library, "matchmaking") == 0)
return &modules::matchmaking;
#ifdef _WIN32
else if (strcmp(library, "hammer") == 0)
return &modules::hammer;
Expand Down
2 changes: 1 addition & 1 deletion src/playermanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1305,7 +1305,7 @@ ETargetError CPlayerManager::GetPlayersFromString(CCSPlayerController* pPlayer,
CBaseEntity* entTarget = nullptr;
entTarget = UTIL_FindPickerEntity(pPlayer);

if (!entTarget->IsPawn())
if (!entTarget || !entTarget->IsPawn())
return ETargetError::INVALID;

CCSPlayerController* pTarget = CCSPlayerController::FromPawn(static_cast<CCSPlayerPawn*>(entTarget));
Expand Down
75 changes: 24 additions & 51 deletions src/votemanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,10 @@ extern CCSGameRules* g_pGameRules;

ERTVState g_RTVState = ERTVState::MAP_START;
EExtendState g_ExtendState = EExtendState::MAP_START;
int g_iExtends = 0;

bool g_bVoteManagerEnable = false;
int g_iExtendsLeft = 1;
int g_iMaxExtends = 1;
float g_flExtendSucceedRatio = 0.5f;
int g_iExtendTimeToAdd = 20;
float g_flRTVSucceedRatio = 0.6f;
Expand All @@ -53,7 +54,7 @@ float g_flRtvDelay = 300.0f;
FAKE_BOOL_CVAR(cs2f_votemanager_enable, "Whether to enable votemanager features such as RTV and extends", g_bVoteManagerEnable, false, false)
FAKE_FLOAT_CVAR(cs2f_extend_vote_delay, "If cs2f_extend_mode is 2, Time after map start until extend votes can be triggered", g_flExtendVoteDelay, 120.0f, false)
FAKE_INT_CVAR(cs2f_extend_mode, "How extend votes are handled. (0=off, 1=only admins can start, 2=players can start with !ve, 3=auto start at given timeleft)", g_ExtendVoteMode, (int)EExtendVoteMode::EXTENDVOTE_ADMINONLY, false)
FAKE_INT_CVAR(cs2f_extends, "Maximum extends per map", g_iExtendsLeft, 1, false)
FAKE_INT_CVAR(cs2f_extends, "Maximum extends per map", g_iMaxExtends, 1, false)
FAKE_FLOAT_CVAR(cs2f_extend_success_ratio, "Ratio needed to pass an extend vote", g_flExtendSucceedRatio, 0.5f, false)
FAKE_INT_CVAR(cs2f_extend_time, "Time to add per extend in minutes", g_iExtendTimeToAdd, 20, false)
FAKE_FLOAT_CVAR(cs2f_extend_vote_start_time, "If cs2f_extend_mode is 3, start an extend vote at this timeleft (minutes)", g_flExtendVoteStartTime, 4.0f, false)
Expand All @@ -72,6 +73,8 @@ void VoteManager_Init()
g_RTVState = ERTVState::MAP_START;
g_ExtendState = EExtendState::MAP_START;

g_iExtends = 0;

new CTimer(g_flExtendVoteDelay, false, true, []()
{
if (g_ExtendState < EExtendState::POST_EXTEND_NO_EXTENDS_LEFT)
Expand Down Expand Up @@ -110,7 +113,7 @@ float TimerCheckTimeleft()
return flExtendVoteTickrate;

// No more extends or map RTVd
if (g_iExtendsLeft <= 0 || g_ExtendState >= EExtendState::POST_EXTEND_NO_EXTENDS_LEFT)
if ((g_iMaxExtends - g_iExtends) <= 0 || g_ExtendState >= EExtendState::POST_EXTEND_NO_EXTENDS_LEFT)
return flExtendVoteTickrate;

ConVar* cvar = g_pCVar->GetConVar(g_pCVar->FindConVar("mp_timelimit"));
Expand Down Expand Up @@ -401,6 +404,9 @@ CON_COMMAND_CHAT(ve, "- Vote to extend current map")
case EExtendState::POST_EXTEND_NO_EXTENDS_LEFT:
ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "There are no extends left for the current map.");
return;
case EExtendState::POST_EXTEND_FAILED:
ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "A previous extend vote already failed.");
return;
case EExtendState::POST_LAST_ROUND_END:
ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Extend vote is closed during next map selection.");
return;
Expand Down Expand Up @@ -491,7 +497,7 @@ CON_COMMAND_CHAT_FLAGS(adminve, "Start a vote extend immediately.", ADMFLAG_CHAN

if (g_ExtendState == EExtendState::IN_PROGRESS || bVoteStarting)
{
ClientPrint(player, HUD_PRINTCONSOLE, CHAT_PREFIX "An extend vote is already in progress.");
ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "An extend vote is already in progress.");
return;
}

Expand Down Expand Up @@ -544,54 +550,22 @@ CON_COMMAND_CHAT_FLAGS(enablertv, "- Restore the ability for players to vote to
ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX ADMIN_PREFIX "enabled vote for RTV.", pszCommandPlayerName);
}

CON_COMMAND_CHAT_FLAGS(addextend, "- Add another extend to the current map for players to vote", ADMFLAG_RCON)
{
if (!g_bVoteManagerEnable)
return;

if (g_ExtendState == EExtendState::IN_PROGRESS)
{
if (player)
ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Wait until the current vote has ended to add extends.");
else
ConMsg("Wait until the current vote has ended to add extends.");
return;
}

const char* pszCommandPlayerName = player ? player->GetPlayerName() : CONSOLE_NAME;

if (g_ExtendState == EExtendState::POST_EXTEND_NO_EXTENDS_LEFT || g_ExtendState == EExtendState::NO_EXTENDS)
g_ExtendState = EExtendState::EXTEND_ALLOWED;

g_iExtendsLeft += 1;

ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX ADMIN_PREFIX "allowed for an additional extend.", pszCommandPlayerName);
}

CON_COMMAND_CHAT(extendsleft, "- Display amount of extends left for the current map")
{
if (!g_bVoteManagerEnable)
return;

char message[64];

switch (g_iExtendsLeft)
if (g_iMaxExtends - g_iExtends <= 0)
{
case 0:
strcpy(message, "There are no extends left.");
break;
case 1:
strcpy(message, "There's 1 extend left");
break;
default:
V_snprintf(message, sizeof(message), "There are %i extends left.", g_iExtendsLeft);
break;
ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "There are no extends left, the map was already extended %i/%i times.", g_iExtends, g_iMaxExtends);
}

if (player)
ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "%s", message);
else
ConMsg("%s", message);
{
if (g_ExtendState == EExtendState::POST_EXTEND_FAILED)
ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "The map had %i/%i extends left, but the last extend vote failed.", g_iMaxExtends - g_iExtends, g_iMaxExtends);
else
ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "The map has %i/%i extends left.", g_iMaxExtends - g_iExtends, g_iMaxExtends);
}
}

CON_COMMAND_CHAT(timeleft, "- Display time left to end of current map.")
Expand Down Expand Up @@ -682,11 +656,11 @@ void VoteExtendHandler(YesNoVoteAction action, int param1, int param2)
{
if ((YesNoVoteEndReason)param1 == YesNoVoteEndReason::VoteEnd_Cancelled)
{
// Admin cancelled so stop further automatic votes
// Admin cancelled so stop further votes
// It will reenable if an admin manually calls a vote
if (g_ExtendVoteMode == EExtendVoteMode::EXTENDVOTE_AUTO)
{
g_ExtendState = EExtendState::POST_EXTEND_NO_EXTENDS_LEFT;
g_ExtendState = EExtendState::POST_EXTEND_FAILED;
}
}

Expand All @@ -710,8 +684,9 @@ bool VoteExtendEndCallback(YesNoVoteInfo info)
if (yes_percent >= g_flExtendSucceedRatio)
{
ExtendMap(g_iExtendTimeToAdd);
g_iExtends++;

if (g_iExtendsLeft == 1)
if (g_iMaxExtends - g_iExtends <= 0)
// there are no extends left after a successfull extend vote
g_ExtendState = EExtendState::POST_EXTEND_NO_EXTENDS_LEFT;
else
Expand Down Expand Up @@ -747,15 +722,13 @@ bool VoteExtendEndCallback(YesNoVoteInfo info)
pPlayer->SetExtendVote(false);
}

g_iExtendsLeft--;
ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX "Extend vote succeeded! Current map has been extended by %i minutes.", g_iExtendTimeToAdd);

return true;
}

// Vote failed so we don't allow any more player initiated votes
g_ExtendState = EExtendState::POST_EXTEND_NO_EXTENDS_LEFT;
g_iExtendsLeft = 0;
// Vote failed so we don't allow any more votes
g_ExtendState = EExtendState::POST_EXTEND_FAILED;

ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX "Extend vote failed! Further extend votes disabled!", g_iExtendTimeToAdd);

Expand Down
2 changes: 1 addition & 1 deletion src/votemanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ enum class EExtendState
IN_PROGRESS,
POST_EXTEND_COOLDOWN,
POST_EXTEND_NO_EXTENDS_LEFT,
POST_EXTEND_FAILED,
POST_LAST_ROUND_END,
POST_RTV,
NO_EXTENDS,
Expand All @@ -51,7 +52,6 @@ enum EExtendVoteMode

extern ERTVState g_RTVState;
extern EExtendState g_ExtendState;
extern int g_iExtendsLeft;
extern bool g_bVoteManagerEnable;

void VoteManager_Init();
Expand Down
Loading
Loading