/**
*
* Name: Stop the Bastards
* Version: 1.6.6 (11.02.2017)
* Author: F@nt0M
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <
http://www.gnu.org/licenses/>
*
*/
#pragma semicolon 1
#include <amxmodx>
#include <reapi>
#include <sqlx>
#include <nvault>
#include <reaimdetector>
#if AMXX_VERSION_NUM < 183
#include <colorchat>
#define MAX_PLAYERS 32
#define MAX_NAME_LENGTH 32
new MaxClients;
#endif
// EDIT HERE
// #define FWD_DISCONNECT
#define MAX_REASONS 10
#define MAX_TIMES 10
#define MAX_REASON_LENGTH 64
#define DEFAULT_REASON "No Reason"
#define LOG_TAG "STOP_THE_BASTARDS"
// Special for Bullseye
#define HIDE_ME_IN_MENU
#define FORGIVE_DISPLAY_ALL
#define OBSERVER_HUD_POSITION 0.95, -1.0
//#define TAKEDMG_HOOK
#define MENU_TAB "^t^t^t^t"
// END EDIT BLOCK
// #define DEBUG
#if defined client_disconnected && !defined FWD_DISCONNECT
#define fwd_disconnected client_disconnected
#else
#define fwd_disconnected client_disconnect
#endif
#define isPlayer(%1) (1 <= %1 <= MaxClients)
forward amxbans_sql_initialized(Handle:sqlTuple, const dbPrefix[]);
forward fbans_sql_connected(Handle:sqlTuple);
#if defined DEBUG
CheckBit(v1, v2) {
#pragma unused v1
#pragma unused v2
return 1;
}
#else
#define CheckBit(%1,%2) (%1 & (1 << (%2 & 31)))
#endif
#define SetBit(%1,%2) (%1 |= (1 << (%2 & 31)))
#define ClearBit(%1,%2) (%1 &= ~(1 << (%2 & 31)))
#define ToggleFlag(%1,%2) (g_MenuPlayers[%1][MENU_PLAYERS_FLAGS] ^= %2)
#define CHECK_PLAYER(%1) \
if (%1 < 1 || %1 > MaxClients) { \
log_error(AMX_ERR_NATIVE, "Player out of range (%d)", %1); \
return 0; \
} else if (!is_user_connected(%1) && !is_user_connecting(%1)) { \
log_error(AMX_ERR_NATIVE, "Invalid player %d", %1); \
return 0; \
}
#define VERSION "1.6.6"
#define MAX_AUTHID_LENGTH 22
#define MAX_IP_LENGTH 16
#define TASK_CHECK_ID 100
#define TASK_TIMEOUT_ID 200
#define OBSERVER_TASK_ID 300
enum {
time_seconds = 1,
time_minutes = 60,
time_hours = 3600,
time_days = 86400,
time_weeks = 604800,
}
stock const g_TextChannels[][] = {
"#Cstrike_Chat_All",
"#Cstrike_Chat_AllDead",
"#Cstrike_Chat_T",
"#Cstrike_Chat_T_Dead",
"#Cstrike_Chat_CT",
"#Cstrike_Chat_CT_Dead",
"#Cstrike_Chat_Spec",
"#Cstrike_Chat_AllSpec"
};
stock const g_BanIpSteamId[] = {
"HLTV",
"STEAM_ID_LAN",
"VALVE_ID_LAN",
"VALVE_ID_PENDING",
"STEAM_ID_PENDING"
};
enum (+=1) {
NONE = 0,
AMXBANS,
FRESHBANS
}
enum (<<=1) {
BLOCK_ATTACK = 1, // a
BLOCK_TIMEOUT, // b
BLOCK_MOVE, // c
BLOCK_CHAT, // d
BLOCK_MICRO, // e
BLOCK_BAN // f
}
new g_BanSystem = NONE;
new g_BanType;
new Handle:g_DBTuple;
new g_TableName[32];
new g_ServerIp[16];
new g_ServerPort[6];
new g_ServerName[64];
enum _:REASON {
REASON_TIME,
REASON_FLAGS,
REASON_STRING[MAX_REASON_LENGTH]
}
new g_Reasons[MAX_REASONS][REASON];
new g_ReasonsNum = 0;
new g_Times[MAX_TIMES];
new g_TimesNum = 0;
enum _:MenuPlayersEnum{
MENU_PLAYERS_PAGE,
MENU_PALYERS_NUM,
MENU_PLAYERS_ID,
MENU_PLAYERS_TIME,
MENU_PLAYERS_FLAGS,
MENU_PLAYERS_REASON[MAX_REASON_LENGTH],
MENU_PLAYERS_DATA[MAX_PLAYERS]
};
new g_MenuPlayers[MAX_PLAYERS+1][MenuPlayersEnum];
new TeamName:g_PlayersMenuTeams[MAX_PLAYERS+1];
new g_LogFile[128];
new bool:g_CFGLogToFile = true;
new g_CFGBlockDamage = 90;
new g_CFGBlockTimeout = 60;
new g_CFGBlockMove = 30;
new g_CFGReservedSlots = 5;
new Float:g_CFGTimeoutMin = 0.5;
new Float:g_CFGTimeoutMax = 0.5;
new bool:g_CFGNotifyAdmins = true;
new bool:g_CFGNotifyPlayers = false;
new bool:g_CFGNotifyPunished = false;
new bool:g_CFGNotifyPlayer = false;
new bool:g_CFGAdminViewChat = true;
new g_CFGSuperFlag = ADMIN_CFG;
new g_DefaultReason[MAX_REASON_LENGTH] = DEFAULT_REASON;
new g_DefaultTime = 0;
new g_DefaultFlags = BLOCK_ATTACK | BLOCK_CHAT | BLOCK_MICRO | BLOCK_BAN;
new g_MsgSayText;
new g_MsgSayTextEvent;
new HookChain:g_HookTakeDamage;
new HookChain:g_HookPlayerKilled;
#if defined OBSERVER_HUD_POSITION
new HookChain:g_HookObserver;
new HookChain:g_HookPlayerSpawn;
#endif
new bool:g_Enabled;
new g_BlockList;
new g_MsgHud;
new g_FwdPunished;
new g_FwdForgived;
new g_FwdChecked;
new g_FwdReturn;
new g_IsBlocked;
new g_IsAttackBlocked;
new g_IsAttackTimeout;
new g_IsMoveBlocked;
new g_IsChatBlocked;
new g_IsMicroBlocked;
enum _:PLAYER_DATA {
PLAYER_BAN_ID,
PLAYER_BLOCK_EXPIRED,
PLAYER_TIMEOUT_FLAGS,
PLAYER_NAME[MAX_NAME_LENGTH],
PLAYER_AUTHID[MAX_AUTHID_LENGTH],
PLAYER_IP[MAX_IP_LENGTH],
}
new g_PlayersData[MAX_PLAYERS+1][PLAYER_DATA];
public plugin_natives()
{
set_native_filter("native_filter");
register_library("StopTheBastards");
register_native("stb_punish_player", "native_punish_player", 0);
register_native("stb_forgive_player", "native_forgive_player", 0);
}
public native_filter(const name[], index, trap)
{
#pragma unused index
#pragma unused name
return trap ? PLUGIN_CONTINUE : PLUGIN_HANDLED;
}
public plugin_precache()
{
parseConfig();
}
public plugin_init()
{
register_plugin("Stop the Bastards", VERSION, "F@nt0M");
register_cvar("stb_version", VERSION, FCVAR_SERVER | FCVAR_SPONLY);
register_dictionary("stop_the_bastards.txt");
register_dictionary("common.txt");
register_concmd("amx_sb", "cmdPunish", ADMIN_BAN);
register_concmd("amx_unsb", "cmdForgive", ADMIN_BAN);
register_concmd("amx_sbconfig", "cmdConfig", ADMIN_CFG);
register_clcmd("amx_sbmenu", "cmdMenu", ADMIN_BAN);
register_clcmd("say /sb", "cmdPunishChat", ADMIN_BAN);
register_clcmd("say_team /sb", "cmdPunishChat", ADMIN_BAN);
register_menucmd(register_menuid("MENU_STB_PLAYERS"), 1023, "ActionMenuPlayers");
register_menucmd(register_menuid("MENU_STB_REASONS"), 1023, "ActionReason");
register_menucmd(register_menuid("MENU_STB_TIME"), 1023, "ActionTime");
register_menucmd(register_menuid("MENU_STB_FLAGS"), 1023, "ActionFlags");
register_menucmd(register_menuid("MENU_STB_ACCEPT"), 1023, "ActionAccept");
RegisterHookChain(RG_CBasePlayer_SetClientUserInfoName, "HookSetClientUserInfoName", 1);
#if defined TAKEDMG_HOOK
g_HookTakeDamage = RegisterHookChain(RG_CBasePlayer_TakeDamage, "HookPlayerTakeDamage", 0);
#else
g_HookTakeDamage = RegisterHookChain(RG_CSGameRules_FPlayerCanTakeDamage, "HookPlayerCanTakeDamage", 1);
#endif
g_HookPlayerKilled = RegisterHookChain(RG_CBasePlayer_Killed, "HookPlayerKilled", 0);
#if defined OBSERVER_HUD_POSITION
g_HookObserver = RegisterHookChain(RG_CBasePlayer_StartObserver, "HookStartObserver", 1);
g_HookPlayerSpawn = RegisterHookChain(RG_CBasePlayer_Spawn, "HookStarSpawn", 1);
#endif
g_MsgSayText = get_user_msgid("SayText");
#if defined DEBUG
SetHooksEnable(true);
#else
SetHooksEnable(false);
#endif
g_BlockList = nvault_open("stop_the_bastards");
if (g_BlockList == INVALID_HANDLE) {
LogError("Error open nvault file");
}
#if AMXX_VERSION_NUM < 183
MaxClients = get_maxplayers();
#endif
g_MsgHud = CreateHudSyncObj();
g_FwdPunished = CreateMultiForward("stb_punished_player", ET_IGNORE, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_STRING);
g_FwdForgived = CreateMultiForward("stb_forgived_player", ET_IGNORE, FP_CELL, FP_CELL, FP_CELL);
g_FwdChecked = CreateMultiForward("stb_checked_player", ET_IGNORE, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_STRING);
}
public plugin_cfg()
{
get_cvar_string("hostname", g_ServerName, charsmax(g_ServerName));
get_user_ip(0, g_ServerIp, charsmax(g_ServerIp), 0);
strtok(g_ServerIp, g_ServerIp, charsmax(g_ServerIp), g_ServerPort, charsmax(g_ServerPort), ':');
copy(g_PlayersData[0][PLAYER_NAME], MAX_NAME_LENGTH - 1, g_ServerName);
copy(g_PlayersData[0][PLAYER_AUTHID], MAX_AUTHID_LENGTH - 1, "STEAM_ID_SERVER");
formatex(g_PlayersData[0][PLAYER_IP], MAX_IP_LENGTH - 1, "%s:%s", g_ServerIp, g_ServerPort);
}
public plugin_end()
{
if (g_BlockList != INVALID_HANDLE) {
nvault_close(g_BlockList);
}
if (g_FwdPunished != INVALID_HANDLE) {
DestroyForward(g_FwdPunished);
}
if (g_FwdForgived != INVALID_HANDLE) {
DestroyForward(g_FwdForgived);
}
if (g_FwdChecked != INVALID_HANDLE) {
DestroyForward(g_FwdChecked);
}
}
public client_connect(id)
{
if (g_Enabled) {
KickPlayers();
}
}
public client_putinserver(id)
{
ClearBit(g_IsBlocked, id);
ClearBit(g_IsAttackBlocked, id);
ClearBit(g_IsAttackTimeout, id);
ClearBit(g_IsChatBlocked, id);
ClearBit(g_IsMicroBlocked, id);
g_PlayersData[id][PLAYER_BAN_ID] = 0;
g_PlayersData[id][PLAYER_BLOCK_EXPIRED] = 0;
g_PlayersData[id][PLAYER_TIMEOUT_FLAGS] = 0;
get_user_name(id, g_PlayersData[id][PLAYER_NAME], MAX_NAME_LENGTH - 1);
get_user_authid(id, g_PlayersData[id][PLAYER_AUTHID], MAX_AUTHID_LENGTH - 1);
get_user_ip(id, g_PlayersData[id][PLAYER_IP], MAX_IP_LENGTH - 1, 1);
CheckPlayer(id);
}
public fwd_disconnected(id)
{
ClearBit(g_IsBlocked, id);
ClearBit(g_IsAttackBlocked, id);
ClearBit(g_IsChatBlocked, id);
ClearBit(g_IsAttackTimeout, id);
ClearBit(g_IsMicroBlocked, id);
g_PlayersData[id][PLAYER_BAN_ID] = 0;
g_PlayersData[id][PLAYER_BLOCK_EXPIRED] = 0;
g_PlayersData[id][PLAYER_TIMEOUT_FLAGS] = 0;
arrayset(g_PlayersData[id][PLAYER_NAME], 0, MAX_NAME_LENGTH);
arrayset(g_PlayersData[id][PLAYER_AUTHID], 0, MAX_AUTHID_LENGTH);
arrayset(g_PlayersData[id][PLAYER_IP], 0, MAX_IP_LENGTH);
if (g_Enabled && NumberOfSetBits(g_IsBlocked) == 0) {
SetHooksEnable(false);
}
}
public HookSetClientUserInfoName(const id, infobuffer[], name[])
{
#pragma unused infobuffer
if (strcmp(name, g_PlayersData[id][PLAYER_NAME])) {
copy(g_PlayersData[id][PLAYER_NAME], MAX_NAME_LENGTH - 1, name);
}
return HC_CONTINUE;
}
public TaskCheckExpired()
{
static id, systime, blocked;
systime = get_systime();
blocked = g_IsBlocked;
while ((id = ctz(blocked)) != 0) {
if (is_user_connected(id) && g_PlayersData[id][PLAYER_BLOCK_EXPIRED] <= systime) {
ForgivePlayer(0, id, true);
}
ClearBit(blocked, id);
}
}
public MessageSayText(msgid, dest, receiver)
{
#pragma unused msgid
#pragma unused dest
static sender;
if (get_msg_args() != 4) {
return PLUGIN_CONTINUE;
}
if (g_CFGAdminViewChat && (get_user_flags(receiver) & ADMIN_CHAT)) {
return PLUGIN_CONTINUE;
}
sender = get_msg_arg_int(1);
return (sender != receiver && CheckBit(g_IsChatBlocked, sender)) ? PLUGIN_HANDLED : PLUGIN_CONTINUE;
}
#if defined TAKEDMG_HOOK
public HookPlayerTakeDamage(const id, const pevInflictor, const attacker, Float:flDamage, bitsDamageType)
{
#pragma unused pevInflictor
static chance, player, bool:blocked, returnVal;
returnVal = HC_CONTINUE;
if (!isPlayer(attacker) || id == attacker || get_member(id, m_iTeam) == get_member(attacker, m_iTeam)) {
return returnVal;
}
#if defined DEBUG
chance = 0;
player = attacker;
#else
if (CheckBit(g_IsBlocked, attacker)) {
player = attacker;
} else if (CheckBit(g_IsBlocked, id)) {
player = id;
} else {
return returnVal;
}
chance = random_num(0, 99);
#endif
if (attacker == player && chance < g_CFGBlockDamage && CheckBit(g_IsAttackBlocked, attacker)) {
SendDamageMessage(id, attacker, floatround(flDamage), bitsDamageType);
SetHookChainReturn(ATYPE_INTEGER, 0);
SetHookChainArg(4, ATYPE_FLOAT,0.0);
returnVal = HC_SUPERCEDE;
}
blocked = false;
if (chance < g_CFGBlockTimeout && CheckBit(g_IsAttackTimeout, player)) {
set_member(player, m_bIsDefusing, true);
g_PlayersData[player][PLAYER_TIMEOUT_FLAGS] |= BLOCK_TIMEOUT;
blocked = true;
}
if (chance < g_CFGBlockMove && CheckBit(g_IsMoveBlocked, player)) {
set_entvar(player, var_flags, get_entvar(player, var_flags) | FL_FROZEN);
g_PlayersData[player][PLAYER_TIMEOUT_FLAGS] |= BLOCK_MOVE;
blocked = true;
}
if (blocked) {
remove_task(TASK_TIMEOUT_ID + player);
set_task(random_float(g_CFGTimeoutMin, g_CFGTimeoutMax), "TaskTimeout", TASK_TIMEOUT_ID + player);
}
return returnVal;
}
#else
public HookPlayerCanTakeDamage(const id, const attacker)
{
static chance, player, bool:blocked;
if (!isPlayer(attacker) || id == attacker || get_member(id, m_iTeam) == get_member(attacker, m_iTeam)) {
return HC_CONTINUE;
}
#if defined DEBUG
chance = 0;
player = attacker;
#else
if (CheckBit(g_IsBlocked, attacker)) {
player = attacker;
} else if (CheckBit(g_IsBlocked, id)) {
player = id;
} else {
return HC_CONTINUE;
}
chance = random_num(0, 99);
#endif
if (attacker == player && chance < g_CFGBlockDamage && CheckBit(g_IsAttackBlocked, attacker)) {
SendDamageMessage(id, attacker, chance, DMG_BULLET);
SetHookChainReturn(ATYPE_INTEGER, 0);
}
blocked = false;
if (chance < g_CFGBlockTimeout && CheckBit(g_IsAttackTimeout, player)) {
set_member(player, m_bIsDefusing, true);
g_PlayersData[player][PLAYER_TIMEOUT_FLAGS] |= BLOCK_TIMEOUT;
blocked = true;
}
if (chance < g_CFGBlockMove && CheckBit(g_IsMoveBlocked, player)) {
set_entvar(player, var_flags, get_entvar(player, var_flags) | FL_FROZEN);
g_PlayersData[player][PLAYER_TIMEOUT_FLAGS] |= BLOCK_MOVE;
blocked = true;
}
if (blocked) {
remove_task(TASK_TIMEOUT_ID + player);
set_task(random_float(g_CFGTimeoutMin, g_CFGTimeoutMax), "TaskTimeout", TASK_TIMEOUT_ID + player);
}
return HC_CONTINUE;
}
#endif
public HookPlayerKilled(const victim, const killer, const inflictor)
{
#pragma unused killer
#pragma unused inflictor
if (task_exists(TASK_TIMEOUT_ID + victim)) {
remove_task(TASK_TIMEOUT_ID + victim);
TaskTimeout(TASK_TIMEOUT_ID + victim);
}
}
public TaskTimeout(id)
{
id -= TASK_TIMEOUT_ID;
if (g_PlayersData[id][PLAYER_TIMEOUT_FLAGS] & BLOCK_TIMEOUT) {
set_member(id, m_bIsDefusing, false);
}
if (g_PlayersData[id][PLAYER_TIMEOUT_FLAGS] & BLOCK_MOVE) {
set_entvar(id, var_flags, get_entvar(id, var_flags) & ~FL_FROZEN);
}
g_PlayersData[id][PLAYER_TIMEOUT_FLAGS] = 0;
}
#if defined OBSERVER_HUD_POSITION
public HookStartObserver(const id)
{
remove_task(OBSERVER_TASK_ID + id);
set_task(1.0, "TaskObserver", OBSERVER_TASK_ID + id, .flags = "b");
}
public HookStarSpawn(const id)
{
remove_task(OBSERVER_TASK_ID + id);
}
public TaskObserver(id)
{
id -= OBSERVER_TASK_ID;
if (get_member(id, m_iObserverLastMode) != 4) {
return PLUGIN_CONTINUE;
}
new player = get_member(id, m_hObserverTarget);
if (!isPlayer(player) || !is_user_connected(player)) {
return PLUGIN_CONTINUE;
}
if (!CheckBit(g_IsBlocked, player)) {
return PLUGIN_CONTINUE;
}
set_hudmessage(255, 51, 204, OBSERVER_HUD_POSITION, 0, 1.0, 1.0);
ShowSyncHudMsg(id, g_MsgHud, "%L", id, "STB_HUD_INFO");
return PLUGIN_CONTINUE;
}
#endif
public cmdPunish(id, level)
{
if (~get_user_flags(id) & level) {
console_print(id, "%L", id, "NO_ACC_COM");
return PLUGIN_HANDLED;
}
if (read_argc() < 2) {
console_print(id, "%L: amx_sb <steamID or nickname or #authid or IP> [flags] [time] [reason]", id, "USAGE");
return PLUGIN_HANDLED;
}
new args[160], identifier[32], timeStr[32], reason[64], flagsStr[32];
read_args(args, charsmax(args));
#if AMXX_VERSION_NUM < 183
new pos = strbreak(args, identifier, charsmax(identifier), args, charsmax(args));
if (pos != -1) {
pos = strbreak(args, flagsStr, charsmax(flagsStr), args, charsmax(args));
}
if (pos != -1) {
pos = strbreak(args, timeStr, charsmax(timeStr), args, charsmax(args));
}
if (pos != -1) {
copy(reason, charsmax(reason), args);
}
#else
new pos;
pos = argparse(args, pos, identifier, charsmax(identifier));
if (pos != -1) {
pos = argparse(args, pos, flagsStr, charsmax(flagsStr));
}
if (pos != -1) {
pos = argparse(args, pos, timeStr, charsmax(timeStr));
}
if (pos != -1) {
copy(reason, charsmax(reason), args[pos]);
}
#endif
trim(identifier);
trim(flagsStr);
trim(timeStr);
trim(reason);
remove_quotes(identifier);
remove_quotes(flagsStr);
remove_quotes(timeStr);
remove_quotes(reason);
new player = locate_player(identifier);
if (!player) {
console_print(id, "%L", id, "MORE_CL_MATCHT");
return PLUGIN_HANDLED;
}
if ((get_user_flags(player) & ADMIN_IMMUNITY) && !(get_user_flags(id) & g_CFGSuperFlag)) {
console_print(id, "%L", id, "CLIENT_IMM", g_PlayersData[player][PLAYER_NAME]);
return PLUGIN_HANDLED;
}
if (CheckBit(g_IsBlocked, player)) {
console_print(id, "%L", id, "STB_IS_PUNISHED", g_PlayersData[player][PLAYER_NAME]);
return PLUGIN_HANDLED;
}
new time = timeStr[0] ? parseTime(timeStr) : g_DefaultTime;
new flags = flagsStr[0] ? read_flags(flagsStr) : g_DefaultFlags;
if (!reason[0]) {
copy(reason, charsmax(reason), g_DefaultReason);
}
PunishPlayer(id, player, reason, time, flags);
console_print(id, "Player ^"%s^" successfully punished", g_PlayersData[player][PLAYER_NAME]);
return PLUGIN_HANDLED;
}
public cmdForgive(id, level)
{
if (~get_user_flags(id) & level) {
console_print(id, "%L", id, "NO_ACC_COM");
return PLUGIN_HANDLED;
}
if (read_argc() < 2) {
console_print(id, "%L: amx_unsb <steamID or nickname or #authid or IP>", id, "USAGE");
return PLUGIN_HANDLED;
}
new args[32];
read_args(args, charsmax(args));
remove_quotes(args);
new player = locate_player(args);
if (!player) {
return cmdForgiveOffline(id, args);
}
if (!CheckBit(g_IsBlocked, player)) {
console_print(id, "%L", id, "STB_NOT_PUNISHED", g_PlayersData[player][PLAYER_NAME]);
return PLUGIN_HANDLED;
}
ForgivePlayer(id, player, false);
console_print(id, "Player ^"%s^" successfully forgiven", g_PlayersData[player][PLAYER_NAME]);
return PLUGIN_HANDLED;
}
cmdForgiveOffline(id, const authId[])
{
if (g_BlockList == INVALID_HANDLE) {
console_print(id, "%L", id, "MORE_CL_MATCHT");
return PLUGIN_HANDLED;
}
new data[2], timestamp;
if (!nvault_lookup(g_BlockList, authId, data, charsmax(data), timestamp)) {
console_print(id, "%L", id, "MORE_CL_MATCHT");
return PLUGIN_HANDLED;
}
nvault_remove(g_BlockList, authId);
console_print(id, "Player ^"%s^" successfully forgiven", authId);
return PLUGIN_HANDLED;
}
public cmdMenu(id, level)
{
if (~get_user_flags(id) & level) {
console_print(id, "%L", id, "NO_ACC_COM");
return PLUGIN_HANDLED;
}
DisplayMenuPlayers(id, false);
return PLUGIN_HANDLED;
}
public cmdConfig(id, level)
{
if (~get_user_flags(id) & level) {
console_print(id, "%L", id, "NO_ACC_COM");
return PLUGIN_HANDLED;
}
if (read_argc() < 2) {
console_print(id, "%L: amx_sbconfig <key> [value]", id, "USAGE");
return PLUGIN_HANDLED;
}
new args[256];
read_args(args, charsmax(args));
new key[128], value[128];
if (!strcmp(args, "reload")) {
if (parseConfig()) {
console_print(id, "[%s] Reloading successfully finished", LOG_TAG);
} else {
console_print(id, "[%s] Error while reloading", LOG_TAG);
}
} else if (!strcmp(args, "clean")) {
if (g_BlockList != INVALID_HANDLE) {
nvault_prune(g_BlockList, 0, get_systime());
console_print(id, "[%s] Cleaning successfully finished", LOG_TAG);
} else {
console_print(id, "[%s] Error while cleaning", LOG_TAG);
}
} else if (!strcmp(args, "dump")) {
new const config[][] = {
"log_to_file",
"reserved_slots",
"block_damage",
"block_timeout",
"block_move",
"timeout_min",
"timeout_max",
"default_reason",
"default_time",
"default_type",
"super_flag",
"notify_admins",
"notify_players",
"notify_punished",
"notify_player",
"admin_view_chat"
};
for (new i = 0; i < sizeof config; i++) {
GetCfgValue(config
, value, charsmax(value));
console_print(id, "[%s] %s is '%s'", LOG_TAG, config, value);
}
} else {
parse(args, key, charsmax(key), value, charsmax(value));
if (value[0]) {
if (SetCfgValue(key, value)) {
console_print(id, "[%s] %s successfully changed", LOG_TAG, key);
} else {
console_print(id, "[%s] %s not found", LOG_TAG, key);
}
} else {
if (GetCfgValue(key, value, charsmax(value))) {
console_print(id, "[%s] %s is '%s'", LOG_TAG, key, value);
} else {
console_print(id, "[%s] %s not found", LOG_TAG, key);
}
}
}
return PLUGIN_HANDLED;
}
public cmdPunishChat(id, level)
{
if (~get_user_flags(id) & level) {
console_print(id, "%L", id, "NO_ACC_COM");
return PLUGIN_CONTINUE;
}
DisplayMenuPlayers(id, true);
return PLUGIN_CONTINUE;
}
public amxbans_sql_initialized(Handle:sqlTuple, const dbPrefix[])
{
if (g_BanSystem != NONE) {
return PLUGIN_CONTINUE;
}
g_DBTuple = sqlTuple;
g_BanSystem = AMXBANS;
formatex(g_TableName, charsmax(g_TableName), "%s_bans", dbPrefix);
get_cvar_string("amxbans_server_address", g_ServerIp, charsmax(g_ServerIp));
if (!g_ServerIp[0]) {
get_user_ip(0, g_ServerIp, charsmax(g_ServerIp), 0);
}
strtok(g_ServerIp, g_ServerIp, charsmax(g_ServerIp), g_ServerPort, charsmax(g_ServerPort), ':');
get_cvar_string("amxbans_servernick", g_ServerName, charsmax(g_ServerName));
if (!g_ServerName[0]) {
get_cvar_string("hostname", g_ServerName, charsmax(g_ServerName));
}
copy(g_PlayersData[0][PLAYER_NAME], MAX_NAME_LENGTH - 1, g_ServerName);
formatex(g_PlayersData[0][PLAYER_IP], MAX_IP_LENGTH - 1, "%s:%s", g_ServerIp, g_ServerPort);
g_BanType = get_cvar_num("amxbans_bantype");
return PLUGIN_CONTINUE;
}
public fbans_sql_connected(Handle:sqlTuple)
{
if (g_BanSystem != NONE) {
return PLUGIN_CONTINUE;
}
g_DBTuple = sqlTuple;
g_BanSystem = FRESHBANS;
get_cvar_string("fb_sql_table", g_TableName, charsmax(g_TableName));
get_cvar_string("fb_server_ip", g_ServerIp, charsmax(g_ServerIp));
get_cvar_string("fb_server_port", g_ServerPort, charsmax(g_ServerPort));
get_cvar_string("fb_server_name", g_ServerName, charsmax(g_ServerName));
copy(g_PlayersData[0][PLAYER_NAME], MAX_NAME_LENGTH - 1, g_ServerName);
formatex(g_PlayersData[0][PLAYER_IP], MAX_IP_LENGTH - 1, "%s:%s", g_ServerIp, g_ServerPort);
g_BanType = get_cvar_num("fb_force_bantype_ip");
return PLUGIN_CONTINUE;
}
DisplayMenuPlayers(id, bool:punished)
{
new players[MAX_PLAYERS], num;
for (new i = 1; i <= MaxClients; i++) {
if (!is_user_connected(i) || (punished && !CheckBit(g_IsBlocked, i))) {
continue;
}
#if defined HIDE_ME_IN_MENU
if (id == i) {
continue;
}
#endif
players[num++] = i;
g_PlayersMenuTeams = TeamName:get_member(i, m_iTeam);
}
if (num == 0) {
client_print_color(id, print_team_default, "%L", id, "STB_EMPTY_LIST");
} else {
arrayset(g_MenuPlayers[id][MENU_PLAYERS_DATA], 0, MAX_PLAYERS);
SortCustom1D(players, num, "_PlayersMenuSortTeam");
g_MenuPlayers[id][MENU_PLAYERS_DATA] = players;
g_MenuPlayers[id][MENU_PALYERS_NUM] = num;
RenderMenuPlayers(id, 0);
}
}
public _PlayersMenuSortTeam(const elem1, const elem2)
{
if (elem1 == 0 || elem2 == 0 || elem1 == elem2) {
return 0;
}
if (g_PlayersMenuTeams[elem1] > g_PlayersMenuTeams[elem2]) {
return 1;
} else if (g_PlayersMenuTeams[elem1] < g_PlayersMenuTeams[elem2]) {
return -1;
}
return 0;
}
RenderMenuPlayers(id, page)
{
if (page < 0) {
g_MenuPlayers[id][MENU_PLAYERS_ID] = 0;
g_MenuPlayers[id][MENU_PLAYERS_REASON][0] = EOS;
g_MenuPlayers[id][MENU_PLAYERS_TIME] = -1;
g_MenuPlayers[id][MENU_PLAYERS_FLAGS] = 0;
return PLUGIN_HANDLED;
}
new bool:superFlag = (get_user_flags(id) & g_CFGSuperFlag) ? true : false;
new num = g_MenuPlayers[id][MENU_PALYERS_NUM];
new i = min(page * 8, num);
new start = i - (i % 8);
new end = min(start + 8, num);
page = start / 8;
g_MenuPlayers[id][MENU_PLAYERS_PAGE] = page;
new menu[512], team[10];
new len = formatex(menu, charsmax(menu), "%s\r%L^t\d%d/%d^n^n", MENU_TAB, id, "STB_MENU_TITLE", page + 1, ((num - 1) / 8) + 1);
new player, flags;
new keys = MENU_KEY_0;
new item = 0;
for (i = start; i < end; i++) {
player = g_MenuPlayers[id][MENU_PLAYERS_DATA];
if (!is_user_connected(player)) {
continue;
}
switch (g_PlayersMenuTeams[player]) {
case TEAM_TERRORIST: {
formatex(team, charsmax(team), "TT");
}
case TEAM_CT: {
formatex(team, charsmax(team), "CT");
}
default: {
formatex(team, charsmax(team), "SPEC");
}
}
if (id == player) {
keys |= (1 << item);
if (CheckBit(g_IsBlocked, player)) {
len += formatex(menu[len], charsmax(menu) - len, "%s\r[%d] \r[%s] [PUNISHED] ", MENU_TAB, ++item, team);
} else {
len += formatex(menu[len], charsmax(menu) - len, "%s\r[%d] \y[%s] ", MENU_TAB, ++item, team);
}
} else if (is_user_hltv(player)) {
len += formatex(menu[len], charsmax(menu) - len, "%s\d[%d] [HLTV] ", MENU_TAB, ++item);
} else if (is_user_bot(player)) {
#if defined DEBUG
keys |= (1 << item);
#endif
len += formatex(menu[len], charsmax(menu) - len, "%s\d[%d] [%s] [BOT] ", MENU_TAB, ++item, team);
} else {
flags = get_user_flags(player);
if ((flags & ADMIN_IMMUNITY) && !superFlag) {
len += formatex(menu[len], charsmax(menu) - len, "%s\d[%d] [%s] [IMMUNITY] ", MENU_TAB, ++item, team);
} else if (CheckBit(g_IsBlocked, player)) {
keys |= (1 << item);
len += formatex(menu[len], charsmax(menu) - len, "%s\r[%d] \r[%s] [PUNISHED] ", MENU_TAB, ++item, team);
} else {
keys |= (1 << item);
len += formatex(menu[len], charsmax(menu) - len, "%s\r[%d] \y[%s] ", MENU_TAB, ++item, team);
}
}
len += formatex(menu[len], charsmax(menu) - len, " \w%s^n", g_PlayersData[player][PLAYER_NAME]);
}
new tmp[15];
setc(tmp, 8 - (end - start), '^n');
len += copy(menu[len], charsmax(menu) - len, tmp);
if (end < num) {
keys |= MENU_KEY_9;
len += formatex(menu[len], charsmax(menu) - len, "^n%s\r[9] \w%L^n%s\r[0] \w%L", MENU_TAB, id, "MORE", MENU_TAB, id, (page == 0 ? "EXIT" : "BACK"));
} else {
len += formatex(menu[len], charsmax(menu) - len, "^n^n%s\r[0] \w%L", MENU_TAB, id, (page == 0 ? "EXIT" : "BACK"));
}
show_menu(id, keys, menu, -1, "MENU_STB_PLAYERS");
return PLUGIN_HANDLED;
}
public ActionMenuPlayers(id, key)
{
switch (key) {
case 8: {
RenderMenuPlayers(id, ++g_MenuPlayers[id][MENU_PLAYERS_PAGE]);
}
case 9: {
RenderMenuPlayers(id, --g_MenuPlayers[id][MENU_PLAYERS_PAGE]);
}
default: {
new player = (g_MenuPlayers[id][MENU_PLAYERS_PAGE] * 8) + key;
player = g_MenuPlayers[id][MENU_PLAYERS_DATA][player];
if (!is_user_connected(player)) {
client_print_color(id, print_team_default, "%L", id, "STB_DISCONNECTED");
} else {
g_MenuPlayers[id][MENU_PLAYERS_ID] = player;
if (!CheckBit(g_IsBlocked, player) && g_ReasonsNum != 0) {
DisplayMenuReason(id);
} else {
DisplayMenuAccept(id);
}
}
}
}
}
DisplayMenuReason(id, page = 0)
{
if (page < 0) {
RenderMenuPlayers(id, 0);
return PLUGIN_HANDLED;
}
new i = min(page * 8, g_ReasonsNum);
new start = i - (i % 8);
new end = min(start + 8, g_ReasonsNum);
page = start / 8;
g_MenuPlayers[id][MENU_PLAYERS_PAGE] = page;
new menu[512];
new len = formatex(menu, charsmax(menu), "%s\r%L^t\d%d/%d^n^n", MENU_TAB, id, "STB_REASON_TITLE", page + 1, ((g_ReasonsNum - 1) / 8) + 1);
new keys = MENU_KEY_0;
new item = 0;
new timeDisplay[64];
for (i = start; i < end; i++) {
keys |= (1 << item);
len += formatex(menu[len], charsmax(menu) - len, "%s\r[%d] \y%s", MENU_TAB, ++item, g_Reasons[REASON_STRING]);
if (g_Reasons[REASON_TIME] != -1) {
GetTimeString(id, g_Reasons[REASON_TIME], timeDisplay, charsmax(timeDisplay), time_minutes);
len += formatex(menu[len], charsmax(menu) - len, " \d[\r%s\d]", timeDisplay);
}
len += add(menu[len], charsmax(menu) - len, "^n");
}
new tmp[15];
setc(tmp, 8 - (end - start), '^n');
len += copy(menu[len], charsmax(menu) - len, tmp);
if (end < g_ReasonsNum) {
keys |= MENU_KEY_9;
len += formatex(menu[len], charsmax(menu) - len, "^n%s\r[9] \w%L^n\r%s[0] \w%L", MENU_TAB, id, "MORE", MENU_TAB, id, "BACK");
} else {
len += formatex(menu[len], charsmax(menu) - len, "^n^n%s\r[0] \w%L", MENU_TAB, id, "BACK");
}
show_menu(id, keys, menu, -1, "MENU_STB_REASONS");
return PLUGIN_HANDLED;
}
public ActionReason(id, key)
{
switch (key) {
case 8: {
DisplayMenuReason(id, ++g_MenuPlayers[id][MENU_PLAYERS_PAGE]);
}
case 9: {
DisplayMenuReason(id, --g_MenuPlayers[id][MENU_PLAYERS_PAGE]);
}
default: {
if (!is_user_connected(g_MenuPlayers[id][MENU_PLAYERS_ID])) {
client_print_color(id, print_team_default, "%L", id, "STB_DISCONNECTED");
} else {
new reason = (g_MenuPlayers[id][MENU_PLAYERS_PAGE] * 8) + key;
if (0 <= reason < g_ReasonsNum) {
copy(g_MenuPlayers[id][MENU_PLAYERS_REASON], MAX_REASON_LENGTH - 1, g_Reasons[reason][REASON_STRING]);
g_MenuPlayers[id][MENU_PLAYERS_TIME] = g_Reasons[reason][REASON_TIME];
g_MenuPlayers[id][MENU_PLAYERS_FLAGS] = g_Reasons[reason][REASON_FLAGS];
if (g_MenuPlayers[id][MENU_PLAYERS_TIME] == -1) {
DisplayMenuTime(id);
} else if (g_MenuPlayers[id][MENU_PLAYERS_FLAGS] == 0) {
DisplayMenuFlags(id);
} else {
DisplayMenuAccept(id);
}
} else {
copy(g_MenuPlayers[id][MENU_PLAYERS_REASON], MAX_REASON_LENGTH - 1, g_DefaultReason);
g_MenuPlayers[id][MENU_PLAYERS_TIME] = -1;
g_MenuPlayers[id][MENU_PLAYERS_FLAGS] = 0;
DisplayMenuTime(id);
}
}
}
}
}
DisplayMenuTime(id, page = 0)
{
if (page < 0) {
DisplayMenuReason(id, 0);
return PLUGIN_HANDLED;
}
new i = min(page * 8, g_TimesNum);
new start = i - (i % 8);
new end = min(start + 8, g_TimesNum);
page = start / 8;
g_MenuPlayers[id][MENU_PLAYERS_PAGE] = page;
new menu[512];
new len = formatex(menu, charsmax(menu), "%s\r%L^t\d%d/%d^n^n", MENU_TAB, id, "STB_REASON_TIME", page + 1, ((g_TimesNum - 1) / 8) + 1);
new keys = MENU_KEY_0;
new item = 0;
new timeDisplay[64];
for (i = start; i < end; i++) {
keys |= (1 << item);
GetTimeString(id, g_Times, timeDisplay, charsmax(timeDisplay), time_minutes);
len += formatex(menu[len], charsmax(menu) - len, "%s\r[%d] \y%s^n", MENU_TAB, ++item, timeDisplay);
}
new tmp[15];
setc(tmp, 8 - (end - start), '^n');
len += copy(menu[len], charsmax(menu) - len, tmp);
if (end < g_TimesNum) {
keys |= MENU_KEY_9;
len += formatex(menu[len], charsmax(menu) - len, "^n%s\r[9] \w%L^n%s\r[0] \w%L", MENU_TAB, id, "MORE", MENU_TAB, id, "BACK");
} else {
len += formatex(menu[len], charsmax(menu) - len, "^n^n%s\r[0] \w%L", MENU_TAB, id, "BACK");
}
show_menu(id, keys, menu, -1, "MENU_STB_TIME");
return PLUGIN_HANDLED;
}
public ActionTime(id, key)
{
switch (key) {
case 8: {
DisplayMenuTime(id, ++g_MenuPlayers[id][MENU_PLAYERS_PAGE]);
}
case 9: {
DisplayMenuTime(id, --g_MenuPlayers[id][MENU_PLAYERS_PAGE]);
}
default: {
if (!is_user_connected(g_MenuPlayers[id][MENU_PLAYERS_ID])) {
client_print_color(id, print_team_default, "%L", id, "STB_DISCONNECTED");
} else {
new time = (g_MenuPlayers[id][MENU_PLAYERS_PAGE] * 8) + key;
if (0 <= time < g_TimesNum) {
g_MenuPlayers[id][MENU_PLAYERS_TIME] = g_Times[time];
} else {
g_MenuPlayers[id][MENU_PLAYERS_TIME] = g_DefaultTime;
}
if (g_MenuPlayers[id][MENU_PLAYERS_FLAGS] == 0) {
g_MenuPlayers[id][MENU_PLAYERS_FLAGS] = g_DefaultFlags;
DisplayMenuFlags(id);
} else {
DisplayMenuAccept(id);
}
}
}
}
}
DisplayMenuFlags(id)
{
new keys = MENU_KEY_0 | MENU_KEY_9;
new item = 0;
new menu[512];
new len = formatex(menu, charsmax(menu), "%s\r%L^n^n", MENU_TAB, id, "STB_FLAGS_TITLE");
new flags = g_MenuPlayers[id][MENU_PLAYERS_FLAGS];
keys |= (1 << item);
len += formatex(menu[len], charsmax(menu) - len, "%s\r[%d] \d%L: \y%L^n",
MENU_TAB, ++item, id, "STB_BLOCK_ATTACK", id, (flags & BLOCK_ATTACK ? "STB_ENABLE" : "STB_DISABLE")
);
keys |= (1 << item);
len += formatex(menu[len], charsmax(menu) - len, "%s\r[%d] \d%L: \y%L^n",
MENU_TAB, ++item, id, "STB_BLOCK_TIMEOUT", id, (flags & BLOCK_TIMEOUT ? "STB_ENABLE" : "STB_DISABLE")
);
keys |= (1 << item);
len += formatex(menu[len], charsmax(menu) - len, "%s\r[%d] \d%L: \y%L^n",
MENU_TAB, ++item, id, "STB_BLOCK_MOVE", id, (flags & BLOCK_MOVE ? "STB_ENABLE" : "STB_DISABLE")
);
keys |= (1 << item);
len += formatex(menu[len], charsmax(menu) - len, "%s\r[%d] \d%L: \y%L^n",
MENU_TAB, ++item, id, "STB_BLOCK_CHAT", id, (flags & BLOCK_CHAT ? "STB_ENABLE" : "STB_DISABLE")
);
keys |= (1 << item);
len += formatex(menu[len], charsmax(menu) - len, "%s\r[%d] \d%L: \y%L^n",
MENU_TAB, ++item, id, "STB_BLOCK_MICRO", id, (flags & BLOCK_MICRO ? "STB_ENABLE" : "STB_DISABLE")
);
keys |= (1 << item);
len += formatex(menu[len], charsmax(menu) - len, "%s\r[%d] \d%L: \y%L^n",
MENU_TAB, ++item, id, "STB_BLOCK_BAN", id, (flags & BLOCK_BAN ? "STB_ENABLE" : "STB_DISABLE")
);
len += add(menu[len], charsmax(menu) - len, "^n^n");
len += formatex(menu[len], charsmax(menu) - len, "%s\r[9] \w%L^n", MENU_TAB, id, "STB_START");
len += formatex(menu[len], charsmax(menu) - len, "%s\r[0] \w%L^n", MENU_TAB, id, "BACK");
show_menu(id, keys, menu, -1, "MENU_STB_FLAGS");
}
public ActionFlags(id, key)
{
switch (key) {
case 0: {
ToggleFlag(id, BLOCK_ATTACK);
DisplayMenuFlags(id);
}
case 1: {
ToggleFlag(id, BLOCK_TIMEOUT);
DisplayMenuFlags(id);
}
case 2: {
ToggleFlag(id, BLOCK_MOVE);
DisplayMenuFlags(id);
}
case 3: {
ToggleFlag(id, BLOCK_CHAT);
DisplayMenuFlags(id);
}
case 4: {
ToggleFlag(id, BLOCK_MICRO);
DisplayMenuFlags(id);
}
case 5: {
ToggleFlag(id, BLOCK_BAN);
DisplayMenuFlags(id);
}
case 8: {
DisplayMenuAccept(id);
}
case 9: {
DisplayMenuTime(id, 0);
}
}
}
DisplayMenuAccept(id)
{
new menu[512];
new timeDisplay[64];
new player = g_MenuPlayers[id][MENU_PLAYERS_ID];
new len = formatex(menu, charsmax(menu), "%s\r%L^n^n", MENU_TAB, id, "STB_ACCEPT_TITLE");
len += formatex(menu[len], charsmax(menu) - len, "%s\d%L^n", MENU_TAB, id, "STB_ACCEPT_TEXT");
if (!CheckBit(g_IsBlocked, player)) {
len += formatex(menu[len], charsmax(menu) - len, "%s\d%L: \y%s^n", MENU_TAB, id, "STB_PLAYER", g_PlayersData[player][PLAYER_NAME]);
GetTimeString(id, g_MenuPlayers[id][MENU_PLAYERS_TIME], timeDisplay, charsmax(timeDisplay), time_minutes);
len += formatex(menu[len], charsmax(menu) - len, "%s\d%L: \y%s. \d%L: \y%s", MENU_TAB, id, "STB_REASON", g_MenuPlayers[id][MENU_PLAYERS_REASON], id, "STB_TIME", timeDisplay);
} else {
len += formatex(menu[len], charsmax(menu) - len, "%s\d%L: \y%s^n", MENU_TAB, id, "STB_FORGIVE", g_PlayersData[player][PLAYER_NAME]);
GetTimeString(id, g_PlayersData[player][PLAYER_BLOCK_EXPIRED] - get_systime(), timeDisplay, charsmax(timeDisplay), time_seconds);
len += formatex(menu[len], charsmax(menu) - len, "%s\d%L: \y%s", MENU_TAB, id, "STB_LEFT", timeDisplay);
}
len += formatex(menu[len], charsmax(menu) - len, "^n^n%s\r1. \r%L^n%s\r2. \w%L", MENU_TAB, id, "YES", MENU_TAB, id, "NO");
show_menu(id, MENU_KEY_1 | MENU_KEY_2, menu, -1, "MENU_STB_ACCEPT");
}
public ActionAccept(id, key)
{
if (key == 0) {
new player = g_MenuPlayers[id][MENU_PLAYERS_ID];
if (!is_user_connected(player)) {
client_print_color(id, print_team_default, "%L", id, "STB_DISCONNECTED");
} else if (!CheckBit(g_IsBlocked, player)) {
PunishPlayer(id, player, g_MenuPlayers[id][MENU_PLAYERS_REASON], g_MenuPlayers[id][MENU_PLAYERS_TIME], g_MenuPlayers[id][MENU_PLAYERS_FLAGS]);
} else {
ForgivePlayer(id, player, false);
}
} else {
RenderMenuPlayers(id, g_MenuPlayers[id][MENU_PLAYERS_PAGE]);
}
}
PunishPlayer(const admin, const player, const reason[], time, flags)
{
ad_set_client(player, AimCheck, 0);
ad_set_client(player, NoSpreadCheck, 0);
SetBit(g_IsBlocked, player);
if (flags & BLOCK_ATTACK) {
SetBit(g_IsAttackBlocked, player);
}
if (flags & BLOCK_TIMEOUT) {
SetBit(g_IsAttackTimeout, player);
}
if (flags & BLOCK_MOVE) {
SetBit(g_IsMoveBlocked, player);
}
if (flags & BLOCK_CHAT) {
SetBit(g_IsChatBlocked, player);
}
if (flags & BLOCK_MICRO) {
SetBit(g_IsMicroBlocked, player);
if (has_vtc()) {
VTC_MuteClient(player);
}
}
new now = get_systime();
g_PlayersData[player][PLAYER_BLOCK_EXPIRED] = now + (time * 60);
if (PunishFowrward(admin, player, time, flags, reason)) {
PunishNotify(admin, player, time, reason);
PunishLog(admin, player, time, flags, reason);
if (!g_Enabled) {
SetHooksEnable(true);
}
if (g_BanSystem != NONE && flags & BLOCK_BAN) {
InsertBan(admin, player, reason, time);
} else if (g_BlockList != INVALID_HANDLE) {
new data[256];
formatex(data, charsmax(data), "%d %d %d ^"%s^"", now, time, flags, reason);
nvault_set(g_BlockList, g_PlayersData[player][PLAYER_AUTHID], data);
}
} else {
//
}
}
ForgivePlayer(const admin, const player, bool:expired = false)
{
if (CheckBit(g_IsMicroBlocked, player)) {
if (has_vtc()) {
VTC_UnmuteClient(player);
}
}
ClearBit(g_IsBlocked, player);
ClearBit(g_IsAttackBlocked, player);
ClearBit(g_IsAttackTimeout, player);
ClearBit(g_IsMoveBlocked, player);
ClearBit(g_IsChatBlocked, player);
ClearBit(g_IsMicroBlocked, player);
if (ForgiveFowrward(admin, player, expired)) {
ForgiveNotify(admin, player, expired);
ForgiveLog(admin, player, expired);
if (g_Enabled && NumberOfSetBits(g_IsBlocked) == 0) {
SetHooksEnable(false);
}
if (g_BanSystem != NONE && g_PlayersData[player][PLAYER_BAN_ID] != 0) {
DeleteBan(g_PlayersData[player][PLAYER_BAN_ID]);
} else if (g_BlockList != INVALID_HANDLE) {
nvault_remove(g_BlockList, g_PlayersData[player][PLAYER_AUTHID]);
}
} else {
//
}
}
CheckPlayer(id)
{
if (g_BlockList == INVALID_HANDLE) {
CheckFowrward(false, id);
return 0;
}
new data[256], timestamp;
if (!nvault_lookup(g_BlockList, g_PlayersData[id][PLAYER_AUTHID], data, charsmax(data), timestamp)) {
CheckFowrward(false, id);
return 0;
}
new createdStr[32], timeStr[32], flagsStr[32], reason[64];
#if AMXX_VERSION_NUM < 183
new pos = strbreak(data, createdStr, charsmax(createdStr), data, charsmax(data));
if (pos != -1) {
pos = strbreak(data, timeStr, charsmax(timeStr), data, charsmax(data));
}
if (pos != -1) {
pos = strbreak(data, flagsStr, charsmax(flagsStr), data, charsmax(data));
}
if (pos != -1) {
copy(reason, charsmax(reason), data);
}
#else
new pos;
pos = argparse(data, pos, createdStr, charsmax(createdStr));
if (pos != -1) {
pos = argparse(data, pos, timeStr, charsmax(timeStr));
}
if (pos != -1) {
pos = argparse(data, pos, flagsStr, charsmax(flagsStr));
}
if (pos != -1) {
copy(reason, charsmax(reason), data[pos]);
}
#endif
trim(createdStr);
trim(timeStr);
trim(flagsStr);
trim(reason);
remove_quotes(createdStr);
remove_quotes(timeStr);
remove_quotes(flagsStr);
remove_quotes(reason);
new created = str_to_num(createdStr);
new time = str_to_num(timeStr);
new expired = time > 0 ? created + (time * 60) : 0;
if (expired == 0 || expired > get_systime()) {
ad_set_client(id, AimCheck, 0);
ad_set_client(id, NoSpreadCheck, 0);
new flags = str_to_num(flagsStr);
SetBit(g_IsBlocked, id);
if (flags & BLOCK_ATTACK) {
SetBit(g_IsAttackBlocked, id);
}
if (flags & BLOCK_MOVE) {
SetBit(g_IsMoveBlocked, id);
}
if (flags & BLOCK_TIMEOUT) {
SetBit(g_IsAttackTimeout, id);
}
if (flags & BLOCK_CHAT) {
SetBit(g_IsChatBlocked, id);
}
if (flags & BLOCK_MICRO) {
SetBit(g_IsMicroBlocked, id);
if (has_vtc()) {
VTC_MuteClient(id);
}
}
g_PlayersData[id][PLAYER_BLOCK_EXPIRED] = expired;
new left = time > 0 ? expired - get_systime() : 0;
CheckNotify(id, time, left, reason);
CheckLog(id, created, time, left, flags, reason);
CheckFowrward(true, id);
if (!g_Enabled) {
SetHooksEnable(true);
}
} else {
nvault_remove(g_BlockList, g_PlayersData[id][PLAYER_AUTHID]);
CheckFowrward(false, id);
}
return 1;
}
SetHooksEnable(bool:enable)
{
if (enable) {
EnableHookChain(g_HookTakeDamage);
EnableHookChain(g_HookPlayerKilled);
#if defined OBSERVER_HUD_POSITION
EnableHookChain(g_HookObserver);
EnableHookChain(g_HookPlayerSpawn);
#endif
g_MsgSayTextEvent = register_message(g_MsgSayText, "MessageSayText");
remove_task(TASK_CHECK_ID);
set_task(60.0, "TaskCheckExpired", TASK_CHECK_ID, .flags = "b");
} else {
unregister_message(g_MsgSayText, g_MsgSayTextEvent);
DisableHookChain(g_HookTakeDamage);
DisableHookChain(g_HookPlayerKilled);
#if defined OBSERVER_HUD_POSITION
DisableHookChain(g_HookObserver);
DisableHookChain(g_HookPlayerSpawn);
#endif
remove_task(TASK_CHECK_ID);
}
g_Enabled = enable;
}
KickPlayers()
{
if (get_playersnum() > (MaxClients - g_CFGReservedSlots)) {
new players[MAX_PLAYERS], num;
get_players(players, num, "ch");
new i = 0;
do {
if (CheckBit(g_IsBlocked, players)) {
server_cmd("kick #%d", get_user_userid(players));
break;
}
} while (++i < num);
}
}
PunishLog(const admin, const player, const time, const flags, const reason[])
{
new timeDisplay[64], flagsDisplay[32];
GetTimeString(LANG_SERVER, time, timeDisplay, charsmax(timeDisplay), time_minutes);
get_flags(flags, flagsDisplay, charsmax(flagsDisplay));
if (admin == 0) {
LogAction("%L", LANG_SERVER, "STB_PUNISH_LOG_SERVER",
g_PlayersData[player][PLAYER_NAME], g_PlayersData[player][PLAYER_AUTHID], g_PlayersData[player][PLAYER_IP],
timeDisplay, reason, flagsDisplay
);
} else {
LogAction("%L", LANG_SERVER, "STB_PUNISH_LOG",
g_PlayersData[admin][PLAYER_NAME], g_PlayersData[admin][PLAYER_AUTHID], g_PlayersData[admin][PLAYER_IP],
g_PlayersData[player][PLAYER_NAME], g_PlayersData[player][PLAYER_AUTHID], g_PlayersData[player][PLAYER_IP],
timeDisplay, reason, flagsDisplay
);
}
}
ForgiveLog(const admin, const player, const bool:expired)
{
if (expired) {
LogAction("%L", LANG_SERVER, "STB_FORGIVE_LOG_EXPIRED",
g_PlayersData[player][PLAYER_NAME], g_PlayersData[player][PLAYER_AUTHID], g_PlayersData[player][PLAYER_IP]
);
} else if (admin == 0) {
LogAction("%L", LANG_SERVER, "STB_FORGIVE_LOG_SERVER",
g_PlayersData[player][PLAYER_NAME], g_PlayersData[player][PLAYER_AUTHID], g_PlayersData[player][PLAYER_IP]
);
} else {
LogAction("%L", LANG_SERVER, "STB_FORGIVE_LOG",
g_PlayersData[admin][PLAYER_NAME], g_PlayersData[admin][PLAYER_AUTHID], g_PlayersData[admin][PLAYER_IP],
g_PlayersData[player][PLAYER_NAME], g_PlayersData[player][PLAYER_AUTHID], g_PlayersData[player][PLAYER_IP]
);
}
}
CheckLog(const player, const created, const time, const left, const flags, const reason[])
{
new timeDisplay[64], leftDisplay[64], dateDisplay[32], flagsDisplay[32];
GetTimeString(LANG_SERVER, time, timeDisplay, charsmax(timeDisplay), time_minutes);
GetTimeString(LANG_SERVER, left, leftDisplay, charsmax(leftDisplay), time_seconds);
format_time(dateDisplay, charsmax(dateDisplay), "%d.%m.%Y - %H:%M:%S", created);
get_flags(flags, flagsDisplay, charsmax(flagsDisplay));
LogAction("%L", LANG_SERVER, "STB_CHECK_LOG",
g_PlayersData[player][PLAYER_NAME], g_PlayersData[player][PLAYER_AUTHID], g_PlayersData[player][PLAYER_IP], timeDisplay, dateDisplay, reason, leftDisplay, flagsDisplay
);
}
PunishNotify(const admin, const player, const time, const reason[])
{
new players[MAX_PLAYERS], num;
GetPlayers(player, players, num);
new timeDisplay[64];
for (new i = 0; i < num; i++) {
GetTimeString(players, time, timeDisplay, charsmax(timeDisplay), time_minutes);
if (admin == 0) {
client_print_color(players, player, "%L", players, "STB_PUNISH_NOTIFY_SERVER", g_PlayersData[player][PLAYER_NAME], timeDisplay, reason);
} else {
client_print_color(players, player, "%L", players, "STB_PUNISH_NOTIFY", g_PlayersData[admin][PLAYER_NAME], g_PlayersData[player][PLAYER_NAME], timeDisplay, reason);
}
}
}
ForgiveNotify(const admin, const player, const bool:expired)
{
new players[MAX_PLAYERS], num;
#if defined FORGIVE_DISPLAY_ALL
get_players(players, num, "ch");
#else
GetPlayers(player, players, num);
#endif
for (new i = 0; i < num; i++) {
if (expired) {
client_print_color(players, player, "%L", players, "STB_FORGIVE_NOTIFY_EXPIRED", g_PlayersData[player][PLAYER_NAME]);
} else if (admin == 0) {
client_print_color(players, player, "%L", players, "STB_FORGIVE_NOTIFY_SERVER", g_PlayersData[player][PLAYER_NAME]);
} else {
client_print_color(players, player, "%L", players, "STB_FORGIVE_NOTIFY", g_PlayersData[admin][PLAYER_NAME], g_PlayersData[player][PLAYER_NAME]);
}
}
}
CheckNotify(const player, const time, const left, const reason[])
{
new players[MAX_PLAYERS], num;
GetPlayers(player, players, num);
new timeDisplay[64], leftDisplay[64];
for (new i = 0; i < num; i++) {
GetTimeString(players, time, timeDisplay, charsmax(timeDisplay), time_minutes);
GetTimeString(players, left, leftDisplay, charsmax(leftDisplay), time_seconds);
client_print_color(players, player, "%L", players, "STB_CHECK_NOTIFY", g_PlayersData[player][PLAYER_NAME], timeDisplay, reason, leftDisplay);
}
}
bool:PunishFowrward(const admin, const player, const time, const flags, const reason[])
{
if (g_FwdPunished == INVALID_HANDLE) {
return false;
}
ExecuteForward(g_FwdPunished, g_FwdReturn, admin, player, time, flags, reason);
return g_FwdReturn == PLUGIN_CONTINUE ? true : false;
}
bool:ForgiveFowrward(const admin, const player, const bool:expired)
{
if (g_FwdForgived == INVALID_HANDLE) {
return false;
}
ExecuteForward(g_FwdForgived, g_FwdReturn, admin, player, expired ? 1 : 0);
return g_FwdReturn == PLUGIN_CONTINUE ? true : false;
}
bool:CheckFowrward(bool:punished, const player, const created = 0, const time = 0, const left = 0, const flags = 0, const reason[] = "")
{
if (g_FwdChecked == INVALID_HANDLE) {
return false;
}
ExecuteForward(g_FwdChecked, g_FwdReturn, punished ? 1 : 0, player, created, time, left, flags, reason);
return g_FwdReturn == PLUGIN_CONTINUE ? true : false;
}
stock GetPlayers(const player, players[MAX_PLAYERS], &num = 0)
{
num = 0;
for (new id = 1; id <= MaxClients; id++) {
if (is_user_connected(id) && !is_user_bot(id) && !is_user_hltv(id)) {
if (!g_CFGNotifyPunished && CheckBit(g_IsBlocked, id)) {
continue;
}
if (id == player) {
if (g_CFGNotifyPlayer) {
players[num++] = id;
}
} else if (get_user_flags(id) & ADMIN_BAN) {
if (g_CFGNotifyAdmins) {
players[num++] = id;
}
} else if (g_CFGNotifyPlayers) {
players[num++] = id;
}
}
}
}
InsertBan(const admin, const player, const reason[], time)
{
new adminNameEx[MAX_NAME_LENGTH*2], adminAuthidEx[44], adminIpEx[32];
new playerNameEx[MAX_NAME_LENGTH*2], playerAuthidEx[44], playerIpEx[32];
new reasonEx[MAX_REASON_LENGTH*2];
mysql_escape_string(g_PlayersData[admin][PLAYER_NAME], adminNameEx, charsmax(adminNameEx));
mysql_escape_string(g_PlayersData[admin][PLAYER_AUTHID], adminAuthidEx, charsmax(adminAuthidEx));
mysql_escape_string(g_PlayersData[admin][PLAYER_IP], adminIpEx, charsmax(adminIpEx));
mysql_escape_string(g_PlayersData[player][PLAYER_NAME], playerNameEx, charsmax(playerNameEx));
mysql_escape_string(g_PlayersData[player][PLAYER_AUTHID], playerAuthidEx, charsmax(playerAuthidEx));
mysql_escape_string(g_PlayersData[player][PLAYER_IP], playerIpEx, charsmax(playerIpEx));
mysql_escape_string(reason, reasonEx, charsmax(reasonEx));
new pquery[1024], len;
len = formatex(pquery, charsmax(pquery), "SET NAMES UTF8; INSERT INTO %s (player_id, player_ip, player_nick, admin_ip, admin_id, admin_nick, ban_type, ban_reason, ban_created, ban_length, server_name, server_ip, `expired`) ",
g_TableName
);
new bantype = get_ban_type(g_PlayersData[admin][PLAYER_AUTHID], g_PlayersData[admin][PLAYER_IP]);
len += formatex(pquery[len], charsmax(pquery) - len, "VALUES('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', UNIX_TIMESTAMP(NOW()), %d, '%s', '%s:%s', 0);",
playerAuthidEx, playerIpEx, playerNameEx, adminIpEx, adminAuthidEx, adminNameEx, (bantype ? "SI" : "S"), reasonEx, time, g_ServerName, g_ServerIp, g_ServerPort
);
new data[1];
data[0] = player;
SQL_ThreadQuery(g_DBTuple, "InsertBanPost", pquery, data, 1);
}
public InsertBanPost(failstate, Handle:query, const error[], errornum, const data[], size, Float:queuetime)
{
if (failstate) {
SQL_Error(query, error, errornum, failstate);
SQL_FreeHandle(query);
} else {
SQL_FreeHandle(query);
new player = data[0];
if (is_user_connected(player)) {
new pquery[512];
formatex(pquery, charsmax(pquery), "SELECT bid FROM %s WHERE player_id='%s' AND server_ip='%s:%s' ORDER BY ban_created DESC LIMIT 1", g_TableName, g_PlayersData[player][PLAYER_AUTHID], g_ServerIp, g_ServerPort);
SQL_ThreadQuery(g_DBTuple, "GetBanPost", pquery, data, 1);
}
}
}
public GetBanPost(failstate, Handle:query, const error[], errornum, const data[], size, Float:queuetime)
{
if (failstate) {
SQL_Error(query, error, errornum, failstate);
SQL_FreeHandle(query);
} else if(SQL_NumResults(query) > 0) {
new player = data[0];
g_PlayersData[player][PLAYER_BAN_ID] = SQL_ReadResult(query, 0);
}
}
DeleteBan(banid)
{
new pquery[512];
formatex(pquery, charsmax(pquery), "UPDATE %s SET expired=1 WHERE bid=%d LIMIT 1", g_TableName, banid);
SQL_ThreadQuery(g_DBTuple, "DeleteBanPost", pquery);
}
public DeleteBanPost(failstate, Handle:query, const error[], errornum, const data[], size, Float:queuetime)
{
if (failstate) {
SQL_Error(query, error, errornum, failstate);
}
SQL_FreeHandle(query);
}
LogActionInit()
{
get_localinfo("amxx_logs", g_LogFile, charsmax(g_LogFile));
add(g_LogFile, charsmax(g_LogFile), "/stb");
if (!dir_exists(g_LogFile)) {
mkdir(g_LogFile);
}
new logTime[16];
get_time("/L%d%m%Y.log", logTime, charsmax(logTime));
add(g_LogFile, charsmax(g_LogFile), logTime);
new logMap[32];
get_mapname(logMap, charsmax(logMap));
log_to_file(g_LogFile, "Start of log session (map %s)", logMap);
}
LogAction(const fmt[], any:...)
{
new msg[256];
vformat(msg, charsmax(msg), fmt, 2);
if (g_CFGLogToFile) {
if (!g_LogFile[0]) {
LogActionInit();
}
log_to_file(g_LogFile, "[%s] %s", LOG_TAG, msg);
} else {
log_amx("[%s] %s", LOG_TAG, msg);
}
}
SQL_Error(Handle:query, const error[], errornum, failstate)
{
if (failstate == TQUERY_CONNECT_FAILED) {
LogError("Connection failed!");
LogError("Message: %s (%d)", error, errornum);
} else if (failstate == TQUERY_QUERY_FAILED) {
new qstring[1024];
SQL_GetQueryString(query, qstring, 1023);
LogError("Query failed!");
LogError("Message: %s (%d)", error, errornum);
LogError("Query statement: %s", qstring);
}
}
LogError(const fmt[], any:...)
{
static logFile[128];
if (!logFile[0]) {
new logTime[22];
get_localinfo("amxx_logs", logFile, charsmax(logFile));
get_time("/error_%d%m%Y.log", logTime, charsmax(logTime));
add(logFile, charsmax(logFile), logTime);
}
new msg[256];
vformat(msg, charsmax(msg), fmt, 2);
log_to_file(logFile, "[%s] %s", LOG_TAG, msg);
}
bool:parseConfig()
{
new filename[128];
get_localinfo("amxx_configsdir", filename, charsmax(filename));
add(filename, charsmax(filename), "/stop_the_bastards.ini");
new file = fopen(filename, "rt");
if (!file) {
abort(AMX_ERR_NONE, "Can not open config file '%s'", filename);
return false;
}
g_ReasonsNum = 0;
new line[256], section[64], key[128], value[128], flags[32];
new semicolonPos, sectionNum;
while (!feof(file)) {
fgets(file, line, charsmax(line));
if ((semicolonPos = contain(line, ";")) != -1) {
line[semicolonPos] = EOS;
}
trim(line);
if (!line[0] || line[0] == ';') {
continue;
}
if (line[0] == '[') {
copyc(section, charsmax(section), line[1], ']');
trim(section);
if (!strcmp(section, "CONFIG")) {
sectionNum = 1;
} else if (!strcmp(section, "REASONS")) {
sectionNum = 2;
}
} else {
switch (sectionNum) {
case 1: {
strtok(line, key, charsmax(key), value, charsmax(value), '=', 0);
trim(key);
trim(value);
remove_quotes(key);
remove_quotes(value);
SetCfgValue(key, value);
}
case 2: {
if (g_ReasonsNum < MAX_REASONS) {
arrayset(key, 0, sizeof key);
arrayset(value, 0, sizeof value);
arrayset(flags, 0, sizeof flags);
parse(line, key, charsmax(key), value, charsmax(value), flags, charsmax(flags));
trim(key);
trim(value);
trim(flags);
remove_quotes(key);
remove_quotes(value);
remove_quotes(flags);
arrayset(g_Reasons[g_ReasonsNum][REASON_STRING], 0, MAX_REASON_LENGTH);
copy(g_Reasons[g_ReasonsNum][REASON_STRING], MAX_REASON_LENGTH - 1, key);
if (value[0]) {
if (isTime(value)) {
g_Reasons[g_ReasonsNum][REASON_TIME] = parseTime(value);
g_Reasons[g_ReasonsNum][REASON_FLAGS] = read_flags(flags);
} else {
g_Reasons[g_ReasonsNum][REASON_TIME] = -1;
g_Reasons[g_ReasonsNum][REASON_FLAGS] = read_flags(value);
}
} else {
g_Reasons[g_ReasonsNum][REASON_TIME] = -1;
g_Reasons[g_ReasonsNum][REASON_FLAGS] = 0;
}
g_ReasonsNum++;
}
}
}
}
}
fclose(file);
return true;
}
bool:SetCfgValue(const key[], const value[])
{
if (!strcmp(key, "log_to_file")) {
g_CFGLogToFile = parseBool(value);
} else if (!strcmp(key, "reserved_slots")) {
g_CFGReservedSlots = clamp(str_to_num(value), 0, MAX_PLAYERS);
return true;
} else if (!strcmp(key, "block_damage")) {
g_CFGBlockDamage = clamp(str_to_num(value), 0, 100);
return true;
} else if (!strcmp(key, "block_timeout")) {
g_CFGBlockTimeout = clamp(str_to_num(value), 0, 100);
return true;
} else if (!strcmp(key, "block_move")) {
g_CFGBlockMove = clamp(str_to_num(value), 0, 100);
return true;
} else if (!strcmp(key, "timeout_min")) {
g_CFGTimeoutMin = floatclamp(floatstr(value), 0.0, 999.0);
return true;
} else if (!strcmp(key, "timeout_max")) {
g_CFGTimeoutMax = floatclamp(floatstr(value), 0.1, 999.0);
return true;
} else if (!strcmp(key, "default_reason")) {
copy(g_DefaultReason, charsmax(g_DefaultReason), value);
return true;
} else if (!strcmp(key, "default_time")) {
g_DefaultTime = abs(str_to_num(value));
return true;
} else if (!strcmp(key, "default_type")) {
g_DefaultFlags = read_flags(value);
return true;
} else if (!strcmp(key, "super_flag")) {
g_CFGSuperFlag = read_flags(value);
return true;
} else if (!strcmp(key, "notify_admins")) {
g_CFGNotifyAdmins = parseBool(value);
return true;
} else if (!strcmp(key, "notify_players")) {
g_CFGNotifyPlayers = parseBool(value);
return true;
} else if (!strcmp(key, "notify_punished")) {
g_CFGNotifyPunished = parseBool(value);
return true;
} else if (!strcmp(key, "notify_player")) {
g_CFGNotifyPlayer = parseBool(value);
return true;
} else if (!strcmp(key, "admin_view_chat")) {
g_CFGAdminViewChat = parseBool(value);
return true;
} else if (!strcmp(key, "ban_times")) {
arrayset(g_Times, 0, MAX_TIMES);
g_TimesNum = 0;
parseBanTimes(value);
return true;
}
return false;
}
bool:GetCfgValue(const key[], value[], len)
{
if (!strcmp(key, "log_to_file")) {
copy(value, len, g_CFGLogToFile ? "true" : "false");
return true;
} else if (!strcmp(key, "reserved_slots")) {
num_to_str(g_CFGReservedSlots, value, len);
return true;
} else if (!strcmp(key, "block_damage")) {
num_to_str(g_CFGBlockDamage, value, len);
return true;
} else if (!strcmp(key, "block_timeout")) {
num_to_str(g_CFGBlockTimeout, value, len);
return true;
} else if (!strcmp(key, "block_move")) {
num_to_str(g_CFGBlockMove, value, len);
return true;
} else if (!strcmp(key, "timeout_min")) {
formatex(value, len, "%0.2f", g_CFGTimeoutMin);
return true;
} else if (!strcmp(key, "timeout_max")) {
formatex(value, len, "%0.2f", g_CFGTimeoutMax);
return true;
} else if (!strcmp(key, "default_reason")) {
copy(value, len, g_DefaultReason);
return true;
} else if (!strcmp(key, "default_time")) {
num_to_str(g_DefaultTime, value, len);
return true;
} else if (!strcmp(key, "default_type")) {
get_flags(g_DefaultFlags, value, len);
return true;
} else if (!strcmp(key, "super_flag")) {
get_flags(g_CFGSuperFlag, value, len);
return true;
} else if (!strcmp(key, "notify_admins")) {
copy(value, len, g_CFGNotifyAdmins ? "true" : "false");
return true;
} else if (!strcmp(key, "notify_players")) {
copy(value, len, g_CFGNotifyPlayers ? "true" : "false");
return true;
} else if (!strcmp(key, "notify_punished")) {
copy(value, len, g_CFGNotifyPunished ? "true" : "false");
return true;
} else if (!strcmp(key, "notify_player")) {
copy(value, len, g_CFGNotifyPlayer ? "true" : "false");
return true;
} else if (!strcmp(key, "admin_view_chat")) {
copy(value, len, g_CFGAdminViewChat ? "true" : "false");
return true;
}
return false;
}
parseTime(const value[])
{
new i, t, k;
while (value != EOS) {
switch (value) {
case '0'..'9': {
t = (t * 10) + (value - '0');
}
case 'h': {
k += t * 60;
t = 0;
}
case 'd': {
k += t * 1440;
t = 0;
}
case 'w': {
k += t * 10080;
t = 0;
}
case 'm': {
k += t * 43200;
t = 0;
}
case 'y': {
k += t * 518400;
t = 0;
}
}
i++;
}
return k + t;
}
parseBanTimes(const value[])
{
new i, t, k;
while (value != EOS) {
switch (value) {
case '0'..'9': {
t = (t * 10) + (value - '0');
}
case 'h': {
k += t * 60;
t = 0;
}
case 'd': {
k += t * 1440;
t = 0;
}
case 'w': {
k += t * 10080;
t = 0;
}
case 'm': {
k += t * 43200;
t = 0;
}
case 'y': {
k += t * 518400;
t = 0;
}
case ' ': {
if (g_TimesNum < MAX_TIMES) {
g_Times[g_TimesNum++] = k + t;
}
t = 0;
k = 0;
}
}
i++;
}
if (i > 0 && g_TimesNum < MAX_TIMES) {
g_Times[g_TimesNum++] = k + t;
}
}
stock bool:isTime(const value[])
{
new i = 0;
do {
if ('0' <= value <= '9') {
return true;
}
} while (value[++i] != EOS);
return false;
}
stock bool:parseBool(const value[])
{
return !strcmp(value, "true") ? true : false;
}
stock locate_player(const identifier[])
{
new player = 0;
if (identifier[0]=='#' && identifier[1]) {
player = find_player("k", str_to_num(identifier[1]));
}
if (!player) {
player = find_player("c", identifier);
}
if (!player) {
player = find_player("bl", identifier);
}
if (!player) {
player = find_player("d", identifier);
}
return player;
}
stock NumberOfSetBits(i)
{
i = i - ((i >> 1) & 0x55555555);
i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
}
stock mysql_escape_string(const str[], dest[], len)
{
copy(dest, len, str);
replace_all(dest, len, "\\", "\\\\");
replace_all(dest, len, "\0", "\\0");
replace_all(dest, len, "\n", "\\n");
replace_all(dest, len, "\r", "\\r");
replace_all(dest, len, "\x1a", "\Z");
replace_all(dest, len, "'", "\'");
replace_all(dest, len, "^"", "\^"");
}
stock bool:isTextChannel(const str[])
{
static i;
for (i = 0; i < sizeof(g_TextChannels); i++){
if(!strcmp(str, g_TextChannels)) {
return true;
}
}
return false;
}
stock SendDamageMessage(id, attacker, damage, damagebits)
{
static msgDamage;
if (!msgDamage) {
msgDamage = get_user_msgid("Damage");
}
new origin[3];
get_user_origin(attacker, origin);
emessage_begin(MSG_ONE, msgDamage, _, id);
ewrite_byte(damage);
ewrite_byte(damage);
ewrite_long(damagebits);
ewrite_coord(origin[0]);
ewrite_coord(origin[1]);
ewrite_coord(origin[2]);
emessage_end();
}
stock get_ban_type(const steamid[], const ip[])
{
if (g_BanType == 1) {
return 1;
} else if(g_BanType == 2) {
return 0;
} else if(strcmp(ip, "127.0.0.1")) {
for (new i = 0, n = sizeof g_BanIpSteamId; i < n; i++) {
if (!strcmp(g_BanIpSteamId, steamid)) {
return 1;
}
}
}
return 0;
}
stock GetTimeString(id, time, output[], outputLen, units = time_seconds)
{
new secondCnt = time * units;
if (secondCnt > 0) {
new timeCnt, len = 0;
timeCnt = secondCnt / 604800;
secondCnt -= (timeCnt * 604800);
if (timeCnt > 0) {
len += formatex(output[len], outputLen - len, "%i %L", timeCnt, id, "STB_WEEKS");
}
timeCnt = secondCnt / 86400;
secondCnt -= (timeCnt * 86400);
if (timeCnt > 0) {
len += formatex(output[len], outputLen - len, "%i %L", timeCnt, id, "STB_DAYS");
}
timeCnt = secondCnt / 3600;
secondCnt -= (timeCnt * 3600);
if (timeCnt > 0) {
len += formatex(output[len], outputLen - len, "%i %L", timeCnt, id, "STB_HOURS");
}
timeCnt = secondCnt / 60;
secondCnt -= (timeCnt * 60);
if (timeCnt > 0) {
len += formatex(output[len], outputLen - len, "%i %L", timeCnt, id, "STB_MINUTES");
}
if (secondCnt > 0) {
len += formatex(output[len], outputLen - len, "%i %L", secondCnt, id, "STB_SECONDS");
}
} else if (secondCnt < 0) {
formatex(output, outputLen, "%L", id, "STB_EXPIRED");
} else {
formatex(output, outputLen, "%L", id, "STB_PERMANENTLY");
}
}
stock ctz(x) {
if (x == 0) {
return 0;
}
new n = 0;
if ((x & 0x0000FFFF) == 0) {
n += 16;
x = x >> 16;
}
if ((x & 0x000000FF) == 0) {
n = n + 8;
x = x >> 8;
}
if ((x & 0x0000000F) == 0) {
n += 4;
x = x >> 4;
}
if ((x & 0x00000003) == 0) {
n += 2;
x = x >> 2;
}
if ((x & 0x00000001) == 0) {
n += 1;
}
return n == 0 ? 32 : n;
}
public native_punish_player(plugin_id, param_nums)
{
if (param_nums < 2) {
return 0;
}
new admin = get_param(1);
CHECK_PLAYER(admin)
new player = get_param(2);
CHECK_PLAYER(player)
new time = (param_nums >= 3) ? get_param(2) : g_DefaultTime;
new flags = (param_nums >= 4) ? get_param(4) : g_DefaultFlags;
new reason[MAX_REASON_LENGTH];
if (param_nums >= 5) {
get_array(5, reason, charsmax(reason));
} else {
copy(reason, charsmax(reason), g_DefaultReason);
}
PunishPlayer(admin, player, reason, time, flags);
return 1;
}
public native_forgive_player(plugin_id, param_nums)
{
if (param_nums != 2) {
return 0;
}
new admin = get_param(1);
CHECK_PLAYER(admin)
new player = get_param(2);
CHECK_PLAYER(player)
ForgivePlayer(admin, player);
return 1;
}