Stop the Bastards не наказывает

Статус
В этой теме нельзя размещать новые ответы.
Сообщения
35
Реакции
0
Помог
1 раз(а)
Дезинформация по билду
Ошибка
L 06/13/2018 - 20:34:50: Expected 0 parameters, got 5
L 06/13/2018 - 20:34:50: [AMXX] Displaying debug trace (plugin "stop_the_bastardss.amxx", version "1.6.6")
L 06/13/2018 - 20:34:50: [AMXX] Run time error 10: native error (native "ExecuteForward")
L 06/13/2018 - 20:34:50: [AMXX] [0] stop_the_bastards.sma::PunishFowrward (line 1669)
L 06/13/2018 - 20:34:50: [AMXX] [1] stop_the_bastards.sma::PunishPlayer (line 1369)
L 06/13/2018 - 20:34:50: [AMXX] [2] stop_the_bastards.sma::cmdPunish (line
ОС
Linux
Билд
6153
ReGamedll
ReGameDLL version: 5.2.0.177-de
Список метамодулей
description      stat pend  file                        vers            src  load  unload
[ 1] AMX Mod X RUN - amxmodx_mm_i386.so v1.8.3-Re ini Start ANY
[ 2] Reunion RUN - reunion_mm_i386.so v0.1.0.92 ini Start Never
[ 3] ReSemiclip RUN - resemiclip_mm_i386.so v2.2(a) ini Chlvl ANY
[ 4] VoiceTranscoder RUN - VoiceTranscoder.so v2017RC3 ini ANY ANY
[ 5] Rechecker RUN - rechecker_mm_i386.so v2.5 ini Chlvl ANY
[ 6] MySQL RUN - mysql_amxx_i386.so v1.8.3-Re pl1 ANY ANY
[ 7] ReAimDetector RUN - reaimdetector_amxx_i386.so v0.1.7 pl1 ANY Never
[ 8] Fun RUN - fun_amxx_i386.so v1.8.3-Re pl1 ANY ANY
[ 9] Engine RUN - engine_amxx_i386.so v1.8.3-Re pl1 ANY ANY
[10] FakeMeta RUN - fakemeta_amxx_i386.so v1.8.3-Re pl1 ANY ANY
[11] Ham Sandwich RUN - hamsandwich_amxx_i386.so v1.8.3-Re pl1 ANY ANY
[12] CStrike RUN - cstrike_amxx_i386.so v1.8.3-Re pl1 ANY ANY
[13] ReAPI RUN - reapi_amxx_i386.so v5.6.0.156-dev pl1 ANY Never

[14] CSX RUN - csx_amxx_i386.so v1.8.3-Re pl1 ANY ANY
14 pl
Список плагинов
Currently loaded plugins:
name version author file status
[ 1] Game Namer 1.1 NeuroToxin gamenamechanger running
[ 2] [ReAMX] AMXBans RBS 17.10.30 Larte Team & SKA amxbans_rbs.amx running
[ 3] Admin Commands 1.8.3-Re AMXX Dev Team admincmd.amxx running
[ 4] Menus Front-End 18.03.24 AMXX Dev Team & amxmodmenu_rbs. running
[ 5] [ReAMX] VIP RBS 18.03.24 SKAJIbnEJIb vip_rbs.amxx running
[ 6] Nade Health 0.1 Dorus nade_helth.amxx running
[ 7] Commands Menu 1.8.3-Re AMXX Dev Team cmdmenu.amxx running
[ 8] Players Menu 1.8.3-Re AMXX Dev Team plmenu.amxx running
[ 9] Plugin Menu 1.8.3-Re AMXX Dev Team pluginmenu.amxx running
[ 10] SF Warn Menu 0.1.4g serfreeman1337 sf_admin_warns. running
[ 11] [ReAMX] CsStats MySQL 18.03.24 SKAJIbnEJIb csstats_mysql.a running
[ 12] Restrict Weapons 1.8.3-Re AMXX Dev Team restmenu.amxx running
[ 13] Stop the Bastards 1.6.6 F@nt0M stop_the_bastar debug
[ 14] [ReAMX] StatsX RBS 18.03.24 SKAJIbnEJIb & AM statsx_rbs.amxx running

[ 15] [ReAMX] Skill ELO 18.03.24 SKAJIbnEJIb skill_elo.amxx running
[ 16] Admin Votes 1.8.3-Re AMXX Dev Team adminvote.amxx running
[ 17] Pause Plugins 1.8.3-Re AMXX Dev Team pausecfg.amxx running
[ 18] Stats Configuration 1.8.3-Re AMXX Dev Team statscfg.amxx running
[ 19] Advanced MapChooser 1.1.0 neygomon map_chooser.amx running
[ 20] [ReAMX] MapsMenu RBS 17.10.30 AMXX Dev Team & mapsmenu_rbs.am running
[ 22] Reset Score 1.0 Silenttt resetscore.amxx running
[ 23] [ReAMX] Parachute RBS 17.12.12 KRoT@L/JTP10181 parachute_rbs.a running
[ 24] [ReAMX] Ultimate Knife 18.05.15 SKAJIbnEJIb ultimate_knife. running
[ 25] AFK Control 1.4.1 [Rnd neygomon afk_control.amx debug
[ 26] [ReAMX] VoteBan L4D 17.10.30 Sanlerus voteban_l4d.amx running
[ 27] ReAimDetector API 0.1.8 ReHLDS Team reaimdetector.a running
[ 28] CheckerResourcesList 1.0 s9va CheckerResource running
[ 29] [ReAMX] Spect Bot 17.08.28 SKAJIbnEJIb & Bo SpectBot.amxx running

[ 30] [ReAMX] Damager RBS 17.12.22 SKAJIbnEJIb damager_rbs.amx running
[ 31] [ReAMX] Ultimate Gag 17.12.22BE SKAJIbnEJIb ultimate_gag.am running
[ 32] [ReAMX] Chat Controlle 18.05.15 SKAJIbnEJIb chat_controller running
[ 33] [ReAMX] AdminChat RBS 17.10.30 SKAJIbnEJIb adminchat_rbs.a running
[ 34] [ReAMX] Ad From Server 17.10.30 SKAJIbnEJIb ad_from_server. running
[ 35] Bomb HUD Timer 0.2 Twe3k Bomb_HuD.amxx running
[ 36] [ReAMX] Demo Recorder 18.02.08 SKAJIbnEJIb demorecorder_rb running
[ 37] Ping Faker 1.5a MeRcyLeZZ pingfaker.amxx running
[ 38] [ReAMX] Chat RBS 18.03.24 SKAJIbnEJIb chat_rbs.amxx running
[ 39] Block All Adverts 1.3 neygomon block_a
Исходный код
/**
*
* 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>

#if AMXX_VERSION_NUM < 183
#include <colorchat>
#define MAX_NAME_LENGTH 32
new MaxClients;
#endif


// EDIT HERE
// #define FWD_DISCONNECT
#define MAX_PLAYERS 32
#define MAX_REASONS 10
#define MAX_TIMES 100
#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[i], value, charsmax(value));
console_print(id, "[%s] %s is '%s'", LOG_TAG, config[i], 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[i] = 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][i];

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[i][REASON_STRING]);

if (g_Reasons[i][REASON_TIME] != -1) {
GetTimeString(id, g_Reasons[i][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[i], 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)
{
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()) {

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[i])) {
server_cmd("kick #%d", get_user_userid(players[i]));
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[i], time, timeDisplay, charsmax(timeDisplay), time_minutes);
if (admin == 0) {
client_print_color(players[i], player, "%L", players[i], "STB_PUNISH_NOTIFY_SERVER", g_PlayersData[player][PLAYER_NAME], timeDisplay, reason);
} else {
client_print_color(players[i], player, "%L", players[i], "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[i], player, "%L", players[i], "STB_FORGIVE_NOTIFY_EXPIRED", g_PlayersData[player][PLAYER_NAME]);
} else if (admin == 0) {
client_print_color(players[i], player, "%L", players[i], "STB_FORGIVE_NOTIFY_SERVER", g_PlayersData[player][PLAYER_NAME]);
} else {
client_print_color(players[i], player, "%L", players[i], "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[i], time, timeDisplay, charsmax(timeDisplay), time_minutes);
GetTimeString(players[i], left, leftDisplay, charsmax(leftDisplay), time_seconds);
client_print_color(players[i], player, "%L", players[i], "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[i] != EOS) {
switch (value[i]) {
case '0'..'9': {
t = (t * 10) + (value[i] - '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[i] != EOS) {
switch (value[i]) {
case '0'..'9': {
t = (t * 10) + (value[i] - '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[i] <= '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[i])) {
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[i], 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;
}
Наказание делает якобы. При повторной попытке пишет что игрок наказан но он дальше продолжает убивать.
 
В этой теме было размещено решение! Перейти к решению.
Сообщения
2,491
Реакции
2,790
Помог
61 раз(а)
Приложите конфиг под спойлер
 
Сообщения
35
Реакции
0
Помог
1 раз(а)
fantom,
[CONFIG]
log_to_file = true
reserved_slots = 3
block_damage = 100
block_timeout = 60
block_move = 30
timeout_min = 1.0
timeout_max = 1.5
default_reason = No Reason
default_time = 20
default_type = abc
super_flag = h
notify_admins = true
notify_players = true
notify_punished = false
notify_player = true
admin_view_chat = true
ban_times = "5 15 30 1d 1w"

[REASONS]
"WH" "60" "abcd"
"AIM" "60" "abc"
"Неадекват" "30" "ade"
 
Сообщения
2,491
Реакции
2,790
Помог
61 раз(а)
Можете снять видео или демо. С конфигом все в порядке
 
Сообщения
35
Реакции
0
Помог
1 раз(а)
fantom, дебаг пишет вот что:
L 06/13/2018 - 20:34:50: Expected 0 parameters, got 5
L 06/13/2018 - 20:34:50: [AMXX] Displaying debug trace (plugin "stop_the_bastardss.amxx", version "1.6.6")
L 06/13/2018 - 20:34:50: [AMXX] Run time error 10: native error (native "ExecuteForward")
L 06/13/2018 - 20:34:50: [AMXX] [0] stop_the_bastards.sma::PunishFowrward (line 1669)
L 06/13/2018 - 20:34:50: [AMXX] [1] stop_the_bastards.sma::PunishPlayer (line 1369)
L 06/13/2018 - 20:34:50: [AMXX] [2] stop_the_bastards.sma::cmdPunish (line

Компиляция файла прошла успешно. Если надо демо... завтра сниму...
 
Сообщения
35
Реакции
0
Помог
1 раз(а)
fantom, Ничего не поменялось...


L 06/14/2018 - 09:00:27: [STOP_THE_BASTARDS] Сервер наказал игрока 'KPoJIuK' <STEAM_1:0:1614569708><95.135.144.122> на 17 нед.1 дн. (Причина 'KpoJIuK') (Флаги 'ade')
L 06/14/2018 - 09:00:27: [ReAPI] EnableHookChain: invalid HookChain handle.
L 06/14/2018 - 09:00:27: [AMXX] Displaying debug trace (plugin "stop_the_bastards.amxx", version "1.6.6")
L 06/14/2018 - 09:00:27: [AMXX] Run time error 10: native error (native "EnableHookChain")
L 06/14/2018 - 09:00:27: [AMXX] [0] stop_the_bastards.sma::SetHooksEnable (line 1491)
L 06/14/2018 - 09:00:27: [AMXX] [1] stop_the_bastards.sma::PunishPlayer (line 1352)
L 06/14/2018 - 09:00:27: [AMXX] [2] stop_the_bastards.sma::cmdPunish (li
14 Июн 2018
fantom, скорее всего проблема не в плагине, а в метамод-плагине может ?
 
Сообщения
2,491
Реакции
2,790
Помог
61 раз(а)
А у вас не rehlds? Только regame dll?
 
Сообщения
2,491
Реакции
2,790
Помог
61 раз(а)
Тогда я уже не знаю в какую сторону копать. Попробуйте разве что заменить реамхх на амхх 1.8.3
 
Сообщения
35
Реакции
0
Помог
1 раз(а)
fantom, щас попробую. сам в шоке. все работает. сервер стоит на centos 6 x64 . а твойй плагин...сволочь... не хочет дружить. (((( щас регейм обновлю и попробую амх обновить. отпишу.
 
Статус
В этой теме нельзя размещать новые ответы.

Пользователи, просматривающие эту тему

Сейчас на форуме нет ни одного пользователя.
Сверху Снизу