#pragma semicolon 1
#pragma newdecls required
#define PATH_FILE "cfg/bot.cfg"
ConVar
cvEnable,
cvMode,
cvSpec,
cvTimeMin,
cvTimeMax,
cvRemoveWeapon;
bool
bs_lock,
b_join,
pt_lock;
Handle
bot_join_after_player,
bot_quota_mode,
bot_quota,
ConnectedTimer;
int
CAB_bot;
public Plugin myinfo =
{
name = "Clever Autojoin Bots",
author = "AlmazON FiX",
description = "Ухищренное переключение активности ботов в игре",
version = "1.0.0",
url = "http://www.hlmod.net"
}
public void OnPluginStart()
{
cvEnable = CreateConVar("bot_autojoin_clever", "1", "Интеллектуальное автоматическое добавление ботов на сервер: 0 - отключено, 1 - включено.", 0, true, 0.0, true, 1.0);
cvMode = CreateConVar("bot_join_after_mode", "3", "bot_join_after_player: 1 - основной, 2 - постоянный, 3 - циклический.", 0, true, 1.0, true, 3.0);
cvSpec = CreateConVar("bot_join_after_spec", "1", "Боты - это зрители в [bot_join_after_player = 0].", 0, true, 0.0, true, 1.0);
cvTimeMin = CreateConVar("bot_mode_random_min", "25.5", "Минимальное время для имитации приближения человека к игроку.", 0, true, 0.0, true, 999.9);
cvTimeMax = CreateConVar("bot_mode_random_max", "99.9", "Максимальное время имитации человека при приближении игрока: 0 - отключено.", 0, true, 0.0);
cvRemoveWeapon = CreateConVar("CAB_removing_weapon", "1", "Удалите все оружие игрока при отключении от сервера.", 0, true, 0.0, true, 1.0);
bot_join_after_player = FindConVar("bot_join_after_player");
bot_quota_mode = FindConVar("bot_quota_mode");
bot_quota = FindConVar("bot_quota");
b_join = GetConVarBool(bot_join_after_player);
CAB_bot = GetConVarInt(bot_quota);
HookConVarChange(bot_join_after_player, ConVarChanged);
HookConVarChange(bot_quota, ConVarChanged);
HookConVarChange(cvEnable, OnConVarChanged);
HookConVarChange(cvSpec, OnConVarChanged);
if (!FileExists(PATH_FILE))
{
Handle CfgFile = OpenFile(PATH_FILE, "w");
WriteFileLine(CfgFile, "\n// Бот ждет, когда человек подключится и только тогда подключается сам.\n// -\nbot_join_after_player %i\n", b_join);
WriteFileLine(CfgFile, "\n// Количество добавляемых в игру ботов.\n// -\nbot_quota %d\n", CAB_bot);
CloseHandle(CfgFile);
PrintToServer("[CAB] The configuration file is automatically created in (%s).", PATH_FILE);
}
AutoExecConfig(false, "bot", "");
}
public void ConVarChanged(Handle convar, const char[] oldValue, const char[] newValue)
{
if (convar == bot_join_after_player)
b_join = view_as<bool>(StringToInt(newValue));
else CAB_bot = StringToInt(newValue);
}
public void OnConVarChanged(Handle convar, const char[] oldValue, const char[] newValue)
{
Change();
}
public void OnConfigsExecuted()
{
Handle CfgFile = OpenFile(PATH_FILE, "at");
WriteFileLine(CfgFile, "\n// Умное автодобавление ботов на сервер.\n// -\nbot_autojoin_clever %i\n", cvEnable.BoolValue);
WriteFileLine(CfgFile, "\n// bot_join_after_player:\n// 1 - лишь при загрузке карты, 2 - постоянна, 3 - переменна.\nbot_join_after_mode %d\n", cvMode.IntValue);
WriteFileLine(CfgFile, "\n// Боты будут находиться в спектаторах при bot_join_after_player = 0.\n// -\nbot_join_after_spec %i\n", cvSpec.BoolValue);
WriteFileLine(CfgFile, "\n// Время для иммитации выхода бота-'человека' при заходе игрока, минимум.\n// -\nbot_mode_random_min %f\n", cvTimeMin.FloatValue);
WriteFileLine(CfgFile, "\n// Максимум для иммитации выхода бота-'человека' при заходе игрока:\n// 0 - выключить.\nbot_mode_random_max %f\n", cvTimeMax.FloatValue);
WriteFileLine(CfgFile, "\n// Удалять всё оружие игрока при разъединении с сервером.\n// -\nCAB_removing_weapon %i\n", cvRemoveWeapon.BoolValue);
CloseHandle(CfgFile);
PrintToServer("[CAB] Write new data... finished!");
int size = FileSize(PATH_FILE);
if (!(1240 < size < 1245)) PrintToServer("[CAB] Load custom file size %d Bytes in (%s) completed successfully.", size, PATH_FILE);
Change();
}
public void OnClientConnected(int client)
{
if (IsRealPlayer(client))
{
UhEBS();
if (cvTimeMax.FloatValue > 0.0)
{
char bqm[5];
GetConVarString(bot_quota_mode, bqm, sizeof(bqm));
if (StrEqual(bqm, "fill", false))
{
pt_lock = true;
HookEvent("player_team", PlayerTeam, EventHookMode_Post);
}
}
switch (cvMode.IntValue)
{
case 1: cvMode.IntValue = 2;
case 2: return;
}
if (b_join) BJAP0();
else BJAP1();
}
}
void BotSpawn(Event event, const char[] name, bool dontBroadcast)
{
int i = GetClientOfUserId(GetEventInt(event, "userid"));
if (IsGamePlayer(i) && !GetRealClientCount(false) && GetClientTeam(i) > 1) ChangeClientTeam(i, 1);
}
void PlayerTeam(Event event, const char[] name, bool dontBroadcast)
{
int i = GetClientOfUserId(GetEventInt(event, "userid"));
if (IsGamePlayer(i) && !IsFakeClient(i) && GetEventInt(event, "team") != 1)
{
if (ConnectedTimer == null) SetConVarString(bot_quota_mode, "normal");
else delete ConnectedTimer;
ConnectedTimer = CreateTimer(GetRandomFloat(cvTimeMin.FloatValue, cvTimeMax.FloatValue), KickBots);
}
}
public Action CS_OnCSWeaponDrop(int ci, int wi)
{
if (cvEnable.BoolValue && cvRemoveWeapon.BoolValue && !IsClientInGame(ci))
{
char Bomb[10];
if (GetEntityClassname(wi, Bomb, sizeof(Bomb)) && StrEqual(Bomb, "weapon_c4")) return Plugin_Continue;
else return Plugin_Handled;
}return Plugin_Continue;
}
public void OnClientDisconnect(int client)
{
if (IsRealPlayer(client))
{
Change();
if (cvMode.IntValue == 3)
{
if (b_join) BJAP0();
else BJAP1();
}
}
}
Action KickBots(Handle timer)
{
PToff();
return Plugin_Continue;
}
void Change()
{
if (cvEnable.BoolValue && cvSpec.BoolValue)
{
if (!bs_lock)
{
bs_lock = true;
HookEvent("player_spawn", BotSpawn, EventHookMode_Pre);
Kick();
}
}else UhEBS();
PToff();
}
void Kick()
{
if (GetClientCount(false) - GetRealClientCount(false))
{
ServerCommand("bot_kick");
ServerCommand("bot_quota %d", CAB_bot);
}
}
void PToff()
{
if (pt_lock)
{
pt_lock = false;
UnhookEvent("player_team", PlayerTeam, EventHookMode_Post);
if (ConnectedTimer != null)
{
delete ConnectedTimer;
SetConVarString(bot_quota_mode, "fill");
}
}
}
void BJAP0()
{
SetConVarInt(bot_join_after_player, 0);
}
void BJAP1()
{
SetConVarInt(bot_join_after_player, 1);
}
void UhEBS()
{
if (bs_lock)
{
bs_lock = false;
UnhookEvent("player_spawn", BotSpawn, EventHookMode_Pre);
Kick();
}
}
stock int[] GetRealClientCount(bool InOnlyGame)
{
int clients = 0;
for (int i = 1; i <= MaxClients; i++)
{
if (((InOnlyGame) ? IsGamePlayer(i) : IsClientConnected(i)) && !IsFakeClient(i)) clients++;
}
return clients;
}
stock bool IsGamePlayer(int i)
{
return 0 < i <= MaxClients && IsClientInGame(i);
}
stock bool IsRealPlayer(int client)
{
return cvEnable.BoolValue && GetRealClientCount(false) == 1 && !IsFakeClient(client);
}