diff options
Diffstat (limited to 'sourcemod/scripting/gokz-anticheat')
| -rw-r--r-- | sourcemod/scripting/gokz-anticheat/api.sp | 174 | ||||
| -rw-r--r-- | sourcemod/scripting/gokz-anticheat/bhop_tracking.sp | 336 | ||||
| -rw-r--r-- | sourcemod/scripting/gokz-anticheat/commands.sp | 76 |
3 files changed, 0 insertions, 586 deletions
diff --git a/sourcemod/scripting/gokz-anticheat/api.sp b/sourcemod/scripting/gokz-anticheat/api.sp deleted file mode 100644 index 7f99724..0000000 --- a/sourcemod/scripting/gokz-anticheat/api.sp +++ /dev/null @@ -1,174 +0,0 @@ -static GlobalForward H_OnPlayerSuspected; - - - -// =====[ FORWARDS ]===== - -void CreateGlobalForwards() -{ - H_OnPlayerSuspected = new GlobalForward("GOKZ_AC_OnPlayerSuspected", ET_Ignore, Param_Cell, Param_Cell, Param_String, Param_String); -} - -void Call_OnPlayerSuspected(int client, ACReason reason, const char[] notes, const char[] stats) -{ - Call_StartForward(H_OnPlayerSuspected); - Call_PushCell(client); - Call_PushCell(reason); - Call_PushString(notes); - Call_PushString(stats); - Call_Finish(); -} - - - -// =====[ NATIVES ]===== - -void CreateNatives() -{ - CreateNative("GOKZ_AC_GetSampleSize", Native_GetSampleSize); - CreateNative("GOKZ_AC_GetHitPerf", Native_GetHitPerf); - CreateNative("GOKZ_AC_GetPerfCount", Native_GetPerfCount); - CreateNative("GOKZ_AC_GetPerfRatio", Native_GetPerfRatio); - CreateNative("GOKZ_AC_GetJumpInputs", Native_GetJumpInputs); - CreateNative("GOKZ_AC_GetAverageJumpInputs", Native_GetAverageJumpInputs); - CreateNative("GOKZ_AC_GetPreJumpInputs", Native_GetPreJumpInputs); - CreateNative("GOKZ_AC_GetPostJumpInputs", Native_GetPostJumpInputs); -} - -public int Native_GetSampleSize(Handle plugin, int numParams) -{ - int client = GetNativeCell(1); - return IntMin(gI_BhopCount[client], AC_MAX_BHOP_SAMPLES); -} - -public int Native_GetHitPerf(Handle plugin, int numParams) -{ - int client = GetNativeCell(1); - int sampleSize = IntMin(GOKZ_AC_GetSampleSize(client), GetNativeCell(3)); - - if (sampleSize == 0) - { - return 0; - } - - bool[] perfs = new bool[sampleSize]; - SortByRecent(gB_BhopHitPerf[client], AC_MAX_BHOP_SAMPLES, perfs, sampleSize, gI_BhopIndex[client]); - SetNativeArray(2, perfs, sampleSize); - return sampleSize; -} - -public int Native_GetPerfCount(Handle plugin, int numParams) -{ - int client = GetNativeCell(1); - int sampleSize = IntMin(GOKZ_AC_GetSampleSize(client), GetNativeCell(2)); - - if (sampleSize == 0) - { - return 0; - } - - bool[] perfs = new bool[sampleSize]; - GOKZ_AC_GetHitPerf(client, perfs, sampleSize); - - int perfCount = 0; - for (int i = 0; i < sampleSize; i++) - { - if (perfs[i]) - { - perfCount++; - } - } - return perfCount; -} - -public int Native_GetPerfRatio(Handle plugin, int numParams) -{ - int client = GetNativeCell(1); - int sampleSize = IntMin(GOKZ_AC_GetSampleSize(client), GetNativeCell(2)); - - if (sampleSize == 0) - { - return view_as<int>(0.0); - } - - int perfCount = GOKZ_AC_GetPerfCount(client, sampleSize); - return view_as<int>(float(perfCount) / float(sampleSize)); -} - -public int Native_GetJumpInputs(Handle plugin, int numParams) -{ - int client = GetNativeCell(1); - int sampleSize = IntMin(GOKZ_AC_GetSampleSize(client), GetNativeCell(3)); - - if (sampleSize == 0) - { - return 0; - } - - int[] preJumpInputs = new int[sampleSize]; - SortByRecent(gI_BhopPreJumpInputs[client], AC_MAX_BHOP_SAMPLES, preJumpInputs, sampleSize, gI_BhopIndex[client]); - int[] postJumpInputs = new int[sampleSize]; - SortByRecent(gI_BhopPostJumpInputs[client], AC_MAX_BHOP_SAMPLES, postJumpInputs, sampleSize, gI_BhopIndex[client]); - - int[] jumpInputs = new int[sampleSize]; - for (int i = 0; i < sampleSize; i++) - { - jumpInputs[i] = preJumpInputs[i] + postJumpInputs[i]; - } - - SetNativeArray(2, jumpInputs, sampleSize); - return sampleSize; -} - -public int Native_GetAverageJumpInputs(Handle plugin, int numParams) -{ - int client = GetNativeCell(1); - int sampleSize = IntMin(GOKZ_AC_GetSampleSize(client), GetNativeCell(2)); - - if (sampleSize == 0) - { - return view_as<int>(0.0); - } - - int[] jumpInputs = new int[sampleSize]; - GOKZ_AC_GetJumpInputs(client, jumpInputs, sampleSize); - - int jumpInputCount = 0; - for (int i = 0; i < sampleSize; i++) - { - jumpInputCount += jumpInputs[i]; - } - return view_as<int>(float(jumpInputCount) / float(sampleSize)); -} - -public int Native_GetPreJumpInputs(Handle plugin, int numParams) -{ - int client = GetNativeCell(1); - int sampleSize = IntMin(GOKZ_AC_GetSampleSize(client), GetNativeCell(3)); - - if (sampleSize == 0) - { - return 0; - } - - int[] preJumpInputs = new int[sampleSize]; - SortByRecent(gI_BhopPreJumpInputs[client], AC_MAX_BHOP_SAMPLES, preJumpInputs, sampleSize, gI_BhopIndex[client]); - SetNativeArray(2, preJumpInputs, sampleSize); - return sampleSize; -} - -public int Native_GetPostJumpInputs(Handle plugin, int numParams) -{ - int client = GetNativeCell(1); - int sampleSize = IntMin(GOKZ_AC_GetSampleSize(client), GetNativeCell(3)); - - if (sampleSize == 0) - { - return 0; - } - - int[] postJumpInputs = new int[sampleSize]; - SortByRecent(gI_BhopPostJumpInputs[client], AC_MAX_BHOP_SAMPLES, postJumpInputs, sampleSize, gI_BhopIndex[client]); - SetNativeArray(2, postJumpInputs, sampleSize); - return sampleSize; -}
\ No newline at end of file diff --git a/sourcemod/scripting/gokz-anticheat/bhop_tracking.sp b/sourcemod/scripting/gokz-anticheat/bhop_tracking.sp deleted file mode 100644 index 5607b07..0000000 --- a/sourcemod/scripting/gokz-anticheat/bhop_tracking.sp +++ /dev/null @@ -1,336 +0,0 @@ -/* - Track player's jump inputs and whether they hit perfect - bunnyhops for a number of their recent bunnyhops. -*/ - - - -// =====[ PUBLIC ]===== - -void PrintBhopCheckToChat(int client, int target) -{ - GOKZ_PrintToChat(client, true, - "{lime}%N {grey}[{lime}%d%%%% {grey}%t | {lime}%.2f {grey}%t]", - target, - RoundFloat(GOKZ_AC_GetPerfRatio(target, 20) * 100.0), - "Perfs", - GOKZ_AC_GetAverageJumpInputs(target, 20), - "Average"); - GOKZ_PrintToChat(client, false, - " {grey}%t - %s", - "Pattern", - GenerateScrollPattern(target, 20)); -} - -void PrintBhopCheckToConsole(int client, int target) -{ - PrintToConsole(client, - "%N [%d%% %t | %.2f %t]\n %t - %s", - target, - RoundFloat(GOKZ_AC_GetPerfRatio(target, 20) * 100.0), - "Perfs", - GOKZ_AC_GetAverageJumpInputs(target, 20), - "Average", - "Pattern", - GenerateScrollPattern(target, 20, false)); -} - -// Generate 'scroll pattern' -char[] GenerateScrollPattern(int client, int sampleSize = AC_MAX_BHOP_SAMPLES, bool colours = true) -{ - char report[512]; - int maxIndex = IntMin(gI_BhopCount[client], sampleSize); - bool[] perfs = new bool[maxIndex]; - GOKZ_AC_GetHitPerf(client, perfs, maxIndex); - int[] jumpInputs = new int[maxIndex]; - GOKZ_AC_GetJumpInputs(client, jumpInputs, maxIndex); - - for (int i = 0; i < maxIndex; i++) - { - if (colours) - { - Format(report, sizeof(report), "%s%s%d ", - report, - perfs[i] ? "{green}" : "{default}", - jumpInputs[i]); - } - else - { - Format(report, sizeof(report), "%s%d%s ", - report, - jumpInputs[i], - perfs[i] ? "*" : ""); - } - } - - TrimString(report); - - return report; -} - -// Generate 'scroll pattern' report showing pre and post inputs instead -char[] GenerateScrollPatternEx(int client, int sampleSize = AC_MAX_BHOP_SAMPLES) -{ - char report[512]; - int maxIndex = IntMin(gI_BhopCount[client], sampleSize); - bool[] perfs = new bool[maxIndex]; - GOKZ_AC_GetHitPerf(client, perfs, maxIndex); - int[] jumpInputs = new int[maxIndex]; - GOKZ_AC_GetJumpInputs(client, jumpInputs, maxIndex); - int[] preJumpInputs = new int[maxIndex]; - GOKZ_AC_GetPreJumpInputs(client, preJumpInputs, maxIndex); - int[] postJumpInputs = new int[maxIndex]; - GOKZ_AC_GetPostJumpInputs(client, postJumpInputs, maxIndex); - - for (int i = 0; i < maxIndex; i++) - { - Format(report, sizeof(report), "%s(%d%s%d)", - report, - preJumpInputs[i], - perfs[i] ? "*" : " ", - postJumpInputs[i]); - } - - TrimString(report); - - return report; -} - - - -// =====[ EVENTS ]===== - -void OnClientPutInServer_BhopTracking(int client) -{ - ResetBhopStats(client); -} - -void OnPlayerRunCmdPost_BhopTracking(int client, int buttons, int cmdnum) -{ - if (gCV_sv_autobunnyhopping.BoolValue) - { - return; - } - - int nextIndex = NextIndex(gI_BhopIndex[client], AC_MAX_BHOP_SAMPLES); - - // Record buttons BEFORE checking for bhop - RecordButtons(client, buttons); - - // If bhop was last tick, then record the pre bhop inputs. - // Require two times the button sample size since the last - // takeoff to avoid pre and post bhop input overlap. - if (HitBhop(client, cmdnum) - && cmdnum >= gI_BhopLastTakeoffCmdnum[client] + AC_MAX_BUTTON_SAMPLES * 2 - && gB_LastLandingWasValid[client]) - { - gB_BhopHitPerf[client][nextIndex] = Movement_GetHitPerf(client); - gI_BhopPreJumpInputs[client][nextIndex] = CountJumpInputs(client); - gI_BhopLastRecordedBhopCmdnum[client] = cmdnum; - gB_BhopPostJumpInputsPending[client] = true; - gB_BindExceptionPending[client] = false; - gB_BindExceptionPostPending[client] = false; - } - - // Bind exception - if (gB_BindExceptionPending[client] && cmdnum > Movement_GetLandingCmdNum(client) + AC_MAX_BHOP_GROUND_TICKS) - { - gB_BhopHitPerf[client][nextIndex] = false; - gI_BhopPreJumpInputs[client][nextIndex] = -1; // Special value for binded jumps - gI_BhopLastRecordedBhopCmdnum[client] = cmdnum; - gB_BhopPostJumpInputsPending[client] = true; - gB_BindExceptionPending[client] = false; - gB_BindExceptionPostPending[client] = true; - } - - // Record post bhop inputs once enough ticks have passed - if (gB_BhopPostJumpInputsPending[client] && cmdnum == gI_BhopLastRecordedBhopCmdnum[client] + AC_MAX_BUTTON_SAMPLES) - { - gI_BhopPostJumpInputs[client][nextIndex] = CountJumpInputs(client); - gB_BhopPostJumpInputsPending[client] = false; - gI_BhopIndex[client] = nextIndex; - gI_BhopCount[client]++; - CheckForBhopMacro(client); - gB_BindExceptionPostPending[client] = false; - } - - // Record last jump takeoff time - if (JustJumped(client, cmdnum)) - { - gI_BhopLastTakeoffCmdnum[client] = cmdnum; - gB_BindExceptionPending[client] = false; - if (gB_BindExceptionPostPending[client]) - { - gB_BhopPostJumpInputsPending[client] = false; - gB_BindExceptionPostPending[client] = false; - } - } - - if (JustLanded(client, cmdnum)) - { - // These conditions exist to reduce false positives. - - // Telehopping is when the player bunnyhops out of a teleport that has a - // destination very close to the ground. This will, more than usual, - // result in a perfect bunnyhop. This is alleviated by checking if the - // player's origin was affected by a teleport last tick. - - // When a player is pressing up against a slope but not ascending it (e.g. - // palm trees on kz_adv_cursedjourney), they will switch between on ground - // and off ground frequently, which means that if they manage to jump, the - // jump will be recorded as a perfect bunnyhop. To ignore this, we check - // the jump is more than 1 tick duration. - - gB_LastLandingWasValid[client] = cmdnum - gI_LastOriginTeleportCmdNum[client] > 1 - && cmdnum - Movement_GetTakeoffCmdNum(client) > 1; - - // You can still crouch-bind VNL jumps and some people just don't know that - // it doesn't work with the other modes in GOKZ. This can cause false positives - // if the player uses the bind for bhops and mostly presses it too early or - // exactly on time rather than too late. This is supposed to reduce those by - // detecting jumps where you don't get a bhop and have exactly one jump input - // before landing and none after landing. We require the one input to be right - // before the jump to make it a lot harder to fake a binded jump when doing - // a regular longjump. - gB_BindExceptionPending[client] = (CountJumpInputs(client, AC_BINDEXCEPTION_SAMPLES) == 1 && CountJumpInputs(client, AC_MAX_BUTTON_SAMPLES) == 1); - gB_BindExceptionPostPending[client] = false; - } -} - - - -// =====[ PRIVATE ]===== - -static void CheckForBhopMacro(int client) -{ - if (GOKZ_AC_GetPerfCount(client, 19) == 19) - { - SuspectPlayer(client, ACReason_BhopHack, "High perf ratio", GenerateBhopBanStats(client, 19)); - } - else if (GOKZ_AC_GetPerfCount(client, 30) >= 28) - { - SuspectPlayer(client, ACReason_BhopHack, "High perf ratio", GenerateBhopBanStats(client, 30)); - } - else if (GOKZ_AC_GetPerfCount(client, 20) >= 16 && GOKZ_AC_GetAverageJumpInputs(client, 20) <= 2.0 + EPSILON) - { - SuspectPlayer(client, ACReason_BhopHack, "1's or 2's scroll pattern", GenerateBhopBanStats(client, 20)); - } - else if (gI_BhopCount[client] >= 20 && GOKZ_AC_GetPerfCount(client, 20) >= 8 - && GOKZ_AC_GetAverageJumpInputs(client, 20) >= 19.0 - EPSILON) - { - SuspectPlayer(client, ACReason_BhopMacro, "High scroll pattern", GenerateBhopBanStats(client, 20)); - } - else if (GOKZ_AC_GetPerfCount(client, 30) >= 10 && CheckForRepeatingJumpInputsCount(client, 25, 30) >= 14) - { - SuspectPlayer(client, ACReason_BhopMacro, "Repeating scroll pattern", GenerateBhopBanStats(client, 30)); - } -} - -static char[] GenerateBhopBanStats(int client, int sampleSize) -{ - char stats[512]; - FormatEx(stats, sizeof(stats), - "Perfs: %d/%d, Average: %.2f, Scroll pattern: %s", - GOKZ_AC_GetPerfCount(client, sampleSize), - IntMin(gI_BhopCount[client], sampleSize), - GOKZ_AC_GetAverageJumpInputs(client, sampleSize), - GenerateScrollPatternEx(client, sampleSize)); - return stats; -} - -/** - * Returns -1, or the repeating input count if there if there is - * an input count that repeats for more than the provided ratio. - * - * @param client Client index. - * @param threshold Minimum frequency to be considered 'repeating'. - * @param sampleSize Maximum recent bhop samples to include in calculation. - * @return The repeating input, or else -1. - */ -static int CheckForRepeatingJumpInputsCount(int client, int threshold, int sampleSize = AC_MAX_BHOP_SAMPLES) -{ - int maxIndex = IntMin(gI_BhopCount[client], sampleSize); - int[] jumpInputs = new int[maxIndex]; - GOKZ_AC_GetJumpInputs(client, jumpInputs, maxIndex); - int maxJumpInputs = AC_MAX_BUTTON_SAMPLES + 1; - int[] jumpInputsFrequency = new int[maxJumpInputs]; - - // Count up all the in jump patterns - for (int i = 0; i < maxIndex; i++) - { - // -1 is a binded jump, those are excluded - if (jumpInputs[i] != -1) - { - jumpInputsFrequency[jumpInputs[i]]++; - } - } - - // Returns i if the given number of the sample size has the same jump input count - for (int i = 1; i < maxJumpInputs; i++) - { - if (jumpInputsFrequency[i] >= threshold) - { - return i; - } - } - - return -1; // -1 if no repeating jump input found -} - -// Reset the tracked bhop stats of the client -static void ResetBhopStats(int client) -{ - gI_ButtonCount[client] = 0; - gI_ButtonsIndex[client] = 0; - gI_BhopCount[client] = 0; - gI_BhopIndex[client] = 0; - gI_BhopLastTakeoffCmdnum[client] = 0; - gI_BhopLastRecordedBhopCmdnum[client] = 0; - gB_BhopPostJumpInputsPending[client] = false; - gB_LastLandingWasValid[client] = false; - gB_BindExceptionPending[client] = false; - gB_BindExceptionPostPending[client] = false; -} - -// Returns true if ther was a jump last tick and was within a number of ticks after landing -static bool HitBhop(int client, int cmdnum) -{ - return JustJumped(client, cmdnum) && Movement_GetTakeoffCmdNum(client) - Movement_GetLandingCmdNum(client) <= AC_MAX_BHOP_GROUND_TICKS; -} - -static bool JustJumped(int client, int cmdnum) -{ - return Movement_GetJumped(client) && Movement_GetTakeoffCmdNum(client) == cmdnum; -} - -static bool JustLanded(int client, int cmdnum) -{ - return Movement_GetLandingCmdNum(client) == cmdnum; -} - -// Records current button inputs -static void RecordButtons(int client, int buttons) -{ - gI_ButtonsIndex[client] = NextIndex(gI_ButtonsIndex[client], AC_MAX_BUTTON_SAMPLES); - gI_Buttons[client][gI_ButtonsIndex[client]] = buttons; - gI_ButtonCount[client]++; -} - -// Counts the number of times buttons went from !IN_JUMP to IN_JUMP -static int CountJumpInputs(int client, int sampleSize = AC_MAX_BUTTON_SAMPLES) -{ - int[] recentButtons = new int[sampleSize]; - SortByRecent(gI_Buttons[client], AC_MAX_BUTTON_SAMPLES, recentButtons, sampleSize, gI_ButtonsIndex[client]); - int maxIndex = IntMin(gI_ButtonCount[client], sampleSize); - int jumps = 0; - - for (int i = 0; i < maxIndex - 1; i++) - { - // If buttons went from !IN_JUMP to IN_JUMP - if (!(recentButtons[i + 1] & IN_JUMP) && recentButtons[i] & IN_JUMP) - { - jumps++; - } - } - return jumps; -}
\ No newline at end of file diff --git a/sourcemod/scripting/gokz-anticheat/commands.sp b/sourcemod/scripting/gokz-anticheat/commands.sp deleted file mode 100644 index a1fbe2e..0000000 --- a/sourcemod/scripting/gokz-anticheat/commands.sp +++ /dev/null @@ -1,76 +0,0 @@ -void RegisterCommands() -{ - RegAdminCmd("sm_bhopcheck", CommandBhopCheck, ADMFLAG_ROOT, "[KZ] Show bunnyhop stats report including perf ratio and scroll pattern."); -} - -public Action CommandBhopCheck(int client, int args) -{ - if (args == 0) - { - if (GOKZ_AC_GetSampleSize(client) == 0) - { - GOKZ_PrintToChat(client, true, "%t", "Not Enough Bhops (Self)"); - } - else - { - PrintBhopCheckToChat(client, client); - } - return Plugin_Handled; - } - - char arg[65]; - GetCmdArg(1, arg, sizeof(arg)); - char targetName[MAX_TARGET_LENGTH]; - int targetList[MAXPLAYERS], targetCount; - bool tnIsML; - - if ((targetCount = ProcessTargetString( - arg, - client, - targetList, - MAXPLAYERS, - COMMAND_FILTER_NO_IMMUNITY | COMMAND_FILTER_NO_BOTS, - targetName, - sizeof(targetName), - tnIsML)) <= 0) - { - ReplyToTargetError(client, targetCount); - return Plugin_Handled; - } - - if (targetCount >= 2) - { - GOKZ_PrintToChat(client, true, "%t", "See Console"); - for (int i = 0; i < targetCount; i++) - { - if (GOKZ_AC_GetSampleSize(targetList[i]) == 0) - { - PrintToConsole(client, "%t", "Not Enough Bhops (Console)", targetList[i]); - } - else - { - PrintBhopCheckToConsole(client, targetList[i]); - } - } - } - else - { - if (GOKZ_AC_GetSampleSize(targetList[0]) == 0) - { - if (targetList[0] == client) - { - GOKZ_PrintToChat(client, true, "%t", "Not Enough Bhops (Self)"); - } - else - { - GOKZ_PrintToChat(client, true, "%t", "Not Enough Bhops", targetList[0]); - } - } - else - { - PrintBhopCheckToChat(client, targetList[0]); - } - } - - return Plugin_Handled; -}
\ No newline at end of file |
