diff --git a/AntiBhopCheat/scripting/AntiBhopCheat.sp b/AntiBhopCheat/scripting/AntiBhopCheat.sp new file mode 100644 index 00000000..8de82c81 --- /dev/null +++ b/AntiBhopCheat/scripting/AntiBhopCheat.sp @@ -0,0 +1,656 @@ +#include +#include +#include +#include + +#include +#include "CJump.inc" +#include "CStreak.inc" +#include "CPlayer.inc" + +#define MAX_STREAKS 10 +#define VALID_MIN_JUMPS 3 +#define VALID_MAX_TICKS 5 +#define VALID_MIN_VELOCITY 250 + +int g_aButtons[MAXPLAYERS + 1]; +bool g_bOnGround[MAXPLAYERS + 1]; +bool g_bHoldingJump[MAXPLAYERS + 1]; +bool g_bInJump[MAXPLAYERS + 1]; + +CPlayer g_aPlayers[MAXPLAYERS + 1]; + +// Api +Handle g_hOnClientDetected; + +char g_sStats[4096]; + +public Plugin myinfo = +{ + name = "AntiBhopCheat", + author = "BotoX", + description = "Detect all kinds of bhop cheats", + version = "0.0", + url = "" +}; + + +public void OnPluginStart() +{ + LoadTranslations("common.phrases"); + + RegAdminCmd("sm_stats", Command_Stats, ADMFLAG_GENERIC, "sm_stats <#userid|name>"); + RegAdminCmd("sm_streak", Command_Streak, ADMFLAG_GENERIC, "sm_streak <#userid|name> [streak]"); + + /* Handle late load */ + for(int client = 1; client <= MaxClients; client++) + { + if(IsClientConnected(client)) + { + if(IsClientInGame(client)) + OnClientPutInServer(client); + } + } + + // Api + g_hOnClientDetected = CreateGlobalForward("AntiBhopCheat_OnClientDetected", ET_Ignore, Param_Cell, Param_String, Param_String); +} + +public void OnClientPutInServer(int client) +{ + g_aPlayers[client] = new CPlayer(client); +} + +public void OnClientDisconnect(int client) +{ + if(g_aPlayers[client]) + { + g_aPlayers[client].Dispose(); + g_aPlayers[client] = null; + } + + g_bOnGround[client] = false; + g_bHoldingJump[client] = false; + g_bInJump[client] = false; +} + +public Action OnPlayerRunCmd(int client, int &buttons) +{ + g_aButtons[client] = buttons; + return Plugin_Continue; +} + +public void OnPlayerRunCmdPost(int client, int buttons, int impulse, float vel[3], float angles[3], int weapon, int subtype, int cmdnum, int tickcount) +{ + if(!IsPlayerAlive(client)) + return; + + CPlayer Player = g_aPlayers[client]; + + MoveType ClientMoveType = GetEntityMoveType(client); + bool bInWater = GetEntProp(client, Prop_Send, "m_nWaterLevel") >= 2; + + bool bPrevOnGround = g_bOnGround[client]; + bool bOnGround = !bInWater && GetEntityFlags(client) & FL_ONGROUND; + + bool bPrevHoldingJump = g_bHoldingJump[client]; + bool bHoldingJump = view_as(g_aButtons[client] & IN_JUMP); + + bool bInJump = g_bInJump[client]; + + float fVecVelocity[3]; + GetEntPropVector(client, Prop_Data, "m_vecAbsVelocity", fVecVelocity); + fVecVelocity[2] = 0.0; + float fVelocity = GetVectorLength(fVecVelocity); + + if(bInJump && (bInWater || ClientMoveType == MOVETYPE_LADDER || ClientMoveType == MOVETYPE_NOCLIP)) + bOnGround = true; + + if(bOnGround) + { + if(!bPrevOnGround) + { + g_bOnGround[client] = true; + g_bInJump[client] = false; + if(bInJump) + OnTouchGround(Player, tickcount, fVelocity); + } + } + else + { + if(bPrevOnGround) + g_bOnGround[client] = false; + } + + if(bHoldingJump) + { + if(!bPrevHoldingJump && !bOnGround && (bPrevOnGround || bInJump)) + { + g_bHoldingJump[client] = true; + g_bInJump[client] = true; + OnPressJump(Player, tickcount, fVelocity, bPrevOnGround); + } + } + else + { + if(bPrevHoldingJump) + { + g_bHoldingJump[client] = false; + OnReleaseJump(Player, tickcount, fVelocity); + } + } +} + +// TODO: Release after touch ground + +void OnTouchGround(CPlayer Player, int iTick, float fVelocity) +{ + //PrintToServer("%d - OnTouchGround", iTick); + + CStreak CurStreak = Player.hStreak; + ArrayList hJumps = CurStreak.hJumps; + CJump hJump = hJumps.Get(hJumps.Length - 1); + + hJump.iEndTick = iTick; + hJump.fEndVel = fVelocity; + + int iLength = hJumps.Length; + if(iLength == VALID_MIN_JUMPS) + { + CurStreak.bValid = true; + + // Current streak is valid, push onto hStreaks ArrayList + ArrayList hStreaks = Player.hStreaks; + if(hStreaks.Length == MAX_STREAKS) + { + // Keep the last 10 streaks + CStreak hStreak = hStreaks.Get(0); + hStreak.Dispose(); + hStreaks.Erase(0); + } + hStreaks.Push(CurStreak); + + for(int i = 0; i < iLength - 1; i++) + { + CJump hJump_ = hJumps.Get(i); + DoStats(Player, CurStreak, hJump_); + } + } + else if(iLength > VALID_MIN_JUMPS) + { + CJump hJump_ = hJumps.Get(hJumps.Length - 2); + DoStats(Player, CurStreak, hJump_); + } +} + +void OnPressJump(CPlayer Player, int iTick, float fVelocity, bool bLeaveGround) +{ + //PrintToServer("%d - OnPressJump %d", iTick, bLeaveGround); + + CStreak CurStreak = Player.hStreak; + ArrayList hJumps = CurStreak.hJumps; + CJump hJump; + + if(bLeaveGround) + { + int iPrevJump = -1; + // Check if we should start a new streak + if(hJumps.Length) + { + // Last jump was more than VALID_MAX_TICKS ticks ago or not valid and fVelocity < VALID_MIN_VELOCITY + hJump = hJumps.Get(hJumps.Length - 1); + if(hJump.iEndTick < iTick - VALID_MAX_TICKS || fVelocity < VALID_MIN_VELOCITY) + { + if(CurStreak.bValid) + { + CurStreak.iEndTick = iTick; + + DoStats(Player, CurStreak, hJump); + } + else + CurStreak.Dispose(); + + CurStreak = new CStreak(); + Player.hStreak = CurStreak; + hJumps = CurStreak.hJumps; + } + else + { + iPrevJump = iTick - hJump.iEndTick; + hJump.iNextJump = iPrevJump; + } + } + + hJump = new CJump(); + hJump.iStartTick = iTick; + hJump.fStartVel = fVelocity; + if(iPrevJump != -1) + hJump.iPrevJump = iPrevJump; + hJumps.Push(hJump); + } + else + hJump = hJumps.Get(hJumps.Length - 1); + + ArrayList hPresses = hJump.hPresses; + hPresses.Push(iTick); +} + +void OnReleaseJump(CPlayer Player, int iTick, float fVelocity) +{ + //PrintToServer("%d - OnReleaseJump", iTick); + + CStreak CurStreak = Player.hStreak; + ArrayList hJumps = CurStreak.hJumps; + CJump hJump = hJumps.Get(hJumps.Length - 1); + ArrayList hPresses = hJump.hPresses; + + hPresses.Set(hPresses.Length - 1, iTick, 1); +} + +void DoStats(CPlayer Player, CStreak CurStreak, CJump hJump) +{ + int client = Player.iClient; + int aJumps[3] = {0, 0, 0}; + int iPresses = 0; + int iTicks = 0; + int iLastJunk = 0; + + CurStreak.iJumps++; + Player.iJumps++; + + ArrayList hPresses = hJump.hPresses; + int iStartTick = hJump.iStartTick; + int iEndTick = hJump.iEndTick; + int iPrevJump = hJump.iPrevJump; + int iNextJump = hJump.iNextJump; + + if(iPrevJump != -1) + { + int iPerf = iPrevJump - 1; + if(iPerf > 2) + iPerf = 2; + + aJumps[iPerf]++; + } + + iPresses = hPresses.Length; + iTicks = iEndTick - iStartTick; + iLastJunk = iEndTick - hPresses.Get(iPresses - 1, 1); + + float PressesPerTick = (iPresses * 4.0) / float(iTicks); + if(PressesPerTick >= 0.85) + { + CurStreak.iHyperJumps++; + Player.iHyperJumps++; + } + + if(iNextJump != -1 && iNextJump <= 1 && (iLastJunk > 5 || iPresses <= 2) && hJump.fEndVel >= 285.0) + { + CurStreak.iHackJumps++; + Player.iHackJumps++; + } + + int aGlobalJumps[3]; + Player.GetJumps(aGlobalJumps); + aGlobalJumps[0] += aJumps[0]; + aGlobalJumps[1] += aJumps[1]; + aGlobalJumps[2] += aJumps[2]; + Player.SetJumps(aGlobalJumps); + + int aStreakJumps[3]; + CurStreak.GetJumps(aStreakJumps); + aStreakJumps[0] += aJumps[0]; + aStreakJumps[1] += aJumps[1]; + aStreakJumps[2] += aJumps[2]; + CurStreak.SetJumps(aStreakJumps); + + int iStreakJumps = CurStreak.iJumps; + if(iStreakJumps >= 6) + { + float HackRatio = CurStreak.iHackJumps / float(iStreakJumps); + if(HackRatio >= 0.85 && !Player.bFlagged) + { + Player.bFlagged = true; + NotifyAdmins(client, "bhop hack streak"); +// KickClient(client, "Turn off your hack!"); + return; + } + + float HyperRatio = CurStreak.iHyperJumps / float(iStreakJumps); + if(HyperRatio >= 0.85 && !Player.bFlagged) + { + Player.bFlagged = true; + NotifyAdmins(client, "hyperscroll streak"); + CPrintToChat(client, "{green}[SM]{default} Turn off your bhop macro/script or hyperscroll!"); + CPrintToChat(client, "{green}[SM]{default} Your bhop has been {red}turned off{default} until the end of the map."); + LimitBhop(client, true); + return; + } + } + + int iGlobalJumps = Player.iJumps; + if(iGlobalJumps >= 25) + { + float HackRatio = Player.iHackJumps / float(iGlobalJumps); + if(HackRatio >= 0.65 && !Player.bFlagged) + { + Player.bFlagged = true; + NotifyAdmins(client, "bhop hack global"); +// KickClient(client, "Turn off your hack!"); + return; + } + + float HyperRatio = Player.iHyperJumps / float(iGlobalJumps); + if(HyperRatio >= 0.50 && !Player.bFlagged) + { + Player.bFlagged = true; + NotifyAdmins(client, "hyperscroll global"); + CPrintToChat(client, "{green}[SM]{default} Turn off your bhop macro/script or hyperscroll!"); + CPrintToChat(client, "{green}[SM]{default} Your bhop has been {red}turned off{default} until the end of the map."); + LimitBhop(client, true); + return; + } + } +} + +NotifyAdmins(int client, const char[] sReason) +{ + for(int i = 1; i <= MaxClients; i++) + { + if(IsClientInGame(i) && !IsFakeClient(i) && CheckCommandAccess(i, "sm_stats", ADMFLAG_GENERIC)) + { + CPrintToChat(i, "{green}[SM]{default} %L has been detected for {red}%s{default}, please check your console!", client, sReason) + PrintStats(i, client); + PrintStreak(i, client, -1, true); + } + } + + Forward_OnDetected(client, sReason, g_sStats) +} + +public Action Command_Stats(int client, int argc) +{ + if(argc < 1 || argc > 2) + { + ReplyToCommand(client, "[SM] Usage: sm_stats <#userid|name>"); + return Plugin_Handled; + } + + char sArg[65]; + char sTargetName[MAX_TARGET_LENGTH]; + int iTargets[MAXPLAYERS]; + int iTargetCount; + bool bIsML; + + GetCmdArg(1, sArg, sizeof(sArg)); + + if((iTargetCount = ProcessTargetString(sArg, client, iTargets, MAXPLAYERS, COMMAND_FILTER_NO_MULTI | COMMAND_FILTER_NO_IMMUNITY, sTargetName, sizeof(sTargetName), bIsML)) <= 0) + { + ReplyToTargetError(client, iTargetCount); + return Plugin_Handled; + } + + for(int i = 0; i < iTargetCount; i++) + { + PrintStats(client, iTargets[i]); + } + + return Plugin_Handled; +} + +void PrintStats(int client, int iTarget) +{ + PrintToConsole(client, "[SM] Bunnyhop stats for %L", iTarget); + + CPlayer Player = g_aPlayers[iTarget]; + ArrayList hStreaks = Player.hStreaks; + CStreak hStreak = Player.hStreak; + int iStreaks = hStreaks.Length; + + // Try showing latest valid streak + if(!hStreak.bValid) + { + if(iStreaks) + hStreak = hStreaks.Get(iStreaks - 1); + } + + int iGlobalJumps = Player.iJumps; + float HyperRatio = Player.iHyperJumps / float(iGlobalJumps); + float HackRatio = Player.iHackJumps / float(iGlobalJumps); + + PrintToConsole(client, "Global jumps: %d | Hyper?: %.1f%% | Hack?: %.1f%%", + iGlobalJumps, HyperRatio * 100.0, HackRatio * 100.0); + + + int aGlobalJumps[3]; + Player.GetJumps(aGlobalJumps); + + PrintToConsole(client, "Global jumps perf group (1 2 +): %1.f%% %1.f%% %1.f%%", + (aGlobalJumps[0] / float(iGlobalJumps)) * 100.0, + (aGlobalJumps[1] / float(iGlobalJumps)) * 100.0, + (aGlobalJumps[2] / float(iGlobalJumps)) * 100.0); + + + PrintToConsole(client, "more to come..."); +} + +public Action Command_Streak(int client, int argc) +{ + if(argc < 1 || argc > 2) + { + ReplyToCommand(client, "[SM] Usage: sm_streak <#userid|name> [streak]"); + return Plugin_Handled; + } + + char sArg[65]; + char sArg2[8]; + char sTargetName[MAX_TARGET_LENGTH]; + int iTargets[MAXPLAYERS]; + int iTargetCount; + bool bIsML; + int iStreak = -1; + + GetCmdArg(1, sArg, sizeof(sArg)); + + if(argc == 2) + { + GetCmdArg(2, sArg2, sizeof(sArg2)); + iStreak = StringToInt(sArg2); + } + + if((iTargetCount = ProcessTargetString(sArg, client, iTargets, MAXPLAYERS, COMMAND_FILTER_NO_MULTI | COMMAND_FILTER_NO_IMMUNITY, sTargetName, sizeof(sTargetName), bIsML)) <= 0) + { + ReplyToTargetError(client, iTargetCount); + return Plugin_Handled; + } + + for(int i = 0; i < iTargetCount; i++) + { + PrintStreak(client, iTargets[i], iStreak); + } + + return Plugin_Handled; +} + +void PrintStreak(int client, int iTarget, int iStreak, bool bDetected=false) +{ + g_sStats = ""; + + PrintToConsole(client, "[SM] Bunnyhop streak %d for %L", iStreak, iTarget); + + if (bDetected) + Format(g_sStats, sizeof(g_sStats), "%sBunnyhop streak %d for %L\n", + g_sStats, iStreak, iTarget); + + CPlayer Player = g_aPlayers[iTarget]; + ArrayList hStreaks = Player.hStreaks; + CStreak hStreak = Player.hStreak; + int iStreaks = hStreaks.Length; + + // Try showing latest valid streak + if(iStreak <= 0 && !hStreak.bValid) + { + if(iStreaks) + hStreak = hStreaks.Get(iStreaks - 1); + } + else if(iStreak > 0) + { + if(iStreak > MAX_STREAKS) + { + ReplyToCommand(client, "[SM] Streak is out of bounds (max. %d)!", MAX_STREAKS); + return; + } + + int iIndex = iStreaks - iStreak; + if(iIndex < 0) + { + ReplyToCommand(client, "[SM] Only %d streaks are available for this player right now!", iStreaks); + return; + } + + hStreak = hStreaks.Get(iIndex); + } + + int iStreakJumps = hStreak.iJumps; + float HyperRatio = hStreak.iHyperJumps / float(iStreakJumps); + float HackRatio = hStreak.iHackJumps / float(iStreakJumps); + + PrintToConsole(client, "Streak jumps: %d | Hyper?: %.1f%% | Hack?: %.1f%%", + iStreakJumps, HyperRatio * 100.0, HackRatio * 100.0); + + if (bDetected) + Format(g_sStats, sizeof(g_sStats), "%sStreak jumps: %d | Hyper?: %.1f%% | Hack?: %.1f%%\n", + g_sStats, iStreakJumps, HyperRatio * 100.0, HackRatio * 100.0); + + int aStreakJumps[3]; + hStreak.GetJumps(aStreakJumps); + + PrintToConsole(client, "Streak jumps perf group (1 2 +): %1.f%% %1.f%% %1.f%%", + (aStreakJumps[0] / float(iStreakJumps)) * 100.0, + (aStreakJumps[1] / float(iStreakJumps)) * 100.0, + (aStreakJumps[2] / float(iStreakJumps)) * 100.0); + + if (bDetected) + Format(g_sStats, sizeof(g_sStats), "%sStreak jumps perf group (1 2 +): %1.f%% %1.f%% %1.f%%\n", + g_sStats, + (aStreakJumps[0] / float(iStreakJumps)) * 100.0, + (aStreakJumps[1] / float(iStreakJumps)) * 100.0, + (aStreakJumps[2] / float(iStreakJumps)) * 100.0); + + PrintToConsole(client, "#%2s %5s %7s %7s %5s %5s %8s %4s %6s %s", + "id", " diff", " invel", " outvel", " gain", " comb", " avgdist", " num", " avg+-", "pattern"); + + if (bDetected) + Format(g_sStats, sizeof(g_sStats), "%s#%2s %5s %7s %7s %5s %5s %8s %4s %6s %s\n", + g_sStats, "id", " diff", " invel", " outvel", " gain", " comb", " avgdist", " num", " avg+-", "pattern"); + + ArrayList hJumps = hStreak.hJumps; + float fPrevVel = 0.0; + int iPrevEndTick = -1; + + for(int i = 0; i < hJumps.Length; i++) + { + CJump hJump = hJumps.Get(i); + ArrayList hPresses = hJump.hPresses; + + float fInVel = hJump.fStartVel; + float fOutVel = hJump.fEndVel; + int iEndTick = hJump.iEndTick; + + static char sPattern[256]; + int iPatternLen = 0; + int iPrevTick = -1; + int iTicks; + + if(iPrevEndTick != -1) + { + iTicks = hJump.iStartTick - iPrevEndTick; + for(int k = 0; k < iTicks && k < 16; k++) + sPattern[iPatternLen++] = '|'; + } + + float fAvgDist = 0.0; + float fAvgDownUp = 0.0; + + int iPresses = hPresses.Length; + for(int j = 0; j < iPresses; j++) + { + int aJunkJump[2]; + hPresses.GetArray(j, aJunkJump); + + if(iPrevTick != -1) + { + iTicks = aJunkJump[0] - iPrevTick; + for(int k = 0; k < iTicks && k < 16; k++) + sPattern[iPatternLen++] = '.'; + + fAvgDist += iTicks; + } + + sPattern[iPatternLen++] = '^'; + + iTicks = aJunkJump[1] - aJunkJump[0]; + for(int k = 0; k < iTicks && k < 16; k++) + sPattern[iPatternLen++] = ','; + + fAvgDownUp += iTicks; + + sPattern[iPatternLen++] = 'v'; + + iPrevTick = aJunkJump[1]; + } + + fAvgDist /= iPresses; + fAvgDownUp /= iPresses; + + iTicks = iEndTick - iPrevTick; + for(int k = 0; k < iTicks && k < 16; k++) + sPattern[iPatternLen++] = '.'; + + sPattern[iPatternLen++] = '|'; + sPattern[iPatternLen++] = '\0'; + + if(fPrevVel == 0.0) + fPrevVel = fInVel; + + PrintToConsole(client, "#%2d %4d%% %7.1f %7.1f %4d%% %4d%% %8.2f %4d %6.2f %s", + i, + fPrevVel == 0.0 ? 100 : RoundFloat((fInVel / fPrevVel) * 100.0 - 100.0), + fInVel, + fOutVel, + fInVel == 0.0 ? 100 : RoundFloat((fOutVel / fInVel) * 100.0 - 100.0), + fPrevVel == 0.0 ? 100 : RoundFloat((fOutVel / fPrevVel) * 100.0 - 100.0), + fAvgDist, + iPresses, + fAvgDownUp, + sPattern); + + if (bDetected) + Format(g_sStats, sizeof(g_sStats), "%s#%2d %4d%% %7.1f %7.1f %4d%% %4d%% %8.2f %4d %6.2f %s\n", + g_sStats, + i, + fPrevVel == 0.0 ? 100 : RoundFloat((fInVel / fPrevVel) * 100.0 - 100.0), + fInVel, + fOutVel, + fInVel == 0.0 ? 100 : RoundFloat((fOutVel / fInVel) * 100.0 - 100.0), + fPrevVel == 0.0 ? 100 : RoundFloat((fOutVel / fPrevVel) * 100.0 - 100.0), + fAvgDist, + iPresses, + fAvgDownUp, + sPattern); + + iPrevEndTick = iEndTick; + fPrevVel = fOutVel; + } +} + +bool Forward_OnDetected(int client, const char[] reason, const char[] stats) +{ + Call_StartForward(g_hOnClientDetected); + Call_PushCell(client); + Call_PushString(reason); + Call_PushString(stats); + Call_Finish(); + + g_sStats = ""; +} \ No newline at end of file diff --git a/AntiBhopCheat/scripting/CJump.inc b/AntiBhopCheat/scripting/CJump.inc new file mode 100644 index 00000000..6bcc2408 --- /dev/null +++ b/AntiBhopCheat/scripting/CJump.inc @@ -0,0 +1,118 @@ +#if defined _class_cjump_ + #endinput +#endif +#define _class_cjump_ + +methodmap CJump < Basic +{ + public CJump() + { + Basic myclass = new Basic(); + + myclass.SetInt("iStartTick", -1); + myclass.SetInt("iEndTick", -1); + myclass.SetFloat("fStartVel", 0.0); + myclass.SetFloat("fEndVel", 0.0); + + myclass.SetInt("iPrevJump", -1); + myclass.SetInt("iNextJump", -1); + + myclass.SetHandle("hPresses", new ArrayList(2)); + + return view_as(myclass); + } + + property int iStartTick + { + public get() + { + return this.GetInt("iStartTick"); + } + public set(int value) + { + this.SetInt("iStartTick", value); + } + } + + property int iEndTick + { + public get() + { + return this.GetInt("iEndTick"); + } + public set(int value) + { + this.SetInt("iEndTick", value); + } + } + + property float fStartVel + { + public get() + { + return this.GetFloat("fStartVel"); + } + public set(float value) + { + this.SetFloat("fStartVel", value); + } + } + + property float fEndVel + { + public get() + { + return this.GetFloat("fEndVel"); + } + public set(float value) + { + this.SetFloat("fEndVel", value); + } + } + + property int iPrevJump + { + public get() + { + return this.GetInt("iPrevJump"); + } + public set(int value) + { + this.SetInt("iPrevJump", value); + } + } + + property int iNextJump + { + public get() + { + return this.GetInt("iNextJump"); + } + public set(int value) + { + this.SetInt("iNextJump", value); + } + } + + property ArrayList hPresses + { + public get() + { + return view_as(this.GetHandle("hPresses")); + } + public set(ArrayList value) + { + this.SetHandle("hPresses", value); + } + } + + public void Dispose(bool disposemembers=true) + { + if(disposemembers) + { + delete this.hPresses; + } + + delete this; + } +} diff --git a/AntiBhopCheat/scripting/CPlayer.inc b/AntiBhopCheat/scripting/CPlayer.inc new file mode 100644 index 00000000..1aa08379 --- /dev/null +++ b/AntiBhopCheat/scripting/CPlayer.inc @@ -0,0 +1,141 @@ +#if defined _class_cplayer_ + #endinput +#endif +#define _class_cplayer_ + +methodmap CPlayer < Basic +{ + public CPlayer(int client) + { + Basic myclass = new Basic(); + + myclass.SetInt("iClient", client); + myclass.SetBool("bFlagged", false); + + myclass.SetInt("iJumps", 0); + myclass.SetInt("iHyperJumps", 0); + myclass.SetInt("iHackJumps", 0); + myclass.SetArray("aJumps", {0, 0, 0}, 3); + + myclass.SetHandle("hStreak", new CStreak()); + myclass.SetHandle("hStreaks", new ArrayList(1)); + + return view_as(myclass); + } + + property int iClient + { + public get() + { + return this.GetInt("iClient"); + } + public set(int value) + { + this.SetInt("iClient", value); + } + } + + property bool bFlagged + { + public get() + { + return this.GetBool("bFlagged"); + } + public set(bool value) + { + this.SetBool("bFlagged", value); + } + } + + property int iJumps + { + public get() + { + return this.GetInt("iJumps"); + } + public set(int value) + { + this.SetInt("iJumps", value); + } + } + + property int iHyperJumps + { + public get() + { + return this.GetInt("iHyperJumps"); + } + public set(int value) + { + this.SetInt("iHyperJumps", value); + } + } + + property int iHackJumps + { + public get() + { + return this.GetInt("iHackJumps"); + } + public set(int value) + { + this.SetInt("iHackJumps", value); + } + } + + public void GetJumps(int value[3]) + { + this.GetArray("aJumps", value, sizeof(value)); + } + + public void SetJumps(const int value[3]) + { + this.SetArray("aJumps", value, sizeof(value)); + } + + property CStreak hStreak + { + public get() + { + return view_as(this.GetHandle("hStreak")); + } + public set(CStreak value) + { + this.SetHandle("hStreak", value); + } + } + + property ArrayList hStreaks + { + public get() + { + return view_as(this.GetHandle("hStreaks")); + } + public set(ArrayList value) + { + this.SetHandle("hStreaks", value); + } + } + + public void Dispose(bool disposemembers=true) + { + if(disposemembers) + { + ArrayList hStreaks = this.hStreaks; + + CStreak hStreak; + for(int i = 0; i < hStreaks.Length; i++) + { + hStreak = view_as(hStreaks.Get(i)); + hStreak.Dispose(); + } + + delete hStreaks; + + if(this.hStreak != hStreak) + this.hStreak.Dispose(); + } + + delete this; + } +} diff --git a/AntiBhopCheat/scripting/CStreak.inc b/AntiBhopCheat/scripting/CStreak.inc new file mode 100644 index 00000000..f4b4d28a --- /dev/null +++ b/AntiBhopCheat/scripting/CStreak.inc @@ -0,0 +1,163 @@ +#if defined _class_cstreak_ + #endinput +#endif +#define _class_cstreak_ + +methodmap CStreak < Basic +{ + public CStreak() + { + Basic myclass = new Basic(); + + myclass.SetBool("bValid", false); + myclass.SetInt("iStartTick", -1); + myclass.SetInt("iEndTick", -1); + myclass.SetFloat("fStartVel", 0.0); + myclass.SetFloat("fEndVel", 0.0); + + myclass.SetInt("iJumps", 0); + myclass.SetInt("iHyperJumps", 0); + myclass.SetInt("iHackJumps", 0); + myclass.SetArray("aJumps", {0, 0, 0}, 3); + + myclass.SetHandle("hJumps", new ArrayList(1)); + + return view_as(myclass); + } + + property bool bValid + { + public get() + { + return this.GetBool("bValid"); + } + public set(bool value) + { + this.SetBool("bValid", value); + } + } + + property int iStartTick + { + public get() + { + return this.GetInt("iStartTick"); + } + public set(int value) + { + this.SetInt("iStartTick", value); + } + } + + property int iEndTick + { + public get() + { + return this.GetInt("iEndTick"); + } + public set(int value) + { + this.SetInt("iEndTick", value); + } + } + + property float fStartVel + { + public get() + { + return this.GetFloat("fStartVel"); + } + public set(float value) + { + this.SetFloat("fStartVel", value); + } + } + + property float fEndVel + { + public get() + { + return this.GetFloat("fEndVel"); + } + public set(float value) + { + this.SetFloat("fEndVel", value); + } + } + + property int iJumps + { + public get() + { + return this.GetInt("iJumps"); + } + public set(int value) + { + this.SetInt("iJumps", value); + } + } + + property int iHyperJumps + { + public get() + { + return this.GetInt("iHyperJumps"); + } + public set(int value) + { + this.SetInt("iHyperJumps", value); + } + } + + property int iHackJumps + { + public get() + { + return this.GetInt("iHackJumps"); + } + public set(int value) + { + this.SetInt("iHackJumps", value); + } + } + + public void GetJumps(int value[3]) + { + this.GetArray("aJumps", value, sizeof(value)); + } + + public void SetJumps(const int value[3]) + { + this.SetArray("aJumps", value, sizeof(value)); + } + + property ArrayList hJumps + { + public get() + { + return view_as(this.GetHandle("hJumps")); + } + public set(ArrayList value) + { + this.SetHandle("hJumps", value); + } + } + + public void Dispose(bool disposemembers=true) + { + if(disposemembers) + { + ArrayList hJumps = this.hJumps; + + for(int i = 0; i < hJumps.Length; i++) + { + CJump hJump = view_as(hJumps.Get(i)); + hJump.Dispose(); + } + + delete hJumps; + } + + delete this; + } +} diff --git a/AntiBhopCheat/scripting/include/AntiBhopCheat.inc b/AntiBhopCheat/scripting/include/AntiBhopCheat.inc new file mode 100644 index 00000000..0b968fb1 --- /dev/null +++ b/AntiBhopCheat/scripting/include/AntiBhopCheat.inc @@ -0,0 +1,6 @@ +#if defined _AntiBhopCheat_Included + #endinput +#endif +#define _AntiBhopCheat_Included + +forward void AntiBhopCheat_OnClientDetected(int client, char[] sReason, char[] sStats); \ No newline at end of file