diff --git a/csgo-knifehp.smx b/csgo-knifehp.smx new file mode 100644 index 0000000..6430586 Binary files /dev/null and b/csgo-knifehp.smx differ diff --git a/csgo-knifehp.sp b/csgo-knifehp.sp new file mode 100644 index 0000000..7f2ad7c --- /dev/null +++ b/csgo-knifehp.sp @@ -0,0 +1,68 @@ +#pragma semicolon 1 + +#define DEBUG + +#define PLUGIN_NAME "CSGO Knife Regen" +#define PLUGIN_AUTHOR "jackzmc" +#define PLUGIN_VERSION "1.00" +#define PLUGIN_DESCRIPTION "" + +#include +#include +#include +//#include + +EngineVersion g_Game; + +public Plugin myinfo = +{ + name = PLUGIN_NAME, + author = PLUGIN_AUTHOR, + description = PLUGIN_DESCRIPTION, + version = PLUGIN_VERSION, + url = "" +}; + +ConVar g_bKnifeHPEnabled, g_iKnifeHPMax, g_iKnifeHPRegain; + +public OnPluginStart() +{ + g_Game = GetEngineVersion(); + if (g_Game != Engine_CSGO && g_Game != Engine_CSS) + { + SetFailState("This plugin is for CSGO/CSS only."); + } + + g_bKnifeHPEnabled = CreateConVar("knifehp_enable", "1", "Enable regaining health on knife kill", FCVAR_NONE, true, 0.0, true, 1.0); + g_iKnifeHPMax = CreateConVar("knifehp_max_health", "100", "Maximum health to set an attacker to", FCVAR_NONE, true, 0.0); + g_iKnifeHPRegain = CreateConVar("knifehp_amount", "100", "Amount of health to give attacker", FCVAR_NONE, true, 0.0); + HookEvent("player_death", Event_PlayerDeath); + + AutoExecConfig(true, "csgo_knifehp"); +} + +public void Event_PlayerDeath(Event event, const char[] name, bool dontBroadcast) +{ + if (g_bKnifeHPEnabled.BoolValue) { + char weapon_name[64]; + event.GetString("weapon", weapon_name, sizeof(weapon_name)); + if (StrContains(weapon_name, "knife", false) > -1) { + int attacker = event.GetInt("attacker"); + int client = GetClientOfUserId(attacker); + + //get the new health value (current client hp + the regen amount) + int new_health = GetClientHealth(client) + g_iKnifeHPRegain.IntValue; + //50 + 20 <= max + if (IsClientInGame(client) && IsPlayerAlive(client) && !IsFakeClient(client)) { + if(new_health <= g_iKnifeHPMax.IntValue) { //if the new health is less than max, set it to it + SetEntityHealth(client, new_health); + }else{ //if > max, set it to max + SetEntityHealth(client, g_iKnifeHPMax.IntValue); + } + } + + } + + + } +} \ No newline at end of file diff --git a/l4d2-info-cmd.smx b/l4d2-info-cmd.smx new file mode 100644 index 0000000..63e6d19 Binary files /dev/null and b/l4d2-info-cmd.smx differ diff --git a/l4d2-info-cmd.sp b/l4d2-info-cmd.sp new file mode 100644 index 0000000..3a174a8 --- /dev/null +++ b/l4d2-info-cmd.sp @@ -0,0 +1,192 @@ +#pragma semicolon 1 + +#define DEBUG + +#define PLUGIN_NAME "L4D2 Game Info" +#define PLUGIN_DESCRIPTION "" +#define PLUGIN_AUTHOR "jackzmc" +#define PLUGIN_VERSION "1.0" + +#include +#include +//#include + +bool g_icAFK[MAXPLAYERS + 1]; +char g_icDifficulty[16] = "Normal"; + +public Plugin myinfo = +{ + name = PLUGIN_NAME, + author = PLUGIN_AUTHOR, + description = PLUGIN_DESCRIPTION, + version = PLUGIN_VERSION, + url = "" +}; + +public OnPluginStart() +{ + EngineVersion g_Game = GetEngineVersion(); + if(g_Game != Engine_Left4Dead && g_Game != Engine_Left4Dead2) + { + SetFailState("This plugin is for L4D/L4D2 only."); + } + RegConsoleCmd("sm_gameinfo", PrintGameInfo, "Show the director main menu"); + HookEvent("difficulty_changed", Event_DifficultyChanged); + HookEvent("player_afk", Event_PlayerAfk); + HookEvent("player_bot_replace", Event_PlayerBotReplace); + FindConVar("z_difficulty").GetString(g_icDifficulty, sizeof(g_icDifficulty)); +} +// print info +public Action PrintGameInfo(int client, int args) { + //print server info + ReplyToCommand(client, ">map,diff"); + char map[32]; + + GetCurrentMap(map, sizeof(map)); + + ReplyToCommand(client, "%s,%s",map,g_icDifficulty); + //print client info + ReplyToCommand(client,">id,name,bot,health,status,afk,throwSlot,kitSlot,pillSlot,modelName"); + for (int i = 1; i < MaxClients;i++) { + if (!IsClientConnected(i)) continue; + if (GetClientTeam(i) != 2) continue; + int hp = GetClientRealHealth(i); + int bot = GetSteamAccountID(i, false) == 0; + int afk = g_icAFK[i]; + bool incap = IsPlayerIncapped(i); + bool blackandwhite = IsPlayerNearDead(i); + + char status[9]; + char name[32]; + char pillType[32]; + char kitType[32]; + char throwType[32]; + char survType[9]; + + if(hp < 0) { + status = "dead"; + }else if(incap) { + status = "incap"; + }else if(blackandwhite) { + status = "neardead"; + }else{ + status = "alive"; + } + int pillWpn = GetPlayerWeaponSlot(i, 4); //pills slot + int kitWpn = GetPlayerWeaponSlot(i, 3); + int throwWpn = GetPlayerWeaponSlot(i, 2); + if(pillWpn != -1) GetEdictClassname(pillWpn, pillType, sizeof(pillType)); + if(kitWpn != -1) GetEdictClassname(kitWpn, kitType, sizeof(kitType)); + if(throwWpn != -1) GetEdictClassname(throwWpn, throwType, sizeof(throwType)); + ReplaceString(pillType, sizeof(pillType), "weapon_", ""); + ReplaceString(kitType, sizeof(kitType), "weapon_", ""); + ReplaceString(throwType, sizeof(throwType), "weapon_", ""); + + GetClientName(i, name, sizeof(name)); + GetModelName(i, survType, sizeof(survType)); + + ReplyToCommand(client,"%d,%s,%d,%d,%s,%d,%s,%s,%s,%s", i, name, bot, hp, status, afk, throwType, kitType, pillType, survType); + } + +} +// EVENTS // +public void Event_DifficultyChanged(Event event, const char[] name, bool dontBroadcast) { + event.GetString("newDifficulty",g_icDifficulty,sizeof(g_icDifficulty)); +} +public void Event_PlayerAfk(Event event, const char[] name, bool dontBroadcast) { + g_icAFK[GetClientOfUserId(event.GetInt("player"))] = true; +} +public void Event_PlayerBotReplace(Event event, const char[] name, bool dontBroadcast) { + g_icAFK[GetClientOfUserId(event.GetInt("player"))] = false; +} + +// METHODS // +bool IsPlayerIncapped(int client) +{ + if (GetEntProp(client, Prop_Send, "m_isIncapacitated", 1)) return true; + return false; +} +bool IsPlayerNearDead(int client) { + if (GetEntProp(client, Prop_Send, "m_bIsOnThirdStrike", 1)) return true; + return false; +} + +stock void GetModelName(int client, char[] buffer, int length) { + char modelName[38]; + GetClientModel(client, modelName, sizeof(modelName)); + if(StrContains(modelName,"biker",false) > -1) { + strcopy(buffer, length, "Francis"); + }else if(StrContains(modelName,"teenangst",false) > -1) { + strcopy(buffer, length, "Zoey"); + }else if(StrContains(modelName,"namvet",false) > -1) { + strcopy(buffer, length, "Bill"); + }else if(StrContains(modelName,"manager",false) > -1) { + strcopy(buffer, length, "Louis"); + }else if(StrContains(modelName,"coach",false) > -1) { + strcopy(buffer, length, "Coach"); + }else if(StrContains(modelName,"producer",false) > -1) { + strcopy(buffer, length, "Rochelle"); + }else if(StrContains(modelName,"gambler",false) > -1) { + strcopy(buffer, length, "Nick"); + }else if(StrContains(modelName,"mechanic",false) > -1) { + strcopy(buffer, length, "Ellis"); + } +} + +stock GetClientRealHealth(client) +{ + //First filter -> Must be a valid client, successfully in-game and not an spectator (The dont have health). + if(!client + || !IsValidEntity(client) + || !IsClientInGame(client) + || !IsPlayerAlive(client) + || IsClientObserver(client)) + { + return -1; + } + + //If the client is not on the survivors team, then just return the normal client health. + if(GetClientTeam(client) != 2) + { + return GetClientHealth(client); + } + + //First, we get the amount of temporal health the client has + float buffer = GetEntPropFloat(client, Prop_Send, "m_healthBuffer"); + + //We declare the permanent and temporal health variables + float TempHealth; + int PermHealth = GetClientHealth(client); + + //In case the buffer is 0 or less, we set the temporal health as 0, because the client has not used any pills or adrenaline yet + if(buffer <= 0.0) + { + TempHealth = 0.0; + } + + //In case it is higher than 0, we proceed to calculate the temporl health + else + { + //This is the difference between the time we used the temporal item, and the current time + float difference = GetGameTime() - GetEntPropFloat(client, Prop_Send, "m_healthBufferTime"); + + //We get the decay rate from this convar (Note: Adrenaline uses this value) + float decay = GetConVarFloat(FindConVar("pain_pills_decay_rate")); + + //This is a constant we create to determine the amount of health. This is the amount of time it has to pass + //before 1 Temporal HP is consumed. + float constant = 1.0/decay; + + //Then we do the calcs + TempHealth = buffer - (difference / constant); + } + + //If the temporal health resulted less than 0, then it is just 0. + if(TempHealth < 0.0) + { + TempHealth = 0.0; + } + + //Return the value + return RoundToFloor(PermHealth + TempHealth); +} \ No newline at end of file diff --git a/l4d2-manual-director.smx b/l4d2-manual-director.smx new file mode 100644 index 0000000..84a8c9d Binary files /dev/null and b/l4d2-manual-director.smx differ diff --git a/l4d2-manual-director.sp b/l4d2-manual-director.sp new file mode 100644 index 0000000..bec5bc8 --- /dev/null +++ b/l4d2-manual-director.sp @@ -0,0 +1,258 @@ +#pragma semicolon 1 +#pragma newdecls required + +#define DEBUG + +#define PLUGIN_NAME "L4D2 Manual Director" +#define PLUGIN_DESCRIPTION "Tell the director to spawn specials manually, even bypassing limits" +#define PLUGIN_AUTHOR "jackzmc" +#define PLUGIN_VERSION "1.2" + +#include +#include + +ConVar g_cMdNotify, g_cMdEnableTank, g_cMdEnableWitch, g_cMdEnableMob, g_cMdAnnounceLevel; +bool g_bMdIsL4D2 = false; + +public Plugin myinfo = +{ + name = PLUGIN_NAME, + author = PLUGIN_AUTHOR, + description = PLUGIN_DESCRIPTION, + version = PLUGIN_VERSION, + url = "" +}; +public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) +{ + EngineVersion test = GetEngineVersion(); + if (test != Engine_Left4Dead2 && test != Engine_Left4Dead) + { + strcopy(error, err_max, "Plugin only supports Left 4 Dead [2]."); + return APLRes_SilentFailure; + } + if (test == Engine_Left4Dead2) { + g_bMdIsL4D2 = true; + } + return APLRes_Success; +} + +public void OnPluginStart() +{ + CreateConVar("manual_director_version", PLUGIN_VERSION, "Manual Director Version", FCVAR_SPONLY | FCVAR_DONTRECORD); + CreateConVar("mandirector_version", PLUGIN_VERSION, "Manual Director Version", FCVAR_SPONLY | FCVAR_DONTRECORD); + + g_cMdNotify = CreateConVar("mandirector_notify_spawn", "0", "Should spawning specials notify on use?", FCVAR_NONE, true, 0.0, true, 1.0); + g_cMdAnnounceLevel = CreateConVar("mandirector_announce_level", "0", "Announcement types. 0 - None, 1 - Only bosses, 2 - Only specials+, 3 - Everything", FCVAR_NONE, true, 0.0, true, 3.0); + g_cMdEnableTank = CreateConVar("mandirector_enable_tank", "1", "Should tanks be allowed to be spawned?", FCVAR_NONE, true, 0.0, true, 1.0); + g_cMdEnableWitch = CreateConVar("mandirector_enable_witch", "1", "Should witches be allowed to be spawned?", FCVAR_NONE, true, 0.0, true, 1.0); + g_cMdEnableMob = CreateConVar("mandirector_enable_mob", "1", "Should mobs be allowed to be spawned?", FCVAR_NONE, true, 0.0, true, 1.0); + + + RegAdminCmd("sm_spawnspecial", Command_SpawnSpecial, ADMFLAG_CHEATS, "Spawn a special via director"); + RegAdminCmd("sm_forcespecial", Command_SpawnSpecialForce, ADMFLAG_CHEATS, "Force spawn a special via director, bypassing spawn limits"); + RegAdminCmd("sm_forcecursor", Command_SpawnSpecialForceLocal, ADMFLAG_CHEATS, "Force spawn a special at cursor, bypassing spawn limits"); + RegAdminCmd("sm_cursormenu", ShowLocalSpecialMenu, ADMFLAG_CHEATS, "Show the spawn menu for cursor spawning"); + RegAdminCmd("sm_specialmenu", ShowSpecialMenu, ADMFLAG_CHEATS, "Show the spawn menu for director spawning"); + RegAdminCmd("sm_directormenu", ShowSpecialMenu, ADMFLAG_CHEATS, "Show the director main menu"); + PrintToServer("Manual Director V"...PLUGIN_VERSION..." is now loaded."); + AutoExecConfig(true, "l4d2_manual_director"); +} + +public Action Command_SpawnSpecial(int client, int args) { + char arg1[32]; + GetCmdArg(1, arg1, sizeof(arg1)); + int executioner = GetAnyValidClient(); + if (args < 1) { + ReplyToCommand(client, "[SM] Usage: sm_spawnspecial - Requests a special to spawn via director", arg1); + } else { + if (executioner <= 0) { + ReplyToCommand(client, "[SM] Cannot spawn a %s as there are no players online.", arg1); + } else { + if (StrEqual(arg1, "mob", false) && !g_cMdEnableMob.BoolValue) { + ReplyToCommand(client, "[SM] Spawning mobs has been disabled."); + } else if (StrEqual(arg1, "witch", false) && !g_cMdEnableWitch.BoolValue) { + ReplyToCommand(client, "[SM] Spawning witches has been disabled."); + } else if (StrEqual(arg1, "tank", false) && !g_cMdEnableTank.BoolValue) { + ReplyToCommand(client, "[SM] Spawning tanks has been disabled."); + } else { + CheatCommand(executioner, g_bMdIsL4D2 ? "z_spawn_old" : "z_spawn", arg1, "auto"); + if (g_cMdNotify.BoolValue) { + ReplyToCommand(client, "[SM] Director will now attempt to spawn a %s.", arg1); + } + AnnounceSpawn(arg1); + LogAction(client, -1, "\"%L\" spawned a \"%s\"", client, arg1); + } + } + } + return Plugin_Handled; +} +public Action Command_SpawnSpecialForceLocal(int client, int args) { + char arg1[32]; + GetCmdArg(1, arg1, sizeof(arg1)); + if (args < 1) { + ReplyToCommand(client, "[SM] Usage: sm_forcecursor - Requests a special to spawn at cursor", arg1); + } else { + int bot = CreateFakeClient("ManualDirectorBot"); + if (bot != 0) { + ChangeClientTeam(bot, 3); + CreateTimer(0.1, kickbot, bot); + } + CheatCommand(client, g_bMdIsL4D2 ? "z_spawn_old" : "z_spawn", arg1,""); + if (g_cMdNotify.BoolValue) { + ReplyToCommand(client, "[SM] Spawned a %s.", arg1); + } + AnnounceSpawn(arg1); + LogAction(client, -1, "\"%L\" spawned a \"%s\"", client, arg1); + } + return Plugin_Handled; +} + +public Action Command_SpawnSpecialForce(int client, int args) { + char arg1[32]; + GetCmdArg(1, arg1, sizeof(arg1)); + int executioner = GetAnyValidClient(); + if (args < 1) { + ReplyToCommand(client, "[SM] Usage: sm_forcespecial - Requests a special to spawn via director", arg1); + } else { + if (executioner <= 0) { + ReplyToCommand(client, "[SM] Cannot spawn a %s as there are no players online.", arg1); + } else { + int bot = CreateFakeClient("ManualDirectorBot"); + if (bot != 0) { + ChangeClientTeam(bot, 3); + CreateTimer(0.1, kickbot, bot); + } + CheatCommand(executioner, g_bMdIsL4D2 ? "z_spawn_old" : "z_spawn", arg1, "auto"); + if (g_cMdNotify.BoolValue) { + ReplyToCommand(client, "[SM] Spawned a %s.", arg1); + } + AnnounceSpawn(arg1); + LogAction(client, -1, "\"%L\" spawned a \"%s\"", client, arg1); + } + } + return Plugin_Handled; +} +public Action ShowSpecialMenu(int client, int args) { + + Menu menu = new Menu(Handle_SpawnMenu); + menu.SetTitle("Manual Director - Auto"); + if (g_bMdIsL4D2) { + menu.AddItem("jockey", "Jockey"); + menu.AddItem("charger", "Charger"); + menu.AddItem("spitter", "Spitter"); + } + menu.AddItem("hunter", "Hunter"); + menu.AddItem("smoker", "Smoker"); + menu.AddItem("boomer", "Boomer"); + if (g_cMdEnableWitch.BoolValue)menu.AddItem("witch", "Witch"); + if (g_cMdEnableTank.BoolValue)menu.AddItem("tank", "Tank"); + if (g_cMdEnableMob.BoolValue)menu.AddItem("mob", "Mob"); + menu.ExitButton = true; + menu.Display(client, 0); +} +public Action ShowLocalSpecialMenu(int client, int args) { + Menu menu = new Menu(Handle_LocalSpawnMenu); + menu.SetTitle("Manual Director - Cursor"); + menu.AddItem("common", "Single Common"); + if (g_bMdIsL4D2) { + menu.AddItem("jockey", "Jockey"); + menu.AddItem("charger", "Charger"); + menu.AddItem("spitter", "Spitter"); + } + menu.AddItem("hunter", "Hunter"); + menu.AddItem("smoker", "Smoker"); + menu.AddItem("boomer", "Boomer"); + if (g_cMdEnableWitch.BoolValue) menu.AddItem("witch", "Witch"); + if (g_cMdEnableTank.BoolValue) menu.AddItem("tank", "Tank"); + if (g_cMdEnableMob.BoolValue) menu.AddItem("mob", "Mob"); + menu.ExitButton = true; + menu.Display(client, 0); +} + +public int Handle_SpawnMenu(Menu menu, MenuAction action, int client, int index) +{ + /* If an option was selected, tell the client about the item. */ + if (action == MenuAction_Select) + { + char info[32]; + menu.GetItem(index, info, sizeof(info)); + FakeClientCommand(client, "sm_forcespecial %s", info); + ShowSpecialMenu(client, 0); + //PrintToConsole(param1, "You selected item: %d (found? %d info: %s)", index, found, info); + } + /* If the menu was cancelled, print a message to the server about it. */ + else if (action == MenuAction_Cancel) + { + PrintToServer("Client %d's menu was cancelled. Reason: %d", client, index); + } + /* If the menu has ended, destroy it */ + else if (action == MenuAction_End) + { + delete menu; + } +} +public int Handle_LocalSpawnMenu(Menu menu, MenuAction action, int client, int index) +{ + if (action == MenuAction_Select) + { + char info[32]; + menu.GetItem(index, info, sizeof(info)); + FakeClientCommand(client, "sm_forcecursor %s", info); + ShowLocalSpecialMenu(client, 0); + } + else if (action == MenuAction_Cancel) + { + PrintToServer("Client %d's menu was cancelled. Reason: %d", client, index); + } + else if (action == MenuAction_End) + { + delete menu; + } +} + +stock Action kickbot(Handle timer, int client) +{ + if (IsClientInGame(client) && (!IsClientInKickQueue(client))) + { + if (IsFakeClient(client))KickClient(client); + } +} + + +stock int GetAnyValidClient() +{ + for (int i = 1; i <= MaxClients; i++) + { + if (IsClientInGame(i) && !IsFakeClient(i)) + { + return i; + } + } + return -1; +} + +stock void CheatCommand(int client, char[] command, char[] argument1, char[] argument2) +{ + int userFlags = GetUserFlagBits(client); + SetUserFlagBits(client, ADMFLAG_ROOT); + int flags = GetCommandFlags(command); + SetCommandFlags(command, flags & ~FCVAR_CHEAT); + FakeClientCommand(client, "%s %s %s", command, argument1, argument2); + SetCommandFlags(command, flags); + SetUserFlagBits(client, userFlags); +} + +void AnnounceSpawn(char[] type) { + switch(g_cMdAnnounceLevel.IntValue) { + case 1: + if(StrEqual(type,"tank") || StrEqual(type,"witch")) { + PrintToChatAll("A %s has spawned!", type); + } + case 2: + if(!StrEqual(type,"mob") && !StrEqual(type,"common") && !StrEqual(type,"panic")) { + PrintToChatAll("A %s has spawned!", type); + } + case 3: + PrintToChatAll("A %s has spawned!", type); + } +} \ No newline at end of file