/**
История изменений:
0.1b (01.08.2022) by b0t.
- Тестовый релиз;
0.2b (02.08.2022) by b0t & Orpheus.
- Доработка метода блокировки "Бага";
*Благодарность: Orpheus
0.3b (04.08.2022) by b0t.
- Значение углов переведены в float для большей точности;
- Добавлена проверка на расстояние, для избежания ложных срабатываний;
0.4b (30.09.2022) by b0t.
- fix недочётов с проверками;
*/
new const VERSION[] = "0.4b";
#include <amxmodx>
#include <fakemeta>
#include <reapi>
enum _:XYZ {
Float:X,Float:Y,Float:Z
};
enum _:CVARS_DATA {
CVAR__USE_WARN,
CVAR__MAX_WARN,
CVAR__BLOCK_DMG,
CVAR__WARN_PUNISHMENT[256]
};
new
pCvar[CVARS_DATA];
new
p_iWarn[33];
public plugin_init() {
register_plugin("Fix Bug Ricochet",VERSION,"b0t. & Orpheus");
Func__CreateCvars();
RegisterHookChain(RG_CBasePlayer_TakeDamage,"CBasePlayer_TraceAttack_Pre", .post = false);
}
public CBasePlayer_TraceAttack_Pre(const pVictim,const iInvlictor,const pAttacker,const Float:fDamage) {
if(!is_user_connected(pAttacker))
return HC_CONTINUE;
if(!rg_is_player_can_takedamage(pVictim,pAttacker))
return HC_CONTINUE;
if(~get_entvar(pAttacker,var_button) & IN_DUCK)
return HC_CONTINUE;
static iActiveItem;
iActiveItem = get_member(pAttacker,m_pActiveItem);
if(is_nullent(iActiveItem))
return HC_CONTINUE;
static WeaponIdType:iWeaponID;
iWeaponID = get_member(iActiveItem,m_iId);
if(iWeaponID != WEAPON_KNIFE)
return HC_CONTINUE;
static Float:fOriginAttacker[XYZ],Float:fOriginVictim[XYZ];
get_entvar(pAttacker,var_origin,fOriginAttacker);
get_entvar(pVictim,var_origin,fOriginVictim);
static Float:fDistance;
fDistance = get_distance_f(fOriginAttacker,fOriginVictim);
if(fDistance < 90.0)
return HC_CONTINUE;
static Float:fAngles[XYZ];
get_entvar(pAttacker,var_angles,fAngles);
if(fAngles[X] > 0.0)
return HC_CONTINUE;
if(4.8 <= abs_f(fAngles[X]) <= 5.1) {
if(pCvar[CVAR__USE_WARN] && ++p_iWarn[pAttacker] >= pCvar[CVAR__MAX_WARN])
Func__SetPunishment(pAttacker);
if(pCvar[CVAR__BLOCK_DMG]) {
SetHookChainReturn(ATYPE_INTEGER,0);
return HC_SUPERCEDE;
}
}
return HC_CONTINUE;
}
public Func__SetPunishment(const id) {
new szData[256];
copy(szData,charsmax(szData),pCvar[CVAR__WARN_PUNISHMENT]);
replace_all(szData,charsmax(szData),"%user_id%",fmt("%i",get_user_userid(id)));
server_cmd(szData);
}
public client_putinserver(id) {
p_iWarn[id] = 0;
}
public Func__CreateCvars() {
bind_pcvar_num(
create_cvar(
.name = "br_block_dmg",
.string = "1",
.description = "Блокировать урон, если игрок использует баг^n1 - Да | 0 - Нет"
),
pCvar[CVAR__USE_WARN]
);
bind_pcvar_num(
create_cvar(
.name = "br_use_warn_system",
.string = "1",
.description = "Использовать систему наказаний^n1 - Да | 0 - Нет"
),
pCvar[CVAR__USE_WARN]
);
bind_pcvar_num(
create_cvar(
.name = "br_max_warns",
.string = "3",
.description = "Максимально кол-во предупреждений после которого последует наказание из 'br_warn_punishment'"
),
pCvar[CVAR__MAX_WARN]
);
bind_pcvar_string(
create_cvar(
.name = "br_warn_punishment",
.string = "fb_ban 1440 %user_id% BugUser",
.description = "Наказание. Выполняется в консоли сервера^n%user_id% - Юзер ид игрока"
),
pCvar[CVAR__WARN_PUNISHMENT],charsmax(pCvar)
);
AutoExecConfig(.name = "BugRicochet");
}
stock Float:abs_f(Float:fNum) {
return Float:(fNum > 0 ? fNum : -fNum);
}