/*
*****************************************************************************************************
* - version 1.0: *
* Initial release. *
*****************************************************************************************************
*/
#pragma semicolon 1
#pragma newdecls required
#include <sourcemod>
#define PLUGIN_VERSION "1.0"
public Plugin myinfo =
{
name = "Spawn SI",
author = "BloodyBlade",
description = "Spawn SI on timers",
version = PLUGIN_VERSION,
url = ""
};
ConVar SSIOn;
ConVar SSIC;
ConVar SSI_MaxInf;
ConVar SSI_MaxPlayerInf;
ConVar SSI_MinionLimit;
ConVar SSII;
ConVar SSINoSpecials;
Handle SSITimer;
int survivors;
int infcount;
float autodiff = 0.0;
public void OnPluginStart()
{
SSIOn = CreateConVar("SpawnSIOn", "1", "Spawn Special Infected on timers", 0, true, 0.0);
SSIC = CreateConVar("SpawnSIC", "1", "Reduce the timer time depending on the number of survivors?", 0, true, 0.0);
SSI_MaxInf = CreateConVar("SSI_MaxInf", "4", "Max Special Infected", 0, true, 0.0);
SSI_MaxPlayerInf = CreateConVar("SSI_MaxPlayerInf", "4", "Max Players Special Infected(z_max_player_zombies)", 0, true, 0.0);
SSI_MinionLimit = CreateConVar("SSI_MinionLimit", "4", "SI Minion Limit(z_minion_limit)", 0, true, 0.0);
SSII = CreateConVar("SpawnSIInterval", "5.0", "How many seconds till another special infected spawns?", 0, true, 1.0, true, 60.0);
SSINoSpecials = CreateConVar("NoSpecials", "0", "Shutdown the specials?", 0, true, 0.0);
HookEvent("round_start", Start);
HookEvent("player_left_start_area", Killed);
HookEvent("player_left_checkpoint", Killed);
HookEvent("round_end", End);
HookEvent("map_transition", End);
HookEvent("round_start_pre_entity", End);
HookEvent("round_start_post_nav", End);
HookEvent("finale_win", End);
HookEvent("mission_lost", End);
HookEvent("infected_death", Killed);
}
public Action Start(Event event, const char[] name, bool dontBroadcast)
{
if(GetConVarInt(SSIOn) == 1)
{
int flags = GetConVarFlags(FindConVar("z_max_player_zombies"));
SetConVarBounds(FindConVar("z_max_player_zombies"), ConVarBound_Upper, false);
SetConVarFlags(FindConVar("z_max_player_zombies"), flags & ~FCVAR_NOTIFY);
}
}
public void OnClientPutInServer(int client)
{
if(GetConVarInt(SSIOn) == 1)
{
if (IsFakeClient(client)) return;
if(SSITimer)
{
delete SSITimer;
SSITimer = null;
}
Check();
}
}
public void OnClientDisconnect(int client)
{
if(GetConVarInt(SSIOn) == 1)
{
if (IsFakeClient(client)) return;
if(SSITimer)
{
delete SSITimer;
SSITimer = null;
}
if(client > 0) Check();
}
}
bool LeftStartArea()
{
int ent = -1;
for (int i = MaxClients + 1; i <= GetMaxEntities(); i++)
{
if (IsValidEntity(i))
{
char netclass[64];
GetEntityNetClass(i, netclass, sizeof(netclass));
if (StrEqual(netclass, "CTerrorPlayerResource"))
{
ent = i;
break;
}
}
}
if (ent != -1)
{
if (GetEntProp(ent, Prop_Send, "m_hasAnySurvivorLeftSafeArea"))
{
return true;
}
}
return false;
}
public Action Killed(Event event, const char[] name, bool dontBroadcast)
{
if(GetConVarInt(SSIOn) == 1)
{
Check();
}
}
void Check()
{
if(!SSITimer && LeftStartArea())
{
CountSurvivors();
SSITimer = CreateTimer(GetConVarInt(SSII) - autodiff, Spawn, _, TIMER_REPEAT);
}
}
public Action Spawn(Handle timer)
{
if (!IsServerProcessing()) return;
if(GetConVarInt(SSIOn) == 1)
{
if (GetConVarInt(SSINoSpecials) == 1)
{
int anyclient = GetAnyClient();
if (anyclient > 0) { DirectorCommand(anyclient, "director_stop"); }
SetConVarInt(FindConVar("director_no_bosses"), 1);
SetConVarInt(FindConVar("director_no_specials"), 1);
SetConVarInt(FindConVar("director_no_mobs"), 1);
}
else
{
SetConVarInt(FindConVar("director_no_bosses"), 0);
SetConVarInt(FindConVar("director_no_specials"), 0);
SetConVarInt(FindConVar("director_no_mobs"), 0);
int anyclient = GetAnyClient();
if (anyclient > 0) { DirectorCommand(anyclient, "director_start"); }
}
SetConVarInt(FindConVar("z_max_player_zombies"), GetConVarInt(SSI_MaxPlayerInf));
SetConVarInt(FindConVar("z_minion_limit"), GetConVarInt(SSI_MinionLimit));
CountInf();
if (infcount < GetConVarInt(SSI_MaxInf))
{
int bot = CreateFakeClient("Infected Bot");
if (bot > 0)
{
int random = GetRandomInt(1, 6);
switch(random)
{
case 1:
SpawnCommand(bot, "z_spawn_old", "smoker auto");
case 2:
SpawnCommand(bot, "z_spawn_old", "boomer auto");
case 3:
SpawnCommand(bot, "z_spawn_old", "hunter auto");
case 4:
SpawnCommand(bot, "z_spawn_old", "spitter auto");
case 5:
SpawnCommand(bot, "z_spawn_old", "jockey auto");
case 6:
SpawnCommand(bot, "z_spawn_old", "charger auto");
}
}
}
}
}
public Action End(Event event, const char[] name, bool dontBroadcast)
{
if(SSITimer)
{
delete SSITimer;
SSITimer = null;
}
if(GetConVarInt(SSIOn) == 1)
{
for(int i = 1; i <= MaxClients; i++)
{
if(IsClientInGame(i) && IsFakeClient(i) && GetClientTeam(i) == 3 && !IsTank(i))
{
KickClient(i);
}
}
}
}
void CountSurvivors()
{
survivors = 0;
for (int i = 1; i <= MaxClients; i++)
{
if (IsClientInGame(i) && IsPlayerAlive(i) && GetClientTeam(i) == 2 && !IsFakeClient(i))
{
survivors++;
}
}
if(SSIC)
{
if(survivors == 1) autodiff = 0.0;
else if(survivors == 2) autodiff = 0.25;
else if(survivors == 3) autodiff = 0.5;
else if(survivors == 4) autodiff = 0.75;
else if(survivors == 5) autodiff = 1.0;
else if(survivors == 6) autodiff = 1.25;
else if(survivors == 7) autodiff = 1.5;
else if(survivors == 8) autodiff = 1.75;
else if(survivors == 9) autodiff = 2.0;
else if(survivors == 10) autodiff = 2.25;
else if(survivors == 11) autodiff = 2.5;
else if(survivors == 12) autodiff = 2.75;
else if(survivors == 13) autodiff = 3.0;
else if(survivors == 14) autodiff = 3.25;
else if(survivors == 15) autodiff = 3.5;
else if(survivors == 16) autodiff = 3.75;
else if(survivors >= 16) autodiff = 4.0;
}
}
void CountInf()
{
infcount = 0;
char classname[32];
for (int i = 1; i <= MaxClients; i++)
{
if (IsClientInGame(i) && IsFakeClient(i) && GetClientTeam(i) == 3)
{
GetClientModel(i, classname, sizeof(classname));
if (StrContains(classname, "smoker")
|| StrContains(classname, "boomer")
|| StrContains(classname, "hunter")
|| StrContains(classname, "spitter")
|| StrContains(classname, "jockey")
|| StrContains(classname, "charger")
|| StrContains(classname, "hulk"))
{
infcount++;
}
}
}
}
bool IsTank(int i)
{
char classname[32];
GetClientModel(i, classname, sizeof(classname));
if (StrContains(classname, "hulk", false) != -1)
return true;
return false;
}
stock int GetAnyClient()
{
for (int i = 1; i <= MaxClients; i++)
if (IsClientInGame(i) && !IsFakeClient(i))
return i;
return 0;
}
stock void SpawnCommand(int client, char[] command, char[] arguments = "")
{
if (client)
{
ChangeClientTeam(client, 3);
int flags = GetCommandFlags(command);
SetCommandFlags(command, flags & ~FCVAR_CHEAT);
FakeClientCommand(client, "%s %s", command, arguments);
SetCommandFlags(command, flags | FCVAR_CHEAT);
CreateTimer(0.1, Kickbot, client);
}
}
public Action Kickbot(Handle timer, any client)
{
if (IsClientInGame(client) && IsFakeClient(client))
KickClient(client);
}
stock void DirectorCommand(int client, char[] command)
{
if (client)
{
int flags = GetCommandFlags(command);
SetCommandFlags(command, flags & ~FCVAR_CHEAT);
FakeClientCommand(client, "%s", command);
SetCommandFlags(command, flags | FCVAR_CHEAT);
}
}