/*
1.0 (16.04.2025 by mx?!):
* First release
1.1 (Modified):
* Added dhud progress bar for camp warnings
* Removed center messages to avoid conflicts
1.2 (Modified):
* Show progress bar only from 5th warning
* Smaller font and top center position
1.3 (Modified):
* Smaller text using two-line format
*/
new const PLUGIN_VERSION[] = "1.3"
#include <amxmodx>
#include <reapi>
#include <xs>
// Create and execture autoconfig?
// Valus represents name of the config file, excluding the .cfg extension. If empty, <plugin-filename.cfg> is assumed.
#define AUTO_CFG ""
// Debug mode. Should be commented by default.
//#define DEBUG
enum _:CVAR_ENUM {
Float:CVAR_F__CHECK_FREQ,
CVAR__CAMP_RADIUS,
CVAR__MAX_WARNS,
CVAR__SLAP_POWER
}
new g_eCvar[CVAR_ENUM]
new g_iLastCampOrigin[MAX_PLAYERS + 1][3]
new g_iWarns[MAX_PLAYERS + 1]
public plugin_init() {
register_plugin("DM AntiCamper", PLUGIN_VERSION, "mx?!")
register_dictionary("dm_anticamper.txt")
RegCvars()
set_task(3.0, "task_RegHooks")
}
public task_RegHooks() {
RegisterHookChain(RG_CBasePlayer_Spawn, "CBasePlayer_Spawn_Post", true)
RegisterHookChain(RG_CBasePlayer_Killed, "CBasePlayer_Killed_Post", true)
}
RegCvars() {
bind_pcvar_float(create_cvar("dmac_check_freq", "1.0", .description = "Check frequency"), g_eCvar[CVAR_F__CHECK_FREQ])
bind_pcvar_num(create_cvar("dmac_camp_radius", "400", .description = "Camping radius to gain warns"), g_eCvar[CVAR__CAMP_RADIUS])
bind_pcvar_num(create_cvar("dmac_max_warns", "15", .description = "Max warns to start slapping"), g_eCvar[CVAR__MAX_WARNS])
bind_pcvar_num(create_cvar("dmac_slap_power", "1", .description = "Damage power of each slap"), g_eCvar[CVAR__SLAP_POWER])
#if defined AUTO_CFG
AutoExecConfig(.name = AUTO_CFG)
#endif
}
public CBasePlayer_Spawn_Post(pPlayer) {
if(is_user_alive(pPlayer) && !is_user_bot(pPlayer)) {
g_iLastCampOrigin[pPlayer][0] = g_iLastCampOrigin[pPlayer][1] = g_iLastCampOrigin[pPlayer][2] = 4096
g_iWarns[pPlayer] = 0
remove_task(pPlayer)
if(g_eCvar[CVAR_F__CHECK_FREQ]) {
set_task(g_eCvar[CVAR_F__CHECK_FREQ], "task_CheckCoords", pPlayer, .flags = "b")
}
}
}
public CBasePlayer_Killed_Post(pVictim, pKiller, iGibType) {
remove_task(pVictim)
}
public client_disconnected(pPlayer) {
remove_task(pPlayer)
}
public task_CheckCoords(pPlayer) {
new iOrigin[3]
get_user_origin(pPlayer, iOrigin, Origin_Client)
if(
IsIntCoordsNearlyEqual(iOrigin[0], g_iLastCampOrigin[pPlayer][0])
&&
IsIntCoordsNearlyEqual(iOrigin[1], g_iLastCampOrigin[pPlayer][1])
&&
IsIntCoordsNearlyEqual(iOrigin[2], g_iLastCampOrigin[pPlayer][2])
) {
if(++g_iWarns[pPlayer] >= g_eCvar[CVAR__MAX_WARNS]) {
// Показываем полную красную шкалу при достижении максимума
ShowProgressBar(pPlayer, 100)
user_slap(pPlayer, g_eCvar[CVAR__SLAP_POWER])
}
else if(g_iWarns[pPlayer] >= 5) {
// Показываем прогресс-бар только с 5-го предупреждения
new Float:percent = float(g_iWarns[pPlayer]) / float(g_eCvar[CVAR__MAX_WARNS]) * 100.0
ShowProgressBar(pPlayer, floatround(percent))
}
}
else {
g_iWarns[pPlayer] = 0
get_user_origin(pPlayer, g_iLastCampOrigin[pPlayer], Origin_Client)
// Скрываем прогресс-бар когда игрок двигается
HideProgressBar(pPlayer)
}
#if defined DEBUG
client_print(pPlayer, print_chat, "DM AntiCamper warns: %i/%i", g_iWarns[pPlayer], g_eCvar[CVAR__MAX_WARNS])
#endif
}
// Функция для показа прогресс-бара
ShowProgressBar(pPlayer, percent) {
new maxWarns = g_eCvar[CVAR__MAX_WARNS]
new currentWarns = g_iWarns[pPlayer]
// Определяем цвет в зависимости от процента заполнения
new r, g, b
if(percent <= 30) {
// Зеленый для 0-30%
r = 0; g = 255; b = 0
}
else if(percent <= 60) {
// Желтый для 31-60%
r = 255; g = 255; b = 0
}
else {
// Красный для 61-100%
r = 255; g = 0; b = 0
}
// Создаем текстовую шкалу прогресса (короткая шкала)
new bar[16]
new bars = floatround(10.0 * float(percent) / 100.0) // 10 символов для полной шкалы
for(new i = 0; i < 10; i++) {
if(i < bars) {
bar = '|'
}
else {
bar = '.'
}
}
bar[10] = 0
// Показываем dhud с прогресс-баром в две строки (имитация меньшего шрифта)
// r, // Красный (динамический из вашего кода)
// g, // Зеленый (динамический из вашего кода)
// b, // Синий (динамический из вашего кода)
// 0.0, // X = 0.0 (горизонтальный центр)
// 0.06, // Y = 0.06 (6% от верха экрана)
// 0, // Эффект: 0 (волна/пульсация)
// 6.0, // Время эффекта: 6 секунд
// 1.1, // Сообщение держится 1.1 секунды
// 0.1, // Появление за 0.1 секунды
// 0.2 // Исчезновение за 0.2 секунды
set_dhudmessage(r, g, b, 1.0, 0.20, 0, 6.0, 1.1, 0.1, 0.2)
// Разбиваем на две строки для компактности
if(percent < 100) {
show_dhudmessage(pPlayer, "Кемпер!^n[%s] %d%% (%d/%d)", bar, percent, currentWarns, maxWarns)
} else {
show_dhudmessage(pPlayer, "Двигайся!^n[%s] %d%% (%d/%d)", bar, percent, currentWarns, maxWarns)
}
}
// Функция для скрытия прогресс-бара
HideProgressBar(pPlayer) {
set_dhudmessage(0, 0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0.0, 0.0)
show_dhudmessage(pPlayer, "")
}
stock bool:IsIntCoordsNearlyEqual(iCoord1, iCoord2) {
return xs_abs(iCoord1 - iCoord2) <= g_eCvar[CVAR__CAMP_RADIUS]
}