Код: Выделить всё
#include <sourcemod>
#include <sdktools>
#define CVAR_FLAGS FCVAR_PLUGIN
#define PLUGIN_VERSION "1.3.0"
#define MAX_LINE_WIDTH 64
#define L4D_MAXPLAYERS 32
#define TEAM_SURVIVORS 2
#define TEAM_INFECTED 3
#define ZC_HUNTER 3
#define ZC_TANK 5
new Handle:PluginMode;
new Handle:rotoblin_health_style = INVALID_HANDLE;
new Handle:z_common_limit = INVALID_HANDLE;
new Handle:jmod_restart_on_free = INVALID_HANDLE;
new Handle:jmod_show_frags = INVALID_HANDLE;
new Handle:jmod_show_tank_damage = INVALID_HANDLE;
new Handle:jmod_show_witch_damage = INVALID_HANDLE;
new Handle:z_max_player_zombies = INVALID_HANDLE;
new Kills[L4D_MAXPLAYERS + 1];
new TankDamage[L4D_MAXPLAYERS + 1];
new WitchDamage[L4D_MAXPLAYERS + 1];
new LastPrintTime;
new String:slotPills[MAX_LINE_WIDTH];
new bool:TankHPPrinted;
new bool:FragsPrinted;
new bool:TimerEnabled = false;
new bool:IsSpamTagsRemoved = false;
public Plugin:myinfo =
{
name = "Rotoblin JMOD",
author = "Jonny",
description = "Fix some shit here.",
version = PLUGIN_VERSION,
url = ""
}
public OnPluginStart()
{
PluginMode = CreateConVar("jmod_mode", "1", "-1 = disabled, 0 = normal 4v4, 1 = 4v4 HC medkits, 2 = 1v1 fix, 3 = 2v2 fix, 4 = 3v3 fix, 5,6 = hunter training", FCVAR_PLUGIN);
CreateConVar("rotoblin_jmod", PLUGIN_VERSION, "Rotoblin Jonny's Mod Version", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_UNLOGGED|FCVAR_DONTRECORD|FCVAR_REPLICATED|FCVAR_NOTIFY);
jmod_show_frags = CreateConVar("jmod_show_frags", "0", "0 = disabled, 1 = normal (once per map), 2 = after each kill", FCVAR_PLUGIN);
jmod_show_witch_damage = CreateConVar("jmod_show_witch_damage", "0", "0 = disabled, 1 = normal", FCVAR_PLUGIN);
jmod_show_tank_damage = CreateConVar("jmod_show_tank_damage", "0", "0 = disabled, 1 = normal", FCVAR_PLUGIN);
rotoblin_health_style = FindConVar("rotoblin_health_style");
if (rotoblin_health_style == INVALID_HANDLE) SetFailState("Rotoblin not found here, dude.");
z_common_limit = FindConVar("z_common_limit");
jmod_restart_on_free = CreateConVar("jmod_restart_on_free", "1", "", FCVAR_PLUGIN);
z_max_player_zombies = FindConVar("z_max_player_zombies");
HookConVarChange(rotoblin_health_style, Rotoblin_Health_Stryle_Changed);
HookConVarChange(z_common_limit, Common_Limit_Changed);
HookEvent("round_start", Event_RoundStart);
HookEvent("round_end", Event_RoundEnd);
HookEvent("player_death", Event_PlayerDeath);
HookEvent("player_incapacitated", Event_PlayerIncapacitated);
HookEvent("hunter_punched", Event_HunterPunched);
HookEvent("player_hurt", Event_PlayerHurt);
HookEvent("player_bot_replace", Event_Replace);
HookEvent("bot_player_replace", Event_Replace);
HookEvent("infected_hurt", Event_InfectedHurt, EventHookMode_Post);
HookEvent("witch_killed", Event_WitchKilled, EventHookMode_Post);
HookEvent("tank_killed", Event_TankKilled, EventHookMode_Post);
RegConsoleCmd("sm_reset", Command_Reset);
RegConsoleCmd("sm_hunters", Command_HuntersLite);
RegConsoleCmd("sm_frags", Command_Frags);
}
public OnMapStart()
{
ClearKillsCounter();
ClearWitchDamageCounter();
ClearTankDamageCounter();
if (TimerEnabled) return;
TimerEnabled = true;
CreateTimer(1.0, timerSpawnHunterss, _, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
}
public OnClientPostAdminCheck(client)
{
if (IsSpamTagsRemoved) return;
IsSpamTagsRemoved = true;
}
ClearKillsCounter()
{
FragsPrinted = false;
for (new i = 1; i <= MaxClients; i++)
{
Kills[i] = 0;
}
}
ClearWitchDamageCounter()
{
for (new i = 0; i <= MaxClients; i++)
{
WitchDamage[i] = 0;
}
}
ClearTankDamageCounter()
{
for (new i = 0; i <= MaxClients; i++)
{
TankDamage[i] = 0;
}
}
public Action:timerSpawnHunterss(Handle:timer, any:Particle)
{
if (GetConVarInt(PluginMode) > 4 && GetConVarInt(PluginMode) < 8)
{
SpawnHunters(1);
}
}
SpawnHunters(hunters_count)
{
if (hunters_count < 1) return;
new current_hunters = GetHuntersCount();
if (current_hunters >= GetConVarInt(z_max_player_zombies)) return;
new need_hunters = GetConVarInt(z_max_player_zombies) - current_hunters;
for (new i = 1; i <= need_hunters; i++) CheatCMD(GetClient(), "z_spawn", "hunter auto");
}
PrintTotalFrags(mode)
{
if (mode < 2)
{
if (LastPrintTime + 15 > GetTime() || FragsPrinted)
{
return;
}
else
{
FragsPrinted = true;
LastPrintTime = GetTime();
}
}
new String:Message[256];
new String:TempMessage[64];
Message = "\x01Frags: ";
new bool:more_than_one = false;
new frags_sum = 0;
for (new i = 1; i <= MaxClients; i++)
{
if (IsValidClient(i) && IsClientInGame(i) && GetClientTeam(i) == TEAM_SURVIVORS)
{
if (more_than_one)
{
Format(TempMessage, sizeof(TempMessage), "\x01, \x03%N: \x01%d", i, Kills[i]);
}
else
{
Format(TempMessage, sizeof(TempMessage), "\x03%N: \x01%d", i, Kills[i]);
}
frags_sum = frags_sum + Kills[i];
more_than_one = true;
StrCat(String:Message, sizeof(Message), TempMessage);
}
}
if (mode == 0 && frags_sum == 0) return;
PrintToChatAll(Message);
}
PrintTotalWitchDamage()
{
new String:Message[256];
new String:TempMessage[64];
Message = "\x01Witch was killed by: ";
new bool:more_than_one = false;
new wd_sum = 0;
for (new i = 1; i <= MaxClients; i++)
{
if (IsValidClient(i) && IsClientInGame(i) && GetClientTeam(i) == TEAM_SURVIVORS && WitchDamage[i] > 0)
{
if (more_than_one)
{
Format(TempMessage, sizeof(TempMessage), "\x01, \x03%N(\x01%d)", i, WitchDamage[i]);
}
else
{
Format(TempMessage, sizeof(TempMessage), "\x03%N(\x01%d)", i, WitchDamage[i]);
}
wd_sum = wd_sum + WitchDamage[i];
more_than_one = true;
StrCat(String:Message, sizeof(Message), TempMessage);
}
}
if (wd_sum == 0) return;
PrintToChatAll(Message);
}
PrintTotalTankDamage(mode)
{
new String:Message[256];
new String:TempMessage[64];
if (mode > 0)
{
Message = "\x01Tank was killed by: ";
}
else
{
Message = "\x01Tank was damaged by: ";
}
new bool:more_than_one = false;
new td_sum = 0;
for (new i = 1; i <= MaxClients; i++)
{
if (IsValidClient(i) && IsClientInGame(i) && GetClientTeam(i) == TEAM_SURVIVORS && TankDamage[i] > 0)
{
if (more_than_one)
{
Format(TempMessage, sizeof(TempMessage), "\x01, \x03%N(\x01%d)", i, TankDamage[i]);
}
else
{
Format(TempMessage, sizeof(TempMessage), "\x03%N(\x01%d)", i, TankDamage[i]);
}
td_sum = td_sum + TankDamage[i];
more_than_one = true;
StrCat(String:Message, sizeof(Message), TempMessage);
}
}
if (td_sum == 0) return;
PrintToChatAll(Message);
}
public OnClientDisconnect_Post(client)
{
if (GetConVarInt(jmod_restart_on_free) < 1) return;
for (new i = 1; i <= MaxClients; i++)
{
if (IsValidEntity(i) && IsClientInGame(i) && !IsFakeClient(i))
{
return;
}
}
if (IsServerProcessing())
{
PrintToServer("Server cannot hibernate?\nExiting...");
ServerCommand("exit");
}
}
public Rotoblin_Health_Stryle_Changed(Handle:hVariable, const String:strOldValue[], const String:strNewValue[])
{
if (GetConVarInt(PluginMode) == 2)
{
SetConVarInt(rotoblin_health_style, 3, false, false);
}
}
public Common_Limit_Changed(Handle:hVariable, const String:strOldValue[], const String:strNewValue[])
{
if (GetConVarInt(z_common_limit) == 0) return;
switch (GetConVarInt(PluginMode))
{
case 0: SetConVarInt(z_common_limit, 30, false, false);
case 1: SetConVarInt(z_common_limit, 30, false, false);
case 2: SetConVarInt(z_common_limit, 10, false, false);
case 3: SetConVarInt(z_common_limit, 20, false, false);
case 4: SetConVarInt(z_common_limit, 30, false, false);
case 5: SetConVarInt(z_common_limit, 0, false, false);
case 6: SetConVarInt(z_common_limit, 0, false, false);
case 7: SetConVarInt(z_common_limit, 0, false, false);
}
}
public Action:Event_RoundStart(Handle:hEvent, const String:strName[], bool:DontBroadcast)
{
ClearKillsCounter();
ClearWitchDamageCounter();
ClearTankDamageCounter();
if (GetConVarInt(PluginMode) == 5 || GetConVarInt(PluginMode) == 6)
{
if (IsRealHumans())
{
for (new i = 1; i <= MaxClients; i++)
{
if (IsValidEntity(i) && IsClientConnected(i) && IsClientInGame(i))
{
if (GetClientTeam(i) == TEAM_SURVIVORS && IsFakeClient(i))
{
KickClient(i);
}
}
}
}
}
TankHPPrinted = false;
if (GetConVarInt(PluginMode) < 1) return;
if (GetConVarInt(PluginMode) == 1)
{
new String:current_map[64];
GetCurrentMap(current_map, sizeof(current_map));
if (StrEqual(current_map, "l4d_vs_airport05_runway", false) || StrEqual(current_map, "l4d_vs_farm05_cornfield", false)
|| StrEqual(current_map, "l4d_vs_hospital05_rooftop", false) || StrEqual(current_map, "l4d_vs_smalltown05_houseboat", false)
|| StrEqual(current_map, "l4d_garage02_lots", false) || StrEqual(current_map, "l4d_river03_port", false))
{
SetConVarInt(rotoblin_health_style, 2, false, false);
}
else
{
SetConVarInt(rotoblin_health_style, 3, false, false);
}
return;
}
if (GetConVarInt(PluginMode) == 2)
{
SetConVarInt(rotoblin_health_style, 3, false, false);
}
if (GetConVarInt(PluginMode) == 3)
{
CreateTimer(0.3, TimedCheckPills, _);
}
}
public Action:Event_RoundEnd(Handle:hEvent, const String:strName[], bool:DontBroadcast)
{
if (GetConVarInt(jmod_show_frags) > 0) PrintTotalFrags(0);
}
public Action:Event_PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast)
{
new client = GetClientOfUserId(GetEventInt(event, "userid"));
if (client && GetClientTeam(client) == TEAM_INFECTED)
{
decl String:modelname[128];
GetEntPropString(client, Prop_Data, "m_ModelName", modelname, 128);
if (StrEqual(modelname, "models/infected/hulk.mdl", false))
{
Event_TankKilled(event, name, dontBroadcast);
}
}
if (!IsValidClient(client)) return;
new attacker = GetClientOfUserId(GetEventInt(event, "attacker"));
if (IsValidClient(attacker) && GetClientTeam(attacker) == TEAM_SURVIVORS && GetClientZC(client) != ZC_TANK)
{
Kills[attacker]++;
if (GetConVarInt(jmod_show_frags) > 1 && attacker != client)
{
PrintCenterText(attacker, "%d", Kills[attacker]);
}
}
if (GetConVarInt(PluginMode) < 2 || TankHPPrinted) return;
if (GetConVarInt(PluginMode) > 2 || GetConVarInt(PluginMode) == 1)
{
if (!IsPlayersAlive() && !IsPluginTankDamageEnabled())
{
new TankHP = GetTankHP();
if (TankHP > 0)
{
TankHPPrinted = true;
PrintToChatAll("Tank had \x03%d\x01 health remaining!", TankHP);
PrintTotalTankDamage(0);
}
if (GetConVarInt(jmod_show_frags) > 0) PrintTotalFrags(1);
}
return;
}
if (GetConVarInt(PluginMode) == 2 && !IsPluginTankDamageEnabled())
{
new TankHP = GetTankHP();
if (TankHP > 0)
{
TankHPPrinted = true;
PrintToChatAll("Tank had \x03%d\x01 health remaining!", TankHP);
PrintTotalTankDamage(0);
}
if (GetConVarInt(jmod_show_frags) > 0) PrintTotalFrags(1);
return;
}
}
public Action:Event_HunterPunched(Handle:event, const String:name[], bool:dontBroadcast)
{
if (GetConVarInt(PluginMode) != 5) return;
new hunter = GetClientOfUserId(GetEventInt(event, "hunteruserid"));
PrintToChatAll("(Punched) Hunter HP: \x03%d", GetClientHealth(hunter));
ForcePlayerSuicide(hunter);
SpawnHunters(1);
}
public Action:Event_PlayerIncapacitated(Handle:event, const String:name[], bool:dontBroadcast)
{
if (TankHPPrinted) return;
if (GetConVarInt(PluginMode) > 2 || GetConVarInt(PluginMode) == 1)
{
if (!IsPlayersAlive() && !IsPluginTankDamageEnabled())
{
new TankHP = GetTankHP();
if (TankHP > 0)
{
TankHPPrinted = true;
PrintToChatAll("Tank had \x03%d\x01 health remaining!", TankHP);
PrintTotalTankDamage(0);
}
if (GetConVarInt(jmod_show_frags) > 0) PrintTotalFrags(1);
}
return;
}
}
public Action:Event_PlayerHurt(Handle:event, const String:name[], bool:dontBroadcast)
{
if (GetConVarInt(PluginMode) != 5 && GetConVarInt(PluginMode) != 6 && GetConVarInt(jmod_show_tank_damage) < 1) return;
new damagetype = GetEventInt(event, "type");
new enemy = GetClientOfUserId(GetEventInt(event, "attacker"));
new target = GetClientOfUserId(GetEventInt(event, "userid"));
decl String:modelname[128];
GetEntPropString(target, Prop_Data, "m_ModelName", modelname, 128);
if (GetConVarInt(jmod_show_tank_damage) > 0 && StrEqual(modelname, "models/infected/hulk.mdl", false)) // ZombieClass is a wrong solution
{
if (IsValidClient(enemy) && !IsIncapacitated(target))
{
new damage_count = GetEventInt(event, "dmg_health");
TankDamage[enemy] += damage_count;
//PrintToChatAll("[TankDamage] Total: %d, Last: %d", TankDamage[enemy], damage_count);
}
}
if (GetConVarInt(PluginMode) != 5 && GetConVarInt(PluginMode) != 6) return;
// PrintToChatAll("damage_type = %d", damagetype);
// PrintToConsole(target, "damage_type = %d", damagetype);
if (damagetype != 1) return;
if (target == 0) return;
if (IsValidEntity(target) && IsClientConnected(target) && IsClientInGame(target))
{
if (GetClientTeam(target) == TEAM_SURVIVORS)
{
PrintToChatAll("Hunter HP: %d", GetClientHealth(enemy));
SetEntityHealth(target, 100);
if (GetConVarInt(PluginMode) == 5)
{
new hunters_count = 0;
for (new i = 1; i <= MaxClients; i++)
{
if (IsValidEntity(i) && IsClientConnected(i) && IsClientInGame(i))
{
if (GetClientTeam(i) == TEAM_INFECTED)
{
ForcePlayerSuicide(i);
hunters_count++;
}
}
}
SpawnHunters(hunters_count);
}
if (GetConVarInt(PluginMode) == 6)
{
ForcePlayerSuicide(enemy);
SpawnHunters(1);
}
}
}
}
public Action:Event_Replace(Handle:event, const String:name[], bool:dontBroadcast)
{
new player = GetClientOfUserId(GetEventInt(event, "player"));
new bot = GetClientOfUserId(GetEventInt(event, "bot"));
Kills[player] = 0;
Kills[bot] = 0;
TankDamage[player] = 0;
TankDamage[bot] = 0;
WitchDamage[player] = 0;
WitchDamage[bot] = 0;
}
public Action:Event_InfectedHurt(Handle:event, const String:name[], bool:dontBroadcast)
{
new entityid = GetEventInt(event, "entityid");
decl String:class_name[128];
GetEdictClassname(entityid, class_name, sizeof(class_name));
if (!StrEqual(class_name, "witch", false)) return Plugin_Continue;
new attacker = GetClientOfUserId(GetEventInt(event, "attacker"));
if (!IsValidClient(attacker)) return Plugin_Continue;
WitchDamage[attacker] += GetEventInt(event, "amount")
return Plugin_Continue;
}
public Action:Event_WitchKilled(Handle:event, const String:name[], bool:dontBroadcast)
{
if (GetConVarInt(jmod_show_witch_damage) < 1) return;
PrintTotalWitchDamage();
ClearWitchDamageCounter();
}
public Action:Event_TankKilled(Handle:event, const String:name[], bool:dontBroadcast)
{
if (GetConVarInt(jmod_show_tank_damage) < 1) return;
PrintTotalTankDamage(1);
ClearTankDamageCounter();
}
public Action:Command_Reset(client, args)
{
if (GetConVarInt(PluginMode) != 5 && GetConVarInt(PluginMode) != 6) return;
for (new i = 1; i <= MaxClients; i++)
{
if (IsValidEntity(i) && IsClientConnected(i) && IsClientInGame(i))
{
if (GetClientTeam(i) == TEAM_INFECTED)
{
ForcePlayerSuicide(i);
}
}
}
SetEntityHealth(client, 100);
for (new i = 0; i < 5; i++)
{
if (GetPlayerWeaponSlot(client, i) > -1)
{
RemovePlayerItem(client, GetPlayerWeaponSlot(client, i));
}
}
CheatCMD(client, "give", "pistol");
CheatCMD(client, "give", "pistol");
CheatCMD(client, "give", "pumpshotgun");
CheatCMD(client, "ent_remove_all", "z_common_infected");
CheatCMD(client, "ent_remove_all", "weapon_first_aid_kit_spawn");
CheatCMD(client, "ent_remove_all", "weapon_pain_pills_spawn");
CheatCMD(client, "ent_remove_all", "weapon_first_aid_kit");
CheatCMD(client, "ent_remove_all", "weapon_pain_pills");
}
public Action:Command_Hunters(client, args)
{
new count = 0;
for (new i = 1; i <= MaxClients; i++)
{
if (IsValidEntity(i) && IsClientConnected(i) && IsClientInGame(i))
{
count++;
}
}
if (count != 1) return;
ChangeClientTeam(client, 2);
ServerCommand("exec rotoblin_hardcore_hunters.cfg");
}
public Action:Command_HuntersLite(client, args)
{
new count = 0;
for (new i = 1; i <= MaxClients; i++)
{
if (IsValidEntity(i) && IsClientConnected(i) && IsClientInGame(i) && !IsFakeClient(i))
{
count++;
}
}
if (count != 1) return;
ServerCommand("exec rotoblin_hardcore_hunters_lite.cfg");
CheatCMD(client, "director_force_versus_start", "");
}
public Action:Command_Frags(client, args)
{
PrintTotalFrags(2);
}
public GetWeaponNameAtSlot(client, slot, String:weaponName[], maxlen)
{
new wclient = GetPlayerWeaponSlot(client, slot);
if (wclient < 0)
{
weaponName[0] = 0;
return;
}
GetEdictClassname(wclient, weaponName, maxlen);
}
public Action:TimedCheckPills(Handle:timer, any:Particle)
{
for (new i = 1; i <= MaxClients; i++)
{
if (IsValidEntity(i) && IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == TEAM_SURVIVORS && IsPlayerAlive(i))
{
GetWeaponNameAtSlot(i, 4, slotPills, MAX_LINE_WIDTH);
if (!StrEqual("weapon_pain_pills", slotPills, false))
{
RemovePlayerItem(i, GetPlayerWeaponSlot(i, 4));
CheatCMD(i, "give", "pain_pills");
}
}
}
}
public CheatCMD(any:client, const String:Command[], const String:Parameters[])
{
if (client == 0) return;
new CheatCMD_flags = GetCommandFlags(Command);
SetCommandFlags(Command, CheatCMD_flags & ~FCVAR_CHEAT);
FakeClientCommand(client, "%s %s", Command, Parameters);
SetCommandFlags(Command, CheatCMD_flags);
}
stock GetClient()
{
for (new i = 1; i <= MaxClients; i++)
{
if (IsValidEntity(i) && IsClientConnected(i) && IsClientInGame(i))
{
if (!IsFakeClient(i))
{
return i;
}
}
}
return 0;
}
stock GetHuntersCount()
{
new count = 0;
for (new i = 1; i <= MaxClients; i++)
{
if (IsValidEntity(i) && IsClientConnected(i) && IsClientInGame(i))
{
if (GetClientZC(i) == ZC_HUNTER)
{
count++;
}
}
}
return count;
}
bool:IsValidClient(client)
{
if (client < 1 || client > MaxClients)
{
return false;
}
if (!IsValidEntity(client))
{
return false;
}
return true;
}
stock GetClientZC(client)
{
return GetEntProp(client, Prop_Send, "m_zombieClass");
}
bool:IsPluginTankDamageEnabled()
{
new Handle:l4d_tankdamage_enabled = INVALID_HANDLE;
l4d_tankdamage_enabled = FindConVar("l4d_tankdamage_enabled");
if (l4d_tankdamage_enabled == INVALID_HANDLE) return false;
if (GetConVarInt(l4d_tankdamage_enabled) > 0) return true;
return false;
}
bool:IsIncapacitated(client)
{
new isIncap = GetEntProp(client, Prop_Send, "m_isIncapacitated");
if (isIncap)
{
return true;
}
return false;
}
bool:IsRealHumans()
{
for (new i = 1; i <= MaxClients; i++)
{
if (IsValidEntity(i) && IsClientConnected(i) && IsClientInGame(i))
{
if (!IsFakeClient(i))
{
return true;
}
}
}
return false;
}
bool:IsPlayersAlive()
{
for (new i = 1; i <= MaxClients; i++)
{
if (IsValidEntity(i) && IsClientConnected(i) && IsClientInGame(i) && GetClientTeam(i) == TEAM_SURVIVORS && IsPlayerAlive(i) && !IsIncapacitated(i))
{
return true;
}
}
return false;
}
stock GetTankHP()
{
for (new i = 1; i <= MaxClients; i++)
{
if (IsValidEntity(i) && IsClientConnected(i) && IsClientInGame(i))
{
if (GetClientZC(i) == ZC_TANK && IsPlayerAlive(i))
{
if (IsIncapacitated(i))
{
return 0;
}
return GetClientHealth(i);
}
}
}
return 0;
}