Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More map system updates + misc dev #339

Merged
merged 29 commits into from
Feb 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
73686a9
Simplify !nominate code
Vauff Jan 3, 2025
02c5932
Also simplify !setnextmap
Vauff Jan 3, 2025
a441d0f
Several !map updates
Vauff Jan 4, 2025
6e77265
Move some code to shared func + add workshop ID support to !setnextmap
Vauff Jan 6, 2025
afbbb0a
Add !nextmap, show next map in nominate/nomlist
Vauff Jan 6, 2025
de30226
Fix maps with more nominations not being taken to map vote
Vauff Jan 9, 2025
b9398a1
!nominate grammar fix
Vauff Jan 9, 2025
fc4fdbd
Randomize map selection when nomination counts are tied
Vauff Jan 10, 2025
891295e
Add error to !nomlist & !mapcooldowns if nothing to display
Vauff Jan 11, 2025
43abe27
Switch map config to JSON & add KV1 auto-converter
Vauff Jan 11, 2025
a1e547a
Add nomination status messages + refactors
Vauff Jan 12, 2025
a376f68
Create CVoteManager class
Vauff Jan 13, 2025
5ec1dfb
Fix case of RTV getting stuck at max votes after player disconnect
Vauff Jan 13, 2025
4bfef73
Add config to ExtendMap for not allowing extra time
Vauff Jan 13, 2025
62f534f
Migrate map list code to std functions & remove workshop ID ordering
Vauff Jan 13, 2025
060243b
Improve current map detection
Vauff Jan 14, 2025
1328ad0
Several changes made possible by map vote slot disabling + misc stuff
Vauff Jan 18, 2025
a310343
fix windows bullshit
Vauff Jan 18, 2025
e12c6de
Split cs_win_panel_match event listener
Vauff Jan 20, 2025
2419296
Overhaul cooldown system with time-based cooldowns
Vauff Jan 27, 2025
af80f0b
Add group cooldown system
Vauff Jan 27, 2025
d3d5ace
Fix !mapcooldowns no maps on cooldown message in some cases
Vauff Jan 28, 2025
378937a
Stop storing g_pNetworkGameServer & revert to storing current map name
Vauff Jan 29, 2025
26e8c5c
Re-add !maplist command
Vauff Jan 29, 2025
4436bf1
Fix INetworkGameServer implicit cast
Vauff Jan 30, 2025
88f1e01
Fix memory safety issues with stored CGlobalVars pointer
Vauff Jan 30, 2025
08b86c3
Fix memory safety issues with g_pGameRules
Vauff Jan 31, 2025
e650705
Unify active/pending cooldown storage
Vauff Feb 13, 2025
488e319
Fix edge case where map end could be prematurely detected
Vauff Feb 13, 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
2 changes: 1 addition & 1 deletion AMBuildScript
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ class MMSPluginConfig(object):
if builder.options.targets:
target_archs = builder.options.targets.split(',')
else:
target_archs = ['x86', 'x86_64']
target_archs = ['x86_64']

