#pragma semicolon 1
#include <sdkhooks>
#include <sdktools>
/* Спасибо Zipcore - макросы */
#define LoopIngameClients(%1) for(int %1=1;%1<=MaxClients;++%1)\
if(IsClientInGame(%1))
/* Переменные */
#define MINUS_BLEED_HP 1 // Здоровье, отнимаемое у игрока в X секунд.
#define BLEED_BORDER 30 // Здоровье, ниже которого начинается кровотечение.
/* ========== */
new Handle:BleedChance;
new bool:Bleed[MAXPLAYERS + 1];
Handle g_hTimer = null;
ConVar g_cvCheckInterval;
new Float:g_fCheckInterval;
new Float:g_fShakeAmp;
new Float:g_fShakeTime;
new Handle:g_hConVar_fShakeAmp = INVALID_HANDLE;
new Handle:g_hConVar_fShakeTime = INVALID_HANDLE;
public Plugin:myinfo = {
author = "Hejter",
name = "[CS:GO] Bleeding",
description = "Кровотечение с X шансом.",
version = "0.9",
url = "hlmod.ru & excw.ru",
}
public OnPluginStart(){
BleedChance = CreateConVar("sm_bleeding_chance", "0.25", "Шанс кровотечения, 1.00 = 100%, 0.50 = 50%, и т.д", FCVAR_PLUGIN);
g_hConVar_fShakeAmp = CreateConVar("sm_heartbeat_shakeamp", "7.0", "Сила тряски экрана");
g_hConVar_fShakeTime = CreateConVar("sm_heartbeat_shaketime", "3.0", "промежуток тряски экрана");
g_cvCheckInterval = CreateConVar("sm_check_interval", "2.5", "Отрезок времени через которое игроку будет снимать ХП.");
HookConVarChange(g_hConVar_fShakeAmp, ConVar_Callback);
HookConVarChange(g_hConVar_fShakeTime, ConVar_Callback);
HookConVarChange(g_cvCheckInterval, ConVar_Callback);
g_fShakeAmp = GetConVarFloat(g_hConVar_fShakeAmp);
g_fShakeTime = GetConVarFloat(g_hConVar_fShakeTime);
g_fCheckInterval = GetConVarFloat(g_cvCheckInterval);
HookEvent("player_death", PlayerDeath);
HookEvent("player_hurt", PlayerHurt);
HookEvent("player_spawn", PlayerSpawn);
HookEvent("round_start", RoundStart);
HookEvent("round_end", RoundEnd);
AutoExecConfig(true, "sm_bleeding");
}
public OnMapStart()
{
AddFileToDownloadsTable("materials/excw/bleed.vmt");
AddFileToDownloadsTable("materials/excw/bleed.vtf");
}
public ConVar_Callback(Handle:cvar, const String:oldVal[], const String:newVal[])
{
if ( cvar == g_hConVar_fShakeAmp )
{
g_fShakeAmp = GetConVarFloat(g_hConVar_fShakeAmp);
}
else if ( cvar == g_hConVar_fShakeTime )
{
g_fShakeTime = GetConVarFloat(g_hConVar_fShakeTime);
}
else if (cvar == g_cvCheckInterval)
{
g_fCheckInterval = GetConVarFloat(g_cvCheckInterval);
if(g_hTimer != null)
CloseHandle(g_hTimer);
g_hTimer = CreateTimer(g_fCheckInterval, Timer_CheckPlayers, 0, TIMER_REPEAT);
}
}
public RoundStart(Handle:event, const String:name[], bool:dontBroadcast){
g_hTimer = CreateTimer(g_fCheckInterval, Timer_CheckPlayers, 0, TIMER_REPEAT);
}
public RoundEnd(Handle:event, const String:name[], bool:dontBroadcast){
if(g_hTimer != null)
{
KillTimer(g_hTimer);
g_hTimer = null;
}
}
public Action:Timer_CheckPlayers(Handle:timer)
{
CheckPlayers();
return Plugin_Continue;
}
CheckPlayers()
{
LoopIngameClients(client)
{
CheckPlayer(client);
}
}
CheckPlayer(client)
{
new Float:iBleedChance = GetConVarFloat(BleedChance);
new Float:iRoll = GetRandomFloat();
if (IsPlayerAlive(client) && Bleed[client])
{
new cHealth = GetClientHealth(client) - MINUS_BLEED_HP;
if (iBleedChance >= iRoll)
{
if (cHealth <= BLEED_BORDER)
{
Bleed[client] = true;
SetEntityHealth(client, cHealth);
ClientCommand(client,"r_screenoverlay excw/bleed");
SetBlind(client, 300, 0, {255, 0, 0, 30});
SetShake(client);
}
}
if (cHealth <= 0)
{
ForcePlayerSuicide(client);
Bleed[client] = false;
}
}
}
public PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast){
new client = GetClientOfUserId(GetEventInt(event, "userid"));
if(IsClientInGame(client) && IsPlayerAlive(client))
{
InsertInfo(client);
ClientCommand(client,"r_screenoverlay 0");
}
}
public PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast)
{
new client = GetClientOfUserId(GetEventInt(event, "userid"));
if(IsClientInGame(client))
{
InsertInfo(client);
ClientCommand(client,"r_screenoverlay 0");
}
}
public OnClientPutInServer(client)
{
InsertInfo(client);
}
public OnClientDisconnect(client){
InsertInfo(client);
}
/* Спасибо AlmazON - убиваем глобальный таймер, если все игроки вышли с сервера */
public OnClientDisconnect_Post(client)
{
for (new i = 1; i <= MaxClients; ++i)
{
if (IsClientInGame(i)) return;
}
if(g_hTimer != null)
{
KillTimer(g_hTimer);
g_hTimer = null;
}
}
InsertInfo(client){
Bleed[client] = false;
}
public PlayerHurt(Handle:event, const String:name[], bool:dontBroadcast){
new client = GetClientOfUserId(GetEventInt(event, "userid"));
new Float:iBleedChance = GetConVarFloat(BleedChance);
new Float:iRoll = GetRandomFloat();
if(IsPlayerAlive(client) && Bleed[client] == false && client != GetClientOfUserId(GetEventInt(event, "attacker")))
{
if (iBleedChance >= iRoll)
{
if (GetEventInt(event, "health") <= BLEED_BORDER)
{
Bleed[client] = true;
}
}
}
}
/* Функция затемнение экрана */
stock SetBlind(client, duration, hold_time, const color[4]) {
new flags = 0x0001;
new Handle:message = StartMessageOne("Fade", client);
if (message != INVALID_HANDLE)
{
PbSetInt(message, "duration", duration); // 1 * 300 = 300 - сколько duration поставишь, столько он времени будет светлеть
PbSetInt(message, "hold_time", hold_time); // Время задержки цвета
PbSetInt(message, "flags", flags);
PbSetColor(message, "clr", color);
EndMessage();
}
}
/* Функция тряски экрана */
stock SetShake(client){
new Handle:hBf = StartMessageOne("Shake", client);
if( hBf != INVALID_HANDLE )
{
PbSetInt(hBf, "command", 0);
PbSetFloat(hBf, "local_amplitude", g_fShakeAmp);
PbSetFloat(hBf, "frequency", 1.0);
PbSetFloat(hBf, "duration", g_fShakeTime);
EndMessage();
}
}