diff --git a/plugins/L4D2FFKickProtection.smx b/plugins/L4D2FFKickProtection.smx index 9f01014..c9cb15d 100644 Binary files a/plugins/L4D2FFKickProtection.smx and b/plugins/L4D2FFKickProtection.smx differ diff --git a/plugins/l4d2_feedthetrolls.smx b/plugins/l4d2_feedthetrolls.smx index 856515b..8c0aa8f 100644 Binary files a/plugins/l4d2_feedthetrolls.smx and b/plugins/l4d2_feedthetrolls.smx differ diff --git a/scripting/L4D2FFKickProtection.sp b/scripting/L4D2FFKickProtection.sp index 93438b2..0467ede 100644 --- a/scripting/L4D2FFKickProtection.sp +++ b/scripting/L4D2FFKickProtection.sp @@ -36,11 +36,13 @@ public void OnPluginStart() { forceKickFFThreshold = CreateConVar("sm_votekick_force_threshold","30.0","The threshold of amount of FF to then automatically kick.\n0: Any attempted damage\n -1: No auto kick.\n>0: When FF count > this", FCVAR_NONE, true, -1.0); } +int iJoinTime[MAXPLAYERS+1]; public void OnClientPutInServer(int client) { int team = GetClientTeam(client); if(team == 2) { SDKHook(client, SDKHook_OnTakeDamageAlive, OnTakeDamage); } + iJoinTime[client] = GetTime(); } public void Event_PlayerTeam(Event event, const char[] name, bool dontBroadcast) { @@ -56,8 +58,13 @@ public void Event_PlayerTeam(Event event, const char[] name, bool dontBroadcast) } } /* -Dropped BabybackRibs from server (Disconnect by user.) L 02/16/2022 - 10:38:53: [SM] Exception reported: No valid ban method flags specified L 02/16/2022 - 10:38:53: [SM] Blaming: L4D2FFKickProtection.smx L 02/16/2022 - 10:38:53: [SM] Call stack trace: L 02/16/2022 - 10:38:53: [SM] [0] BanClient L 02/16/2022 - 10:38:53: [SM] [1] Line 78, s:\Jackz\Documents\Sourcepawn\scripting\L4D2FFKickProtection.sp::VoteStart Potential vote being called Client "Andean Brain Surgeon" connected (70.112.126.195:27005). String Table dictionary for downloadables should be rebuilt, only found 39 of 51 strings in dictionary String Table dictionary for soundprecache */ - +Dropped BabybackRibs from server (Disconnect by user.) +L 02/16/2022 - 10:38:53: [SM] Exception reported: No valid ban method flags specified +L 02/16/2022 - 10:38:53: [SM] Blaming: L4D2FFKickProtection.smx + L 02/16/2022 - 10:38:53: [SM] Call stack trace: + L 02/16/2022 - 10:38:53: [SM] [0] BanClient + L 02/16/2022 - 10:38:53: [SM] [1] Line 78, s:\Jackz\Documents\Sourcepawn\scripting\L4D2FFKickProtection.sp::VoteStart Potential vote being called +*/ public Action VoteStart(int client, const char[] command, int argc) { if(!IsClientInGame(client)) { PrintToServer("Preventing vote from user not in game: %N", client); @@ -80,8 +87,13 @@ public Action VoteStart(int client, const char[] command, int argc) { AdminId targetAdmin = GetUserAdmin(target); if(targetAdmin != INVALID_ADMIN_ID) { //Only run if vote is against an admin PrintToChat(target, "%N has attempted to vote kick you.", client); - if(callerAdmin == INVALID_ADMIN_ID) { //If vote starter is not an admin, ban their ass - BanClient(client, 0, 0, "Attempted Vote Kick Admin", "Dick-Be-Gone", "noFF"); + for(int i = 1; i <= MaxClients; i++) { + if(target != i && IsClientConnected(i) && IsClientInGame(i) && GetUserAdmin(i) != INVALID_ADMIN_ID) { + PrintToChat(i, "%N attempted to vote-kick %N", client, target); + } + } + if(callerAdmin == INVALID_ADMIN_ID && GetTime() - iJoinTime[client] <= 120) { + KickClient(client, "No."); } return Plugin_Handled; } diff --git a/scripting/include/feedthetrolls/commands.inc b/scripting/include/feedthetrolls/commands.inc index 0e9b698..fcd5e8d 100644 --- a/scripting/include/feedthetrolls/commands.inc +++ b/scripting/include/feedthetrolls/commands.inc @@ -39,9 +39,9 @@ public Action Command_InstaSpecial(int client, int args) { ReplyToTargetError(client, target_count); return Plugin_Handled; } - int specialType = GetSpecialType(arg2); + SpecialType specialType = GetSpecialType(arg2); static float pos[3]; - if(specialType == -1) { + if(specialType == Special_Invalid) { ReplyToCommand(client, "Unknown special \"%s\"", arg2); return Plugin_Handled; } @@ -108,9 +108,9 @@ public Action Command_InstaSpecialFace(int client, int args) { ReplyToTargetError(client, target_count); return Plugin_Handled; } - int specialType = GetSpecialType(arg2); + SpecialType specialType = GetSpecialType(arg2); static float pos[3]; - if(specialType == -1) { + if(specialType == Special_Invalid) { ReplyToCommand(client, "Unknown special \"%s\"", arg2); return Plugin_Handled; } diff --git a/scripting/include/feedthetrolls/events.inc b/scripting/include/feedthetrolls/events.inc index e009062..a9a56e4 100644 --- a/scripting/include/feedthetrolls/events.inc +++ b/scripting/include/feedthetrolls/events.inc @@ -30,11 +30,15 @@ public void Event_PlayerSpawn(Event event, const char[] name, bool dontBroadcast } public Action Timer_CheckSpecial(Handle h, int specialID) { int special = GetClientOfUserId(specialID); + // Check if new player is the spawned special: if(special > 0 && gInstaSpecialType > -1 && IsFakeClient(special) && GetClientTeam(special) == 3) { int type = GetEntProp(special, Prop_Send, "m_zombieClass"); + // Verify type of special is spawned special if(type == gInstaSpecialType) { gInstaSpecialType = -1; + // Set special to only attack them: g_iAttackerTarget[special] = gInstaSpecialTarget; + // Incremenet count of specials targetting player: gInstaSpecialMagnet[GetClientOfUserId(gInstaSpecialTarget)]++; TeleportEntity(special, gInstaSpecialSpawnPos, gInstaSpecialSpawnAng, NULL_VECTOR); @@ -95,9 +99,8 @@ public Action Event_PlayerDeath(Event event, const char[] name, bool dontBroadca } public Action Event_WeaponReload(int weapon) { int client = GetEntPropEnt(weapon, Prop_Send, "m_hOwner"); - if(IsTrollActive(client, "Gun Jam")) { - float dec = GetRandomFloat(0.0, 1.0); - if(FloatCompare(dec, 0.50) == -1) { //10% chance gun jams + if(client > 0 && IsTrollActive(client, "Gun Jam")) { + if(GetRandomFloat() < 0.10) { //10% chance gun jams return Plugin_Stop; } } @@ -140,7 +143,7 @@ public Action L4D2_OnChooseVictim(int attacker, int &curTarget) { int existingTarget = GetClientOfUserId(g_iAttackerTarget[attacker]); if(existingTarget > 0) { if(IsPlayerAlive(existingTarget)) { - // Insta-specials ALWAYS target + // Insta-specials ALWAYS target, if target has any attackers remaining if(gInstaSpecialMagnet[existingTarget] > 0) { curTarget = existingTarget; return Plugin_Changed; @@ -711,7 +714,7 @@ public Action OnAntiRush(int client, int &type, float distance) { PrintToConsoleAll("[FTT] Antirush: %N (dist=%d) (GameTime=%f)", client, distance, GetGameTime()); if(type == 3 && IsPlayerAlive(client) && !IsPlayerIncapped(client)) { if(GetGameTime() - iLastAntiRushEvent[client] > 30.0) { - int special = GetRandomInt(0,6); + SpecialType special = view_as(GetRandomInt(0,6)); iLastAntiRushEvent[client] = GetGameTime(); SpawnSpecialNear(client, special); PrintToConsoleAll("[FTT] Spawning anti-rush special on %N (dist=%f) (special=%d)", client, distance, special); diff --git a/scripting/include/feedthetrolls/menus.inc b/scripting/include/feedthetrolls/menus.inc index 0f3c290..d157028 100644 --- a/scripting/include/feedthetrolls/menus.inc +++ b/scripting/include/feedthetrolls/menus.inc @@ -31,18 +31,23 @@ public int Insta_SpecialHandler(Menu menu, MenuAction action, int client, int pa ExplodeString(info, "|", str, 3, 8, false); int target = GetClientOfUserId(StringToInt(str[0])); bool inFace = StrEqual(str[1], "1"); - int special = StringToInt(str[2]); + int specialInt = StringToInt(str[2]); + if(specialInt < 0 || specialInt > 8) { + ReplyToCommand(client, "Invalid special id"); + return; + } + SpecialType special = view_as(specialInt); if(inFace) { if(SpawnSpecialInFace(target, special)) { - LogAction(client, target, "\"%L\" spawned Insta-%s™ on \"%L\"", client, SPECIAL_NAMES[special-1], target); - ShowActivityEx(client, "[FTT] ", "spawned Insta-%s™ on %N", SPECIAL_NAMES[special-1], target); + LogAction(client, target, "\"%L\" spawned Insta-%s™ on \"%L\"", client, SPECIAL_NAMES[specialInt-1], target); + ShowActivityEx(client, "[FTT] ", "spawned Insta-%s™ on %N", SPECIAL_NAMES[specialInt-1], target); } else { ReplyToCommand(client, "Could not spawn special."); } } else { if(SpawnSpecialNear(target, special)) { - LogAction(client, target, "\"%L\" spawned Insta-%s™ near \"%L\"", client, SPECIAL_NAMES[special-1], target); - ShowActivityEx(client, "[FTT] ", "spawned Insta-%s™ near %N", SPECIAL_NAMES[special-1], target); + LogAction(client, target, "\"%L\" spawned Insta-%s™ near \"%L\"", client, SPECIAL_NAMES[specialInt-1], target); + ShowActivityEx(client, "[FTT] ", "spawned Insta-%s™ near %N", SPECIAL_NAMES[specialInt-1], target); } else { ReplyToCommand(client, "Could not spawn special."); } diff --git a/scripting/include/feedthetrolls/specials.inc b/scripting/include/feedthetrolls/specials.inc index 559b011..cb20914 100644 --- a/scripting/include/feedthetrolls/specials.inc +++ b/scripting/include/feedthetrolls/specials.inc @@ -1,12 +1,23 @@ char SPECIAL_NAMES[][] = { "Smoker", "Boomer", "Hunter", "Spitter", "Jockey", "Charger", "Witch", "Tank" }; +enum SpecialType { + Special_Invalid = -1, + Special_Smoker = 0, + Special_Boomer, + Special_Hunter, + Special_Spitter, + Special_Jockey, + Special_Charger, + Special_Witch, + Special_Tank +} -stock int GetSpecialType(const char[] input) { +stock SpecialType GetSpecialType(const char[] input) { for(int i = 0; i < 8; i++) { - if(strcmp(SPECIAL_NAMES[i], input, false) == 0) return i + 1; + if(strcmp(SPECIAL_NAMES[i], input, false) == 0) return view_as(i + 1); } - return -1; + return Special_Invalid; } stock bool FindSuitablePosition(int target, const float pos[3], float outputPos[3], float minDistance = 19000.0, int tries = 100) { @@ -25,7 +36,7 @@ stock bool FindSuitablePosition(int target, const float pos[3], float outputPos[ return false; } -float GetIdealMinDistance(int specialType) { +float GetIdealMinDistance(SpecialType specialType) { switch(specialType) { // /*Boomer*/ case 2: return 1200.0; /*Charger*/ case 6: return 19500.0; @@ -36,20 +47,19 @@ float GetIdealMinDistance(int specialType) { } } -bool SpawnSpecialInFace(int target, int specialType) { - if(specialType > 8) return false; +bool SpawnSpecialInFace(int target, SpecialType specialType) { static float pos[3], ang[3]; static float testPos[3]; testPos = pos; GetClientAbsOrigin(target, pos); GetClientEyeAngles(target, ang); - if(specialType == 2) + if(specialType == Special_Boomer) gInstaSpecialInstaKill = true; - if(specialType != 5 && specialType != 2) { //If not jockey/hunter find a suitable area that is at least 5 m away + if(specialType != Special_Jockey && specialType != Special_Hunter) { //If not jockey/hunter find a suitable area that is at least 5 m away float minDistance = GetIdealMinDistance(specialType); GetHorizontalPositionFromOrigin(pos, ang, minDistance, testPos); if(!FindSuitablePosition(target, pos, testPos, minDistance, 100)) { - L4D_GetRandomPZSpawnPosition(target, specialType, 10, testPos); + L4D_GetRandomPZSpawnPosition(target, view_as(specialType), 10, testPos); } pos = testPos; } else { // Else spawn a little bit off, and above (above for jockeys) @@ -62,12 +72,11 @@ bool SpawnSpecialInFace(int target, int specialType) { return SpawnSpecialInternal(specialType, target, pos, NULL_VECTOR) != -1; } -bool SpawnSpecialNear(int target, int specialType) { +bool SpawnSpecialNear(int target, SpecialType type) { gInstaSpecialInstaKill = false; - if(specialType > 8) return false; static float pos[3]; - if(L4D_GetRandomPZSpawnPosition(target, specialType, 10, pos)) { - return SpawnSpecialInternal(specialType, target, pos, NULL_VECTOR) != -1; + if(L4D_GetRandomPZSpawnPosition(target, view_as(type), 10, pos)) { + return SpawnSpecialInternal(type, target, pos, NULL_VECTOR) != -1; } return false; } @@ -81,10 +90,10 @@ void BypassLimit() { } } -int SpawnSpecialInternal(int type, int target, float pos[3], float ang[3]) { - if(type <= 6) { +int SpawnSpecialInternal(SpecialType type, int target, float pos[3], float ang[3]) { + if(view_as(type) <= 6) { // Bypass limit: - gInstaSpecialType = type; + gInstaSpecialType = view_as(type); gInstaSpecialTarget = GetClientUserId(target); gInstaSpecialSpawnPos = pos; gInstaSpecialSpawnAng = pos; @@ -94,16 +103,16 @@ int SpawnSpecialInternal(int type, int target, float pos[3], float ang[3]) { ChangeClientTeam(bot, 3); CreateTimer(0.1, Timer_KickBot, bot); } - CheatCommand(target, "z_spawn_old", SPECIAL_NAMES[type-1], "auto"); + CheatCommand(target, "z_spawn_old", SPECIAL_NAMES[view_as(type) = -1], "auto"); return 0; } - else if(type == 7) { + else if(type == Special_Witch) { int witch = L4D2_SpawnWitch(pos, ang); if(witch != -1) SetWitchTarget(witch, target); return witch; } - else if(type == 8) { + else if(type == Special_Tank) { // BypassLimit(); int tank = L4D2_SpawnTank(pos, ang); if(tank <= 0 || !IsClientConnected(tank)) return -1; @@ -114,8 +123,24 @@ int SpawnSpecialInternal(int type, int target, float pos[3], float ang[3]) { else return -1; } -/* TODO: Bypass limit: - Spawn special auto, far away, mark with global vars: - 1. special type (check) - 2. its target - 3. float[3] to TP it to \ No newline at end of file +stock bool GetGroundBehind(int client, float vPos[3], float vAng[3]) { + GetClientAbsOrigin(client, vPos); + vAng = vPos; + vAng[2] += 5.0; + vPos[2] -= 500.0; + + Handle trace = TR_TraceRayFilterEx(vAng, vPos, MASK_SHOT, RayType_EndPoint, RayFilter_NonClient); + if(!TR_DidHit(trace)) { + delete trace; + return false; + } + TR_GetEndPosition(vPos, trace); + delete trace; + + GetClientAbsAngles(client, vAng); + return true; +} + +stock bool RayFilter_NonClient(int entity, int contentsMask) { + return entity > MaxClients; +} \ No newline at end of file