diff --git a/TeamManager/scripting/TeamManager.sp b/TeamManager/scripting/TeamManager.sp new file mode 100644 index 00000000..89a85942 --- /dev/null +++ b/TeamManager/scripting/TeamManager.sp @@ -0,0 +1,210 @@ +#include +#include + +#pragma semicolon 1 +#pragma newdecls required + +#define MIN_PLAYERS 2 + +bool g_bWarmup = false; +int g_Warmup = 0; +ConVar g_CVar_sm_warmuptime; +ConVar g_CVar_sm_warmupratio; + +bool g_bRoundEnded = false; +bool g_bZombieSpawned = false; +bool g_bIgnoreGameStart = false; +int g_TeamChangeQueue[MAXPLAYERS + 1] = { -1, ... }; + +public Plugin myinfo = +{ + name = "TeamManager", + author = "BotoX", + description = "", + version = "1.0", + url = "https://github.com/CSSZombieEscape/sm-plugins/tree/master/TeamManager" +}; + +public void OnPluginStart() +{ + AddCommandListener(OnJoinTeamCommand, "jointeam"); + HookEvent("round_start", OnRoundStart, EventHookMode_Pre); + HookEvent("round_end", OnRoundEnd, EventHookMode_PostNoCopy); + + g_CVar_sm_warmuptime = CreateConVar("sm_warmuptime", "10", "Warmup timer.", 0, true, 0.0, true, 60.0); + g_CVar_sm_warmupratio = CreateConVar("sm_warmupratio", "0.60", "Ratio of connected players that need to be in game to start warmup timer.", 0, true, 0.0, true, 1.0); + + /* Late load */ + for(int client = 1; client <= MaxClients; client++) + { + if(!IsClientInGame(client)) + continue; + } + + AutoExecConfig(true, "plugin.TeamManager"); +} + +public void OnMapStart() +{ + g_bWarmup = false; + g_Warmup = 0; + if(g_CVar_sm_warmuptime.IntValue > 0 || g_CVar_sm_warmupratio.FloatValue > 0.0) + { + g_bWarmup = true; + CreateTimer(1.0, OnWarmupTimer, 0, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); + } +} + +public Action OnWarmupTimer(Handle timer) +{ + if(g_CVar_sm_warmupratio.FloatValue > 0.0) + { + int ClientsConnected = GetClientCount(false); + int ClientsInGame = GetClientCount(true); + int ClientsNeeded = RoundToCeil(float(ClientsConnected) * g_CVar_sm_warmupratio.FloatValue); + ClientsNeeded = ClientsNeeded > MIN_PLAYERS ? ClientsNeeded : MIN_PLAYERS; + + if(ClientsInGame < ClientsNeeded) + { + g_Warmup = 0; + PrintCenterTextAll("Warmup: Waiting for %d more players to join.", ClientsNeeded - ClientsInGame); + return Plugin_Continue; + } + } + + if(g_Warmup >= g_CVar_sm_warmuptime.IntValue) + { + g_bWarmup = false; + g_Warmup = 0; + CS_TerminateRound(3.0, CSRoundEnd_GameStart, false); + return Plugin_Stop; + } + + PrintCenterTextAll("Warmup: %d", g_CVar_sm_warmuptime.IntValue - g_Warmup); + g_Warmup++; + + return Plugin_Continue; +} + +public void OnClientConnected(int client) +{ + g_TeamChangeQueue[client] = -1; +} + +public Action OnJoinTeamCommand(int client, const char[] command, int argc) +{ + if(client < 1 || client >= MaxClients || !IsClientInGame(client)) + return Plugin_Continue; + + char sArg[8]; + GetCmdArg(1, sArg, sizeof(sArg)); + + int CurrentTeam = GetClientTeam(client); + int NewTeam = StringToInt(sArg); + + if(NewTeam < CS_TEAM_NONE || NewTeam > CS_TEAM_CT) + return Plugin_Handled; + + if(g_bRoundEnded) + { + if(NewTeam == CS_TEAM_T || NewTeam == CS_TEAM_NONE) + NewTeam = CS_TEAM_CT; + + if(NewTeam == CurrentTeam) + { + if(g_TeamChangeQueue[client] != -1) + { + g_TeamChangeQueue[client] = -1; + PrintCenterText(client, "Team change request canceled."); + } + return Plugin_Handled; + } + + g_TeamChangeQueue[client] = NewTeam; + PrintCenterText(client, "You will be placed in the selected team shortly."); + return Plugin_Handled; + } + + if(!g_bZombieSpawned) + { + if(NewTeam == CS_TEAM_T || NewTeam == CS_TEAM_NONE) + NewTeam = CS_TEAM_CT; + } + else if(NewTeam == CS_TEAM_NONE) + NewTeam = CS_TEAM_T; + + if(NewTeam == CurrentTeam) + return Plugin_Handled; + + ChangeClientTeam(client, NewTeam); + return Plugin_Handled; +} + +public void OnRoundStart(Event event, const char[] name, bool dontBroadcast) +{ + g_bRoundEnded = false; + g_bZombieSpawned = false; + + for(int client = 1; client <= MaxClients; client++) + { + if(!IsClientInGame(client)) + continue; + + int CurrentTeam = GetClientTeam(client); + int NewTeam = CS_TEAM_CT; + + if(g_TeamChangeQueue[client] != -1) + { + NewTeam = g_TeamChangeQueue[client]; + g_TeamChangeQueue[client] = -1; + } + else if(CurrentTeam <= CS_TEAM_SPECTATOR) + continue; + + if(NewTeam == CurrentTeam) + continue; + + if(NewTeam >= CS_TEAM_T) + CS_SwitchTeam(client, NewTeam); + else + ChangeClientTeam(client, NewTeam); + + if(NewTeam >= CS_TEAM_T && !IsPlayerAlive(client)) + CS_RespawnPlayer(client); + } +} + +public void OnRoundEnd(Event event, const char[] name, bool dontBroadcast) +{ + g_bRoundEnded = true; + g_bZombieSpawned = false; +} + +public Action CS_OnTerminateRound(float &delay, CSRoundEndReason &reason) +{ + if(reason == CSRoundEnd_GameStart && g_bIgnoreGameStart) + { + g_bIgnoreGameStart = false; + + return Plugin_Handled; + } + + if(g_bWarmup) + return Plugin_Handled; + + return Plugin_Continue; +} + +public Action ZR_OnClientInfect(int &client, int &attacker, bool &motherInfect, bool &respawnOverride, bool &respawn) +{ + if(g_bWarmup) + return Plugin_Handled; + + if(motherInfect) + { + g_bIgnoreGameStart = true; + g_bZombieSpawned = true; + } + + return Plugin_Continue; +}