uploading nides edition of fakeclients with sm_debugfakes added
This commit is contained in:
parent
80d0b85367
commit
6acdc80767
80
FakeClients/configs/fakeclients.txt
Normal file
80
FakeClients/configs/fakeclients.txt
Normal file
@ -0,0 +1,80 @@
|
||||
HAFL-LIFE_2
|
||||
NoobDnoRaq
|
||||
IMBA
|
||||
ТАЩИР
|
||||
ebaw-kak-t34
|
||||
h4rdc0r3
|
||||
omfg]wiz
|
||||
GOdlikebAby
|
||||
SHITSHITSHIT
|
||||
-Impulse-
|
||||
SLAVA_UKRAINE
|
||||
4ik-pyk
|
||||
BigBoss
|
||||
lolkalalka
|
||||
muhahahahaha
|
||||
GFLClan.ru
|
||||
nide.gg
|
||||
vk.com/nide_css
|
||||
alex481516
|
||||
alahakbar
|
||||
HeadShot
|
||||
HolySHIT
|
||||
CRAY_ZEE
|
||||
mlpro
|
||||
Deadmemories
|
||||
MaGothic
|
||||
ILoveYouBaby
|
||||
nevazhno
|
||||
Tauren
|
||||
Calypso
|
||||
Hawk
|
||||
(1)HAFL-LIFE_2
|
||||
(1)NoobDnoRaq
|
||||
(1)Hawk
|
||||
(1)Tauren
|
||||
(1)mlpro
|
||||
(1)CRAY_ZEE
|
||||
(1)NF-CSS.RU
|
||||
(1)Calypso
|
||||
(1)BigBoss
|
||||
HAFL-LIFE_2
|
||||
NoobDnoRaq
|
||||
IMBA
|
||||
ТАЩИР
|
||||
ebaw-kak-t34
|
||||
h4rdc0r3
|
||||
omfg]wiz
|
||||
GOdlikebAby
|
||||
SHITSHITSHIT
|
||||
-Impulse-
|
||||
SLAVA_UKRAINE
|
||||
4ik-pyk
|
||||
BigBoss
|
||||
lolkalalka
|
||||
muhahahahaha
|
||||
cp.powerhub.ru
|
||||
NiDE.GG
|
||||
vk.com/nide_css
|
||||
alex481516
|
||||
alahakbar
|
||||
HeadShot
|
||||
HolySHIT
|
||||
CRAY_ZEE
|
||||
mlpro
|
||||
Deadmemories
|
||||
MaGothic
|
||||
ILoveYouBaby
|
||||
nevazhno
|
||||
Tauren
|
||||
Calypso
|
||||
Hawk
|
||||
(1)HAFL-LIFE_2
|
||||
(1)NoobDnoRaq
|
||||
(1)Hawk
|
||||
(1)Tauren
|
||||
(1)mlpro
|
||||
(1)CRAY_ZEE
|
||||
(1)NF-CSS.RU
|
||||
(1)Calypso
|
||||
(1)BigBoss
|
||||
@ -1,114 +0,0 @@
|
||||
Dwelitram
|
||||
Gwyri
|
||||
Caredus
|
||||
Arerawia
|
||||
Vilali
|
||||
Astiwiel
|
||||
Vardonydd
|
||||
Ybaossa
|
||||
Umyk
|
||||
Nico50Pax
|
||||
Onand
|
||||
Thelian
|
||||
Nydaleth
|
||||
Chomarin
|
||||
Traedien
|
||||
Miev
|
||||
Kaaede
|
||||
Koamond
|
||||
TheRottenBenson
|
||||
BigLegend2017
|
||||
TRIGGEREDHarambexXx
|
||||
InPepe2016
|
||||
xXxMaster2012
|
||||
InBoixXx
|
||||
TheKopsing
|
||||
Cornelius
|
||||
Gustavo
|
||||
Bryant
|
||||
Winfred
|
||||
Nicolas
|
||||
Mitchel
|
||||
Dana
|
||||
Carrol
|
||||
Darell
|
||||
Ruben
|
||||
Jeromy
|
||||
Wade
|
||||
Scotty
|
||||
Salvatore
|
||||
Kory
|
||||
Don
|
||||
Morgan
|
||||
Kurtis
|
||||
Federico
|
||||
Darin
|
||||
css-ru
|
||||
aimbot
|
||||
lastkraftwagenfahrzeug
|
||||
edger
|
||||
clownface
|
||||
слово
|
||||
счастливый
|
||||
kara
|
||||
puta
|
||||
meow
|
||||
uncle sam
|
||||
FunBun
|
||||
Counter-Strike.Com.Ua
|
||||
For-css.Ru
|
||||
BOBO
|
||||
Z3r0
|
||||
ZeTo
|
||||
Sakharov
|
||||
Sache11
|
||||
Mr. Dogenberg
|
||||
Maus
|
||||
Magikarpet
|
||||
Miles
|
||||
magick
|
||||
James Lebron
|
||||
jiZZ
|
||||
Dobel
|
||||
THE POPE OF DOPE
|
||||
The Joker
|
||||
that guy over there
|
||||
Be happy :)
|
||||
KingKong
|
||||
Figger Nucker
|
||||
noname
|
||||
alexdu63
|
||||
I put babies in the microwave
|
||||
Tango!!
|
||||
faggot killer
|
||||
admin pidaras
|
||||
MESSI>RONALDO
|
||||
Gabe Newell
|
||||
acetylsalicylic acid
|
||||
Country-Steak: Sauce
|
||||
chlamydia harvester
|
||||
kyle_69
|
||||
Shaggy's dog
|
||||
rEVERSE
|
||||
Piment d'espelette
|
||||
FireHawk
|
||||
Sgt. Pepper
|
||||
krix.
|
||||
imPulse_^_
|
||||
Lardon
|
||||
CAPS LOCK
|
||||
$pussymoneyweed$
|
||||
Low5
|
||||
Bonerfart
|
||||
Shiny Thanos
|
||||
MARK NUTT
|
||||
Legless Runner
|
||||
Banana is a berry
|
||||
Gabriel
|
||||
El Moustachio
|
||||
James Bong
|
||||
Disco Fever
|
||||
Acacia
|
||||
Sugared
|
||||
ronald goddamn macdonald
|
||||
pizza is life
|
||||
27
FakeClients/configs/fakeclients_tiers.cfg
Normal file
27
FakeClients/configs/fakeclients_tiers.cfg
Normal file
@ -0,0 +1,27 @@
|
||||
"FakeClientsTiers"
|
||||
{
|
||||
"0" "23"
|
||||
"3" "22"
|
||||
"6" "21"
|
||||
"9" "20"
|
||||
"12" "19"
|
||||
"15" "18"
|
||||
"18" "17"
|
||||
"21" "16"
|
||||
"24" "15"
|
||||
"27" "14"
|
||||
"30" "13"
|
||||
"33" "12"
|
||||
"36" "11"
|
||||
"39" "10"
|
||||
"42" "9"
|
||||
"45" "8"
|
||||
"48" "7"
|
||||
"51" "6"
|
||||
"54" "5"
|
||||
"55" "4"
|
||||
"57" "3"
|
||||
"60" "2"
|
||||
"61" "1"
|
||||
"62" "0"
|
||||
}
|
||||
480
FakeClients/scripting/FakeClients_nide.sp
Normal file
480
FakeClients/scripting/FakeClients_nide.sp
Normal file
@ -0,0 +1,480 @@
|
||||
#pragma semicolon 1
|
||||
#pragma newdecls required
|
||||
#include <sourcemod>
|
||||
#include <sdktools>
|
||||
#include <cstrike>
|
||||
|
||||
#define MAX_TIERS 32
|
||||
|
||||
ConVar g_hCount;
|
||||
ConVar g_hDelay;
|
||||
ConVar g_hUseTiers;
|
||||
ArrayList g_hNames;
|
||||
|
||||
int g_iTierThreshold[MAX_TIERS]; // real player count that triggers this tier
|
||||
int g_iTierMaxBots[MAX_TIERS]; // max bots allowed for this tier
|
||||
int g_iTierCount = 0;
|
||||
int g_iPendingBots = 0;
|
||||
|
||||
bool g_bUseTiers = false;
|
||||
|
||||
public Plugin myinfo = {
|
||||
name = "FakeClients",
|
||||
author = "Tsunami, .Rushaway",
|
||||
description = "Put fake clients in server with tier system",
|
||||
version = "3.0.0",
|
||||
url = "https://github.com/srcdslab/sm-plugin-FakeClients"
|
||||
}
|
||||
|
||||
public void OnPluginStart()
|
||||
{
|
||||
g_hCount = CreateConVar("sm_fakeclients_players", "8", "Fallback: number of bots when tier system is disabled", _, true, 0.0, true, 64.0);
|
||||
g_hDelay = CreateConVar("sm_fakeclients_delay", "120", "Delay after map change before fake clients join (seconds)", _, true, 0.0, true, 10000.0);
|
||||
g_hUseTiers = CreateConVar("sm_fakeclients_tiers", "0", "Use tier system from fakeclients_tiers.cfg (1 = enabled, 0 = disabled)", _, true, 0.0, true, 1.0);
|
||||
|
||||
g_bUseTiers = g_hUseTiers.BoolValue;
|
||||
g_hUseTiers.AddChangeHook(OnConVarChanged);
|
||||
|
||||
RegAdminCmd("sm_debugfakes", Command_DebugFakes, ADMFLAG_GENERIC, "Shows the amount of fake-clients on server");
|
||||
RegAdminCmd("sm_fakes", Command_Fakes, ADMFLAG_GENERIC, "Shows the fake-clients on server");
|
||||
|
||||
AutoExecConfig(true);
|
||||
}
|
||||
|
||||
public Action Command_DebugFakes(int client, int argc)
|
||||
{
|
||||
int iFakes = 0;
|
||||
int iFakesInTeam = 0;
|
||||
int iPlayers = GetClientCount(false);
|
||||
|
||||
for(int i = 1; i <= MaxClients; i++)
|
||||
{
|
||||
if (!IsClientConnected(i))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (IsFakeClient(i) || IsClientSourceTV(i))
|
||||
{
|
||||
iFakes++;
|
||||
iPlayers--;
|
||||
}
|
||||
if (IsFakeClient(i) && GetClientTeam(i) > CS_TEAM_SPECTATOR)
|
||||
iFakesInTeam++;
|
||||
|
||||
}
|
||||
|
||||
ReplyToCommand(client, "[SM] There are currently %d Fake-Clients, from which %d are in Spectate. Real Clients %d", iFakes, iFakes - iFakesInTeam, iPlayers);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
public Action Command_Fakes(int client, int args)
|
||||
{
|
||||
char aBuf[1024];
|
||||
char aBuf2[MAX_NAME_LENGTH];
|
||||
|
||||
for(int i = 1; i <= MaxClients; i++)
|
||||
{
|
||||
if(IsClientInGame(i))
|
||||
{
|
||||
if(IsClientConnected(i) && IsFakeClient(i) && !IsClientSourceTV(i))
|
||||
{
|
||||
GetClientName(i, aBuf2, sizeof(aBuf2));
|
||||
StrCat(aBuf, sizeof(aBuf), aBuf2);
|
||||
StrCat(aBuf, sizeof(aBuf), ", ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(strlen(aBuf))
|
||||
{
|
||||
aBuf[strlen(aBuf) - 2] = 0;
|
||||
ReplyToCommand(client, "[SM] Fake-Clients online: %s", aBuf);
|
||||
}
|
||||
else
|
||||
ReplyToCommand(client, "[SM] Fake-Clients online: none");
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public void OnMapStart()
|
||||
{
|
||||
ParseNames();
|
||||
ParseTiers();
|
||||
CreateTimer(g_hDelay.FloatValue, Timer_CreateFakeClients, _, TIMER_FLAG_NO_MAPCHANGE);
|
||||
}
|
||||
|
||||
public void OnConVarChanged(ConVar hConVar, const char[] sOldValue, const char[] sNewValue)
|
||||
{
|
||||
if (hConVar == g_hUseTiers)
|
||||
{
|
||||
g_bUseTiers = g_hUseTiers.BoolValue;
|
||||
LogMessage("Tier system %s", g_bUseTiers ? "enabled" : "disabled");
|
||||
|
||||
if (g_bUseTiers)
|
||||
{
|
||||
g_iPendingBots = 0;
|
||||
|
||||
for (int i = 1; i <= MaxClients; i++)
|
||||
{
|
||||
if (!IsClientConnected(i) || !IsClientInGame(i))
|
||||
continue;
|
||||
|
||||
if (!IsFakeClient(i) || IsClientSourceTV(i))
|
||||
continue;
|
||||
|
||||
KickClient(i, "Client Disconnect");
|
||||
}
|
||||
|
||||
// Wait a moment for all bots to be kicked before trying to add new ones according to tiers.
|
||||
CreateTimer(1.0, Timer_CreateFakeClients, _, TIMER_FLAG_NO_MAPCHANGE);
|
||||
}
|
||||
else
|
||||
{
|
||||
AdjustFakeClientsToTier();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the target bot count based on the current number of real players.
|
||||
* Falls back to sm_fakeclients_players if tiers are disabled or not loaded.
|
||||
*/
|
||||
int GetTargetBotCount(int iRealPlayers)
|
||||
{
|
||||
if (!g_bUseTiers || g_iTierCount == 0)
|
||||
return g_hCount.IntValue;
|
||||
|
||||
// Walk tiers from highest threshold down, pick the first one that applies
|
||||
for (int t = g_iTierCount - 1; t >= 0; t--)
|
||||
{
|
||||
if (iRealPlayers >= g_iTierThreshold[t])
|
||||
return g_iTierMaxBots[t];
|
||||
}
|
||||
|
||||
// No tier matched (e.g. config missing threshold "0")
|
||||
LogMessage("Warning: no tier matched for %d real players, defaulting to 0 bots", iRealPlayers);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the clamped target bot count, accounting for available slots and
|
||||
* server over-capacity. Shared by AdjustFakeClientsToTier and OnClientPutInServer.
|
||||
*/
|
||||
int ComputeTarget(int iBots, int iRealPlayers, int iReservedSlots)
|
||||
{
|
||||
int iTarget = GetTargetBotCount(iRealPlayers);
|
||||
if (iTarget < 0)
|
||||
iTarget = 0;
|
||||
|
||||
// Bots currently being added already count as occupied slots
|
||||
int iEffectiveBots = iBots + g_iPendingBots;
|
||||
int iFreeSlots = MaxClients - (iRealPlayers + iEffectiveBots + iReservedSlots);
|
||||
|
||||
if (iFreeSlots < 0)
|
||||
{
|
||||
iTarget = iEffectiveBots + iFreeSlots;
|
||||
if (iTarget < 0)
|
||||
iTarget = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int iMaxBotsBySlots = iEffectiveBots + iFreeSlots;
|
||||
if (iTarget > iMaxBotsBySlots)
|
||||
iTarget = iMaxBotsBySlots;
|
||||
}
|
||||
|
||||
return iTarget;
|
||||
}
|
||||
|
||||
/**
|
||||
* Kicks excess bots until the bot count reaches iTarget.
|
||||
* Never kicks real players or SourceTV.
|
||||
*/
|
||||
void KickExcessBots(int iBots, int iRealPlayers, int iTarget)
|
||||
{
|
||||
int iToKick = iBots - iTarget;
|
||||
int iKicked = 0;
|
||||
|
||||
for (int i = 1; i <= MaxClients && iKicked < iToKick; i++)
|
||||
{
|
||||
if (!IsClientConnected(i) || !IsClientInGame(i))
|
||||
continue;
|
||||
|
||||
// Safety: never kick real players or SourceTV
|
||||
if (!IsFakeClient(i) || IsClientSourceTV(i))
|
||||
continue;
|
||||
|
||||
LogMessage("Kicking fake client '%N' (slot %d) — bots:%d target:%d", i, i, iBots, iTarget);
|
||||
|
||||
KickClient(i, "Client Disconnect");
|
||||
iKicked++;
|
||||
}
|
||||
|
||||
if (iKicked > 0)
|
||||
LogMessage("Kicked %d bot(s) — real:%d bots:%d target:%d slots:%d", iKicked, iRealPlayers, iBots, iTarget, MaxClients);
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules staggered timers to add bots up to iToAdd, respecting free slots.
|
||||
*/
|
||||
void ScheduleBotsToAdd(int iToAdd, int iFreeSlots)
|
||||
{
|
||||
if (iFreeSlots <= 0 || iToAdd <= 0)
|
||||
return;
|
||||
|
||||
if (iToAdd > iFreeSlots)
|
||||
iToAdd = iFreeSlots;
|
||||
|
||||
// Keep a staggered cadence but add jitter so joins look less scripted.
|
||||
float fNextDelay = GetRandomFloat(0.4, 1.2);
|
||||
|
||||
for (int j = 0; j < iToAdd; j++)
|
||||
{
|
||||
g_iPendingBots++;
|
||||
CreateTimer(fNextDelay, Timer_CreateFakeClient, _, TIMER_FLAG_NO_MAPCHANGE);
|
||||
fNextDelay += GetRandomFloat(0.7, 1.9);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares current bot count against the target and either kicks excess bots
|
||||
* or schedules new ones to fill the gap.
|
||||
*/
|
||||
void AdjustFakeClientsToTier()
|
||||
{
|
||||
int iBots, iRealPlayers, iReservedSlots;
|
||||
CollectClientCounts(iBots, iRealPlayers, iReservedSlots);
|
||||
|
||||
int iTarget = ComputeTarget(iBots, iRealPlayers, iReservedSlots);
|
||||
int iFreeSlots = MaxClients - (iRealPlayers + iBots + iReservedSlots);
|
||||
|
||||
// Too many active bots -> kick extras
|
||||
if (iBots > iTarget)
|
||||
{
|
||||
g_iPendingBots = 0;
|
||||
KickExcessBots(iBots, iRealPlayers, iTarget);
|
||||
}
|
||||
// Active + pending bots are below target -> add missing bots
|
||||
else if ((iBots + g_iPendingBots) < iTarget)
|
||||
ScheduleBotsToAdd(iTarget - iBots - g_iPendingBots, iFreeSlots);
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects fake bots, real players and reserved slots in a single client loop.
|
||||
*/
|
||||
void CollectClientCounts(int &iBots, int &iRealPlayers, int &iReservedSlots)
|
||||
{
|
||||
iBots = 0;
|
||||
iRealPlayers = 0;
|
||||
bool bHasSourceTV = false;
|
||||
|
||||
for (int i = 1; i <= MaxClients; i++)
|
||||
{
|
||||
if (!IsClientConnected(i))
|
||||
continue;
|
||||
|
||||
if (IsClientSourceTV(i))
|
||||
{
|
||||
bHasSourceTV = true;
|
||||
continue; // SourceTV occupies its own slot in MaxClients — do not count it as a bot
|
||||
}
|
||||
|
||||
if (IsFakeClient(i))
|
||||
iBots++;
|
||||
else
|
||||
iRealPlayers++;
|
||||
}
|
||||
|
||||
// Reserve 1 free slot so a real player can always connect.
|
||||
// When SourceTV is active, reserve 1 extra (SourceTV's slot is already in MaxClients).
|
||||
iReservedSlots = bHasSourceTV ? 2 : 1;
|
||||
}
|
||||
|
||||
public void OnClientPutInServer(int client)
|
||||
{
|
||||
// Skip fake clients: bot additions are managed via timers.
|
||||
// Calling AdjustFakeClientsToTier on every bot join would cause cascading timers.
|
||||
if (!client || IsFakeClient(client))
|
||||
return;
|
||||
|
||||
// A real player joined: only kick excess bots, never schedule additions.
|
||||
// Scheduling here would race with the staggered timers already in flight.
|
||||
int iBots, iRealPlayers, iReservedSlots;
|
||||
CollectClientCounts(iBots, iRealPlayers, iReservedSlots);
|
||||
|
||||
int iTarget = ComputeTarget(iBots, iRealPlayers, iReservedSlots);
|
||||
if (iBots > iTarget)
|
||||
KickExcessBots(iBots, iRealPlayers, iTarget);
|
||||
}
|
||||
|
||||
public void OnClientDisconnect(int client)
|
||||
{
|
||||
// Ignore bot disconnects (caused by our own kicks) to avoid cascading timers.
|
||||
if (IsFakeClient(client))
|
||||
return;
|
||||
|
||||
CreateTimer(0.5, Timer_CreateFakeClients, _, TIMER_FLAG_NO_MAPCHANGE);
|
||||
}
|
||||
|
||||
public Action Timer_CreateFakeClient(Handle timer)
|
||||
{
|
||||
g_iPendingBots--;
|
||||
if (g_iPendingBots < 0)
|
||||
g_iPendingBots = 0;
|
||||
|
||||
int iBots, iRealPlayers, iReservedSlots;
|
||||
CollectClientCounts(iBots, iRealPlayers, iReservedSlots);
|
||||
|
||||
int iTarget = ComputeTarget(iBots, iRealPlayers, iReservedSlots);
|
||||
int iFreeSlots = MaxClients - (iRealPlayers + iBots + iReservedSlots);
|
||||
|
||||
// Recheck: tier may have changed since this timer was scheduled
|
||||
if (iFreeSlots <= 0 || iBots >= iTarget)
|
||||
return Plugin_Handled;
|
||||
|
||||
char sName[MAX_NAME_LENGTH];
|
||||
char sTarget[MAX_TARGET_LENGTH];
|
||||
int iTargets[MAXPLAYERS];
|
||||
bool bTN_Is_ML;
|
||||
|
||||
// Pick a random name, re-roll if it's already taken by a fake client.
|
||||
// Stop after trying all available names to prevent an infinite loop when
|
||||
// the name list is smaller than the number of bots (duplicates are allowed).
|
||||
// If no names are configured, CreateFakeClient will assign a default name based on the engine.
|
||||
int iNameCount = g_hNames.Length;
|
||||
if (iNameCount > 0)
|
||||
{
|
||||
g_hNames.GetString(GetRandomInt(0, iNameCount - 1), sName, sizeof(sName));
|
||||
|
||||
for (int iAttempt = 1; iAttempt < iNameCount; iAttempt++)
|
||||
{
|
||||
if (ProcessTargetString(sName, 0, iTargets, MAXPLAYERS, COMMAND_FILTER_NO_MULTI, sTarget, MAX_TARGET_LENGTH, bTN_Is_ML) != 1 || !IsFakeClient(iTargets[0]))
|
||||
break;
|
||||
|
||||
g_hNames.GetString(GetRandomInt(0, iNameCount - 1), sName, sizeof(sName));
|
||||
}
|
||||
}
|
||||
|
||||
CreateFakeClient(sName);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action Timer_CreateFakeClients(Handle timer)
|
||||
{
|
||||
AdjustFakeClientsToTier();
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads tier thresholds from configs/fakeclients_tiers.cfg. Max 32 tiers.
|
||||
* Format (KeyValues):
|
||||
*
|
||||
* "FakeClientsTiers"
|
||||
* {
|
||||
* "0" "12" // 0 real players → up to 12 bots
|
||||
* "5" "10" // 5+ real players → up to 10 bots
|
||||
* "15" "8" // And so on...
|
||||
* }
|
||||
*
|
||||
* Entries are sorted by threshold automatically, so order in the file
|
||||
* does not matter.
|
||||
*/
|
||||
stock void ParseTiers()
|
||||
{
|
||||
if (!g_bUseTiers)
|
||||
return;
|
||||
|
||||
g_iTierCount = 0;
|
||||
|
||||
char sPath[PLATFORM_MAX_PATH];
|
||||
BuildPath(Path_SM, sPath, sizeof(sPath), "configs/fakeclients_tiers.cfg");
|
||||
|
||||
KeyValues kv = new KeyValues("FakeClientsTiers");
|
||||
|
||||
if (!kv.ImportFromFile(sPath))
|
||||
{
|
||||
LogError("configs/fakeclients_tiers.cfg not found — falling back to sm_fakeclients_players");
|
||||
g_hUseTiers.BoolValue = false;
|
||||
delete kv;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!kv.GotoFirstSubKey(false))
|
||||
{
|
||||
LogError("configs/fakeclients_tiers.cfg is empty or malformed");
|
||||
g_hUseTiers.BoolValue = false;
|
||||
delete kv;
|
||||
return;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if (g_iTierCount >= MAX_TIERS)
|
||||
break;
|
||||
|
||||
char sKey[16], sVal[16];
|
||||
kv.GetSectionName(sKey, sizeof(sKey));
|
||||
kv.GetString(NULL_STRING, sVal, sizeof(sVal), "-1");
|
||||
|
||||
int iMaxBots = StringToInt(sVal);
|
||||
if (iMaxBots < 0)
|
||||
continue; // skip malformed lines
|
||||
|
||||
g_iTierThreshold[g_iTierCount] = StringToInt(sKey);
|
||||
g_iTierMaxBots[g_iTierCount] = iMaxBots;
|
||||
g_iTierCount++;
|
||||
|
||||
} while (kv.GotoNextKey(false));
|
||||
|
||||
delete kv;
|
||||
|
||||
// Bubble sort tiers by threshold (ascending) so GetTargetBotCount() works correctly
|
||||
for (int i = 0; i < g_iTierCount - 1; i++)
|
||||
{
|
||||
for (int j = 0; j < g_iTierCount - 1 - i; j++)
|
||||
{
|
||||
if (g_iTierThreshold[j] > g_iTierThreshold[j + 1])
|
||||
{
|
||||
int tmp;
|
||||
tmp = g_iTierThreshold[j]; g_iTierThreshold[j] = g_iTierThreshold[j + 1]; g_iTierThreshold[j + 1] = tmp;
|
||||
tmp = g_iTierMaxBots[j]; g_iTierMaxBots[j] = g_iTierMaxBots[j + 1]; g_iTierMaxBots[j + 1] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LogMessage("Loaded %d tier(s) from fakeclients_tiers.cfg", g_iTierCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads bot display names from configs/fakeclients.txt (one name per line).
|
||||
*/
|
||||
stock void ParseNames()
|
||||
{
|
||||
delete g_hNames;
|
||||
g_hNames = new ArrayList(MAX_NAME_LENGTH);
|
||||
|
||||
char sBuffer[256];
|
||||
BuildPath(Path_SM, sBuffer, sizeof(sBuffer), "configs/fakeclients.txt");
|
||||
|
||||
File hConfig = OpenFile(sBuffer, "r");
|
||||
if (!hConfig)
|
||||
{
|
||||
LogError("configs/fakeclients.txt not found — using default engine name");
|
||||
return;
|
||||
}
|
||||
|
||||
while (hConfig.ReadLine(sBuffer, sizeof(sBuffer)))
|
||||
{
|
||||
TrimString(sBuffer);
|
||||
if (strlen(sBuffer) > 0)
|
||||
g_hNames.PushString(sBuffer);
|
||||
}
|
||||
|
||||
delete hConfig;
|
||||
|
||||
if (!g_hNames.Length)
|
||||
LogError("configs/fakeclients.txt is empty — using default engine name");
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user