From 4d699fe780d7594ef703fd2ec5e1fc1b5002c759 Mon Sep 17 00:00:00 2001 From: zaCade Date: Fri, 7 Dec 2018 16:49:40 +0100 Subject: [PATCH 01/52] Initialize --- .gitignore | 4 ++++ compile-all.py | 47 ++++++++++++++++++++++++++++++++++++++++++++++ compile.py | 42 +++++++++++++++++++++++++++++++++++++++++ plugins/.gitignore | 2 ++ 4 files changed, 95 insertions(+) create mode 100644 .gitignore create mode 100644 compile-all.py create mode 100644 compile.py create mode 100644 plugins/.gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b0f1d39 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/include +/spcomp +/spcomp.exe +*.secret diff --git a/compile-all.py b/compile-all.py new file mode 100644 index 0000000..40e034c --- /dev/null +++ b/compile-all.py @@ -0,0 +1,47 @@ +#!/usr/bin/python3 +import os +import sys +import subprocess + +c_null = "\x1b[00;00m" +c_red = "\x1b[31;01m" +c_blue = "\x1b[34;01m" +c_green = "\x1b[32;01m" + +SM_INCLUDES = "includes" +SPCOMP = "./spcomp" + +if __name__ == "__main__": + Plugins = [] + Path, Directories, Files = next(os.walk(".")) + for Directory in Directories: + if not Directory.startswith(".") and not Directory.startswith("_") and Directory != "include" and Directory != "includes" and Directory != "plugins": + Plugins.append(Directory) + + for Plugin in Plugins: + print(c_red + "### Compiling {0}".format(Plugin) + c_null) + + SourcePath = os.path.join(Plugin, "scripting") + Path, Directories, Files = next(os.walk(SourcePath)) + for File in Files: + if File.endswith(".sp"): + print(c_green + "# Compiling {0} ({1})".format(os.path.basename(File), Plugin) + c_null) + SourcePath = os.path.join(Path, File) + IncludePath = os.path.join(Path, "include") + OutDir = "plugins" + OutPath = os.path.join(OutDir, os.path.splitext(os.path.basename(SourcePath))[0] + ".smx") + + Compiler = [SPCOMP, "-i" + SM_INCLUDES] + if os.path.isdir(IncludePath): + Compiler.append("-i" + IncludePath) + Compiler.append(SourcePath) + Compiler.append("-o" + OutPath) + + try: + err = subprocess.call(Compiler) + if err: + raise Exception() + except Exception: + sys.exit(1) + + print("") diff --git a/compile.py b/compile.py new file mode 100644 index 0000000..ffe789f --- /dev/null +++ b/compile.py @@ -0,0 +1,42 @@ +#!/usr/bin/python3 +import os +import sys +import subprocess + +c_null = "\x1b[00;00m" +c_red = "\x1b[31;01m" +c_blue = "\x1b[34;01m" +c_green = "\x1b[32;01m" + +SM_INCLUDES = "includes" +SPCOMP = "./spcomp" + +if __name__ == "__main__": + Plugins = [] + for Directory in sys.argv[1:]: + if Directory != ".git" and Directory != "include" and Directory != "includes" and Directory != "plugins": + Plugins.append(Directory) + + for Plugin in Plugins: + SourcePath = os.path.join(Plugin, "scripting") + Path, Directories, Files = next(os.walk(SourcePath)) + for File in Files: + if File.endswith(".sp"): + print(c_green + "# Compiling {0} ({1})".format(os.path.basename(File), Plugin) + c_null) + SourcePath = os.path.join(Path, File) + IncludePath = os.path.join(Path, "include") + OutDir = "plugins" + OutPath = os.path.join(OutDir, os.path.splitext(os.path.basename(SourcePath))[0] + ".smx") + + Compiler = [SPCOMP, "-i" + SM_INCLUDES] + if os.path.isdir(IncludePath): + Compiler.append("-i" + IncludePath) + Compiler.append(SourcePath) + Compiler.append("-o" + OutPath) + + try: + subprocess.call(Compiler) + except Exception: + sys.exit(1) + + print("") diff --git a/plugins/.gitignore b/plugins/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/plugins/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore From 74560d9797cefad6157583b9a49cff103ffd67d5 Mon Sep 17 00:00:00 2001 From: neon <> Date: Sat, 8 Dec 2018 17:32:15 +0100 Subject: [PATCH 02/52] Vscripts: initial commit --- VScripts/scripting/vscript_ze_dreamin_v2.sp | 720 ++++++++++++++++++++ 1 file changed, 720 insertions(+) create mode 100644 VScripts/scripting/vscript_ze_dreamin_v2.sp diff --git a/VScripts/scripting/vscript_ze_dreamin_v2.sp b/VScripts/scripting/vscript_ze_dreamin_v2.sp new file mode 100644 index 0000000..b8d966a --- /dev/null +++ b/VScripts/scripting/vscript_ze_dreamin_v2.sp @@ -0,0 +1,720 @@ +#pragma semicolon 1 + +#include +#include +#include + +#pragma newdecls required + +#define MAXTIMERS 128 + +/* STRINGS */ + +/* CONVARS */ + +/* HANDLES */ +Handle g_hTimers[MAXTIMERS] = {INVALID_HANDLE, ...}; + +/* BOOLS */ + +/* INTEGERS */ +int g_iTimerCount = 0; + + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Plugin myinfo = +{ + name = "ze_dreamin VScript", + author = "Neon", + description = "", + version = "1.0", + url = "https://steamcommunity.com/id/n3ontm" +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnPluginStart() +{ + HookEvent("round_start", OnRoundStart); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnMapStart() +{ + VerifyMap(); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void VerifyMap() +{ + char currentMap[64]; + GetCurrentMap(currentMap, sizeof(currentMap)); + if (strcmp(currentMap, "ze_dreamin_v2_1s_fix3", false) != 0) + { + char sFilename[256]; + GetPluginFilename(INVALID_HANDLE, sFilename, sizeof(sFilename)); + ServerCommand("sm plugins unload %s", sFilename); + } +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnRoundStart(Event hEvent, const char[] sEvent, bool bDontBroadcast) +{ + + for (int i = 0; i <= (MAXTIMERS - 1); i++) + { + if (g_hTimers[i] != INVALID_HANDLE && CloseHandle(g_hTimers[i])) + g_hTimers[i] = INVALID_HANDLE; + } + g_iTimerCount = 0; + + + int iEntity = INVALID_ENT_REFERENCE; + + iEntity = FindEntityByTargetName("reflect_logic"); + if (iEntity != INVALID_ENT_REFERENCE) + HookSingleEntityOutput(iEntity, "OnFalse", st3_hitbox_reflect, false); + + iEntity = FindEntityByTargetName("upline_timer"); + if (iEntity != INVALID_ENT_REFERENCE) + HookSingleEntityOutput(iEntity, "OnTimer", upline_maker_upline, false); + + iEntity = FindEntityByTargetName("explo_timer"); + if (iEntity != INVALID_ENT_REFERENCE) + HookSingleEntityOutput(iEntity, "OnTimer", explo_maker_setan, false); + + iEntity = FindEntityByTargetName("linelaser_random"); + if (iEntity != INVALID_ENT_REFERENCE) + { + HookSingleEntityOutput(iEntity, "OnCase01", linelaser_maker_left, false); + HookSingleEntityOutput(iEntity, "OnCase02", linelaser_maker_right, false); + } + + iEntity = FindEntityByTargetName("totem_random"); + if (iEntity != INVALID_ENT_REFERENCE) + { + HookSingleEntityOutput(iEntity, "OnCase01", push_maker_setrandom, false); + HookSingleEntityOutput(iEntity, "OnCase02", heal_maker_setrandom, false); + HookSingleEntityOutput(iEntity, "OnCase03", stable_maker_setrandom, false); + HookSingleEntityOutput(iEntity, "OnCase04", rotate_maker_setrandom, false); + } + + iEntity = FindEntityByTargetName("spike_timer"); + if (iEntity != INVALID_ENT_REFERENCE) + HookSingleEntityOutput(iEntity, "OnTimer", spike_maker_top, false); + + iEntity = FindEntityByHammerID(389450); + if (iEntity != INVALID_ENT_REFERENCE) + HookSingleEntityOutput(iEntity, "OnStartTouch", trigger_once_389450_display, false); + + iEntity = FindEntityByHammerID(385777); + if (iEntity != INVALID_ENT_REFERENCE) + HookSingleEntityOutput(iEntity, "OnStartTouch", trigger_once_385777_display, false); + + iEntity = FindEntityByHammerID(385886); + if (iEntity != INVALID_ENT_REFERENCE) + HookSingleEntityOutput(iEntity, "OnStartTouch", trigger_once_385886_display, false); + + iEntity = FindEntityByHammerID(386004); + if (iEntity != INVALID_ENT_REFERENCE) + HookSingleEntityOutput(iEntity, "OnStartTouch", trigger_once_386004_display, false); + + iEntity = FindEntityByHammerID(381396); + if (iEntity != INVALID_ENT_REFERENCE) + HookSingleEntityOutput(iEntity, "OnPressed", func_button_381396_display, false); + + iEntity = FindEntityByHammerID(381463); + if (iEntity != INVALID_ENT_REFERENCE) + HookSingleEntityOutput(iEntity, "OnStartTouch", trigger_once_381463_display, false); + + iEntity = FindEntityByHammerID(381581); + if (iEntity != INVALID_ENT_REFERENCE) + HookSingleEntityOutput(iEntity, "OnStartTouch", trigger_once_381581_display, false); + + iEntity = FindEntityByHammerID(381648); + if (iEntity != INVALID_ENT_REFERENCE) + HookSingleEntityOutput(iEntity, "OnStartTouch", trigger_once_381648_display, false); + + iEntity = FindEntityByHammerID(378212); + if (iEntity != INVALID_ENT_REFERENCE) + HookSingleEntityOutput(iEntity, "OnStartTouch", trigger_once_378212_display, false); + + iEntity = FindEntityByHammerID(375007); + if (iEntity != INVALID_ENT_REFERENCE) + HookSingleEntityOutput(iEntity, "OnStartTouch", trigger_once_375007_display, false); + + iEntity = FindEntityByHammerID(241061); + if (iEntity != INVALID_ENT_REFERENCE) + HookSingleEntityOutput(iEntity, "OnPressed", func_button_241061_display, false); + + iEntity = FindEntityByHammerID(213033); + if (iEntity != INVALID_ENT_REFERENCE) + HookSingleEntityOutput(iEntity, "OnStartTouch", trigger_once_213033_display, false); + + iEntity = FindEntityByHammerID(142829); + if (iEntity != INVALID_ENT_REFERENCE) + HookSingleEntityOutput(iEntity, "OnStartTouch", trigger_once_142829_display, false); + + iEntity = FindEntityByHammerID(95608); + if (iEntity != INVALID_ENT_REFERENCE) + HookSingleEntityOutput(iEntity, "OnStartTouch", trigger_once_95608_display, false); + + iEntity = FindEntityByHammerID(95733); + if (iEntity != INVALID_ENT_REFERENCE) + HookSingleEntityOutput(iEntity, "OnStartTouch", trigger_once_95733_display, false); + + iEntity = FindEntityByHammerID(95823); + if (iEntity != INVALID_ENT_REFERENCE) + HookSingleEntityOutput(iEntity, "OnStartTouch", trigger_once_95823_display, false); + + iEntity = FindEntityByHammerID(77927); + if (iEntity != INVALID_ENT_REFERENCE) + HookSingleEntityOutput(iEntity, "OnPressed", func_button_77927_display, false); + + iEntity = FindEntityByHammerID(23408); + if (iEntity != INVALID_ENT_REFERENCE) + HookSingleEntityOutput(iEntity, "OnStartTouch", trigger_once_23408_display, false); + + iEntity = FindEntityByHammerID(23452); + if (iEntity != INVALID_ENT_REFERENCE) + HookSingleEntityOutput(iEntity, "OnStartTouch", trigger_once_23452_display, false); + + iEntity = FindEntityByHammerID(23474); + if (iEntity != INVALID_ENT_REFERENCE) + HookSingleEntityOutput(iEntity, "OnStartTouch", trigger_once_23474_display, false); + + iEntity = FindEntityByHammerID(23551); + if (iEntity != INVALID_ENT_REFERENCE) + HookSingleEntityOutput(iEntity, "OnBreak", func_breakable_23551_display, false); + + iEntity = FindEntityByHammerID(21950); + if (iEntity != INVALID_ENT_REFERENCE) + HookSingleEntityOutput(iEntity, "OnPressed", func_button_21950_display, false); + + iEntity = FindEntityByHammerID(22017); + if (iEntity != INVALID_ENT_REFERENCE) + HookSingleEntityOutput(iEntity, "OnPressed", func_button_22017_display, false); + + iEntity = FindEntityByHammerID(3664); + if (iEntity != INVALID_ENT_REFERENCE) + HookSingleEntityOutput(iEntity, "OnBreak", func_breakable_3664_display, false); + + iEntity = FindEntityByHammerID(11288); + if (iEntity != INVALID_ENT_REFERENCE) + HookSingleEntityOutput(iEntity, "OnHitMin", math_counter_11288_display, false); + + CreateTimer(12.0, Credits, INVALID_HANDLE, TIMER_FLAG_NO_MAPCHANGE); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Action Credits(Handle timer) +{ + CPrintToChatAll("{pink}[VScripts] {white}Map using VScripts ported by Neon™"); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void st3_hitbox_reflect(const char[] output, int caller, int activator, float delay) +{ + if (!IsValidClient(activator)) + return; + + int iHealth = GetClientHealth(activator); + + if(iHealth > 10) + { + SetEntityHealth(activator, iHealth - 10); + } + else + { + SetEntityHealth(activator, 1); + } +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void upline_maker_upline(const char[] output, int caller, int activator, float delay) +{ + float fOrigin[3]; + fOrigin[0] = GetRandomFloat(-1280.0, 1280.0); + fOrigin[1] = GetRandomFloat(-1280.0, 1280.0); + fOrigin[2] = -2780.0; + + int iEntity = INVALID_ENT_REFERENCE; + + iEntity = FindEntityByTargetName("upline_maker"); + if (iEntity != INVALID_ENT_REFERENCE) + TeleportEntity(iEntity, fOrigin, NULL_VECTOR, NULL_VECTOR); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void explo_maker_setan(const char[] output, int caller, int activator, float delay) +{ + float fAngles[3]; + fAngles[0] = 0.0; + fAngles[1] = GetRandomFloat(0.0, 359.0); + fAngles[2] = 0.0; + + int iEntity = INVALID_ENT_REFERENCE; + + iEntity = FindEntityByTargetName("explo_maker"); + if (iEntity != INVALID_ENT_REFERENCE) + TeleportEntity(iEntity, NULL_VECTOR, fAngles, NULL_VECTOR); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void linelaser_maker_left(const char[] output, int caller, int activator, float delay) +{ + float fOrigin[3]; + fOrigin[0] = 0.0; + fOrigin[1] = GetRandomFloat(-640.0, 640.0); + fOrigin[2] = -1780.0; + + float fAngles[3]; + fAngles[0] = 0.0; + fAngles[1] = 0.0; + fAngles[2] = 0.0; + + int iEntity = INVALID_ENT_REFERENCE; + + iEntity = FindEntityByTargetName("linelaser_maker"); + if (iEntity != INVALID_ENT_REFERENCE) + TeleportEntity(iEntity, fOrigin, fAngles, NULL_VECTOR); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void linelaser_maker_right(const char[] output, int caller, int activator, float delay) +{ + float fOrigin[3]; + fOrigin[0] = 0.0; + fOrigin[1] = GetRandomFloat(-640.0, 640.0); + fOrigin[2] = -1820.0; + + float fAngles[3]; + fAngles[0] = 0.0; + fAngles[1] = 90.0; + fAngles[2] = 0.0; + + int iEntity = INVALID_ENT_REFERENCE; + + iEntity = FindEntityByTargetName("linelaser_maker"); + if (iEntity != INVALID_ENT_REFERENCE) + TeleportEntity(iEntity, fOrigin, fAngles, NULL_VECTOR); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void push_maker_setrandom(const char[] output, int caller, int activator, float delay) +{ + float fOrigin[3]; + fOrigin[0] = GetRandomFloat(-768.0, 768.0); + fOrigin[1] = GetRandomFloat(-768.0, 768.0); + fOrigin[2] = -2720.0; + + int iEntity = INVALID_ENT_REFERENCE; + + iEntity = FindEntityByTargetName("push_maker"); + if (iEntity != INVALID_ENT_REFERENCE) + TeleportEntity(iEntity, fOrigin, NULL_VECTOR, NULL_VECTOR); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void heal_maker_setrandom(const char[] output, int caller, int activator, float delay) +{ + float fOrigin[3]; + fOrigin[0] = GetRandomFloat(-768.0, 768.0); + fOrigin[1] = GetRandomFloat(-768.0, 768.0); + fOrigin[2] = -2720.0; + + int iEntity = INVALID_ENT_REFERENCE; + + iEntity = FindEntityByTargetName("heal_maker"); + if (iEntity != INVALID_ENT_REFERENCE) + TeleportEntity(iEntity, fOrigin, NULL_VECTOR, NULL_VECTOR); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void stable_maker_setrandom(const char[] output, int caller, int activator, float delay) +{ + float fOrigin[3]; + fOrigin[0] = GetRandomFloat(-768.0, 768.0); + fOrigin[1] = GetRandomFloat(-768.0, 768.0); + fOrigin[2] = -2720.0; + + int iEntity = INVALID_ENT_REFERENCE; + + iEntity = FindEntityByTargetName("stable_maker"); + if (iEntity != INVALID_ENT_REFERENCE) + TeleportEntity(iEntity, fOrigin, NULL_VECTOR, NULL_VECTOR); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void rotate_maker_setrandom(const char[] output, int caller, int activator, float delay) +{ + float fOrigin[3]; + fOrigin[0] = GetRandomFloat(-768.0, 768.0); + fOrigin[1] = GetRandomFloat(-768.0, 768.0); + fOrigin[2] = -2720.0; + + int iEntity = INVALID_ENT_REFERENCE; + + iEntity = FindEntityByTargetName("rotate_maker"); + if (iEntity != INVALID_ENT_REFERENCE) + TeleportEntity(iEntity, fOrigin, NULL_VECTOR, NULL_VECTOR); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void spike_maker_top(const char[] output, int caller, int activator, float delay) +{ + float fOrigin[3]; + fOrigin[0] = GetRandomFloat(12090.0, 14363.0); + fOrigin[1] = GetRandomFloat(1280.0, 3560.0); + fOrigin[2] = 1500.0; + + int iEntity = INVALID_ENT_REFERENCE; + + iEntity = FindEntityByTargetName("spike_maker"); + if (iEntity != INVALID_ENT_REFERENCE) + { + TeleportEntity(iEntity, fOrigin, NULL_VECTOR, NULL_VECTOR); + AcceptEntityInput(iEntity, "ForceSpawn"); + } +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void trigger_once_389450_display(const char[] output, int caller, int activator, float delay) +{ + Display(30); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void trigger_once_385777_display(const char[] output, int caller, int activator, float delay) +{ + Display(20); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void trigger_once_385886_display(const char[] output, int caller, int activator, float delay) +{ + Display(20); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void trigger_once_386004_display(const char[] output, int caller, int activator, float delay) +{ + Display(20); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void func_button_381396_display(const char[] output, int caller, int activator, float delay) +{ + Display(30); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void trigger_once_381463_display(const char[] output, int caller, int activator, float delay) +{ + Display(30); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void trigger_once_381581_display(const char[] output, int caller, int activator, float delay) +{ + Display(50); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void trigger_once_381648_display(const char[] output, int caller, int activator, float delay) +{ + Display(30); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void trigger_once_378212_display(const char[] output, int caller, int activator, float delay) +{ + Display(30); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void trigger_once_375007_display(const char[] output, int caller, int activator, float delay) +{ + Display(20); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void func_button_241061_display(const char[] output, int caller, int activator, float delay) +{ + Display(30); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void trigger_once_213033_display(const char[] output, int caller, int activator, float delay) +{ + Display(30); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void trigger_once_142829_display(const char[] output, int caller, int activator, float delay) +{ + Display(20); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void trigger_once_95608_display(const char[] output, int caller, int activator, float delay) +{ + Display(30); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void trigger_once_95733_display(const char[] output, int caller, int activator, float delay) +{ + Display(30); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void trigger_once_95823_display(const char[] output, int caller, int activator, float delay) +{ + Display(30); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void func_button_77927_display(const char[] output, int caller, int activator, float delay) +{ + Display(30); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void trigger_once_23408_display(const char[] output, int caller, int activator, float delay) +{ + Display(35); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void trigger_once_23452_display(const char[] output, int caller, int activator, float delay) +{ + Display(20); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void trigger_once_23474_display(const char[] output, int caller, int activator, float delay) +{ + Display(25); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void func_breakable_23551_display(const char[] output, int caller, int activator, float delay) +{ + Display(20); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void func_button_21950_display(const char[] output, int caller, int activator, float delay) +{ + Display(30); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void func_button_22017_display(const char[] output, int caller, int activator, float delay) +{ + Display(10); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void func_breakable_3664_display(const char[] output, int caller, int activator, float delay) +{ + Display(45); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void math_counter_11288_display(const char[] output, int caller, int activator, float delay) +{ + Display(51); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void Display(int amount) +{ + float fOrigin[3]; + fOrigin[0] = 0.0; + fOrigin[1] = 0.0; + fOrigin[2] = 0.0; + + int iRelay = CreateEntityAtOrigin("logic_relay", fOrigin); + DispatchKeyFormat(iRelay, "targetname", "vscript_countdown_relay"); + DispatchKeyFormat(iRelay, "spawnflags", "0"); + DispatchKeyFormat(iRelay, "OnTrigger", "seconds_left,AddOutput,message seconds left,0,-1"); + DispatchKeyFormat(iRelay, "OnTrigger", "text_sec,AddOutput,message %d,0,-1", amount - 1); + + int iBackup = amount; + + for (int j = 0; j <= amount; j++) + { + iBackup --; + DispatchKeyFormat(iRelay, "OnTrigger", "text_sec,AddOutput,message %d,%d,-1", iBackup, j); + DispatchKeyFormat(iRelay, "OnTrigger", "text_sec,Display,,%d,-1",j); + DispatchKeyFormat(iRelay, "OnTrigger", "seconds_left,Display,,%d,-1",j); + } + DispatchKeyFormat(iRelay, "OnTrigger", "text_sec,AddOutput,message ,%d,-1",amount + 1); + DispatchKeyFormat(iRelay, "OnTrigger", "seconds_left,AddOutput,message ,%d,-1",amount + 1); + DispatchKeyFormat(iRelay, "OnTrigger", "!self,Kill,,%d,-1",amount + 2); + + SpawnAndActivate(iRelay); + AcceptEntityInput(iRelay, "Trigger"); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public int FindEntityByTargetName(const char[] sTargetnameToFind) +{ + int iEntity = INVALID_ENT_REFERENCE; + while((iEntity = FindEntityByClassname(iEntity, "*")) != INVALID_ENT_REFERENCE) + { + char sTargetname[64]; + GetEntPropString(iEntity, Prop_Data, "m_iName", sTargetname, sizeof(sTargetname)); + + if (strcmp(sTargetnameToFind, sTargetname, false) == 0) + { + return iEntity; + } + } + PrintToChatAll("[VScripts] Error! Could not find entity: %s", sTargetnameToFind); + return INVALID_ENT_REFERENCE; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public int FindEntityByHammerID(int iHammerID) +{ + int iEntity = INVALID_ENT_REFERENCE; + while((iEntity = FindEntityByClassname(iEntity, "*")) != INVALID_ENT_REFERENCE) + { + if(GetEntProp(iEntity, Prop_Data, "m_iHammerID") == iHammerID) + { + return iEntity; + } + } + PrintToChatAll("[VScripts] Error! Could not find entity: #%d", iHammerID); + return INVALID_ENT_REFERENCE; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +stock int CreateEntityAtOrigin(const char[] classname, const float origin[3]) +{ + int entity = CreateEntityByName(classname); + + TeleportEntity(entity, origin, NULL_VECTOR, NULL_VECTOR); + + return entity; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +stock bool DispatchKeyFormat(int entity, const char[] key, const char[] value, any ...) +{ + char buffer[1024]; + VFormat(buffer, sizeof(buffer), value, 4); + + DispatchKeyValue(entity, key, buffer); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +stock void SpawnAndActivate(int entity) +{ + DispatchSpawn(entity); + ActivateEntity(entity); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +stock bool IsValidClient(int client) +{ + return (client > 0 && client <= MaxClients && IsClientInGame(client) && IsPlayerAlive(client)); +} \ No newline at end of file From 013ff290ee64d28ca3a29f91f570a9244c80c61e Mon Sep 17 00:00:00 2001 From: zaCade Date: Sat, 8 Dec 2018 17:46:50 +0100 Subject: [PATCH 03/52] VScripts: Clean code slightly, and remove 'version' check. --- ...ze_dreamin_v2.sp => vscript_ze_dreamin.sp} | 44 +++++-------------- 1 file changed, 12 insertions(+), 32 deletions(-) rename VScripts/scripting/{vscript_ze_dreamin_v2.sp => vscript_ze_dreamin.sp} (98%) diff --git a/VScripts/scripting/vscript_ze_dreamin_v2.sp b/VScripts/scripting/vscript_ze_dreamin.sp similarity index 98% rename from VScripts/scripting/vscript_ze_dreamin_v2.sp rename to VScripts/scripting/vscript_ze_dreamin.sp index b8d966a..a70737e 100644 --- a/VScripts/scripting/vscript_ze_dreamin_v2.sp +++ b/VScripts/scripting/vscript_ze_dreamin.sp @@ -1,26 +1,10 @@ -#pragma semicolon 1 - #include #include #include +#pragma semicolon 1 #pragma newdecls required -#define MAXTIMERS 128 - -/* STRINGS */ - -/* CONVARS */ - -/* HANDLES */ -Handle g_hTimers[MAXTIMERS] = {INVALID_HANDLE, ...}; - -/* BOOLS */ - -/* INTEGERS */ -int g_iTimerCount = 0; - - //---------------------------------------------------------------------------------------------------- // Purpose: //---------------------------------------------------------------------------------------------------- @@ -54,12 +38,14 @@ public void OnMapStart() //---------------------------------------------------------------------------------------------------- public void VerifyMap() { - char currentMap[64]; - GetCurrentMap(currentMap, sizeof(currentMap)); - if (strcmp(currentMap, "ze_dreamin_v2_1s_fix3", false) != 0) + char sCurrentMap[64]; + GetCurrentMap(sCurrentMap, sizeof(sCurrentMap)); + + if (strncmp(sCurrentMap, "ze_dreamin_", 11, false) != 0) { char sFilename[256]; GetPluginFilename(INVALID_HANDLE, sFilename, sizeof(sFilename)); + ServerCommand("sm plugins unload %s", sFilename); } } @@ -69,15 +55,6 @@ public void VerifyMap() //---------------------------------------------------------------------------------------------------- public void OnRoundStart(Event hEvent, const char[] sEvent, bool bDontBroadcast) { - - for (int i = 0; i <= (MAXTIMERS - 1); i++) - { - if (g_hTimers[i] != INVALID_HANDLE && CloseHandle(g_hTimers[i])) - g_hTimers[i] = INVALID_HANDLE; - } - g_iTimerCount = 0; - - int iEntity = INVALID_ENT_REFERENCE; iEntity = FindEntityByTargetName("reflect_logic"); @@ -629,13 +606,14 @@ public void Display(int amount) for (int j = 0; j <= amount; j++) { - iBackup --; + iBackup--; DispatchKeyFormat(iRelay, "OnTrigger", "text_sec,AddOutput,message %d,%d,-1", iBackup, j); - DispatchKeyFormat(iRelay, "OnTrigger", "text_sec,Display,,%d,-1",j); DispatchKeyFormat(iRelay, "OnTrigger", "seconds_left,Display,,%d,-1",j); + DispatchKeyFormat(iRelay, "OnTrigger", "text_sec,Display,,%d,-1",j); } - DispatchKeyFormat(iRelay, "OnTrigger", "text_sec,AddOutput,message ,%d,-1",amount + 1); + DispatchKeyFormat(iRelay, "OnTrigger", "seconds_left,AddOutput,message ,%d,-1",amount + 1); + DispatchKeyFormat(iRelay, "OnTrigger", "text_sec,AddOutput,message ,%d,-1",amount + 1); DispatchKeyFormat(iRelay, "OnTrigger", "!self,Kill,,%d,-1",amount + 2); SpawnAndActivate(iRelay); @@ -658,6 +636,7 @@ public int FindEntityByTargetName(const char[] sTargetnameToFind) return iEntity; } } + PrintToChatAll("[VScripts] Error! Could not find entity: %s", sTargetnameToFind); return INVALID_ENT_REFERENCE; } @@ -675,6 +654,7 @@ public int FindEntityByHammerID(int iHammerID) return iEntity; } } + PrintToChatAll("[VScripts] Error! Could not find entity: #%d", iHammerID); return INVALID_ENT_REFERENCE; } From 3e0b6eba5b5e95fb6564e360c766c1cfbee30fb8 Mon Sep 17 00:00:00 2001 From: zaCade Date: Sat, 8 Dec 2018 18:02:39 +0100 Subject: [PATCH 04/52] Add Includes. --- includes/multicolors.inc | 403 ++++++++++++ includes/multicolors/colors.inc | 944 +++++++++++++++++++++++++++ includes/multicolors/morecolors.inc | 953 ++++++++++++++++++++++++++++ 3 files changed, 2300 insertions(+) create mode 100644 includes/multicolors.inc create mode 100644 includes/multicolors/colors.inc create mode 100644 includes/multicolors/morecolors.inc diff --git a/includes/multicolors.inc b/includes/multicolors.inc new file mode 100644 index 0000000..e3d31c8 --- /dev/null +++ b/includes/multicolors.inc @@ -0,0 +1,403 @@ +#if defined _mutlicolors_included + #endinput +#endif +#define _mutlicolors_included + +#define MuCo_VERSION "2.0.1" +#define MuCo_LoopClients(%1) for(int %1 = 1; %1 <= MaxClients; %1++) + +#include +#include + +/* +* +* Credits: +* - Popoklopsi +* - Powerlord +* - exvel +* - Dr. McKay +* +* Based on stamm-colors +* - https://github.com/popoklopsi/Stamm/blob/master/include/stamm/stamm-colors.inc +* +*/ + + + +/* Global var to check whether colors are fixed or not */ +bool g_bCFixColors = false; + + + +/** + * Writes a message to a client with the correct stock for the game. + * + * @param client Client index. + * @param message Message (formatting rules). + * + * @noreturn + * @error If the client is not connected an error will be thrown. + */ +stock void CPrintToChat(int client, const char[] message, any ...) +{ + char buffer[MAX_MESSAGE_LENGTH]; + VFormat(buffer, sizeof(buffer), message, 3); + + if (!g_bCFixColors) + CFixColors(); + + if (!IsSource2009()) + C_PrintToChat(client, "%s", buffer); + else + MC_PrintToChat(client, "%s", buffer); +} + + + +/** + * Prints a message to all clients in the chat area. + * Supports color tags. + * + * @param client Client index. + * @param message Message (formatting rules) + * @return No return + */ +stock void CPrintToChatAll(const char[] message, any ...) +{ + char buffer[MAX_MESSAGE_LENGTH]; + VFormat(buffer, sizeof(buffer), message, 2); + + if (!g_bCFixColors) + CFixColors(); + + if (!IsSource2009()) + C_PrintToChatAll("%s", buffer); + else + MC_PrintToChatAll("%s", buffer); +} + +/** + * Writes a message to all of a client's observers. + * + * @param target Client index. + * @param message Message (formatting rules). + * + * @noreturn + */ +stock void CPrintToChatObservers(int target, const char[] message, any ...) +{ + char buffer[MAX_MESSAGE_LENGTH]; + VFormat(buffer, sizeof(buffer), message, 3); + + if (!g_bCFixColors) + CFixColors(); + + for(int client = 1; client <= MaxClients; client++) + { + if(IsClientInGame(client) && !IsPlayerAlive(client) && !IsFakeClient(client)) + { + int observee = GetEntPropEnt(client, Prop_Send, "m_hObserverTarget"); + int ObserverMode = GetEntProp(client, Prop_Send, "m_iObserverMode"); + + if(observee == target && (ObserverMode == 4 || ObserverMode == 5)) + { + CPrintToChat(client, buffer); + } + } + } +} + + +/** + * Writes a message to a client with the correct stock for the game. + * + * @param client Client index. + * @param author Author index. + * @param message Message (formatting rules). + * + * @noreturn + * @error If the client is not connected an error will be thrown. + */ +stock void CPrintToChatEx(int client, int author, const char[] message, any ...) +{ + char buffer[MAX_MESSAGE_LENGTH]; + VFormat(buffer, sizeof(buffer), message, 4); + + if (!g_bCFixColors) + CFixColors(); + + if (!IsSource2009()) + C_PrintToChatEx(client, author, "%s", buffer); + else + MC_PrintToChatEx(client, author, "%s", buffer); +} + +/** + * Writes a message to all clients with the correct stock for the game. + * + * @param author Author index. + * @param message Message (formatting rules). + * + * @noreturn + */ +stock void CPrintToChatAllEx(int author, const char[] message, any ...) +{ + char buffer[MAX_MESSAGE_LENGTH]; + VFormat(buffer, sizeof(buffer), message, 3); + + if (!g_bCFixColors) + CFixColors(); + + if (!IsSource2009()) + C_PrintToChatAllEx(author, "%s", buffer); + else + MC_PrintToChatAllEx(author, "%s", buffer); +} + +/** + * Writes a message to all of a client's observers with the correct + * game stock. + * + * @param target Client index. + * @param message Message (formatting rules). + * + * @noreturn + */ +stock void CPrintToChatObserversEx(int target, const char[] message, any ...) +{ + char buffer[MAX_MESSAGE_LENGTH]; + VFormat(buffer, sizeof(buffer), message, 3); + + if (!g_bCFixColors) + CFixColors(); + + for(int client = 1; client <= MaxClients; client++) + { + if(IsClientInGame(client) && !IsPlayerAlive(client) && !IsFakeClient(client)) + { + int observee = GetEntPropEnt(client, Prop_Send, "m_hObserverTarget"); + int ObserverMode = GetEntProp(client, Prop_Send, "m_iObserverMode"); + + if(observee == target && (ObserverMode == 4 || ObserverMode == 5)) + { + CPrintToChatEx(client, target, buffer); + } + } + } +} + + +/** + * Replies to a command with colors + * + * @param client Client to reply to + * @param message Message (formatting rules) + * @noreturn + */ +stock void CReplyToCommand(int author, const char[] message, any ...) +{ + char buffer[MAX_MESSAGE_LENGTH]; + VFormat(buffer, sizeof(buffer), message, 3); + + if (!g_bCFixColors) + CFixColors(); + + if (!IsSource2009()) + C_ReplyToCommand(author, "%s", buffer); + else + MC_ReplyToCommand(author, "%s", buffer); +} + + + +/** + * Replies to a command with colors + * + * @param client Client to reply to + * @param author Client to use for {teamcolor} + * @param message Message (formatting rules) + * @noreturn + */ + stock void CReplyToCommandEx(int client, int author, const char[] message, any ...) +{ + char buffer[MAX_MESSAGE_LENGTH]; + + VFormat(buffer, sizeof(buffer), message, 4); + + if (!g_bCFixColors) + CFixColors(); + + if (!IsSource2009()) + C_ReplyToCommandEx(client, author, "%s", buffer); + else + MC_ReplyToCommandEx(client, author, "%s", buffer); +} + + + +/** + * Displays usage of an admin command to users depending on the + * setting of the sm_show_activity cvar. + * + * This version does not display a message to the originating client + * if used from chat triggers or menus. If manual replies are used + * for these cases, then this function will suffice. Otherwise, + * CShowActivity2() is slightly more useful. + * Supports color tags. + * + * @param client Client index doing the action, or 0 for server. + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @noreturn + * @error + */ +stock void CShowActivity(int author, const char[] message, any ...) +{ + char buffer[MAX_MESSAGE_LENGTH]; + VFormat(buffer, sizeof(buffer), message, 3); + + if (!g_bCFixColors) + CFixColors(); + + if (!IsSource2009()) + C_ShowActivity(author, "%s", buffer); + else + MC_ShowActivity(author, "%s", buffer); +} + + +/** + * Same as C_ShowActivity(), except the tag parameter is used instead of "[SM] " (note that you must supply any spacing). + * Supports color tags. + * + * @param client Client index doing the action, or 0 for server. + * @param tags Tag to display with. + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @noreturn + * @error + */ +stock void CShowActivityEx(int author, const char[] tag, const char[] message, any ...) +{ + char buffer[MAX_MESSAGE_LENGTH]; + VFormat(buffer, sizeof(buffer), message, 4); + + if (!g_bCFixColors) + CFixColors(); + + if (!IsSource2009()) + C_ShowActivityEx(author, tag, "%s", buffer); + else + MC_ShowActivityEx(author, tag, "%s", buffer); +} + + + +/** + * Displays usage of an admin command to users depending on the setting of the sm_show_activity cvar. + * All users receive a message in their chat text, except for the originating client, + * who receives the message based on the current ReplySource. + * Supports color tags. + * + * @param client Client index doing the action, or 0 for server. + * @param tags Tag to prepend to the message. + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @noreturn + * @error + */ + stock void CShowActivity2(int author, const char[] tag, const char[] message, any ...) +{ + char buffer[MAX_MESSAGE_LENGTH]; + VFormat(buffer, sizeof(buffer), message, 4); + + if (!g_bCFixColors) + CFixColors(); + + if (!IsSource2009()) + C_ShowActivity2(author, tag, "%s", buffer); + else + MC_ShowActivity2(author, tag, "%s", buffer); +} + + + +/** + * Replaces color tags in a string with color codes + * + * @param message String. + * @param maxlength Maximum length of the string buffer. + * + * @noreturn + */ +stock void CFormatColor(char[] message, int maxlength, int author = -1) +{ + if (!g_bCFixColors) + CFixColors(); + + if (!IsSource2009()) + { + if (author == 0) + author = -1; + + C_Format(message, maxlength, author); + } + else + { + if (author == -1) + author = 0; + + MC_ReplaceColorCodes(message, author, false, maxlength); + } +} + + + +/** + * Removes color tags from a message + * + * @param message Message to remove tags from + * @param maxlen Maximum buffer length + * @noreturn + */ +stock void CRemoveTags(char[] message, int maxlen) +{ + if (!IsSource2009()) + { + C_RemoveTags(message, maxlen); + } + else + { + MC_RemoveTags(message, maxlen); + } +} + + + +/** + * Fixes missing Lightgreen color. + * + * @noreturn + */ +stock void CFixColors() +{ + g_bCFixColors = true; + + // Replace lightgreen if not exists + if (!C_ColorAllowed(Color_Lightgreen)) + { + if (C_ColorAllowed(Color_Lime)) + C_ReplaceColor(Color_Lightgreen, Color_Lime); + else if (C_ColorAllowed(Color_Olive)) + C_ReplaceColor(Color_Lightgreen, Color_Olive); + } +} + +stock bool IsSource2009() +{ + if(GetEngineVersion() == Engine_CSS || GetEngineVersion() == Engine_HL2DM || GetEngineVersion() == Engine_DODS || GetEngineVersion() == Engine_TF2) + { + return true; + } + return false; +} diff --git a/includes/multicolors/colors.inc b/includes/multicolors/colors.inc new file mode 100644 index 0000000..17bf1b1 --- /dev/null +++ b/includes/multicolors/colors.inc @@ -0,0 +1,944 @@ +/************************************************************************** + * * + * Colored Chat Functions * + * Author: exvel, Editor: Popoklopsi, Powerlord, Bara * + * Version: 2.0.0-MC * + * * + **************************************************************************/ + + +#if defined _colors_included + #endinput +#endif +#define _colors_included + +#define MAX_MESSAGE_LENGTH 250 +#define MAX_COLORS 18 + +#define SERVER_INDEX 0 +#define NO_INDEX -1 +#define NO_PLAYER -2 + +enum C_Colors +{ + Color_Default = 0, + Color_Darkred, + Color_Green, + Color_Lightgreen, + Color_Red, + Color_Blue, + Color_Olive, + Color_Lime, + Color_Lightred, + Color_Purple, + Color_Grey, + Color_Orange, + Color_Bluegrey, + Color_Lightblue, + Color_Darkblue, + Color_Grey2, + Color_Orchid, + Color_Lightred2 +} + +/* C_Colors' properties */ +char C_Tag[][] = {"{default}", "{darkred}", "{green}", "{lightgreen}", "{red}", "{blue}", "{olive}", "{lime}", "{lightred}", "{purple}", "{grey}", "{orange}", "{bluegrey}", "{lightblue}", "{darkblue}", "{grey2}", "{orchid}", "{lightred2}"}; +char C_TagCode[][] = {"\x01", "\x02", "\x04", "\x03", "\x03", "\x03", "\x05", "\x06", "\x07", "\x03", "\x08", "\x09", "\x0A", "\x0B", "\x0C", "\x0D", "\x0E", "\x0F"}; +bool C_TagReqSayText2[] = {false, false, false, true, true, true, false, false, false, false, false, false, false, false, false, false, false, false}; +bool C_EventIsHooked = false; +bool C_SkipList[MAXPLAYERS+1] = {false,...}; + +/* Game default profile */ +bool C_Profile_Colors[] = {true, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false}; +int C_Profile_TeamIndex[] = {NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX, NO_INDEX}; +bool C_Profile_SayText2 = false; + +static Handle sm_show_activity = null; + +/** + * Prints a message to a specific client in the chat area. + * Supports color tags. + * + * @param client Client index. + * @param szMessage Message (formatting rules). + * @return No return + * + * On error/Errors: If the client is not connected an error will be thrown. + */ +stock void C_PrintToChat(int client, const char[] szMessage, any ...) +{ + if (client <= 0 || client > MaxClients) + ThrowError("Invalid client index %d", client); + + if (!IsClientInGame(client)) + ThrowError("Client %d is not in game", client); + + char szBuffer[MAX_MESSAGE_LENGTH]; + char szCMessage[MAX_MESSAGE_LENGTH]; + + SetGlobalTransTarget(client); + + Format(szBuffer, sizeof(szBuffer), "\x01%s", szMessage); + VFormat(szCMessage, sizeof(szCMessage), szBuffer, 3); + + int index = C_Format(szCMessage, sizeof(szCMessage)); + + if (index == NO_INDEX) + PrintToChat(client, "%s", szCMessage); + else + C_SayText2(client, index, szCMessage); +} + +/** + * Reples to a message in a command. A client index of 0 will use PrintToServer(). + * If the command was from the console, PrintToConsole() is used. If the command was from chat, C_PrintToChat() is used. + * Supports color tags. + * + * @param client Client index, or 0 for server. + * @param szMessage Formatting rules. + * @param ... Variable number of format parameters. + * @return No return + * + * On error/Errors: If the client is not connected or invalid. + */ +stock void C_ReplyToCommand(int client, const char[] szMessage, any ...) +{ + char szCMessage[MAX_MESSAGE_LENGTH]; + SetGlobalTransTarget(client); + VFormat(szCMessage, sizeof(szCMessage), szMessage, 3); + + if (client == 0) + { + C_RemoveTags(szCMessage, sizeof(szCMessage)); + PrintToServer("%s", szCMessage); + } + else if (GetCmdReplySource() == SM_REPLY_TO_CONSOLE) + { + C_RemoveTags(szCMessage, sizeof(szCMessage)); + PrintToConsole(client, "%s", szCMessage); + } + else + { + C_PrintToChat(client, "%s", szCMessage); + } +} + +/** + * Reples to a message in a command. A client index of 0 will use PrintToServer(). + * If the command was from the console, PrintToConsole() is used. If the command was from chat, C_PrintToChat() is used. + * Supports color tags. + * + * @param client Client index, or 0 for server. + * @param author Author index whose color will be used for teamcolor tag. + * @param szMessage Formatting rules. + * @param ... Variable number of format parameters. + * @return No return + * + * On error/Errors: If the client is not connected or invalid. + */ +stock void C_ReplyToCommandEx(int client, int author, const char[] szMessage, any ...) +{ + char szCMessage[MAX_MESSAGE_LENGTH]; + SetGlobalTransTarget(client); + VFormat(szCMessage, sizeof(szCMessage), szMessage, 4); + + if (client == 0) + { + C_RemoveTags(szCMessage, sizeof(szCMessage)); + PrintToServer("%s", szCMessage); + } + else if (GetCmdReplySource() == SM_REPLY_TO_CONSOLE) + { + C_RemoveTags(szCMessage, sizeof(szCMessage)); + PrintToConsole(client, "%s", szCMessage); + } + else + { + C_PrintToChatEx(client, author, "%s", szCMessage); + } +} + +/** + * Prints a message to all clients in the chat area. + * Supports color tags. + * + * @param client Client index. + * @param szMessage Message (formatting rules) + * @return No return + */ +stock void C_PrintToChatAll(const char[] szMessage, any ...) +{ + char szBuffer[MAX_MESSAGE_LENGTH]; + + MuCo_LoopClients(i) + { + if (i > 0 && IsClientInGame(i) && !IsFakeClient(i) && !C_SkipList[i]) + { + SetGlobalTransTarget(i); + VFormat(szBuffer, sizeof(szBuffer), szMessage, 2); + + C_PrintToChat(i, "%s", szBuffer); + } + + C_SkipList[i] = false; + } +} + +/** + * Prints a message to a specific client in the chat area. + * Supports color tags and teamcolor tag. + * + * @param client Client index. + * @param author Author index whose color will be used for teamcolor tag. + * @param szMessage Message (formatting rules). + * @return No return + * + * On error/Errors: If the client or author are not connected an error will be thrown. + */ +stock void C_PrintToChatEx(int client, int author, const char[] szMessage, any ...) +{ + if (client <= 0 || client > MaxClients) + ThrowError("Invalid client index %d", client); + + if (!IsClientInGame(client)) + ThrowError("Client %d is not in game", client); + + if (author < 0 || author > MaxClients) + ThrowError("Invalid client index %d", author); + + char szBuffer[MAX_MESSAGE_LENGTH]; + char szCMessage[MAX_MESSAGE_LENGTH]; + + SetGlobalTransTarget(client); + + Format(szBuffer, sizeof(szBuffer), "\x01%s", szMessage); + VFormat(szCMessage, sizeof(szCMessage), szBuffer, 4); + + int index = C_Format(szCMessage, sizeof(szCMessage), author); + + if (index == NO_INDEX) + PrintToChat(client, "%s", szCMessage); + else + C_SayText2(client, author, szCMessage); +} + +/** + * Prints a message to all clients in the chat area. + * Supports color tags and teamcolor tag. + * + * @param author Author index whos color will be used for teamcolor tag. + * @param szMessage Message (formatting rules). + * @return No return + * + * On error/Errors: If the author is not connected an error will be thrown. + */ +stock void C_PrintToChatAllEx(int author, const char[] szMessage, any ...) +{ + if (author < 0 || author > MaxClients) + ThrowError("Invalid client index %d", author); + + if (!IsClientInGame(author)) + ThrowError("Client %d is not in game", author); + + char szBuffer[MAX_MESSAGE_LENGTH]; + + MuCo_LoopClients(i) + { + if (i > 0 && IsClientInGame(i) && !IsFakeClient(i) && !C_SkipList[i]) + { + SetGlobalTransTarget(i); + VFormat(szBuffer, sizeof(szBuffer), szMessage, 3); + + C_PrintToChatEx(i, author, "%s", szBuffer); + } + + C_SkipList[i] = false; + } +} + +/** + * Removes color tags from the string. + * + * @param szMessage String. + * @return No return + */ +stock void C_RemoveTags(char[] szMessage, int maxlength) +{ + for (int i = 0; i < MAX_COLORS; i++) + ReplaceString(szMessage, maxlength, C_Tag[i], "", false); + + ReplaceString(szMessage, maxlength, "{teamcolor}", "", false); +} + +/** + * Checks whether a color is allowed or not + * + * @param tag Color Tag. + * @return True when color is supported, otherwise false + */ +stock bool C_ColorAllowed(C_Colors color) +{ + if (!C_EventIsHooked) + { + C_SetupProfile(); + + C_EventIsHooked = true; + } + + return C_Profile_Colors[color]; +} + +/** + * Replace the color with another color + * Handle with care! + * + * @param color color to replace. + * @param newColor color to replace with. + * @noreturn + */ +stock void C_ReplaceColor(C_Colors color, C_Colors newColor) +{ + if (!C_EventIsHooked) + { + C_SetupProfile(); + + C_EventIsHooked = true; + } + + C_Profile_Colors[color] = C_Profile_Colors[newColor]; + C_Profile_TeamIndex[color] = C_Profile_TeamIndex[newColor]; + + C_TagReqSayText2[color] = C_TagReqSayText2[newColor]; + Format(C_TagCode[color], sizeof(C_TagCode[]), C_TagCode[newColor]); +} + +/** + * This function should only be used right in front of + * C_PrintToChatAll or C_PrintToChatAllEx and it tells + * to those funcions to skip specified client when printing + * message to all clients. After message is printed client will + * no more be skipped. + * + * @param client Client index + * @return No return + */ +stock void C_SkipNextClient(int client) +{ + if (client <= 0 || client > MaxClients) + ThrowError("Invalid client index %d", client); + + C_SkipList[client] = true; +} + +/** + * Replaces color tags in a string with color codes + * + * @param szMessage String. + * @param maxlength Maximum length of the string buffer. + * @return Client index that can be used for SayText2 author index + * + * On error/Errors: If there is more then one team color is used an error will be thrown. + */ +stock int C_Format(char[] szMessage, int maxlength, int author = NO_INDEX) +{ + /* Hook event for auto profile setup on map start */ + if (!C_EventIsHooked) + { + C_SetupProfile(); + HookEvent("server_spawn", C_Event_MapStart, EventHookMode_PostNoCopy); + + C_EventIsHooked = true; + } + + int iRandomPlayer = NO_INDEX; + + // On CS:GO set invisible precolor + if (GetEngineVersion() == Engine_CSGO) + { + Format(szMessage, maxlength, " %s", szMessage); + } + + /* If author was specified replace {teamcolor} tag */ + if (author != NO_INDEX) + { + if (C_Profile_SayText2) + { + ReplaceString(szMessage, maxlength, "{teamcolor}", "\x03", false); + + iRandomPlayer = author; + } + /* If saytext2 is not supported by game replace {teamcolor} with green tag */ + else + ReplaceString(szMessage, maxlength, "{teamcolor}", C_TagCode[Color_Green], false); + } + else + ReplaceString(szMessage, maxlength, "{teamcolor}", "", false); + + /* For other color tags we need a loop */ + for (int i = 0; i < MAX_COLORS; i++) + { + /* If tag not found - skip */ + if (StrContains(szMessage, C_Tag[i], false) == -1) + continue; + + /* If tag is not supported by game replace it with green tag */ + else if (!C_Profile_Colors[i]) + ReplaceString(szMessage, maxlength, C_Tag[i], C_TagCode[Color_Green], false); + + /* If tag doesn't need saytext2 simply replace */ + else if (!C_TagReqSayText2[i]) + ReplaceString(szMessage, maxlength, C_Tag[i], C_TagCode[i], false); + + /* Tag needs saytext2 */ + else + { + /* If saytext2 is not supported by game replace tag with green tag */ + if (!C_Profile_SayText2) + ReplaceString(szMessage, maxlength, C_Tag[i], C_TagCode[Color_Green], false); + + /* Game supports saytext2 */ + else + { + /* If random player for tag wasn't specified replace tag and find player */ + if (iRandomPlayer == NO_INDEX) + { + /* Searching for valid client for tag */ + iRandomPlayer = C_FindRandomPlayerByTeam(C_Profile_TeamIndex[i]); + + /* If player not found replace tag with green color tag */ + if (iRandomPlayer == NO_PLAYER) + ReplaceString(szMessage, maxlength, C_Tag[i], C_TagCode[Color_Green], false); + + /* If player was found simply replace */ + else + ReplaceString(szMessage, maxlength, C_Tag[i], C_TagCode[i], false); + + } + /* If found another team color tag throw error */ + else + { + //ReplaceString(szMessage, maxlength, C_Tag[i], ""); + ThrowError("Using two team colors in one message is not allowed"); + } + } + + } + } + + return iRandomPlayer; +} + +/** + * Founds a random player with specified team + * + * @param color_team Client team. + * @return Client index or NO_PLAYER if no player found + */ +stock int C_FindRandomPlayerByTeam(int color_team) +{ + if (color_team == SERVER_INDEX) + return 0; + else + { + MuCo_LoopClients(i) + { + if (i > 0 && IsClientInGame(i) && GetClientTeam(i) == color_team) + return i; + } + } + + return NO_PLAYER; +} + +/** + * Sends a SayText2 usermessage to a client + * + * @param szMessage Client index + * @param maxlength Author index + * @param szMessage Message + * @return No return. + */ +stock void C_SayText2(int client, int author, const char[] szMessage) +{ + Handle hBuffer = StartMessageOne("SayText2", client, USERMSG_RELIABLE|USERMSG_BLOCKHOOKS); + + if(GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available && GetUserMessageType() == UM_Protobuf) + { + PbSetInt(hBuffer, "ent_idx", author); + PbSetBool(hBuffer, "chat", true); + PbSetString(hBuffer, "msg_name", szMessage); + PbAddString(hBuffer, "params", ""); + PbAddString(hBuffer, "params", ""); + PbAddString(hBuffer, "params", ""); + PbAddString(hBuffer, "params", ""); + } + else + { + BfWriteByte(hBuffer, author); + BfWriteByte(hBuffer, true); + BfWriteString(hBuffer, szMessage); + } + + EndMessage(); +} + +/** + * Creates game color profile + * This function must be edited if you want to add more games support + * + * @return No return. + */ +stock void C_SetupProfile() +{ + EngineVersion engine = GetEngineVersion(); + + if (engine == Engine_CSS) + { + C_Profile_Colors[Color_Lightgreen] = true; + C_Profile_Colors[Color_Red] = true; + C_Profile_Colors[Color_Blue] = true; + C_Profile_Colors[Color_Olive] = true; + C_Profile_TeamIndex[Color_Lightgreen] = SERVER_INDEX; + C_Profile_TeamIndex[Color_Red] = 2; + C_Profile_TeamIndex[Color_Blue] = 3; + C_Profile_SayText2 = true; + } + else if (engine == Engine_CSGO) + { + C_Profile_Colors[Color_Red] = true; + C_Profile_Colors[Color_Blue] = true; + C_Profile_Colors[Color_Olive] = true; + C_Profile_Colors[Color_Darkred] = true; + C_Profile_Colors[Color_Lime] = true; + C_Profile_Colors[Color_Lightred] = true; + C_Profile_Colors[Color_Purple] = true; + C_Profile_Colors[Color_Grey] = true; + C_Profile_Colors[Color_Orange] = true; + C_Profile_Colors[Color_Bluegrey] = true; + C_Profile_Colors[Color_Lightblue] = true; + C_Profile_Colors[Color_Darkblue] = true; + C_Profile_Colors[Color_Grey2] = true; + C_Profile_Colors[Color_Orchid] = true; + C_Profile_Colors[Color_Lightred2] = true; + C_Profile_TeamIndex[Color_Red] = 2; + C_Profile_TeamIndex[Color_Blue] = 3; + C_Profile_SayText2 = true; + } + else if (engine == Engine_TF2) + { + C_Profile_Colors[Color_Lightgreen] = true; + C_Profile_Colors[Color_Red] = true; + C_Profile_Colors[Color_Blue] = true; + C_Profile_Colors[Color_Olive] = true; + C_Profile_TeamIndex[Color_Lightgreen] = SERVER_INDEX; + C_Profile_TeamIndex[Color_Red] = 2; + C_Profile_TeamIndex[Color_Blue] = 3; + C_Profile_SayText2 = true; + } + else if (engine == Engine_Left4Dead || engine == Engine_Left4Dead2) + { + C_Profile_Colors[Color_Lightgreen] = true; + C_Profile_Colors[Color_Red] = true; + C_Profile_Colors[Color_Blue] = true; + C_Profile_Colors[Color_Olive] = true; + C_Profile_TeamIndex[Color_Lightgreen] = SERVER_INDEX; + C_Profile_TeamIndex[Color_Red] = 3; + C_Profile_TeamIndex[Color_Blue] = 2; + C_Profile_SayText2 = true; + } + else if (engine == Engine_HL2DM) + { + /* hl2mp profile is based on mp_teamplay convar */ + if (GetConVarBool(FindConVar("mp_teamplay"))) + { + C_Profile_Colors[Color_Red] = true; + C_Profile_Colors[Color_Blue] = true; + C_Profile_Colors[Color_Olive] = true; + C_Profile_TeamIndex[Color_Red] = 3; + C_Profile_TeamIndex[Color_Blue] = 2; + C_Profile_SayText2 = true; + } + else + { + C_Profile_SayText2 = false; + C_Profile_Colors[Color_Olive] = true; + } + } + else if (engine == Engine_DODS) + { + C_Profile_Colors[Color_Olive] = true; + C_Profile_SayText2 = false; + } + /* Profile for other games */ + else + { + if (GetUserMessageId("SayText2") == INVALID_MESSAGE_ID) + { + C_Profile_SayText2 = false; + } + else + { + C_Profile_Colors[Color_Red] = true; + C_Profile_Colors[Color_Blue] = true; + C_Profile_TeamIndex[Color_Red] = 2; + C_Profile_TeamIndex[Color_Blue] = 3; + C_Profile_SayText2 = true; + } + } +} + +public Action C_Event_MapStart(Event event, const char[] name, bool dontBroadcast) +{ + C_SetupProfile(); + + MuCo_LoopClients(i) + C_SkipList[i] = false; +} + +/** + * Displays usage of an admin command to users depending on the + * setting of the sm_show_activity cvar. + * + * This version does not display a message to the originating client + * if used from chat triggers or menus. If manual replies are used + * for these cases, then this function will suffice. Otherwise, + * C_ShowActivity2() is slightly more useful. + * Supports color tags. + * + * @param client Client index doing the action, or 0 for server. + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @noreturn + * @error + */ +stock int C_ShowActivity(int client, const char[] format, any ...) +{ + if (sm_show_activity == null) + sm_show_activity = FindConVar("sm_show_activity"); + + char tag[] = "[SM] "; + + char szBuffer[MAX_MESSAGE_LENGTH]; + //char szCMessage[MAX_MESSAGE_LENGTH]; + int value = GetConVarInt(sm_show_activity); + ReplySource replyto = GetCmdReplySource(); + + char name[MAX_NAME_LENGTH] = "Console"; + char sign[MAX_NAME_LENGTH] = "ADMIN"; + bool display_in_chat = false; + if (client != 0) + { + if (client < 0 || client > MaxClients || !IsClientConnected(client)) + ThrowError("Client index %d is invalid", client); + + GetClientName(client, name, sizeof(name)); + AdminId id = GetUserAdmin(client); + if (id == INVALID_ADMIN_ID + || !GetAdminFlag(id, Admin_Generic, Access_Effective)) + { + sign = "PLAYER"; + } + + /* Display the message to the client? */ + if (replyto == SM_REPLY_TO_CONSOLE) + { + SetGlobalTransTarget(client); + VFormat(szBuffer, sizeof(szBuffer), format, 3); + + C_RemoveTags(szBuffer, sizeof(szBuffer)); + PrintToConsole(client, "%s%s\n", tag, szBuffer); + display_in_chat = true; + } + } + else + { + SetGlobalTransTarget(LANG_SERVER); + VFormat(szBuffer, sizeof(szBuffer), format, 3); + + C_RemoveTags(szBuffer, sizeof(szBuffer)); + PrintToServer("%s%s\n", tag, szBuffer); + } + + if (!value) + { + return 1; + } + + MuCo_LoopClients(i) + { + if (i == 0 + || !IsClientInGame(i) + || IsFakeClient(i) + || (display_in_chat && i == client)) + { + continue; + } + AdminId id = GetUserAdmin(i); + SetGlobalTransTarget(i); + if (id == INVALID_ADMIN_ID + || !GetAdminFlag(id, Admin_Generic, Access_Effective)) + { + /* Treat this as a normal user. */ + if ((value & 1) | (value & 2)) + { + char newsign[MAX_NAME_LENGTH]; + newsign = sign; + if ((value & 2) || (i == client)) + { + newsign = name; + } + VFormat(szBuffer, sizeof(szBuffer), format, 3); + + C_PrintToChatEx(i, client, "%s%s: %s", tag, newsign, szBuffer); + } + } + else + { + /* Treat this as an admin user */ + bool is_root = GetAdminFlag(id, Admin_Root, Access_Effective); + if ((value & 4) + || (value & 8) + || ((value & 16) && is_root)) + { + char newsign[MAX_NAME_LENGTH]; + newsign = sign; + if ((value & 8) || ((value & 16) && is_root) || (i == client)) + { + newsign = name; + } + VFormat(szBuffer, sizeof(szBuffer), format, 3); + + C_PrintToChatEx(i, client, "%s%s: %s", tag, newsign, szBuffer); + } + } + } + + return 1; +} + +/** + * Same as C_ShowActivity(), except the tag parameter is used instead of "[SM] " (note that you must supply any spacing). + * Supports color tags. + * + * @param client Client index doing the action, or 0 for server. + * @param tags Tag to display with. + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @noreturn + * @error + */ +stock int C_ShowActivityEx(int client, const char[] tag, const char[] format, any ...) +{ + if (sm_show_activity == null) + sm_show_activity = FindConVar("sm_show_activity"); + + char szBuffer[MAX_MESSAGE_LENGTH]; + //char szCMessage[MAX_MESSAGE_LENGTH]; + int value = GetConVarInt(sm_show_activity); + ReplySource replyto = GetCmdReplySource(); + + char name[MAX_NAME_LENGTH] = "Console"; + char sign[MAX_NAME_LENGTH] = "ADMIN"; + bool display_in_chat = false; + if (client != 0) + { + if (client < 0 || client > MaxClients || !IsClientConnected(client)) + ThrowError("Client index %d is invalid", client); + + GetClientName(client, name, sizeof(name)); + AdminId id = GetUserAdmin(client); + if (id == INVALID_ADMIN_ID + || !GetAdminFlag(id, Admin_Generic, Access_Effective)) + { + sign = "PLAYER"; + } + + /* Display the message to the client? */ + if (replyto == SM_REPLY_TO_CONSOLE) + { + SetGlobalTransTarget(client); + VFormat(szBuffer, sizeof(szBuffer), format, 4); + + C_RemoveTags(szBuffer, sizeof(szBuffer)); + PrintToConsole(client, "%s%s\n", tag, szBuffer); + display_in_chat = true; + } + } + else + { + SetGlobalTransTarget(LANG_SERVER); + VFormat(szBuffer, sizeof(szBuffer), format, 4); + + C_RemoveTags(szBuffer, sizeof(szBuffer)); + PrintToServer("%s%s\n", tag, szBuffer); + } + + if (!value) + { + return 1; + } + + MuCo_LoopClients(i) + { + if (i == 0 + || !IsClientInGame(i) + || IsFakeClient(i) + || (display_in_chat && i == client)) + { + continue; + } + AdminId id = GetUserAdmin(i); + SetGlobalTransTarget(i); + if (id == INVALID_ADMIN_ID + || !GetAdminFlag(id, Admin_Generic, Access_Effective)) + { + /* Treat this as a normal user. */ + if ((value & 1) | (value & 2)) + { + char newsign[MAX_NAME_LENGTH]; + newsign = sign; + if ((value & 2) || (i == client)) + { + newsign = name; + } + VFormat(szBuffer, sizeof(szBuffer), format, 4); + + C_PrintToChatEx(i, client, "%s%s: %s", tag, newsign, szBuffer); + } + } + else + { + /* Treat this as an admin user */ + bool is_root = GetAdminFlag(id, Admin_Root, Access_Effective); + if ((value & 4) + || (value & 8) + || ((value & 16) && is_root)) + { + char newsign[MAX_NAME_LENGTH]; + newsign = sign; + if ((value & 8) || ((value & 16) && is_root) || (i == client)) + { + newsign = name; + } + VFormat(szBuffer, sizeof(szBuffer), format, 4); + + C_PrintToChatEx(i, client, "%s%s: %s", tag, newsign, szBuffer); + } + } + } + + return 1; +} + +/** + * Displays usage of an admin command to users depending on the setting of the sm_show_activity cvar. + * All users receive a message in their chat text, except for the originating client, + * who receives the message based on the current ReplySource. + * Supports color tags. + * + * @param client Client index doing the action, or 0 for server. + * @param tags Tag to prepend to the message. + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @noreturn + * @error + */ +stock int C_ShowActivity2(int client, const char[] tag, const char[] format, any ...) +{ + if (sm_show_activity == null) + sm_show_activity = FindConVar("sm_show_activity"); + + char szBuffer[MAX_MESSAGE_LENGTH]; + //char szCMessage[MAX_MESSAGE_LENGTH]; + int value = GetConVarInt(sm_show_activity); + // ReplySource replyto = GetCmdReplySource(); + + char name[MAX_NAME_LENGTH] = "Console"; + char sign[MAX_NAME_LENGTH] = "ADMIN"; + if (client != 0) + { + if (client < 0 || client > MaxClients || !IsClientConnected(client)) + ThrowError("Client index %d is invalid", client); + + GetClientName(client, name, sizeof(name)); + AdminId id = GetUserAdmin(client); + if (id == INVALID_ADMIN_ID + || !GetAdminFlag(id, Admin_Generic, Access_Effective)) + { + sign = "PLAYER"; + } + + SetGlobalTransTarget(client); + VFormat(szBuffer, sizeof(szBuffer), format, 4); + + /* We don't display directly to the console because the chat text + * simply gets added to the console, so we don't want it to print + * twice. + */ + C_PrintToChatEx(client, client, "%s%s", tag, szBuffer); + } + else + { + SetGlobalTransTarget(LANG_SERVER); + VFormat(szBuffer, sizeof(szBuffer), format, 4); + + C_RemoveTags(szBuffer, sizeof(szBuffer)); + PrintToServer("%s%s\n", tag, szBuffer); + } + + if (!value) + { + return 1; + } + + MuCo_LoopClients(i) + { + if (i == 0 + || !IsClientInGame(i) + || IsFakeClient(i) + || i == client) + { + continue; + } + AdminId id = GetUserAdmin(i); + SetGlobalTransTarget(i); + if (id == INVALID_ADMIN_ID + || !GetAdminFlag(id, Admin_Generic, Access_Effective)) + { + /* Treat this as a normal user. */ + if ((value & 1) | (value & 2)) + { + char newsign[MAX_NAME_LENGTH]; + newsign = sign; + if ((value & 2)) + { + newsign = name; + } + VFormat(szBuffer, sizeof(szBuffer), format, 4); + + C_PrintToChatEx(i, client, "%s%s: %s", tag, newsign, szBuffer); + } + } + else + { + /* Treat this as an admin user */ + bool is_root = GetAdminFlag(id, Admin_Root, Access_Effective); + if ((value & 4) + || (value & 8) + || ((value & 16) && is_root)) + { + char newsign[MAX_NAME_LENGTH]; + newsign = sign; + if ((value & 8) || ((value & 16) && is_root)) + { + newsign = name; + } + VFormat(szBuffer, sizeof(szBuffer), format, 4); + + C_PrintToChatEx(i, client, "%s%s: %s", tag, newsign, szBuffer); + } + } + } + + return 1; +} diff --git a/includes/multicolors/morecolors.inc b/includes/multicolors/morecolors.inc new file mode 100644 index 0000000..ecf7413 --- /dev/null +++ b/includes/multicolors/morecolors.inc @@ -0,0 +1,953 @@ +// MOAR COLORS +// By Dr. McKay +// Inspired by: https://forums.alliedmods.net/showthread.php?t=96831 + +#if defined _more_colors_included + #endinput +#endif +#define _more_colors_included + +#include + +#define MORE_COLORS_VERSION "2.0.0-MC" +#define MC_MAX_MESSAGE_LENGTH 256 +#define MAX_BUFFER_LENGTH (MC_MAX_MESSAGE_LENGTH * 4) + +#define MCOLOR_RED 0xFF4040 +#define MCOLOR_BLUE 0x99CCFF +#define MCOLOR_GRAY 0xCCCCCC +#define MCOLOR_GREEN 0x3EFF3E + +#define MC_GAME_DODS 0 + +bool MC_SkipList[MAXPLAYERS + 1]; +Handle MC_Trie; +int MC_TeamColors[][] = {{0xCCCCCC, 0x4D7942, 0xFF4040}}; // Multi-dimensional array for games that don't support SayText2. First index is the game index (as defined by the GAME_ defines), second index is team. 0 = spectator, 1 = team1, 2 = team2 + +static Handle sm_show_activity = INVALID_HANDLE; + +/** + * Prints a message to a specific client in the chat area. + * Supports color tags. + * + * @param client Client index. + * @param message Message (formatting rules). + * @noreturn + * + * On error/Errors: If the client is not connected an error will be thrown. + */ +stock void MC_PrintToChat(int client, const char[] message, any ...) { + MC_CheckTrie(); + if(client <= 0 || client > MaxClients) { + ThrowError("Invalid client index %i", client); + } + if(!IsClientInGame(client)) { + ThrowError("Client %i is not in game", client); + } + char buffer[MAX_BUFFER_LENGTH], buffer2[MAX_BUFFER_LENGTH]; + SetGlobalTransTarget(client); + Format(buffer, sizeof(buffer), "\x01%s", message); + VFormat(buffer2, sizeof(buffer2), buffer, 3); + MC_ReplaceColorCodes(buffer2); + MC_SendMessage(client, buffer2); +} + +/** + * Prints a message to all clients in the chat area. + * Supports color tags. + * + * @param client Client index. + * @param message Message (formatting rules). + * @noreturn + */ +stock void MC_PrintToChatAll(const char[] message, any ...) { + MC_CheckTrie(); + char buffer[MAX_BUFFER_LENGTH], buffer2[MAX_BUFFER_LENGTH]; + MuCo_LoopClients(i) { + if(i == 0 || !IsClientInGame(i) || MC_SkipList[i]) { + MC_SkipList[i] = false; + continue; + } + SetGlobalTransTarget(i); + Format(buffer, sizeof(buffer), "\x01%s", message); + VFormat(buffer2, sizeof(buffer2), buffer, 2); + MC_ReplaceColorCodes(buffer2); + MC_SendMessage(i, buffer2); + } +} + +/** + * Prints a message to a specific client in the chat area. + * Supports color tags and teamcolor tag. + * + * @param client Client index. + * @param author Author index whose color will be used for teamcolor tag. + * @param message Message (formatting rules). + * @noreturn + * + * On error/Errors: If the client or author are not connected an error will be thrown + */ +stock void MC_PrintToChatEx(int client, int author, const char[] message, any ...) { + MC_CheckTrie(); + if(client <= 0 || client > MaxClients) { + ThrowError("Invalid client index %i", client); + } + if(!IsClientInGame(client)) { + ThrowError("Client %i is not in game", client); + } + if(author <= 0 || author > MaxClients) { + ThrowError("Invalid client index %i", author); + } + if(!IsClientInGame(author)) { + ThrowError("Client %i is not in game", author); + } + char buffer[MAX_BUFFER_LENGTH], buffer2[MAX_BUFFER_LENGTH]; + SetGlobalTransTarget(client); + Format(buffer, sizeof(buffer), "\x01%s", message); + VFormat(buffer2, sizeof(buffer2), buffer, 4); + MC_ReplaceColorCodes(buffer2, author); + MC_SendMessage(client, buffer2, author); +} + +/** + * Prints a message to all clients in the chat area. + * Supports color tags and teamcolor tag. + * + * @param author Author index whose color will be used for teamcolor tag. + * @param message Message (formatting rules). + * @noreturn + * + * On error/Errors: If the author is not connected an error will be thrown. + */ +stock void MC_PrintToChatAllEx(int author, const char[] message, any ...) { + MC_CheckTrie(); + if(author <= 0 || author > MaxClients) { + ThrowError("Invalid client index %i", author); + } + if(!IsClientInGame(author)) { + ThrowError("Client %i is not in game", author); + } + char buffer[MAX_BUFFER_LENGTH], buffer2[MAX_BUFFER_LENGTH]; + MuCo_LoopClients(i) { + if(i == 0 || !IsClientInGame(i) || MC_SkipList[i]) { + MC_SkipList[i] = false; + continue; + } + SetGlobalTransTarget(i); + Format(buffer, sizeof(buffer), "\x01%s", message); + VFormat(buffer2, sizeof(buffer2), buffer, 3); + MC_ReplaceColorCodes(buffer2, author); + MC_SendMessage(i, buffer2, author); + } +} + +/** + * Sends a SayText2 usermessage + * + * @param client Client to send usermessage to + * @param message Message to send + * @noreturn + */ +stock void MC_SendMessage(int client, const char[] message, int author = 0) { + if(author == 0) { + author = client; + } + char buffer[MC_MAX_MESSAGE_LENGTH]; + strcopy(buffer, sizeof(buffer), message); + UserMsg index = GetUserMessageId("SayText2"); + if(index == INVALID_MESSAGE_ID) { + if(GetEngineVersion() == Engine_DODS) { + int team = GetClientTeam(author); + if(team == 0) { + ReplaceString(buffer, sizeof(buffer), "\x03", "\x04", false); // Unassigned gets green + } else { + char temp[16]; + Format(temp, sizeof(temp), "\x07%06X", MC_TeamColors[MC_GAME_DODS][team - 1]); + ReplaceString(buffer, sizeof(buffer), "\x03", temp, false); + } + } + PrintToChat(client, "%s", buffer); + return; + } + Handle buf = StartMessageOne("SayText2", client, USERMSG_RELIABLE|USERMSG_BLOCKHOOKS); + if(GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available && GetUserMessageType() == UM_Protobuf) { + PbSetInt(buf, "ent_idx", author); + PbSetBool(buf, "chat", true); + PbSetString(buf, "msg_name", buffer); + PbAddString(buf, "params", ""); + PbAddString(buf, "params", ""); + PbAddString(buf, "params", ""); + PbAddString(buf, "params", ""); + } else { + BfWriteByte(buf, author); // Message author + BfWriteByte(buf, true); // Chat message + BfWriteString(buf, buffer); // Message text + } + EndMessage(); +} + +/** + * This function should only be used right in front of + * MC_PrintToChatAll or MC_PrintToChatAllEx. It causes those functions + * to skip the specified client when printing the message. + * After printing the message, the client will no longer be skipped. + * + * @param client Client index + * @noreturn + */ +stock void MC_SkipNextClient(int client) { + if(client <= 0 || client > MaxClients) { + ThrowError("Invalid client index %i", client); + } + MC_SkipList[client] = true; +} + +/** + * Checks if the colors trie is initialized and initializes it if it's not (used internally) + * + * @return No return + */ +stock void MC_CheckTrie() { + if(MC_Trie == INVALID_HANDLE) { + MC_Trie = MC_InitColorTrie(); + } +} + +/** + * Replaces color tags in a string with color codes (used internally by MC_PrintToChat, MC_PrintToChatAll, MC_PrintToChatEx, and MC_PrintToChatAllEx + * + * @param buffer String. + * @param author Optional client index to use for {teamcolor} tags, or 0 for none + * @param removeTags Optional boolean value to determine whether we're replacing tags with colors, or just removing tags, used by MC_RemoveTags + * @param maxlen Optional value for max buffer length, used by MC_RemoveTags + * @noreturn + * + * On error/Errors: If the client index passed for author is invalid or not in game. + */ +stock void MC_ReplaceColorCodes(char[] buffer, int author = 0, bool removeTags = false, int maxlen = MAX_BUFFER_LENGTH) { + MC_CheckTrie(); + if(!removeTags) { + ReplaceString(buffer, maxlen, "{default}", "\x01", false); + } else { + ReplaceString(buffer, maxlen, "{default}", "", false); + ReplaceString(buffer, maxlen, "{teamcolor}", "", false); + } + if(author != 0 && !removeTags) { + if(author < 0 || author > MaxClients) { + ThrowError("Invalid client index %i", author); + } + if(!IsClientInGame(author)) { + ThrowError("Client %i is not in game", author); + } + ReplaceString(buffer, maxlen, "{teamcolor}", "\x03", false); + } + int cursor = 0; + int value; + char tag[32], buff[32]; + char[] output = new char[maxlen]; + + strcopy(output, maxlen, buffer); + // Since the string's size is going to be changing, output will hold the replaced string and we'll search buffer + + Handle regex = CompileRegex("{[a-zA-Z0-9]+}"); + for(int i = 0; i < 1000; i++) { // The RegEx extension is quite flaky, so we have to loop here :/. This loop is supposed to be infinite and broken by return, but conditions have been added to be safe. + if(MatchRegex(regex, buffer[cursor]) < 1) { + CloseHandle(regex); + strcopy(buffer, maxlen, output); + return; + } + GetRegexSubString(regex, 0, tag, sizeof(tag)); + MC_StrToLower(tag); + cursor = StrContains(buffer[cursor], tag, false) + cursor + 1; + strcopy(buff, sizeof(buff), tag); + ReplaceString(buff, sizeof(buff), "{", ""); + ReplaceString(buff, sizeof(buff), "}", ""); + + if(!GetTrieValue(MC_Trie, buff, value)) { + continue; + } + + if(removeTags) { + ReplaceString(output, maxlen, tag, "", false); + } else { + Format(buff, sizeof(buff), "\x07%06X", value); + ReplaceString(output, maxlen, tag, buff, false); + } + } + LogError("[MORE COLORS] Infinite loop broken."); +} + +/** + * Gets a part of a string + * + * @param input String to get the part from + * @param output Buffer to write to + * @param maxlen Max length of output buffer + * @param start Position to start at + * @param numChars Number of characters to return, or 0 for the end of the string + * @noreturn + */ +stock void CSubString(const char[] input, char[] output, int maxlen, int start, int numChars = 0) { + int i = 0; + for(;;) { + if(i == maxlen - 1 || i >= numChars || input[start + i] == '\0') { + output[i] = '\0'; + return; + } + output[i] = input[start + i]; + i++; + } +} + +/** + * Converts a string to lowercase + * + * @param buffer String to convert + * @noreturn + */ +stock void MC_StrToLower(char[] buffer) { + int len = strlen(buffer); + for(int i = 0; i < len; i++) { + buffer[i] = CharToLower(buffer[i]); + } +} + +/** + * Adds a color to the colors trie + * + * @param name Color name, without braces + * @param color Hexadecimal representation of the color (0xRRGGBB) + * @return True if color was added successfully, false if a color already exists with that name + */ +stock bool MC_AddColor(const char[] name, int color) { + MC_CheckTrie(); + int value; + if(GetTrieValue(MC_Trie, name, value)) { + return false; + } + char newName[64]; + strcopy(newName, sizeof(newName), name); + MC_StrToLower(newName); + SetTrieValue(MC_Trie, newName, color); + return true; +} + +/** + * Removes color tags from a message + * + * @param message Message to remove tags from + * @param maxlen Maximum buffer length + * @noreturn + */ +stock void MC_RemoveTags(char[] message, int maxlen) { + MC_ReplaceColorCodes(message, 0, true, maxlen); +} + +/** + * Replies to a command with colors + * + * @param client Client to reply to + * @param message Message (formatting rules) + * @noreturn + */ +stock void MC_ReplyToCommand(int client, const char[] message, any ...) { + char buffer[MAX_BUFFER_LENGTH]; + SetGlobalTransTarget(client); + VFormat(buffer, sizeof(buffer), message, 3); + if(GetCmdReplySource() == SM_REPLY_TO_CONSOLE) { + MC_RemoveTags(buffer, sizeof(buffer)); + PrintToConsole(client, "%s", buffer); + } else { + MC_PrintToChat(client, "%s", buffer); + } +} + +/** + * Replies to a command with colors + * + * @param client Client to reply to + * @param author Client to use for {teamcolor} + * @param message Message (formatting rules) + * @noreturn + */ +stock void MC_ReplyToCommandEx(int client, int author, const char[] message, any ...) { + char buffer[MAX_BUFFER_LENGTH]; + SetGlobalTransTarget(client); + VFormat(buffer, sizeof(buffer), message, 4); + if(GetCmdReplySource() == SM_REPLY_TO_CONSOLE) { + MC_RemoveTags(buffer, sizeof(buffer)); + PrintToConsole(client, "%s", buffer); + } else { + MC_PrintToChatEx(client, author, "%s", buffer); + } +} + +/** + * Displays usage of an admin command to users depending on the + * setting of the sm_show_activity cvar. + * + * This version does not display a message to the originating client + * if used from chat triggers or menus. If manual replies are used + * for these cases, then this function will suffice. Otherwise, + * MC_ShowActivity2() is slightly more useful. + * Supports color tags. + * + * @param client Client index doing the action, or 0 for server. + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @noreturn + * @error + */ +stock int MC_ShowActivity(int client, const char[] format, any ...) +{ + if (sm_show_activity == INVALID_HANDLE) + sm_show_activity = FindConVar("sm_show_activity"); + + char tag[] = "[SM] "; + + char szBuffer[MC_MAX_MESSAGE_LENGTH]; + //char szCMessage[MC_MAX_MESSAGE_LENGTH]; + int value = GetConVarInt(sm_show_activity); + ReplySource replyto = GetCmdReplySource(); + + char name[MAX_NAME_LENGTH] = "Console"; + char sign[MAX_NAME_LENGTH] = "ADMIN"; + bool display_in_chat = false; + if (client != 0) + { + if (client < 0 || client > MaxClients || !IsClientConnected(client)) + ThrowError("Client index %d is invalid", client); + + GetClientName(client, name, sizeof(name)); + AdminId id = GetUserAdmin(client); + if (id == INVALID_ADMIN_ID + || !GetAdminFlag(id, Admin_Generic, Access_Effective)) + { + sign = "PLAYER"; + } + + /* Display the message to the client? */ + if (replyto == SM_REPLY_TO_CONSOLE) + { + SetGlobalTransTarget(client); + VFormat(szBuffer, sizeof(szBuffer), format, 3); + + MC_RemoveTags(szBuffer, sizeof(szBuffer)); + PrintToConsole(client, "%s%s\n", tag, szBuffer); + display_in_chat = true; + } + } + else + { + SetGlobalTransTarget(LANG_SERVER); + VFormat(szBuffer, sizeof(szBuffer), format, 3); + + MC_RemoveTags(szBuffer, sizeof(szBuffer)); + PrintToServer("%s%s\n", tag, szBuffer); + } + + if (!value) + { + return 1; + } + + MuCo_LoopClients(i) + { + if (i == 0 + || !IsClientInGame(i) + || IsFakeClient(i) + || (display_in_chat && i == client)) + { + continue; + } + AdminId id = GetUserAdmin(i); + SetGlobalTransTarget(i); + if (id == INVALID_ADMIN_ID + || !GetAdminFlag(id, Admin_Generic, Access_Effective)) + { + /* Treat this as a normal user. */ + if ((value & 1) | (value & 2)) + { + char newsign[MAX_NAME_LENGTH]; + newsign = sign; + if ((value & 2) || (i == client)) + { + newsign = name; + } + VFormat(szBuffer, sizeof(szBuffer), format, 3); + + MC_PrintToChatEx(i, client, "%s%s: %s", tag, newsign, szBuffer); + } + } + else + { + /* Treat this as an admin user */ + bool is_root = GetAdminFlag(id, Admin_Root, Access_Effective); + if ((value & 4) + || (value & 8) + || ((value & 16) && is_root)) + { + char newsign[MAX_NAME_LENGTH]; + newsign = sign; + if ((value & 8) || ((value & 16) && is_root) || (i == client)) + { + newsign = name; + } + VFormat(szBuffer, sizeof(szBuffer), format, 3); + + MC_PrintToChatEx(i, client, "%s%s: %s", tag, newsign, szBuffer); + } + } + } + + return 1; +} + +/** + * Same as MC_ShowActivity(), except the tag parameter is used instead of "[SM] " (note that you must supply any spacing). + * Supports color tags. + * + * @param client Client index doing the action, or 0 for server. + * @param tags Tag to display with. + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @noreturn + * @error + */ +stock int MC_ShowActivityEx(int client, const char[] tag, const char[] format, any ...) +{ + if (sm_show_activity == INVALID_HANDLE) + sm_show_activity = FindConVar("sm_show_activity"); + + char szBuffer[MC_MAX_MESSAGE_LENGTH]; + //char szCMessage[MC_MAX_MESSAGE_LENGTH]; + int value = GetConVarInt(sm_show_activity); + ReplySource replyto = GetCmdReplySource(); + + char name[MAX_NAME_LENGTH] = "Console"; + char sign[MAX_NAME_LENGTH] = "ADMIN"; + bool display_in_chat = false; + if (client != 0) + { + if (client < 0 || client > MaxClients || !IsClientConnected(client)) + ThrowError("Client index %d is invalid", client); + + GetClientName(client, name, sizeof(name)); + AdminId id = GetUserAdmin(client); + if (id == INVALID_ADMIN_ID + || !GetAdminFlag(id, Admin_Generic, Access_Effective)) + { + sign = "PLAYER"; + } + + /* Display the message to the client? */ + if (replyto == SM_REPLY_TO_CONSOLE) + { + SetGlobalTransTarget(client); + VFormat(szBuffer, sizeof(szBuffer), format, 4); + + MC_RemoveTags(szBuffer, sizeof(szBuffer)); + PrintToConsole(client, "%s%s\n", tag, szBuffer); + display_in_chat = true; + } + } + else + { + SetGlobalTransTarget(LANG_SERVER); + VFormat(szBuffer, sizeof(szBuffer), format, 4); + + MC_RemoveTags(szBuffer, sizeof(szBuffer)); + PrintToServer("%s%s\n", tag, szBuffer); + } + + if (!value) + { + return 1; + } + + MuCo_LoopClients(i) + { + if (i == 0 + || !IsClientInGame(i) + || IsFakeClient(i) + || (display_in_chat && i == client)) + { + continue; + } + AdminId id = GetUserAdmin(i); + SetGlobalTransTarget(i); + if (id == INVALID_ADMIN_ID + || !GetAdminFlag(id, Admin_Generic, Access_Effective)) + { + /* Treat this as a normal user. */ + if ((value & 1) | (value & 2)) + { + char newsign[MAX_NAME_LENGTH]; + newsign = sign; + if ((value & 2) || (i == client)) + { + newsign = name; + } + VFormat(szBuffer, sizeof(szBuffer), format, 4); + + MC_PrintToChatEx(i, client, "%s%s: %s", tag, newsign, szBuffer); + } + } + else + { + /* Treat this as an admin user */ + bool is_root = GetAdminFlag(id, Admin_Root, Access_Effective); + if ((value & 4) + || (value & 8) + || ((value & 16) && is_root)) + { + char newsign[MAX_NAME_LENGTH]; + newsign = sign; + if ((value & 8) || ((value & 16) && is_root) || (i == client)) + { + newsign = name; + } + VFormat(szBuffer, sizeof(szBuffer), format, 4); + + MC_PrintToChatEx(i, client, "%s%s: %s", tag, newsign, szBuffer); + } + } + } + + return 1; +} + +/** + * Displays usage of an admin command to users depending on the setting of the sm_show_activity cvar. + * All users receive a message in their chat text, except for the originating client, + * who receives the message based on the current ReplySource. + * Supports color tags. + * + * @param client Client index doing the action, or 0 for server. + * @param tags Tag to prepend to the message. + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @noreturn + * @error + */ +stock int MC_ShowActivity2(int client, const char[] tag, const char[] format, any ...) +{ + if (sm_show_activity == INVALID_HANDLE) + sm_show_activity = FindConVar("sm_show_activity"); + + char szBuffer[MC_MAX_MESSAGE_LENGTH]; + //char szCMessage[MC_MAX_MESSAGE_LENGTH]; + int value = GetConVarInt(sm_show_activity); + // ReplySource replyto = GetCmdReplySource(); + + char name[MAX_NAME_LENGTH] = "Console"; + char sign[MAX_NAME_LENGTH] = "ADMIN"; + if (client != 0) + { + if (client < 0 || client > MaxClients || !IsClientConnected(client)) + ThrowError("Client index %d is invalid", client); + + GetClientName(client, name, sizeof(name)); + AdminId id = GetUserAdmin(client); + if (id == INVALID_ADMIN_ID + || !GetAdminFlag(id, Admin_Generic, Access_Effective)) + { + sign = "PLAYER"; + } + + SetGlobalTransTarget(client); + VFormat(szBuffer, sizeof(szBuffer), format, 4); + + /* We don't display directly to the console because the chat text + * simply gets added to the console, so we don't want it to print + * twice. + */ + MC_PrintToChatEx(client, client, "%s%s", tag, szBuffer); + } + else + { + SetGlobalTransTarget(LANG_SERVER); + VFormat(szBuffer, sizeof(szBuffer), format, 4); + + MC_RemoveTags(szBuffer, sizeof(szBuffer)); + PrintToServer("%s%s\n", tag, szBuffer); + } + + if (!value) + { + return 1; + } + + MuCo_LoopClients(i) + { + if (i == 0 + || !IsClientInGame(i) + || IsFakeClient(i) + || i == client) + { + continue; + } + AdminId id = GetUserAdmin(i); + SetGlobalTransTarget(i); + if (id == INVALID_ADMIN_ID + || !GetAdminFlag(id, Admin_Generic, Access_Effective)) + { + /* Treat this as a normal user. */ + if ((value & 1) | (value & 2)) + { + char newsign[MAX_NAME_LENGTH]; + newsign = sign; + if ((value & 2)) + { + newsign = name; + } + VFormat(szBuffer, sizeof(szBuffer), format, 4); + + MC_PrintToChatEx(i, client, "%s%s: %s", tag, newsign, szBuffer); + } + } + else + { + /* Treat this as an admin user */ + bool is_root = GetAdminFlag(id, Admin_Root, Access_Effective); + if ((value & 4) + || (value & 8) + || ((value & 16) && is_root)) + { + char newsign[MAX_NAME_LENGTH]; + newsign = sign; + if ((value & 8) || ((value & 16) && is_root)) + { + newsign = name; + } + VFormat(szBuffer, sizeof(szBuffer), format, 4); + + MC_PrintToChatEx(i, client, "%s%s: %s", tag, newsign, szBuffer); + } + } + } + + return 1; +} + +/** + * Determines whether a color name exists + * + * @param color The color name to check + * @return True if the color exists, false otherwise + */ +stock bool CColorExists(const char[] color) { + MC_CheckTrie(); + int temp; + return GetTrieValue(MC_Trie, color, temp); +} + +/** + * Returns the hexadecimal representation of a client's team color (will NOT initialize the trie) + * + * @param client Client to get the team color for + * @return Client's team color in hexadecimal, or green if unknown + * On error/Errors: If the client index passed is invalid or not in game. + */ +stock int CGetTeamColor(int client) { + if(client <= 0 || client > MaxClients) { + ThrowError("Invalid client index %i", client); + } + if(!IsClientInGame(client)) { + ThrowError("Client %i is not in game", client); + } + int value; + switch(GetClientTeam(client)) { + case 1: { + value = MCOLOR_GRAY; + } + case 2: { + value = MCOLOR_RED; + } + case 3: { + value = MCOLOR_BLUE; + } + default: { + value = MCOLOR_GREEN; + } + } + return value; +} + +stock Handle MC_InitColorTrie() { + Handle hTrie = CreateTrie(); + SetTrieValue(hTrie, "aliceblue", 0xF0F8FF); + SetTrieValue(hTrie, "allies", 0x4D7942); // same as Allies team in DoD:S + SetTrieValue(hTrie, "ancient", 0xEB4B4B); // same as Ancient item rarity in Dota 2 + SetTrieValue(hTrie, "antiquewhite", 0xFAEBD7); + SetTrieValue(hTrie, "aqua", 0x00FFFF); + SetTrieValue(hTrie, "aquamarine", 0x7FFFD4); + SetTrieValue(hTrie, "arcana", 0xADE55C); // same as Arcana item rarity in Dota 2 + SetTrieValue(hTrie, "axis", 0xFF4040); // same as Axis team in DoD:S + SetTrieValue(hTrie, "azure", 0x007FFF); + SetTrieValue(hTrie, "beige", 0xF5F5DC); + SetTrieValue(hTrie, "bisque", 0xFFE4C4); + SetTrieValue(hTrie, "black", 0x000000); + SetTrieValue(hTrie, "blanchedalmond", 0xFFEBCD); + SetTrieValue(hTrie, "blue", 0x99CCFF); // same as BLU/Counter-Terrorist team color + SetTrieValue(hTrie, "blueviolet", 0x8A2BE2); + SetTrieValue(hTrie, "brown", 0xA52A2A); + SetTrieValue(hTrie, "burlywood", 0xDEB887); + SetTrieValue(hTrie, "cadetblue", 0x5F9EA0); + SetTrieValue(hTrie, "chartreuse", 0x7FFF00); + SetTrieValue(hTrie, "chocolate", 0xD2691E); + SetTrieValue(hTrie, "collectors", 0xAA0000); // same as Collector's item quality in TF2 + SetTrieValue(hTrie, "common", 0xB0C3D9); // same as Common item rarity in Dota 2 + SetTrieValue(hTrie, "community", 0x70B04A); // same as Community item quality in TF2 + SetTrieValue(hTrie, "coral", 0xFF7F50); + SetTrieValue(hTrie, "cornflowerblue", 0x6495ED); + SetTrieValue(hTrie, "cornsilk", 0xFFF8DC); + SetTrieValue(hTrie, "corrupted", 0xA32C2E); // same as Corrupted item quality in Dota 2 + SetTrieValue(hTrie, "crimson", 0xDC143C); + SetTrieValue(hTrie, "cyan", 0x00FFFF); + SetTrieValue(hTrie, "darkblue", 0x00008B); + SetTrieValue(hTrie, "darkcyan", 0x008B8B); + SetTrieValue(hTrie, "darkgoldenrod", 0xB8860B); + SetTrieValue(hTrie, "darkgray", 0xA9A9A9); + SetTrieValue(hTrie, "darkgrey", 0xA9A9A9); + SetTrieValue(hTrie, "darkgreen", 0x006400); + SetTrieValue(hTrie, "darkkhaki", 0xBDB76B); + SetTrieValue(hTrie, "darkmagenta", 0x8B008B); + SetTrieValue(hTrie, "darkolivegreen", 0x556B2F); + SetTrieValue(hTrie, "darkorange", 0xFF8C00); + SetTrieValue(hTrie, "darkorchid", 0x9932CC); + SetTrieValue(hTrie, "darkred", 0x8B0000); + SetTrieValue(hTrie, "darksalmon", 0xE9967A); + SetTrieValue(hTrie, "darkseagreen", 0x8FBC8F); + SetTrieValue(hTrie, "darkslateblue", 0x483D8B); + SetTrieValue(hTrie, "darkslategray", 0x2F4F4F); + SetTrieValue(hTrie, "darkslategrey", 0x2F4F4F); + SetTrieValue(hTrie, "darkturquoise", 0x00CED1); + SetTrieValue(hTrie, "darkviolet", 0x9400D3); + SetTrieValue(hTrie, "deeppink", 0xFF1493); + SetTrieValue(hTrie, "deepskyblue", 0x00BFFF); + SetTrieValue(hTrie, "dimgray", 0x696969); + SetTrieValue(hTrie, "dimgrey", 0x696969); + SetTrieValue(hTrie, "dodgerblue", 0x1E90FF); + SetTrieValue(hTrie, "exalted", 0xCCCCCD); // same as Exalted item quality in Dota 2 + SetTrieValue(hTrie, "firebrick", 0xB22222); + SetTrieValue(hTrie, "floralwhite", 0xFFFAF0); + SetTrieValue(hTrie, "forestgreen", 0x228B22); + SetTrieValue(hTrie, "frozen", 0x4983B3); // same as Frozen item quality in Dota 2 + SetTrieValue(hTrie, "fuchsia", 0xFF00FF); + SetTrieValue(hTrie, "fullblue", 0x0000FF); + SetTrieValue(hTrie, "fullred", 0xFF0000); + SetTrieValue(hTrie, "gainsboro", 0xDCDCDC); + SetTrieValue(hTrie, "genuine", 0x4D7455); // same as Genuine item quality in TF2 + SetTrieValue(hTrie, "ghostwhite", 0xF8F8FF); + SetTrieValue(hTrie, "gold", 0xFFD700); + SetTrieValue(hTrie, "goldenrod", 0xDAA520); + SetTrieValue(hTrie, "gray", 0xCCCCCC); // same as spectator team color + SetTrieValue(hTrie, "grey", 0xCCCCCC); + SetTrieValue(hTrie, "green", 0x3EFF3E); + SetTrieValue(hTrie, "greenyellow", 0xADFF2F); + SetTrieValue(hTrie, "haunted", 0x38F3AB); // same as Haunted item quality in TF2 + SetTrieValue(hTrie, "honeydew", 0xF0FFF0); + SetTrieValue(hTrie, "hotpink", 0xFF69B4); + SetTrieValue(hTrie, "immortal", 0xE4AE33); // same as Immortal item rarity in Dota 2 + SetTrieValue(hTrie, "indianred", 0xCD5C5C); + SetTrieValue(hTrie, "indigo", 0x4B0082); + SetTrieValue(hTrie, "ivory", 0xFFFFF0); + SetTrieValue(hTrie, "khaki", 0xF0E68C); + SetTrieValue(hTrie, "lavender", 0xE6E6FA); + SetTrieValue(hTrie, "lavenderblush", 0xFFF0F5); + SetTrieValue(hTrie, "lawngreen", 0x7CFC00); + SetTrieValue(hTrie, "legendary", 0xD32CE6); // same as Legendary item rarity in Dota 2 + SetTrieValue(hTrie, "lemonchiffon", 0xFFFACD); + SetTrieValue(hTrie, "lightblue", 0xADD8E6); + SetTrieValue(hTrie, "lightcoral", 0xF08080); + SetTrieValue(hTrie, "lightcyan", 0xE0FFFF); + SetTrieValue(hTrie, "lightgoldenrodyellow", 0xFAFAD2); + SetTrieValue(hTrie, "lightgray", 0xD3D3D3); + SetTrieValue(hTrie, "lightgrey", 0xD3D3D3); + SetTrieValue(hTrie, "lightgreen", 0x99FF99); + SetTrieValue(hTrie, "lightpink", 0xFFB6C1); + SetTrieValue(hTrie, "lightsalmon", 0xFFA07A); + SetTrieValue(hTrie, "lightseagreen", 0x20B2AA); + SetTrieValue(hTrie, "lightskyblue", 0x87CEFA); + SetTrieValue(hTrie, "lightslategray", 0x778899); + SetTrieValue(hTrie, "lightslategrey", 0x778899); + SetTrieValue(hTrie, "lightsteelblue", 0xB0C4DE); + SetTrieValue(hTrie, "lightyellow", 0xFFFFE0); + SetTrieValue(hTrie, "lime", 0x00FF00); + SetTrieValue(hTrie, "limegreen", 0x32CD32); + SetTrieValue(hTrie, "linen", 0xFAF0E6); + SetTrieValue(hTrie, "magenta", 0xFF00FF); + SetTrieValue(hTrie, "maroon", 0x800000); + SetTrieValue(hTrie, "mediumaquamarine", 0x66CDAA); + SetTrieValue(hTrie, "mediumblue", 0x0000CD); + SetTrieValue(hTrie, "mediumorchid", 0xBA55D3); + SetTrieValue(hTrie, "mediumpurple", 0x9370D8); + SetTrieValue(hTrie, "mediumseagreen", 0x3CB371); + SetTrieValue(hTrie, "mediumslateblue", 0x7B68EE); + SetTrieValue(hTrie, "mediumspringgreen", 0x00FA9A); + SetTrieValue(hTrie, "mediumturquoise", 0x48D1CC); + SetTrieValue(hTrie, "mediumvioletred", 0xC71585); + SetTrieValue(hTrie, "midnightblue", 0x191970); + SetTrieValue(hTrie, "mintcream", 0xF5FFFA); + SetTrieValue(hTrie, "mistyrose", 0xFFE4E1); + SetTrieValue(hTrie, "moccasin", 0xFFE4B5); + SetTrieValue(hTrie, "mythical", 0x8847FF); // same as Mythical item rarity in Dota 2 + SetTrieValue(hTrie, "navajowhite", 0xFFDEAD); + SetTrieValue(hTrie, "navy", 0x000080); + SetTrieValue(hTrie, "normal", 0xB2B2B2); // same as Normal item quality in TF2 + SetTrieValue(hTrie, "oldlace", 0xFDF5E6); + SetTrieValue(hTrie, "olive", 0x9EC34F); + SetTrieValue(hTrie, "olivedrab", 0x6B8E23); + SetTrieValue(hTrie, "orange", 0xFFA500); + SetTrieValue(hTrie, "orangered", 0xFF4500); + SetTrieValue(hTrie, "orchid", 0xDA70D6); + SetTrieValue(hTrie, "palegoldenrod", 0xEEE8AA); + SetTrieValue(hTrie, "palegreen", 0x98FB98); + SetTrieValue(hTrie, "paleturquoise", 0xAFEEEE); + SetTrieValue(hTrie, "palevioletred", 0xD87093); + SetTrieValue(hTrie, "papayawhip", 0xFFEFD5); + SetTrieValue(hTrie, "peachpuff", 0xFFDAB9); + SetTrieValue(hTrie, "peru", 0xCD853F); + SetTrieValue(hTrie, "pink", 0xFFC0CB); + SetTrieValue(hTrie, "plum", 0xDDA0DD); + SetTrieValue(hTrie, "powderblue", 0xB0E0E6); + SetTrieValue(hTrie, "purple", 0x800080); + SetTrieValue(hTrie, "rare", 0x4B69FF); // same as Rare item rarity in Dota 2 + SetTrieValue(hTrie, "red", 0xFF4040); // same as RED/Terrorist team color + SetTrieValue(hTrie, "rosybrown", 0xBC8F8F); + SetTrieValue(hTrie, "royalblue", 0x4169E1); + SetTrieValue(hTrie, "saddlebrown", 0x8B4513); + SetTrieValue(hTrie, "salmon", 0xFA8072); + SetTrieValue(hTrie, "sandybrown", 0xF4A460); + SetTrieValue(hTrie, "seagreen", 0x2E8B57); + SetTrieValue(hTrie, "seashell", 0xFFF5EE); + SetTrieValue(hTrie, "selfmade", 0x70B04A); // same as Self-Made item quality in TF2 + SetTrieValue(hTrie, "sienna", 0xA0522D); + SetTrieValue(hTrie, "silver", 0xC0C0C0); + SetTrieValue(hTrie, "skyblue", 0x87CEEB); + SetTrieValue(hTrie, "slateblue", 0x6A5ACD); + SetTrieValue(hTrie, "slategray", 0x708090); + SetTrieValue(hTrie, "slategrey", 0x708090); + SetTrieValue(hTrie, "snow", 0xFFFAFA); + SetTrieValue(hTrie, "springgreen", 0x00FF7F); + SetTrieValue(hTrie, "steelblue", 0x4682B4); + SetTrieValue(hTrie, "strange", 0xCF6A32); // same as Strange item quality in TF2 + SetTrieValue(hTrie, "tan", 0xD2B48C); + SetTrieValue(hTrie, "teal", 0x008080); + SetTrieValue(hTrie, "thistle", 0xD8BFD8); + SetTrieValue(hTrie, "tomato", 0xFF6347); + SetTrieValue(hTrie, "turquoise", 0x40E0D0); + SetTrieValue(hTrie, "uncommon", 0xB0C3D9); // same as Uncommon item rarity in Dota 2 + SetTrieValue(hTrie, "unique", 0xFFD700); // same as Unique item quality in TF2 + SetTrieValue(hTrie, "unusual", 0x8650AC); // same as Unusual item quality in TF2 + SetTrieValue(hTrie, "valve", 0xA50F79); // same as Valve item quality in TF2 + SetTrieValue(hTrie, "vintage", 0x476291); // same as Vintage item quality in TF2 + SetTrieValue(hTrie, "violet", 0xEE82EE); + SetTrieValue(hTrie, "wheat", 0xF5DEB3); + SetTrieValue(hTrie, "white", 0xFFFFFF); + SetTrieValue(hTrie, "whitesmoke", 0xF5F5F5); + SetTrieValue(hTrie, "yellow", 0xFFFF00); + SetTrieValue(hTrie, "yellowgreen", 0x9ACD32); + return hTrie; +} \ No newline at end of file From d4378f64766356cceec3e2a5b8ab4b7236193cc4 Mon Sep 17 00:00:00 2001 From: zaCade Date: Sat, 8 Dec 2018 18:03:02 +0100 Subject: [PATCH 05/52] VScripts: Cleaning some more code. --- VScripts/scripting/vscript_ze_dreamin.sp | 48 +++++++----------------- 1 file changed, 14 insertions(+), 34 deletions(-) diff --git a/VScripts/scripting/vscript_ze_dreamin.sp b/VScripts/scripting/vscript_ze_dreamin.sp index a70737e..e222d01 100644 --- a/VScripts/scripting/vscript_ze_dreamin.sp +++ b/VScripts/scripting/vscript_ze_dreamin.sp @@ -589,35 +589,27 @@ public void math_counter_11288_display(const char[] output, int caller, int acti //---------------------------------------------------------------------------------------------------- // Purpose: //---------------------------------------------------------------------------------------------------- -public void Display(int amount) +public void Display(int iTimer) { - float fOrigin[3]; - fOrigin[0] = 0.0; - fOrigin[1] = 0.0; - fOrigin[2] = 0.0; + int iRelay = CreateEntityByName("logic_relay"); + DispatchKeyFormat(iRelay, "targetname", "vscript_countdown_relay"); + DispatchKeyFormat(iRelay, "spawnflags", "0"); + DispatchKeyFormat(iRelay, "OnSpawn", "seconds_left,AddOutput,message seconds left,0,-1"); + DispatchKeyFormat(iRelay, "OnSpawn", "text_sec,AddOutput,message %d,0,-1", iTimer - 1); - int iRelay = CreateEntityAtOrigin("logic_relay", fOrigin); - DispatchKeyFormat(iRelay, "targetname", "vscript_countdown_relay"); - DispatchKeyFormat(iRelay, "spawnflags", "0"); - DispatchKeyFormat(iRelay, "OnTrigger", "seconds_left,AddOutput,message seconds left,0,-1"); - DispatchKeyFormat(iRelay, "OnTrigger", "text_sec,AddOutput,message %d,0,-1", amount - 1); - - int iBackup = amount; - - for (int j = 0; j <= amount; j++) + int iBackup = iTimer; + for (int j = 0; j <= iTimer; j++) { iBackup--; - DispatchKeyFormat(iRelay, "OnTrigger", "text_sec,AddOutput,message %d,%d,-1", iBackup, j); - DispatchKeyFormat(iRelay, "OnTrigger", "seconds_left,Display,,%d,-1",j); - DispatchKeyFormat(iRelay, "OnTrigger", "text_sec,Display,,%d,-1",j); + DispatchKeyFormat(iRelay, "OnSpawn", "text_sec,AddOutput,message %d,%d,-1", iBackup, j); + DispatchKeyFormat(iRelay, "OnSpawn", "seconds_left,Display,,%d,-1", j); + DispatchKeyFormat(iRelay, "OnSpawn", "text_sec,Display,,%d,-1", j); } - DispatchKeyFormat(iRelay, "OnTrigger", "seconds_left,AddOutput,message ,%d,-1",amount + 1); - DispatchKeyFormat(iRelay, "OnTrigger", "text_sec,AddOutput,message ,%d,-1",amount + 1); - DispatchKeyFormat(iRelay, "OnTrigger", "!self,Kill,,%d,-1",amount + 2); - + DispatchKeyFormat(iRelay, "OnSpawn", "seconds_left,AddOutput,message ,%d,-1", iTimer + 1); + DispatchKeyFormat(iRelay, "OnSpawn", "text_sec,AddOutput,message ,%d,-1", iTimer + 1); + DispatchKeyFormat(iRelay, "OnSpawn", "!self,Kill,,%d,-1", iTimer + 2); SpawnAndActivate(iRelay); - AcceptEntityInput(iRelay, "Trigger"); } //---------------------------------------------------------------------------------------------------- @@ -659,18 +651,6 @@ public int FindEntityByHammerID(int iHammerID) return INVALID_ENT_REFERENCE; } -//---------------------------------------------------------------------------------------------------- -// Purpose: -//---------------------------------------------------------------------------------------------------- -stock int CreateEntityAtOrigin(const char[] classname, const float origin[3]) -{ - int entity = CreateEntityByName(classname); - - TeleportEntity(entity, origin, NULL_VECTOR, NULL_VECTOR); - - return entity; -} - //---------------------------------------------------------------------------------------------------- // Purpose: //---------------------------------------------------------------------------------------------------- From 8cdcb01100f439645aa9d9ab9b1d33007e879b7f Mon Sep 17 00:00:00 2001 From: zaCade Date: Sat, 8 Dec 2018 21:12:39 +0100 Subject: [PATCH 06/52] Misc: Move shared stuff to shared git. --- AdminCheats/scripting/AdminCheats.sp | 130 + AdminIcon/scripting/AdminIcon.sp | 73 + .../scripting/AdvancedTargeting.sp | 493 +++ .../scripting/include/AdvancedTargeting.inc | 26 + AntiFlood/scripting/AntiFlood.sp | 71 + AntiJumpSpam/scripting/AntiJumpSpam.sp | 115 + AntiPingMask/scripting/AntiPingMask.sp | 79 + AutoRecorder/scripting/AutoRecorder.sp | 221 ++ .../scripting/ConVarSuppression.sp | 118 + Extend/gamedata/Extend.games.txt | 25 + Extend/scripting/Extend.sp | 387 ++ ExtraCommands/scripting/ExtraCommands.sp | 1377 +++++++ FixAngles/scripting/FixAngles.sp | 47 + FixGameUI/scripting/FixGameUI.sp | 129 + .../gamedata/FixPlayerEquip.games.txt | 14 + FixPlayerEquip/scripting/FixPlayerEquip.sp | 112 + .../gamedata/FixPointTeleport.games.txt | 19 + .../scripting/FixPointTeleport.sp | 101 + Flashlight/scripting/Flashlight.sp | 44 + ForceInputs/scripting/ForceInputs.sp | 206 ++ FullUpdate/gamedata/FullUpdate.games.txt | 20 + FullUpdate/scripting/FullUpdate.sp | 106 + FullUpdate/scripting/include/FullUpdate.inc | 24 + GlowColors/configs/GlowColors.cfg | 18 + GlowColors/scripting/GlowColors.sp | 535 +++ InfoMessage/configs/info_messages/test.txt | 10 + InfoMessage/scripting/InfoMessage.sp | 115 + KnifeAlert/scripting/KnifeAlert.sp | 112 + MapAdmin/configs/MapAdmin.cfg | 3137 ++++++++++++++++ MapAdmin/scripting/MapAdmin.sp | 342 ++ NameFilter/configs/NameFilter.cfg | 21 + NameFilter/scripting/NameFilter.sp | 350 ++ NapalmLagFix/gamedata/napalmlagfix.games.txt | 28 + NapalmLagFix/scripting/NapalmLagFix.sp | 70 + .../gamedata/NoGrenadeRinging.games.txt | 15 + .../scripting/NoGrenadeRinging.sp | 49 + NoShake/scripting/NoShake.sp | 91 + .../scripting/PlayerVisibility.sp | 339 ++ .../configs/PointServerCommandFilter.cfg | 139 + .../PointServerCommandFilter.example.cfg | 74 + .../scripting/PointServerCommandFilter.sp | 592 +++ QuickSwitch/scripting/QuickSwitch.sp | 73 + RoundTime/scripting/RoundTime.sp | 28 + .../ZE_FFVII_Mako_Reactor_V6_B08.cfg | 67 + .../ze_FFVII_Mako_Reactor_v1_4_1.cfg | 49 + .../savelevel/ze_FFVII_Mako_Reactor_v3_1.cfg | 49 + .../savelevel/ze_FFXII_Feywood_b3_1.cfg | 60 + .../savelevel/ze_FFXII_Paramina_Rift_v1_3.cfg | 92 + .../savelevel/ze_FFXII_Paramina_Rift_v1_4.cfg | 92 + .../configs/savelevel/ze_TESV_Skyrim_v3.cfg | 76 + .../savelevel/ze_harry_potter_v1_3.cfg | 76 + .../savelevel/ze_harry_potter_v2_1.cfg | 76 + .../savelevel/ze_lila_panic_escape_v3_1.cfg | 92 + .../ze_lotr_minas_tirith_v2_2fix.cfg | 92 + .../savelevel/ze_lotr_minas_tirith_v3_5.cfg | 92 + .../savelevel/ze_tesv_skyrim_v4fix.cfg | 76 + SaveLevel/scripting/SaveLevel.sp | 521 +++ SelectiveBhop/scripting/SelectiveBhop.sp | 416 +++ .../scripting/include/SelectiveBhop.inc | 26 + SlopeFix/scripting/SlopeFix.sp | 150 + .../materials/decals/spraymanager/1.vmt | 6 + .../materials/decals/spraymanager/1.vtf | Bin 0 -> 8400 bytes .../materials/decals/spraymanager/2.vmt | 6 + .../materials/decals/spraymanager/2.vtf | Bin 0 -> 8400 bytes .../materials/decals/spraymanager/3.vmt | 8 + .../materials/decals/spraymanager/3.vtf | Bin 0 -> 5552 bytes SprayManager/scripting/SprayManager.sp | 3201 +++++++++++++++++ Status/gamedata/serverfps.games.txt | 45 + Status/scripting/Status.sp | 204 ++ Status/scripting/include/serverfps.inc | 49 + StopSound/scripting/StopSound.sp | 693 ++++ .../translations/plugin.stopsound.phrases.txt | 68 + SvGravityFix/scripting/SvGravityFix.sp | 38 + TeamManager/scripting/TeamManager.sp | 206 ++ Teleport/scripting/Teleport.sp | 330 ++ WeaponCleaner/scripting/WeaponCleaner.sp | 305 ++ .../configs/custom-chatcolors.cfg | 59 + .../configs/custom-chatcolorsbans.cfg | 3 + .../configs/custom-chatcolorsreplace.cfg | 67 + .../scripting/custom-chatcolors.sp | 3113 ++++++++++++++++ custom-chatcolors/scripting/include/ccc.inc | 191 + .../translations/allchat.phrases.txt | 58 + entWatch/gamedata/plugin.entWatch.txt | 28 + entWatch/scripting/entWatch.sp | 2644 ++++++++++++++ entWatch/scripting/include/entWatch.inc | 150 + entWatch/translations/entWatch.phrases.txt | 47 + entWatch/translations/fr/entWatch.phrases.txt | 47 + entWatch/translations/ru/entWatch.phrases.txt | 47 + includes/CSSFixes.inc | 30 + includes/SteamWorks.inc | 383 ++ includes/connect.inc | 42 + includes/dhooks.inc | 485 +++ includes/outputinfo.inc | 63 + includes/zombiereloaded.inc | 67 + includes/zr/class.zr.inc | 127 + includes/zr/infect.zr.inc | 133 + includes/zr/respawn.zr.inc | 95 + 97 files changed, 25215 insertions(+) create mode 100644 AdminCheats/scripting/AdminCheats.sp create mode 100644 AdminIcon/scripting/AdminIcon.sp create mode 100644 AdvancedTargeting/scripting/AdvancedTargeting.sp create mode 100644 AdvancedTargeting/scripting/include/AdvancedTargeting.inc create mode 100644 AntiFlood/scripting/AntiFlood.sp create mode 100644 AntiJumpSpam/scripting/AntiJumpSpam.sp create mode 100644 AntiPingMask/scripting/AntiPingMask.sp create mode 100644 AutoRecorder/scripting/AutoRecorder.sp create mode 100644 ConVarSuppression/scripting/ConVarSuppression.sp create mode 100644 Extend/gamedata/Extend.games.txt create mode 100644 Extend/scripting/Extend.sp create mode 100644 ExtraCommands/scripting/ExtraCommands.sp create mode 100644 FixAngles/scripting/FixAngles.sp create mode 100644 FixGameUI/scripting/FixGameUI.sp create mode 100644 FixPlayerEquip/gamedata/FixPlayerEquip.games.txt create mode 100644 FixPlayerEquip/scripting/FixPlayerEquip.sp create mode 100644 FixPointTeleport/gamedata/FixPointTeleport.games.txt create mode 100644 FixPointTeleport/scripting/FixPointTeleport.sp create mode 100644 Flashlight/scripting/Flashlight.sp create mode 100644 ForceInputs/scripting/ForceInputs.sp create mode 100644 FullUpdate/gamedata/FullUpdate.games.txt create mode 100644 FullUpdate/scripting/FullUpdate.sp create mode 100644 FullUpdate/scripting/include/FullUpdate.inc create mode 100644 GlowColors/configs/GlowColors.cfg create mode 100644 GlowColors/scripting/GlowColors.sp create mode 100644 InfoMessage/configs/info_messages/test.txt create mode 100644 InfoMessage/scripting/InfoMessage.sp create mode 100644 KnifeAlert/scripting/KnifeAlert.sp create mode 100644 MapAdmin/configs/MapAdmin.cfg create mode 100644 MapAdmin/scripting/MapAdmin.sp create mode 100644 NameFilter/configs/NameFilter.cfg create mode 100644 NameFilter/scripting/NameFilter.sp create mode 100644 NapalmLagFix/gamedata/napalmlagfix.games.txt create mode 100644 NapalmLagFix/scripting/NapalmLagFix.sp create mode 100644 NoGrenadeRinging/gamedata/NoGrenadeRinging.games.txt create mode 100644 NoGrenadeRinging/scripting/NoGrenadeRinging.sp create mode 100644 NoShake/scripting/NoShake.sp create mode 100644 PlayerVisibility/scripting/PlayerVisibility.sp create mode 100644 PointServerCommandFilter/configs/PointServerCommandFilter.cfg create mode 100644 PointServerCommandFilter/configs/PointServerCommandFilter.example.cfg create mode 100644 PointServerCommandFilter/scripting/PointServerCommandFilter.sp create mode 100644 QuickSwitch/scripting/QuickSwitch.sp create mode 100644 RoundTime/scripting/RoundTime.sp create mode 100644 SaveLevel/configs/savelevel/ZE_FFVII_Mako_Reactor_V6_B08.cfg create mode 100644 SaveLevel/configs/savelevel/ze_FFVII_Mako_Reactor_v1_4_1.cfg create mode 100644 SaveLevel/configs/savelevel/ze_FFVII_Mako_Reactor_v3_1.cfg create mode 100644 SaveLevel/configs/savelevel/ze_FFXII_Feywood_b3_1.cfg create mode 100644 SaveLevel/configs/savelevel/ze_FFXII_Paramina_Rift_v1_3.cfg create mode 100644 SaveLevel/configs/savelevel/ze_FFXII_Paramina_Rift_v1_4.cfg create mode 100644 SaveLevel/configs/savelevel/ze_TESV_Skyrim_v3.cfg create mode 100644 SaveLevel/configs/savelevel/ze_harry_potter_v1_3.cfg create mode 100644 SaveLevel/configs/savelevel/ze_harry_potter_v2_1.cfg create mode 100644 SaveLevel/configs/savelevel/ze_lila_panic_escape_v3_1.cfg create mode 100644 SaveLevel/configs/savelevel/ze_lotr_minas_tirith_v2_2fix.cfg create mode 100644 SaveLevel/configs/savelevel/ze_lotr_minas_tirith_v3_5.cfg create mode 100644 SaveLevel/configs/savelevel/ze_tesv_skyrim_v4fix.cfg create mode 100644 SaveLevel/scripting/SaveLevel.sp create mode 100644 SelectiveBhop/scripting/SelectiveBhop.sp create mode 100644 SelectiveBhop/scripting/include/SelectiveBhop.inc create mode 100644 SlopeFix/scripting/SlopeFix.sp create mode 100644 SprayManager/content/materials/decals/spraymanager/1.vmt create mode 100644 SprayManager/content/materials/decals/spraymanager/1.vtf create mode 100644 SprayManager/content/materials/decals/spraymanager/2.vmt create mode 100644 SprayManager/content/materials/decals/spraymanager/2.vtf create mode 100644 SprayManager/content/materials/decals/spraymanager/3.vmt create mode 100644 SprayManager/content/materials/decals/spraymanager/3.vtf create mode 100644 SprayManager/scripting/SprayManager.sp create mode 100644 Status/gamedata/serverfps.games.txt create mode 100644 Status/scripting/Status.sp create mode 100644 Status/scripting/include/serverfps.inc create mode 100644 StopSound/scripting/StopSound.sp create mode 100644 StopSound/translations/plugin.stopsound.phrases.txt create mode 100644 SvGravityFix/scripting/SvGravityFix.sp create mode 100644 TeamManager/scripting/TeamManager.sp create mode 100644 Teleport/scripting/Teleport.sp create mode 100644 WeaponCleaner/scripting/WeaponCleaner.sp create mode 100644 custom-chatcolors/configs/custom-chatcolors.cfg create mode 100644 custom-chatcolors/configs/custom-chatcolorsbans.cfg create mode 100644 custom-chatcolors/configs/custom-chatcolorsreplace.cfg create mode 100644 custom-chatcolors/scripting/custom-chatcolors.sp create mode 100644 custom-chatcolors/scripting/include/ccc.inc create mode 100644 custom-chatcolors/translations/allchat.phrases.txt create mode 100644 entWatch/gamedata/plugin.entWatch.txt create mode 100644 entWatch/scripting/entWatch.sp create mode 100644 entWatch/scripting/include/entWatch.inc create mode 100644 entWatch/translations/entWatch.phrases.txt create mode 100644 entWatch/translations/fr/entWatch.phrases.txt create mode 100644 entWatch/translations/ru/entWatch.phrases.txt create mode 100644 includes/CSSFixes.inc create mode 100644 includes/SteamWorks.inc create mode 100644 includes/connect.inc create mode 100644 includes/dhooks.inc create mode 100644 includes/outputinfo.inc create mode 100644 includes/zombiereloaded.inc create mode 100644 includes/zr/class.zr.inc create mode 100644 includes/zr/infect.zr.inc create mode 100644 includes/zr/respawn.zr.inc diff --git a/AdminCheats/scripting/AdminCheats.sp b/AdminCheats/scripting/AdminCheats.sp new file mode 100644 index 0000000..36dac76 --- /dev/null +++ b/AdminCheats/scripting/AdminCheats.sp @@ -0,0 +1,130 @@ +#include + +#pragma semicolon 1 +#pragma newdecls required + +#define PLUGIN_VERSION "1.0" +public Plugin myinfo = +{ + name = "AdminCheats", + author = "BotoX", + description = "Allows usage of (most) cheat commands for admins.", + version = PLUGIN_VERSION, + url = "" +}; + +ConVar g_CVar_sv_cheats; + +public void OnPluginStart() +{ + g_CVar_sv_cheats = FindConVar("sv_cheats"); + g_CVar_sv_cheats.Flags &= ~FCVAR_NOTIFY; + g_CVar_sv_cheats.Flags &= ~FCVAR_REPLICATED; + g_CVar_sv_cheats.AddChangeHook(OnConVarChanged); + g_CVar_sv_cheats.SetInt(1); + + MakeCheatCommand("give"); + + int NumHooks = 0; + char sConCommand[128]; + bool IsCommand; + int Flags; + Handle hSearch = FindFirstConCommand(sConCommand, sizeof(sConCommand), IsCommand, Flags); + do + { + if(IsCommand && Flags & FCVAR_CHEAT) + { + AddCommandListener(OnCheatCommand, sConCommand); + NumHooks++; + } + } + while(FindNextConCommand(hSearch, sConCommand, sizeof(sConCommand), IsCommand, Flags)); + + AddCommandListener(OnCheatCommand, "kill"); NumHooks++; + AddCommandListener(OnCheatCommand, "explode"); NumHooks++; + + PrintToServer("Hooked %d cheat commands.", NumHooks); + + UpdateClients(); +} + +public void OnPluginEnd() +{ + g_CVar_sv_cheats.SetInt(0); + g_CVar_sv_cheats.Flags |= FCVAR_NOTIFY; + g_CVar_sv_cheats.Flags |= FCVAR_REPLICATED; +} + +public void OnConVarChanged(ConVar convar, const char[] oldValue, const char[] newValue) +{ + g_CVar_sv_cheats.SetInt(1); + CreateTimer(0.1, Timer_UpdateClients); +} + +public Action Timer_UpdateClients(Handle timer, Handle hndl) +{ + UpdateClients(); +} + +public void UpdateClients() +{ + for(int i = 1; i <= MaxClients; i++) + { + if(IsClientInGame(i) && !IsFakeClient(i) && IsClientAuthorized(i)) + OnClientPostAdminCheck(i); + } +} + +public void OnClientPutInServer(int client) +{ + if(IsFakeClient(client)) + return; + + SendConVarValue(client, g_CVar_sv_cheats, "0"); +} + +public void OnClientPostAdminCheck(int client) +{ + if(IsFakeClient(client)) + return; + + if(g_CVar_sv_cheats.BoolValue && CheckCommandAccess(client, "", ADMFLAG_CHEATS)) + SendConVarValue(client, g_CVar_sv_cheats, "1"); + else + SendConVarValue(client, g_CVar_sv_cheats, "0"); +} + +public Action OnCheatCommand(int client, const char[] command, int argc) +{ + if(client == 0) + return Plugin_Continue; + + if(IsClientAuthorized(client) && CheckCommandAccess(client, "", ADMFLAG_CHEATS)) + return Plugin_Continue; + + if(!argc && (StrEqual(command, "kill") || StrEqual(command, "explode"))) + return Plugin_Continue; + + return Plugin_Handled; +} + +public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3], float angles[3], int &weapon, int &subtype, int &cmdnum, int &tickcount, int &seed, int mouse[2]) +{ + if(!impulse) + return Plugin_Continue; + + if(impulse == 100 || impulse == 201) + return Plugin_Continue; + + if(IsClientAuthorized(client) && CheckCommandAccess(client, "", ADMFLAG_CHEATS)) + return Plugin_Continue; + + return Plugin_Handled; +} + +stock void MakeCheatCommand(const char[] name) +{ + int Flags = GetCommandFlags(name); + if(Flags != INVALID_FCVAR_FLAGS) + SetCommandFlags(name, FCVAR_CHEAT | Flags); +} diff --git a/AdminIcon/scripting/AdminIcon.sp b/AdminIcon/scripting/AdminIcon.sp new file mode 100644 index 0000000..8e91798 --- /dev/null +++ b/AdminIcon/scripting/AdminIcon.sp @@ -0,0 +1,73 @@ +#pragma semicolon 1 +#pragma newdecls required + +#include +#include +#include + +bool g_bIsAdmin[MAXPLAYERS + 1] = {false, ...}; + +public Plugin myinfo = +{ + name = "AdminIcon", + author = "BotoX", + description = "Gives admins a defuser.", + version = "1.0", + url = "" +}; + +public void OnPluginStart() +{ + for(int client = 1; client <= MaxClients; client++) + { + g_bIsAdmin[client] = false; + if(IsClientInGame(client) && !IsFakeClient(client) && IsClientAuthorized(client)) + OnClientPostAdminCheck(client); + } +} + +public void OnClientConnected(int client) +{ + g_bIsAdmin[client] = false; +} + +public void OnClientDisconnect(int client) +{ + g_bIsAdmin[client] = false; +} + +public void OnClientPostAdminCheck(int client) +{ + if(IsFakeClient(client)) + return; + + if(GetAdminFlag(GetUserAdmin(client), Admin_Generic)) + g_bIsAdmin[client] = true; +} + +public void OnGameFrame() +{ + for(int client = 1; client <= MaxClients; client++) + { + if(g_bIsAdmin[client]) + { + if(IsClientObserver(client)) + SetEntProp(client, Prop_Send, "m_bHasDefuser", 0); + else + SetEntProp(client, Prop_Send, "m_bHasDefuser", 1); + } + } +} + +public void OnEntityCreated(int entity, const char[] classname) +{ + if(IsValidEntity(entity) && StrEqual(classname, "item_defuser")) + { + SDKHook(entity, SDKHook_Spawn, OnWeaponSpawned); + } +} + +public void OnWeaponSpawned(int entity) +{ + AcceptEntityInput(entity, "Kill"); +} diff --git a/AdvancedTargeting/scripting/AdvancedTargeting.sp b/AdvancedTargeting/scripting/AdvancedTargeting.sp new file mode 100644 index 0000000..130bf0d --- /dev/null +++ b/AdvancedTargeting/scripting/AdvancedTargeting.sp @@ -0,0 +1,493 @@ +#pragma semicolon 1 + +#pragma dynamic 128*1024 + +#include +#include +#include +#include +#include + +#pragma newdecls required + +Handle g_FriendsArray[MAXPLAYERS + 1] = {INVALID_HANDLE, ...}; +bool g_bLateLoad = false; + +#include "SteamAPI.secret" //#define STEAM_API_KEY here + +public Plugin myinfo = +{ + name = "Advanced Targeting", + author = "BotoX + Obus", + description = "Adds extra targeting methods", + version = "1.2", + url = "https://github.com/CSSZombieEscape/sm-plugins/tree/master/AdvancedTargeting/" +} + +public void OnPluginStart() +{ + AddMultiTargetFilter("@admins", Filter_Admin, "Admins", false); + AddMultiTargetFilter("@!admins", Filter_NotAdmin, "Not Admins", false); + AddMultiTargetFilter("@friends", Filter_Friends, "Steam Friends", false); + AddMultiTargetFilter("@!friends", Filter_NotFriends, "Not Steam Friends", false); + AddMultiTargetFilter("@random", Filter_Random, "a Random Player", false); + AddMultiTargetFilter("@randomct", Filter_RandomCT, "a Random CT", false); + AddMultiTargetFilter("@randomt", Filter_RandomT, "a Random T", false); + + RegConsoleCmd("sm_admins", Command_Admins, "Currently online admins."); + RegConsoleCmd("sm_friends", Command_Friends, "Currently online friends."); + + if(g_bLateLoad) + { + char sSteam32ID[32]; + for(int i = 1; i <= MaxClients; i++) + { + if(IsClientInGame(i) && !IsFakeClient(i) && IsClientAuthorized(i) && + GetClientAuthId(i, AuthId_Steam2, sSteam32ID, sizeof(sSteam32ID))) + { + OnClientAuthorized(i, sSteam32ID); + } + } + } +} + +public void OnPluginEnd() +{ + RemoveMultiTargetFilter("@admins", Filter_Admin); + RemoveMultiTargetFilter("@!admins", Filter_NotAdmin); + RemoveMultiTargetFilter("@friends", Filter_Friends); + RemoveMultiTargetFilter("@!friends", Filter_NotFriends); + RemoveMultiTargetFilter("@random", Filter_Random); + RemoveMultiTargetFilter("@randomct", Filter_RandomCT); + RemoveMultiTargetFilter("@randomt", Filter_RandomT); +} + +public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) +{ + CreateNative("IsClientFriend", Native_IsClientFriend); + CreateNative("ReadClientFriends", Native_ReadClientFriends); + RegPluginLibrary("AdvancedTargeting"); + + g_bLateLoad = late; + return APLRes_Success; +} + +public Action Command_Admins(int client, int args) +{ + char aBuf[1024]; + char aBuf2[MAX_NAME_LENGTH]; + for(int i = 1; i <= MaxClients; i++) + { + if(IsClientInGame(i) && !IsFakeClient(i) && GetAdminFlag(GetUserAdmin(i), Admin_Generic)) + { + GetClientName(i, aBuf2, sizeof(aBuf2)); + StrCat(aBuf, sizeof(aBuf), aBuf2); + StrCat(aBuf, sizeof(aBuf), ", "); + } + } + + if(strlen(aBuf)) + { + aBuf[strlen(aBuf) - 2] = 0; + ReplyToCommand(client, "[SM] Admins currently online: %s", aBuf); + } + else + ReplyToCommand(client, "[SM] Admins currently online: none"); + + return Plugin_Handled; +} + +public Action Command_Friends(int client, int args) +{ + if(!client) + return Plugin_Handled; + + if(g_FriendsArray[client] == INVALID_HANDLE) + { + PrintToChat(client, "[SM] Could not read your friendslist, your profile must be set to public!"); + return Plugin_Handled; + } + + char aBuf[1024]; + char aBuf2[MAX_NAME_LENGTH]; + for(int i = 1; i <= MaxClients; i++) + { + if(IsClientInGame(i) && !IsFakeClient(i) && IsClientAuthorized(i)) + { + int Steam3ID = GetSteamAccountID(i); + + if(FindValueInArray(g_FriendsArray[client], Steam3ID) != -1) + { + GetClientName(i, aBuf2, sizeof(aBuf2)); + StrCat(aBuf, sizeof(aBuf), aBuf2); + StrCat(aBuf, sizeof(aBuf), ", "); + } + } + } + + if(strlen(aBuf)) + { + aBuf[strlen(aBuf) - 2] = 0; + PrintToChat(client, "[SM] Friends currently online: %s", aBuf); + } + else + PrintToChat(client, "[SM] Friends currently online: none"); + + return Plugin_Handled; +} + +public bool Filter_Admin(const char[] sPattern, Handle hClients, int client) +{ + for(int i = 1; i <= MaxClients; i++) + { + if(IsClientInGame(i) && !IsFakeClient(i) && GetAdminFlag(GetUserAdmin(i), Admin_Generic)) + { + PushArrayCell(hClients, i); + } + } + + return true; +} + +public bool Filter_NotAdmin(const char[] sPattern, Handle hClients, int client) +{ + for(int i = 1; i <= MaxClients; i++) + { + if(IsClientInGame(i) && !IsFakeClient(i) && !GetAdminFlag(GetUserAdmin(i), Admin_Generic)) + { + PushArrayCell(hClients, i); + } + } + + return true; +} + +public bool Filter_Friends(const char[] sPattern, Handle hClients, int client) +{ + if(g_FriendsArray[client] == INVALID_HANDLE) + { + PrintToChat(client, "[SM] Could not read your friendslist, your profile must be set to public!"); + return false; + } + + for(int i = 1; i <= MaxClients; i++) + { + if(i != client && IsClientInGame(i) && !IsFakeClient(i) && IsClientAuthorized(i)) + { + int Steam3ID = GetSteamAccountID(i); + + if(FindValueInArray(g_FriendsArray[client], Steam3ID) != -1) + PushArrayCell(hClients, i); + } + } + + return true; +} + +public bool Filter_NotFriends(const char[] sPattern, Handle hClients, int client) +{ + if(g_FriendsArray[client] == INVALID_HANDLE) + { + PrintToChat(client, "[SM] Could not read your friendslist, your profile must be set to public!"); + return false; + } + + for(int i = 1; i <= MaxClients; i++) + { + if(i != client && IsClientInGame(i) && !IsFakeClient(i) && IsClientAuthorized(i)) + { + int Steam3ID = GetSteamAccountID(i); + + if(FindValueInArray(g_FriendsArray[client], Steam3ID) == -1) + PushArrayCell(hClients, i); + } + } + + return true; +} + +public bool Filter_Random(const char[] sPattern, Handle hClients, int client) +{ + int iRand = GetRandomInt(1, MaxClients); + + if(IsClientInGame(iRand) && IsPlayerAlive(iRand)) + PushArrayCell(hClients, iRand); + else + Filter_Random(sPattern, hClients, client); + + return true; +} + +public bool Filter_RandomCT(const char[] sPattern, Handle hClients, int client) +{ + int iCTCount = GetTeamClientCount(CS_TEAM_CT); + + if(!iCTCount) + return false; + + int[] iCTs = new int[iCTCount]; + + int iCurIndex; + + for(int i = 1; i <= MaxClients; i++) + { + if(!IsClientInGame(i) || GetClientTeam(i) != CS_TEAM_CT) + continue; + + if(!IsPlayerAlive(i)) + { + iCTCount--; + continue; + } + + iCTs[iCurIndex] = i; + iCurIndex++; + } + + PushArrayCell(hClients, iCTs[GetRandomInt(0, iCTCount-1)]); + + return true; +} + +public bool Filter_RandomT(const char[] sPattern, Handle hClients, int client) +{ + int iTCount = GetTeamClientCount(CS_TEAM_T); + + if(!iTCount) + return false; + + int[] iTs = new int[iTCount]; + + int iCurIndex; + + for(int i = 1; i <= MaxClients; i++) + { + if(!IsClientInGame(i) || GetClientTeam(i) != CS_TEAM_T) + continue; + + if(!IsPlayerAlive(i)) + { + iTCount--; + continue; + } + + iTs[iCurIndex] = i; + iCurIndex++; + } + + PushArrayCell(hClients, iTs[GetRandomInt(0, iTCount-1)]); + + return true; +} + +public void OnClientAuthorized(int client, const char[] auth) +{ + if(IsFakeClient(client)) + return; + + char sSteam64ID[32]; + Steam32IDtoSteam64ID(auth, sSteam64ID, sizeof(sSteam64ID)); + + static char sRequest[256]; + FormatEx(sRequest, sizeof(sRequest), "http://api.steampowered.com/ISteamUser/GetFriendList/v0001/?key=%s&steamid=%s&relationship=friend&format=vdf", STEAM_API_KEY, sSteam64ID); + + Handle hRequest = SteamWorks_CreateHTTPRequest(k_EHTTPMethodGET, sRequest); + if (!hRequest || + !SteamWorks_SetHTTPRequestContextValue(hRequest, client) || + !SteamWorks_SetHTTPCallbacks(hRequest, OnTransferComplete) || + !SteamWorks_SendHTTPRequest(hRequest)) + { + CloseHandle(hRequest); + } +} + +public void OnClientDisconnect(int client) +{ + if(g_FriendsArray[client] != INVALID_HANDLE) + CloseHandle(g_FriendsArray[client]); + + g_FriendsArray[client] = INVALID_HANDLE; +} + +public int OnTransferComplete(Handle hRequest, bool bFailure, bool bRequestSuccessful, EHTTPStatusCode eStatusCode, int client) +{ + if(bFailure || !bRequestSuccessful || eStatusCode != k_EHTTPStatusCode200OK) + { + // Private profile or maybe steam down? + //LogError("SteamAPI HTTP Response failed: %d", eStatusCode); + CloseHandle(hRequest); + return; + } + + int Length; + SteamWorks_GetHTTPResponseBodySize(hRequest, Length); + + char[] sData = new char[Length]; + SteamWorks_GetHTTPResponseBodyData(hRequest, sData, Length); + //SteamWorks_GetHTTPResponseBodyCallback(hRequest, APIWebResponse, client); + + CloseHandle(hRequest); + + APIWebResponse(sData, client); +} + +public void APIWebResponse(const char[] sData, int client) +{ + KeyValues Response = new KeyValues("SteamAPIResponse"); + if(!Response.ImportFromString(sData, "SteamAPIResponse")) + { + LogError("ImportFromString(sData, \"SteamAPIResponse\") failed."); + delete Response; + return; + } + + if(!Response.JumpToKey("friends")) + { + LogError("JumpToKey(\"friends\") failed."); + delete Response; + return; + } + + // No friends? + if(!Response.GotoFirstSubKey()) + { + //LogError("GotoFirstSubKey() failed."); + delete Response; + return; + } + + if(g_FriendsArray[client] != INVALID_HANDLE) + CloseHandle(g_FriendsArray[client]); + + g_FriendsArray[client] = CreateArray(); + + char sCommunityID[32]; + do + { + Response.GetString("steamid", sCommunityID, sizeof(sCommunityID)); + + PushArrayCell(g_FriendsArray[client], Steam64toSteam3(sCommunityID)); + } + while(Response.GotoNextKey()); + + delete Response; +} + + +stock bool Steam32IDtoSteam64ID(const char[] sSteam32ID, char[] sSteam64ID, int Size) +{ + if(strlen(sSteam32ID) < 11 || strncmp(sSteam32ID[0], "STEAM_0:", 8)) + { + sSteam64ID[0] = 0; + return false; + } + + int iUpper = 765611979; + int isSteam64ID = StringToInt(sSteam32ID[10]) * 2 + 60265728 + sSteam32ID[8] - 48; + + int iDiv = isSteam64ID / 100000000; + int iIdx = 9 - (iDiv ? (iDiv / 10 + 1) : 0); + iUpper += iDiv; + + IntToString(isSteam64ID, sSteam64ID[iIdx], Size - iIdx); + iIdx = sSteam64ID[9]; + IntToString(iUpper, sSteam64ID, Size); + sSteam64ID[9] = iIdx; + + return true; +} + +stock int Steam64toSteam3(const char[] sSteam64ID) +{ + if(strlen(sSteam64ID) != 17) + return 0; + + // convert SteamID64 to array of integers + int aSteam64ID[17]; + for(int i = 0; i < 17; i++) + aSteam64ID[i] = sSteam64ID[i] - 48; + + // subtract individual SteamID64 identifier (0x0110000100000000) + int aSteam64IDIdent[] = {7, 6, 5, 6, 1, 1, 9, 7, 9, 6, 0, 2, 6, 5, 7, 2, 8}; + int Carry = 0; + for(int i = 16; i >= 0; i--) + { + if(aSteam64ID[i] < aSteam64IDIdent[i] + Carry) + { + aSteam64ID[i] = aSteam64ID[i] - aSteam64IDIdent[i] - Carry + 10; + Carry = 1; + } + else + { + aSteam64ID[i] = aSteam64ID[i] - aSteam64IDIdent[i] - Carry; + Carry = 0; + } + } + + char aBuf[17]; + int j = 0; + bool ZereosDone = false; + for(int i = 0; i < 17; i++) + { + if(!ZereosDone && !aSteam64ID[i]) + continue; + ZereosDone = true; + + aBuf[j++] = aSteam64ID[i] + 48; + } + + return StringToInt(aBuf); +} + +public int Native_IsClientFriend(Handle plugin, int numParams) +{ + int client = GetNativeCell(1); + int friend = GetNativeCell(2); + + if(client > MaxClients || client <= 0 || friend > MaxClients || friend <= 0) + { + ThrowNativeError(SP_ERROR_NATIVE, "Client is not valid."); + return -1; + } + + if(!IsClientInGame(client) || !IsClientInGame(friend)) + { + ThrowNativeError(SP_ERROR_NATIVE, "Client is not in-game."); + return -1; + } + + if(IsFakeClient(client) || IsFakeClient(friend)) + { + ThrowNativeError(SP_ERROR_NATIVE, "Client is fake-client."); + return -1; + } + + if(g_FriendsArray[client] == INVALID_HANDLE) + return -1; + + if(IsClientAuthorized(friend)) + { + int Steam3ID = GetSteamAccountID(friend); + + if(FindValueInArray(g_FriendsArray[client], Steam3ID) != -1) + return 1; + } + + return 0; +} + +public int Native_ReadClientFriends(Handle plugin, int numParams) +{ + int client = GetNativeCell(1); + + if(client > MaxClients || client <= 0) + { + ThrowNativeError(SP_ERROR_NATIVE, "Client is not valid."); + return -1; + } + + if(g_FriendsArray[client] != INVALID_HANDLE) + return 1; + + return 0; +} diff --git a/AdvancedTargeting/scripting/include/AdvancedTargeting.inc b/AdvancedTargeting/scripting/include/AdvancedTargeting.inc new file mode 100644 index 0000000..8ffd3ad --- /dev/null +++ b/AdvancedTargeting/scripting/include/AdvancedTargeting.inc @@ -0,0 +1,26 @@ +#if defined _AdvancedTargeting_Included + #endinput +#endif +#define _AdvancedTargeting_Included + +native int IsClientFriend(int client, int friend); +native int ReadClientFriends(int client); + +public SharedPlugin __pl_AdvancedTargeting = +{ + name = "AdvancedTargeting", + file = "AdvancedTargeting.smx", +#if defined REQUIRE_PLUGIN + required = 1, +#else + required = 0, +#endif +}; + +#if !defined REQUIRE_PLUGIN +public __pl_AdvancedTargeting_SetNTVOptional() +{ + MarkNativeAsOptional("IsClientFriend"); + MarkNativeAsOptional("ReadClientFriends"); +} +#endif diff --git a/AntiFlood/scripting/AntiFlood.sp b/AntiFlood/scripting/AntiFlood.sp new file mode 100644 index 0000000..8fa66f8 --- /dev/null +++ b/AntiFlood/scripting/AntiFlood.sp @@ -0,0 +1,71 @@ +#include + +#pragma semicolon 1 +#pragma newdecls required + +int g_Client_CommandCount[MAXPLAYERS + 1]; +float g_Client_LastFlood[MAXPLAYERS + 1]; + +#define MAX_COMMANDS 100 +#define INTERVAL 1.0 + +public Plugin myinfo = +{ + name = "AntiFlood", + author = "BotoX", + description = "", + version = "1.0", + url = "" +}; + +public void OnPluginStart() +{ + /* Late load */ + for(int client = 1; client <= MaxClients; client++) + { + if(IsClientInGame(client)) + OnClientConnected(client); + } + + AddCommandListener(OnAnyCommand, ""); +} + +public void OnClientConnected(int client) +{ + g_Client_CommandCount[client] = 0; + g_Client_LastFlood[client] = 0.0; +} + +//public Action OnClientCommand(int client, int args) +public Action OnAnyCommand(int client, const char[] command, int argc) +{ + if(FloodCheck(client)) + return Plugin_Handled; + + return Plugin_Continue; +} + +public void OnClientSettingsChanged(int client) +{ + FloodCheck(client); +} + +bool FloodCheck(int client) +{ + if(client <= 0 || client > MaxClients) + return false; + + if(++g_Client_CommandCount[client] <= MAX_COMMANDS) + return false; + + float Time = GetGameTime(); + if(Time >= g_Client_LastFlood[client] + INTERVAL) + { + g_Client_LastFlood[client] = Time; + g_Client_CommandCount[client] = 0; + return false; + } + + KickClientEx(client, "STOP FLOODING THE SERVER!!!"); + return true; +} diff --git a/AntiJumpSpam/scripting/AntiJumpSpam.sp b/AntiJumpSpam/scripting/AntiJumpSpam.sp new file mode 100644 index 0000000..d34550a --- /dev/null +++ b/AntiJumpSpam/scripting/AntiJumpSpam.sp @@ -0,0 +1,115 @@ +#pragma semicolon 1 + +#include +#include + +#undef REQUIRE_PLUGIN +#tryinclude +#define REQUIRE_PLUGIN + +#pragma newdecls required + +bool g_bZRLoaded; + +ConVar g_cvarJumpsUntilBlock = null; +ConVar g_cvarIntervalBetweenJumps = null; +ConVar g_cvarCooldownInterval = null; + +float g_fLastJumpTime[MAXPLAYERS + 1]; + +int g_iFastJumpCount[MAXPLAYERS + 1]; + +public Plugin myinfo = +{ + name = "Anti Jump Spam", + author = "Obus", + description = "Prevents clients from spamming jump to avoid knockback in crawl spaces.", + version = "1.0.0", + url = "" +} + +public void OnPluginStart() +{ + g_cvarJumpsUntilBlock = CreateConVar("sm_ajs_jumpsuntilblock", "5", "Successive jumps until anti jump-spam kicks in."); + g_cvarIntervalBetweenJumps = CreateConVar("sm_ajs_jumpinterval", "0.2", "If a client jumps faster than this their jumps will be blocked after the amount of jumps specified in \"sm_ajs_jumpsuntilblock\" is reached."); + g_cvarCooldownInterval = CreateConVar("sm_ajs_cooldowninterval", "0.0", "Changes the amount of time required for a jump to not be considered spam anymore. (Setting this to 0 makes the interval sm_ajs_jumpinterval * 2)"); + + AutoExecConfig(true, "plugin.antijumpspam"); +} + +public void OnAllPluginsLoaded() +{ + g_bZRLoaded = LibraryExists("zombiereloaded"); +} + +public void OnLibraryAdded(const char[] sName) +{ + if (strcmp(sName, "zombiereloaded", false) == 0) + g_bZRLoaded = true; +} + +public void OnLibraryRemoved(const char[] sName) +{ + if (strcmp(sName, "zombiereloaded", false) == 0) + g_bZRLoaded = false; +} + +public void OnClientDisconnect(int client) +{ + g_fLastJumpTime[client] = 0.0; + g_iFastJumpCount[client] = 0; +} + +public Action OnPlayerRunCmd(int client, int &buttons) +{ + static bool bHoldingJump[MAXPLAYERS + 1]; + +#if defined _zr_included + if (!IsPlayerAlive(client) || (g_bZRLoaded && !ZR_IsClientZombie(client)) || (!g_bZRLoaded && GetClientTeam(client) != CS_TEAM_T)) + return Plugin_Continue; +#else + if (!IsPlayerAlive(client) || GetClientTeam(client) != CS_TEAM_T) + return Plugin_Continue; +#endif + + if (buttons & IN_JUMP && GetEntityFlags(client) & FL_ONGROUND) + { + float fCurTime = GetEngineTime(); + float fTimeSinceLastJump = fCurTime - g_fLastJumpTime[client]; + + if (!bHoldingJump[client]) + { + if (fTimeSinceLastJump > (g_cvarCooldownInterval.FloatValue > 0.0 ? g_cvarCooldownInterval.FloatValue : g_cvarIntervalBetweenJumps.FloatValue * 2.0) && g_iFastJumpCount[client] > 0) + { + int iJumpsToDeduct = RoundToFloor(fTimeSinceLastJump / (g_cvarCooldownInterval.FloatValue > 0.0 ? g_cvarCooldownInterval.FloatValue : g_cvarIntervalBetweenJumps.FloatValue * 2)); + + iJumpsToDeduct = iJumpsToDeduct <= g_iFastJumpCount[client] ? iJumpsToDeduct : g_iFastJumpCount[client]; + + g_iFastJumpCount[client] -= iJumpsToDeduct; + } + } + + if (g_iFastJumpCount[client] >= g_cvarJumpsUntilBlock.IntValue) + { + buttons &= ~IN_JUMP; + + return Plugin_Continue; + } + + if (!bHoldingJump[client]) + { + bHoldingJump[client] = true; + + if (fTimeSinceLastJump < g_cvarIntervalBetweenJumps.FloatValue) + g_iFastJumpCount[client]++; + + g_fLastJumpTime[client] = fCurTime; + } + } + else if (bHoldingJump[client]) + { + bHoldingJump[client] = false; + } + + return Plugin_Continue; +} diff --git a/AntiPingMask/scripting/AntiPingMask.sp b/AntiPingMask/scripting/AntiPingMask.sp new file mode 100644 index 0000000..40a2cae --- /dev/null +++ b/AntiPingMask/scripting/AntiPingMask.sp @@ -0,0 +1,79 @@ +#pragma semicolon 1 +#pragma newdecls required + +#include +#include + +#define REMIND_INTERVAL 5.0 + +bool g_IsMasked[MAXPLAYERS + 1] = {false, ...}; + +public Plugin myinfo = +{ + name = "AntiPingMask", + author = "BotoX", + description = "Shows real ping when client tries to mask it.", + version = "1.0", + url = "" +}; + +public void OnClientDisconnect(int client) +{ + g_IsMasked[client] = false; +} + +public void OnMapStart() +{ + CreateTimer(REMIND_INTERVAL, Timer_Remind, _, TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE); +} + +public Action Timer_Remind(Handle Timer, any Data) +{ + for(int client = 1; client <= MaxClients; client++) + { + if(g_IsMasked[client] && IsClientInGame(client)) + PrintToChat(client, "[SM] Please turn off your pingmask! (cl_cmdrate 100)"); + } +} + +public void OnClientSettingsChanged(int client) +{ + static char sCmdRate[32]; + GetClientInfo(client, "cl_cmdrate", sCmdRate, sizeof(sCmdRate)); + bool bBadCmdRate = !IsNatural(sCmdRate); + + if(bBadCmdRate) + g_IsMasked[client] = true; + else + g_IsMasked[client] = false; +} + +public void OnGameFrame() +{ + for(int client = 1; client <= MaxClients; client++) + { + if(g_IsMasked[client]) + ForcePing(client); + } +} + +public void ForcePing(int client) +{ + int iResEnt = GetPlayerResourceEntity(); + if(iResEnt == -1) + return; + + int iLatency = RoundToNearest(GetClientAvgLatency(client, NetFlow_Outgoing) * 1000.0); + SetEntProp(iResEnt, Prop_Send, "m_iPing", iLatency, _, client); +} + +stock bool IsNatural(const char[] sString) +{ + for(int i = 0; sString[i]; i++) + { + if(!IsCharNumeric(sString[i])) + return false; + } + + return true; +} diff --git a/AutoRecorder/scripting/AutoRecorder.sp b/AutoRecorder/scripting/AutoRecorder.sp new file mode 100644 index 0000000..8ea8d01 --- /dev/null +++ b/AutoRecorder/scripting/AutoRecorder.sp @@ -0,0 +1,221 @@ +#pragma semicolon 1 +#include + +ConVar g_hTvEnabled; +ConVar g_hAutoRecord; +ConVar g_hMinPlayersStart; +ConVar g_hIgnoreBots; +ConVar g_hTimeStart; +ConVar g_hTimeStop; +ConVar g_hFinishMap; +ConVar g_hDemoPath; +ConVar g_hMaxLength; + +bool g_bIsRecording = false; +bool g_bIsManual = false; + +int g_iStartedRecording; + +// Default: o=rx,g=rx,u=rwx | 755 +#define DIRECTORY_PERMISSIONS (FPERM_O_READ|FPERM_O_EXEC | FPERM_G_READ|FPERM_G_EXEC | FPERM_U_READ|FPERM_U_WRITE|FPERM_U_EXEC) + +public Plugin myinfo = +{ + name = "Auto Recorder", + author = "Stevo.TVR", + description = "Automates SourceTV recording based on player count and time of day.", + version = "1.2.0", + url = "http://www.theville.org" +} + +public void OnPluginStart() +{ + g_hAutoRecord = CreateConVar("sm_autorecord_enable", "1", "Enable automatic recording", _, true, 0.0, true, 1.0); + g_hMinPlayersStart = CreateConVar("sm_autorecord_minplayers", "4", "Minimum players on server to start recording", _, true, 0.0); + g_hIgnoreBots = CreateConVar("sm_autorecord_ignorebots", "1", "Ignore bots in the player count", _, true, 0.0, true, 1.0); + g_hTimeStart = CreateConVar("sm_autorecord_timestart", "-1", "Hour in the day to start recording (0-23, -1 disables)"); + g_hTimeStop = CreateConVar("sm_autorecord_timestop", "-1", "Hour in the day to stop recording (0-23, -1 disables)"); + g_hFinishMap = CreateConVar("sm_autorecord_finishmap", "1", "If 1, continue recording until the map ends", _, true, 0.0, true, 1.0); + g_hDemoPath = CreateConVar("sm_autorecord_path", "demos/", "Path to store recorded demos"); + g_hMaxLength = CreateConVar("sm_autorecord_maxlength", "0", "Maximum length of demos in seconds, 0 to disable", _, true, 0.0); + + AutoExecConfig(true, "autorecorder"); + + RegAdminCmd("sm_record", Command_Record, ADMFLAG_KICK, "Starts a SourceTV demo"); + RegAdminCmd("sm_stoprecord", Command_StopRecord, ADMFLAG_KICK, "Stops the current SourceTV demo"); + + HookEvent("round_start", OnRoundStart); + + g_hTvEnabled = FindConVar("tv_enable"); + + static char sPath[PLATFORM_MAX_PATH]; + GetConVarString(g_hDemoPath, sPath, sizeof(sPath)); + + if(!DirExists(sPath)) + CreateDirectory(sPath, DIRECTORY_PERMISSIONS); + + HookConVarChange(g_hMinPlayersStart, OnConVarChanged); + HookConVarChange(g_hIgnoreBots, OnConVarChanged); + HookConVarChange(g_hTimeStart, OnConVarChanged); + HookConVarChange(g_hTimeStop, OnConVarChanged); + HookConVarChange(g_hDemoPath, OnConVarChanged); + + CreateTimer(300.0, Timer_CheckStatus, _, TIMER_REPEAT); + + StopRecord(); + CheckStatus(); +} + +public void OnRoundStart(Event hEvent, const char[] sEvent, bool bDontBroadcast) +{ + int maxLength = GetConVarInt(g_hMaxLength); + if(g_bIsRecording && maxLength > 0 && GetTime() >= g_iStartedRecording + maxLength) + { + StopRecord(); + CheckStatus(); + } +} + +public void OnConVarChanged(ConVar convar, const char[] oldValue, const char[] newValue) +{ + if(convar == g_hDemoPath) + { + if(!DirExists(newValue)) + CreateDirectory(newValue, DIRECTORY_PERMISSIONS); + } + else + CheckStatus(); +} + +public void OnMapEnd() +{ + if(g_bIsRecording) + { + StopRecord(); + g_bIsManual = false; + } +} + +public void OnClientPutInServer(int client) +{ + CheckStatus(); +} + +public void OnClientDisconnect_Post(int client) +{ + CheckStatus(); +} + +public Action Timer_CheckStatus(Handle hTimer) +{ + CheckStatus(); +} + +public Action Command_Record(int client, int args) +{ + if(g_bIsRecording) + { + ReplyToCommand(client, "[SM] SourceTV is already recording!"); + return Plugin_Handled; + } + + StartRecord(); + g_bIsManual = true; + + ReplyToCommand(client, "[SM] SourceTV is now recording..."); + + return Plugin_Handled; +} + +public Action Command_StopRecord(int client, int args) +{ + if(!g_bIsRecording) + { + ReplyToCommand(client, "[SM] SourceTV is not recording!"); + return Plugin_Handled; + } + + StopRecord(); + + if(g_bIsManual) + { + g_bIsManual = false; + CheckStatus(); + } + + ReplyToCommand(client, "[SM] Stopped recording."); + + return Plugin_Handled; +} + +void CheckStatus() +{ + if(GetConVarBool(g_hAutoRecord) && !g_bIsManual) + { + int iMinClients = GetConVarInt(g_hMinPlayersStart); + + int iTimeStart = GetConVarInt(g_hTimeStart); + int iTimeStop = GetConVarInt(g_hTimeStop); + bool bReverseTimes = (iTimeStart > iTimeStop); + + static char sCurrentTime[4]; + FormatTime(sCurrentTime, sizeof(sCurrentTime), "%H", GetTime()); + int iCurrentTime = StringToInt(sCurrentTime); + + if(GetPlayerCount() >= iMinClients+1 && (iTimeStart < 0 || (iCurrentTime >= iTimeStart && (bReverseTimes || iCurrentTime < iTimeStop)))) + { + StartRecord(); + } + else if(g_bIsRecording && !GetConVarBool(g_hFinishMap) && (iTimeStop < 0 || iCurrentTime >= iTimeStop)) + { + StopRecord(); + } + } +} + +int GetPlayerCount() +{ + if(!GetConVarBool(g_hIgnoreBots)) + return GetClientCount(false) - 1; + + int iNumPlayers = 0; + for(int i = 1; i <= MaxClients; i++) + { + if(IsClientConnected(i) && !IsFakeClient(i)) + iNumPlayers++; + } + + return iNumPlayers; +} + +void StartRecord() +{ + if(GetConVarBool(g_hTvEnabled) && !g_bIsRecording) + { + static char sPath[PLATFORM_MAX_PATH]; + static char sMap[PLATFORM_MAX_PATH]; + static char sTime[16]; + + GetConVarString(g_hDemoPath, sPath, sizeof(sPath)); + FormatTime(sTime, sizeof(sTime), "%Y%m%d-%H%M%S", GetTime()); + GetCurrentMap(sMap, sizeof(sMap)); + + // replace slashes in map path name with dashes, to prevent fail on workshop maps + ReplaceString(sMap, sizeof(sMap), "/", "-", false); + + ServerCommand("tv_record \"%s/auto-%s-%s\"", sPath, sTime, sMap); + g_bIsRecording = true; + g_iStartedRecording = GetTime(); + + LogMessage("Recording to auto-%s-%s.dem", sTime, sMap); + } +} + +void StopRecord() +{ + if(GetConVarBool(g_hTvEnabled)) + { + ServerCommand("tv_stoprecord"); + g_bIsRecording = false; + } +} diff --git a/ConVarSuppression/scripting/ConVarSuppression.sp b/ConVarSuppression/scripting/ConVarSuppression.sp new file mode 100644 index 0000000..b0cd80d --- /dev/null +++ b/ConVarSuppression/scripting/ConVarSuppression.sp @@ -0,0 +1,118 @@ +#pragma semicolon 1 +#include + +#define PLUGIN_PREFIX "\x04[ConVar Suppression]\x03 " +#define PLUGIN_VERSION "1.0" + +new Handle:g_hGlobalTrie = INVALID_HANDLE; + +public Plugin:myinfo = +{ + name = "ConVar Suppression", /* https://www.youtube.com/watch?v=ZhjtChtUmBE&hd=1 */ + author = "Kyle Sanderson", + description = "Atleast we have candy.", + version = PLUGIN_VERSION, + url = "http://www.SourceMod.net/" +}; + +public OnPluginStart() +{ + g_hGlobalTrie = CreateTrie(); + HookEvent("server_cvar", Event_ServerCvar, EventHookMode_Pre); + RegAdminCmd("sm_suppressconvar", OnSupressConVar, ADMFLAG_ROOT, "Supress a ConVar from displaying changes to Clients."); + + CreateConVar("sm_convarsuppression_version", PLUGIN_VERSION, "Version string for ConVar Supression.", FCVAR_REPLICATED|FCVAR_DONTRECORD|FCVAR_NOTIFY); + + AutoExecConfig(true, "plugin.ConVarSupression"); +} + +public Action:OnSupressConVar(client, argc) +{ + if (client && !IsClientInGame(client)) /* Isn't needed, but makes me feel safe inside. */ + { + return Plugin_Handled; + } + + decl String:sCommand[256]; + + if (argc < 2) + { + if (!GetCmdArg(0, sCommand, sizeof(sCommand))) + { + return Plugin_Handled; + } + + ReplyToCommand(client, "%s%s ", PLUGIN_PREFIX, sCommand); + return Plugin_Handled; + } + + if (!GetCmdArg(2, sCommand, sizeof(sCommand))) + { + return Plugin_Handled; + } + + TrimString(sCommand); + new iValue = -1; + + if (!IsCharNumeric(sCommand[0])) + { + switch (CharToLower(sCommand[0])) + { + case 'd': + { + iValue = 0; + } + + case 'e': + { + iValue = 1; + } + } + } + else + { + iValue = StringToInt(sCommand); + } + + if (!GetCmdArg(1, sCommand, sizeof(sCommand))) + { + return Plugin_Handled; + } + + switch (iValue) + { + case 0: + { + RemoveFromTrie(g_hGlobalTrie, sCommand); + if (client) + { + ReplyToCommand(client, "%sRemoved ConVar: %s", PLUGIN_PREFIX, sCommand); + } + } + + case 1: + { + SetTrieValue(g_hGlobalTrie, sCommand, 1, true); + if (client) + { + ReplyToCommand(client, "%sAdded Hook for ConVar: %s", PLUGIN_PREFIX, sCommand); + } + } + + default: + { + ReplyToCommand(client, "%sIllegal Input for Enabled/Disabled with ConVar: %s", PLUGIN_PREFIX, sCommand); + } + } + + return Plugin_Handled; +} + +public Action:Event_ServerCvar(Handle:event, const String:name[], bool:dontBroadcast) +{ + decl String:sConVarName[64]; + new iValue; + + GetEventString(event, "cvarname", sConVarName, sizeof(sConVarName)); + return (GetTrieValue(g_hGlobalTrie, sConVarName, iValue) && iValue) ? Plugin_Handled : Plugin_Continue; +} \ No newline at end of file diff --git a/Extend/gamedata/Extend.games.txt b/Extend/gamedata/Extend.games.txt new file mode 100644 index 0000000..3c6177e --- /dev/null +++ b/Extend/gamedata/Extend.games.txt @@ -0,0 +1,25 @@ +"Games" +{ + "#default" + { + "Addresses" + { + "GameOver" + { + "linux" + { + "signature" "g_fGameOver" + } + } + } + + "Signatures" + { + "g_fGameOver" + { + "library" "server" + "linux" "@g_fGameOver" + } + } + } +} diff --git a/Extend/scripting/Extend.sp b/Extend/scripting/Extend.sp new file mode 100644 index 0000000..442bcca --- /dev/null +++ b/Extend/scripting/Extend.sp @@ -0,0 +1,387 @@ +#pragma semicolon 1 +#pragma newdecls required + +#include +#include + +#define VOTE_NO "###no###" +#define VOTE_YES "###yes###" + +ConVar g_cvarExtendVoteTime = null; +ConVar g_cvarExtendVotePercent = null; +ConVar g_cvarMpMaxRounds = null; +ConVar g_cvarMpFragLimit = null; +ConVar g_cvarMpWinLimit = null; +ConVar g_cvarMpTimeLimit = null; + +bool g_bGameOver = false; +Address g_pGameOver; + +public Plugin myinfo = +{ + name = "Map extend tools", + author = "Obus + BotoX", + description = "Adds map extension commands.", + version = "1.0", + url = "" +}; + +public void OnPluginStart() +{ + LoadTranslations("common.phrases"); + LoadTranslations("basevotes.phrases"); + + g_cvarMpMaxRounds = FindConVar("mp_maxrounds"); + g_cvarMpFragLimit = FindConVar("mp_fraglimit"); + g_cvarMpWinLimit = FindConVar("mp_winlimit"); + g_cvarMpTimeLimit = FindConVar("mp_timelimit"); + + g_cvarExtendVoteTime = CreateConVar("sm_extendvote_time", "15", "Time that will be added to mp_timelimit shall the extend vote succeed", FCVAR_NONE, true, 1.0); + g_cvarExtendVotePercent = CreateConVar("sm_extendvote_percent", "0.6", "Percentage of \"yes\" votes required to consider the vote successful", FCVAR_NONE, true, 0.05, true, 1.0); + + AutoExecConfig(true, "plugin.Extend"); + + if (g_cvarMpMaxRounds != null) + RegAdminCmd("sm_extend_rounds", Command_Extend_Rounds, ADMFLAG_GENERIC, "Add more rounds to mp_maxrounds"); + else + LogMessage("Failed to find \"mp_maxrounds\" console variable, related commands will be disabled."); + + if (g_cvarMpFragLimit != null) + RegAdminCmd("sm_extend_frags", Command_Extend_Frags, ADMFLAG_GENERIC, "Add more frags to mp_fraglimit"); + else + LogMessage("Failed to find \"mp_fraglimit\" console variable, related commands will be disabled."); + + if (g_cvarMpWinLimit != null) + RegAdminCmd("sm_extend_wins", Command_Extend_Wins, ADMFLAG_GENERIC, "Add more wins to mp_winlimit"); + else + LogMessage("Failed to find \"mp_winlimit\" console variable, related commands will be disabled."); + + if (g_cvarMpTimeLimit != null) + { + RegAdminCmd("sm_extend", Command_Extend, ADMFLAG_GENERIC, "Add more time to mp_timelimit"); + RegAdminCmd("sm_extend_time", Command_Extend, ADMFLAG_GENERIC, "Add more time to mp_timelimit"); + RegAdminCmd("sm_extendvote", Command_ExtendVote, ADMFLAG_GENERIC, "sm_extendvote [time] - Start an extendvote"); + RegAdminCmd("sm_voteextend", Command_ExtendVote, ADMFLAG_GENERIC, "sm_voteextend [time] - Start an extendvote"); + RegAdminCmd("sm_extend_vote", Command_ExtendVote, ADMFLAG_GENERIC, "sm_extend_vote [time] - Start an extendvote"); + } + else + { + LogMessage("Failed to find \"mp_timelimit\" console variable, related commands will be disabled."); + } + + Handle hGameConf = LoadGameConfigFile("Extend.games"); + if(hGameConf == INVALID_HANDLE) + { + g_bGameOver = false; + LogError("Couldn't load Extend.games game config! GameOver cancel disabled."); + return; + } + + if(!(g_pGameOver = GameConfGetAddress(hGameConf, "GameOver"))) + { + g_bGameOver = false; + CloseHandle(hGameConf); + LogError("Couldn't get GameOver address from game config! GameOver cancel disabled."); + return; + } + + g_bGameOver = true; + CloseHandle(hGameConf); +} + +public Action Command_Extend_Rounds(int client, int argc) +{ + if (argc < 1) + { + ReplyToCommand(client, "[SM] Usage: sm_extend_rounds "); + return Plugin_Handled; + } + + char sArgs[16]; + + GetCmdArg(1, sArgs, sizeof(sArgs)); + + if (sArgs[0] == '-') + { + int iRoundsToDeduct; + + if (!StringToIntEx(sArgs[1], iRoundsToDeduct)) + { + ReplyToCommand(client, "[SM] Invalid value"); + return Plugin_Handled; + } + + g_cvarMpMaxRounds.IntValue -= iRoundsToDeduct; + + LogAction(client, -1, "\"%L\" deducted \"%d\" rounds from \"mp_maxrounds\"", client, iRoundsToDeduct); + + return Plugin_Handled; + } + + int iRoundsToAdd; + + if (!StringToIntEx(sArgs, iRoundsToAdd)) + { + ReplyToCommand(client, "[SM] Invalid value"); + return Plugin_Handled; + } + + g_cvarMpMaxRounds.IntValue += iRoundsToAdd; + CancelGameOver(); + + LogAction(client, -1, "\"%L\" added \"%d\" rounds to \"mp_maxrounds\"", client, iRoundsToAdd); + + return Plugin_Handled; +} + +public Action Command_Extend_Frags(int client, int argc) +{ + if (argc < 1) + { + ReplyToCommand(client, "[SM] Usage: sm_extend_frags "); + return Plugin_Handled; + } + + char sArgs[16]; + + GetCmdArg(1, sArgs, sizeof(sArgs)); + + if (sArgs[0] == '-') + { + int iFragsToDeduct; + + if (!StringToIntEx(sArgs[1], iFragsToDeduct)) + { + ReplyToCommand(client, "[SM] Invalid value"); + return Plugin_Handled; + } + + g_cvarMpFragLimit.IntValue -= iFragsToDeduct; + + LogAction(client, -1, "\"%L\" deducted \"%d\" frags from \"mp_fraglimit\"", client, iFragsToDeduct); + + return Plugin_Handled; + } + + int iFragsToAdd; + + if (!StringToIntEx(sArgs, iFragsToAdd)) + { + ReplyToCommand(client, "[SM] Invalid value"); + return Plugin_Handled; + } + + g_cvarMpFragLimit.IntValue += iFragsToAdd; + CancelGameOver(); + + LogAction(client, -1, "\"%L\" added \"%d\" frags to \"mp_fraglimit\"", client, iFragsToAdd); + + return Plugin_Handled; +} + +public Action Command_Extend_Wins(int client, int argc) +{ + if (argc < 1) + { + ReplyToCommand(client, "[SM] Usage: sm_extend_wins "); + return Plugin_Handled; + } + + char sArgs[16]; + + GetCmdArg(1, sArgs, sizeof(sArgs)); + + if (sArgs[0] == '-') + { + int iWinsToDeduct; + + if (!StringToIntEx(sArgs[1], iWinsToDeduct)) + { + ReplyToCommand(client, "[SM] Invalid value"); + return Plugin_Handled; + } + + g_cvarMpWinLimit.IntValue -= iWinsToDeduct; + + LogAction(client, -1, "\"%L\" deducted \"%d\" wins from \"mp_winlimit\"", client, iWinsToDeduct); + + return Plugin_Handled; + } + + int iWinsToAdd; + + if (!StringToIntEx(sArgs, iWinsToAdd)) + { + ReplyToCommand(client, "[SM] Invalid value"); + return Plugin_Handled; + } + + g_cvarMpWinLimit.IntValue += iWinsToAdd; + CancelGameOver(); + + LogAction(client, -1, "\"%L\" added \"%d\" wins to \"mp_winlimit\"", client, iWinsToAdd); + + return Plugin_Handled; +} + +public Action Command_Extend(int client, int argc) +{ + if (argc < 1) + { + ReplyToCommand(client, "[SM] Usage: sm_extend