Update bin/includes

This commit is contained in:
Jackz 2023-05-07 08:44:32 -05:00
parent 8c2ca6453c
commit d23503099b
No known key found for this signature in database
GPG key ID: E0BBD94CF657F603
19 changed files with 1115 additions and 431 deletions

View file

@ -363,7 +363,8 @@ public Action Timer_UpdateGrab(Handle timer, DataPack pack) {
// *** Runs whether in rotation mode or not
float entNewPos[3];
GetEntNewPosition(client, entNewPos);
int buttons = GetClientButtons(client);
GetEntNewPosition(client, entNewPos, buttons & IN_SPEED == 0);
entNewPos[0] += g_fGrabOffset[client][0];
entNewPos[1] += g_fGrabOffset[client][1];
entNewPos[2] += g_fGrabOffset[client][2];
@ -426,14 +427,14 @@ int GetLookingEntity(int client, TraceEntityFilter filter) {
static float pos[3], ang[3];
GetClientEyePosition(client, pos);
GetClientEyeAngles(client, ang);
TR_TraceRayFilter(pos, ang, MASK_OPAQUE, RayType_Infinite, filter, client);
TR_TraceRayFilter(pos, ang, MASK_ALL, RayType_Infinite, filter, client);
if(TR_DidHit()) {
return TR_GetEntityIndex();
}
return -1;
}
stock bool GetEntNewPosition(int client, float endPos[3])
stock bool GetEntNewPosition(int client, float endPos[3], bool doCollision = true)
{
if (client > 0 && client <= MaxClients && IsClientInGame(client)) {
float clientEye[3], clientAngle[3], direction[3];
@ -444,9 +445,11 @@ stock bool GetEntNewPosition(int client, float endPos[3])
ScaleVector(direction, g_fGrabDistance[client]);
AddVectors(clientEye, direction, endPos);
TR_TraceRayFilter(clientEye, endPos, MASK_OPAQUE, RayType_EndPoint, TraceRayFilterEnt, client);
if (TR_DidHit(INVALID_HANDLE)) {
TR_GetEndPosition(endPos);
if(doCollision) {
TR_TraceRayFilter(clientEye, endPos, MASK_OPAQUE, RayType_EndPoint, TraceRayFilterEnt, client);
if (TR_DidHit(INVALID_HANDLE)) {
TR_GetEndPosition(endPos);
}
}
return true;
}

View file

@ -52,9 +52,9 @@ void SetupsTrollCombos() {
#if defined _behavior_included
combo.AddTroll("Witch Magnet");
#endif
combo.AddTroll("No Button Touchie", TrollMod_Constant, 17);
combo.AddTroll("Slow Speed", TrollMod_Constant, 2);
combo.AddTroll("Instant Commons", TrollMod_Instant, 1);
combo.AddTroll("No Button Touchie", 17, TrollMod_Constant);
combo.AddTroll("Slow Speed", 2, TrollMod_Constant);
combo.AddTroll("Instant Commons", 1, TrollMod_Instant);
// combo.AddTroll("Swarm", TrollMod_Instant);
combo.AddTroll("Vomit Player");
combo.AddTroll("Dull Melee", .flags=2);

View file

@ -218,6 +218,35 @@ public Action Event_WeaponReload(int weapon) {
}
return Plugin_Continue;
}
public Action L4D2_CGasCan_EventKilled(int gascan, int &inflictor, int &attacker) {
static int noButtonPressIndex;
if(!noButtonPressIndex) noButtonPressIndex = GetTrollID("No Button Touchie");
if(attacker > 0 && attacker <= MaxClients) {
if(Trolls[noButtonPressIndex].IsActive(attacker)) {
if(Trolls[noButtonPressIndex].activeFlagClients[attacker] & 1) {
return Plugin_Handled;
}
if(Trolls[noButtonPressIndex].activeFlagClients[attacker] & 2) {
L4D_CTerrorPlayer_OnVomitedUpon(attacker, attacker);
}
if(Trolls[noButtonPressIndex].activeFlagClients[attacker] & 4) {
L4D_SetPlayerIncapacitatedState(attacker, true);
}
if(Trolls[noButtonPressIndex].activeFlagClients[attacker] & 8) {
ServerCommand("sm_slay #%d", GetClientUserId(attacker));
}
if(Trolls[noButtonPressIndex].activeFlagClients[attacker] & 16) {
float speed = GetEntPropFloat(attacker, Prop_Send, "m_flLaggedMovementValue");
if(speed > 0.9) speed = 0.80;
speed -= 5.0;
SetEntPropFloat(attacker, Prop_Send, "m_flLaggedMovementValue", speed);
PrintToConsoleAdmins("[FTT] NoButtonTouchie: %N speed is now %f", speed);
}
}
lastButtonUser = attacker;
}
return Plugin_Continue;
}
public Action Event_ButtonPress(const char[] output, int entity, int client, float delay) {
static int noButtonPressIndex;
if(!noButtonPressIndex) noButtonPressIndex = GetTrollID("No Button Touchie");

View file

@ -740,6 +740,23 @@ stock void HSVToRGBInt(const float vec[3], int out[3]) {
out[2] = RoundToFloor(view_as<float>(out[2]));
}
stock bool GetCursorLocation(int client, float outPos[3]) {
float angle[3];
GetClientEyePosition(client, outPos);
GetClientEyeAngles(client, angle);
TR_TraceRayFilter(outPos, angle, MASK_SOLID, RayType_Infinite, Filter_IgnorePlayer, client);
if(TR_DidHit()) {
TR_GetEndPosition(outPos);
return true;
} else {
return false;
}
}
bool Filter_IgnorePlayer(int entity, int mask, int data) {
return entity > 0 && entity != data;
}
// Gets a position from where the cursor is upto distance away (basically <= distance, going against walls)
stock bool GetCursorLimited(int client, float distance, float endPos[3], TraceEntityFilter filter)
{

View file

@ -18,7 +18,7 @@
* Copyright (C) 2017 "Accelerator74"
*
* Left 4 DHooks Direct SourceMod plugin
* Copyright (C) 2022 "SilverShot" / "Silvers"
* Copyright (C) 2023 "SilverShot" / "Silvers"
*
* =============================================================================
*
@ -58,13 +58,13 @@
// Natives: 252 (including 3 for L4D1 only)
// L4D1 = 31 [left4downtown] + 47 [l4d_direct] + 16 [l4d2addresses] + 56 [silvers - mine!] + 4 [anim] = 154
// L4D2 = 61 [left4downtown] + 59 [l4d_direct] + 31 [l4d2addresses] + 94 [silvers - mine!] + 4 [anim] = 249
// Natives: 253 (including 3 for L4D1 only)
// L4D1 = 31 [left4downtown] + 47 [l4d_direct] + 16 [l4d2addresses] + 58 [silvers - mine!] + 4 [anim] = 156
// L4D2 = 61 [left4downtown] + 59 [l4d_direct] + 31 [l4d2addresses] + 95 [silvers - mine!] + 4 [anim] = 250
// Forwards: 183 (including 2 for L4D1 only)
// L4D1 = 129
// L4D2 = 181
// Forwards: 188 (including 2 for L4D1 only)
// L4D1 = 132
// L4D2 = 186
// Stocks: 168 (L4D1 = 111, L4D2 = 164)
// left4dhooks_silver 45 stocks (L4D1 = 38, L4D2 = 52)
@ -1058,6 +1058,40 @@ forward void L4D_OnEnterGhostState(int client);
*/
forward void L4D_OnEnterGhostState_PostHandled(int client);
/**
* @brief Called whenever CTerrorPlayer::TakeOverBot(CTerrorPlayer*) is invoked
* @remarks This happens when player is looking to take over a bot
*
* @param client the client that is looking to take over a bot
*
* @return Plugin_Handled to block, Plugin_Continue otherwise
*/
forward Action L4D_OnTakeOverBot(int client);
/**
* @brief Called whenever CTerrorPlayer::TakeOverBot(CTerrorPlayer*) is invoked
* @remarks This happens when player is looking to take over a bot
* @remarks This forward will not trigger if the relative pre-hook forward has been blocked with Plugin_Handled
*
* @param client the client that is looking to take over a bot
* @param success true if the takeover was successful, false otherwise
*
* @noreturn
*/
forward void L4D_OnTakeOverBot_Post(int client, bool success);
/**
* @brief Called whenever CTerrorPlayer::TakeOverBot(CTerrorPlayer*) is invoked
* @remarks This happens when player is looking to take over a bot
* @remarks This forward will ONLY trigger if the relative pre-hook forward has been blocked with Plugin_Handled
*
* @param client the client that is looking to take over a bot
* @param success true if the takeover was successful, false otherwise
*
* @noreturn
*/
forward void L4D_OnTakeOverBot_PostHandled(int client, bool success);
/**
* @brief Called whenever CTerrorPlayer::MaterializeFromGhost is invoked
* @remarks Called when a Special Infected spawns out of ghost mode.
@ -2471,7 +2505,7 @@ forward void L4D_OnGrabWithTongue_PostHandled(int victim, int attacker);
*
* @return Plugin_Handled to block, Plugin_Continue otherwise
*/
// L4D2 only.
// L4D2 only.
forward Action L4D2_OnJockeyRide(int victim, int attacker);
/**
@ -2484,7 +2518,7 @@ forward Action L4D2_OnJockeyRide(int victim, int attacker);
*
* @noreturn
*/
// L4D2 only.
// L4D2 only.
forward void L4D2_OnJockeyRide_Post(int victim, int attacker);
/**
@ -2497,7 +2531,7 @@ forward void L4D2_OnJockeyRide_Post(int victim, int attacker);
*
* @noreturn
*/
// L4D2 only.
// L4D2 only.
forward void L4D2_OnJockeyRide_PostHandled(int victim, int attacker);
/**
@ -2512,7 +2546,7 @@ forward void L4D2_OnJockeyRide_PostHandled(int victim, int attacker);
*
* @return Plugin_Handled to block, Plugin_Changed to use overwritten values from plugin, Plugin_Continue otherwise
*/
// L4D2 only.
// L4D2 only.
forward Action L4D2_OnSlammedSurvivor(int victim, int attacker, bool &bWallSlam, bool &bDeadlyCharge);
/**
@ -2528,7 +2562,7 @@ forward Action L4D2_OnSlammedSurvivor(int victim, int attacker, bool &bWallSlam,
*
* @noreturn
*/
// L4D2 only.
// L4D2 only.
forward void L4D2_OnSlammedSurvivor_Post(int victim, int attacker, bool bWallSlam, bool bDeadlyCharge);
/**
@ -2544,7 +2578,7 @@ forward void L4D2_OnSlammedSurvivor_Post(int victim, int attacker, bool bWallSla
*
* @noreturn
*/
// L4D2 only.
// L4D2 only.
forward void L4D2_OnSlammedSurvivor_PostHandled(int victim, int attacker, bool bWallSlam, bool bDeadlyCharge);
/**
@ -2556,7 +2590,7 @@ forward void L4D2_OnSlammedSurvivor_PostHandled(int victim, int attacker, bool b
*
* @return Plugin_Handled to block, Plugin_Continue otherwise
*/
// L4D2 only.
// L4D2 only.
forward Action L4D2_OnStartCarryingVictim(int victim, int attacker);
/**
@ -2569,7 +2603,7 @@ forward Action L4D2_OnStartCarryingVictim(int victim, int attacker);
*
* @noreturn
*/
// L4D2 only.
// L4D2 only.
forward void L4D2_OnStartCarryingVictim_Post(int victim, int attacker);
/**
@ -2582,7 +2616,7 @@ forward void L4D2_OnStartCarryingVictim_Post(int victim, int attacker);
*
* @noreturn
*/
// L4D2 only.
// L4D2 only.
forward void L4D2_OnStartCarryingVictim_PostHandled(int victim, int attacker);
/**
@ -2862,7 +2896,7 @@ forward void L4D2_VomitJar_Detonate_PostHandled(int entity, int client);
*
* @return Plugin_Handled to block allowing damage to an entity, Plugin_Continue otherwise
*/
// L4D2 only.
// L4D2 only.
forward Action L4D2_CInsectSwarm_CanHarm(int acid, int spitter, int entity);
/**
@ -2876,7 +2910,7 @@ forward Action L4D2_CInsectSwarm_CanHarm(int acid, int spitter, int entity);
*
* @noreturn
*/
// L4D2 only.
// L4D2 only.
forward void L4D2_CInsectSwarm_CanHarm_Post(int acid, int spitter, int entity);
/**
@ -2890,7 +2924,7 @@ forward void L4D2_CInsectSwarm_CanHarm_Post(int acid, int spitter, int entity);
*
* @noreturn
*/
// L4D2 only.
// L4D2 only.
forward void L4D2_CInsectSwarm_CanHarm_PostHandled(int acid, int spitter, int entity);
/**
@ -2905,6 +2939,19 @@ forward void L4D2_CInsectSwarm_CanHarm_PostHandled(int acid, int spitter, int en
*/
forward void L4D_CBreakableProp_Break(int prop, int entity);
/**
* @brief Called whenever CGasCan::Event_Killed() is invoked
* @remarks Called when a gascan is broken
*
* @param gascan the gascan entity index
* @param inflictor the inflictor entity index
* @param attacker the attacker entity index
*
* @return Plugin_Handled to block detonating, Plugin_Changed to change any values, Plugin_Continue otherwise
*/
// L4D2 only.
forward Action L4D2_CGasCan_EventKilled(int gascan, int &inflictor, int &attacker);
/**
* @brief Called whenever CGasCan::Event_Killed() is invoked
* @remarks Called when a gascan is broken
@ -2915,8 +2962,21 @@ forward void L4D_CBreakableProp_Break(int prop, int entity);
*
* @noreturn
*/
// L4D2 only.
forward void L4D2_CGasCan_EventKilled(int gascan, int inflictor, int attacker);
// L4D2 only.
forward void L4D2_CGasCan_EventKilled_Post(int gascan, int inflictor, int attacker);
/**
* @brief Called whenever CGasCan::Event_Killed() is invoked
* @remarks Called when a gascan is broken
*
* @param gascan the gascan entity index
* @param inflictor the inflictor entity index
* @param attacker the attacker entity index
*
* @noreturn
*/
// L4D2 only.
forward void L4D2_CGasCan_EventKilled_PostHandled(int gascan, int inflictor, int attacker);
/**
* @brief Called whenever CGasCan::ShouldStartAction() is invoked
@ -2928,7 +2988,7 @@ forward void L4D2_CGasCan_EventKilled(int gascan, int inflictor, int attacker);
*
* @return Plugin_Handled to block adding to Scavenge score (see "Scavenge Score Fix" plugin for more details), Plugin_Continue otherwise
*/
// L4D2 only.
// L4D2 only.
forward Action L4D2_CGasCan_ShouldStartAction(int client, int gascan, int nozzle);
/**
@ -2942,7 +3002,7 @@ forward Action L4D2_CGasCan_ShouldStartAction(int client, int gascan, int nozzle
*
* @noreturn
*/
// L4D2 only.
// L4D2 only.
forward void L4D2_CGasCan_ShouldStartAction_Post(int client, int gascan, int nozzle);
/**
@ -2956,7 +3016,7 @@ forward void L4D2_CGasCan_ShouldStartAction_Post(int client, int gascan, int noz
*
* @noreturn
*/
// L4D2 only.
// L4D2 only.
forward void L4D2_CGasCan_ShouldStartAction_PostHandled(int client, int gascan, int nozzle);
/**
@ -2969,7 +3029,7 @@ forward void L4D2_CGasCan_ShouldStartAction_PostHandled(int client, int gascan,
*
* @return Plugin_Handled to block adding to Scavenge score (see "Scavenge Score Fix" plugin for more details), Plugin_Continue otherwise
*/
// L4D2 only.
// L4D2 only.
forward Action L4D2_CGasCan_ActionComplete(int client, int gascan, int nozzle);
/**
@ -2983,7 +3043,7 @@ forward Action L4D2_CGasCan_ActionComplete(int client, int gascan, int nozzle);
*
* @noreturn
*/
// L4D2 only.
// L4D2 only.
forward void L4D2_CGasCan_ActionComplete_Post(int client, int gascan, int nozzle);
/**
@ -2997,7 +3057,7 @@ forward void L4D2_CGasCan_ActionComplete_Post(int client, int gascan, int nozzle
*
* @noreturn
*/
// L4D2 only.
// L4D2 only.
forward void L4D2_CGasCan_ActionComplete_PostHandled(int client, int gascan, int nozzle);
/**
@ -3028,7 +3088,7 @@ forward void L4D_OnServerHibernationUpdate(bool hibernating);
*
* @return Plugin_Handled to let the client through with addons, Plugin_Continue otherwise.
*/
// L4D2 only.
// L4D2 only.
forward Action L4D2_OnClientDisableAddons(const char[] SteamID);
/**
@ -3358,7 +3418,7 @@ native any L4D_GetNearestNavArea(const float vecPos[3], float maxDist = 300.0, b
*
* @param client The client to check
*
* @return The nav area adress or 0 on fail
* @return The nav area address or 0 on fail
*/
native any L4D_GetLastKnownArea(int client);
@ -3412,6 +3472,15 @@ native void L4D_FindRandomSpot(int NavArea, float vecPos[3]);
*/
native bool L4D2_IsVisibleToPlayer(int client, int team, int team_target, int NavArea, float vecPos[3]);
/**
* @brief Teleports a player to a valid position if they are stuck.
*
* @param client Client to perform the action
*
* @noreturn
*/
native void L4D_WarpToValidPositionIfStuck(int client);
/**
* @brief Returns true when any survivor has left the starting area and true in Versus when the saferoom door automatically opens.
*
@ -3516,11 +3585,10 @@ native bool L4D2_IsReachable(int client, const float vecPos[3]);
*
* @param startArea NavArea address
* @param endArea NavArea address
* @param ignoreNavBlockers Bool to ignore blocked areas while checking (does not seem to work as expected)
* @param ignoreNavBlockers Bool to ignore blocked areas while checking (does not seem to work as expected) (ignored in L4D1)
*
* @return Distance between the areas, 0.0 if the same area or -1.0 on failure.
*/
// L4D2 only.
native float L4D2_NavAreaTravelDistance(float startPos[3], float endPos[3], bool ignoreNavBlockers);
/**
@ -3738,7 +3806,7 @@ native bool L4D_GoAwayFromKeyboard(int client);
*
* @return True or false
*/
// L4D2 only.
// L4D2 only.
native bool L4D2_AreWanderersAllowed();
/**
@ -4330,6 +4398,7 @@ native int L4D_GetMaxChapters();
/**
* @brief Returns all TheNavAreas addresses
* @remarks Can only be called 1 frame after OnMapStart at the earliest otherwise the addresses are invalid
*
*param aList The ArrayList to store all nav area addresses.
*
@ -4339,6 +4408,7 @@ native void L4D_GetAllNavAreas(ArrayList aList);
/**
* @brief Returns a given NavArea's ID from it's address
* @remarks Can only be called 1 frame after OnMapStart at the earliest otherwise the addresses are invalid
*
*param area The NavArea address
*
@ -4348,6 +4418,7 @@ native int L4D_GetNavAreaID(Address area);
/**
* @brief Returns a given NavArea address from it's ID
* @remarks Can only be called 1 frame after OnMapStart at the earliest otherwise the addresses are invalid
*
*param id The NavArea ID
*
@ -4357,6 +4428,7 @@ native Address L4D_GetNavAreaByID(int id);
/**
* @brief Returns origin of a given NavArea
* @remarks Can only be called 1 frame after OnMapStart at the earliest otherwise the addresses are invalid
*
*param area The address of the NavArea to read.
*param vecPos The vector to store the position read.
@ -4367,6 +4439,7 @@ native void L4D_GetNavAreaPos(Address area, float vecPos[3]);
/**
* @brief Returns size of a given NavArea
* @remarks Can only be called 1 frame after OnMapStart at the earliest otherwise the addresses are invalid
*
*param area The address of the NavArea to read.
*param vecPos The vector to store the size read.
@ -4378,6 +4451,7 @@ native void L4D_GetNavAreaSize(Address area, float vecSize[3]);
/**
* @brief Returns the nav area attribute flags
* @remarks See the "NAV_BASE_*" near the top of the include file
* @remarks Can only be called 1 frame after OnMapStart at the earliest otherwise the addresses are invalid
*
*param pTerrorNavArea Pointer to a NavArea
*
@ -4388,6 +4462,7 @@ native int L4D_GetNavArea_AttributeFlags(Address pTerrorNavArea);
/**
* @brief Sets the nav area attribute flags
* @remarks See the "NAV_BASE_*" near the top of the include file
* @remarks Can only be called 1 frame after OnMapStart at the earliest otherwise the addresses are invalid
*
*param pTerrorNavArea Pointer to a NavArea
*param flags Attribute flags to set
@ -4399,6 +4474,7 @@ native void L4D_SetNavArea_AttributeFlags(Address pTerrorNavArea, int flags);
/**
* @brief Returns the terror nav area attribute flags
* @remarks See the "NAV_SPAWN_*" near the top of the include file
* @remarks Can only be called 1 frame after OnMapStart at the earliest otherwise the addresses are invalid
*
*param pTerrorNavArea Pointer to a TerrorNavArea
*
@ -4409,6 +4485,7 @@ native int L4D_GetNavArea_SpawnAttributes(Address pTerrorNavArea);
/**
* @brief Sets the terror nav area attribute flags
* @remarks See the "NAV_SPAWN_*" near the top of the include file
* @remarks Can only be called 1 frame after OnMapStart at the earliest otherwise the addresses are invalid
*
*param pTerrorNavArea Pointer to a TerrorNavArea
*param flags Attribute flags to set

View file

@ -27,7 +27,7 @@
#tryinclude <left4dhooks_silver>
#tryinclude <left4dhooks_stocks>
#define LUX_LIBRARY_VERSION "0.5.5"
#define LUX_LIBRARY_VERSION "0.5.7"
#define GIMMEDATA "lux_library"
@ -395,16 +395,57 @@ stock float Terror_GetAdrenalineTime(int iClient)
}
/**
* Create a physics explosion that does not affect players and don't check for line of sight and no force fall-off.
* Calls CTerrorPlayer::OnRevivedByDefibrillator()
*
* @param iRevivee Client index be revived.
* @param iReviver Client index who revived can be same as revivee.
* @param iDeathModel Death model index, dead survivor model (survivor_death_model).
*
* @return True if revive was successful false otherwise.
* @error Invalid entity index or invalid attachment name,
* signature for function not found, or SDKCall failed.
**/
stock bool Terror_ReviveDeathModel(int iRevivee, int iReviver, int iDeathModel)
{
static Handle hSDKCall;
if(hSDKCall == null)
{
Handle hGamedata;
GetGameData(hGamedata);
StartPrepSDKCall(SDKCall_Player);
if(PrepSDKCall_SetFromConf(hGamedata, SDKConf_Signature, "CTerrorPlayer::OnRevivedByDefibrillator"))
{
PrepSDKCall_AddParameter(SDKType_CBasePlayer, SDKPass_Pointer);
PrepSDKCall_AddParameter(SDKType_CBaseEntity, SDKPass_Pointer);
hSDKCall = EndPrepSDKCall();
if(hSDKCall == null)
LogError("Unable to prep 'CTerrorPlayer::OnRevivedByDefibrillator'");
}
else
{
LogError("Error finding the 'CTerrorPlayer::OnRevivedByDefibrillator' signature.");
}
delete hGamedata;
if(hSDKCall == null)
return false;
}
SDKCall(hSDKCall, iRevivee, iReviver, iDeathModel);
return true;
}
/**
* Create a physics explosion that does not affect players.
*
* @param vecOrigin Origin of the explosion.
* @param iMagnitude Magnitude of the explosion.
* @param iMagnitude Magnitude of the explosion limit of 100, explode more than once for more power.
* @param flRadius Radius of the explosion.
* @param bDamage True to damage props, false otherwise.
* @param flInnerRadius If not zero, the LOS is calculated from a point intersecting this sphere.
*
* @error Failed to create explosion.
**/
stock void PhysicsExplode(float vecOrigin[3], int iMagnitude, float flRadius, bool bDamage=false)
stock void PhysicsExplode(float vecOrigin[3], int iMagnitude, float flRadius, bool bDamage=false, float flInnerRadius=0.0)
{
static int iBoom = INVALID_ENT_REFERENCE;
@ -420,11 +461,11 @@ stock void PhysicsExplode(float vecOrigin[3], int iMagnitude, float flRadius, bo
if(bDamage)
{
DispatchKeyValue(iBoom, "spawnflags", "0");
DispatchKeyValue(iBoom, "spawnflags", "8");
}
else
{
DispatchKeyValue(iBoom, "spawnflags", "1");
DispatchKeyValue(iBoom, "spawnflags", "9");
}
char sBuf[32];
@ -433,7 +474,7 @@ stock void PhysicsExplode(float vecOrigin[3], int iMagnitude, float flRadius, bo
IntToString(RoundFloat(flRadius), sBuf, sizeof(sBuf));
DispatchKeyValue(iBoom, "radius", sBuf);
DispatchKeyValueFloat(iBoom, "inner_radius", flRadius);
DispatchKeyValueFloat(iBoom, "inner_radius", flInnerRadius);
TeleportEntity(iBoom, vecOrigin, NULL_VECTOR, NULL_VECTOR);
@ -523,15 +564,8 @@ stock void TE_SetupPhysicsProp(float vecModelOrigin[3],
*
* @return True on success, false on failure.
**/
stock bool TE_SetupDynamicLight(float vecOrigin[3], int RGB[3], float flRadius, float flTime, float flDecay=0.0, int exponent=0)
stock void TE_SetupDynamicLight(float vecOrigin[3], int RGB[3], float flRadius, float flTime, float flDecay=0.0, int exponent=0)
{
static int iLastTick;
int iCurrentTick = GetGameTickCount();
if(iLastTick == iCurrentTick)
return false;
iLastTick = iCurrentTick;
TE_Start("Dynamic Light");
TE_WriteVector("m_vecOrigin", vecOrigin);
@ -542,8 +576,6 @@ stock bool TE_SetupDynamicLight(float vecOrigin[3], int RGB[3], float flRadius,
TE_WriteFloat("m_fRadius", flRadius);
TE_WriteFloat("m_fTime", flTime);
TE_WriteFloat("m_fDecay", flDecay);
return true;
}
/**
@ -1249,4 +1281,435 @@ stock void GetAbsOrigin(int iEntity, float vecOrigin[3], bool bCenter=false)
vecOrigin[1] += (vecMins[1] + vecMaxs[1]) * 0.5;
vecOrigin[2] += (vecMins[2] + vecMaxs[2]) * 0.5;
}
}
}
///////////////////////////////////////Sound
/**
* level boost in some games maybe clamed, e.g. l4d max seems to be 150
* pitch is clamed between 1-200, this maybe different between games.
* sndChannel static sound wont be replaced, however if overflowed it wont play any sound until static sounds have finished.
*
* @param sample sound file path.
* @param origin origin to emit sound from.
* @param entity entity to emit sound from.
* @param level sound level attenuation, the wav sound it's self matters.
* @param pitch sound pitch.
* @param sndChannel sound channel.
* @param rangeMin players within the min range sound wont be mixed.
* @param rangeCurve range curve until max mix can be achieved.
* @param levelBoost add level boost to mixed sounds max rangeCurve will apply levelBoost, half will apply half levelBoost.
* @param exponent exponent value to multiply, logarithmic.
*
* @error Invalid client index.
**/
stock void EmitMixedAmbientSoundToAll(const char[] sample,
const float origin[3] = NULL_VECTOR,
int entity = SOUND_FROM_PLAYER,
int level = SNDLEVEL_NORMAL,
int pitch = SNDPITCH_NORMAL,
int sndChannel = SNDCHAN_AUTO,
float rangeMin,
float rangeCurve=1500.0,
int levelBoost=0,
float exponent=1.0)
{
for(int i = 1; i <= MaxClients; ++i)
{
if(!IsClientInGame(i) || IsFakeClient(i))
continue;
EmitMixedAmbientSound(i, sample, origin, entity, level, pitch, sndChannel, rangeMin, rangeCurve, levelBoost, exponent);
}
}
/**
* level boost in some games maybe clamed, e.g. l4d max seems to be 150
* pitch is clamed between 1-200, this maybe different between games.
* sndChannel static sound wont be replaced, however if overflowed it wont play any sound until static sounds have finished.
*
* @param sample sound file path.
* @param origin origin to emit sound from.
* @param entity entity to emit sound from.
* @param level sound level attenuation, the wav sound it's self matters.
* @param pitch sound pitch.
* @param sndChannel sound channel.
* @param rangeMin players within the min range sound wont be mixed.
* @param rangeCurve range curve until max mix can be achieved, sample2 is played when 2x this value.
* @param levelBoost add level boost to mixed sounds max rangeCurve will apply levelBoost, half will apply half levelBoost.
* @param exponent exponent value to multiply, logarithmic.
* @param sample2 sound file path.
* @param level2 sound level attenuation.
* @param pitch2 sound pitch.
*
* @error Invalid client index.
**/
stock void EmitMixedAmbientSoundToAll_FallBack(const char[] sample,
const float origin[3] = NULL_VECTOR,
int entity = SOUND_FROM_PLAYER,
int level = SNDLEVEL_NORMAL,
int pitch = SNDPITCH_NORMAL,
int sndChannel = SNDCHAN_AUTO,
float rangeMin,
float rangeCurve=1500.0,
int levelBoost=0,
float exponent=1.0,
const char[] sample2,
int level2 = SNDLEVEL_NORMAL,
int pitch2 = SNDPITCH_NORMAL)
{
for(int i = 1; i <= MaxClients; ++i)
{
if(!IsClientInGame(i) || IsFakeClient(i))
continue;
EmitMixedAmbientSound_FallBack(i, sample, origin, entity, level, pitch, sndChannel, rangeMin, rangeCurve, levelBoost, exponent, sample2, level2, pitch2);
}
}
/**
* level boost in some games maybe clamed, e.g. l4d max seems to be 150
* pitch is clamed between 1-200, this maybe different between games.
* sndChannel static sound wont be replaced, however if overflowed it wont play any sound until static sounds have finished.
*
* @param client client index.
* @param sample sound file path.
* @param origin origin to emit sound from.
* @param entity entity to emit sound from.
* @param level sound level attenuation, the wav sound it's self matters.
* @param pitch sound pitch.
* @param sndChannel sound channel.
* @param rangeMin players within the min range sound wont be mixed.
* @param rangeCurve range curve until max mix can be achieved.
* @param levelBoost add level boost to mixed sounds max rangeCurve will apply levelBoost, half will apply half levelBoost.
* @param exponent exponent value to multiply, logarithmic.
*
* @error Invalid client index.
**/
stock void EmitMixedAmbientSound(int client, const char[] sample,
const float origin[3] = NULL_VECTOR,
int entity = SOUND_FROM_PLAYER,
int level = SNDLEVEL_NORMAL,
int pitch = SNDPITCH_NORMAL,
int sndChannel = SNDCHAN_AUTO,
float rangeMin,
float rangeCurve=1500.0,
int levelBoost=0,
float exponent=1.0)
{
static float vecEyePos[3];
int newPitch;
float flDist;
float flDistPercent;
float flDistMulti;
int DistLevelBoost;
int viewEnt = -1;
viewEnt = GetEntPropEnt(client, Prop_Send, "m_hViewEntity");
if(viewEnt > 0)
{
GetAbsOrigin(viewEnt, vecEyePos);
}
else
{
GetClientEyePosition(client, vecEyePos);
}
flDist = GetVectorDistance(origin, vecEyePos);
if(rangeCurve == 0.0)
{
LogError("RangeCurve == 0.0");
return;
}
flDist = (flDist - rangeMin < 0.0 ? 0.0 : flDist - rangeMin);
flDistPercent = (flDist / rangeCurve);
flDistMulti = (flDistPercent * 2) * exponent;
newPitch = pitch;
if(flDistMulti > 1.0)
{
newPitch = FloatToInt(newPitch / (flDistMulti > 2.0 ? 2.0 : flDistMulti));
}
DistLevelBoost = FloatToInt((flDistPercent * exponent) * levelBoost);
if(DistLevelBoost > levelBoost)
DistLevelBoost = levelBoost;
EmitSoundToClient(client, sample, entity, sndChannel, level + DistLevelBoost, _, _, newPitch, _, origin);
}
/**
* level boost in some games maybe clamed, e.g. l4d max seems to be 150
* pitch is clamed between 1-200, this maybe different between games.
* sndChannel static sound wont be replaced, however if overflowed it wont play any sound until static sounds have finished.
*
* @param client client index.
* @param sample sound file path.
* @param origin origin to emit sound from.
* @param entity entity to emit sound from.
* @param level sound level attenuation, the wav sound it's self matters.
* @param pitch sound pitch.
* @param sndChannel sound channel.
* @param rangeMin players within the min range sound wont be mixed.
* @param rangeCurve range curve until max mix can be achieved, sample2 is played when 2x this value.
* @param levelBoost add level boost to mixed sounds max rangeCurve will apply levelBoost, half will apply half levelBoost.
* @param exponent exponent value to multiply, logarithmic.
* @param sample2 sound file path.
* @param level2 sound level attenuation.
* @param pitch2 sound pitch.
*
* @error Invalid client index.
**/
stock void EmitMixedAmbientSound_FallBack(int client, const char[] sample,
const float origin[3] = NULL_VECTOR,
int entity = SOUND_FROM_PLAYER,
int level = SNDLEVEL_NORMAL,
int pitch = SNDPITCH_NORMAL,
int sndChannel = SNDCHAN_AUTO,
float rangeMin,
float rangeCurve=1500.0,
int levelBoost=0,
float exponent=1.0,
const char[] sample2,
int level2 = SNDLEVEL_NORMAL,
int pitch2 = SNDPITCH_NORMAL)
{
static float vecEyePos[3];
int newPitch;
float flDist;
float flDistPercent;
float flDistMulti;
int DistLevelBoost;
int viewEnt = -1;
viewEnt = GetEntPropEnt(client, Prop_Send, "m_hViewEntity");
if(viewEnt > 0)
{
GetAbsOrigin(viewEnt, vecEyePos);
}
else
{
GetClientEyePosition(client, vecEyePos);
}
flDist = GetVectorDistance(origin, vecEyePos);
if(rangeCurve == 0.0)
{
LogError("RangeCurve == 0.0");
return;
}
flDist = (flDist - rangeMin < 0.0 ? 0.0 : flDist - rangeMin);
flDistPercent = (flDist / rangeCurve);
flDistMulti = (flDistPercent * 2) * exponent;
if(flDistMulti >= 2.0)
{
EmitSoundToClient(client, sample2, entity, sndChannel, level2, _, _, pitch2, _, origin);
return;
}
newPitch = pitch;
if(flDistMulti > 1.0)
{
newPitch = FloatToInt(newPitch / (flDistMulti > 2.0 ? 2.0 : flDistMulti));
}
DistLevelBoost = FloatToInt((flDistPercent * exponent) * levelBoost);
if(DistLevelBoost > levelBoost)
DistLevelBoost = levelBoost;
EmitSoundToClient(client, sample, entity, sndChannel, level + DistLevelBoost, _, _, newPitch, _, origin);
}
int FloatToInt(float val)
{
return RoundFloat(val);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////Legacy Particle Stock///////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Creates a tempent particle.
*
* @param iParticleIndex Particle index location in the "ParticleEffectNames" stringtable.
* @param iEntIndex Entity index to attach particle to.
* @param fDelay Delay for the TE_SendToAll function.
* @param SendToAll True to send to all clients, false otherwise. You must call the send function yourself if sending to specific clients.
* @param sParticleName Name of the particle to find the index with. Only used if the particle index is invalid.
* @param iAttachmentIndex Attachment index of the particle. Decompile the model to retrieve this value.
* @param fParticleAngles Angles of the particle. Usually effects particles that have no gravity.
* @param iFlags Flags of the particle. Note: A value of "1" is required for attachment points and damage types.
* @param iDamageType The damage type of the particle. (Used in impact effect dispatches and attachment points need to be set to use.)
* @param fMagnitude The magnitude of the particle. (Needs testing; used in pipe bomb blast.)
* @param fScale The scale of the particle (doesn't apply to most particles). (Needs testing.)
*
* @return True on success, false on failure.
* @error Invalid effect index or invalid particle stringtable index.
**/
#pragma deprecated Used for backwards compatibility.
stock bool L4D_TE_Create_Particle(float fParticleStartPos[3]={0.0, 0.0, 0.0},
float fParticleEndPos[3]={0.0, 0.0, 0.0},
int iParticleIndex=-1,
int iEntIndex=0,
float fDelay=0.0,
bool SendToAll=true,
char sParticleName[64]="",
int iAttachmentIndex=0,
float fParticleAngles[3]={0.0, 0.0, 0.0},
int iFlags=0,
int iDamageType=0,
float fMagnitude=0.0,
float fScale=1.0,
float fRadius=0.0)
{
TE_Start("EffectDispatch");
static EngineVersion IsEngine;
if(IsEngine == Engine_Unknown)
IsEngine = GetEngineVersion();
TE_WriteFloat(IsEngine == Engine_Left4Dead2 ? "m_vOrigin.x" :"m_vOrigin[0]", fParticleStartPos[0]);
TE_WriteFloat(IsEngine == Engine_Left4Dead2 ? "m_vOrigin.y" :"m_vOrigin[1]", fParticleStartPos[1]);
TE_WriteFloat(IsEngine == Engine_Left4Dead2 ? "m_vOrigin.z" :"m_vOrigin[2]", fParticleStartPos[2]);
TE_WriteFloat(IsEngine == Engine_Left4Dead2 ? "m_vStart.x" :"m_vStart[0]", fParticleEndPos[0]);//end point usually for bulletparticles or ropes
TE_WriteFloat(IsEngine == Engine_Left4Dead2 ? "m_vStart.y" :"m_vStart[1]", fParticleEndPos[1]);
TE_WriteFloat(IsEngine == Engine_Left4Dead2 ? "m_vStart.z" :"m_vStart[2]", fParticleEndPos[2]);
static int iEffectIndex = INVALID_STRING_INDEX;
if(iEffectIndex < 0)
{
iEffectIndex = __FindStringIndex2(FindStringTable("EffectDispatch"), "ParticleEffect");
if(iEffectIndex == INVALID_STRING_INDEX)
SetFailState("Unable to find EffectDispatch/ParticleEffect indexes");
}
TE_WriteNum("m_iEffectName", iEffectIndex);
if(iParticleIndex < 0)
{
static int iParticleStringIndex = INVALID_STRING_INDEX;
iParticleStringIndex = __FindStringIndex2(FindStringTable("ParticleEffectNames"), sParticleName);
if(iParticleStringIndex == INVALID_STRING_INDEX)
return false;
TE_WriteNum("m_nHitBox", iParticleStringIndex);
}
else
TE_WriteNum("m_nHitBox", iParticleIndex);
TE_WriteNum("entindex", iEntIndex);
TE_WriteNum("m_nAttachmentIndex", iAttachmentIndex);
TE_WriteVector("m_vAngles", fParticleAngles);
TE_WriteNum("m_fFlags", iFlags);
TE_WriteFloat("m_flMagnitude", fMagnitude);// saw this being used in pipebomb needs testing what it does probs shaking screen?
TE_WriteFloat("m_flScale", fScale);
TE_WriteFloat("m_flRadius", fRadius);// saw this being used in pipebomb needs testing what it does probs shaking screen?
TE_WriteNum("m_nDamageType", iDamageType);// this shit is required dunno why for attachpoint emitting valve probs named it wrong
if(SendToAll)
TE_SendToAll(fDelay);
return true;
}
/**
* Stops a tempent particle.
*
* @param fParticleStartPos Starting position of the particle.
* @param fParticleEndPos Ending position of the particle.
* @param iParticleIndex Particle index location in the "ParticleEffectNames" stringtable.
* @param iEntIndex Entity index to attach particle to.
* @param fDelay Delay for the TE_SendToAll function.
* @param SendToAll True to send to all clients, false otherwise. You must call the send function yourself if sending to specific clients.
* @param sParticleName Name of the particle to find the index with. Only used if the particle index is invalid.
* @param iAttachmentIndex Attachment index of the particle. Decompile the model to retrieve this value.
* @param fParticleAngles Angles of the particle. Usually effects particles that have no gravity.
* @param iFlags Flags of the particle.
* @param iDamageType The damage type of the particle. (Used in impact effect dispatches and attachment points need to be set to use.)
* @param fMagnitude The magnitude of the particle. (Needs testing; used in pipe bomb blast.)
* @param fScale The scale of the particle (doesn't apply to most particles). (Needs testing.)
* @param fRadius The radius of the particle.
*
* @return True on success, false on failure.
* @error Invalid effect index or invalid particle stringtable index.
**/
#pragma deprecated Used only for backwards compatibility.
stock bool L4D_TE_Stop_Particle(float fParticleStartPos[3]={0.0, 0.0, 0.0},
float fParticleEndPos[3]={0.0, 0.0, 0.0},
int iParticleIndex=-1,
int iEntIndex=0,
float fDelay=0.0,
bool SendToAll=true,
char sParticleName[64]="",
int iAttachmentIndex=0,
float fParticleAngles[3]={0.0, 0.0, 0.0},
int iFlags=0,
int iDamageType=0,
float fMagnitude=0.0,
float fScale=1.0,
float fRadius=0.0)
{
TE_Start("EffectDispatch");
static EngineVersion IsEngine;
if(IsEngine == Engine_Unknown)
IsEngine = GetEngineVersion();
TE_WriteFloat(IsEngine == Engine_Left4Dead2 ? "m_vOrigin.x" :"m_vStart[0]", fParticleStartPos[0]);
TE_WriteFloat(IsEngine == Engine_Left4Dead2 ? "m_vOrigin.y" :"m_vStart[1]", fParticleStartPos[1]);
TE_WriteFloat(IsEngine == Engine_Left4Dead2 ? "m_vOrigin.z" :"m_vStart[2]", fParticleStartPos[2]);
TE_WriteFloat(IsEngine == Engine_Left4Dead2 ? "m_vStart.x" :"m_vOrigin[0]", fParticleEndPos[0]);//end point usually for bulletparticles or ropes
TE_WriteFloat(IsEngine == Engine_Left4Dead2 ? "m_vStart.y" :"m_vOrigin[1]", fParticleEndPos[1]);
TE_WriteFloat(IsEngine == Engine_Left4Dead2 ? "m_vStart.z" :"m_vOrigin[2]", fParticleEndPos[2]);
static int iEffectIndex = INVALID_STRING_INDEX;
if(iEffectIndex < 0)
{
iEffectIndex = __FindStringIndex2(FindStringTable("EffectDispatch"), "ParticleEffectStop");
if(iEffectIndex == INVALID_STRING_INDEX)
SetFailState("Unable to find EffectDispatch/ParticleEffectStop indexes");
}
TE_WriteNum("m_iEffectName", iEffectIndex);
if(iParticleIndex < 0)
{
static int iParticleStringIndex = INVALID_STRING_INDEX;
iParticleStringIndex = __FindStringIndex2(FindStringTable("ParticleEffectNames"), sParticleName);
if(iParticleStringIndex == INVALID_STRING_INDEX)
return false;
TE_WriteNum("m_nHitBox", iParticleStringIndex);
}
else
TE_WriteNum("m_nHitBox", iParticleIndex);
TE_WriteNum("entindex", iEntIndex);
TE_WriteNum("m_nAttachmentIndex", iAttachmentIndex);
TE_WriteVector("m_vAngles", fParticleAngles);
TE_WriteNum("m_fFlags", iFlags);
TE_WriteFloat("m_flMagnitude", fMagnitude);// saw this being used in pipebomb needs testing what it does probs shaking screen?
TE_WriteFloat("m_flScale", fScale);
TE_WriteFloat("m_flRadius", fRadius);// saw this being used in pipebomb needs testing what it does probs shaking screen?
TE_WriteNum("m_nDamageType", iDamageType);// this shit is required dunno why for attachpoint emitting valve probs named it wrong
if(SendToAll)
TE_SendToAll(fDelay);
return true;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

View file

@ -1,6 +1,6 @@
/*
* Left 4 DHooks Direct - Stock Functions
* Copyright (C) 2022 Silvers
* Copyright (C) 2023 Silvers
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -202,7 +202,7 @@ bool ComputeGroups(Group groups[MAX_GROUPS], GroupResult result, float activateF
inGroup[j] = true;
members.Push(GetClientUserId(j));
} else {
PrintDebug("not adding member to group %d: %N (dist = %.4f) (fldiff = %.1f) (l:%N)", groupIndex + 1, j, dist, flowDiff, i);
// PrintDebug("not adding member to group %d: %N (dist = %.4f) (fldiff = %.1f) (l:%N)", groupIndex + 1, j, dist, flowDiff, i);
}
}
}
@ -294,6 +294,39 @@ bool ComputeGroups(Group groups[MAX_GROUPS], GroupResult result, float activateF
return groupIndex > 0;
}
public Action L4D2_CGasCan_EventKilled(int gascan, int &inflictor, int &attacker) {
if(hEnabled.IntValue > 0 && attacker > 0 && attacker <= MaxClients) {
float activatorFlow = L4D2Direct_GetFlowDistance(attacker);
Group groups[MAX_GROUPS];
GroupResult result;
ComputeGroups(groups, result, activatorFlow);
AdminId admin = GetUserAdmin(attacker);
if(admin != INVALID_ADMIN_ID && admin.HasFlag(Admin_Custom1)) {
lastButtonPressTime = GetGameTime();
return Plugin_Continue;
} else if(result.groupCount > 0 && result.ungroupedCount > 0) {
lastButtonPressTime = GetGameTime();
return Plugin_Continue;
}
if(panicStarted) {
panicStarted = false;
return Plugin_Continue;
}
PrintToConsoleAll("[CC] Gascan Light by %N", attacker);
if(hEnabled.IntValue == 2 || !IsActivationAllowed(activatorFlow, 1500.0)) {
ClientCommand(attacker, "play ui/menu_invalid.wav");
PrintToChat(attacker, "Please wait for players to catch up.");
return Plugin_Handled;
}
lastButtonPressTime = GetGameTime();
}
return Plugin_Continue;
}
// 5 far/8 total
// [Debug] average 4222.518066 - difference 2262.424316

View file

@ -150,7 +150,7 @@ Restore from saved inventory
static StringMap weaponMaxClipSizes;
static StringMap pInv;
static char HUD_SCRIPT_DATA[] = "g_ModeScript._eph <- {Fields = {players = {slot = g_ModeScript.HUD_RIGHT_BOT, dataval = \"%s\", flags = g_ModeScript.HUD_FLAG_ALIGN_LEFT|g_ModeScript.HUD_FLAG_TEAM_SURVIVORS|g_ModeScript.HUD_FLAG_NOBG}}};HUDSetLayout(g_ModeScript._eph);HUDPlace(g_ModeScript.HUD_RIGHT_BOT, 0.72,0.78,0.3,0.3);g_ModeScript";
static char HUD_SCRIPT_DATA[] = "g_ModeScript._eph <- { Fields = { players = { slot = g_ModeScript.HUD_RIGHT_BOT, dataval = \"%s\", flags = g_ModeScript.HUD_FLAG_ALIGN_LEFT | g_ModeScript.HUD_FLAG_TEAM_SURVIVORS | g_ModeScript.HUD_FLAG_NOBG } } }; HUDSetLayout(g_ModeScript._eph); HUDPlace(g_ModeScript.HUD_RIGHT_BOT, 0.72,0.78,0.3,0.3); g_ModeScript";
static char HUD_SCRIPT_CLEAR[] = "g_ModeScript._eph <- { Fields = { players = { slot = g_ModeScript.HUD_RIGHT_BOT, dataval = \"\", flags = g_ModeScript.HUD_FLAG_ALIGN_LEFT|g_ModeScript.HUD_FLAG_TEAM_SURVIVORS|g_ModeScript.HUD_FLAG_NOBG } } };HUDSetLayout( g_ModeScript._eph );g_ModeScript";
@ -1271,7 +1271,6 @@ public Action Timer_UpdateHud(Handle h) {
Format(prefix, 13, "AFK %N", client);
else
Format(prefix, 8, "%N", i);
} else {
Format(prefix, 8, "%N", i);
}

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/*
* Anti Rush
* Copyright (C) 2021 Silvers
* Copyright (C) 2023 Silvers
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -18,7 +18,7 @@
#define PLUGIN_VERSION "1.17"
#define PLUGIN_VERSION "1.19"
#define DEBUG_BENCHMARK 0 // 0=Off. 1=Benchmark logic function.
/*======================================================================================
@ -33,6 +33,15 @@
========================================================================================
Change Log:
1.19 (10-Mar-2023)
- Added cvar "l4d_anti_rush_health" to hurt players who are rushing. Requested by "Voevoda".
- Changed cvar "l4d_anti_rush_type" to allow disabling teleport or slowdown, to only enable health drain.
- Translation phrases updated to support the health drain only type. Thanks to "Voevoda" and "HarryPotter" for updating Russian and Chinese translations.
1.18 (01-Jun-2022)
- L4D1: Fixed throwing errors.
- L4D2: Added map "c5m5_bridge" to the data config.
1.17 (04-Dec-2021)
- Changes to fix warnings when compiling on SourceMod 1.11.
@ -136,8 +145,8 @@ float g_iBenchTicks;
#define EVENTS_CONFIG "data/l4d_anti_rush.cfg"
ConVar g_hCvarAllow, g_hCvarMPGameMode, g_hCvarModes, g_hCvarModesOff, g_hCvarModesTog, g_hCvarFinale, g_hCvarFlags, g_hCvarIgnore, g_hCvarIncap, g_hCvarPlayers, g_hCvarRangeLast, g_hCvarRangeLead, g_hCvarSlow, g_hCvarTank, g_hCvarText, g_hCvarTime, g_hCvarType, g_hCvarWarnLast, g_hCvarWarnLead, g_hCvarWarnTime;
float g_fCvarRangeLast, g_fCvarRangeLead, g_fCvarSlow, g_fCvarTime, g_fCvarWarnLast, g_fCvarWarnLead, g_fCvarWarnTime;
ConVar g_hCvarAllow, g_hCvarMPGameMode, g_hCvarModes, g_hCvarModesOff, g_hCvarModesTog, g_hCvarFinale, g_hCvarFlags, g_hCvarIgnore, g_hCvarHealth, g_hCvarIncap, g_hCvarPlayers, g_hCvarRangeLast, g_hCvarRangeLead, g_hCvarSlow, g_hCvarTank, g_hCvarText, g_hCvarTime, g_hCvarType, g_hCvarWarnLast, g_hCvarWarnLead, g_hCvarWarnTime;
float g_fCvarHealth, g_fCvarRangeLast, g_fCvarRangeLead, g_fCvarSlow, g_fCvarTime, g_fCvarWarnLast, g_fCvarWarnLead, g_fCvarWarnTime;
int g_iCvarFinale, g_iCvarFlags, g_iCvarIgnore, g_iCvarIncap, g_iCvarPlayers, g_iCvarTank, g_iCvarText, g_iCvarType;
bool g_bCvarAllow, g_bMapStarted, g_bLeft4Dead2;
@ -145,6 +154,7 @@ bool g_bInhibit[MAXPLAYERS+1];
float g_fHintLast[MAXPLAYERS+1];
float g_fHintWarn[MAXPLAYERS+1];
float g_fLastFlow[MAXPLAYERS+1];
float g_fHighestFlow[MAXPLAYERS+1];
Handle g_hTimer;
char g_sMap[PLATFORM_MAX_PATH];
@ -152,6 +162,7 @@ bool g_bFoundMap;
bool g_bEventStarted;
float g_fEventExtended;
ArrayList g_hElevators;
GlobalForward g_OnRushForward;
@ -193,16 +204,17 @@ public void OnPluginStart()
g_hCvarModesTog = CreateConVar( "l4d_anti_rush_modes_tog", "0", "Turn on the plugin in these game modes. 0=All, 1=Coop, 2=Survival, 4=Versus, 8=Scavenge. Add numbers together.", CVAR_FLAGS );
g_hCvarFinale = CreateConVar( "l4d_anti_rush_finale", g_bLeft4Dead2 ? "2" : "0", "Should the plugin activate in finales. 0=Off. 1=All finales. 2=Gauntlet type finales (L4D2 only).", CVAR_FLAGS );
g_hCvarFlags = CreateConVar( "l4d_anti_rush_flags", "", "Players with these flags will be immune from teleporting forward when behind or slowing down when ahead.", CVAR_FLAGS );
g_hCvarHealth = CreateConVar( "l4d_anti_rush_health", "0", "0=Off. Amount of health to remove every second when someone is rushing.", CVAR_FLAGS);
g_hCvarIgnore = CreateConVar( "l4d_anti_rush_ignore", "0", "Should players with the immune flags be counted toward total flow distance. 0=Ignore them. 1=Count them.", CVAR_FLAGS );
g_hCvarIncap = CreateConVar( "l4d_anti_rush_incapped", "0", "0=Off. How many survivors must be incapped before ignoring them in calculating rushers and slackers.", CVAR_FLAGS );
g_hCvarPlayers = CreateConVar( "l4d_anti_rush_players", "3", "Minimum number of alive survivors before the function kicks in. Must be 3 or greater otherwise the lead/last and average cannot be detected.", CVAR_FLAGS, true, 3.0 );
g_hCvarRangeLast = CreateConVar( "l4d_anti_rush_range_last", "3000.0", "How far behind someone can travel from the average Survivor distance before being teleported forward.", CVAR_FLAGS, true, MINIMUM_RANGE );
g_hCvarRangeLead = CreateConVar( "l4d_anti_rush_range_lead", "3000.0", "How far forward someone can travel from the average Survivor distance before being teleported or slowed down.", CVAR_FLAGS, true, MINIMUM_RANGE );
g_hCvarRangeLast = CreateConVar( "l4d_anti_rush_range_last", "3000.0", "0.0=Off. How far behind someone can travel from the average Survivor distance before being teleported forward.", CVAR_FLAGS );
g_hCvarRangeLead = CreateConVar( "l4d_anti_rush_range_lead", "3000.0", "How far forward someone can travel from the average Survivor distance before being teleported, slowed down or health drained.", CVAR_FLAGS, true, MINIMUM_RANGE );
g_hCvarSlow = CreateConVar( "l4d_anti_rush_slow", "75.0", "Maximum speed someone can travel when being slowed down.", CVAR_FLAGS, true, 20.0 );
g_hCvarTank = CreateConVar( "l4d_anti_rush_tanks", "1", "0=Off. 1=On. Should Anti-Rush be enabled when there are active Tanks.", CVAR_FLAGS );
g_hCvarText = CreateConVar( "l4d_anti_rush_text", "1", "0=Off. 1=Print To Chat. 2=Hint Text. Display a message to someone rushing, or falling behind.", CVAR_FLAGS );
g_hCvarTime = CreateConVar( "l4d_anti_rush_time", "10", "How often to print the message to someone if slowdown is enabled and affecting them.", CVAR_FLAGS );
g_hCvarType = CreateConVar( "l4d_anti_rush_type", "1", "What to do with rushers. 1=Slowdown player speed when moving forward. 2=Teleport back to group. 3=Spawn Special On Them", CVAR_FLAGS );
g_hCvarType = CreateConVar( "l4d_anti_rush_type", "1", "What to do with rushers. 0=Ignore (used for health drain / forward only). 1=Slowdown player speed when moving forward. 2=Teleport back to group.", CVAR_FLAGS );
g_hCvarWarnLast = CreateConVar( "l4d_anti_rush_warn_last", "2500.0", "How far behind someone can travel from the average Survivor distance before being warned about being teleported.", CVAR_FLAGS, true, MINIMUM_RANGE );
g_hCvarWarnLead = CreateConVar( "l4d_anti_rush_warn_lead", "2500.0", "How far forward someone can travel from the average Survivor distance before being warned about being teleported or slowed down.", CVAR_FLAGS, true, MINIMUM_RANGE );
g_hCvarWarnTime = CreateConVar( "l4d_anti_rush_warn_time", "15.0", "0.0=Off. How often to print a message to someone warning them they are ahead or behind and will be teleported or slowed down.", CVAR_FLAGS );
@ -217,6 +229,7 @@ public void OnPluginStart()
g_hCvarAllow.AddChangeHook(ConVarChanged_Allow);
g_hCvarFinale.AddChangeHook(ConVarChanged_Cvars);
g_hCvarFlags.AddChangeHook(ConVarChanged_Cvars);
g_hCvarHealth.AddChangeHook(ConVarChanged_Cvars);
g_hCvarIgnore.AddChangeHook(ConVarChanged_Cvars);
g_hCvarIncap.AddChangeHook(ConVarChanged_Cvars);
g_hCvarPlayers.AddChangeHook(ConVarChanged_Cvars);
@ -250,12 +263,12 @@ public void OnConfigsExecuted()
IsAllowed();
}
public void ConVarChanged_Allow(Handle convar, const char[] oldValue, const char[] newValue)
void ConVarChanged_Allow(Handle convar, const char[] oldValue, const char[] newValue)
{
IsAllowed();
}
public void ConVarChanged_Cvars(Handle convar, const char[] oldValue, const char[] newValue)
void ConVarChanged_Cvars(Handle convar, const char[] oldValue, const char[] newValue)
{
GetCvars();
}
@ -268,6 +281,7 @@ void GetCvars()
g_iCvarIgnore = g_hCvarIgnore.IntValue;
g_iCvarFinale = g_hCvarFinale.IntValue;
g_fCvarHealth = g_hCvarHealth.FloatValue;
g_iCvarIncap = g_hCvarIncap.IntValue;
g_iCvarPlayers = g_hCvarPlayers.IntValue;
g_fCvarTime = g_hCvarTime.FloatValue;
@ -377,7 +391,7 @@ bool IsAllowedGameMode()
return true;
}
public void OnGamemode(const char[] output, int caller, int activator, float delay)
void OnGamemode(const char[] output, int caller, int activator, float delay)
{
if( strcmp(output, "OnCoop") == 0 )
g_iCurrentMode = 1;
@ -428,7 +442,7 @@ bool ParseConfigFile(const char[] file)
return (result == SMCError_Okay);
}
public SMCResult ColorConfig_NewSection(Handle parser, const char[] section, bool quotes)
SMCResult ColorConfig_NewSection(Handle parser, const char[] section, bool quotes)
{
g_iSectionLevel++;
@ -443,7 +457,7 @@ public SMCResult ColorConfig_NewSection(Handle parser, const char[] section, boo
return SMCParse_Continue;
}
public SMCResult ColorConfig_KeyValue(Handle parser, const char[] key, const char[] value, bool key_quotes, bool value_quotes)
SMCResult ColorConfig_KeyValue(Handle parser, const char[] key, const char[] value, bool key_quotes, bool value_quotes)
{
// On / Off
if( g_iSectionLevel == 2 && g_bFoundMap )
@ -478,24 +492,24 @@ public SMCResult ColorConfig_KeyValue(Handle parser, const char[] key, const cha
return SMCParse_Continue;
}
public void OutputStart(const char[] output, int caller, int activator, float delay)
void OutputStart(const char[] output, int caller, int activator, float delay)
{
g_bEventStarted = true;
}
public void OutputStop(const char[] output, int caller, int activator, float delay)
void OutputStop(const char[] output, int caller, int activator, float delay)
{
g_bEventStarted = false;
}
public SMCResult ColorConfig_EndSection(Handle parser)
SMCResult ColorConfig_EndSection(Handle parser)
{
g_iSectionLevel--;
return SMCParse_Continue;
}
public void ColorConfig_End(Handle parser, bool halted, bool failed)
void ColorConfig_End(Handle parser, bool halted, bool failed)
{
if( failed )
SetFailState("Error: Cannot load the config file: \"%s\"", EVENTS_CONFIG);
@ -536,7 +550,7 @@ int FindByClassTargetName(const char[] sClass, const char[] sTarget)
// ====================================================================================================
// EVENTS
// ====================================================================================================
public void Event_RoundStart(Event event, const char[] name, bool dontBroadcast)
void Event_RoundStart(Event event, const char[] name, bool dontBroadcast)
{
delete g_hTimer;
@ -568,13 +582,13 @@ public void Event_RoundStart(Event event, const char[] name, bool dontBroadcast)
}
}
public void Event_RoundEnd(Event event, const char[] name, bool dontBroadcast)
void Event_RoundEnd(Event event, const char[] name, bool dontBroadcast)
{
ResetSlowdown();
ResetPlugin();
}
public void Event_PlayerDeath(Event event, const char[] name, bool dontBroadcast)
void Event_PlayerDeath(Event event, const char[] name, bool dontBroadcast)
{
int client = GetClientOfUserId(event.GetInt("userid"));
if( client )
@ -583,7 +597,7 @@ public void Event_PlayerDeath(Event event, const char[] name, bool dontBroadcast
}
}
public void Event_PlayerTeam(Event event, const char[] name, bool dontBroadcast)
void Event_PlayerTeam(Event event, const char[] name, bool dontBroadcast)
{
int client = GetClientOfUserId(event.GetInt("userid"));
if( client )
@ -624,6 +638,7 @@ void ResetClient(int i)
g_fHintLast[i] = 0.0;
g_fHintWarn[i] = 0.0;
g_fLastFlow[i] = 0.0;
g_fHighestFlow[i] = 0.0;
SDKUnhook(i, SDKHook_PreThinkPost, PreThinkPost);
}
@ -646,7 +661,7 @@ void ResetSlowdown()
// ====================================================================================================
// LOGIC
// ====================================================================================================
public Action TimerTest(Handle timer)
Action TimerTest(Handle timer)
{
if( !g_bMapStarted ) return Plugin_Continue;
@ -712,7 +727,7 @@ public Action TimerTest(Handle timer)
continue;
// Ignore healing / using stuff
if( GetEntPropEnt(client, Prop_Send, "m_useActionTarget") > 0 )
if( g_bLeft4Dead2 && GetEntPropEnt(client, Prop_Send, "m_useActionTarget") > 0 )
continue;
// Ignore reviving
@ -734,6 +749,13 @@ public Action TimerTest(Handle timer)
// Get flow
flow = L4D2Direct_GetFlowDistance(client);
// Only get the highest flow
if(flow > g_fHighestFlow[client]) {
g_fHighestFlow[client] = flow;
} else {
flow = g_fHighestFlow[client];
}
if( flow && flow != -9999.0 ) // Invalid flows
{
countflow++;
@ -792,17 +814,17 @@ public Action TimerTest(Handle timer)
{
g_fHintWarn[client] = GetGameTime() + g_fCvarWarnTime;
if( g_iCvarType == 1 )
ClientHintMessage(client, "Warn_Slowdown");
else
ClientHintMessage(client, "Warn_Ahead");
switch( g_iCvarType )
{
case 0: ClientHintMessage(client, "Warn_Health");
case 1: ClientHintMessage(client, "Warn_Slowdown");
case 2: ClientHintMessage(client, "Warn_Ahead");
}
}
// Compare higher flow with next survivor, they're rushing
if( distance > g_fCvarRangeLead )
{
// PrintToServer("RUSH: %N %f", client, distance);
flowBack = false;
int punishType = g_iCvarType, result;
Call_StartForward(g_OnRushForward);
@ -812,8 +834,11 @@ public Action TimerTest(Handle timer)
if(Call_Finish(result) == SP_ERROR_NONE && result > 0) break;
// PrintToServer("RUSH: %N %f", client, distance);
flowBack = false;
// Slowdown enabled?
if( punishType == 1 )
if( g_fCvarHealth || punishType == 1 )
{
// Inhibit moving forward
// Only check > or < because when == the same flow distance, they're either already being slowed or running back, so we don't want to change/affect them within the same flow NavMesh.
@ -821,7 +846,7 @@ public Action TimerTest(Handle timer)
{
g_fLastFlow[client] = flow;
if( g_bInhibit[client] == false )
if( g_iCvarType == 1 && g_bInhibit[client] == false )
{
g_bInhibit[client] = true;
SDKHook(client, SDKHook_PreThinkPost, PreThinkPost);
@ -832,7 +857,17 @@ public Action TimerTest(Handle timer)
{
g_fHintLast[client] = GetGameTime() + g_fCvarTime;
ClientHintMessage(client, "Rush_Slowdown");
switch( g_iCvarType )
{
case 0: ClientHintMessage(client, "Rush_Health");
case 1: ClientHintMessage(client, "Rush_Slowdown");
}
}
// Hurt for rushing?
if( g_fCvarHealth )
{
SDKHooks_TakeDamage(client, 0, 0, g_fCvarHealth);
}
}
else if( flow < g_fLastFlow[client] )
@ -973,7 +1008,7 @@ public Action L4D_OnGetWalkTopSpeed(int target, float &retVal)
}
// */
public void PreThinkPost(int client)
void PreThinkPost(int client)
{
SetEntPropFloat(client, Prop_Send, "m_flMaxspeed", g_fCvarSlow);
}

View file

@ -80,7 +80,7 @@ public void OnPluginStart() {
void ShowRepMenu(int client, int targetUserid) {
Menu menu = new Menu(RepFinalHandler);
menu.SetTitle("Choose a rating");
char id[8];
char id[16];
Format(id, sizeof(id), "%d|1", targetUserid);
menu.AddItem(id, "+Rep");
Format(id, sizeof(id), "%d|1", targetUserid);
@ -91,7 +91,7 @@ void ShowRepMenu(int client, int targetUserid) {
public int RepPlayerHandler(Menu menu, MenuAction action, int param1, int param2) {
/* If an option was selected, tell the client about the item. */
if (action == MenuAction_Select) {
static char info[4];
static char info[8];
menu.GetItem(param2, info, sizeof(info));
int targetUserid = StringToInt(info);
int target = GetClientOfUserId(targetUserid);
@ -111,7 +111,7 @@ public int RepPlayerHandler(Menu menu, MenuAction action, int param1, int param2
public int RepFinalHandler(Menu menu, MenuAction action, int param1, int param2) {
/* If an option was selected, tell the client about the item. */
if (action == MenuAction_Select) {
char info[8];
char info[16];
menu.GetItem(param2, info, sizeof(info));
char str[2][8];
ExplodeString(info, "|", str, 2, 8, false);
@ -443,7 +443,7 @@ public void DB_FindNotes(Database db, DBResultSet results, const char[] error, a
CPrintChatToAdmins(" > {olive}%d Auto Actions Applied", actions);
}
if(repP > 0 || repN > 0) {
CPrintChatToAdmins(" > {olive}%d +rep\t{yellow}-rep", repP, repN);
CPrintChatToAdmins(" > {olive}%d +rep\t{yellow}%d-rep", repP, repN);
}
}
}
@ -615,6 +615,6 @@ any Native_AddNoteIdentity(Handle plugin, int numParams) {
void AddNoteIdentity(const char noteCreator[32], const char noteTarget[32], const char[] message) {
// messaege length + steamids (32 + 32 + null term)
// char[] query = new char[strlen(message) + 65];
DB.Format(query, sizeof(query), "INSERT INTO `notes` (steamid, markedBy, content) VALUES ('%s', '%s', '%s')", noteCreator, noteTarget, message);
DB.Format(query, sizeof(query), "INSERT INTO `notes` (steamid, markedBy, content) VALUES ('%s', '%s', '%s')", noteTarget, noteCreator, message);
DB.Query(DB_AddNote, query);
}