diff --git a/addons/sourcemod/plugins/confoglcompmod.smx b/addons/sourcemod/plugins/confoglcompmod.smx index eb03298f1..9121f3bc5 100644 Binary files a/addons/sourcemod/plugins/confoglcompmod.smx and b/addons/sourcemod/plugins/confoglcompmod.smx differ diff --git a/addons/sourcemod/plugins/fixes/l4d2_tank_flying_incap.smx b/addons/sourcemod/plugins/fixes/l4d2_tank_flying_incap.smx new file mode 100644 index 000000000..918d56de2 Binary files /dev/null and b/addons/sourcemod/plugins/fixes/l4d2_tank_flying_incap.smx differ diff --git a/addons/sourcemod/scripting/confoglcompmod/GhostTank.sp b/addons/sourcemod/scripting/confoglcompmod/GhostTank.sp index 324c8674f..af5611265 100644 --- a/addons/sourcemod/scripting/confoglcompmod/GhostTank.sp +++ b/addons/sourcemod/scripting/confoglcompmod/GhostTank.sp @@ -29,7 +29,6 @@ static ConVar g_hCvarZMobSpawnMaxIntervalNormal = null, g_hCvarMobSpawnMinSize = null, g_hCvarMobSpawnMaxSize = null, - g_hCvarSurvivorIncapHealth = null, g_hGT_RemoveEscapeTank = null, g_hGT_BlockPunchRock = null, g_hGT_DisableTankHordes = null; // Disable Tank Hordes items @@ -47,7 +46,6 @@ void GT_OnModuleStart() g_hGT_DisableTankHordes = CreateConVarEx("disable_tank_hordes", "0", "Disable natural hordes while tanks are in play", _, true, 0.0, true, 1.0); g_hGT_BlockPunchRock = CreateConVarEx("block_punch_rock", "0", "Block tanks from punching and throwing a rock at the same time", _, true, 0.0, true, 1.0); - g_hCvarSurvivorIncapHealth = FindConVar("survivor_incap_health"); g_hCvarTankThrowAllowRange = FindConVar("tank_throw_allow_range"); g_hCvarDirectorTankLotterySelectionTime = FindConVar("director_tank_lottery_selection_time"); g_hCvarZMobSpawnMinIntervalNormal = FindConVar("z_mob_spawn_min_interval_normal"); @@ -60,7 +58,6 @@ void GT_OnModuleStart() HookEvent("player_death", GT_TankKilled); HookEvent("player_hurt", GT_TankOnFire); HookEvent("item_pickup", GT_ItemPickup); - HookEvent("player_incapacitated", GT_PlayerIncap); HookEvent("finale_vehicle_incoming", GT_FinaleVehicleIncoming, EventHookMode_PostNoCopy); HookEvent("finale_vehicle_ready", GT_FinaleVehicleIncoming, EventHookMode_PostNoCopy); } @@ -245,42 +242,6 @@ static void GT_TankOnFire(Event hEvent, const char[] sEventName, bool bDontBroad SetEntityHealth(client, iSetHealth); } -static void GT_PlayerIncap(Event hEvent, const char[] sEventName, bool bDontBroadcast) -{ - if (!g_bGT_TankIsInPlay || !IsPluginEnabled() || !g_hGT_Enabled.BoolValue) { - return; - } - - char weapon[MAX_ENTITY_NAME_LENGTH]; - hEvent.GetString("weapon", weapon, sizeof(weapon)); - - if (strcmp(weapon, "tank_claw") != 0) { - return; - } - - int userid = hEvent.GetInt("userid"); - int client = GetClientOfUserId(userid); - if (client < 1 || !IsClientInGame(client) || GetClientTeam(client) != L4D2Team_Survivor) { - return; - } - - SetEntProp(client, Prop_Send, "m_isIncapacitated", 0, 1); - SetEntityHealth(client, 1); - - CreateTimer(0.4, GT_IncapTimer, userid, TIMER_FLAG_NO_MAPCHANGE); -} - -static Action GT_IncapTimer(Handle hTimer, int userid) -{ - int client = GetClientOfUserId(userid); - if (client > 0) { - SetEntProp(client, Prop_Send, "m_isIncapacitated", 1, 1); - SetEntityHealth(client, g_hCvarSurvivorIncapHealth.IntValue); - } - - return Plugin_Stop; -} - static Action GT_ResumeTankTimer(Handle hTimer) { GT_ResumeTank(); diff --git a/addons/sourcemod/scripting/l4d2_tank_flying_incap.sp b/addons/sourcemod/scripting/l4d2_tank_flying_incap.sp new file mode 100644 index 000000000..db3697afd --- /dev/null +++ b/addons/sourcemod/scripting/l4d2_tank_flying_incap.sp @@ -0,0 +1,142 @@ +#pragma semicolon 1 +#pragma newdecls required + +#include +#include +#define L4D2UTIL_STOCKS_ONLY 1 +#include + +int iSurvivorIncapHealth = 300; + +bool + bLateLoad, + bDebug = false; + +ConVar + convarDebug, + convarSurvivorIncapHealth = null; + +public Plugin myinfo = +{ + name = "[L4D2] Flying Incap - Tank Punch", + author = "Sir", + description = "Sends Survivors flying on the incapping punch.", + version = "1.0", + url = "https://github.com/SirPlease/L4D2-Competitive-Rework" +}; + +public APLRes AskPluginLoad2(Handle plugin, bool late, char[] error, int errMax) +{ + bLateLoad = late; + return APLRes_Success; +} + +public void OnPluginStart() +{ + if (bLateLoad) + { + for (int i = 1; i < MaxClients+1; i++) + { + if (IsClientInGame(i)) + { + OnClientPutInServer(i); + } + } + } + + convarDebug = CreateConVar("l4d2_tank_flying_incap_debug", "0", "Are we debugging?"); + convarSurvivorIncapHealth = FindConVar("survivor_incap_health"); + bDebug = convarDebug.BoolValue; + iSurvivorIncapHealth = convarSurvivorIncapHealth.IntValue; + convarDebug.AddChangeHook(CvarsChanged); + convarSurvivorIncapHealth.AddChangeHook(CvarsChanged); +} + +public void OnClientPutInServer(int client) +{ + SDKHook(client, SDKHook_OnTakeDamage, OnTakeDamage); +} + +public void OnClientDisconnect(int client) +{ + SDKUnhook(client, SDKHook_OnTakeDamage, OnTakeDamage); +} + +public Action OnTakeDamage(int victim, int &attacker, int &inflictor, float &damage, int &damagetype) +{ + if (damagetype != DMG_CLUB) + return Plugin_Continue; + + if (!IsValidSurvivor(victim) || !IsValidTank(attacker)) + return Plugin_Continue; + + if (inflictor <= MaxClients || !IsValidEdict(inflictor)) + return Plugin_Continue; + + char sClassName[ENTITY_MAX_NAME_LENGTH]; + GetEdictClassname(inflictor, sClassName, sizeof(sClassName)); + + if (strcmp("weapon_tank_claw", sClassName) == 0) + { + if (!IsIncapacitated(victim)) + { + int iTotalHealth = GetSurvivorPermanentHealth(victim) + GetSurvivorTemporaryHealth(victim); + + if (iTotalHealth <= damage) + { + if (bDebug) + PrintToChatAll("[FlyingIncap]: %N got hit by Tank and has %i HP on incapping punch", victim, iTotalHealth); + + DataPack dp; + CreateDataTimer(0.4, Timer_ApplyDamageLater, dp, TIMER_FLAG_NO_MAPCHANGE); + dp.WriteCell(GetClientUserId(victim)); + dp.WriteCell(GetClientUserId(attacker)); + dp.WriteCell(inflictor); + dp.WriteCell(iTotalHealth); + + SetEntityHealth(victim, 1); + SetTempHealth(victim, 0.0); + damage = 0.0; + return Plugin_Changed; + } + } + } + return Plugin_Continue; +} + +Action Timer_ApplyDamageLater(Handle timer, DataPack dp) +{ + dp.Reset(); + int iSurvivor = GetClientOfUserId(dp.ReadCell()); + int iTank = GetClientOfUserId(dp.ReadCell()); + int iInflictor = dp.ReadCell(); + float damage = float(dp.ReadCell()); + damage = damage >= 1.0 ? damage : 1.0; + + if (iSurvivor > 0) + { + iTank = iTank > 0 ? iTank : 0; + + if (bDebug) + PrintToChatAll("[FlyingIncap]: Applied %0.2f damage to %N", damage, iSurvivor); + + SDKHooks_TakeDamage(iSurvivor, iInflictor, iTank, damage, DMG_CLUB, WEPID_TANK_CLAW); + + if (IsIncapacitated(iSurvivor)) + SetEntityHealth(iSurvivor, iSurvivorIncapHealth); + } + + return Plugin_Stop; +} + +void CvarsChanged(ConVar convar, const char[] oldValue, const char[] newValue) +{ + bDebug = convarDebug.BoolValue; + iSurvivorIncapHealth = convarSurvivorIncapHealth.IntValue; +} + +void SetTempHealth(int client, float fHealth) +{ + SetEntPropFloat(client, Prop_Send, "m_healthBufferTime", GetGameTime()); + SetEntPropFloat(client, Prop_Send, "m_healthBuffer", fHealth); +} \ No newline at end of file diff --git a/cfg/generalfixes.cfg b/cfg/generalfixes.cfg index 3eed43b02..ec68b6407 100644 --- a/cfg/generalfixes.cfg +++ b/cfg/generalfixes.cfg @@ -63,6 +63,7 @@ sm plugins load fixes/l4d2_changelevel.smx sm plugins load fixes/weapon_spawn_duplicate_fix.smx sm plugins load fixes/l4d_fix_common_shove.smx sm plugins load fixes/l4d2_null_cusercmd_fix.smx +sm plugins load fixes/l4d2_tank_flying_incap.smx // Anti-Cheat. sm plugins load anticheat/l4d2_noghostcheat.smx