#pragma semicolon 1
#include <sourcemod>
#include <sdktools>
#include <sdkhooks>
#include <morecolors>
#include <ljstats>
new Handle:g_hSQL;
new g_iReconnectCounter = 0;
new g_iStrafeNumber[MAXPLAYERS+1];
new g_iDirection[MAXPLAYERS+1];
new bool:g_bJumped[MAXPLAYERS+1];
new bool:g_bReset[MAXPLAYERS+1];
new bool:g_bCheckSurf[MAXPLAYERS+1];
new bool:g_bLJStats[MAXPLAYERS+1];
new bool:g_bTurning[MAXPLAYERS+1];
new bool:g_bStraifingAW[MAXPLAYERS+1];
new bool:g_bStraifingSD[MAXPLAYERS+1];
new bool:g_bOnGround[MAXPLAYERS+1];
new bool:g_bPostThink[MAXPLAYERS+1];
new Handle:g_h_sv_gravity = INVALID_HANDLE;
new Float:g_fDistanceCache[MAXPLAYERS+1];
enum RecordCache
{
String:Auth[32],
Float:Distance,
Float:Maxspeed,
Float:Gain,
Float:Prestrafe,
Strafenumber,
Direction,
String:Name[32],
Float:Sync
}
new String:g_sDirectionNames[][] =
{
{"Forwards"},
{"Sideways"},
{"Backwards"}
};
new g_cache[100][RecordCache];
new g_cacheCount = 0;
new bool:g_bCacheLoaded = false;
public Plugin:myinfo =
{
name = "LJ Stats",
// Sorry, Alon told me :[
//author = "0wn3r & Exolent, SchlumPF*, xPaw",
author = "shavit/TimeBomb",
description = "Longjump stats.",
version = "1.5",
// Sorry, Alon told me :[
//url = "http://playground.org.ua/"
url = "not vgames"
};
public OnPluginStart()
{
g_h_sv_gravity = FindConVar("sv_gravity");
RegConsoleCmd("sm_ljstats", Command_LJStats);
RegConsoleCmd("sm_lj", Command_LJStats);
RegConsoleCmd("sm_pre", Command_LJStats);
RegConsoleCmd("sm_ljtop", Command_LJTop);
RegAdminCmd("sm_removejump", Command_DeleteRecord_All, ADMFLAG_RCON, "sm_removejump STEAM_ID");
HookEvent("player_spawn", Event_PlayerSpawn);
HookEntityOutput("trigger_teleport", "OnEndTouch", ResetJump);
HookEntityOutput("trigger_push", "OnEndTouch", ResetJump);
HookEntityOutput("trigger_wind", "OnEndTouch", ResetJump);
ConnectSQL();
}
public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max)
{
return APLRes_Success;
}
public OnMapStart()
{
ConnectSQL();
}
public Action:Command_LJStats(client, args)
{
g_bLJStats[client] = !g_bLJStats[client];
if (g_bLJStats[client])
{
CPrintToChat(client, "{green}[{fullblue}LJStats{green}]{gold} LJ Stats is enabled.");
}
else
{
CPrintToChat(client, "{green}[{fullblue}LJStats{green}]{gold} LJ Stats is disabled.");
}
return Plugin_Handled;
}
public ResetJump(const String:output[], caller, activator, Float:delay)
{
if ((1 <= activator <= MaxClients) && IsClientConnected(activator))
{
g_bReset[activator] = true;
}
}
public Action:ResetJumpTimer(Handle:Timer, any:client)
{
g_bReset[client] = true;
}
public Action:Event_PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast)
{
g_bReset[GetClientOfUserId(GetEventInt(event, "userid"))] = true;
return Plugin_Continue;
}
public OnClientPutInServer(client)
{
SDKHook(client, SDKHook_PreThink, OnPreThink);
SDKHook(client, SDKHook_PostThink, OnPostThink);
SDKHook(client, SDKHook_Touch, OnTouch);
g_bLJStats[client] = false;
UpdateClientCache(client);
}
public OnTouch(client, other)
{
if ((1 <= client <= MaxClients) && !(GetEntityFlags(client) & FL_ONGROUND))
{
g_bCheckSurf[client] = true;
}
if ((1 <= other <= MaxClients) && !(GetEntityFlags(other) & FL_ONGROUND))
{
g_bCheckSurf[other] = true;
}
}
public Action:OnPreThink(client)
{
if (!IsPlayerAlive(client))
{
return Plugin_Continue;
}
static String:weapon[32];
GetClientWeapon(client, weapon, 32);
if(StrEqual(weapon, "weapon_scout"))
{
return Plugin_Continue;
}
static nOldButtons;
new bool:bOnGround = IsUserOnGround(client);
if (g_bCheckSurf[client])
{
g_bCheckSurf[client] = false;
if (!bOnGround && !g_bOnGround[client])
{
g_bReset[client] = true;
nOldButtons = GetClientButtons(client);
g_bOnGround[client] = bOnGround;
return Plugin_Continue;
}
}
static iFrames[MAXPLAYERS+1], iFramesGainedSpeed[MAXPLAYERS+1];
static bool:bFirstFrame[MAXPLAYERS+1];
static Float:fMaxspeed[MAXPLAYERS+1], Float:fPrestrafe[MAXPLAYERS+1];
static Float:vecFrameOrigin[MAXPLAYERS+1][2][3], Float:vecFrameVelocity[MAXPLAYERS+1][2][3];
static Float:vecJumpoffOrigin[MAXPLAYERS+1][3];
static iGroundFrames[MAXPLAYERS+1];
static Float:fLastMaxspeedChange[MAXPLAYERS+1];
static Float:flOldMaxspeed[MAXPLAYERS+1];
static Float:vecOldOrigin[MAXPLAYERS+1][3];
static Float:flMaxspeed;
flMaxspeed = GetEntPropFloat(client, Prop_Data, "m_flMaxspeed");
static Float:vecOrigin[3];
GetEntPropVector(client, Prop_Data, "m_vecOrigin", vecOrigin);
if (g_bReset[client] || flMaxspeed != flOldMaxspeed[client] || GetVectorDistance(vecOldOrigin[client], vecOrigin) > 20)
{
g_bReset[client] = false;
g_bJumped[client] = false;
bFirstFrame[client] = false;
iFramesGainedSpeed[client] = 0;
iFrames[client] = 0;
iGroundFrames[client] = 0;
g_iStrafeNumber[client] = 0;
fLastMaxspeedChange[client] = GetGameTime();
nOldButtons = GetClientButtons(client);
flOldMaxspeed[client] = flMaxspeed;
vecOldOrigin[client] = vecOrigin;
g_bOnGround[client] = bOnGround;
return Plugin_Continue;
}
static Float:vecVelocity[3];
GetEntPropVector(client, Prop_Data, "m_vecVelocity", vecVelocity);
static nButtons;
nButtons = GetClientButtons(client);
if (!bOnGround && g_bJumped[client])
{
new Float:fSpeed = SquareRoot(Pow(vecVelocity[0], 2.0) + Pow(vecVelocity[1], 2.0));
static Float:fOldSpeed[MAXPLAYERS+1];
if (fSpeed > fOldSpeed[client])
{
iFramesGainedSpeed[client]++;
}
iFrames[client]++;
fOldSpeed[client] = fSpeed;
if (fSpeed > fMaxspeed[client])
{
fMaxspeed[client] = fSpeed;
}
if (bFirstFrame[client])
{
bFirstFrame[client] = false;
vecFrameOrigin[client][0] = vecOrigin;
vecFrameVelocity[client][0] = vecVelocity;
}
else
{
vecFrameOrigin[client][1] = vecOrigin;
vecFrameVelocity[client][1] = vecVelocity;
}
}
if ((nButtons & IN_JUMP) && !(nOldButtons & IN_JUMP) && bOnGround && !g_bJumped[client])
{
if (iGroundFrames[client] >= 50)
{
new Float:fGameTime = GetGameTime();
if (fLastMaxspeedChange[client] > (fGameTime + 0.7))
{
g_bReset[client] = true;
nOldButtons = GetClientButtons(client);
flOldMaxspeed[client] = flMaxspeed;
vecOldOrigin[client] = vecOrigin;
g_bOnGround[client] = bOnGround;
return Plugin_Continue;
}
vecJumpoffOrigin[client] = vecOrigin;
g_iStrafeNumber[client] = 0;
g_bTurning[client] = false;
g_bStraifingAW[client] = false;
g_bStraifingSD[client] = false;
g_bJumped[client] = true;
bFirstFrame[client] = true;
new Float:fSpeed = SquareRoot(Pow(vecVelocity[0], 2.0) + Pow(vecVelocity[1], 2.0));
fPrestrafe[client] = fMaxspeed[client] = fSpeed;
g_iDirection[client] = GetDirection(client);
CreateTimer(0.8, ResetJumpTimer, client);
}
}
else if (bOnGround && !g_bOnGround[client] && g_bJumped[client])
{
static bool:bDucking;
bDucking = IsDucking(client);
static Float:fHeightDifference;
fHeightDifference = vecJumpoffOrigin[client][2] - (bDucking ? vecOrigin[2] + 17.0 : vecOrigin[2]);
if (fHeightDifference > 2.0 || fHeightDifference < -2.0)
{
g_bReset[client] = true;
nOldButtons = GetClientButtons(client);
flOldMaxspeed[client] = flMaxspeed;
vecOldOrigin[client] = vecOrigin;
g_bOnGround[client] = bOnGround;
return Plugin_Continue;
}
static Float:fGravity;
fGravity = GetConVarFloat(g_h_sv_gravity);
static Float:vecLandOrigin[3];
CalculateLandOrigin(bDucking, fGravity, vecOrigin, vecFrameOrigin[client], vecFrameVelocity[client], vecLandOrigin);
static Float:fDistance, Float:fDistance1, Float:fDistance2;
fDistance1 = GetVectorDistance(vecJumpoffOrigin[client], vecOrigin);
fDistance2 = GetVectorDistance(vecJumpoffOrigin[client], vecLandOrigin);
if (fDistance1 > fDistance2)
{
fDistance = fDistance1;
}
else
{
fDistance = fDistance2;
}
fDistance += 32.0;
if (fDistance < 210 || 280 < fDistance)
{
g_bReset[client] = true;
nOldButtons = GetClientButtons(client);
flOldMaxspeed[client] = flMaxspeed;
vecOldOrigin[client] = vecOrigin;
g_bOnGround[client] = bOnGround;
return Plugin_Continue;
}
static Float:fSync, Float:fGain;
fSync = FloatDiv(float(iFramesGainedSpeed[client] * 100), float(iFrames[client]));
fGain = FloatSub(fMaxspeed[client], fPrestrafe[client]);
if (g_bLJStats[client])
{
decl String:display[512];
new Handle:menu = CreateMenu(MenuHandler_DoNothing, MENU_ACTIONS_ALL);
SetMenuTitle(menu, "Jump Stats:");
FormatEx(display, 512, "Distance: %.02f", fDistance);
AddMenuItem(menu, "distance", display);
FormatEx(display, 512, "Maxspeed: %.02f (Gain %.02f)", fMaxspeed[client], fGain);
AddMenuItem(menu, "maxspeed", display);
FormatEx(display, 512, "Prestrafe: %.02f", fPrestrafe[client]);
AddMenuItem(menu, "prestrafe", display);
FormatEx(display, 512, "Strafes: %.d", g_iStrafeNumber[client]);
AddMenuItem(menu, "strafes", display);
FormatEx(display, 512, "Sync: %i%%", RoundToFloor(fSync));
AddMenuItem(menu, "sync", display);
FormatEx(display, 512, "Direction: %s", g_sDirectionNames[g_iDirection[client]]);
AddMenuItem(menu, "direction", display);
SetMenuExitButton(menu, true);
DisplayMenu(menu, client, MENU_TIME_FOREVER);
}
if(fDistance >= 260.00)
{
CPrintToChatAllEx(client, "{green}[{fullblue}LJStats{green}]{teamcolor} %N {gold}jumped for: {fullred}%.02f{gold} units! %s", client, fDistance, g_sDirectionNames[g_iDirection[client]]);
}
if(fDistance >= 240.00)
{
if(g_fDistanceCache[client] == 0.0)
{
RecordJump(client, fDistance, fMaxspeed[client], fGain, fPrestrafe[client], g_iStrafeNumber[client], g_iDirection[client], fSync);
}
else if (fDistance > g_fDistanceCache[client])
{
UpdateJump(client, fDistance, fMaxspeed[client], fGain, fPrestrafe[client], g_iStrafeNumber[client], g_iDirection[client], fSync);
}
}
g_bReset[client] = true;
}
nOldButtons = GetClientButtons(client);
flOldMaxspeed[client] = flMaxspeed;
vecOldOrigin[client] = vecOrigin;
if (!g_bPostThink[client])
{
if (bOnGround)
{
iGroundFrames[client]++;
}
else
{
iGroundFrames[client] = 0;
}
}
else
{
g_bPostThink[client] = false;
}
g_bOnGround[client] = bOnGround;
return Plugin_Continue;
}
public Action:OnPostThink(client)
{
if (!IsPlayerAlive(client))
{
return Plugin_Continue;
}
new bool:bOnGround = IsUserOnGround(client);
if (bOnGround && g_bJumped[client] && !g_bOnGround[client])
{
g_bPostThink[client] = true;
OnPreThink(client);
}
static nButtons;
static Float:vecAngle[3], Float:vecOldAngle[3];
GetClientEyeAngles(client, vecAngle);
g_bTurning[client] = false;
if (vecOldAngle[1] != vecAngle[1])
{
g_bTurning[client] = true;
}
vecOldAngle = vecAngle;
nButtons = GetClientButtons(client);
if (g_bJumped[client] && !bOnGround)
{
if (g_bTurning[client])
{
if (!g_bStraifingAW[client] && ((nButtons & IN_MOVELEFT) || (nButtons & IN_FORWARD)) && !(nButtons & IN_MOVERIGHT) && !(nButtons & IN_BACK))
{
g_bStraifingAW[client] = true;
g_bStraifingSD[client] = false;
g_iStrafeNumber[client]++;
}
else if (!g_bStraifingSD[client] && ((nButtons & IN_BACK) || (nButtons & IN_MOVERIGHT)) && !(nButtons & IN_MOVELEFT) && !(nButtons & IN_FORWARD))
{
g_bStraifingAW[client] = false;
g_bStraifingSD[client] = true;
g_iStrafeNumber[client]++;
}
}
}
if ((1 <= GetEntPropEnt(client, Prop_Send, "m_hGroundEntity") <= MaxClients))
{
g_bReset[client] = true;
}
return Plugin_Continue;
}
// SQL Stuff
ConnectSQL()
{
if (g_hSQL != INVALID_HANDLE)
{
CloseHandle(g_hSQL);
}
g_hSQL = INVALID_HANDLE;
if (SQL_CheckConfig("ljstats"))
{
SQL_TConnect(ConnectSQLCallback, "ljstats");
}
else
{
LogError("PLUGIN STOPPED - Reason: no config entry found for 'ljstats' in databases.cfg - PLUGIN STOPPED");
}
}
public ConnectSQLCallback(Handle:owner, Handle:hndl, const String:error[], any:data)
{
if (g_iReconnectCounter >= 5)
{
LogError("PLUGIN STOPPED - Reason: reconnect counter reached max - PLUGIN STOPPED");
return;
}
if (hndl == INVALID_HANDLE)
{
LogError("Connection to SQL database has failed, Reason: %s", error);
g_iReconnectCounter++;
ConnectSQL();
return;
}
decl String:driver[16];
SQL_GetDriverIdent(owner, driver, sizeof(driver));
g_hSQL = CloneHandle(hndl);
if (StrEqual(driver, "mysql", false))
{
SQL_FastQuery(g_hSQL, "SET NAMES 'utf8'");
SQL_TQuery(g_hSQL, CreateSQLTableCallback, "CREATE TABLE IF NOT EXISTS `jumpstats` (`auth` varchar(32) NOT NULL, `distance` float NOT NULL, `maxspeed` float NOT NULL, `gain` float NOT NULL, `prestrafe` float NOT NULL, `strafenumber` int(11) NOT NULL, `direction` int(11) NOT NULL, `name` varchar(64) NOT NULL, `sync` float NOT NULL);");
}
else if (StrEqual(driver, "sqlite", false))
{
SQL_TQuery(g_hSQL, CreateSQLTableCallback, "CREATE TABLE IF NOT EXISTS `jumpstats` (`auth` varchar(32) NOT NULL, `distance` float NOT NULL, `maxspeed` float NOT NULL, `gain` float NOT NULL, `prestrafe` float NOT NULL, `strafenumber` INTEGER NOT NULL, `direction` INTEGER NOT NULL, `name` varchar(64) NOT NULL, `sync` float NOT NULL);");
}
g_iReconnectCounter = 1;
}
public CreateSQLTableCallback(Handle:owner, Handle:hndl, const String:error[], any:data)
{
if (owner == INVALID_HANDLE)
{
LogError(error);
g_iReconnectCounter++;
ConnectSQL();
return;
}
if (hndl == INVALID_HANDLE)
{
LogError("SQL Error on CreateSQLTable: %s", error);
return;
}
RefreshCache();
}
RecordJump(client, Float:distance, Float:maxspeed, Float:gain, Float:prestrafe, strafenumber, jumpdirection, Float:sync)
{
if (!IsClientInGame(client))
return;
if (!IsPlayerAlive(client))
return;
decl String:auth[32];
GetClientAuthString(client, auth, sizeof(auth));
decl String:name[MAX_NAME_LENGTH];
GetClientName(client, name, sizeof(name));
decl String:safeName[2 * strlen(name) + 1];
SQL_EscapeString(g_hSQL, name, safeName, 2 * strlen(name) + 1);
decl String:query[256];
Format(query, sizeof(query), "INSERT INTO jumpstats (auth, distance, maxspeed, gain, prestrafe, strafenumber, direction, name, sync) VALUES ('%s', %f, %f, %f, %f, %d, %d, '%s', %f);", auth, distance, maxspeed, gain, prestrafe, strafenumber, jumpdirection, safeName, sync);
SQL_TQuery(g_hSQL, RecordJumpCallback, query, client, DBPrio_High);
}
public RecordJumpCallback(Handle:owner, Handle:hndl, const String:error[], any:client)
{
if (hndl == INVALID_HANDLE)
{
LogError("SQL Error on RecordJump: %s", error);
return;
}
UpdateClientCache(client);
RefreshCache();
}
UpdateClientCache(client)
{
if (!IsClientInGame(client))
return;
decl String:auth[32];
GetClientAuthString(client, auth, sizeof(auth));
decl String:query[255];
Format(query, sizeof(query), "SELECT distance FROM jumpstats WHERE auth = '%s'", auth);
SQL_TQuery(g_hSQL, UpdateCacheCallback, query, client, DBPrio_High);
}
public UpdateCacheCallback(Handle:owner, Handle:hndl, const String:error[], any:client)
{
if (hndl == INVALID_HANDLE)
{
LogError("SQL Error on UpdateCache: %s", error);
return;
}
if (SQL_FetchRow(hndl))
{
g_fDistanceCache[client] = SQL_FetchFloat(hndl, 0);
CloseHandle(hndl);
}
else
{
g_fDistanceCache[client] = 0.0;
CloseHandle(hndl);
}
}
UpdateJump(client, Float:distance, Float:maxspeed, Float:gain, Float:prestrafe, strafenumber, jumpdirection, Float:sync)
{
if (!IsClientInGame(client))
return;
if (!IsPlayerAlive(client))
return;
decl String:auth[32];
GetClientAuthString(client, auth, sizeof(auth));
decl String:name[MAX_NAME_LENGTH];
GetClientName(client, name, sizeof(name));
decl String:safeName[2 * strlen(name) + 1];
SQL_EscapeString(g_hSQL, name, safeName, 2 * strlen(name) + 1);
decl String:query[256];
Format(query, sizeof(query), "UPDATE jumpstats SET distance = %f, maxspeed = %f, gain = %f, prestrafe = %f, strafenumber = %d, direction = %d, name = '%s', sync = %f WHERE auth = '%s';", distance, maxspeed, gain, prestrafe, strafenumber, jumpdirection, safeName, sync, auth);
SQL_TQuery(g_hSQL, UpdateJumpCallback, query, client, DBPrio_High);
}
public UpdateJumpCallback(Handle:owner, Handle:hndl, const String:error[], any:client)
{
if (hndl == INVALID_HANDLE)
{
LogError("SQL Error on UpdateJump: %s", error);
return;
}
UpdateClientCache(client);
RefreshCache();
}
RefreshCache()
{
g_bCacheLoaded = false;
if (g_hSQL == INVALID_HANDLE)
{
ConnectSQL();
}
else
{
decl String:query[384];
Format(query, sizeof(query), "SELECT * FROM jumpstats ORDER BY distance DESC LIMIT 100");
SQL_TQuery(g_hSQL, RefreshCacheCallback, query, _, DBPrio_High);
}
}
public RefreshCacheCallback(Handle:owner, Handle:hndl, const String:error[], any:client)
{
if (hndl == INVALID_HANDLE)
{
LogError("SQL Error on RefreshCache: %s", error);
return;
}
g_cacheCount = 0;
while (SQL_FetchRow(hndl))
{
SQL_FetchString(hndl, 0, g_cache[g_cacheCount][Auth], 32);
g_cache[g_cacheCount][Distance] = SQL_FetchFloat(hndl, 1);
g_cache[g_cacheCount][Maxspeed] = SQL_FetchFloat(hndl, 2);
g_cache[g_cacheCount][Gain] = SQL_FetchFloat(hndl, 3);
g_cache[g_cacheCount][Prestrafe] = SQL_FetchFloat(hndl, 4);
g_cache[g_cacheCount][Strafenumber] = SQL_FetchInt(hndl, 5);
g_cache[g_cacheCount][Direction] = SQL_FetchInt(hndl, 6);
SQL_FetchString(hndl, 7, g_cache[g_cacheCount][Name], 32);
g_cache[g_cacheCount][Sync] = SQL_FetchFloat(hndl, 8);
g_cacheCount++;
}
g_bCacheLoaded = true;
}
public Action:Command_DeleteRecord_All(client, args)
{
if (args < 1)
{
ReplyToCommand(client, "Usage: sm_removejump <steamid>");
return Plugin_Handled;
}
new String:auth[32];
GetCmdArgString(auth, sizeof(auth));
decl String:query[384];
Format(query, sizeof(query), "DELETE FROM jumpstats WHERE auth = '%s'", auth);
SQL_TQuery(g_hSQL, DeleteRecordsCallback, query, _, DBPrio_High);
return Plugin_Handled;
}
public DeleteRecordsCallback(Handle:owner, Handle:hndl, const String:error[], any:data)
{
if (hndl == INVALID_HANDLE)
{
LogError("SQL Error on RemoveJump: %s", error);
return;
}
RefreshCache();
}
// End of SQL Stuff
// LJ Top Stuff
public Action:Command_LJTop(client, args)
{
if (!g_bCacheLoaded)
{
PrintToChat(client, "Records can't be loaded");
return Plugin_Handled;
}
CreateTopMenu(client);
return Plugin_Handled;
}
CreateTopMenu(client)
{
new Handle:menu = CreateMenu(MenuHandler_WR);
SetMenuTitle(menu, "Best Jumpers");
new items = 0;
for (new cache = 0; cache < g_cacheCount; cache++)
{
decl String:text[92];
FormatEx(text, sizeof(text), "#%d: %s - %.02f", (cache + 1), g_cache[cache][Name], g_cache[cache][Distance]);
AddMenuItem(menu, g_cache[cache][Auth], text);
items++;
}
if (items == 0)
{
CloseHandle(menu);
PrintToChat(client, "No Records");
return;
}
DisplayMenu(menu, client, MENU_TIME_FOREVER);
}
public MenuHandler_WR(Handle:menu, MenuAction:action, param1, param2)
{
if (action == MenuAction_End)
{
CloseHandle(menu);
}
else if (action == MenuAction_Select)
{
decl String:info[32];
GetMenuItem(menu, param2, info, sizeof(info));
CreateJumpInfoMenu(param1, info);
}
}
CreateJumpInfoMenu(client, const String:AuthString[])
{
new Handle:menu = CreateMenu(MenuHandler_JumpInfo);
SetMenuExitBackButton(menu, true);
for (new cache = 0; cache < g_cacheCount; cache++)
{
if (!strcmp(g_cache[cache][Auth], AuthString))
{
decl String:text[128];
SetMenuTitle(menu, "Jump Info", client);
FormatEx(text, sizeof(text), "Player Name: %s (%s)", g_cache[cache][Name], g_cache[cache][Auth]);
AddMenuItem(menu, "", text);
FormatEx(text, sizeof(text), "Rank: #%d", cache + 1);
AddMenuItem(menu, "", text);
FormatEx(text, sizeof(text), "Distance: %f", g_cache[cache][Distance]);
AddMenuItem(menu, "", text);
FormatEx(text, sizeof(text), "Strafes: %d", g_cache[cache][Strafenumber]);
AddMenuItem(menu, "", text);
FormatEx(text, sizeof(text), "Prestrafe: %f", g_cache[cache][Prestrafe]);
AddMenuItem(menu, "", text);
FormatEx(text, sizeof(text), "Maxspeed: %f", g_cache[cache][Maxspeed]);
AddMenuItem(menu, "", text);
FormatEx(text, sizeof(text), "Direction: %s", g_sDirectionNames[g_cache[cache][Direction]]);
AddMenuItem(menu, "", text);
break;
}
}
DisplayMenu(menu, client, MENU_TIME_FOREVER);
}
public MenuHandler_JumpInfo(Handle:menu, MenuAction:action, param1, param2)
{
if (action == MenuAction_End)
{
CloseHandle(menu);
}
else if (action == MenuAction_Cancel)
{
if (param2 == MenuCancel_ExitBack)
{
CreateTopMenu(param1);
}
}
}
public MenuHandler_DoNothing(Handle:menu, MenuAction:action, param1, param2)
{
if(action == MenuAction_End)
{
CloseHandle(menu);
}
}