Skip to content

Commit

Permalink
Remove GhostTank incap functionality
Browse files Browse the repository at this point in the history
- Removed "Flying Incap" functionality from confoglcompmod.
- Added a plugin to deal with this instead, blocking the damage and then applying the "deserved" damage later.
- This fixes #740 and additional issues that could be caused by player_incapacitated triggering multiple times on a downed player (such as stat recording, etc.)
  • Loading branch information
SirPlease committed Feb 23, 2024
1 parent df16784 commit 727011b
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 39 deletions.
Binary file modified addons/sourcemod/plugins/confoglcompmod.smx
Binary file not shown.
Binary file not shown.
39 changes: 0 additions & 39 deletions addons/sourcemod/scripting/confoglcompmod/GhostTank.sp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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");
Expand All @@ -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);
}
Expand Down Expand Up @@ -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();
Expand Down
142 changes: 142 additions & 0 deletions addons/sourcemod/scripting/l4d2_tank_flying_incap.sp
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
#pragma semicolon 1
#pragma newdecls required

#include <sourcemod>
#include <sdkhooks>
#define L4D2UTIL_STOCKS_ONLY 1
#include <l4d2util>

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);
}
1 change: 1 addition & 0 deletions cfg/generalfixes.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 727011b

Please sign in to comment.