for arch in target_archs:
try:
Expand Down
1 change: 1 addition & 0 deletions CS2Fixes.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@
<ClInclude Include="src\utils\module.h" />
<ClInclude Include="src\utils\plat.h" />
<ClInclude Include="src\utils\virtual.h" />
<ClInclude Include="src\netmessages.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets" />
Expand Down
3 changes: 3 additions & 0 deletions CS2Fixes.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -364,5 +364,8 @@
<ClInclude Include="src\cs2_sdk\entity\ctriggerteleport.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\netmessages.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>
2 changes: 1 addition & 1 deletion PackageScript
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ mapcfg_folder = builder.AddFolder(os.path.join('cfg', MMSPlugin.plugin_name, 'ma
gamedata_folder = builder.AddFolder(os.path.join('addons', MMSPlugin.plugin_name, 'gamedata'))
builder.AddCopy(os.path.join(builder.sourcePath, 'configs', 'admins.cfg.example'), configs_folder)
builder.AddCopy(os.path.join(builder.sourcePath, 'configs', 'discordbots.cfg.example'), configs_folder)
builder.AddCopy(os.path.join(builder.sourcePath, 'configs', 'maplist.cfg.example'), configs_folder)
builder.AddCopy(os.path.join(builder.sourcePath, 'configs', 'maplist.jsonc.example'), configs_folder)
builder.AddCopy(os.path.join(builder.sourcePath, 'cfg', MMSPlugin.plugin_name, 'cs2fixes.cfg'), cfg_folder)
builder.AddCopy(os.path.join(builder.sourcePath, 'cfg', MMSPlugin.plugin_name, 'maps', 'de_somemap.cfg'), mapcfg_folder)
builder.AddCopy(os.path.join(builder.sourcePath, 'configs', 'zr', 'playerclass.jsonc.example'), zr_folder)
Expand Down
5 changes: 3 additions & 2 deletions cfg/cs2fixes/cs2fixes.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,9 @@ cs2f_rtv_success_ratio 0.6 // Ratio needed to pass RTV
cs2f_rtv_endround 0 // Whether to immediately end the round when RTV succeeds

// Map vote settings
cs2f_vote_maps_cooldown 10 // Default number of maps to wait until a map can be voted / nominated again i.e. cooldown.
cs2f_vote_max_nominations 10 // Number of nominations to include per vote, out of a maximum of 10.
cs2f_vote_maps_cooldown 6.0 // Default number of hours until a map can be played again i.e. cooldown
cs2f_vote_max_nominations 10 // Number of nominations to include per vote, out of a maximum of 10
cs2f_vote_max_maps 10 // Number of total maps to include per vote, including nominations, out of a maximum of 10

// User preferences settings
cs2f_user_prefs_api "" // User Preferences REST API endpoint
Expand Down
29 changes: 0 additions & 29 deletions configs/maplist.cfg.example

This file was deleted.

52 changes: 52 additions & 0 deletions configs/maplist.jsonc.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"Groups":
{
// If any map in a group gets played, all maps in that group will receive the group cooldown
// The group cooldown applies immediately, but only starts ticking down *after* the trigger map ends
"MyFirstGroup":
{
"enabled": true,
"cooldown": 4 // Cooldown in hours
},
"MySecondGroup":
{
"enabled": true,
"cooldown": 0.5
},
"MyThirdGroup":
{
// Omitting the cooldown option will fall back to cs2f_vote_maps_cooldown cvar
"enabled": true
}
},
"Maps":
{
"de_dust2": // Map name should always match .vpk name to avoid unintended behaviour
{
"enabled": true
},
"ze_my_first_ze_map":
{
"enabled": true,
"workshop_id": 123, // Workshop ID must be specified for workshop maps
"min_players": 20, // Minimum players required to nominate or appear in vote
"cooldown": 2 // Custom cooldown in hours, can override default map cooldown
},
"ze_my_second_ze_map":
{
"enabled": true,
"workshop_id": 456,
"min_players": 5, // Maximum players where map can be nominated or appear in vote
"max_players": 10,
"cooldown": 3,
"groups": [ "MyFirstGroup" ] // Any other maps in this group will receive the group cooldown when this map is played
},
"ze_my_third_ze_map":
{
"enabled": true,
"workshop_id": 789,
"max_players": 20,
"groups": [ "MyFirstGroup", "MySecondGroup" ] // A map can be in multiple groups
}
}
}
96 changes: 16 additions & 80 deletions src/adminsystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@

extern IVEngineServer2* g_pEngineServer2;
extern CGameEntitySystem* g_pEntitySystem;
extern CGlobalVars* gpGlobals;
extern CGlobalVars* GetGlobals();
extern CCSGameRules* g_pGameRules;

CAdminSystem* g_pAdminSystem = nullptr;
Expand Down Expand Up @@ -113,10 +113,10 @@ void PrintMultiAdminAction(ETargetType nType, const char* pszAdminName, const ch

CON_COMMAND_F(c_reload_admins, "Reload admin config", FCVAR_SPONLY | FCVAR_LINKED_CONCOMMAND)
{
if (!g_pAdminSystem->LoadAdmins())
if (!g_pAdminSystem->LoadAdmins() || !GetGlobals())
return;

for (int i = 0; i < gpGlobals->maxClients; i++)
for (int i = 0; i < GetGlobals()->maxClients; i++)
{
ZEPlayer* pPlayer = g_playerManager->GetPlayer(i);

Expand All @@ -131,10 +131,10 @@ CON_COMMAND_F(c_reload_admins, "Reload admin config", FCVAR_SPONLY | FCVAR_LINKE

CON_COMMAND_F(c_reload_infractions, "Reload infractions file", FCVAR_SPONLY | FCVAR_LINKED_CONCOMMAND)
{
if (!g_pAdminSystem->LoadInfractions())
if (!g_pAdminSystem->LoadInfractions() || !GetGlobals())
return;

for (int i = 0; i < gpGlobals->maxClients; i++)
for (int i = 0; i < GetGlobals()->maxClients; i++)
{
ZEPlayer* pPlayer = g_playerManager->GetPlayer(i);

Expand Down Expand Up @@ -577,76 +577,6 @@ CON_COMMAND_CHAT_FLAGS(entfirecontroller, "<name> <input> [parameter] - Fire out
ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Input successful on %i player controllers.", iFoundEnts);
}

CON_COMMAND_CHAT_FLAGS(map, "<mapname> - Change map", ADMFLAG_CHANGEMAP)
{
if (args.ArgC() < 2)
{
ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Usage: !map <mapname>");
return;
}

std::string sMapName = args[1];

for (int i = 0; sMapName[i]; i++)
{
// Injection prevention, because we may pass user input to ServerCommand
if (sMapName[i] == ';' || sMapName[i] == '|')
return;

sMapName[i] = tolower(sMapName[i]);
}

const char* pszMapName = sMapName.c_str();

if (!g_pEngineServer2->IsMapValid(pszMapName))
{
std::string sCommand;
std::vector<int> foundIndexes = g_pMapVoteSystem->GetMapIndexesFromSubstring(pszMapName);

// 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, NULL, NULL, PARSING_FLAG_SKIP_WARNING) != 0)
{
sCommand = "host_workshop_map " + sMapName;
}
else if (g_bVoteManagerEnable && foundIndexes.size() > 0)
{
if (foundIndexes.size() > 1)
{
ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Multiple maps matched \x06%s\x01, try being more specific:", pszMapName);

for (int i = 0; i < foundIndexes.size() && i < 5; i++)
ClientPrint(player, HUD_PRINTTALK, "- %s", g_pMapVoteSystem->GetMapName(foundIndexes[i]));

return;
}

sCommand = "host_workshop_map " + std::to_string(g_pMapVoteSystem->GetMapWorkshopId(foundIndexes[0]));
}
else
{
ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Failed to find a map matching %s.", pszMapName);
return;
}

ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX "Changing map to %s...", pszMapName);

new CTimer(5.0f, false, true, [sCommand]() {
g_pEngineServer2->ServerCommand(sCommand.c_str());
return -1.0f;
});

return;
}

ClientPrintAll(HUD_PRINTTALK, CHAT_PREFIX "Changing map to %s...", pszMapName);

new CTimer(5.0f, false, true, [sMapName]() {
g_pEngineServer2->ChangeLevel(sMapName.c_str(), nullptr);
return -1.0f;
});
}

CON_COMMAND_CHAT_FLAGS(hsay, "<message> - Say something as a hud hint", ADMFLAG_CHAT)
{
if (args.ArgC() < 2)
Expand Down Expand Up @@ -685,8 +615,7 @@ CON_COMMAND_CHAT_FLAGS(extend, "<minutes> - Extend current map (negative value r

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

// Call the votemanager extend function so the extend vote can be checked
ExtendMap(iExtendTime);
g_pVoteManager->ExtendMap(iExtendTime);

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

Expand All @@ -698,6 +627,9 @@ CON_COMMAND_CHAT_FLAGS(extend, "<minutes> - Extend current map (negative value r

CON_COMMAND_CHAT_FLAGS(pm, "<name> <message> - Private message a player. This will also show to all online admins", ADMFLAG_GENERIC)
{
if (!GetGlobals())
return;

if (args.ArgC() < 3)
{
ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Usage: /pm <name> <message>");
Expand Down Expand Up @@ -737,7 +669,7 @@ CON_COMMAND_CHAT_FLAGS(pm, "<name> <message> - Private message a player. This wi
return;
}

for (int i = 0; i < gpGlobals->maxClients; i++)
for (int i = 0; i < GetGlobals()->maxClients; i++)
{
ZEPlayer* pPlayer = g_playerManager->GetPlayer(i);

Expand All @@ -755,9 +687,12 @@ CON_COMMAND_CHAT_FLAGS(pm, "<name> <message> - Private message a player. This wi

CON_COMMAND_CHAT_FLAGS(who, "- List the flags of all online players", ADMFLAG_GENERIC)
{
if (!GetGlobals())
return;

std::vector<std::tuple<std::string, std::string, uint64>> rgNameSlotID;

for (size_t i = 0; i < gpGlobals->maxClients; i++)
for (size_t i = 0; i < GetGlobals()->maxClients; i++)
{
CCSPlayerController* ccsPly = CCSPlayerController::FromSlot(i);

Expand Down Expand Up @@ -961,7 +896,8 @@ CON_COMMAND_CHAT_FLAGS(listdc, "- List recently disconnected players and their S

CON_COMMAND_CHAT_FLAGS(endround, "- Immediately ends the round, client-side variant of endround", ADMFLAG_RCON)
{
g_pGameRules->TerminateRound(0.0f, CSRoundEndReason::Draw);
if (g_pGameRules)
g_pGameRules->TerminateRound(0.0f, CSRoundEndReason::Draw);
}

CON_COMMAND_CHAT_FLAGS(money, "<name> <amount> - Set a player's amount of money", ADMFLAG_CHEATS)
Expand Down
4 changes: 2 additions & 2 deletions src/buttonwatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ bool IsButtonWatchEnabled()
std::map<int, bool> mapRecentEnts;
void ButtonWatch(const CEntityIOOutput* pThis, CEntityInstance* pActivator, CEntityInstance* pCaller, const CVariant* value, float flDelay)
{
if (!IsButtonWatchEnabled() || V_stricmp(pThis->m_pDesc->m_pName, "OnPressed") || !pActivator || !((CBaseEntity*)pActivator)->IsPawn() || !pCaller || mapRecentEnts.contains(pCaller->GetEntityIndex().Get()))
if (!IsButtonWatchEnabled() || !GetGlobals() || V_stricmp(pThis->m_pDesc->m_pName, "OnPressed") || !pActivator || !((CBaseEntity*)pActivator)->IsPawn() || !pCaller || mapRecentEnts.contains(pCaller->GetEntityIndex().Get()))
return;

CCSPlayerController* ccsPlayer = CCSPlayerController::FromPawn(static_cast<CCSPlayerPawn*>(pActivator));
Expand All @@ -112,7 +112,7 @@ void ButtonWatch(const CEntityIOOutput* pThis, CEntityInstance* pActivator, CEnt

std::string strButton = std::to_string(pCaller->GetEntityIndex().Get()) + " " + std::string(((CBaseEntity*)pCaller)->GetName());

for (int i = 0; i < gpGlobals->maxClients; i++)
for (int i = 0; i < GetGlobals()->maxClients; i++)
{
CCSPlayerController* ccsPlayer = CCSPlayerController::FromSlot(i);
if (!ccsPlayer)
Expand Down
9 changes: 6 additions & 3 deletions src/cs2_sdk/entity/ccsweaponbase.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

#include "cbaseentity.h"

extern CGlobalVars* gpGlobals;
extern CGlobalVars* GetGlobals();

enum gear_slot_t : uint32_t
{
Expand Down Expand Up @@ -97,8 +97,11 @@ class CBasePlayerWeapon : public CEconEntity

void Disarm()
{
m_nNextPrimaryAttackTick(MAX(m_nNextPrimaryAttackTick(), gpGlobals->tickcount + 24));
m_nNextSecondaryAttackTick(MAX(m_nNextSecondaryAttackTick(), gpGlobals->tickcount + 24));
if (!GetGlobals())
return;

m_nNextPrimaryAttackTick(MAX(m_nNextPrimaryAttackTick(), GetGlobals()->tickcount + 24));
m_nNextSecondaryAttackTick(MAX(m_nNextSecondaryAttackTick(), GetGlobals()->tickcount + 24));
}
};

Expand Down
1 change: 1 addition & 0 deletions src/cs2_sdk/entity/cgamerules.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class CCSGameRules : public CGameRules
SCHEMA_FIELD(GameTime_t, m_fRoundStartTime)
SCHEMA_FIELD(GameTime_t, m_flRestartRoundTime)
SCHEMA_FIELD_POINTER(int, m_nEndMatchMapGroupVoteOptions)
SCHEMA_FIELD_POINTER(int, m_nEndMatchMapGroupVoteTypes)
SCHEMA_FIELD(int, m_nEndMatchMapVoteWinner)
SCHEMA_FIELD(int, m_iRoundTime)
SCHEMA_FIELD(bool, m_bFreezePeriod)
Expand Down
2 changes: 1 addition & 1 deletion src/cs2_sdk/schema.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

#include "tier0/memdbgon.h"

extern CGlobalVars* gpGlobals;
extern CGlobalVars* GetGlobals();

using SchemaKeyValueMap_t = CUtlMap<uint32_t, SchemaKey>;
using SchemaTableMap_t = CUtlMap<uint32_t, SchemaKeyValueMap_t*>;
Expand Down
Loading