Updated the Include files and also Recompiled with it
This commit is contained in:
parent
acb57e4657
commit
af731f99bc
29 changed files with 7459 additions and 2883 deletions
scripting/include/shavit
anti-sv_cheats.spbhopstats-timerified.incbhopstats-timerified.spchat-colors.incchat.inccheckpoints.inccore.inchud.incmapchooser.incmaps-folder-stocks.incmisc.incphysicsuntouch.incrankings.increplay-file.increplay-playback.increplay-recorder.increplay-stocks.spsql-create-tables-and-migrations.spsteamid-stocks.incstyle-settings.sptas-oblivious.inctas-xutax.inctas.incweapon-stocks.incwr.inczones.inc
131
scripting/include/shavit/anti-sv_cheats.sp
Normal file
131
scripting/include/shavit/anti-sv_cheats.sp
Normal file
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* shavit's Timer - anti-sv_cheats.sp
|
||||
* by: rtldg
|
||||
*
|
||||
* This file is part of shavit's Timer.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
Convar gCV_DisableSvCheats = null;
|
||||
|
||||
#if !DEBUG
|
||||
ConVar sv_cheats = null;
|
||||
|
||||
char gS_CheatCommands[][] = {
|
||||
"ent_create",
|
||||
"ent_orient",
|
||||
"ent_pause",
|
||||
|
||||
"ent_remove",
|
||||
"ent_remove_all",
|
||||
|
||||
"ent_setname",
|
||||
"ent_setpos",
|
||||
|
||||
"ent_teleport",
|
||||
|
||||
"firetarget",
|
||||
|
||||
"setpos",
|
||||
"setpos_exact",
|
||||
"setpos_player",
|
||||
|
||||
// can be used to kill other players
|
||||
"explode",
|
||||
"explodevector",
|
||||
"kill",
|
||||
"killvector",
|
||||
|
||||
"give",
|
||||
};
|
||||
#endif
|
||||
|
||||
void Anti_sv_cheats_cvars()
|
||||
{
|
||||
gCV_DisableSvCheats = new Convar("shavit_core_disable_sv_cheats", "1", "Force sv_cheats to 0.", 0, true, 0.0, true, 1.0);
|
||||
|
||||
#if !DEBUG
|
||||
sv_cheats = FindConVar("sv_cheats");
|
||||
sv_cheats.AddChangeHook(sv_cheats_hook);
|
||||
|
||||
for (int i = 0; i < sizeof(gS_CheatCommands); i++)
|
||||
{
|
||||
AddCommandListener(Command_Cheats, gS_CheatCommands[i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Anti_sv_cheats_OnConfigsExecuted()
|
||||
{
|
||||
if (gCV_DisableSvCheats.BoolValue)
|
||||
{
|
||||
#if !DEBUG
|
||||
sv_cheats.SetInt(0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void Remove_sv_cheat_Impluses(int client, int &impulse)
|
||||
{
|
||||
#if !DEBUG
|
||||
if (impulse && sv_cheats.BoolValue && !(GetUserFlagBits(client) & ADMFLAG_ROOT))
|
||||
{
|
||||
// Block cheat impulses
|
||||
switch (impulse)
|
||||
{
|
||||
case 76, 81, 82, 83, 102, 195, 196, 197, 202, 203:
|
||||
{
|
||||
impulse = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !DEBUG
|
||||
public void sv_cheats_hook(ConVar convar, const char[] oldValue, const char[] newValue)
|
||||
{
|
||||
if (gCV_DisableSvCheats.BoolValue)
|
||||
{
|
||||
sv_cheats.SetInt(0);
|
||||
}
|
||||
}
|
||||
|
||||
public Action Command_Cheats(int client, const char[] command, int args)
|
||||
{
|
||||
if (!sv_cheats.BoolValue || client == 0)
|
||||
{
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
if (StrContains(command, "kill") != -1 || StrContains(command, "explode") != -1)
|
||||
{
|
||||
bool bVector = StrContains(command, "vector") != -1;
|
||||
bool bKillOther = args > (bVector ? 3 : 0);
|
||||
|
||||
if (!bKillOther)
|
||||
{
|
||||
return Plugin_Continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(GetUserFlagBits(client) & ADMFLAG_ROOT))
|
||||
{
|
||||
return Plugin_Stop;
|
||||
}
|
||||
|
||||
return Plugin_Continue;
|
||||
}
|
||||
#endif
|
195
scripting/include/shavit/bhopstats-timerified.inc
Normal file
195
scripting/include/shavit/bhopstats-timerified.inc
Normal file
|
@ -0,0 +1,195 @@
|
|||
/*
|
||||
* Bunnyhop Statistics API - Include file
|
||||
* by: shavit
|
||||
*
|
||||
* This file is part of Bunnyhop Statistics API.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined _shavit_bhopstats_included
|
||||
#endinput
|
||||
#endif
|
||||
#define _shavit_bhopstats_included
|
||||
|
||||
/**
|
||||
* Called when the jump key is pressed.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param onground True if the jump key will do anything for the player when tapped.
|
||||
* @param perfect Was the jump perfectly timed?
|
||||
* @noreturn
|
||||
*/
|
||||
forward void Shavit_Bhopstats_OnJumpPressed(int client, bool onground, bool perfect);
|
||||
|
||||
/**
|
||||
* Called when the jump key is released.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param onground True if the jump key will do anything for the player when tapped.
|
||||
* @noreturn
|
||||
*/
|
||||
forward void Shavit_Bhopstats_OnJumpReleased(int client, bool onground);
|
||||
|
||||
/**
|
||||
* Called when the player touches the ground.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @noreturn
|
||||
*/
|
||||
forward void Shavit_Bhopstats_OnTouchGround(int client);
|
||||
|
||||
/**
|
||||
* Called when the player leaves the ground, by either jumping or falling from somewhere.
|
||||
* AKA the HookEventless better version of player_jump.
|
||||
* The `jumped` variable is true if the ground was left by tapping the jump key, or false if the player fell from somewhere.
|
||||
* `ladder` is true if the player left the 'ground' from a ladder.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param jumped Did the client leave the ground by jumping?
|
||||
* @param ladder Did the client leave the ground by leaving a ladder, aka ladderstrafing?
|
||||
* @noreturn
|
||||
*/
|
||||
forward void Shavit_Bhopstats_OnLeaveGround(int client, bool jumped, bool ladder);
|
||||
|
||||
/**
|
||||
* Retrieves the amount of separate +jump inputs since the player left the ground.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @return Amount of +jump inputs since the left the ground, or 0 if the player is on ground.
|
||||
*/
|
||||
native int Shavit_Bhopstats_GetScrollCount(int client);
|
||||
|
||||
/**
|
||||
* Checks if the player is on ground, or if the jump key will function as in actually triggering a jump or altering velocity.
|
||||
* The result will be true if the player is on a ladder or in water, as jumping will be functional.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @return Boolean value of 'is the player on ground?'
|
||||
*/
|
||||
native bool Shavit_Bhopstats_IsOnGround(int client);
|
||||
|
||||
/**
|
||||
* Checks if the player is holding his jump key.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @return Boolean value of 'is the player holding the jump key?''
|
||||
*/
|
||||
native bool Shavit_Bhopstats_IsHoldingJump(int client);
|
||||
|
||||
/**
|
||||
* Gets a percentage of perfectly timed bunnyhops.
|
||||
* Resets at player connection or the Shavit_Bhopstats_ResetPerfectJumps native for it is called.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @return Perfect jump percentage. Results are from 0.0 to 100.0.
|
||||
*/
|
||||
native float Shavit_Bhopstats_GetPerfectJumps(int client);
|
||||
|
||||
/**
|
||||
* Resets the perfect jumps percentage of a player back to 0.0.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @noreturn
|
||||
*/
|
||||
native void Shavit_Bhopstats_ResetPerfectJumps(int client);
|
||||
|
||||
methodmap Shavit_BunnyhopStats __nullable__
|
||||
{
|
||||
public Shavit_BunnyhopStats(int client)
|
||||
{
|
||||
return view_as<Shavit_BunnyhopStats>(client);
|
||||
}
|
||||
|
||||
property int index
|
||||
{
|
||||
public get()
|
||||
{
|
||||
return view_as<int>(this);
|
||||
}
|
||||
}
|
||||
|
||||
property int ScrollCount
|
||||
{
|
||||
public get()
|
||||
{
|
||||
return Shavit_Bhopstats_GetScrollCount(this.index);
|
||||
}
|
||||
}
|
||||
|
||||
property bool OnGround
|
||||
{
|
||||
public get()
|
||||
{
|
||||
return Shavit_Bhopstats_IsOnGround(this.index);
|
||||
}
|
||||
}
|
||||
|
||||
property bool HoldingJump
|
||||
{
|
||||
public get()
|
||||
{
|
||||
return Shavit_Bhopstats_IsHoldingJump(this.index);
|
||||
}
|
||||
}
|
||||
|
||||
property float PerfectJumps
|
||||
{
|
||||
public get()
|
||||
{
|
||||
return Shavit_Bhopstats_GetPerfectJumps(this.index);
|
||||
}
|
||||
}
|
||||
|
||||
public void ResetPrefects()
|
||||
{
|
||||
Shavit_Bhopstats_ResetPerfectJumps(this.index);
|
||||
}
|
||||
|
||||
public static int GetScrollCount(int client)
|
||||
{
|
||||
return Shavit_Bhopstats_GetScrollCount(client);
|
||||
}
|
||||
|
||||
public static bool IsOnGround(int client)
|
||||
{
|
||||
return Shavit_Bhopstats_IsOnGround(client);
|
||||
}
|
||||
|
||||
public static bool IsHoldingJump(int client)
|
||||
{
|
||||
return Shavit_Bhopstats_IsHoldingJump(client);
|
||||
}
|
||||
|
||||
public static float GetPerfectJumps(int client)
|
||||
{
|
||||
return Shavit_Bhopstats_GetPerfectJumps(client);
|
||||
}
|
||||
|
||||
public static void ResetPrefectJumps(int client)
|
||||
{
|
||||
Shavit_Bhopstats_ResetPerfectJumps(client);
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined REQUIRE_PLUGIN
|
||||
public void __pl_shavit_bhopstats_SetNTVOptional()
|
||||
{
|
||||
MarkNativeAsOptional("Shavit_Bhopstats_GetScrollCount");
|
||||
MarkNativeAsOptional("Shavit_Bhopstats_IsOnGround");
|
||||
MarkNativeAsOptional("Shavit_Bhopstats_IsHoldingJump");
|
||||
MarkNativeAsOptional("Shavit_Bhopstats_GetPerfectJumps");
|
||||
MarkNativeAsOptional("Shavit_Bhopstats_ResetPerfectJumps");
|
||||
}
|
||||
#endif
|
177
scripting/include/shavit/bhopstats-timerified.sp
Normal file
177
scripting/include/shavit/bhopstats-timerified.sp
Normal file
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* Bunnyhop Statistics API - Plugin
|
||||
* by: shavit
|
||||
*
|
||||
* This file is part of Bunnyhop Statistics API.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma newdecls required
|
||||
#pragma semicolon 1
|
||||
|
||||
bool gB_OnGround[MAXPLAYERS+1];
|
||||
bool gB_PlayerTouchingGround[MAXPLAYERS+1];
|
||||
|
||||
int gI_Scrolls[MAXPLAYERS+1];
|
||||
int gI_Buttons[MAXPLAYERS+1];
|
||||
bool gB_JumpHeld[MAXPLAYERS+1];
|
||||
|
||||
int gI_Jumps[MAXPLAYERS+1];
|
||||
int gI_PerfectJumps[MAXPLAYERS+1];
|
||||
|
||||
Handle gH_Forwards_OnJumpPressed = null;
|
||||
Handle gH_Forwards_OnJumpReleased = null;
|
||||
Handle gH_Forwards_OnTouchGround = null;
|
||||
Handle gH_Forwards_OnLeaveGround = null;
|
||||
|
||||
public void Bhopstats_CreateNatives()
|
||||
{
|
||||
CreateNative("Shavit_Bhopstats_GetScrollCount", Native_GetScrollCount);
|
||||
CreateNative("Shavit_Bhopstats_IsOnGround", Native_IsOnGround);
|
||||
CreateNative("Shavit_Bhopstats_IsHoldingJump", Native_IsHoldingJump);
|
||||
CreateNative("Shavit_Bhopstats_GetPerfectJumps", Native_Bhopstats_GetPerfectJumps);
|
||||
CreateNative("Shavit_Bhopstats_ResetPerfectJumps", Native_ResetPerfectJumps);
|
||||
}
|
||||
|
||||
public void Bhopstats_CreateForwards()
|
||||
{
|
||||
gH_Forwards_OnJumpPressed = CreateGlobalForward("Shavit_Bhopstats_OnJumpPressed", ET_Event, Param_Cell, Param_Cell);
|
||||
gH_Forwards_OnJumpReleased = CreateGlobalForward("Shavit_Bhopstats_OnJumpReleased", ET_Event, Param_Cell, Param_Cell);
|
||||
gH_Forwards_OnTouchGround = CreateGlobalForward("Shavit_Bhopstats_OnTouchGround", ET_Event, Param_Cell);
|
||||
gH_Forwards_OnLeaveGround = CreateGlobalForward("Shavit_Bhopstats_OnLeaveGround", ET_Event, Param_Cell, Param_Cell, Param_Cell);
|
||||
}
|
||||
|
||||
public void Bhopstats_OnClientPutInServer(int client)
|
||||
{
|
||||
gB_OnGround[client] = false;
|
||||
gB_PlayerTouchingGround[client] = false;
|
||||
|
||||
gI_Scrolls[client] = 0;
|
||||
gI_Buttons[client] = 0;
|
||||
gB_JumpHeld[client] = false;
|
||||
|
||||
gI_Jumps[client] = 0;
|
||||
gI_PerfectJumps[client] = 0;
|
||||
|
||||
SDKHook(client, SDKHook_PostThinkPost, Bhopstats_PostThinkPost);
|
||||
}
|
||||
|
||||
public int Native_GetScrollCount(Handle handler, int numParams)
|
||||
{
|
||||
return gI_Scrolls[GetNativeCell(1)];
|
||||
}
|
||||
|
||||
public int Native_IsOnGround(Handle handler, int numParams)
|
||||
{
|
||||
return view_as<int>(gB_OnGround[GetNativeCell(1)]);
|
||||
}
|
||||
|
||||
public int Native_IsHoldingJump(Handle handler, int numParams)
|
||||
{
|
||||
return view_as<int>(gI_Buttons[GetNativeCell(1)] & IN_JUMP);
|
||||
}
|
||||
|
||||
public int Native_Bhopstats_GetPerfectJumps(Handle handler, int numParams)
|
||||
{
|
||||
int client = GetNativeCell(1);
|
||||
|
||||
return view_as<int>((float(gI_PerfectJumps[client]) / gI_Jumps[client]) * 100.0);
|
||||
}
|
||||
|
||||
public int Native_ResetPerfectJumps(Handle handler, int numParams)
|
||||
{
|
||||
int client = GetNativeCell(1);
|
||||
|
||||
gI_Jumps[client] = 0;
|
||||
gI_PerfectJumps[client] = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void Bhopstats_PostThinkPost(int client)
|
||||
{
|
||||
if(!IsPlayerAlive(client))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int buttons = GetClientButtons(client);
|
||||
bool bOldOnGround = gB_OnGround[client];
|
||||
|
||||
int iGroundEntity;
|
||||
|
||||
if (gB_ReplayPlayback && IsFakeClient(client))
|
||||
{
|
||||
iGroundEntity = (Shavit_GetReplayEntityFlags(client) & FL_ONGROUND) ? 0 : -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
iGroundEntity = GetEntPropEnt(client, Prop_Send, "m_hGroundEntity");
|
||||
}
|
||||
|
||||
bool bOnLadder = (GetEntityMoveType(client) == MOVETYPE_LADDER);
|
||||
gB_OnGround[client] = (iGroundEntity != -1 || GetEntProp(client, Prop_Send, "m_nWaterLevel") >= 2 || bOnLadder);
|
||||
|
||||
gB_JumpHeld[client] = (buttons & IN_JUMP && !(gI_Buttons[client] & IN_JUMP));
|
||||
|
||||
if(gB_PlayerTouchingGround[client] && gB_OnGround[client])
|
||||
{
|
||||
Call_StartForward(gH_Forwards_OnTouchGround);
|
||||
Call_PushCell(client);
|
||||
Call_Finish();
|
||||
|
||||
gB_PlayerTouchingGround[client] = false;
|
||||
}
|
||||
else if(!gB_PlayerTouchingGround[client] && ((gB_JumpHeld[client] && iGroundEntity != -1) || iGroundEntity == -1 || bOnLadder))
|
||||
{
|
||||
Call_StartForward(gH_Forwards_OnLeaveGround);
|
||||
Call_PushCell(client);
|
||||
Call_PushCell(gB_JumpHeld[client]);
|
||||
Call_PushCell(bOnLadder);
|
||||
Call_Finish();
|
||||
|
||||
gB_PlayerTouchingGround[client] = true;
|
||||
gI_Scrolls[client] = 0;
|
||||
}
|
||||
|
||||
if(gB_JumpHeld[client])
|
||||
{
|
||||
gI_Scrolls[client]++;
|
||||
|
||||
Call_StartForward(gH_Forwards_OnJumpPressed);
|
||||
Call_PushCell(client);
|
||||
Call_PushCell(gB_OnGround[client]);
|
||||
Call_Finish();
|
||||
|
||||
if(gB_OnGround[client])
|
||||
{
|
||||
gI_Jumps[client]++;
|
||||
|
||||
if(!bOldOnGround)
|
||||
{
|
||||
gI_PerfectJumps[client]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(gI_Buttons[client] & IN_JUMP && !(buttons & IN_JUMP))
|
||||
{
|
||||
Call_StartForward(gH_Forwards_OnJumpReleased);
|
||||
Call_PushCell(client);
|
||||
Call_PushCell(gB_OnGround[client]);
|
||||
Call_Finish();
|
||||
}
|
||||
|
||||
gI_Buttons[client] = buttons;
|
||||
}
|
52
scripting/include/shavit/chat-colors.inc
Normal file
52
scripting/include/shavit/chat-colors.inc
Normal file
|
@ -0,0 +1,52 @@
|
|||
#if defined _shavit_chat_colors_included
|
||||
#endinput
|
||||
#endif
|
||||
#define _shavit_chat_colors_included
|
||||
|
||||
char gS_GlobalColorNames[][] =
|
||||
{
|
||||
"{default}",
|
||||
"{team}",
|
||||
"{green}"
|
||||
};
|
||||
|
||||
char gS_GlobalColors[][] =
|
||||
{
|
||||
"\x01",
|
||||
"\x03",
|
||||
"\x04"
|
||||
};
|
||||
|
||||
char gS_CSGOColorNames[][] =
|
||||
{
|
||||
"{blue}",
|
||||
"{bluegrey}",
|
||||
"{darkblue}",
|
||||
"{darkred}",
|
||||
"{gold}",
|
||||
"{grey}",
|
||||
"{grey2}",
|
||||
"{lightgreen}",
|
||||
"{lightred}",
|
||||
"{lime}",
|
||||
"{orchid}",
|
||||
"{yellow}",
|
||||
"{palered}"
|
||||
};
|
||||
|
||||
char gS_CSGOColors[][] =
|
||||
{
|
||||
"\x0B",
|
||||
"\x0A",
|
||||
"\x0C",
|
||||
"\x02",
|
||||
"\x10",
|
||||
"\x08",
|
||||
"\x0D",
|
||||
"\x05",
|
||||
"\x0F",
|
||||
"\x06",
|
||||
"\x0E",
|
||||
"\x09",
|
||||
"\x07"
|
||||
};
|
53
scripting/include/shavit/chat.inc
Normal file
53
scripting/include/shavit/chat.inc
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* shavit's Timer - chat.inc file
|
||||
* by: shavit
|
||||
*
|
||||
* This file is part of shavit's Timer.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined _shavit_chat_included
|
||||
#endinput
|
||||
#endif
|
||||
#define _shavit_chat_included
|
||||
|
||||
/*
|
||||
* Retrieves the player's chatrank trimmed and without colors.
|
||||
*
|
||||
* @param client Client index
|
||||
* @param buf Buffer to put the put the chatrank into
|
||||
* @param buflen Size of buf
|
||||
* @param includename Include {name} in result.
|
||||
* @noreturn
|
||||
*/
|
||||
native void Shavit_GetPlainChatrank(int client, char[] buf, int buflen, bool includename=false);
|
||||
|
||||
public SharedPlugin __pl_shavit_chat =
|
||||
{
|
||||
name = "shavit-chat",
|
||||
file = "shavit-chat.smx",
|
||||
#if defined REQUIRE_PLUGIN
|
||||
required = 1
|
||||
#else
|
||||
required = 0
|
||||
#endif
|
||||
};
|
||||
|
||||
#if !defined REQUIRE_PLUGIN
|
||||
public void __pl_shavit_chat_SetNTVOptional()
|
||||
{
|
||||
MarkNativeAsOptional("Shavit_GetPlainChatrank");
|
||||
}
|
||||
#endif
|
264
scripting/include/shavit/checkpoints.inc
Normal file
264
scripting/include/shavit/checkpoints.inc
Normal file
|
@ -0,0 +1,264 @@
|
|||
/*
|
||||
* shavit's Timer - Checkpoints
|
||||
* by: shavit
|
||||
*
|
||||
* This file is part of shavit's Timer.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined _shavit_checkpoints_included
|
||||
#endinput
|
||||
#endif
|
||||
#define _shavit_checkpoints_included
|
||||
|
||||
enum struct cp_cache_t
|
||||
{
|
||||
float fPosition[3];
|
||||
float fAngles[3];
|
||||
float fVelocity[3];
|
||||
MoveType iMoveType;
|
||||
float fGravity;
|
||||
float fSpeed;
|
||||
float fStamina;
|
||||
bool bDucked;
|
||||
bool bDucking;
|
||||
float fDucktime; // m_flDuckAmount in csgo
|
||||
float fDuckSpeed; // m_flDuckSpeed in csgo; doesn't exist in css
|
||||
int iFlags;
|
||||
timer_snapshot_t aSnapshot;
|
||||
char sTargetname[64];
|
||||
char sClassname[64];
|
||||
ArrayList aFrames;
|
||||
int iPreFrames;
|
||||
bool bSegmented;
|
||||
int iGroundEntity;
|
||||
int iSteamID;
|
||||
ArrayList aEvents;
|
||||
ArrayList aOutputWaits;
|
||||
float vecLadderNormal[3];
|
||||
StringMap customdata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a player teleports with checkpoints.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param index Checkpoint that was teleported to.
|
||||
* @return Plugin_Continue to allow teleporting, anything else to prevent.
|
||||
*/
|
||||
forward Action Shavit_OnTeleport(int client, int index);
|
||||
|
||||
/**
|
||||
* Called when a saves a checkpoint.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param index Checkpoint that was saved to.
|
||||
* @param overflow Does this checkpoint shift the rest.
|
||||
* @return Plugin_Continue to allow saving, anything else to prevent.
|
||||
*/
|
||||
forward Action Shavit_OnSave(int client, int index, bool overflow);
|
||||
|
||||
/**
|
||||
* Called when a player deletes a checkpoint.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param index Checkpoint that will be deleted.
|
||||
* @return Plugin_Continue to continue deletion, anything else to prevent.
|
||||
*/
|
||||
forward Action Shavit_OnDelete(int client, int index);
|
||||
|
||||
/**
|
||||
* Called after the checkpoint menu has been made and before it's sent to the client.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param segmented If the menu was a segmented menu
|
||||
* @param menu Handle to the menu so you can .AddItem().
|
||||
* @return Plugin_Handled or Plugin_Stop to stop the menu.
|
||||
*/
|
||||
forward Action Shavit_OnCheckpointMenuMade(int client, bool segmented, Menu menu);
|
||||
|
||||
/**
|
||||
* Called before a selection is processed in the main checkpoint menu.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param param2 Second parameter in the callback, usually the item selected.
|
||||
* @param info reference copy of the info string used in the callback
|
||||
* @param maxlength length of the info buffer
|
||||
* @param currentCheckpoint Clients current checkpoint
|
||||
* @param maxCPs Max checkpoints the client can use
|
||||
* @return Plugin_Continue to continue the callback. Return Plugin_Stop to prevent the checkpoints menu from reopening.
|
||||
*/
|
||||
forward Action Shavit_OnCheckpointMenuSelect(int client, int param2, char[] info, int maxlength, int currentCheckpoint, int maxCPs);
|
||||
|
||||
/**
|
||||
* Called when a checkpoint cache is saved.
|
||||
*
|
||||
* @param client The client the checkpoint cache is being saved for.
|
||||
* @param cache The resulting checkpoint cache structure.
|
||||
* @param index The resulting checkpoint index for this checkpoint cache. -1 if the cache is being saved as "persistent data" for rejoins/spectating.
|
||||
* @param target The target of the checkpoint cache.
|
||||
*
|
||||
* @noreturn
|
||||
*/
|
||||
forward void Shavit_OnCheckpointCacheSaved(int client, cp_cache_t cache, int index, int target);
|
||||
|
||||
/**
|
||||
* Called when a checkpoint cache is being loaded.
|
||||
*
|
||||
* @param client The client who is loading the checkpoint cache.
|
||||
* @param cache The cache.
|
||||
* @param index The checkpoint index for this cache. -1 if the cache is being loaded from "persistent data" for rejoins/spectating.
|
||||
*
|
||||
* @noreturn
|
||||
*/
|
||||
forward void Shavit_OnCheckpointCacheLoaded(int client, cp_cache_t cache, int index);
|
||||
|
||||
/**
|
||||
* Called when a checkpoint cache is being deleted.
|
||||
*
|
||||
* @param cache The cache.
|
||||
*
|
||||
* @noreturn
|
||||
*/
|
||||
forward void Shavit_OnCheckpointCacheDeleted(cp_cache_t cache);
|
||||
|
||||
/**
|
||||
* Gets the total number of CPs that a client has saved
|
||||
*
|
||||
* @param client Client index
|
||||
*
|
||||
* @return Total number of checkpoints
|
||||
*/
|
||||
native int Shavit_GetTotalCheckpoints(int client);
|
||||
|
||||
/**
|
||||
* Gets CP data for a client at specified index
|
||||
*
|
||||
* @param client Client index
|
||||
* @param index Index of CP to get
|
||||
* @param cpcache Buffer to store cp data in sizeof(cp_cache_t)
|
||||
* @param size Size of the cpcache buffer, e.g sizeof(cp_cache_t)
|
||||
*
|
||||
* @noreturn
|
||||
*/
|
||||
native bool Shavit_GetCheckpoint(int client, int index, any[] cpcache, int size = sizeof(cp_cache_t));
|
||||
|
||||
/**
|
||||
* Sets checkpoint data at the given index for the given client
|
||||
*
|
||||
* @param client Client index
|
||||
* @param index Index of CP to set, or -1 to push cp as last
|
||||
* @param cpcache Buffer to store cp data in sizeof(cp_cache_t)
|
||||
* @param size Size of the cpcache buffer, e.g sizeof(cp_cache_t)
|
||||
*
|
||||
* @noreturn
|
||||
*/
|
||||
native void Shavit_SetCheckpoint(int client, int index, any[] cpcache, int size = sizeof(cp_cache_t));
|
||||
|
||||
/**
|
||||
* Teleports client to the checkpoint at given index
|
||||
*
|
||||
* @param client Client index
|
||||
* @param index Index of CP to teleport to
|
||||
* @param suppress Supress checkpoint message
|
||||
*
|
||||
* @noreturn
|
||||
*/
|
||||
native void Shavit_TeleportToCheckpoint(int client, int index, bool suppress = false);
|
||||
|
||||
/**
|
||||
* Clears all saved checkpoints for the specified client
|
||||
*
|
||||
* @param client Client index
|
||||
*
|
||||
* @noreturn
|
||||
*/
|
||||
native void Shavit_ClearCheckpoints(int client);
|
||||
|
||||
/**
|
||||
* Saves a new checkpoint and returns the new checkpoint index
|
||||
*
|
||||
* @param client Client index
|
||||
*
|
||||
* @return The new current checkpoint
|
||||
*/
|
||||
native int Shavit_SaveCheckpoint(int client);
|
||||
|
||||
/**
|
||||
* Gets the current checkpoint index.
|
||||
*
|
||||
* @param client Client index
|
||||
*
|
||||
* @return The current checkpoint
|
||||
*/
|
||||
native int Shavit_GetCurrentCheckpoint(int client);
|
||||
|
||||
/**
|
||||
* Sets the current checkpoint index.
|
||||
*
|
||||
* @param client Client index
|
||||
* @param index New index to use
|
||||
*
|
||||
* @noreturn
|
||||
*/
|
||||
native void Shavit_SetCurrentCheckpoint(int client, int index);
|
||||
|
||||
/**
|
||||
* Gets how many times the client has teleported to checkpoints.
|
||||
*
|
||||
* @param client Client index
|
||||
*
|
||||
* @return The number of times the client has teleported to checkpoints.
|
||||
*/
|
||||
native int Shavit_GetTimesTeleported(int client);
|
||||
|
||||
/**
|
||||
* Checks whether the client has savestate data.
|
||||
*
|
||||
* @param client Client index
|
||||
*
|
||||
* @return Whether a savestate or rejoin-savestate data exists for the client.
|
||||
*/
|
||||
native bool Shavit_HasSavestate(int client);
|
||||
|
||||
public SharedPlugin __pl_shavit_checkpoints =
|
||||
{
|
||||
name = "shavit-checkpoints",
|
||||
file = "shavit-checkpoints.smx",
|
||||
#if defined REQUIRE_PLUGIN
|
||||
required = 1
|
||||
#else
|
||||
required = 0
|
||||
#endif
|
||||
};
|
||||
|
||||
#if !defined REQUIRE_PLUGIN
|
||||
public void __pl_shavit_checkpoints_SetNTVOptional()
|
||||
{
|
||||
MarkNativeAsOptional("Shavit_GetTotalCheckpoints");
|
||||
|
||||
MarkNativeAsOptional("Shavit_GetCheckpoint");
|
||||
MarkNativeAsOptional("Shavit_SetCheckpoint");
|
||||
|
||||
MarkNativeAsOptional("Shavit_TeleportToCheckpoint");
|
||||
MarkNativeAsOptional("Shavit_ClearCheckpoints");
|
||||
MarkNativeAsOptional("Shavit_SaveCheckpoint");
|
||||
|
||||
MarkNativeAsOptional("Shavit_GetCurrentCheckpoint");
|
||||
MarkNativeAsOptional("Shavit_SetCurrentCheckpoint");
|
||||
|
||||
MarkNativeAsOptional("Shavit_HasSavestate");
|
||||
}
|
||||
#endif
|
1462
scripting/include/shavit/core.inc
Normal file
1462
scripting/include/shavit/core.inc
Normal file
File diff suppressed because it is too large
Load diff
215
scripting/include/shavit/hud.inc
Normal file
215
scripting/include/shavit/hud.inc
Normal file
|
@ -0,0 +1,215 @@
|
|||
/*
|
||||
* shavit's Timer - hud.inc file
|
||||
* by: shavit
|
||||
*
|
||||
* This file is part of shavit's Timer.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined _shavit_hud_included
|
||||
#endinput
|
||||
#endif
|
||||
#define _shavit_hud_included
|
||||
|
||||
#define HUD_NONE 0
|
||||
#define HUD_MASTER (1 << 0) // master setting
|
||||
#define HUD_CENTER (1 << 1) // show hud as hint text
|
||||
#define HUD_ZONEHUD (1 << 2) // show start/end zone hud
|
||||
#define HUD_OBSERVE (1 << 3) // show the HUD of the player you spectate
|
||||
#define HUD_SPECTATORS (1 << 4) // show list of spectators
|
||||
#define HUD_KEYOVERLAY (1 << 5) // show a key overlay
|
||||
#define HUD_HIDEWEAPON (1 << 6) // hide the player's weapon
|
||||
#define HUD_TOPLEFT (1 << 7) // show top left white HUD with WR/PB times
|
||||
#define HUD_SYNC (1 << 8) // shows sync at right side of the screen (css only)
|
||||
#define HUD_TIMELEFT (1 << 9) // shows time left at right tside of the screen (css only)
|
||||
#define HUD_2DVEL (1 << 10) // shows 2d velocity
|
||||
#define HUD_NOSOUNDS (1 << 11) // disables sounds on personal best, world record etc
|
||||
#define HUD_NOPRACALERT (1 << 12) // hides practice mode chat alert
|
||||
#define HUD_USP (1 << 13) // makes you spawn with a USP
|
||||
#define HUD_GLOCK (1 << 14) // makes you spawn with a Glock
|
||||
#define HUD_DEBUGTARGETNAME (1 << 15) // admin option to show current targetname & classname
|
||||
|
||||
// HUD2 - these settings will *disable* elements for the main hud
|
||||
#define HUD2_TIME (1 << 0)
|
||||
#define HUD2_SPEED (1 << 1)
|
||||
#define HUD2_JUMPS (1 << 2)
|
||||
#define HUD2_STRAFE (1 << 3)
|
||||
#define HUD2_SYNC (1 << 4)
|
||||
#define HUD2_STYLE (1 << 5)
|
||||
#define HUD2_RANK (1 << 6)
|
||||
#define HUD2_TRACK (1 << 7)
|
||||
#define HUD2_SPLITPB (1 << 8)
|
||||
#define HUD2_MAPTIER (1 << 9)
|
||||
#define HUD2_TIMEDIFFERENCE (1 << 10)
|
||||
#define HUD2_PERFS (1 << 11)
|
||||
#define HUD2_TOPLEFT_RANK (1 << 12)
|
||||
#define HUD2_VELOCITYDIFFERENCE (1 << 13)
|
||||
#define HUD2_USPSILENCER (1 << 14) // spawns usps with a silencer on
|
||||
#define HUD2_GLOCKBURST (1 << 15) // spawns glocks with burst
|
||||
#define HUD2_CENTERKEYS (1 << 16) // CSGO option to toggle whether !keys is shown as center-text or in that panel thing.
|
||||
|
||||
#define HUD_DEFAULT (HUD_MASTER|HUD_CENTER|HUD_ZONEHUD|HUD_OBSERVE|HUD_TOPLEFT|HUD_SYNC|HUD_TIMELEFT|HUD_2DVEL|HUD_SPECTATORS)
|
||||
#define HUD_DEFAULT2 (HUD2_PERFS)
|
||||
|
||||
stock bool HUD1Enabled(int hudbits, int flag)
|
||||
{
|
||||
return (hudbits & flag) != 0;
|
||||
}
|
||||
|
||||
stock bool HUD2Enabled(int hudbits, int flag)
|
||||
{
|
||||
return (hudbits & flag) == 0;
|
||||
}
|
||||
|
||||
enum ZoneHUD
|
||||
{
|
||||
ZoneHUD_None,
|
||||
ZoneHUD_Start,
|
||||
ZoneHUD_End
|
||||
};
|
||||
|
||||
enum struct huddata_t
|
||||
{
|
||||
int iTarget;
|
||||
float fTime;
|
||||
int iSpeed;
|
||||
int iStyle;
|
||||
int iTrack;
|
||||
int iJumps;
|
||||
int iStrafes;
|
||||
int iRank;
|
||||
float fSync;
|
||||
float fPB;
|
||||
float fWR;
|
||||
bool bReplay;
|
||||
bool bPractice;
|
||||
TimerStatus iTimerStatus;
|
||||
ZoneHUD iZoneHUD;
|
||||
|
||||
int iHUDSettings;
|
||||
int iHUD2Settings;
|
||||
|
||||
int iPreviousSpeed;
|
||||
float fClosestReplayTime;
|
||||
float fClosestVelocityDifference;
|
||||
int iMapTier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when top left HUD updates.
|
||||
*
|
||||
* @param client Client index that recieves the hud.
|
||||
* @param target Target entity that is either the client or what the client is spectating.
|
||||
* @param topleft Reference to the HUD buffer.
|
||||
* @param topleftlength Max length of the topleft buffer.
|
||||
* @param track Target's track.
|
||||
* @param style Target's style.
|
||||
*
|
||||
* @return Plugin_Handled or Plugin_Stop to block the HUD message from appearing. Anything else to pass along new values.
|
||||
*/
|
||||
forward Action Shavit_OnTopLeftHUD(int client, int target, char[] topleft, int topleftlength, int track, int style);
|
||||
|
||||
/**
|
||||
* Called before the top left HUD updates and used to build the string for shavit-hud.
|
||||
*
|
||||
* @param client Client index that recieves the hud.
|
||||
* @param target Target entity that is either the client or what the client is spectating.
|
||||
* @param topleft Reference to the HUD buffer.
|
||||
* @param topleftlength Max length of the topleft buffer.
|
||||
* @param track Target's track.
|
||||
* @param style Target's style.
|
||||
*
|
||||
* @return Plugin_Handled or Plugin_Stop to block the HUD message from appearing. Plugin_Changed to use own topleft string instead of shavit-hud building it.
|
||||
*/
|
||||
forward Action Shavit_PreOnTopLeftHUD(int client, int target, char[] topleft, int topleftlength, int track, int style);
|
||||
|
||||
/**
|
||||
* Called before the center hud updates.
|
||||
*
|
||||
* @param client Client index that recieves the hud.
|
||||
* @param target Target entity that is either the client or what the client is spectating.
|
||||
* @param buffer Reference to the HUD buffer.
|
||||
* @param buflen Max length of the buffer.
|
||||
* @param data huddata_t which contains target info.
|
||||
*
|
||||
* @return Plugin_Handled or Plugin_Stop to block the HUD message from appearing. Plugin_Changed if you modify the buffer string.
|
||||
*/
|
||||
forward Action Shavit_PreOnDrawCenterHUD(int client, int target, char[] buffer, int buflen, huddata_t data);
|
||||
|
||||
/**
|
||||
* Called before the !keys hud updates.
|
||||
*
|
||||
* @param client Client index that recieves the hud.
|
||||
* @param target Target entity that is either the client or what the client is spectating.
|
||||
* @param style The target's style.
|
||||
* @param buttons The target's buttons.
|
||||
* @param anglediff The difference from the target's last angles and current angles.
|
||||
* @param buffer Reference to the HUD buffer.
|
||||
* @param buflen Max length of the buffer.
|
||||
* @param scrolls How many scrolls the player has so far (relevant for non-auto styles).
|
||||
* @param prevscrolls How many scrolls previously.
|
||||
* @param alternate_center_keys True when you should draw a Linux-specific format since fonts & alignment are different.
|
||||
*
|
||||
* @return Plugin_Handled or Plugin_Stop to block the HUD message from appearing. Plugin_Changed if you modify the buffer string.
|
||||
*/
|
||||
forward Action Shavit_PreOnDrawKeysHUD(int client, int target, int style, int buttons, float anglediff, char[] buffer, int buflen, int scrolls, int prevscrolls, bool alternate_center_keys);
|
||||
|
||||
/**
|
||||
* Force an HUD update for a player. Requires shavit-hud.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param spectators Should also update it for the player's spectators?
|
||||
* @error Error code 200 if client isn't valid.
|
||||
* @return Amount of players that had their HUD updated (client + spectators) or -1 on error.
|
||||
*/
|
||||
native int Shavit_ForceHUDUpdate(int client, bool spectators);
|
||||
|
||||
/**
|
||||
* Gets the HUD settings of a player.
|
||||
* See the HUD_* defines for information.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @return HUD settings.
|
||||
*/
|
||||
native int Shavit_GetHUDSettings(int client);
|
||||
|
||||
/**
|
||||
* Gets the HUD2 settings of a player.
|
||||
* See the HUD2_* defines for information.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @return HUD settings.
|
||||
*/
|
||||
native int Shavit_GetHUD2Settings(int client);
|
||||
|
||||
public SharedPlugin __pl_shavit_hud =
|
||||
{
|
||||
name = "shavit-hud",
|
||||
file = "shavit-hud.smx",
|
||||
#if defined REQUIRE_PLUGIN
|
||||
required = 1
|
||||
#else
|
||||
required = 0
|
||||
#endif
|
||||
};
|
||||
|
||||
#if !defined REQUIRE_PLUGIN
|
||||
public void __pl_shavit_hud_SetNTVOptional()
|
||||
{
|
||||
MarkNativeAsOptional("Shavit_ForceHUDUpdate");
|
||||
MarkNativeAsOptional("Shavit_GetHUDSettings");
|
||||
MarkNativeAsOptional("Shavit_GetHUD2Settings");
|
||||
}
|
||||
#endif
|
83
scripting/include/shavit/mapchooser.inc
Normal file
83
scripting/include/shavit/mapchooser.inc
Normal file
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* shavit's Timer - mapchooser.inc file
|
||||
* by: shavit
|
||||
*
|
||||
* This file is part of shavit's Timer.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined _shavit_mapchooser_included
|
||||
#endinput
|
||||
#endif
|
||||
#define _shavit_mapchooser_included
|
||||
|
||||
/**
|
||||
* Called when a player RTV's.
|
||||
* Requires shavit-mapchooser.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @noreturn
|
||||
*/
|
||||
forward void SMC_OnRTV(int client);
|
||||
|
||||
/**
|
||||
* Called when a player UNRTV's.
|
||||
* Requires shavit-mapchooser.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @noreturn
|
||||
*/
|
||||
forward void SMC_OnUnRTV(int client);
|
||||
|
||||
/**
|
||||
* Called when the map changes from an RTV.
|
||||
* Requires shavit-mapchooser.
|
||||
*
|
||||
* @noreturn
|
||||
*/
|
||||
forward void SMC_OnSuccesfulRTV();
|
||||
|
||||
/**
|
||||
* Returns the ArrayList of maps currently on rotation.
|
||||
*
|
||||
* @return The ArrayList of Maps. Don't delete this handle.
|
||||
*/
|
||||
native ArrayList Shavit_GetMapsArrayList();
|
||||
|
||||
/**
|
||||
* Returns the StringMap of maps currently on rotation.
|
||||
*
|
||||
* @return the StringMap of maps. Don't delete this handle.
|
||||
*/
|
||||
native StringMap Shavit_GetMapsStringMap();
|
||||
|
||||
public SharedPlugin __pl_shavit_mapchooser =
|
||||
{
|
||||
name = "shavit-mapchooser",
|
||||
file = "shavit-mapchooser.smx",
|
||||
#if defined REQUIRE_PLUGIN
|
||||
required = 1
|
||||
#else
|
||||
required = 0
|
||||
#endif
|
||||
};
|
||||
|
||||
#if !defined REQUIRE_PLUGIN
|
||||
public void __pl_shavit_mapchooser_SetNTVOptional()
|
||||
{
|
||||
MarkNativeAsOptional("Shavit_GetMapsArrayList");
|
||||
MarkNativeAsOptional("Shavit_GetMapsStringMap");
|
||||
}
|
||||
#endif
|
260
scripting/include/shavit/maps-folder-stocks.inc
Normal file
260
scripting/include/shavit/maps-folder-stocks.inc
Normal file
|
@ -0,0 +1,260 @@
|
|||
/*
|
||||
* shavit's Timer - maps-folder-stocks.inc file
|
||||
* by: rtldg, kidfearless
|
||||
*
|
||||
* This file is part of shavit's Timer.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined _shavit_mapsfolderstocks_included
|
||||
#endinput
|
||||
#endif
|
||||
#define _shavit_mapsfolderstocks_included
|
||||
|
||||
stock bool WriteNavMesh(const char[] map, bool skipExistsCheck = false)
|
||||
{
|
||||
char sTempMap[PLATFORM_MAX_PATH];
|
||||
FormatEx(sTempMap, PLATFORM_MAX_PATH, "maps/%s.nav", map);
|
||||
|
||||
if (skipExistsCheck || !FileExists(sTempMap))
|
||||
{
|
||||
File file = OpenFile(sTempMap, "wb");
|
||||
|
||||
if (file != null)
|
||||
{
|
||||
static int defaultNavMesh[205] = {
|
||||
0xCE, 0xFA, 0xED, 0xFE, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x58, 0xF6, 0x01, 0x00,
|
||||
0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x80, 0xED, 0xC3, 0x00, 0x00, 0x48, 0x42, 0xFF, 0x1F, 0x00, 0x42, 0x00, 0x00, 0x48, 0xC2,
|
||||
0x00, 0x80, 0xED, 0x43, 0xFF, 0x1F, 0x00, 0x42, 0xFF, 0x1F, 0x00, 0x42, 0xFF, 0x1F, 0x00, 0x42,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xE7, 0xC3, 0x00, 0x00, 0x7A, 0x42, 0xFF, 0x1F, 0x00,
|
||||
0x42, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7A, 0xC2, 0x00, 0x00, 0x7A, 0x42, 0xFF, 0x1F,
|
||||
0x00, 0x42, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7A, 0xC2, 0x00, 0x40, 0xE7, 0x43, 0xFF,
|
||||
0x1F, 0x00, 0x42, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x40, 0xE7, 0xC3, 0x00, 0x40, 0xE7, 0x43,
|
||||
0xFF, 0x1F, 0x00, 0x42, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x42, 0x00, 0x00, 0xF0, 0x42, 0x00, 0x00, 0x80, 0x3F, 0x00,
|
||||
0x00, 0x80, 0x3F, 0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x80, 0x3F, 0x01, 0x00, 0x00, 0x00, 0x01,
|
||||
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
file.Write(defaultNavMesh, sizeof(defaultNavMesh), 1);
|
||||
delete file;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
stock bool WriteNavMeshBz2(const char[] map, bool skipExistsCheck = false)
|
||||
{
|
||||
char sTempMap[PLATFORM_MAX_PATH];
|
||||
FormatEx(sTempMap, PLATFORM_MAX_PATH, "maps/%s.nav.bz2", map);
|
||||
|
||||
if (skipExistsCheck || !FileExists(sTempMap))
|
||||
{
|
||||
File file = OpenFile(sTempMap, "wb");
|
||||
|
||||
if (file != null)
|
||||
{
|
||||
static int defaultNavMeshBz2[132/4] = {
|
||||
0x39685A42, 0x26594131, 0xB8955953, 0x0000B354,
|
||||
0xFEC56E4E, 0x80004004, 0x0040D800, 0x40100040,
|
||||
0x00011800, 0xA0114182, 0xA7127200, 0x915133AA,
|
||||
0x04B501A0, 0x64A03285, 0x31190D0D, 0x96F2A658,
|
||||
0x864651CE, 0xA93468D3, 0xD269C634, 0x66EE82B6,
|
||||
0x3B1D4103, 0xD4BE309C, 0x58DF5463, 0xC0076E1B,
|
||||
0x346C6DC1, 0x8B9FD47B, 0x0385015D, 0x3B260D99,
|
||||
0xF43C28F0, 0xD071CFB3, 0xC95DFC92, 0x4242E114,
|
||||
0xCC52E156
|
||||
};
|
||||
|
||||
file.Write(defaultNavMeshBz2, sizeof(defaultNavMeshBz2), 4);
|
||||
delete file;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
stock void CreateAllNavFiles()
|
||||
{
|
||||
StringMap mapList = new StringMap();
|
||||
DirectoryListing dir = OpenDirectory("maps", true);
|
||||
|
||||
if (dir == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
char fileName[PLATFORM_MAX_PATH];
|
||||
FileType type;
|
||||
|
||||
// Loop through maps folder.
|
||||
// If .bsp, mark as need .nav
|
||||
// If .nav, mark as have .nav
|
||||
while (dir.GetNext(fileName, sizeof(fileName), type))
|
||||
{
|
||||
if (type != FileType_File)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int length = strlen(fileName);
|
||||
|
||||
if (length < 5 || fileName[length-4] != '.') // a.bsp
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fileName[length-3] == 'b' && fileName[length-2] == 's' && fileName[length-1] == 'p')
|
||||
{
|
||||
fileName[length-4] = 0;
|
||||
mapList.SetValue(fileName, false, false); // note: false for 'replace'
|
||||
}
|
||||
else if (fileName[length-3] == 'n' && fileName[length-2] == 'a' && fileName[length-1] == 'v')
|
||||
{
|
||||
fileName[length-4] = 0;
|
||||
mapList.SetValue(fileName, true, true); // note: true for 'replace'
|
||||
}
|
||||
}
|
||||
|
||||
delete dir;
|
||||
|
||||
// StringMap shenanigans are used so we don't call FileExists() 2000 times
|
||||
StringMapSnapshot snapshot = mapList.Snapshot();
|
||||
|
||||
for (int i = 0; i < snapshot.Length; i++)
|
||||
{
|
||||
snapshot.GetKey(i, fileName, sizeof(fileName));
|
||||
|
||||
bool hasNAV = false;
|
||||
mapList.GetValue(fileName, hasNAV);
|
||||
|
||||
if (!hasNAV)
|
||||
{
|
||||
WriteNavMesh(fileName, true);
|
||||
}
|
||||
}
|
||||
|
||||
delete snapshot;
|
||||
delete mapList;
|
||||
}
|
||||
|
||||
stock bool ReadMapsFolderHandler(const char path[PLATFORM_MAX_PATH], bool is_stringmap, Handle data, bool lowercase, bool display, bool iter_subfolders, bool use_valve_fs, char[][] exclude_prefixes, int exclude_count)
|
||||
{
|
||||
bool first_iteration = StrEqual(path, "maps");
|
||||
DirectoryListing dir = OpenDirectory(path, use_valve_fs, NULL_STRING);
|
||||
|
||||
if (dir == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
char buffer[PLATFORM_MAX_PATH];
|
||||
FileType type;
|
||||
|
||||
while (dir.GetNext(buffer, sizeof(buffer), type))
|
||||
{
|
||||
if (type == FileType_Directory)
|
||||
{
|
||||
if (buffer[0] == '.' && (buffer[1] == 0 || (buffer[1] == '.' && buffer[2] == 0)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (iter_subfolders)
|
||||
{
|
||||
char subfolder[PLATFORM_MAX_PATH];
|
||||
FormatEx(subfolder, sizeof(subfolder), "%s/%s", path, buffer);
|
||||
ReadMapsFolderHandler(subfolder, is_stringmap, data, lowercase, display, iter_subfolders, use_valve_fs, exclude_prefixes, exclude_count);
|
||||
}
|
||||
}
|
||||
else if (type == FileType_File)
|
||||
{
|
||||
int length = strlen(buffer);
|
||||
|
||||
if (length < 5 || buffer[length-4] != '.') // a.bsp
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((buffer[length-3] == 'b' && buffer[length-2] == 's' && buffer[length-1] == 'p') ||
|
||||
(buffer[length-3] == 'u' && buffer[length-2] == 'g' && buffer[length-1] == 'c'))
|
||||
{
|
||||
buffer[length-4] = 0;
|
||||
|
||||
if (lowercase)
|
||||
{
|
||||
LowercaseString(buffer);
|
||||
}
|
||||
|
||||
bool skip = false;
|
||||
|
||||
for (int i = 0; i < exclude_count; i++)
|
||||
{
|
||||
if (strncmp(buffer, exclude_prefixes[i], strlen(exclude_prefixes[i]), lowercase) == 0)
|
||||
{
|
||||
skip = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (skip)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!display && !first_iteration)
|
||||
{
|
||||
char temp[PLATFORM_MAX_PATH];
|
||||
int skip_this = 5; // strlen("maps/")
|
||||
FormatEx(temp, sizeof(temp), "%s/%s", path[skip_this], buffer);
|
||||
buffer = temp;
|
||||
}
|
||||
|
||||
if (is_stringmap)
|
||||
{
|
||||
view_as<StringMap>(data).SetValue(buffer, false, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
view_as<ArrayList>(data).PushString(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete dir;
|
||||
return true;
|
||||
}
|
||||
|
||||
static char empty_excludes[][] = {""};
|
||||
|
||||
stock bool ReadMapsFolderStringMap(StringMap data, bool lowercase=true, bool display=false, bool iter_subfolders=true, bool use_valve_fs=true, char[][] exclude_prefixes=empty_excludes, int exclude_count=0)
|
||||
{
|
||||
return ReadMapsFolderHandler("maps", true, data, lowercase, display, iter_subfolders, use_valve_fs, exclude_prefixes, exclude_count);
|
||||
}
|
||||
|
||||
// don't forget to declare your ArrayList like below :)))
|
||||
//// ArrayList maps = new ArrayList(ByteCountToCells(PLATFORM_MAX_PATH));
|
||||
stock bool ReadMapsFolderArrayList(ArrayList data, bool lowercase=true, bool display=false, bool iter_subfolders=true, bool use_valve_fs=true, char[][] exclude_prefixes=empty_excludes, int exclude_count=0)
|
||||
{
|
||||
return ReadMapsFolderHandler("maps", false, data, lowercase, display, iter_subfolders, use_valve_fs, exclude_prefixes, exclude_count);
|
||||
}
|
50
scripting/include/shavit/misc.inc
Normal file
50
scripting/include/shavit/misc.inc
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* shavit's Timer - misc.inc file
|
||||
* by: shavit
|
||||
*
|
||||
* This file is part of shavit's Timer.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined _shavit_misc_included
|
||||
#endinput
|
||||
#endif
|
||||
#define _shavit_misc_included
|
||||
|
||||
/**
|
||||
* Checks if a player is hiding players
|
||||
*
|
||||
* @param client Client index.
|
||||
* @return Boolean value.
|
||||
*/
|
||||
native bool Shavit_IsClientUsingHide(int client);
|
||||
|
||||
public SharedPlugin __pl_shavit_misc =
|
||||
{
|
||||
name = "shavit-misc",
|
||||
file = "shavit-misc.smx",
|
||||
#if defined REQUIRE_PLUGIN
|
||||
required = 1
|
||||
#else
|
||||
required = 0
|
||||
#endif
|
||||
};
|
||||
|
||||
#if !defined REQUIRE_PLUGIN
|
||||
public void __pl_shavit_misc_SetNTVOptional()
|
||||
{
|
||||
MarkNativeAsOptional("Shavit_IsClientUsingHide");
|
||||
}
|
||||
#endif
|
37
scripting/include/shavit/physicsuntouch.inc
Normal file
37
scripting/include/shavit/physicsuntouch.inc
Normal file
|
@ -0,0 +1,37 @@
|
|||
|
||||
#if defined _physicuntouch_included
|
||||
#endinput
|
||||
#endif
|
||||
#define _physicuntouch_included
|
||||
|
||||
// Originally from https://github.com/rumourA/End-Touch-Fix
|
||||
|
||||
#define EFL_CHECK_UNTOUCH (1<<24)
|
||||
|
||||
Handle gH_PhysicsCheckForEntityUntouch;
|
||||
|
||||
stock void LoadPhysicsUntouch(Handle gamedata)
|
||||
{
|
||||
StartPrepSDKCall(SDKCall_Entity);
|
||||
|
||||
if (!PrepSDKCall_SetFromConf(gamedata, SDKConf_Signature, "PhysicsCheckForEntityUntouch"))
|
||||
{
|
||||
SetFailState("Failed to get PhysicsCheckForEntityUntouch");
|
||||
}
|
||||
|
||||
gH_PhysicsCheckForEntityUntouch = EndPrepSDKCall();
|
||||
}
|
||||
|
||||
stock bool GetCheckUntouch(int client)
|
||||
{
|
||||
int flags = GetEntProp(client, Prop_Data, "m_iEFlags");
|
||||
return (flags & EFL_CHECK_UNTOUCH) != 0;
|
||||
}
|
||||
|
||||
stock void MaybeDoPhysicsUntouch(int client)
|
||||
{
|
||||
if (GetCheckUntouch(client))
|
||||
{
|
||||
SDKCall(gH_PhysicsCheckForEntityUntouch, client);
|
||||
}
|
||||
}
|
174
scripting/include/shavit/rankings.inc
Normal file
174
scripting/include/shavit/rankings.inc
Normal file
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
* shavit's Timer - rankings.inc file
|
||||
* by: shavit
|
||||
*
|
||||
* This file is part of shavit's Timer.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined _shavit_rankings_included
|
||||
#endinput
|
||||
#endif
|
||||
#define _shavit_rankings_included
|
||||
|
||||
/**
|
||||
* Gets called when a map's tier is assigned.
|
||||
* Only called once per map, if the rankings plugin is enabled.
|
||||
* The exception is if the admin changes the current map's tier.
|
||||
*
|
||||
* @param map Map display name.
|
||||
* @param tier Map's tier.
|
||||
* @noreturn
|
||||
*/
|
||||
forward void Shavit_OnTierAssigned(const char[] map, int tier);
|
||||
|
||||
/**
|
||||
* Gets called when the server acknowledges the client's ranking status.
|
||||
* It is called after OnClientPostAdminCheck and at forced rank recalculations.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param rank Client's rank. (0 if unranked or unassigned)
|
||||
* @param points Client's points. (0.0 if unranked or unassigned)
|
||||
* @param first True if the forward is called after the initial connection, false if it is caused by recalculation.
|
||||
* @noreturn
|
||||
*/
|
||||
forward void Shavit_OnRankAssigned(int client, int rank, float points, bool first);
|
||||
|
||||
/**
|
||||
* Gets the map tier for a specified map.
|
||||
* Use the map's display name.
|
||||
*
|
||||
* @param map Map to get the tier of. Using "" will get the current map's tier.
|
||||
* @return Map tier. 0 if no results were found.
|
||||
*/
|
||||
native int Shavit_GetMapTier(const char[] map = "");
|
||||
|
||||
/**
|
||||
* Gets a StringMap that contains all the cached map tiers.
|
||||
* The returned StringMap must be deleted from memory after use!
|
||||
*
|
||||
* @return StringMap with {const char[]: map, int: tier} structure.
|
||||
*/
|
||||
native StringMap Shavit_GetMapTiers();
|
||||
|
||||
/**
|
||||
* Gets player points.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @return Points. 0.0 if unranked.
|
||||
*/
|
||||
native float Shavit_GetPoints(int client);
|
||||
|
||||
/**
|
||||
* Gets player rank.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @return Rank. 0 if unranked.
|
||||
*/
|
||||
native int Shavit_GetRank(int client);
|
||||
|
||||
/**
|
||||
* Gets the amount of players with over 0 points.
|
||||
*
|
||||
* @return Amount of ranked players.
|
||||
*/
|
||||
native int Shavit_GetRankedPlayers();
|
||||
|
||||
/**
|
||||
* Deletes tier setting for the specified map.
|
||||
* Points recalculation will run right after this is finished.
|
||||
*
|
||||
* @param map Map name.
|
||||
* @noreturn
|
||||
*/
|
||||
native void Shavit_Rankings_DeleteMap(const char[] map);
|
||||
|
||||
/**
|
||||
* Retrieves the amount of #1 records a player has.
|
||||
* Requires shavit-rankings.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param track Track to retrieve WRs from. -1 to use all tracks. All bonus tracks are combined.
|
||||
* @param style Style to retrieve WRs from. -1 to use all styles.
|
||||
* @param usecvars Whether to depend on the value of `shavit_stats_mvprankones` and `shavit_stats_mvprankones_maintrack`.
|
||||
* @return The number of WRs.
|
||||
*/
|
||||
native int Shavit_GetWRCount(int client, int track = -1, int style = -1, bool usecvars = true);
|
||||
|
||||
/**
|
||||
* Retrieves the number of players who hold #1 records.
|
||||
* Requires shavit-rankings.
|
||||
*
|
||||
* @param track Track to retrieve WRs from. -1 to use all tracks. All bonus tracks are combined.
|
||||
* @param style Style to retrieve WRs from. -1 to use all styles.
|
||||
* @param usecvars Whether to depend on the value of `shavit_stats_mvprankones` and `shavit_stats_mvprankones_maintrack`.
|
||||
* @return The number of WR holders. 0 if none.
|
||||
*/
|
||||
native int Shavit_GetWRHolders(int track = -1, int style = -1, bool usecvars = true);
|
||||
|
||||
/**
|
||||
* Retrieves the player's rank based on how many #1 records they hold.
|
||||
* Requires shavit-rankings.
|
||||
* Only works with MySQL 8.0+ or with MariaDB 10.2+.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param track Track to retrieve WRs from. -1 to use all tracks. All bonus tracks are combined.
|
||||
* @param style Style to retrieve WRs from. -1 to use all styles.
|
||||
* @param usecvars Whether to depend on the value of `shavit_stats_mvprankones` and `shavit_stats_mvprankones_maintrack`.
|
||||
* @return The rank. 0 if none, or not supported.
|
||||
*/
|
||||
native int Shavit_GetWRHolderRank(int client, int track = -1, int style = -1, bool usecvars = true);
|
||||
|
||||
/*
|
||||
* Calculates how many points a time will give.
|
||||
* Used to minimize number of SQL queries.
|
||||
* Requires shavit-rankings.
|
||||
*
|
||||
* @param track The track the time is from.
|
||||
* @param style The style the time is from.
|
||||
* @param tier The map tier. -1 to use the current map's tier.
|
||||
* @param time The time you want to calculate the points for.
|
||||
* @param wr WR.
|
||||
*
|
||||
* @return The number of points the time would give.
|
||||
*/
|
||||
native float Shavit_GuessPointsForTime(int track, int style, int tier, float time, float wr);
|
||||
|
||||
public SharedPlugin __pl_shavit_rankings =
|
||||
{
|
||||
name = "shavit-rankings",
|
||||
file = "shavit-rankings.smx",
|
||||
#if defined REQUIRE_PLUGIN
|
||||
required = 1
|
||||
#else
|
||||
required = 0
|
||||
#endif
|
||||
};
|
||||
|
||||
#if !defined REQUIRE_PLUGIN
|
||||
public void __pl_shavit_rankings_SetNTVOptional()
|
||||
{
|
||||
MarkNativeAsOptional("Shavit_GetMapTier");
|
||||
MarkNativeAsOptional("Shavit_GetMapTiers");
|
||||
MarkNativeAsOptional("Shavit_GetPoints");
|
||||
MarkNativeAsOptional("Shavit_GetRank");
|
||||
MarkNativeAsOptional("Shavit_GetRankedPlayers");
|
||||
MarkNativeAsOptional("Shavit_Rankings_DeleteMap");
|
||||
MarkNativeAsOptional("Shavit_GetWRCount");
|
||||
MarkNativeAsOptional("Shavit_GetWRHolders");
|
||||
MarkNativeAsOptional("Shavit_GetWRHolderRank");
|
||||
MarkNativeAsOptional("Shavit_GuessPointsForTime");
|
||||
}
|
||||
#endif
|
399
scripting/include/shavit/replay-file.inc
Normal file
399
scripting/include/shavit/replay-file.inc
Normal file
|
@ -0,0 +1,399 @@
|
|||
/*
|
||||
* shavit's Timer - replay file stocks & format
|
||||
* by: shavit
|
||||
*
|
||||
* This file is part of shavit's Timer.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined _shavit_replay_file_included
|
||||
#endinput
|
||||
#endif
|
||||
#define _shavit_replay_file_included
|
||||
|
||||
// History of REPLAY_FORMAT_SUBVERSION:
|
||||
// 0x01: standard origin[3], angles[2], and buttons
|
||||
// 0x02: flags added movetype added
|
||||
// 0x03: integrity stuff: style, track, and map added to header. preframe count added (unimplemented until later though)
|
||||
// 0x04: steamid/accountid written as a 32-bit int instead of a string
|
||||
// 0x05: postframes & fTickrate added
|
||||
// 0x06: mousexy and vel added
|
||||
// 0x07: fixed iFrameCount because postframes were included in the value when they shouldn't be
|
||||
// 0x08: added zone-offsets to header
|
||||
// 0x09: bumped with no actual file changes because time calculation in regards to offsets have been changed/fixed since it seems to have been using the end-zone-offset incorrectly (and should now be fine hopefully since 2021-12-21 / a146b51fb16febf1847657fba7ef9e0c056d7476)
|
||||
|
||||
#define REPLAY_FORMAT_V2 "{SHAVITREPLAYFORMAT}{V2}"
|
||||
#define REPLAY_FORMAT_FINAL "{SHAVITREPLAYFORMAT}{FINAL}"
|
||||
#define REPLAY_FORMAT_SUBVERSION 0x09
|
||||
|
||||
#define REPLAY_FRAMES_PER_WRITE 100 // amounts of frames to write per read/write call
|
||||
|
||||
enum struct replay_header_t
|
||||
{
|
||||
char sReplayFormat[40];
|
||||
int iReplayVersion;
|
||||
char sMap[PLATFORM_MAX_PATH];
|
||||
int iStyle;
|
||||
int iTrack;
|
||||
int iPreFrames;
|
||||
int iFrameCount;
|
||||
float fTime;
|
||||
int iSteamID;
|
||||
int iPostFrames;
|
||||
float fTickrate;
|
||||
float fZoneOffset[2];
|
||||
}
|
||||
|
||||
enum struct frame_t
|
||||
{
|
||||
float pos[3];
|
||||
float ang[2];
|
||||
int buttons;
|
||||
// iReplayVersion >= 0x02
|
||||
int flags;
|
||||
MoveType mt;
|
||||
// Everything below is generally NOT loaded into memory for playback
|
||||
// iReplayVersion >= 0x06
|
||||
int mousexy; // `mousex | (mousey << 16)` // unpack with UnpackSignedShorts
|
||||
int vel; // basically `forwardmove | (sidemove << 16)` // unpack with UnpackSignedShorts
|
||||
}
|
||||
|
||||
enum struct frame_cache_t
|
||||
{
|
||||
int iFrameCount;
|
||||
float fTime;
|
||||
bool bNewFormat;
|
||||
int iReplayVersion;
|
||||
char sReplayName[MAX_NAME_LENGTH];
|
||||
int iPreFrames;
|
||||
ArrayList aFrames;
|
||||
// iReplayVersion >= 0x05
|
||||
int iPostFrames;
|
||||
float fTickrate;
|
||||
// blah blah not affected by iReplayVersion
|
||||
int iSteamID;
|
||||
}
|
||||
|
||||
// Can be used to unpack frame_t.mousexy and frame_t.vel
|
||||
stock void UnpackSignedShorts(int x, int out[2])
|
||||
{
|
||||
out[0] = ((x & 0xFFFF) ^ 0x8000) - 0x8000;
|
||||
out[1] = (((x >> 16) & 0xFFFF) ^ 0x8000) - 0x8000;
|
||||
}
|
||||
|
||||
stock bool LoadReplayCache(frame_cache_t cache, int style, int track, const char[] path, const char[] mapname)
|
||||
{
|
||||
bool success = false;
|
||||
replay_header_t header;
|
||||
File fFile = ReadReplayHeader(path, header, style, track);
|
||||
|
||||
if (fFile != null)
|
||||
{
|
||||
if (header.iReplayVersion > REPLAY_FORMAT_SUBVERSION)
|
||||
{
|
||||
// not going to try and read it
|
||||
}
|
||||
else if (header.iReplayVersion < 0x03 || (StrEqual(header.sMap, mapname, false) && header.iStyle == style && header.iTrack == track))
|
||||
{
|
||||
success = ReadReplayFrames(fFile, header, cache);
|
||||
}
|
||||
|
||||
delete fFile;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
stock bool ReadReplayFrames(File file, replay_header_t header, frame_cache_t cache)
|
||||
{
|
||||
int total_cells = 6;
|
||||
int used_cells = 6;
|
||||
bool is_btimes = false;
|
||||
|
||||
if (header.iReplayVersion > 0x01)
|
||||
{
|
||||
total_cells = 8;
|
||||
used_cells = 8;
|
||||
}
|
||||
|
||||
// We have differing total_cells & used_cells because we want to save memory during playback since the latest two cells added (vel & mousexy) aren't needed and are only useful for replay file anticheat usage stuff....
|
||||
if (header.iReplayVersion >= 0x06)
|
||||
{
|
||||
total_cells = 10;
|
||||
used_cells = 8;
|
||||
}
|
||||
|
||||
any aReplayData[sizeof(frame_t)];
|
||||
|
||||
delete cache.aFrames;
|
||||
int iTotalSize = header.iFrameCount + header.iPreFrames + header.iPostFrames;
|
||||
cache.aFrames = new ArrayList(used_cells, iTotalSize);
|
||||
|
||||
if (!header.sReplayFormat[0]) // old replay format. no header.
|
||||
{
|
||||
char sLine[320];
|
||||
char sExplodedLine[6][64];
|
||||
|
||||
if(!file.Seek(0, SEEK_SET))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
while (!file.EndOfFile())
|
||||
{
|
||||
file.ReadLine(sLine, 320);
|
||||
int iStrings = ExplodeString(sLine, "|", sExplodedLine, 6, 64);
|
||||
|
||||
aReplayData[0] = StringToFloat(sExplodedLine[0]);
|
||||
aReplayData[1] = StringToFloat(sExplodedLine[1]);
|
||||
aReplayData[2] = StringToFloat(sExplodedLine[2]);
|
||||
aReplayData[3] = StringToFloat(sExplodedLine[3]);
|
||||
aReplayData[4] = StringToFloat(sExplodedLine[4]);
|
||||
aReplayData[5] = (iStrings == 6) ? StringToInt(sExplodedLine[5]) : 0;
|
||||
|
||||
cache.aFrames.PushArray(aReplayData, 6);
|
||||
}
|
||||
|
||||
cache.iFrameCount = cache.aFrames.Length;
|
||||
}
|
||||
else // assumes the file position will be at the start of the frames
|
||||
{
|
||||
is_btimes = StrEqual(header.sReplayFormat, "btimes");
|
||||
|
||||
for (int i = 0; i < iTotalSize; i++)
|
||||
{
|
||||
if(file.Read(aReplayData, total_cells, 4) >= 0)
|
||||
{
|
||||
cache.aFrames.SetArray(i, aReplayData, used_cells);
|
||||
|
||||
if (is_btimes && (aReplayData[5] & IN_BULLRUSH))
|
||||
{
|
||||
if (!header.iPreFrames)
|
||||
{
|
||||
header.iPreFrames = i;
|
||||
header.iFrameCount -= i;
|
||||
}
|
||||
else if (!header.iPostFrames)
|
||||
{
|
||||
header.iPostFrames = header.iFrameCount + header.iPreFrames - i;
|
||||
header.iFrameCount -= header.iPostFrames;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cache.aFrames.Length <= 10) // worthless replay so it doesn't get to load
|
||||
{
|
||||
delete cache.aFrames;
|
||||
return false;
|
||||
}
|
||||
|
||||
cache.iFrameCount = header.iFrameCount;
|
||||
cache.fTime = header.fTime;
|
||||
cache.iReplayVersion = header.iReplayVersion;
|
||||
cache.bNewFormat = StrEqual(header.sReplayFormat, REPLAY_FORMAT_FINAL) || is_btimes;
|
||||
cache.sReplayName = "unknown";
|
||||
cache.iPreFrames = header.iPreFrames;
|
||||
cache.iPostFrames = header.iPostFrames;
|
||||
cache.fTickrate = header.fTickrate;
|
||||
cache.iSteamID = header.iSteamID;
|
||||
|
||||
if (cache.iSteamID > 0)
|
||||
{
|
||||
FormatEx(cache.sReplayName, sizeof(cache.sReplayName), "[U:1:%d]", cache.iSteamID);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
stock File ReadReplayHeader(const char[] path, replay_header_t header, int style = 0, int track = 0)
|
||||
{
|
||||
replay_header_t empty_header;
|
||||
header = empty_header;
|
||||
|
||||
File file = OpenFile(path, "rb");
|
||||
|
||||
if (file == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
char sHeader[64];
|
||||
|
||||
if(!file.ReadLine(sHeader, 64))
|
||||
{
|
||||
delete file;
|
||||
return null;
|
||||
}
|
||||
|
||||
TrimString(sHeader);
|
||||
char sExplodedHeader[2][64];
|
||||
ExplodeString(sHeader, ":", sExplodedHeader, 2, 64);
|
||||
|
||||
strcopy(header.sReplayFormat, sizeof(header.sReplayFormat), sExplodedHeader[1]);
|
||||
|
||||
if(StrEqual(header.sReplayFormat, REPLAY_FORMAT_FINAL)) // hopefully, the last of them
|
||||
{
|
||||
int version = StringToInt(sExplodedHeader[0]);
|
||||
|
||||
header.iReplayVersion = version;
|
||||
|
||||
// replay file integrity and PreFrames
|
||||
if(version >= 0x03)
|
||||
{
|
||||
file.ReadString(header.sMap, PLATFORM_MAX_PATH);
|
||||
file.ReadUint8(header.iStyle);
|
||||
file.ReadUint8(header.iTrack);
|
||||
|
||||
file.ReadInt32(header.iPreFrames);
|
||||
|
||||
// In case the replay was from when there could still be negative preframes
|
||||
if(header.iPreFrames < 0)
|
||||
{
|
||||
header.iPreFrames = 0;
|
||||
}
|
||||
}
|
||||
|
||||
file.ReadInt32(header.iFrameCount);
|
||||
file.ReadInt32(view_as<int>(header.fTime));
|
||||
|
||||
if (header.iReplayVersion < 0x07)
|
||||
{
|
||||
header.iFrameCount -= header.iPreFrames;
|
||||
}
|
||||
|
||||
if(version >= 0x04)
|
||||
{
|
||||
file.ReadInt32(header.iSteamID);
|
||||
}
|
||||
else
|
||||
{
|
||||
char sAuthID[32];
|
||||
file.ReadString(sAuthID, 32);
|
||||
ReplaceString(sAuthID, 32, "[U:1:", "");
|
||||
ReplaceString(sAuthID, 32, "]", "");
|
||||
header.iSteamID = StringToInt(sAuthID);
|
||||
}
|
||||
|
||||
if (version >= 0x05)
|
||||
{
|
||||
file.ReadInt32(header.iPostFrames);
|
||||
file.ReadInt32(view_as<int>(header.fTickrate));
|
||||
|
||||
if (header.iReplayVersion < 0x07)
|
||||
{
|
||||
header.iFrameCount -= header.iPostFrames;
|
||||
}
|
||||
}
|
||||
|
||||
if (version >= 0x08)
|
||||
{
|
||||
file.ReadInt32(view_as<int>(header.fZoneOffset[0]));
|
||||
file.ReadInt32(view_as<int>(header.fZoneOffset[1]));
|
||||
}
|
||||
}
|
||||
else if(StrEqual(header.sReplayFormat, REPLAY_FORMAT_V2))
|
||||
{
|
||||
header.iFrameCount = StringToInt(sExplodedHeader[0]);
|
||||
}
|
||||
else // old, outdated and slow - only used for ancient replays
|
||||
{
|
||||
// check for btimes replays
|
||||
file.Seek(0, SEEK_SET);
|
||||
any stuff[2];
|
||||
file.Read(stuff, 2, 4);
|
||||
|
||||
int btimes_player_id = stuff[0];
|
||||
float run_time = stuff[1];
|
||||
|
||||
if (btimes_player_id >= 0 && run_time > 0.0 && run_time < (10.0 * 60.0 * 60.0))
|
||||
{
|
||||
header.sReplayFormat = "btimes";
|
||||
header.fTime = run_time;
|
||||
|
||||
file.Seek(0, SEEK_END);
|
||||
header.iFrameCount = (file.Position / 4 - 2) / 6;
|
||||
file.Seek(2*4, SEEK_SET);
|
||||
}
|
||||
}
|
||||
|
||||
if (header.iReplayVersion < 0x03)
|
||||
{
|
||||
header.iStyle = style;
|
||||
header.iTrack = track;
|
||||
}
|
||||
|
||||
if (header.iReplayVersion < 0x05)
|
||||
{
|
||||
header.fTickrate = (1.0 / GetTickInterval()); // just assume it's our own tickrate...
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
stock void WriteReplayHeader(File fFile, int style, int track, float time, int steamid, int preframes, int postframes, float fZoneOffset[2], int iSize, float tickrate, const char[] sMap)
|
||||
{
|
||||
fFile.WriteLine("%d:" ... REPLAY_FORMAT_FINAL, REPLAY_FORMAT_SUBVERSION);
|
||||
|
||||
fFile.WriteString(sMap, true);
|
||||
fFile.WriteInt8(style);
|
||||
fFile.WriteInt8(track);
|
||||
fFile.WriteInt32(preframes);
|
||||
|
||||
fFile.WriteInt32(iSize - preframes - postframes);
|
||||
fFile.WriteInt32(view_as<int>(time));
|
||||
fFile.WriteInt32(steamid);
|
||||
|
||||
fFile.WriteInt32(postframes);
|
||||
fFile.WriteInt32(view_as<int>(tickrate));
|
||||
|
||||
fFile.WriteInt32(view_as<int>(fZoneOffset[0]));
|
||||
fFile.WriteInt32(view_as<int>(fZoneOffset[1]));
|
||||
}
|
||||
|
||||
// file_a is usually used as the wr replay file.
|
||||
// file_b is usually used as the duplicate/backup replay file.
|
||||
stock void WriteReplayFrames(ArrayList playerrecording, int iSize, File file_a, File file_b)
|
||||
{
|
||||
any aFrameData[sizeof(frame_t)];
|
||||
any aWriteData[sizeof(frame_t) * REPLAY_FRAMES_PER_WRITE];
|
||||
int iFramesWritten = 0;
|
||||
|
||||
for(int i = 0; i < iSize; i++)
|
||||
{
|
||||
playerrecording.GetArray(i, aFrameData, sizeof(frame_t));
|
||||
|
||||
for(int j = 0; j < sizeof(frame_t); j++)
|
||||
{
|
||||
aWriteData[(sizeof(frame_t) * iFramesWritten) + j] = aFrameData[j];
|
||||
}
|
||||
|
||||
if(++iFramesWritten == REPLAY_FRAMES_PER_WRITE || i == iSize - 1)
|
||||
{
|
||||
if (file_a)
|
||||
{
|
||||
file_a.Write(aWriteData, sizeof(frame_t) * iFramesWritten, 4);
|
||||
}
|
||||
|
||||
if (file_b)
|
||||
{
|
||||
file_b.Write(aWriteData, sizeof(frame_t) * iFramesWritten, 4);
|
||||
}
|
||||
|
||||
iFramesWritten = 0;
|
||||
}
|
||||
}
|
||||
}
|
499
scripting/include/shavit/replay-playback.inc
Normal file
499
scripting/include/shavit/replay-playback.inc
Normal file
|
@ -0,0 +1,499 @@
|
|||
/*
|
||||
* shavit's Timer - replay-playback.inc file
|
||||
* by: shavit
|
||||
*
|
||||
* This file is part of shavit's Timer.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined _shavit_replay_playback_included
|
||||
#endinput
|
||||
#endif
|
||||
#define _shavit_replay_playback_included
|
||||
|
||||
#include <shavit/replay-file>
|
||||
|
||||
enum //ReplayStatus
|
||||
{
|
||||
Replay_Start,
|
||||
Replay_Running,
|
||||
Replay_End,
|
||||
Replay_Idle
|
||||
};
|
||||
|
||||
enum //ReplayBotType
|
||||
{
|
||||
Replay_Central,
|
||||
Replay_Looping, // these are the ones that loop styles, tracks, and (eventually) stages...
|
||||
Replay_Dynamic, // these are bots that spawn on !replay when the central bot is taken
|
||||
Replay_Prop, // A prop entity that is being used as a replay...
|
||||
};
|
||||
|
||||
/**
|
||||
* Called when replay playback starts.
|
||||
* Will be called twice for every replay bot unless the replay is canceled before the second call. Use `delay_elapsed` to check for the first & second time.
|
||||
*
|
||||
* @param ent Entity index for the replay.
|
||||
* @param type The type of replay. Replay_Prop means `ent` is not a fakeclient, but instead a prop.
|
||||
* @param delay_elapsed `false` when the replay bot just spawned but before the start delay has elapsed. `true` when the start delay has elapsed.
|
||||
* @noreturn
|
||||
*/
|
||||
forward void Shavit_OnReplayStart(int ent, int type, bool delay_elapsed);
|
||||
|
||||
/**
|
||||
* Called when replay playback ends.
|
||||
* Will be called twice for most replay bots unless the replay bot is canceled before it finishes. See `actually_finished`.
|
||||
*
|
||||
* @param ent Entity index for the replay.
|
||||
* @param type The type of replay. Replay_Prop means `ent` is not a fakeclient, but instead a prop.
|
||||
* @param actually_finished `false` when the replay runs out of frames and is starting the timer to despawn. `true` when the replay bot is about to despawn. `true` will always run.
|
||||
* @noreturn
|
||||
*/
|
||||
forward void Shavit_OnReplayEnd(int ent, int type, bool actually_finished);
|
||||
|
||||
/**
|
||||
* Called when all replays files have been loaded.
|
||||
*
|
||||
* @noreturn
|
||||
*/
|
||||
forward void Shavit_OnReplaysLoaded();
|
||||
|
||||
/**
|
||||
* Deletes all replays for the specified map.
|
||||
* Plugin will refresh if map is currently on.
|
||||
*
|
||||
* @param map Map name.
|
||||
* @noreturn
|
||||
*/
|
||||
native void Shavit_Replay_DeleteMap(const char[] map);
|
||||
|
||||
/**
|
||||
* Deletes the specified replay file.
|
||||
* Replay data will be unloaded if necessary.
|
||||
*
|
||||
* @param map Map display name.
|
||||
* @param style Bhop style.
|
||||
* @param track Timer track.
|
||||
* @param accountid Account ID to validate against, 0 to skip validation.
|
||||
* @return true if replay existed, false if the steam id didn't match or the file didn't exist.
|
||||
*/
|
||||
native bool Shavit_DeleteReplay(const char[] map, int style, int track, int accountid = 0);
|
||||
|
||||
/**
|
||||
* Retrieves the engine time of the replay bot's first frame.
|
||||
*
|
||||
* @param entity Entity index.
|
||||
* @return The engine time of the replay bot's first frame.
|
||||
*/
|
||||
native float Shavit_GetReplayBotFirstFrameTime(int entity);
|
||||
|
||||
/**
|
||||
* Retrieve the replay bot's entity index.
|
||||
*
|
||||
* @param style Style you want. -1 if you want the central bot. If no central bot, the first bot it finds it used.
|
||||
* @param track Track you want. -1 if you want the central bot. If no central bot, the first bot it finds it used.
|
||||
* @return Client index for the replay bot. -1 if not found.
|
||||
*/
|
||||
native int Shavit_GetReplayBotIndex(int style, int track);
|
||||
|
||||
/**
|
||||
* Retrieve the style being played by the replay bot.
|
||||
*
|
||||
* @param entity Entity index.
|
||||
* @return Style being played by the replay bot. -1 if the replay bot is idle.
|
||||
*/
|
||||
native int Shavit_GetReplayBotStyle(int entity);
|
||||
|
||||
/**
|
||||
* Retrieve the timer track being played by the replay bot.
|
||||
*
|
||||
* @param entity entity index.
|
||||
* @return Timer track replayed by the bot. -1 if the replay bot is idle.
|
||||
*/
|
||||
native int Shavit_GetReplayBotTrack(int entity);
|
||||
|
||||
/**
|
||||
* Gets the replay bot type setting of the server.
|
||||
*
|
||||
* @return See ReplayBotType enum.
|
||||
*/
|
||||
native int Shavit_GetReplayBotType();
|
||||
|
||||
/**
|
||||
* Retrieve the replay bot's current played frame.
|
||||
*
|
||||
* @param entity Entity index.
|
||||
* @return Current played frame.
|
||||
*/
|
||||
native int Shavit_GetReplayBotCurrentFrame(int entity);
|
||||
|
||||
/**
|
||||
* Retrieves the client who started the replay.
|
||||
*
|
||||
* @param Replay entity.
|
||||
* @return Client index of starter. Can be 0
|
||||
*/
|
||||
native int Shavit_GetReplayStarter(int ent);
|
||||
|
||||
/**
|
||||
* Retrieves the replay's buttons for its current tick.
|
||||
* Really, this is only useful for things like replay props.
|
||||
*
|
||||
* @param Replay entity.
|
||||
* @param anglediff The angle difference between the previous and current y angles.
|
||||
*
|
||||
* @return buttons
|
||||
*/
|
||||
native int Shavit_GetReplayButtons(int ent, float& anglediff);
|
||||
|
||||
/**
|
||||
* Retrieves the replay's entity flags for its current tick.
|
||||
* @param Replay entity.
|
||||
* @return Entity flags
|
||||
*/
|
||||
native int Shavit_GetReplayEntityFlags(int ent);
|
||||
|
||||
/**
|
||||
* Retrieves a replay's frame count.
|
||||
*
|
||||
* @param style Style.
|
||||
* @param track Track.
|
||||
* @return Frame count.
|
||||
*/
|
||||
native int Shavit_GetReplayFrameCount(int style, int track);
|
||||
|
||||
/**
|
||||
* Retrieves a replay's pre-run frame count.
|
||||
*
|
||||
* @param style Style.
|
||||
* @param track Track.
|
||||
* @return Frame count.
|
||||
*/
|
||||
native int Shavit_GetReplayPreFrames(int style, int track);
|
||||
|
||||
/**
|
||||
* Retrieves a replay's post-run frame count.
|
||||
*
|
||||
* @param style Style.
|
||||
* @param track Track.
|
||||
* @return Frame count.
|
||||
*/
|
||||
native int Shavit_GetReplayPostFrames(int style, int track);
|
||||
|
||||
/**
|
||||
* Retrieves the frame count from the currently running replay bot's frame_cache_t.
|
||||
*
|
||||
* @param bot Replay bot entity.
|
||||
* @return Frame count.
|
||||
*/
|
||||
native int Shavit_GetReplayCacheFrameCount(int bot);
|
||||
|
||||
/**
|
||||
* Retrieves the pre-run frame count from the currently running replay bot's frame_cache_t.
|
||||
*
|
||||
* @param bot Replay bot entity.
|
||||
* @return Frame count.
|
||||
*/
|
||||
native int Shavit_GetReplayCachePreFrames(int bot);
|
||||
|
||||
/**
|
||||
* Retrieves the post-run frame count from the currently running replay bot's frame_cache_t.
|
||||
*
|
||||
* @param bot Replay bot entity.
|
||||
* @return Frame count.
|
||||
*/
|
||||
native int Shavit_GetReplayCachePostFrames(int bot);
|
||||
|
||||
/**
|
||||
* Retrieves the replay data for the given style and track.
|
||||
*
|
||||
* @param style Style.
|
||||
* @param track Track.
|
||||
* @param cheapCloneHandle False means we duplicate the frames (ArrayList.Clone). True means we clone the handle to the frames (CloneHandle).
|
||||
*
|
||||
* @return ArrayList with proper replay data, or null if there is no recorded data. Delete this handle when you're done with it.
|
||||
*/
|
||||
native ArrayList Shavit_GetReplayFrames(int style, int track, bool cheapCloneHandle=false);
|
||||
|
||||
/**
|
||||
* Retrieves a replay's total length in seconds.
|
||||
*
|
||||
* @param style Style.
|
||||
* @param track Track.
|
||||
* @return Replay length.
|
||||
*/
|
||||
native float Shavit_GetReplayLength(int style, int track);
|
||||
|
||||
/**
|
||||
* Retrieves the replay's total length in seconds from the currently running replay bot's frame_cache_t.
|
||||
*
|
||||
* @param bot Replay bot entity.
|
||||
* @return Replay length.
|
||||
*/
|
||||
native float Shavit_GetReplayCacheLength(int bot);
|
||||
|
||||
/**
|
||||
* Retrieves an actively playing replay's time.
|
||||
*
|
||||
* @param entity Entity index.
|
||||
* @return The bot's current time in the replay.
|
||||
*/
|
||||
native float Shavit_GetReplayTime(int entity);
|
||||
|
||||
/**
|
||||
* Retrieves a replay holder's name.
|
||||
*
|
||||
* @param style Style.
|
||||
* @param track Track.
|
||||
* @param buffer Buffer string.
|
||||
* @param length String length.
|
||||
* @noreturn
|
||||
*/
|
||||
native void Shavit_GetReplayName(int style, int track, char[] buffer, int length);
|
||||
|
||||
/**
|
||||
* Retrieves a replay holder's name from an active replay bot.
|
||||
*
|
||||
* @param bot Bot.
|
||||
* @param buffer Buffer string.
|
||||
* @param length String length.
|
||||
* @noreturn
|
||||
*/
|
||||
native void Shavit_GetReplayCacheName(int bot, char[] buffer, int length);
|
||||
|
||||
/**
|
||||
* Retrieves the folder path where the replay files are saved.
|
||||
*
|
||||
* @param buffer Buffer string.
|
||||
* @param length String length.
|
||||
* @noreturn
|
||||
*/
|
||||
native void Shavit_GetReplayFolderPath(char[] buffer, int length);
|
||||
|
||||
/**
|
||||
* Checks if there's loaded replay data for a bhop style or not.
|
||||
*
|
||||
* @param style Style.
|
||||
* @param track Track.
|
||||
* @return Boolean value of if there's loaded replay data.
|
||||
*/
|
||||
native bool Shavit_IsReplayDataLoaded(int style, int track);
|
||||
|
||||
/**
|
||||
* Checks if the given entity is a replay bot (fakeclient) or replay prop.
|
||||
*
|
||||
* @param The entity index to check.
|
||||
*/
|
||||
native bool Shavit_IsReplayEntity(int ent);
|
||||
|
||||
/**
|
||||
* Sets the sReplayName value in the bot's frame_cache_t.
|
||||
* Useful for `Shavit_StartReplayFromFile` and family.
|
||||
*
|
||||
* @param bot The replay bot entity.
|
||||
* @param name The name to use.
|
||||
*/
|
||||
native void Shavit_SetReplayCacheName(int bot, char[] name);
|
||||
|
||||
/**
|
||||
* Starts a replay given a style and track.
|
||||
*
|
||||
* @param style Bhop style.
|
||||
* @param track Timer track.
|
||||
* @param delay Delay until starting. If -1.0, then uses shavit_replay_delay
|
||||
* @param client Client index.
|
||||
* @param bot Bot to play on. Should be of type Replay_Central or Replay_Dynamic. -1 to create new replay bot.
|
||||
* @param type ReplayBotType. Replay_Prop needs `bot` to be -1.
|
||||
* @param ignorelimit Ignore cvar limit for dynamic bots.
|
||||
* @return Replay entity. 0 is returned if couldn't be created.
|
||||
*/
|
||||
native int Shavit_StartReplay(int style, int track, float delay, int client, int bot, int type, bool ignorelimit);
|
||||
|
||||
/**
|
||||
* Starts a replay with a given set of frames.
|
||||
* Useful for playing a replay downloaded from a global WR database...
|
||||
*
|
||||
* @param style Bhop style.
|
||||
* @param track Timer track.
|
||||
* @param delay Delay until starting. If -1.0, then uses shavit_replay_delay
|
||||
* @param client Client index.
|
||||
* @param bot Bot to play on. Should be of type Replay_Central or Replay_Dynamic. -1 to create new replay bot.
|
||||
* @param type ReplayBotType. Replay_Prop needs `bot` to be -1.
|
||||
* @param ignorelimit Ignore cvar limit for dynamic bots.
|
||||
* @param cache frame_cache_t filled with replay info and frames.
|
||||
* @param size sizeof(frame_cache_t). Used to throw errors at you if you don't recompile plugins.
|
||||
* @return Replay entity. 0 is returned if couldn't be created.
|
||||
*/
|
||||
native int Shavit_StartReplayFromFrameCache(int style, int track, float delay, int client, int bot, int type, bool ignorelimit, any[] cache, int size = sizeof(frame_cache_t));
|
||||
|
||||
/**
|
||||
* Starts a replay from a replay file.
|
||||
* Useful for playing a replay downloaded from a global WR database...
|
||||
*
|
||||
* @param style Bhop style.
|
||||
* @param track Timer track.
|
||||
* @param delay Delay until starting. If -1.0, then uses shavit_replay_delay
|
||||
* @param client Client index.
|
||||
* @param bot Bot to play on. Should be of type Replay_Central or Replay_Dynamic. -1 to create new replay bot.
|
||||
* @param type ReplayBotType. Replay_Prop needs `bot` to be -1.
|
||||
* @param ignorelimit Ignore cvar limit for dynamic bots.
|
||||
* @param path File path to replay
|
||||
* @return Replay entity. 0 is returned if couldn't be created.
|
||||
*/
|
||||
native int Shavit_StartReplayFromFile(int style, int track, float delay, int client, int bot, int type, bool ignorelimit, const char[] path);
|
||||
|
||||
/**
|
||||
* Reloads a specific replay into the replay bot cache.
|
||||
* Note: Not guaranteed to work with legacy replay bots.
|
||||
*
|
||||
* @param style Replay style.
|
||||
* @param track Replay track.
|
||||
* @param restart Restart the playback of the replay bot if it's playing?
|
||||
* @param path Path to the replay file. Use `BuildPath(Path_SM, ...)` to generate one. Leave as empty to use default.
|
||||
* @return Was the replay loaded?
|
||||
*/
|
||||
native bool Shavit_ReloadReplay(int style, int track, bool restart, char[] path = "");
|
||||
|
||||
/**
|
||||
* Reloads all of the replays for the map.
|
||||
*
|
||||
* @param restart Restart the playback of the replay bots?
|
||||
* @return Amount of loaded replays.
|
||||
*/
|
||||
native int Shavit_ReloadReplays(bool restart);
|
||||
|
||||
/**
|
||||
* Gets time from replay frame that is closest to client.
|
||||
*
|
||||
* @param client Client index.
|
||||
*
|
||||
* @return Replay time.
|
||||
*/
|
||||
native float Shavit_GetClosestReplayTime(int client);
|
||||
|
||||
/**
|
||||
* Gets the style the client is getting the closest replay time from.
|
||||
*
|
||||
* @param client Client index.
|
||||
*
|
||||
* @return style
|
||||
*/
|
||||
native int Shavit_GetClosestReplayStyle(int client);
|
||||
|
||||
/**
|
||||
* Sets the style to grab the closest replay time from.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param style Style blah.
|
||||
*
|
||||
* @param Style to grab replay time from. -1 to use the client's current style.
|
||||
*
|
||||
* @noreturn
|
||||
*/
|
||||
native void Shavit_SetClosestReplayStyle(int client, int style);
|
||||
|
||||
/**
|
||||
* Gets velocity from replay frame that is closest to client.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param threeD true for 3D velocity difference. false for 2D velocity difference.
|
||||
*
|
||||
* @return Velocity difference from closest replay position.
|
||||
*/
|
||||
native float Shavit_GetClosestReplayVelocityDifference(int client, bool threeD);
|
||||
|
||||
/**
|
||||
* Gets the replay status
|
||||
*
|
||||
* @param Replay bot (or prop) entity
|
||||
*
|
||||
* @return Replay's status
|
||||
*/
|
||||
native int Shavit_GetReplayStatus(int ent);
|
||||
|
||||
/*
|
||||
* Used to find a looping replay bot from the loop config name.
|
||||
*
|
||||
* @param name Looping bot config name. An example is "Other Styles" from the default set of looping bots in shavit-replay.cfg
|
||||
*
|
||||
* @return The client index of the looping replay bot. -1 if could not find the config name. 0 if could not find the replay bot client.
|
||||
*/
|
||||
native int Shavit_GetLoopingBotByName(const char[] name);
|
||||
|
||||
/*
|
||||
* Retrieves the playback speed of the replay bot.
|
||||
*
|
||||
* @param bot
|
||||
*
|
||||
* @return Should be 0.5, 1.0, or 2.0.
|
||||
*/
|
||||
native float Shavit_GetReplayPlaybackSpeed(int bot);
|
||||
|
||||
|
||||
public SharedPlugin __pl_shavit_replay_playback =
|
||||
{
|
||||
name = "shavit-replay-playback",
|
||||
file = "shavit-replay-playback.smx",
|
||||
#if defined REQUIRE_PLUGIN
|
||||
required = 1
|
||||
#else
|
||||
required = 0
|
||||
#endif
|
||||
};
|
||||
|
||||
#if !defined REQUIRE_PLUGIN
|
||||
public void __pl_shavit_replay_playback_SetNTVOptional()
|
||||
{
|
||||
MarkNativeAsOptional("Shavit_DeleteReplay");
|
||||
MarkNativeAsOptional("Shavit_GetReplayBotCurrentFrame");
|
||||
MarkNativeAsOptional("Shavit_GetReplayBotFirstFrameTime");
|
||||
MarkNativeAsOptional("Shavit_GetReplayBotIndex");
|
||||
MarkNativeAsOptional("Shavit_GetReplayBotStyle");
|
||||
MarkNativeAsOptional("Shavit_GetReplayBotTrack");
|
||||
MarkNativeAsOptional("Shavit_GetReplayBotType");
|
||||
MarkNativeAsOptional("Shavit_GetReplayStarter");
|
||||
MarkNativeAsOptional("Shavit_GetReplayFrameCount");
|
||||
MarkNativeAsOptional("Shavit_GetReplayFrames");
|
||||
MarkNativeAsOptional("Shavit_GetReplayLength");
|
||||
MarkNativeAsOptional("Shavit_GetReplayName");
|
||||
MarkNativeAsOptional("Shavit_GetReplayCacheName");
|
||||
MarkNativeAsOptional("Shavit_GetReplayStatus");
|
||||
MarkNativeAsOptional("Shavit_GetReplayTime");
|
||||
MarkNativeAsOptional("Shavit_IsReplayDataLoaded");
|
||||
MarkNativeAsOptional("Shavit_ReloadReplay");
|
||||
MarkNativeAsOptional("Shavit_ReloadReplays");
|
||||
MarkNativeAsOptional("Shavit_Replay_DeleteMap");
|
||||
MarkNativeAsOptional("Shavit_StartReplay");
|
||||
MarkNativeAsOptional("Shavit_GetClosestReplayTime");
|
||||
MarkNativeAsOptional("Shavit_GetClosestReplayVelocityDifference");
|
||||
MarkNativeAsOptional("Shavit_IsReplayEntity");
|
||||
MarkNativeAsOptional("Shavit_GetReplayButtons");
|
||||
MarkNativeAsOptional("Shavit_GetReplayEntityFlags");
|
||||
MarkNativeAsOptional("Shavit_GetClosestReplayStyle");
|
||||
MarkNativeAsOptional("Shavit_SetClosestReplayStyle");
|
||||
MarkNativeAsOptional("Shavit_GetReplayCacheFrameCount");
|
||||
MarkNativeAsOptional("Shavit_GetReplayCacheLength");
|
||||
MarkNativeAsOptional("Shavit_StartReplayFromFrameCache");
|
||||
MarkNativeAsOptional("Shavit_StartReplayFromFile");
|
||||
MarkNativeAsOptional("Shavit_GetReplayPreFrames");
|
||||
MarkNativeAsOptional("Shavit_GetReplayPostFrames");
|
||||
MarkNativeAsOptional("Shavit_GetReplayCachePreFrames");
|
||||
MarkNativeAsOptional("Shavit_GetReplayCachePostFrames");
|
||||
MarkNativeAsOptional("Shavit_GetLoopingBotByName");
|
||||
MarkNativeAsOptional("Shavit_SetReplayCacheName");
|
||||
MarkNativeAsOptional("Shavit_GetReplayFolderPath");
|
||||
MarkNativeAsOptional("Shavit_GetReplayPlaybackSpeed");
|
||||
}
|
||||
#endif
|
163
scripting/include/shavit/replay-recorder.inc
Normal file
163
scripting/include/shavit/replay-recorder.inc
Normal file
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
* shavit's Timer - replay-recorder.inc file
|
||||
* by: shavit
|
||||
*
|
||||
* This file is part of shavit's Timer.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined _shavit_replay_recorder_included
|
||||
#endinput
|
||||
#endif
|
||||
#define _shavit_replay_recorder_included
|
||||
|
||||
/**
|
||||
* Called when a player finishes a time. Allows you to save a replay even if the run is not a WR.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param style Style the record was done on.
|
||||
* @param time Record time.
|
||||
* @param jumps Jumps amount.
|
||||
* @param strafes Amount of strafes.
|
||||
* @param sync Sync percentage (0.0 to 100.0) or -1.0 when not measured.
|
||||
* @param track Timer track.
|
||||
* @param oldtime The player's best time on the map before this finish.
|
||||
* @param perfs Perfect jump percentage (0.0 to 100.0) or 100.0 when not measured.
|
||||
* @param avgvel Player's average velocity throughout the run.
|
||||
* @param maxvel Player's highest reached velocity.
|
||||
* @param timestamp System time of when player finished.
|
||||
* @param isbestreplay If the time is the new replay.
|
||||
* @param istoolong If the time is too long to save a replay if the time is a WR. Note: replays WON'T be full length if this is true.
|
||||
*
|
||||
* @return Return Plugin_Changed (or higher) to cause a copy of the replay to be saved. Return Plugin_Continue otherwise.
|
||||
*/
|
||||
forward Action Shavit_ShouldSaveReplayCopy(int client, int style, float time, int jumps, int strafes, float sync, int track, float oldtime, float perfs, float avgvel, float maxvel, int timestamp, bool isbestreplay, bool istoolong);
|
||||
|
||||
/**
|
||||
* Called when either a WR replay or a copy of a replay has been saved.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param style Style the record was done on.
|
||||
* @param time Record time.
|
||||
* @param jumps Jumps amount.
|
||||
* @param strafes Amount of strafes.
|
||||
* @param sync Sync percentage (0.0 to 100.0) or -1.0 when not measured.
|
||||
* @param track Timer track.
|
||||
* @param oldtime The player's best time on the map before this finish.
|
||||
* @param perfs Perfect jump percentage (0.0 to 100.0) or 100.0 when not measured.
|
||||
* @param avgvel Player's average velocity throughout the run.
|
||||
* @param maxvel Player's highest reached velocity.
|
||||
* @param timestamp System time of when player finished.
|
||||
* @param isbestreplay If the time is the new replay.
|
||||
* @param istoolong If the time is too long to save a replay if the time is a WR. Note: replays WON'T be full length if this is true.
|
||||
* @param iscopy If the path points to a copy of the replay.
|
||||
* @param replaypath Path to the saved replay.
|
||||
* @param frames ArrayList of the player's frames in the replay.
|
||||
* @param preframes The number of preframes in the replay.
|
||||
* @param postframes The number of postframes in the replay.
|
||||
* @param name Player's name at the time of the replay.
|
||||
*
|
||||
* @noreturn
|
||||
*/
|
||||
forward void Shavit_OnReplaySaved(int client, int style, float time, int jumps, int strafes, float sync, int track, float oldtime, float perfs, float avgvel, float maxvel, int timestamp, bool isbestreplay, bool istoolong, bool iscopy, const char[] replaypath, ArrayList frames, int preframes, int postframes, const char[] name);
|
||||
|
||||
/**
|
||||
* Retrieves a client's frame count.
|
||||
*
|
||||
* @param client Client Index.
|
||||
*
|
||||
* @return Current number of frames.
|
||||
*/
|
||||
native int Shavit_GetClientFrameCount(int client);
|
||||
|
||||
/*
|
||||
* returns the number of preframes in the players current run.
|
||||
*
|
||||
* @param client Client index
|
||||
*
|
||||
* @return Preframe count
|
||||
*/
|
||||
native int Shavit_GetPlayerPreFrames(int client);
|
||||
|
||||
/*
|
||||
* Sets player's preframe length.
|
||||
*
|
||||
* @param client Client index
|
||||
* @param PreFrame PreFrame length
|
||||
* @param TimerPreFrame Timer start frame length
|
||||
*
|
||||
* @noreturn
|
||||
*/
|
||||
native void Shavit_SetPlayerPreFrames(int client, int PreFrame);
|
||||
|
||||
/**
|
||||
* Sets a player's replay recording frames from a provided ArrayList.
|
||||
* To be used by save states/TAS etc.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param data ArrayList with proper replay data.
|
||||
* @param cheapCloneHandle False means we duplicate the frames (ArrayList.Clone). True means we clone the handle to the frames (CloneHandle).
|
||||
*
|
||||
* @noreturn
|
||||
*/
|
||||
native void Shavit_SetReplayData(int client, ArrayList data, bool cheapCloneHandle=false);
|
||||
|
||||
/**
|
||||
* Saves a player's replay recording frames (if exists) into an ArrayList.
|
||||
* To be used by save states/TAS etc.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param cheapCloneHandle False means we duplicate the frames (Arraylist.Clone). True means we clone the handle to the frames (CloneHandle). This is going to be used for peristent-data in shavit-misc so we don't allocate duplicate memory needlessly.
|
||||
*
|
||||
* @return ArrayList with proper replay data, or null if the player has no recorded data. Delete this handle when you're done with it.
|
||||
*/
|
||||
native ArrayList Shavit_GetReplayData(int client, bool cheapCloneHandle=false);
|
||||
|
||||
/**
|
||||
* Hijack the replay data so that this view angle will be used for the next ticks.
|
||||
* Use case is to make segmented runs look smoother.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param pitch Vertical view angle.
|
||||
* @param yaw Horizontal view angle.
|
||||
* @param ticks The number of ticks to hijack angles for. -1 will calculate the number of ticks based on the client's latency.
|
||||
* @param keeponstart Whether to continue hijacking angles even after someone restarts.
|
||||
*
|
||||
* @noreturn
|
||||
*/
|
||||
native void Shavit_HijackAngles(int client, float pitch, float yaw, int ticks = -1, bool keeponstart = false);
|
||||
|
||||
public SharedPlugin __pl_shavit_replay_recorder =
|
||||
{
|
||||
name = "shavit-replay-recorder",
|
||||
file = "shavit-replay-recorder.smx",
|
||||
#if defined REQUIRE_PLUGIN
|
||||
required = 1
|
||||
#else
|
||||
required = 0
|
||||
#endif
|
||||
};
|
||||
|
||||
#if !defined REQUIRE_PLUGIN
|
||||
public void __pl_shavit_replay_recorder_SetNTVOptional()
|
||||
{
|
||||
MarkNativeAsOptional("Shavit_GetClientFrameCount");
|
||||
MarkNativeAsOptional("Shavit_GetPlayerPreFrames");
|
||||
MarkNativeAsOptional("Shavit_SetPlayerPreFrames");
|
||||
MarkNativeAsOptional("Shavit_GetReplayData");
|
||||
MarkNativeAsOptional("Shavit_HijackAngles");
|
||||
MarkNativeAsOptional("Shavit_SetReplayData");
|
||||
}
|
||||
#endif
|
97
scripting/include/shavit/replay-stocks.sp
Normal file
97
scripting/include/shavit/replay-stocks.sp
Normal file
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* shavit's Timer - stocks used by the replay plugins
|
||||
* by: shavit
|
||||
*
|
||||
* This file is part of shavit's Timer.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
stock bool Shavit_ReplayEnabledStyle(int style)
|
||||
{
|
||||
return !Shavit_GetStyleSettingBool(style, "unranked") && !Shavit_GetStyleSettingBool(style, "noreplay");
|
||||
}
|
||||
|
||||
stock void Shavit_GetReplayFilePath(int style, int track, const char[] mapname, const char[] replayfolder, char sPath[PLATFORM_MAX_PATH])
|
||||
{
|
||||
char sTrack[4];
|
||||
FormatEx(sTrack, 4, "_%d", track);
|
||||
FormatEx(sPath, PLATFORM_MAX_PATH, "%s/%d/%s%s.replay", replayfolder, style, mapname, (track > 0)? sTrack:"");
|
||||
}
|
||||
|
||||
stock bool Shavit_GetReplayFolderPath_Stock(char buffer[PLATFORM_MAX_PATH])
|
||||
{
|
||||
char sPath[PLATFORM_MAX_PATH];
|
||||
BuildPath(Path_SM, sPath, PLATFORM_MAX_PATH, "configs/shavit-replay.cfg");
|
||||
|
||||
KeyValues kv = new KeyValues("shavit-replay");
|
||||
|
||||
if (!kv.ImportFromFile(sPath))
|
||||
{
|
||||
delete kv;
|
||||
return false;
|
||||
}
|
||||
|
||||
kv.GetString("replayfolder", buffer, PLATFORM_MAX_PATH, "{SM}/data/replaybot");
|
||||
|
||||
if (StrContains(buffer, "{SM}") != -1)
|
||||
{
|
||||
ReplaceString(buffer, PLATFORM_MAX_PATH, "{SM}/", "");
|
||||
BuildPath(Path_SM, buffer, PLATFORM_MAX_PATH, "%s", buffer);
|
||||
}
|
||||
|
||||
delete kv;
|
||||
return true;
|
||||
}
|
||||
|
||||
stock void Shavit_Replay_CreateDirectories(const char[] sReplayFolder, int styles)
|
||||
{
|
||||
if (!DirExists(sReplayFolder) && !CreateDirectory(sReplayFolder, 511))
|
||||
{
|
||||
SetFailState("Failed to create replay folder (%s). Make sure you have file permissions", sReplayFolder);
|
||||
}
|
||||
|
||||
char sPath[PLATFORM_MAX_PATH];
|
||||
FormatEx(sPath, PLATFORM_MAX_PATH, "%s/copy", sReplayFolder);
|
||||
|
||||
if (!DirExists(sPath) && !CreateDirectory(sPath, 511))
|
||||
{
|
||||
SetFailState("Failed to create replay copy folder (%s). Make sure you have file permissions", sPath);
|
||||
}
|
||||
|
||||
for(int i = 0; i < styles; i++)
|
||||
{
|
||||
if (!Shavit_ReplayEnabledStyle(i))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
FormatEx(sPath, PLATFORM_MAX_PATH, "%s/%d", sReplayFolder, i);
|
||||
|
||||
if (!DirExists(sPath) && !CreateDirectory(sPath, 511))
|
||||
{
|
||||
SetFailState("Failed to create replay style folder (%s). Make sure you have file permissions", sPath);
|
||||
}
|
||||
}
|
||||
|
||||
// Test to see if replay file creation even works...
|
||||
FormatEx(sPath, sizeof(sPath), "%s/0/faketestfile_69.replay", sReplayFolder);
|
||||
File fTest = OpenFile(sPath, "wb+");
|
||||
CloseHandle(fTest);
|
||||
|
||||
if (fTest == null)
|
||||
{
|
||||
SetFailState("Failed to write to replay folder (%s). Make sure you have file permissions.", sReplayFolder);
|
||||
}
|
||||
}
|
632
scripting/include/shavit/sql-create-tables-and-migrations.sp
Normal file
632
scripting/include/shavit/sql-create-tables-and-migrations.sp
Normal file
|
@ -0,0 +1,632 @@
|
|||
/*
|
||||
* shavit's Timer - SQL table creation and migrations
|
||||
* by: shavit
|
||||
*
|
||||
* This file is part of shavit's Timer.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
Migration_RemoveWorkshopMaptiers, // 0
|
||||
Migration_RemoveWorkshopMapzones,
|
||||
Migration_RemoveWorkshopPlayertimes,
|
||||
Migration_LastLoginIndex,
|
||||
Migration_RemoveCountry,
|
||||
Migration_ConvertIPAddresses, // 5
|
||||
Migration_ConvertSteamIDsUsers,
|
||||
Migration_ConvertSteamIDsPlayertimes,
|
||||
Migration_ConvertSteamIDsChat,
|
||||
Migration_PlayertimesDateToInt,
|
||||
Migration_AddZonesFlagsAndData, // 10
|
||||
Migration_AddPlayertimesCompletions,
|
||||
Migration_AddCustomChatAccess,
|
||||
Migration_AddPlayertimesExactTimeInt,
|
||||
Migration_FixOldCompletionCounts, // old completions accidentally started at 2
|
||||
Migration_AddPrebuiltToMapZonesTable, // 15
|
||||
Migration_AddPlaytime,
|
||||
// sorry, this is kind of dumb but it's better than trying to manage which ones have
|
||||
// finished and which tables exist etc etc in a transaction or a completion counter...
|
||||
Migration_Lowercase_maptiers,
|
||||
Migration_Lowercase_mapzones,
|
||||
Migration_Lowercase_playertimes,
|
||||
Migration_Lowercase_stagetimeswr, // 20
|
||||
Migration_Lowercase_startpositions,
|
||||
Migration_AddPlayertimesPointsCalcedFrom, // points calculated from wr float added to playertimes
|
||||
Migration_RemovePlayertimesPointsCalcedFrom, // lol
|
||||
MIGRATIONS_END
|
||||
};
|
||||
|
||||
static Database2 gH_SQL;
|
||||
static bool gB_MySQL;
|
||||
static char gS_SQLPrefix[32];
|
||||
|
||||
int gI_MigrationsRequired;
|
||||
int gI_MigrationsFinished;
|
||||
|
||||
char gS_TableNames[][32] = {
|
||||
"users",
|
||||
"migrations",
|
||||
"maptiers",
|
||||
"styleplaytime",
|
||||
"playertimes",
|
||||
"stagetimeswr",
|
||||
"stagetimespb",
|
||||
"wrs_min",
|
||||
"wrs",
|
||||
"mapzones",
|
||||
"startpositions",
|
||||
};
|
||||
|
||||
public void RunOnDatabaseLoadedForward()
|
||||
{
|
||||
static GlobalForward hOnDatabasedLoaded;
|
||||
|
||||
if (hOnDatabasedLoaded == null)
|
||||
{
|
||||
hOnDatabasedLoaded = new GlobalForward("Shavit_OnDatabaseLoaded", ET_Ignore);
|
||||
}
|
||||
|
||||
Call_StartForward(hOnDatabasedLoaded);
|
||||
Call_Finish(hOnDatabasedLoaded);
|
||||
}
|
||||
|
||||
public void SQL_CreateTables(Database2 hSQL, const char[] prefix, bool mysql)
|
||||
{
|
||||
gH_SQL = hSQL;
|
||||
gB_MySQL = mysql;
|
||||
strcopy(gS_SQLPrefix, sizeof(gS_SQLPrefix), prefix);
|
||||
|
||||
Transaction2 hTrans = new Transaction2();
|
||||
|
||||
char sQuery[2048];
|
||||
char sOptionalINNODB[16];
|
||||
|
||||
if (gB_MySQL)
|
||||
{
|
||||
sOptionalINNODB = "ENGINE=INNODB";
|
||||
}
|
||||
|
||||
//
|
||||
//// shavit-core
|
||||
//
|
||||
|
||||
if (gB_MySQL)
|
||||
{
|
||||
FormatEx(sQuery, sizeof(sQuery),
|
||||
"CREATE TABLE IF NOT EXISTS `%susers` (`auth` INT NOT NULL, `name` VARCHAR(32) COLLATE 'utf8mb4_general_ci', `ip` INT, `lastlogin` INT NOT NULL DEFAULT -1, `points` FLOAT NOT NULL DEFAULT 0, `playtime` FLOAT NOT NULL DEFAULT 0, PRIMARY KEY (`auth`), INDEX `points` (`points`), INDEX `lastlogin` (`lastlogin`)) ENGINE=INNODB;",
|
||||
gS_SQLPrefix);
|
||||
}
|
||||
else
|
||||
{
|
||||
FormatEx(sQuery, sizeof(sQuery),
|
||||
"CREATE TABLE IF NOT EXISTS `%susers` (`auth` INT NOT NULL PRIMARY KEY, `name` VARCHAR(32), `ip` INT, `lastlogin` INTEGER NOT NULL DEFAULT -1, `points` FLOAT NOT NULL DEFAULT 0, `playtime` FLOAT NOT NULL DEFAULT 0);",
|
||||
gS_SQLPrefix);
|
||||
}
|
||||
|
||||
hTrans.AddQuery2(sQuery);
|
||||
|
||||
FormatEx(sQuery, sizeof(sQuery),
|
||||
"CREATE TABLE IF NOT EXISTS `%smigrations` (`code` TINYINT NOT NULL, PRIMARY KEY (`code`));",
|
||||
gS_SQLPrefix);
|
||||
hTrans.AddQuery2(sQuery);
|
||||
|
||||
//
|
||||
//// shavit-chat
|
||||
//
|
||||
|
||||
if (gB_MySQL)
|
||||
{
|
||||
FormatEx(sQuery, sizeof(sQuery),
|
||||
"CREATE TABLE IF NOT EXISTS `%schat` (`auth` INT NOT NULL, `name` INT NOT NULL DEFAULT 0, `ccname` VARCHAR(128) COLLATE 'utf8mb4_unicode_ci', `message` INT NOT NULL DEFAULT 0, `ccmessage` VARCHAR(16) COLLATE 'utf8mb4_unicode_ci', `ccaccess` INT NOT NULL DEFAULT 0, PRIMARY KEY (`auth`), CONSTRAINT `%sch_auth` FOREIGN KEY (`auth`) REFERENCES `%susers` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE) ENGINE=INNODB;",
|
||||
gS_SQLPrefix, gS_SQLPrefix, gS_SQLPrefix);
|
||||
}
|
||||
else
|
||||
{
|
||||
FormatEx(sQuery, sizeof(sQuery),
|
||||
"CREATE TABLE IF NOT EXISTS `%schat` (`auth` INT NOT NULL, `name` INT NOT NULL DEFAULT 0, `ccname` VARCHAR(128), `message` INT NOT NULL DEFAULT 0, `ccmessage` VARCHAR(16), `ccaccess` INT NOT NULL DEFAULT 0, PRIMARY KEY (`auth`), CONSTRAINT `%sch_auth` FOREIGN KEY (`auth`) REFERENCES `%susers` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE);",
|
||||
gS_SQLPrefix, gS_SQLPrefix, gS_SQLPrefix);
|
||||
}
|
||||
|
||||
hTrans.AddQuery2(sQuery);
|
||||
|
||||
//
|
||||
//// shavit-rankings
|
||||
//
|
||||
|
||||
FormatEx(sQuery, sizeof(sQuery),
|
||||
"CREATE TABLE IF NOT EXISTS `%smaptiers` (`map` VARCHAR(255) NOT NULL, `tier` INT NOT NULL DEFAULT 1, PRIMARY KEY (`map`)) %s;",
|
||||
gS_SQLPrefix, sOptionalINNODB);
|
||||
hTrans.AddQuery2(sQuery);
|
||||
|
||||
//
|
||||
//// shavit-stats
|
||||
//
|
||||
|
||||
FormatEx(sQuery, sizeof(sQuery),
|
||||
"CREATE TABLE IF NOT EXISTS `%sstyleplaytime` (`auth` INT NOT NULL, `style` TINYINT NOT NULL, `playtime` FLOAT NOT NULL, PRIMARY KEY (`auth`, `style`));",
|
||||
gS_SQLPrefix);
|
||||
hTrans.AddQuery2(sQuery);
|
||||
|
||||
//
|
||||
//// shavit-wr
|
||||
//
|
||||
|
||||
if (gB_MySQL)
|
||||
{
|
||||
FormatEx(sQuery, sizeof(sQuery),
|
||||
"CREATE TABLE IF NOT EXISTS `%splayertimes` (`id` INT NOT NULL AUTO_INCREMENT, `style` TINYINT NOT NULL DEFAULT 0, `track` TINYINT NOT NULL DEFAULT 0, `time` FLOAT NOT NULL, `auth` INT NOT NULL, `map` VARCHAR(255) NOT NULL, `points` FLOAT NOT NULL DEFAULT 0, `exact_time_int` INT DEFAULT 0, `jumps` INT, `date` INT, `strafes` INT, `sync` FLOAT, `perfs` FLOAT DEFAULT 0, `completions` SMALLINT DEFAULT 1, PRIMARY KEY (`id`), INDEX `map` (`map`, `style`, `track`, `time`), INDEX `auth` (`auth`, `date`, `points`), INDEX `time` (`time`), INDEX `map2` (`map`)) ENGINE=INNODB;",
|
||||
gS_SQLPrefix);
|
||||
}
|
||||
else
|
||||
{
|
||||
// id style track time auth map points exact_time_int
|
||||
FormatEx(sQuery, sizeof(sQuery),
|
||||
"CREATE TABLE IF NOT EXISTS `%splayertimes` (`id` INTEGER PRIMARY KEY, `style` TINYINT NOT NULL DEFAULT 0, `track` TINYINT NOT NULL DEFAULT 0, `time` FLOAT NOT NULL, `auth` INT NOT NULL, `map` VARCHAR(255) NOT NULL, `points` FLOAT NOT NULL DEFAULT 0, `exact_time_int` INT DEFAULT 0, `jumps` INT, `date` INT, `strafes` INT, `sync` FLOAT, `perfs` FLOAT DEFAULT 0, `completions` SMALLINT DEFAULT 1);",
|
||||
gS_SQLPrefix);
|
||||
}
|
||||
|
||||
hTrans.AddQuery2(sQuery);
|
||||
|
||||
FormatEx(sQuery, sizeof(sQuery),
|
||||
"CREATE TABLE IF NOT EXISTS `%sstagetimeswr` (`style` TINYINT NOT NULL, `track` TINYINT NOT NULL DEFAULT 0, `map` VARCHAR(255) NOT NULL, `stage` TINYINT NOT NULL, `auth` INT NOT NULL, `time` FLOAT NOT NULL, PRIMARY KEY (`style`, `track`, `map`, `stage`)) %s;",
|
||||
gS_SQLPrefix, sOptionalINNODB);
|
||||
hTrans.AddQuery2(sQuery);
|
||||
|
||||
FormatEx(sQuery, sizeof(sQuery),
|
||||
"CREATE TABLE IF NOT EXISTS `%sstagetimespb` (`style` TINYINT NOT NULL, `track` TINYINT NOT NULL DEFAULT 0, `map` VARCHAR(255) NOT NULL, `stage` TINYINT NOT NULL, `auth` INT NOT NULL, `time` FLOAT NOT NULL, PRIMARY KEY (`style`, `track`, `auth`, `map`, `stage`)) %s;",
|
||||
gS_SQLPrefix, sOptionalINNODB);
|
||||
hTrans.AddQuery2(sQuery);
|
||||
|
||||
FormatEx(sQuery, sizeof(sQuery),
|
||||
"%s %swrs_min AS SELECT MIN(time) time, map, track, style FROM %splayertimes GROUP BY map, track, style;",
|
||||
gB_MySQL ? "CREATE OR REPLACE VIEW" : "CREATE VIEW IF NOT EXISTS",
|
||||
gS_SQLPrefix, gS_SQLPrefix);
|
||||
hTrans.AddQuery2(sQuery);
|
||||
|
||||
FormatEx(sQuery, sizeof(sQuery),
|
||||
"%s %swrs AS SELECT a.* FROM %splayertimes a JOIN %swrs_min b ON a.time = b.time AND a.map = b.map AND a.track = b.track AND a.style = b.style;",
|
||||
gB_MySQL ? "CREATE OR REPLACE VIEW" : "CREATE VIEW IF NOT EXISTS",
|
||||
gS_SQLPrefix, gS_SQLPrefix, gS_SQLPrefix);
|
||||
hTrans.AddQuery2(sQuery);
|
||||
|
||||
//
|
||||
//// shavit-wr
|
||||
//
|
||||
|
||||
FormatEx(sQuery, sizeof(sQuery),
|
||||
"CREATE TABLE IF NOT EXISTS `%smapzones` (`id` INT AUTO_INCREMENT, `map` VARCHAR(255) NOT NULL, `type` INT, `corner1_x` FLOAT, `corner1_y` FLOAT, `corner1_z` FLOAT, `corner2_x` FLOAT, `corner2_y` FLOAT, `corner2_z` FLOAT, `destination_x` FLOAT NOT NULL DEFAULT 0, `destination_y` FLOAT NOT NULL DEFAULT 0, `destination_z` FLOAT NOT NULL DEFAULT 0, `track` INT NOT NULL DEFAULT 0, `flags` INT NOT NULL DEFAULT 0, `data` INT NOT NULL DEFAULT 0, `prebuilt` BOOL, PRIMARY KEY (`id`)) %s;",
|
||||
gS_SQLPrefix, sOptionalINNODB);
|
||||
hTrans.AddQuery2(sQuery);
|
||||
|
||||
FormatEx(sQuery, sizeof(sQuery),
|
||||
"CREATE TABLE IF NOT EXISTS `%sstartpositions` (`auth` INTEGER NOT NULL, `track` TINYINT NOT NULL, `map` VARCHAR(255) NOT NULL, `pos_x` FLOAT, `pos_y` FLOAT, `pos_z` FLOAT, `ang_x` FLOAT, `ang_y` FLOAT, `ang_z` FLOAT, `angles_only` BOOL, PRIMARY KEY (`auth`, `track`, `map`)) %s;",
|
||||
gS_SQLPrefix, sOptionalINNODB);
|
||||
hTrans.AddQuery2(sQuery);
|
||||
|
||||
hSQL.Execute(hTrans, Trans_CreateTables_Success, Trans_CreateTables_Error, 0, DBPrio_High);
|
||||
}
|
||||
|
||||
public void Trans_CreateTables_Error(Database db, any data, int numQueries, const char[] error, int failIndex, any[] queryData)
|
||||
{
|
||||
if (0 <= failIndex < sizeof(gS_TableNames))
|
||||
{
|
||||
LogError("Timer (create %s) error. Reason: %s", gS_TableNames[failIndex], error);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogError("Timer (create tables) error. failIndex=%d. numQueries=%d. Reason: %s", failIndex, numQueries, error);
|
||||
}
|
||||
}
|
||||
|
||||
public void Trans_CreateTables_Success(Database db, any data, int numQueries, DBResultSet[] results, any[] queryData)
|
||||
{
|
||||
if (gB_MySQL)
|
||||
{
|
||||
char sQuery[128];
|
||||
FormatEx(sQuery, 128, "SELECT code FROM %smigrations;", gS_SQLPrefix);
|
||||
gH_SQL.Query2(SQL_SelectMigrations_Callback, sQuery, 0, DBPrio_High);
|
||||
}
|
||||
else
|
||||
{
|
||||
RunOnDatabaseLoadedForward();
|
||||
}
|
||||
}
|
||||
|
||||
public void SQL_SelectMigrations_Callback(Database db, DBResultSet results, const char[] error, any data)
|
||||
{
|
||||
if (results == null)
|
||||
{
|
||||
LogError("Timer error! Migrations selection failed. Reason: %s", error);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// this is ugly, i know. but it works and is more elegant than previous solutions so.. let it be =)
|
||||
bool bMigrationApplied[255] = { false, ... };
|
||||
|
||||
while (results.FetchRow())
|
||||
{
|
||||
bMigrationApplied[results.FetchInt(0)] = true;
|
||||
}
|
||||
|
||||
for (int i = 0; i < MIGRATIONS_END; i++)
|
||||
{
|
||||
if (!bMigrationApplied[i])
|
||||
{
|
||||
gI_MigrationsRequired++;
|
||||
PrintToServer("--- Applying database migration %d ---", i);
|
||||
ApplyMigration(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (!gI_MigrationsRequired)
|
||||
{
|
||||
RunOnDatabaseLoadedForward();
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyMigration(int migration)
|
||||
{
|
||||
switch (migration)
|
||||
{
|
||||
case Migration_RemoveWorkshopMaptiers, Migration_RemoveWorkshopMapzones, Migration_RemoveWorkshopPlayertimes: ApplyMigration_RemoveWorkshopPath(migration);
|
||||
case Migration_LastLoginIndex: ApplyMigration_LastLoginIndex();
|
||||
case Migration_RemoveCountry: ApplyMigration_RemoveCountry();
|
||||
case Migration_ConvertIPAddresses: ApplyMigration_ConvertIPAddresses();
|
||||
case Migration_ConvertSteamIDsUsers: ApplyMigration_ConvertSteamIDs();
|
||||
case Migration_ConvertSteamIDsPlayertimes, Migration_ConvertSteamIDsChat: return; // this is confusing, but the above case handles all of them
|
||||
case Migration_PlayertimesDateToInt: ApplyMigration_PlayertimesDateToInt();
|
||||
case Migration_AddZonesFlagsAndData: ApplyMigration_AddZonesFlagsAndData();
|
||||
case Migration_AddPlayertimesCompletions: ApplyMigration_AddPlayertimesCompletions();
|
||||
case Migration_AddCustomChatAccess: ApplyMigration_AddCustomChatAccess();
|
||||
case Migration_AddPlayertimesExactTimeInt: ApplyMigration_AddPlayertimesExactTimeInt();
|
||||
case Migration_FixOldCompletionCounts: ApplyMigration_FixOldCompletionCounts();
|
||||
case Migration_AddPrebuiltToMapZonesTable: ApplyMigration_AddPrebuiltToMapZonesTable();
|
||||
case Migration_AddPlaytime: ApplyMigration_AddPlaytime();
|
||||
case Migration_Lowercase_maptiers: ApplyMigration_LowercaseMaps("maptiers", migration);
|
||||
case Migration_Lowercase_mapzones: ApplyMigration_LowercaseMaps("mapzones", migration);
|
||||
case Migration_Lowercase_playertimes: ApplyMigration_LowercaseMaps("playertimes", migration);
|
||||
case Migration_Lowercase_stagetimeswr: ApplyMigration_LowercaseMaps("stagetimewrs", migration);
|
||||
case Migration_Lowercase_startpositions: ApplyMigration_LowercaseMaps("startpositions", migration);
|
||||
case Migration_AddPlayertimesPointsCalcedFrom: ApplyMigration_AddPlayertimesPointsCalcedFrom();
|
||||
case Migration_RemovePlayertimesPointsCalcedFrom: ApplyMigration_RemovePlayertimesPointsCalcedFrom();
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyMigration_LastLoginIndex()
|
||||
{
|
||||
char sQuery[128];
|
||||
FormatEx(sQuery, 128, "ALTER TABLE `%susers` ADD INDEX `lastlogin` (`lastlogin`);", gS_SQLPrefix);
|
||||
gH_SQL.Query2(SQL_TableMigrationSingleQuery_Callback, sQuery, Migration_LastLoginIndex, DBPrio_High);
|
||||
}
|
||||
|
||||
void ApplyMigration_RemoveCountry()
|
||||
{
|
||||
char sQuery[128];
|
||||
FormatEx(sQuery, 128, "ALTER TABLE `%susers` DROP COLUMN `country`;", gS_SQLPrefix);
|
||||
gH_SQL.Query2(SQL_TableMigrationSingleQuery_Callback, sQuery, Migration_RemoveCountry, DBPrio_High);
|
||||
}
|
||||
|
||||
void ApplyMigration_PlayertimesDateToInt()
|
||||
{
|
||||
char sQuery[128];
|
||||
FormatEx(sQuery, 128, "ALTER TABLE `%splayertimes` CHANGE COLUMN `date` `date` INT;", gS_SQLPrefix);
|
||||
gH_SQL.Query2(SQL_TableMigrationSingleQuery_Callback, sQuery, Migration_PlayertimesDateToInt, DBPrio_High);
|
||||
}
|
||||
|
||||
void ApplyMigration_AddZonesFlagsAndData()
|
||||
{
|
||||
char sQuery[192];
|
||||
FormatEx(sQuery, 192, "ALTER TABLE `%smapzones` ADD COLUMN `flags` INT NULL AFTER `track`, ADD COLUMN `data` INT NULL AFTER `flags`;", gS_SQLPrefix);
|
||||
gH_SQL.Query2(SQL_TableMigrationSingleQuery_Callback, sQuery, Migration_AddZonesFlagsAndData, DBPrio_High);
|
||||
}
|
||||
|
||||
void ApplyMigration_AddPlayertimesCompletions()
|
||||
{
|
||||
char sQuery[192];
|
||||
FormatEx(sQuery, 192, "ALTER TABLE `%splayertimes` ADD COLUMN `completions` SMALLINT DEFAULT 1 AFTER `perfs`;", gS_SQLPrefix);
|
||||
gH_SQL.Query2(SQL_TableMigrationSingleQuery_Callback, sQuery, Migration_AddPlayertimesCompletions, DBPrio_High);
|
||||
}
|
||||
|
||||
void ApplyMigration_AddCustomChatAccess()
|
||||
{
|
||||
char sQuery[192];
|
||||
FormatEx(sQuery, 192, "ALTER TABLE `%schat` ADD COLUMN `ccaccess` INT NOT NULL DEFAULT 0 %s;", gS_SQLPrefix, gB_MySQL ? "AFTER `ccmessage`" : "");
|
||||
gH_SQL.Query2(SQL_TableMigrationSingleQuery_Callback, sQuery, Migration_AddCustomChatAccess, DBPrio_High);
|
||||
}
|
||||
|
||||
void ApplyMigration_AddPlayertimesExactTimeInt()
|
||||
{
|
||||
char sQuery[192];
|
||||
FormatEx(sQuery, 192, "ALTER TABLE `%splayertimes` ADD COLUMN `exact_time_int` INT NOT NULL DEFAULT 0 %s;", gS_SQLPrefix, gB_MySQL ? "AFTER `completions`" : "");
|
||||
gH_SQL.Query2(SQL_TableMigrationSingleQuery_Callback, sQuery, Migration_AddPlayertimesExactTimeInt, DBPrio_High);
|
||||
}
|
||||
|
||||
void ApplyMigration_FixOldCompletionCounts()
|
||||
{
|
||||
char sQuery[192];
|
||||
FormatEx(sQuery, 192, "UPDATE `%splayertimes` SET completions = completions - 1 WHERE completions > 1;", gS_SQLPrefix);
|
||||
gH_SQL.Query2(SQL_TableMigrationSingleQuery_Callback, sQuery, Migration_FixOldCompletionCounts, DBPrio_High);
|
||||
}
|
||||
|
||||
void ApplyMigration_AddPrebuiltToMapZonesTable()
|
||||
{
|
||||
char sQuery[192];
|
||||
FormatEx(sQuery, 192, "ALTER TABLE `%smapzones` ADD COLUMN `prebuilt` BOOL;", gS_SQLPrefix);
|
||||
gH_SQL.Query2(SQL_TableMigrationSingleQuery_Callback, sQuery, Migration_AddPrebuiltToMapZonesTable, DBPrio_High);
|
||||
}
|
||||
|
||||
// double up on this migration because some people may have used shavit-playtime which uses INT but I want FLOAT
|
||||
void ApplyMigration_AddPlaytime()
|
||||
{
|
||||
char sQuery[192];
|
||||
FormatEx(sQuery, 192, "ALTER TABLE `%susers` MODIFY COLUMN `playtime` FLOAT NOT NULL DEFAULT 0;", gS_SQLPrefix);
|
||||
gH_SQL.Query2(SQL_Migration_AddPlaytime2222222_Callback, sQuery, Migration_AddPlaytime, DBPrio_High);
|
||||
}
|
||||
|
||||
public void SQL_Migration_AddPlaytime2222222_Callback(Database db, DBResultSet results, const char[] error, any data)
|
||||
{
|
||||
char sQuery[192];
|
||||
FormatEx(sQuery, 192, "ALTER TABLE `%susers` ADD COLUMN `playtime` FLOAT NOT NULL DEFAULT 0 %s;", gS_SQLPrefix, gB_MySQL ? "AFTER `points`" : "");
|
||||
gH_SQL.Query2(SQL_TableMigrationSingleQuery_Callback, sQuery, Migration_AddPlaytime, DBPrio_High);
|
||||
}
|
||||
|
||||
void ApplyMigration_LowercaseMaps(const char[] table, int migration)
|
||||
{
|
||||
char sQuery[192];
|
||||
FormatEx(sQuery, 192, "UPDATE `%s%s` SET map = LOWER(map);", gS_SQLPrefix, table);
|
||||
gH_SQL.Query2(SQL_TableMigrationSingleQuery_Callback, sQuery, migration, DBPrio_High);
|
||||
}
|
||||
|
||||
void ApplyMigration_AddPlayertimesPointsCalcedFrom()
|
||||
{
|
||||
#if 0
|
||||
char sQuery[192];
|
||||
FormatEx(sQuery, 192, "ALTER TABLE `%splayertimes` ADD COLUMN `points_calced_from` FLOAT NOT NULL DEFAULT 0 %s;", gS_SQLPrefix, gB_MySQL ? "AFTER `points`" : "");
|
||||
gH_SQL.Query2(SQL_TableMigrationSingleQuery_Callback, sQuery, Migration_AddPlayertimesPointsCalcedFrom, DBPrio_High);
|
||||
#else
|
||||
SQL_TableMigrationSingleQuery_Callback(null, null, "", Migration_AddPlayertimesPointsCalcedFrom);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ApplyMigration_RemovePlayertimesPointsCalcedFrom()
|
||||
{
|
||||
char sQuery[192];
|
||||
FormatEx(sQuery, 192, "ALTER TABLE `%splayertimes` DROP COLUMN `points_calced_from`;", gS_SQLPrefix);
|
||||
gH_SQL.Query2(SQL_TableMigrationSingleQuery_Callback, sQuery, Migration_RemovePlayertimesPointsCalcedFrom, DBPrio_High);
|
||||
}
|
||||
|
||||
public void SQL_TableMigrationSingleQuery_Callback(Database db, DBResultSet results, const char[] error, any data)
|
||||
{
|
||||
InsertMigration(data);
|
||||
|
||||
// i hate hardcoding REEEEEEEE
|
||||
if (data == Migration_ConvertSteamIDsChat)
|
||||
{
|
||||
char sQuery[256];
|
||||
// deleting rows that cause data integrity issues
|
||||
FormatEx(sQuery, 256,
|
||||
"DELETE t1 FROM %splayertimes t1 LEFT JOIN %susers t2 ON t1.auth = t2.auth WHERE t2.auth IS NULL;",
|
||||
gS_SQLPrefix, gS_SQLPrefix);
|
||||
gH_SQL.Query2(SQL_TableMigrationIndexing_Callback, sQuery, 0, DBPrio_High);
|
||||
|
||||
#if 0
|
||||
FormatEx(sQuery, 256,
|
||||
"ALTER TABLE `%splayertimes` ADD CONSTRAINT `%spt_auth` FOREIGN KEY (`auth`) REFERENCES `%susers` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE;",
|
||||
gS_SQLPrefix, gS_SQLPrefix, gS_SQLPrefix);
|
||||
gH_SQL.Query2(SQL_TableMigrationIndexing_Callback, sQuery);
|
||||
#endif
|
||||
|
||||
FormatEx(sQuery, 256,
|
||||
"DELETE t1 FROM %schat t1 LEFT JOIN %susers t2 ON t1.auth = t2.auth WHERE t2.auth IS NULL;",
|
||||
gS_SQLPrefix, gS_SQLPrefix);
|
||||
gH_SQL.Query2(SQL_TableMigrationIndexing_Callback, sQuery, 0, DBPrio_High);
|
||||
|
||||
#if 0
|
||||
FormatEx(sQuery, 256,
|
||||
"ALTER TABLE `%schat` ADD CONSTRAINT `%sch_auth` FOREIGN KEY (`auth`) REFERENCES `%susers` (`auth`) ON UPDATE CASCADE ON DELETE CASCADE;",
|
||||
gS_SQLPrefix, gS_SQLPrefix, gS_SQLPrefix);
|
||||
gH_SQL.Query2(SQL_TableMigrationIndexing_Callback, sQuery);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyMigration_ConvertIPAddresses(bool index = true)
|
||||
{
|
||||
char sQuery[128];
|
||||
|
||||
if (index)
|
||||
{
|
||||
FormatEx(sQuery, 128, "ALTER TABLE `%susers` ADD INDEX `ip` (`ip`);", gS_SQLPrefix);
|
||||
gH_SQL.Query2(SQL_TableMigrationIndexing_Callback, sQuery, 0, DBPrio_High);
|
||||
}
|
||||
|
||||
FormatEx(sQuery, 128, "SELECT DISTINCT ip FROM %susers WHERE ip LIKE '%%.%%';", gS_SQLPrefix);
|
||||
gH_SQL.Query2(SQL_TableMigrationIPAddresses_Callback, sQuery);
|
||||
}
|
||||
|
||||
public void SQL_TableMigrationIPAddresses_Callback(Database db, DBResultSet results, const char[] error, DataPack data)
|
||||
{
|
||||
if (results == null || results.RowCount == 0)
|
||||
{
|
||||
InsertMigration(Migration_ConvertIPAddresses);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Transaction2 hTransaction = new Transaction2();
|
||||
int iQueries = 0;
|
||||
|
||||
while (results.FetchRow())
|
||||
{
|
||||
char sIPAddress[32];
|
||||
results.FetchString(0, sIPAddress, 32);
|
||||
|
||||
char sQuery[256];
|
||||
FormatEx(sQuery, 256, "UPDATE %susers SET ip = %d WHERE ip = '%s';", gS_SQLPrefix, IPStringToAddress(sIPAddress), sIPAddress);
|
||||
|
||||
hTransaction.AddQuery2(sQuery);
|
||||
|
||||
if (++iQueries >= 10000)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gH_SQL.Execute(hTransaction, Trans_IPAddressMigrationSuccess, Trans_IPAddressMigrationFailed, iQueries);
|
||||
}
|
||||
|
||||
public void Trans_IPAddressMigrationSuccess(Database db, any data, int numQueries, DBResultSet[] results, any[] queryData)
|
||||
{
|
||||
// too many queries, don't do all at once to avoid server crash due to too many queries in the transaction
|
||||
if (data >= 10000)
|
||||
{
|
||||
ApplyMigration_ConvertIPAddresses(false);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
char sQuery[128];
|
||||
FormatEx(sQuery, 128, "ALTER TABLE `%susers` DROP INDEX `ip`;", gS_SQLPrefix);
|
||||
gH_SQL.Query2(SQL_TableMigrationIndexing_Callback, sQuery, 0, DBPrio_High);
|
||||
|
||||
FormatEx(sQuery, 128, "ALTER TABLE `%susers` CHANGE COLUMN `ip` `ip` INT;", gS_SQLPrefix);
|
||||
gH_SQL.Query2(SQL_TableMigrationSingleQuery_Callback, sQuery, Migration_ConvertIPAddresses, DBPrio_High);
|
||||
}
|
||||
|
||||
public void Trans_IPAddressMigrationFailed(Database db, any data, int numQueries, const char[] error, int failIndex, any[] queryData)
|
||||
{
|
||||
LogError("Timer (core) error! IP address migration failed. Reason: %s", error);
|
||||
}
|
||||
|
||||
void ApplyMigration_ConvertSteamIDs()
|
||||
{
|
||||
char sTables[][] =
|
||||
{
|
||||
"users",
|
||||
"playertimes",
|
||||
"chat"
|
||||
};
|
||||
|
||||
char sQuery[128];
|
||||
FormatEx(sQuery, 128, "ALTER TABLE `%splayertimes` DROP CONSTRAINT `%spt_auth`;", gS_SQLPrefix, gS_SQLPrefix);
|
||||
gH_SQL.Query2(SQL_TableMigrationIndexing_Callback, sQuery, 0, DBPrio_High);
|
||||
|
||||
FormatEx(sQuery, 128, "ALTER TABLE `%schat` DROP CONSTRAINT `%sch_auth`;", gS_SQLPrefix, gS_SQLPrefix);
|
||||
gH_SQL.Query2(SQL_TableMigrationIndexing_Callback, sQuery, 0, DBPrio_High);
|
||||
|
||||
for (int i = 0; i < sizeof(sTables); i++)
|
||||
{
|
||||
DataPack hPack = new DataPack();
|
||||
hPack.WriteCell(Migration_ConvertSteamIDsUsers + i);
|
||||
hPack.WriteString(sTables[i]);
|
||||
|
||||
FormatEx(sQuery, 128, "UPDATE %s%s SET auth = REPLACE(REPLACE(auth, \"[U:1:\", \"\"), \"]\", \"\") WHERE auth LIKE '[%%';", sTables[i], gS_SQLPrefix);
|
||||
gH_SQL.Query2(SQL_TableMigrationSteamIDs_Callback, sQuery, hPack, DBPrio_High);
|
||||
}
|
||||
}
|
||||
|
||||
public void SQL_TableMigrationIndexing_Callback(Database db, DBResultSet results, const char[] error, DataPack data)
|
||||
{
|
||||
// nothing
|
||||
}
|
||||
|
||||
public void SQL_TableMigrationSteamIDs_Callback(Database db, DBResultSet results, const char[] error, DataPack data)
|
||||
{
|
||||
data.Reset();
|
||||
int iMigration = data.ReadCell();
|
||||
char sTable[16];
|
||||
data.ReadString(sTable, 16);
|
||||
delete data;
|
||||
|
||||
char sQuery[128];
|
||||
FormatEx(sQuery, 128, "ALTER TABLE `%s%s` CHANGE COLUMN `auth` `auth` INT;", gS_SQLPrefix, sTable);
|
||||
gH_SQL.Query2(SQL_TableMigrationSingleQuery_Callback, sQuery, iMigration, DBPrio_High);
|
||||
}
|
||||
|
||||
void ApplyMigration_RemoveWorkshopPath(int migration)
|
||||
{
|
||||
char sTables[][] =
|
||||
{
|
||||
"maptiers",
|
||||
"mapzones",
|
||||
"playertimes"
|
||||
};
|
||||
|
||||
DataPack hPack = new DataPack();
|
||||
hPack.WriteCell(migration);
|
||||
hPack.WriteString(sTables[migration]);
|
||||
|
||||
char sQuery[192];
|
||||
FormatEx(sQuery, 192, "SELECT map FROM %s%s WHERE map LIKE 'workshop%%' GROUP BY map;", gS_SQLPrefix, sTables[migration]);
|
||||
gH_SQL.Query2(SQL_TableMigrationWorkshop_Callback, sQuery, hPack, DBPrio_High);
|
||||
}
|
||||
|
||||
public void SQL_TableMigrationWorkshop_Callback(Database db, DBResultSet results, const char[] error, DataPack data)
|
||||
{
|
||||
data.Reset();
|
||||
int iMigration = data.ReadCell();
|
||||
char sTable[16];
|
||||
data.ReadString(sTable, 16);
|
||||
delete data;
|
||||
|
||||
if (results == null || results.RowCount == 0)
|
||||
{
|
||||
// no error logging here because not everyone runs the rankings/wr modules
|
||||
InsertMigration(iMigration);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Transaction2 hTransaction = new Transaction2();
|
||||
|
||||
while (results.FetchRow())
|
||||
{
|
||||
char sMap[PLATFORM_MAX_PATH];
|
||||
results.FetchString(0, sMap, sizeof(sMap));
|
||||
|
||||
char sDisplayMap[PLATFORM_MAX_PATH];
|
||||
GetMapDisplayName(sMap, sDisplayMap, sizeof(sDisplayMap));
|
||||
|
||||
char sQuery[256];
|
||||
FormatEx(sQuery, 256, "UPDATE %s%s SET map = '%s' WHERE map = '%s';", gS_SQLPrefix, sTable, sDisplayMap, sMap);
|
||||
|
||||
hTransaction.AddQuery2(sQuery);
|
||||
}
|
||||
|
||||
gH_SQL.Execute(hTransaction, Trans_WorkshopMigration, INVALID_FUNCTION, iMigration);
|
||||
}
|
||||
|
||||
public void Trans_WorkshopMigration(Database db, any data, int numQueries, DBResultSet[] results, any[] queryData)
|
||||
{
|
||||
InsertMigration(data);
|
||||
}
|
||||
|
||||
void InsertMigration(int migration)
|
||||
{
|
||||
char sQuery[128];
|
||||
FormatEx(sQuery, 128, "INSERT INTO %smigrations (code) VALUES (%d);", gS_SQLPrefix, migration);
|
||||
gH_SQL.Query2(SQL_MigrationApplied_Callback, sQuery, migration);
|
||||
}
|
||||
|
||||
public void SQL_MigrationApplied_Callback(Database db, DBResultSet results, const char[] error, any data)
|
||||
{
|
||||
if (++gI_MigrationsFinished >= gI_MigrationsRequired)
|
||||
{
|
||||
gI_MigrationsRequired = gI_MigrationsFinished = 0;
|
||||
RunOnDatabaseLoadedForward();
|
||||
}
|
||||
}
|
103
scripting/include/shavit/steamid-stocks.inc
Normal file
103
scripting/include/shavit/steamid-stocks.inc
Normal file
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Steam ID handling stocks
|
||||
* by: rtldg
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined _steamid_stocks_included
|
||||
#endinput
|
||||
#endif
|
||||
#define _steamid_stocks_included
|
||||
|
||||
static KeyValues kv = null;
|
||||
|
||||
// Retrieves accountid from STEAM_X:Y:Z, [U:1:123], and 765xxxxxxxxxxxxxx
|
||||
stock int SteamIDToAccountID(const char[] sInput)
|
||||
{
|
||||
char sSteamID[32];
|
||||
strcopy(sSteamID, sizeof(sSteamID), sInput);
|
||||
ReplaceString(sSteamID, 32, "\"", "");
|
||||
TrimString(sSteamID);
|
||||
|
||||
if (StrContains(sSteamID, "STEAM_") != -1)
|
||||
{
|
||||
ReplaceString(sSteamID, 32, "STEAM_", "");
|
||||
|
||||
char parts[3][11];
|
||||
ExplodeString(sSteamID, ":", parts, 3, 11);
|
||||
|
||||
// Let X, Y and Z constants be defined by the SteamID: STEAM_X:Y:Z.
|
||||
// Using the formula W=Z*2+Y, a SteamID can be converted:
|
||||
return StringToInt(parts[2]) * 2 + StringToInt(parts[1]);
|
||||
}
|
||||
else if (StrContains(sSteamID, "U:1:") != -1)
|
||||
{
|
||||
ReplaceString(sSteamID, 32, "[", "");
|
||||
ReplaceString(sSteamID, 32, "U:1:", "");
|
||||
ReplaceString(sSteamID, 32, "]", "");
|
||||
|
||||
return StringToInt(sSteamID);
|
||||
}
|
||||
else if (StrContains(sSteamID, "765") == 0)
|
||||
{
|
||||
return SteamID64ToAccountID(sSteamID);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
stock void AccountIDToSteamID64Num(int accountid, int num[2])
|
||||
{
|
||||
num[0] = accountid;
|
||||
// universe | type | instance
|
||||
num[1] = (1 << 24) | (1 << 20) | 1; // 0x01100001
|
||||
}
|
||||
|
||||
stock void AccountIDToSteamID64(int accountid, char[] buf, int buflen)
|
||||
{
|
||||
int num[2];
|
||||
AccountIDToSteamID64Num(accountid, num);
|
||||
SteamID64ToString(num, buf, buflen);
|
||||
}
|
||||
|
||||
stock void AccountIDToSteamID2(int accountid, char[] buf, int buflen)
|
||||
{
|
||||
FormatEx(buf, buflen, "STEAM_0:%d:%d", accountid&1, (accountid>>1) & 0x7FFFFFFF);
|
||||
}
|
||||
|
||||
stock void AccountIDToSteamID3(int accountid, char[] buf, int buflen)
|
||||
{
|
||||
FormatEx(buf, buflen, "[U:1:%d]", accountid);
|
||||
}
|
||||
|
||||
stock void SteamID64ToString(int num[2], char[] buf, int buflen)
|
||||
{
|
||||
if (kv == null)
|
||||
kv = new KeyValues("fuck sourcemod");
|
||||
|
||||
kv.SetUInt64(NULL_STRING, num);
|
||||
kv.GetString(NULL_STRING, buf, buflen);
|
||||
}
|
||||
|
||||
stock int SteamID64ToAccountID(const char[] steamid64)
|
||||
{
|
||||
if (kv == null)
|
||||
kv = new KeyValues("fuck sourcemod");
|
||||
|
||||
int num[2];
|
||||
kv.SetString(NULL_STRING, steamid64);
|
||||
kv.GetUInt64(NULL_STRING, num);
|
||||
return num[0]; // & 0x7FFFFFFF;
|
||||
}
|
714
scripting/include/shavit/style-settings.sp
Normal file
714
scripting/include/shavit/style-settings.sp
Normal file
|
@ -0,0 +1,714 @@
|
|||
/*
|
||||
* shavit's Timer - Style settings
|
||||
* by: shavit
|
||||
*
|
||||
* This file is part of shavit's Timer.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma newdecls required
|
||||
#pragma semicolon 1
|
||||
|
||||
enum struct style_setting_t
|
||||
{
|
||||
float f;
|
||||
char str[128];
|
||||
}
|
||||
|
||||
Handle gH_Forwards_OnStyleConfigLoaded = null;
|
||||
|
||||
bool gB_StyleCommandsRegistered = false;
|
||||
|
||||
int gI_Styles = 0;
|
||||
int gI_OrderedStyles[STYLE_LIMIT];
|
||||
int gI_CurrentParserIndex = 0;
|
||||
|
||||
StringMap gSM_StyleKeys[STYLE_LIMIT];
|
||||
StringMap gSM_StyleCommands = null;
|
||||
StringMap gSM_StyleKeysSet = null;
|
||||
|
||||
int gI_StyleFlag[STYLE_LIMIT];
|
||||
char gS_StyleOverride[STYLE_LIMIT][32];
|
||||
|
||||
void Shavit_Style_Settings_Natives()
|
||||
{
|
||||
CreateNative("Shavit_GetOrderedStyles", Native_GetOrderedStyles);
|
||||
CreateNative("Shavit_GetStyleCount", Native_GetStyleCount);
|
||||
|
||||
CreateNative("Shavit_GetStyleSetting", Native_GetStyleSetting);
|
||||
CreateNative("Shavit_GetStyleSettingInt", Native_GetStyleSettingInt);
|
||||
CreateNative("Shavit_GetStyleSettingBool", Native_GetStyleSettingBool);
|
||||
CreateNative("Shavit_GetStyleSettingFloat", Native_GetStyleSettingFloat);
|
||||
|
||||
CreateNative("Shavit_HasStyleAccess", Native_HasStyleAccess);
|
||||
CreateNative("Shavit_HasStyleSetting", Native_HasStyleSetting);
|
||||
|
||||
CreateNative("Shavit_SetStyleSetting", Native_SetStyleSetting);
|
||||
CreateNative("Shavit_SetStyleSettingInt", Native_SetStyleSettingInt);
|
||||
CreateNative("Shavit_SetStyleSettingBool", Native_SetStyleSettingBool);
|
||||
CreateNative("Shavit_SetStyleSettingFloat", Native_SetStyleSettingFloat);
|
||||
|
||||
CreateNative("Shavit_GetStyleStrings", Native_GetStyleStrings);
|
||||
CreateNative("Shavit_GetStyleStringsStruct", Native_GetStyleStringsStruct);
|
||||
|
||||
gSM_StyleCommands = new StringMap();
|
||||
}
|
||||
|
||||
void Shavit_Style_Settings_Forwards()
|
||||
{
|
||||
gH_Forwards_OnStyleConfigLoaded = CreateGlobalForward("Shavit_OnStyleConfigLoaded", ET_Event, Param_Cell);
|
||||
}
|
||||
|
||||
bool LoadStyles()
|
||||
{
|
||||
for (int i = 0; i < STYLE_LIMIT; i++)
|
||||
{
|
||||
delete gSM_StyleKeys[i];
|
||||
}
|
||||
|
||||
char sPath[PLATFORM_MAX_PATH];
|
||||
BuildPath(Path_SM, sPath, PLATFORM_MAX_PATH, "configs/shavit-styles.cfg");
|
||||
|
||||
SMCParser parser = new SMCParser();
|
||||
parser.OnEnterSection = OnStyleEnterSection;
|
||||
parser.OnLeaveSection = OnStyleLeaveSection;
|
||||
parser.OnKeyValue = OnStyleKeyValue;
|
||||
parser.ParseFile(sPath);
|
||||
delete parser;
|
||||
|
||||
for (int i = 0; i < gI_Styles; i++)
|
||||
{
|
||||
if (gSM_StyleKeys[i] == null)
|
||||
{
|
||||
SetFailState("Missing style index %d. Highest index is %d. Fix addons/sourcemod/configs/shavit-styles.cfg", i, gI_Styles-1);
|
||||
}
|
||||
}
|
||||
|
||||
gB_StyleCommandsRegistered = true;
|
||||
|
||||
SortCustom1D(gI_OrderedStyles, gI_Styles, SortAscending_StyleOrder);
|
||||
|
||||
Call_StartForward(gH_Forwards_OnStyleConfigLoaded);
|
||||
Call_PushCell(gI_Styles);
|
||||
Call_Finish();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public SMCResult OnStyleEnterSection(SMCParser smc, const char[] name, bool opt_quotes)
|
||||
{
|
||||
// styles key
|
||||
if (!IsCharNumeric(name[0]))
|
||||
{
|
||||
return SMCParse_Continue;
|
||||
}
|
||||
|
||||
gI_CurrentParserIndex = StringToInt(name);
|
||||
|
||||
if (gSM_StyleKeys[gI_CurrentParserIndex] != null)
|
||||
{
|
||||
SetFailState("Style index %d (%s) already parsed. Stop using the same index for multiple styles. Fix addons/sourcemod/configs/shavit-styles.cfg", gI_CurrentParserIndex, name);
|
||||
}
|
||||
|
||||
if (gI_CurrentParserIndex >= STYLE_LIMIT)
|
||||
{
|
||||
SetFailState("Style index %d (%s) too high (limit %d). Fix addons/sourcemod/configs/shavit-styles.cfg", gI_CurrentParserIndex, name, STYLE_LIMIT);
|
||||
}
|
||||
|
||||
if (gI_Styles <= gI_CurrentParserIndex)
|
||||
{
|
||||
gI_Styles = gI_CurrentParserIndex + 1;
|
||||
}
|
||||
|
||||
delete gSM_StyleKeysSet;
|
||||
gSM_StyleKeysSet = new StringMap();
|
||||
|
||||
gSM_StyleKeys[gI_CurrentParserIndex] = new StringMap();
|
||||
|
||||
SetStyleSetting(gI_CurrentParserIndex, "name", "<MISSING STYLE NAME>");
|
||||
SetStyleSetting(gI_CurrentParserIndex, "shortname", "<MISSING SHORT STYLE NAME>");
|
||||
SetStyleSetting(gI_CurrentParserIndex, "htmlcolor", "<MISSING STYLE HTML COLOR>");
|
||||
SetStyleSetting(gI_CurrentParserIndex, "command", "");
|
||||
SetStyleSetting(gI_CurrentParserIndex, "clantag", "<MISSING STYLE CLAN TAG>");
|
||||
SetStyleSetting(gI_CurrentParserIndex, "specialstring", "");
|
||||
SetStyleSetting(gI_CurrentParserIndex, "permission", "");
|
||||
|
||||
SetStyleSettingInt (gI_CurrentParserIndex, "autobhop", 1);
|
||||
SetStyleSettingInt (gI_CurrentParserIndex, "easybhop", 1);
|
||||
SetStyleSettingInt (gI_CurrentParserIndex, "prespeed", 0);
|
||||
SetStyleSettingFloat(gI_CurrentParserIndex, "prespeed_ez_vel", 0.0);
|
||||
SetStyleSettingFloat(gI_CurrentParserIndex, "velocity_limit", 0.0);
|
||||
SetStyleSettingInt (gI_CurrentParserIndex, "bunnyhopping", 1);
|
||||
|
||||
SetStyleSettingInt (gI_CurrentParserIndex, "prespeed_type", -1);
|
||||
SetStyleSettingInt (gI_CurrentParserIndex, "blockprejump", -1);
|
||||
SetStyleSettingInt (gI_CurrentParserIndex, "nozaxisspeed", -1);
|
||||
SetStyleSettingInt (gI_CurrentParserIndex, "restrictnoclip", -1);
|
||||
SetStyleSettingInt (gI_CurrentParserIndex, "startinair", 0);
|
||||
|
||||
SetStyleSettingFloat(gI_CurrentParserIndex, "airaccelerate", 1000.0);
|
||||
SetStyleSettingFloat(gI_CurrentParserIndex, "runspeed", 260.00);
|
||||
SetStyleSettingFloat(gI_CurrentParserIndex, "gravity", 1.0);
|
||||
SetStyleSettingFloat(gI_CurrentParserIndex, "speed", 1.0);
|
||||
SetStyleSettingInt (gI_CurrentParserIndex, "halftime", 0);
|
||||
SetStyleSettingFloat(gI_CurrentParserIndex, "timescale", 1.0);
|
||||
|
||||
SetStyleSettingInt (gI_CurrentParserIndex, "tas", 0);
|
||||
SetStyleSettingFloat(gI_CurrentParserIndex, "tas_timescale", 0.0);
|
||||
SetStyleSettingInt (gI_CurrentParserIndex, "autostrafe", 0);
|
||||
SetStyleSettingInt (gI_CurrentParserIndex, "autoprestrafe", 0);
|
||||
SetStyleSettingInt (gI_CurrentParserIndex, "edgejump", 0);
|
||||
SetStyleSettingInt (gI_CurrentParserIndex, "autojumponstart", 0);
|
||||
|
||||
SetStyleSettingInt (gI_CurrentParserIndex, "force_timescale", 0);
|
||||
SetStyleSettingFloat(gI_CurrentParserIndex, "velocity", 1.0);
|
||||
SetStyleSettingFloat(gI_CurrentParserIndex, "bonus_velocity", 0.0);
|
||||
SetStyleSettingFloat(gI_CurrentParserIndex, "min_velocity", 0.0);
|
||||
SetStyleSettingFloat(gI_CurrentParserIndex, "jump_multiplier", 0.0);
|
||||
SetStyleSettingFloat(gI_CurrentParserIndex, "jump_bonus", 0.0);
|
||||
SetStyleSettingInt (gI_CurrentParserIndex, "block_w", 0);
|
||||
SetStyleSettingInt (gI_CurrentParserIndex, "block_a", 0);
|
||||
SetStyleSettingInt (gI_CurrentParserIndex, "block_s", 0);
|
||||
SetStyleSettingInt (gI_CurrentParserIndex, "block_d", 0);
|
||||
SetStyleSettingInt (gI_CurrentParserIndex, "block_use", 0);
|
||||
SetStyleSettingInt (gI_CurrentParserIndex, "force_hsw", 0);
|
||||
SetStyleSettingInt (gI_CurrentParserIndex, "block_pleft", 0);
|
||||
SetStyleSettingInt (gI_CurrentParserIndex, "block_pright", 0);
|
||||
SetStyleSettingInt (gI_CurrentParserIndex, "block_pstrafe", 0);
|
||||
SetStyleSettingInt (gI_CurrentParserIndex, "unranked", 0);
|
||||
SetStyleSettingInt (gI_CurrentParserIndex, "noreplay", 0);
|
||||
SetStyleSettingInt (gI_CurrentParserIndex, "sync", 1);
|
||||
SetStyleSettingInt (gI_CurrentParserIndex, "strafe_count_w", 0);
|
||||
SetStyleSettingInt (gI_CurrentParserIndex, "strafe_count_a", 1);
|
||||
SetStyleSettingInt (gI_CurrentParserIndex, "strafe_count_s", 0);
|
||||
SetStyleSettingInt (gI_CurrentParserIndex, "strafe_count_d", 1);
|
||||
SetStyleSettingFloat(gI_CurrentParserIndex, "rankingmultiplier", 1.0);
|
||||
SetStyleSettingInt (gI_CurrentParserIndex, "special", 0);
|
||||
|
||||
// bhop_freedompuppies on css auto is like 4.2s. prob lower on csgo so 3.5
|
||||
SetStyleSettingFloat(gI_CurrentParserIndex, "minimum_time", 3.5);
|
||||
// bhop_uc_minecraft_beta2 on css auto has a 0.62s time
|
||||
SetStyleSettingFloat(gI_CurrentParserIndex, "minimum_time_bonus", 0.5);
|
||||
|
||||
SetStyleSettingInt(gI_CurrentParserIndex, "ordering", gI_CurrentParserIndex);
|
||||
|
||||
SetStyleSettingInt(gI_CurrentParserIndex, "inaccessible", 0);
|
||||
SetStyleSettingInt(gI_CurrentParserIndex, "enabled", 1);
|
||||
SetStyleSettingInt(gI_CurrentParserIndex, "kzcheckpoints", 0);
|
||||
SetStyleSettingInt(gI_CurrentParserIndex, "kzcheckpoints_ladders", 0);
|
||||
SetStyleSettingInt(gI_CurrentParserIndex, "force_groundkeys", 0);
|
||||
|
||||
gI_OrderedStyles[gI_CurrentParserIndex] = gI_CurrentParserIndex;
|
||||
|
||||
return SMCParse_Continue;
|
||||
}
|
||||
|
||||
public SMCResult OnStyleLeaveSection(SMCParser smc)
|
||||
{
|
||||
if (gI_CurrentParserIndex == -1)
|
||||
{
|
||||
// OnStyleLeaveSection can be called back to back.
|
||||
// And does for when hitting the last style!
|
||||
// So we set gI_CurrentParserIndex to -1 at the end of this function.
|
||||
return SMCParse_Continue;
|
||||
}
|
||||
|
||||
// if this style is disabled, we will force certain settings
|
||||
if (GetStyleSettingInt(gI_CurrentParserIndex, "enabled") <= 0)
|
||||
{
|
||||
SetStyleSettingInt (gI_CurrentParserIndex, "noreplay", 1);
|
||||
SetStyleSettingFloat(gI_CurrentParserIndex, "rankingmultiplier", 0.0);
|
||||
SetStyleSettingInt (gI_CurrentParserIndex, "inaccessible", 1);
|
||||
}
|
||||
|
||||
if (GetStyleSettingBool(gI_CurrentParserIndex, "halftime"))
|
||||
{
|
||||
SetStyleSettingFloat(gI_CurrentParserIndex, "timescale", 0.5);
|
||||
}
|
||||
|
||||
if (GetStyleSettingFloat(gI_CurrentParserIndex, "timescale") <= 0.0)
|
||||
{
|
||||
SetStyleSettingFloat(gI_CurrentParserIndex, "timescale", 1.0);
|
||||
}
|
||||
|
||||
#if 0
|
||||
// Setting it here so that we can reference the timescale setting.
|
||||
if (!HasStyleSetting(gI_CurrentParserIndex, "force_timescale"))
|
||||
{
|
||||
if (GetStyleSettingFloat(gI_CurrentParserIndex, "timescale") == 1.0)
|
||||
{
|
||||
SetStyleSettingInt(gI_CurrentParserIndex, "force_timescale", 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetStyleSettingInt(gI_CurrentParserIndex, "force_timescale", 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (GetStyleSettingInt(gI_CurrentParserIndex, "prespeed") > 0 || GetStyleSettingInt(gI_CurrentParserIndex, "prespeed_type") > 0)
|
||||
{
|
||||
bool value;
|
||||
|
||||
if (!gSM_StyleKeysSet.GetValue("minimum_time", value))
|
||||
{
|
||||
SetStyleSettingFloat(gI_CurrentParserIndex, "minimum_time", 0.01);
|
||||
}
|
||||
|
||||
if (!gSM_StyleKeysSet.GetValue("minimum_time_bonus", value))
|
||||
{
|
||||
SetStyleSettingFloat(gI_CurrentParserIndex, "minimum_time_bonus", 0.01);
|
||||
}
|
||||
}
|
||||
|
||||
char sStyleCommand[128];
|
||||
GetStyleSetting(gI_CurrentParserIndex, "command", sStyleCommand, sizeof(sStyleCommand));
|
||||
char sName[64];
|
||||
GetStyleSetting(gI_CurrentParserIndex, "name", sName, sizeof(sName));
|
||||
|
||||
if (!gB_StyleCommandsRegistered && strlen(sStyleCommand) > 0 && !GetStyleSettingBool(gI_CurrentParserIndex, "inaccessible"))
|
||||
{
|
||||
char sStyleCommands[32][32];
|
||||
int iCommands = ExplodeString(sStyleCommand, ";", sStyleCommands, 32, 32, false);
|
||||
|
||||
char sDescription[128];
|
||||
FormatEx(sDescription, 128, "Change style to %s.", sName);
|
||||
|
||||
for (int x = 0; x < iCommands; x++)
|
||||
{
|
||||
TrimString(sStyleCommands[x]);
|
||||
StripQuotes(sStyleCommands[x]);
|
||||
|
||||
char sCommand[32];
|
||||
FormatEx(sCommand, 32, "sm_%s", sStyleCommands[x]);
|
||||
|
||||
gSM_StyleCommands.SetValue(sCommand, gI_CurrentParserIndex);
|
||||
|
||||
RegConsoleCmd(sCommand, Command_StyleChange, sDescription);
|
||||
}
|
||||
}
|
||||
|
||||
char sPermission[64];
|
||||
GetStyleSetting(gI_CurrentParserIndex, "name", sPermission, sizeof(sPermission));
|
||||
|
||||
if (StrContains(sPermission, ";") != -1)
|
||||
{
|
||||
char sText[2][32];
|
||||
int iCount = ExplodeString(sPermission, ";", sText, 2, 32);
|
||||
|
||||
AdminFlag flag = Admin_Reservation;
|
||||
|
||||
if(FindFlagByChar(sText[0][0], flag))
|
||||
{
|
||||
gI_StyleFlag[gI_CurrentParserIndex] = FlagToBit(flag);
|
||||
}
|
||||
|
||||
strcopy(gS_StyleOverride[gI_CurrentParserIndex], 32, (iCount >= 2)? sText[1]:"");
|
||||
}
|
||||
else if (strlen(sPermission) > 0)
|
||||
{
|
||||
AdminFlag flag = Admin_Reservation;
|
||||
|
||||
if(FindFlagByChar(sPermission[0], flag))
|
||||
{
|
||||
gI_StyleFlag[gI_CurrentParserIndex] = FlagToBit(flag);
|
||||
}
|
||||
}
|
||||
|
||||
if (HasStyleSetting(gI_CurrentParserIndex, "specialstring"))
|
||||
{
|
||||
char value[128];
|
||||
GetStyleSetting(gI_CurrentParserIndex, "specialstring", value, sizeof(value));
|
||||
|
||||
char keys[32][32];
|
||||
int count = ExplodeString(value, ";", keys, 32, 32, false);
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
TrimString(keys[i]);
|
||||
|
||||
char pair[2][32];
|
||||
ExplodeString(keys[i], "=", pair, 2, 32, false);
|
||||
|
||||
TrimString(pair[0]);
|
||||
TrimString(pair[1]);
|
||||
|
||||
if (!pair[0][0])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
LowercaseString(pair[0]);
|
||||
|
||||
#if 0
|
||||
if (HasStyleSetting(gI_CurrentParserIndex, pair[0]))
|
||||
#else
|
||||
bool x;
|
||||
if (gSM_StyleKeysSet.GetValue(pair[0], x))
|
||||
#endif
|
||||
{
|
||||
char asdf[128];
|
||||
GetStyleSetting(gI_CurrentParserIndex, pair[0], asdf, sizeof(asdf));
|
||||
char name[128];
|
||||
GetStyleSetting(gI_CurrentParserIndex, "name", name, sizeof(name));
|
||||
LogError("Style %s (%d) has '%s' set (%s) but is also trying to set it from specialstring (%s).", name, gI_CurrentParserIndex, pair[0], asdf, pair[1][0] ? pair[1] : "1");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pair[1][0])
|
||||
{
|
||||
SetStyleSetting(gI_CurrentParserIndex, pair[0], pair[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetStyleSettingBool(gI_CurrentParserIndex, pair[0], true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (GetStyleSettingBool(gI_CurrentParserIndex, "tas"))
|
||||
{
|
||||
bool x;
|
||||
|
||||
if (!gSM_StyleKeysSet.GetValue("tas_timescale", x))
|
||||
{
|
||||
SetStyleSettingFloat(gI_CurrentParserIndex, "tas_timescale", -1.0);
|
||||
}
|
||||
|
||||
if (!gSM_StyleKeysSet.GetValue("autostrafe", x))
|
||||
{
|
||||
SetStyleSettingInt (gI_CurrentParserIndex, "autostrafe", 1);
|
||||
}
|
||||
|
||||
if (!gSM_StyleKeysSet.GetValue("autoprestrafe", x))
|
||||
{
|
||||
SetStyleSettingBool (gI_CurrentParserIndex, "autoprestrafe", true);
|
||||
}
|
||||
|
||||
if (!gSM_StyleKeysSet.GetValue("edgejump", x))
|
||||
{
|
||||
SetStyleSettingBool (gI_CurrentParserIndex, "edgejump", true);
|
||||
}
|
||||
|
||||
if (!gSM_StyleKeysSet.GetValue("autojumponstart", x))
|
||||
{
|
||||
SetStyleSettingBool (gI_CurrentParserIndex, "autojumponstart", true);
|
||||
}
|
||||
}
|
||||
|
||||
delete gSM_StyleKeysSet;
|
||||
gI_CurrentParserIndex = -1;
|
||||
return SMCParse_Continue;
|
||||
}
|
||||
|
||||
public SMCResult OnStyleKeyValue(SMCParser smc, const char[] key, const char[] value, bool key_quotes, bool value_quotes)
|
||||
{
|
||||
SetStyleSetting(gI_CurrentParserIndex, key, value);
|
||||
gSM_StyleKeysSet.SetValue(key, true);
|
||||
|
||||
return SMCParse_Continue;
|
||||
}
|
||||
|
||||
public int SortAscending_StyleOrder(int index1, int index2, const int[] array, any hndl)
|
||||
{
|
||||
return GetStyleSettingInt(index1, "ordering") - GetStyleSettingInt(index2, "ordering");
|
||||
}
|
||||
|
||||
public Action Command_StyleChange(int client, int args)
|
||||
{
|
||||
char sCommand[128];
|
||||
GetCmdArg(0, sCommand, 128);
|
||||
|
||||
int style = 0;
|
||||
|
||||
if (gSM_StyleCommands.GetValue(sCommand, style))
|
||||
{
|
||||
ChangeClientStyle(client, style, true);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
public int Native_GetStyleCount(Handle handler, int numParams)
|
||||
{
|
||||
return (gI_Styles > 0)? gI_Styles:-1;
|
||||
}
|
||||
|
||||
public int Native_GetOrderedStyles(Handle handler, int numParams)
|
||||
{
|
||||
return SetNativeArray(1, gI_OrderedStyles, GetNativeCell(2));
|
||||
}
|
||||
|
||||
public int Native_GetStyleSetting(Handle handler, int numParams)
|
||||
{
|
||||
int style = GetNativeCell(1);
|
||||
|
||||
char sKey[64];
|
||||
GetNativeString(2, sKey, sizeof(sKey));
|
||||
|
||||
int maxlength = GetNativeCell(4);
|
||||
|
||||
char sValue[128];
|
||||
bool ret = GetStyleSetting(style, sKey, sValue, sizeof(sValue));
|
||||
|
||||
SetNativeString(3, sValue, maxlength);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool GetStyleSetting(int style, const char[] key, char[] value, int size)
|
||||
{
|
||||
style_setting_t ss;
|
||||
|
||||
if (gSM_StyleKeys[style].GetArray(key, ss, sizeof(ss)))
|
||||
{
|
||||
strcopy(value, size, ss.str);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public int Native_GetStyleSettingInt(Handle handler, int numParams)
|
||||
{
|
||||
int style = GetNativeCell(1);
|
||||
|
||||
char sKey[64];
|
||||
GetNativeString(2, sKey, sizeof(sKey));
|
||||
|
||||
return GetStyleSettingInt(style, sKey);
|
||||
}
|
||||
|
||||
int GetStyleSettingInt(int style, char[] key)
|
||||
{
|
||||
float val[1];
|
||||
gSM_StyleKeys[style].GetArray(key, val, 1);
|
||||
return RoundToFloor(val[0]);
|
||||
}
|
||||
|
||||
public int Native_GetStyleSettingBool(Handle handler, int numParams)
|
||||
{
|
||||
int style = GetNativeCell(1);
|
||||
|
||||
char sKey[256];
|
||||
GetNativeString(2, sKey, 256);
|
||||
|
||||
return GetStyleSettingBool(style, sKey);
|
||||
}
|
||||
|
||||
bool GetStyleSettingBool(int style, char[] key)
|
||||
{
|
||||
return GetStyleSettingFloat(style, key) != 0.0;
|
||||
}
|
||||
|
||||
public any Native_GetStyleSettingFloat(Handle handler, int numParams)
|
||||
{
|
||||
int style = GetNativeCell(1);
|
||||
|
||||
char sKey[64];
|
||||
GetNativeString(2, sKey, sizeof(sKey));
|
||||
|
||||
return GetStyleSettingFloat(style, sKey);
|
||||
}
|
||||
|
||||
float GetStyleSettingFloat(int style, char[] key)
|
||||
{
|
||||
float val[1];
|
||||
gSM_StyleKeys[style].GetArray(key, val, 1);
|
||||
return val[0];
|
||||
}
|
||||
|
||||
public any Native_HasStyleSetting(Handle handler, int numParams)
|
||||
{
|
||||
// TODO: replace with sm 1.11 StringMap.ContainsKey
|
||||
int style = GetNativeCell(1);
|
||||
|
||||
char sKey[64];
|
||||
GetNativeString(2, sKey, sizeof(sKey));
|
||||
|
||||
return HasStyleSetting(style, sKey);
|
||||
}
|
||||
|
||||
bool HasStyleSetting(int style, char[] key)
|
||||
{
|
||||
int value[1];
|
||||
return gSM_StyleKeys[style].GetArray(key, value, 1);
|
||||
}
|
||||
|
||||
bool SetStyleSetting(int style, const char[] key, const char[] value, bool replace=true)
|
||||
{
|
||||
style_setting_t ss;
|
||||
ss.f = StringToFloat(value);
|
||||
int strcells = strcopy(ss.str, sizeof(ss.str), value);
|
||||
if (strcells < 1) strcells = 1;
|
||||
return gSM_StyleKeys[style].SetArray(key, ss, strcells+2, replace);
|
||||
}
|
||||
|
||||
public any Native_SetStyleSetting(Handle handler, int numParams)
|
||||
{
|
||||
int style = GetNativeCell(1);
|
||||
|
||||
char sKey[64];
|
||||
GetNativeString(2, sKey, sizeof(sKey));
|
||||
|
||||
char sValue[128];
|
||||
GetNativeString(3, sValue, sizeof(sValue));
|
||||
|
||||
bool replace = GetNativeCell(4);
|
||||
|
||||
return SetStyleSetting(style, sKey, sValue, replace);
|
||||
}
|
||||
|
||||
public any Native_SetStyleSettingFloat(Handle handler, int numParams)
|
||||
{
|
||||
int style = GetNativeCell(1);
|
||||
|
||||
char sKey[64];
|
||||
GetNativeString(2, sKey, sizeof(sKey));
|
||||
|
||||
float fValue = GetNativeCell(3);
|
||||
|
||||
bool replace = GetNativeCell(4);
|
||||
|
||||
return SetStyleSettingFloat(style, sKey, fValue, replace);
|
||||
}
|
||||
|
||||
bool SetStyleSettingFloat(int style, char[] key, float value, bool replace=true)
|
||||
{
|
||||
style_setting_t ss;
|
||||
ss.f = value;
|
||||
int strcells = FloatToString(value, ss.str, sizeof(ss.str));
|
||||
return gSM_StyleKeys[style].SetArray(key, ss, strcells+1, replace);
|
||||
}
|
||||
|
||||
public any Native_SetStyleSettingBool(Handle handler, int numParams)
|
||||
{
|
||||
int style = GetNativeCell(1);
|
||||
|
||||
char sKey[64];
|
||||
GetNativeString(2, sKey, sizeof(sKey));
|
||||
|
||||
bool value = GetNativeCell(3);
|
||||
|
||||
bool replace = GetNativeCell(4);
|
||||
|
||||
return SetStyleSettingBool(style, sKey, value, replace);
|
||||
}
|
||||
|
||||
bool SetStyleSettingBool(int style, char[] key, bool value, bool replace=true)
|
||||
{
|
||||
return SetStyleSettingFloat(style, key, value ? 1.0 : 0.0, replace);
|
||||
}
|
||||
|
||||
public any Native_SetStyleSettingInt(Handle handler, int numParams)
|
||||
{
|
||||
int style = GetNativeCell(1);
|
||||
|
||||
char sKey[64];
|
||||
GetNativeString(2, sKey, sizeof(sKey));
|
||||
|
||||
int value = GetNativeCell(3);
|
||||
|
||||
bool replace = GetNativeCell(4);
|
||||
|
||||
return SetStyleSettingInt(style, sKey, value, replace);
|
||||
}
|
||||
|
||||
bool SetStyleSettingInt(int style, char[] key, int value, bool replace=true)
|
||||
{
|
||||
style_setting_t ss;
|
||||
ss.f = float(value);
|
||||
int strcells = IntToString(value, ss.str, sizeof(ss.str));
|
||||
return gSM_StyleKeys[style].SetArray(key, ss, strcells+1, replace);
|
||||
}
|
||||
|
||||
public int Native_GetStyleStrings(Handle handler, int numParams)
|
||||
{
|
||||
int style = GetNativeCell(1);
|
||||
int type = GetNativeCell(2);
|
||||
int size = GetNativeCell(4);
|
||||
char sValue[128];
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case sStyleName:
|
||||
{
|
||||
GetStyleSetting(style, "name", sValue, sizeof(stylestrings_t::sStyleName));
|
||||
}
|
||||
case sShortName:
|
||||
{
|
||||
GetStyleSetting(style, "shortname", sValue, sizeof(stylestrings_t::sShortName));
|
||||
}
|
||||
case sHTMLColor:
|
||||
{
|
||||
GetStyleSetting(style, "htmlcolor", sValue, sizeof(stylestrings_t::sHTMLColor));
|
||||
}
|
||||
case sChangeCommand:
|
||||
{
|
||||
GetStyleSetting(style, "command", sValue, sizeof(stylestrings_t::sChangeCommand));
|
||||
}
|
||||
case sClanTag:
|
||||
{
|
||||
GetStyleSetting(style, "clantag", sValue, sizeof(stylestrings_t::sClanTag));
|
||||
}
|
||||
case sSpecialString:
|
||||
{
|
||||
GetStyleSetting(style, "specialstring", sValue, sizeof(stylestrings_t::sSpecialString));
|
||||
}
|
||||
case sStylePermission:
|
||||
{
|
||||
GetStyleSetting(style, "permission", sValue, sizeof(stylestrings_t::sStylePermission));
|
||||
}
|
||||
default:
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return SetNativeString(3, sValue, size);
|
||||
}
|
||||
|
||||
public int Native_GetStyleStringsStruct(Handle plugin, int numParams)
|
||||
{
|
||||
int style = GetNativeCell(1);
|
||||
|
||||
if (GetNativeCell(3) != sizeof(stylestrings_t))
|
||||
{
|
||||
return ThrowNativeError(200, "stylestrings_t does not match latest(got %i expected %i). Please update your includes and recompile your plugins", GetNativeCell(3), sizeof(stylestrings_t));
|
||||
}
|
||||
|
||||
stylestrings_t strings;
|
||||
GetStyleSetting(style, "name", strings.sStyleName, sizeof(strings.sStyleName));
|
||||
GetStyleSetting(style, "shortname", strings.sShortName, sizeof(strings.sShortName));
|
||||
GetStyleSetting(style, "htmlcolor", strings.sHTMLColor, sizeof(strings.sHTMLColor));
|
||||
GetStyleSetting(style, "command", strings.sChangeCommand, sizeof(strings.sChangeCommand));
|
||||
GetStyleSetting(style, "clantag", strings.sClanTag, sizeof(strings.sClanTag));
|
||||
GetStyleSetting(style, "specialstring", strings.sSpecialString, sizeof(strings.sSpecialString));
|
||||
GetStyleSetting(style, "permission", strings.sStylePermission, sizeof(strings.sStylePermission));
|
||||
|
||||
return SetNativeArray(2, strings, sizeof(stylestrings_t));
|
||||
}
|
||||
|
||||
public int Native_HasStyleAccess(Handle handler, int numParams)
|
||||
{
|
||||
int style = GetNativeCell(2);
|
||||
|
||||
if (GetStyleSettingBool(style, "inaccessible") || GetStyleSettingInt(style, "enabled") <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return CheckCommandAccess(GetNativeCell(1), (strlen(gS_StyleOverride[style]) > 0)? gS_StyleOverride[style]:"<none>", gI_StyleFlag[style]);
|
||||
}
|
279
scripting/include/shavit/tas-oblivious.inc
Normal file
279
scripting/include/shavit/tas-oblivious.inc
Normal file
|
@ -0,0 +1,279 @@
|
|||
/*
|
||||
* tas-oblivious.inc file
|
||||
* by: oblivious
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined _shavit_tas_oblivious_included
|
||||
#endinput
|
||||
#endif
|
||||
#define _shavit_tas_oblivious_included
|
||||
|
||||
|
||||
stock float normalize_yaw(float _yaw)
|
||||
{
|
||||
while (_yaw > 180.0) _yaw -= 360.0;
|
||||
while (_yaw < -180.0) _yaw += 360.0; return _yaw;
|
||||
}
|
||||
|
||||
stock float get_length_2d(float vec[3])
|
||||
{
|
||||
return SquareRoot(vec[0] * vec[0] + vec[1] * vec[1]);
|
||||
}
|
||||
|
||||
stock float ground_delta_opt(int client, float angles[3], float move[3], float surface_friction,
|
||||
float accelerate, float friction, float stopspeed)
|
||||
{
|
||||
float fore[3], side[3], wishvel[3];
|
||||
float wishspeed;
|
||||
|
||||
GetAngleVectors(angles, fore, side, NULL_VECTOR);
|
||||
|
||||
fore[2] = 0.0;
|
||||
side[2] = 0.0;
|
||||
NormalizeVector(fore, fore);
|
||||
NormalizeVector(side, side);
|
||||
|
||||
wishvel[2] = 0.0;
|
||||
for(int i = 0; i < 2; i++)
|
||||
wishvel[i] = fore[i] * move[0] + side[i] * move[1];
|
||||
|
||||
wishspeed = GetVectorLength(wishvel);
|
||||
|
||||
if(wishspeed > GetEntPropFloat(client, Prop_Send, "m_flMaxspeed") && GetEntPropFloat(client, Prop_Send, "m_flMaxspeed") != 0.0) wishspeed = GetEntPropFloat(client, Prop_Send, "m_flMaxspeed");
|
||||
|
||||
float velocity[3];
|
||||
GetEntPropVector(client, Prop_Data, "m_vecVelocity", velocity);
|
||||
float speed = GetVectorLength(velocity);
|
||||
|
||||
float interval_per_tick = GetTickInterval();
|
||||
|
||||
float accelspeed = accelerate * wishspeed * interval_per_tick * surface_friction;
|
||||
|
||||
float control = speed;
|
||||
if (control < stopspeed) control = stopspeed;
|
||||
float drop = control * friction * interval_per_tick * surface_friction;
|
||||
|
||||
float newspeed = speed - drop;
|
||||
if (newspeed < 0.0) newspeed = 0.0;
|
||||
|
||||
float tmp = wishspeed - accelspeed;
|
||||
|
||||
if (tmp <= newspeed)
|
||||
{
|
||||
float gamma = RadToDeg(ArcCosine(tmp / newspeed));
|
||||
float vel_dir_ang = RadToDeg(ArcTangent2(velocity[1], velocity[0]));
|
||||
|
||||
vel_dir_ang = normalize_yaw(vel_dir_ang);
|
||||
|
||||
float accel_yaw = RadToDeg(ArcTangent2(wishvel[1], wishvel[0]));
|
||||
|
||||
float diffm = vel_dir_ang - gamma;
|
||||
float diffp = vel_dir_ang + gamma;
|
||||
|
||||
diffm = normalize_yaw(diffm - accel_yaw);
|
||||
diffp = normalize_yaw(diffp - accel_yaw);
|
||||
|
||||
float delta_opt = 0.0;
|
||||
if (FloatAbs(diffm) <= FloatAbs(diffp))
|
||||
delta_opt = -diffm;
|
||||
else
|
||||
delta_opt = -diffp;
|
||||
delta_opt = normalize_yaw(delta_opt);
|
||||
|
||||
return delta_opt;
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
stock Action ObliviousOnPlayerRunCmd(int client, int& buttons, int& impulse, float vel[3], float angles[3], int& weapon, int& subtype, int& cmdnum, int& tickcount, int& seed, int mouse[2],
|
||||
float air_accelerate, float surface_friction, float flAirSpeedCap, float flMaxMove,
|
||||
bool no_speed_loss)
|
||||
{
|
||||
float flMaxSpeed = GetEntPropFloat(client, Prop_Send, "m_flMaxspeed");
|
||||
|
||||
bool set_back = true;
|
||||
if (vel[0] != 0.0 || vel[1] != 0.0)
|
||||
set_back = false;
|
||||
if (set_back)
|
||||
vel[1] = flMaxMove;
|
||||
|
||||
float velocity[3], velocity_opt[3];
|
||||
GetEntPropVector(client, Prop_Data, "m_vecVelocity", velocity);
|
||||
|
||||
velocity_opt[0] = velocity[0]; velocity_opt[1] = velocity[1]; velocity_opt[2] = velocity[2];
|
||||
|
||||
float vel_yaw = ArcTangent2(velocity[1], velocity[0]) * 180.0 / FLOAT_PI;
|
||||
|
||||
float delta_opt = -normalize_yaw(angles[1] - vel_yaw);
|
||||
|
||||
if (get_length_2d(velocity) == 0.0)
|
||||
delta_opt = 90.0;
|
||||
|
||||
if (vel[0] != 0.0 && vel[1] == 0.0)
|
||||
{
|
||||
float sign = vel[0] > 0.0 ? -1.0 : 1.0;
|
||||
delta_opt = -normalize_yaw(angles[1] - (vel_yaw + (90.0 * sign)));
|
||||
}
|
||||
if (vel[0] != 0.0 && vel[1] != 0.0)
|
||||
{
|
||||
float sign = vel[1] > 0.0 ? -1.0 : 1.0;
|
||||
if (vel[0] < 0.0)
|
||||
sign = -sign;
|
||||
delta_opt = -normalize_yaw(angles[1] - (vel_yaw + (45.0 * sign)));
|
||||
}
|
||||
|
||||
float frac = 1.0;
|
||||
|
||||
if (buttons & IN_DUCK && no_speed_loss)
|
||||
frac = 0.34;
|
||||
|
||||
float _addspeed = 0.0;
|
||||
if (!set_back)
|
||||
{
|
||||
float _fore[3], _side[3], _wishvel[3], _wishdir[3];
|
||||
float _wishspeed, _wishspd, _currentspeed;
|
||||
|
||||
GetAngleVectors(angles, _fore, _side, NULL_VECTOR);
|
||||
|
||||
_fore[2] = 0.0; _side[2] = 0.0;
|
||||
NormalizeVector(_fore, _fore); NormalizeVector(_side, _side);
|
||||
|
||||
for(int i = 0; i < 2; i++)
|
||||
_wishvel[i] = _fore[i] * vel[0] * frac + _side[i] * vel[1] * frac;
|
||||
|
||||
_wishspeed = NormalizeVector(_wishvel, _wishdir);
|
||||
|
||||
if(_wishspeed > flMaxSpeed && flMaxSpeed != 0.0) _wishspeed = flMaxSpeed;
|
||||
|
||||
_wishspd = _wishspeed;
|
||||
if (_wishspd > flAirSpeedCap)
|
||||
_wishspd = flAirSpeedCap;
|
||||
|
||||
_currentspeed = GetVectorDotProduct(velocity, _wishdir);
|
||||
_addspeed = _wishspd - _currentspeed;
|
||||
if (_addspeed < 0.0)
|
||||
_addspeed = 0.0;
|
||||
}
|
||||
|
||||
float fore[3], side[3], wishvel[3], wishdir[3];
|
||||
float wishspeed, wishspd, addspeed, currentspeed;
|
||||
|
||||
float tmp[3];
|
||||
tmp[0] = 0.0; tmp[2] = 0.0;
|
||||
tmp[1] = normalize_yaw(angles[1] + delta_opt);
|
||||
GetAngleVectors(tmp, fore, side, NULL_VECTOR);
|
||||
|
||||
fore[2] = 0.0; side[2] = 0.0;
|
||||
NormalizeVector(fore, fore); NormalizeVector(side, side);
|
||||
|
||||
for(int i = 0; i < 2; i++)
|
||||
wishvel[i] = fore[i] * vel[0] * frac + side[i] * vel[1] * frac;
|
||||
|
||||
wishspeed = NormalizeVector(wishvel, wishdir);
|
||||
|
||||
if(wishspeed > flMaxSpeed && wishspeed != 0.0) wishspeed = flMaxSpeed;
|
||||
|
||||
wishspd = wishspeed;
|
||||
if (wishspd > flAirSpeedCap)
|
||||
wishspd = flAirSpeedCap;
|
||||
|
||||
currentspeed = GetVectorDotProduct(velocity, wishdir);
|
||||
addspeed = wishspd - currentspeed;
|
||||
|
||||
if (no_speed_loss)
|
||||
{
|
||||
if (_addspeed > addspeed)
|
||||
{
|
||||
addspeed = _addspeed - addspeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
addspeed -= _addspeed;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
addspeed = addspeed - _addspeed;
|
||||
|
||||
if (addspeed > flAirSpeedCap)
|
||||
addspeed = flAirSpeedCap;
|
||||
}
|
||||
|
||||
if (buttons & IN_DUCK)
|
||||
{
|
||||
float vel2d[3]; vel2d[0] = velocity[0]; vel2d[1] = velocity[1];
|
||||
//PrintToChat(client, "%f %f\n", GetVectorLength(vel2d), addspeed);
|
||||
}
|
||||
|
||||
if (addspeed < 0.0)
|
||||
addspeed = 0.0;
|
||||
|
||||
float accelspeed = wishspeed * air_accelerate * GetTickInterval() * surface_friction;
|
||||
|
||||
if (accelspeed > addspeed)
|
||||
accelspeed = addspeed;
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
velocity_opt[i] += accelspeed * wishdir[i];
|
||||
|
||||
float new_vel[3];
|
||||
|
||||
float numer = velocity_opt[0] * velocity[0] + velocity_opt[1] * velocity[1];
|
||||
//float denom = SquareRoot(velocity_opt[0] * velocity_opt[0] + velocity_opt[1] * velocity_opt[1]) * SquareRoot(velocity[0] * velocity[0] + velocity[1] * velocity[1]);
|
||||
float denom = get_length_2d(velocity_opt) * get_length_2d(velocity);
|
||||
float ang = 0.0;
|
||||
if (denom > numer)
|
||||
ang = ArcCosine(numer / denom) * 180.0 / FLOAT_PI;
|
||||
if (vel[1] < 0.0) ang = -ang;
|
||||
|
||||
float st = Sine(ang * FLOAT_PI / 180.0);
|
||||
float ct = Cosine(ang * FLOAT_PI / 180.0);
|
||||
|
||||
new_vel[0] = (velocity_opt[0] * ct) - (velocity_opt[1] * st);
|
||||
new_vel[1] = (velocity_opt[0] * st) + (velocity_opt[1] * ct);
|
||||
new_vel[2] = velocity_opt[2];
|
||||
|
||||
float base_vel[3];
|
||||
GetEntPropVector(client, Prop_Data, "m_vecBaseVelocity", base_vel);
|
||||
|
||||
//PrintToChat(client, "%.2f, %.2f, %.2f", base_vel[0], base_vel[1], base_vel[2]);
|
||||
|
||||
if (GetVectorLength(new_vel) < 99999.0 && GetVectorLength(new_vel) > 0.0)
|
||||
{
|
||||
#if 0
|
||||
SetEntPropVector(client, Prop_Data, "m_vecVelocity", new_vel);
|
||||
|
||||
float _new_vel[3];
|
||||
for (int i = 0; i < 3; i++)
|
||||
_new_vel[i] = new_vel[i] + base_vel[i];
|
||||
|
||||
SetEntPropVector(client, Prop_Data, "m_vecAbsVelocity", _new_vel); // m_vecBaseVelocity+m_vecVelocity
|
||||
#else
|
||||
TeleportEntity(client, NULL_VECTOR, NULL_VECTOR, new_vel);
|
||||
#endif
|
||||
SetEntPropVector(client, Prop_Data, "m_vecBaseVelocity", base_vel);
|
||||
}
|
||||
|
||||
#if 0
|
||||
SetEntPropVector(client, Prop_Data, "m_vecBaseVelocity", base_vel);
|
||||
#endif
|
||||
|
||||
if (set_back)
|
||||
vel[1] = 0.0;
|
||||
|
||||
return Plugin_Continue;
|
||||
}
|
412
scripting/include/shavit/tas-xutax.inc
Normal file
412
scripting/include/shavit/tas-xutax.inc
Normal file
|
@ -0,0 +1,412 @@
|
|||
/*
|
||||
* tas-xutax.inc file
|
||||
* by: xutaxkamay
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined _shavit_tas_xutax_included
|
||||
#endinput
|
||||
#endif
|
||||
#define _shavit_tas_xutax_included
|
||||
|
||||
// reference code for CGameMovement::AirAccelerate & CGameMovement::AirMove at:
|
||||
// https://github.com/ValveSoftware/source-sdk-2013/blob/0d8dceea4310fde5706b3ce1c70609d72a38efdf/mp/src/game/shared/gamemovement.cpp#L1707-L1799
|
||||
|
||||
|
||||
stock float AngleNormalize(float flAngle)
|
||||
{
|
||||
if (flAngle > 180.0)
|
||||
flAngle -= 360.0;
|
||||
else if (flAngle < -180.0)
|
||||
flAngle += 360.0;
|
||||
|
||||
return flAngle;
|
||||
}
|
||||
|
||||
stock float Vec2DToYaw(float vec[2])
|
||||
{
|
||||
float flYaw = 0.0;
|
||||
|
||||
if (vec[0] != 0.0 || vec[1] != 0.0)
|
||||
{
|
||||
float vecNormalized[2];
|
||||
|
||||
float flLength = SquareRoot(vec[0] * vec[0] + vec[1] * vec[1]);
|
||||
|
||||
vecNormalized[0] = vec[0] / flLength;
|
||||
vecNormalized[1] = vec[1] / flLength;
|
||||
|
||||
// Credits to Valve.
|
||||
flYaw = ArcTangent2(vecNormalized[1], vecNormalized[0]) * (180.0 / FLOAT_PI);
|
||||
|
||||
flYaw = AngleNormalize(flYaw);
|
||||
}
|
||||
|
||||
return flYaw;
|
||||
}
|
||||
|
||||
/*
|
||||
* So our problem here is to find a wishdir that no matter the angles we choose, it should go to the direction we want.
|
||||
* So forward/right vector changing but not sidemove and forwardmove for the case where we modify our angles. (1)
|
||||
* But in our case we want sidemove and forwardmove values changing and not the forward/right vectors. (2)
|
||||
* So our unknown variables is fmove and smove to know the (2) case. But we know the (1) case so we can solve this into a linear equation.
|
||||
* To make it more simplier, we know the wishdir values and forward/right vectors, but we do not know the fowardmove and sidemove variables
|
||||
* and that's what we want to solve.
|
||||
* That's what is doing this function, but only in 2D since we can only move forward or side.
|
||||
* But, for noclip (3D) it's a different story that I will let you discover, same method, but 3 equations and 3 unknown variables (forwardmove, sidemove, upmove).
|
||||
*/
|
||||
|
||||
stock void Solve2DMovementsVars(float vecWishDir[2], float vecForward[2], float vecRight[2], float &flForwardMove, float &flSideMove, float flMaxMove)
|
||||
{
|
||||
// wishdir[0] = foward[0] * forwardmove + right[0] * sidemove;
|
||||
// wishdir[1] = foward[1] * forwardmove + right[1] * sidemove;
|
||||
|
||||
// Let's translate this to letters.
|
||||
// v = a * b + c * d
|
||||
// w = e * b + f * d
|
||||
// v = wishdir[0]; w = wishdir[1]...
|
||||
|
||||
// Now let's solve it with online solver https://quickmath.com/webMathematica3/quickmath/equations/solve/advanced.jsp
|
||||
// https://cdn.discordapp.com/attachments/609163806085742622/675477245178937385/c3ca4165c30b3b342e57b903a3ded367-3.png
|
||||
|
||||
float v = vecWishDir[0];
|
||||
float w = vecWishDir[1];
|
||||
float a = vecForward[0];
|
||||
float c = vecRight[0];
|
||||
float e = vecForward[1];
|
||||
float f = vecRight[1];
|
||||
|
||||
float flDivide = (c * e - a * f);
|
||||
if(flDivide == 0.0)
|
||||
{
|
||||
flForwardMove = flMaxMove;
|
||||
flSideMove = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
flForwardMove = (c * w - f * v) / flDivide;
|
||||
flSideMove = (e * v - a * w) / flDivide;
|
||||
}
|
||||
}
|
||||
|
||||
stock float GetThetaAngleInAir(float flVelocity[2], float flAirAccelerate, float flMaxSpeed, float flSurfaceFriction, float flFrametime, float flAirSpeedCap)
|
||||
{
|
||||
// In order to solve this, we must check that accelspeed < 30
|
||||
// so it applies the correct strafing method.
|
||||
// So there is basically two cases:
|
||||
// if 30 - accelspeed <= 0 -> We use the perpendicular of velocity.
|
||||
// but if 30 - accelspeed > 0 the dot product must be equal to = 30 - accelspeed
|
||||
// in order to get the best gain.
|
||||
// First case is theta == 90
|
||||
// How to solve the second case?
|
||||
// here we go
|
||||
// d = velocity2DLength * cos(theta)
|
||||
// cos(theta) = d / velocity2D
|
||||
// theta = arcos(d / velocity2D)
|
||||
|
||||
float flAccelSpeed = flAirAccelerate * flMaxSpeed * flSurfaceFriction * flFrametime;
|
||||
|
||||
float flWantedDotProduct = flAirSpeedCap - flAccelSpeed;
|
||||
|
||||
if (flWantedDotProduct > 0.0)
|
||||
{
|
||||
float flVelLength2D = SquareRoot(flVelocity[0] * flVelocity[0] + flVelocity[1] * flVelocity[1]);
|
||||
if(flVelLength2D == 0.0)
|
||||
{
|
||||
return 90.0;
|
||||
}
|
||||
float flCosTheta = flWantedDotProduct / flVelLength2D;
|
||||
|
||||
if (flCosTheta > 1.0)
|
||||
{
|
||||
flCosTheta = 1.0;
|
||||
}
|
||||
else if(flCosTheta < -1.0)
|
||||
{
|
||||
flCosTheta = -1.0;
|
||||
}
|
||||
|
||||
|
||||
float flTheta = ArcCosine(flCosTheta) * (180.0 / FLOAT_PI);
|
||||
|
||||
return flTheta;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 90.0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Same as above, but this time we calculate max delta angle
|
||||
// so we can change between normal strafer and autostrafer depending on the player's viewangles difference.
|
||||
/*float GetMaxDeltaInAir(float flVelocity[2], float flAirAccelerate, float flMaxSpeed, float flSurfaceFriction, float flFrametime)
|
||||
{
|
||||
float flAccelSpeed = flAirAccelerate * flMaxSpeed * flSurfaceFriction * flFrametime;
|
||||
|
||||
if (flAccelSpeed >= g_flAirSpeedCap)
|
||||
{
|
||||
flAccelSpeed = g_flAirSpeedCap;
|
||||
}
|
||||
|
||||
float flVelLength2D = SquareRoot(flVelocity[0] * flVelocity[0] + flVelocity[1] * flVelocity[1]);
|
||||
|
||||
float flMaxDelta = ArcTangent2(flAccelSpeed, flVelLength2D) * (180 / FLOAT_PI);
|
||||
|
||||
return flMaxDelta;
|
||||
}*/
|
||||
|
||||
stock float SimulateAirAccelerate(float flVelocity[2], float flWishDir[2], float flAirAccelerate, float flMaxSpeed, float flSurfaceFriction, float flFrametime, float flVelocityOutput[2], float flAirSpeedCap)
|
||||
{
|
||||
float flWishSpeedCapped = flMaxSpeed;
|
||||
|
||||
// Cap speed
|
||||
if( flWishSpeedCapped > flAirSpeedCap )
|
||||
flWishSpeedCapped = flAirSpeedCap;
|
||||
|
||||
// Determine veer amount
|
||||
float flCurrentSpeed = flVelocity[0] * flWishDir[0] + flVelocity[1] * flWishDir[1];
|
||||
|
||||
// See how much to add
|
||||
float flAddSpeed = flWishSpeedCapped - flCurrentSpeed;
|
||||
|
||||
// If not adding any, done.
|
||||
if( flAddSpeed <= 0.0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine acceleration speed after acceleration
|
||||
float flAccelSpeed = flAirAccelerate * flMaxSpeed * flFrametime * flSurfaceFriction;
|
||||
|
||||
// Cap it
|
||||
if( flAccelSpeed > flAddSpeed )
|
||||
{
|
||||
flAccelSpeed = flAddSpeed;
|
||||
}
|
||||
|
||||
flVelocityOutput[0] = flVelocity[0] + flAccelSpeed * flWishDir[0];
|
||||
flVelocityOutput[1] = flVelocity[1] + flAccelSpeed * flWishDir[1];
|
||||
}
|
||||
|
||||
// The idea is to get the maximum angle
|
||||
stock float GetMaxDeltaInAir(float flVelocity[2], float flMaxSpeed, float flSurfaceFriction, bool bLeft, float flAirAccelerate, float flAirSpeedCap)
|
||||
{
|
||||
float flFrametime = GetTickInterval();
|
||||
|
||||
float flTheta = GetThetaAngleInAir(flVelocity, flAirAccelerate, flMaxSpeed, flSurfaceFriction, flFrametime, flAirSpeedCap);
|
||||
|
||||
// Convert velocity 2D to angle.
|
||||
float flYawVelocity = Vec2DToYaw(flVelocity);
|
||||
|
||||
// Get the best yaw direction on the right.
|
||||
float flBestYawRight = AngleNormalize(flYawVelocity + flTheta);
|
||||
|
||||
// Get the best yaw direction on the left.
|
||||
float flBestYawLeft = AngleNormalize(flYawVelocity - flTheta);
|
||||
|
||||
float flTemp[3], vecBestLeft3D[3], vecBestRight3D[3];
|
||||
|
||||
flTemp[0] = 0.0;
|
||||
flTemp[1] = flBestYawLeft;
|
||||
flTemp[2] = 0.0;
|
||||
|
||||
GetAngleVectors(flTemp, vecBestLeft3D, NULL_VECTOR, NULL_VECTOR);
|
||||
|
||||
flTemp[0] = 0.0;
|
||||
flTemp[1] = flBestYawRight;
|
||||
flTemp[2] = 0.0;
|
||||
|
||||
GetAngleVectors(flTemp, vecBestRight3D, NULL_VECTOR, NULL_VECTOR);
|
||||
|
||||
float vecBestRight[2], vecBestLeft[2];
|
||||
|
||||
vecBestRight[0] = vecBestRight3D[0];
|
||||
vecBestRight[1] = vecBestRight3D[1];
|
||||
|
||||
vecBestLeft[0] = vecBestLeft3D[0];
|
||||
vecBestLeft[1] = vecBestLeft3D[1];
|
||||
|
||||
float flCalcVelocityLeft[2], flCalcVelocityRight[2];
|
||||
|
||||
// Simulate air accelerate function in order to get the new max gain possible on both side.
|
||||
SimulateAirAccelerate(flVelocity, vecBestLeft, flAirAccelerate, flMaxSpeed, flFrametime, flSurfaceFriction, flCalcVelocityLeft, flAirSpeedCap);
|
||||
SimulateAirAccelerate(flVelocity, vecBestRight, flAirAccelerate, flMaxSpeed, flFrametime, flSurfaceFriction, flCalcVelocityRight, flAirSpeedCap);
|
||||
|
||||
float flNewBestYawLeft = Vec2DToYaw(flCalcVelocityLeft);
|
||||
float flNewBestYawRight = Vec2DToYaw(flCalcVelocityRight);
|
||||
|
||||
// Then get the difference in order to find the maximum angle.
|
||||
if (bLeft)
|
||||
{
|
||||
return FloatAbs(AngleNormalize(flYawVelocity - flNewBestYawLeft));
|
||||
}
|
||||
else
|
||||
{
|
||||
return FloatAbs(AngleNormalize(flYawVelocity - flNewBestYawRight));
|
||||
}
|
||||
|
||||
// Do an estimate otherwhise.
|
||||
// return FloatAbs(AngleNormalize(flNewBestYawLeft - flNewBestYawRight) / 2.0);
|
||||
}
|
||||
|
||||
stock void GetIdealMovementsInAir(float flYawWantedDir, float flVelocity[2], float flMaxSpeed, float flSurfaceFriction, float &flForwardMove, float &flSideMove, bool bPreferRight, float flAirAccelerate, float flMaxMove, float flAirSpeedCap)
|
||||
{
|
||||
float flFrametime = GetTickInterval();
|
||||
float flYawVelocity = Vec2DToYaw(flVelocity);
|
||||
|
||||
// Get theta angle
|
||||
float flTheta = GetThetaAngleInAir(flVelocity, flAirAccelerate, flMaxSpeed, flSurfaceFriction, flFrametime, flAirSpeedCap);
|
||||
|
||||
// Get the best yaw direction on the right.
|
||||
float flBestYawRight = AngleNormalize(flYawVelocity + flTheta);
|
||||
|
||||
// Get the best yaw direction on the left.
|
||||
float flBestYawLeft = AngleNormalize(flYawVelocity - flTheta);
|
||||
|
||||
float vecBestDirLeft[3], vecBestDirRight[3];
|
||||
float tempAngle[3];
|
||||
|
||||
tempAngle[0] = 0.0;
|
||||
tempAngle[1] = flBestYawRight;
|
||||
tempAngle[2] = 0.0;
|
||||
|
||||
GetAngleVectors(tempAngle, vecBestDirRight, NULL_VECTOR, NULL_VECTOR);
|
||||
|
||||
tempAngle[0] = 0.0;
|
||||
tempAngle[1] = flBestYawLeft;
|
||||
tempAngle[2] = 0.0;
|
||||
|
||||
GetAngleVectors(tempAngle, vecBestDirLeft, NULL_VECTOR, NULL_VECTOR);
|
||||
|
||||
// Our wanted direction.
|
||||
float vecBestDir[2];
|
||||
|
||||
// Let's follow the most the wanted direction now with max possible gain.
|
||||
float flDiffYaw = AngleNormalize(flYawWantedDir - flYawVelocity);
|
||||
|
||||
if (flDiffYaw > 0.0)
|
||||
{
|
||||
vecBestDir[0] = vecBestDirRight[0];
|
||||
vecBestDir[1] = vecBestDirRight[1];
|
||||
}
|
||||
else if(flDiffYaw < 0.0)
|
||||
{
|
||||
vecBestDir[0] = vecBestDirLeft[0];
|
||||
vecBestDir[1] = vecBestDirLeft[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Going straight.
|
||||
if (bPreferRight)
|
||||
{
|
||||
vecBestDir[0] = vecBestDirRight[0];
|
||||
vecBestDir[1] = vecBestDirRight[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
vecBestDir[0] = vecBestDirLeft[0];
|
||||
vecBestDir[1] = vecBestDirLeft[1];
|
||||
}
|
||||
}
|
||||
|
||||
float vecForwardWantedDir3D[3], vecRightWantedDir3D[3];
|
||||
float vecForwardWantedDir[2], vecRightWantedDir[2];
|
||||
|
||||
tempAngle[0] = 0.0;
|
||||
tempAngle[1] = flYawWantedDir;
|
||||
tempAngle[2] = 0.0;
|
||||
|
||||
// Convert our yaw wanted direction to vectors.
|
||||
GetAngleVectors(tempAngle, vecForwardWantedDir3D, vecRightWantedDir3D, NULL_VECTOR);
|
||||
|
||||
vecForwardWantedDir[0] = vecForwardWantedDir3D[0];
|
||||
vecForwardWantedDir[1] = vecForwardWantedDir3D[1];
|
||||
|
||||
vecRightWantedDir[0] = vecRightWantedDir3D[0];
|
||||
vecRightWantedDir[1] = vecRightWantedDir3D[1];
|
||||
|
||||
// Solve the movement variables from our wanted direction and the best gain direction.
|
||||
Solve2DMovementsVars(vecBestDir, vecForwardWantedDir, vecRightWantedDir, flForwardMove, flSideMove, flMaxMove);
|
||||
|
||||
float flLengthMovements = SquareRoot(flForwardMove * flForwardMove + flSideMove * flSideMove);
|
||||
|
||||
if(flLengthMovements != 0.0)
|
||||
{
|
||||
flForwardMove /= flLengthMovements;
|
||||
flSideMove /= flLengthMovements;
|
||||
}
|
||||
}
|
||||
|
||||
stock Action XutaxOnPlayerRunCmd(int client, int& buttons, int& impulse, float vel[3], float angles[3], int& weapon, int& subtype, int& cmdnum, int& tickcount, int& seed, int mouse[2],
|
||||
float flAirAccelerate, float flSurfaceFriction, float flAirSpeedCap, float flMaxMove, float flOldYawAngle, float fPower)
|
||||
{
|
||||
// clear out forward because Surf_W_Okay is nice...
|
||||
vel[0] = 0.0;
|
||||
|
||||
float flFowardMove, flSideMove;
|
||||
float flMaxSpeed = GetEntPropFloat(client, Prop_Data, "m_flMaxspeed");
|
||||
float flVelocity[3], flVelocity2D[2];
|
||||
|
||||
GetEntPropVector(client, Prop_Data, "m_vecVelocity", flVelocity);
|
||||
|
||||
flVelocity2D[0] = flVelocity[0];
|
||||
flVelocity2D[1] = flVelocity[1];
|
||||
|
||||
// PrintToChat(client, "%f", SquareRoot(flVelocity2D[0] * flVelocity2D[0] + flVelocity2D[1] * flVelocity2D[1]));
|
||||
|
||||
GetIdealMovementsInAir(angles[1], flVelocity2D, flMaxSpeed, flSurfaceFriction, flFowardMove, flSideMove, true, flAirAccelerate, flMaxMove, flAirSpeedCap);
|
||||
|
||||
float flAngleDifference = AngleNormalize(angles[1] - flOldYawAngle);
|
||||
float flCurrentAngles = FloatAbs(flAngleDifference);
|
||||
|
||||
|
||||
// Right
|
||||
if (flAngleDifference < 0.0)
|
||||
{
|
||||
float flMaxDelta = GetMaxDeltaInAir(flVelocity2D, flMaxSpeed, flSurfaceFriction, true, flAirAccelerate, flAirSpeedCap);
|
||||
|
||||
if (flCurrentAngles <= flMaxDelta * fPower)
|
||||
{
|
||||
vel[0] = flFowardMove * flMaxMove;
|
||||
vel[1] = flSideMove * flMaxMove;
|
||||
}
|
||||
else
|
||||
{
|
||||
vel[1] = flMaxMove;
|
||||
}
|
||||
}
|
||||
else if (flAngleDifference > 0.0)
|
||||
{
|
||||
float flMaxDelta = GetMaxDeltaInAir(flVelocity2D, flMaxSpeed, flSurfaceFriction, false, flAirAccelerate, flAirSpeedCap);
|
||||
|
||||
if (flCurrentAngles <= flMaxDelta * fPower)
|
||||
{
|
||||
vel[0] = flFowardMove * flMaxMove;
|
||||
vel[1] = flSideMove * flMaxMove;
|
||||
}
|
||||
else
|
||||
{
|
||||
vel[1] = -flMaxMove;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
vel[0] = flFowardMove * flMaxMove;
|
||||
vel[1] = flSideMove * flMaxMove;
|
||||
}
|
||||
|
||||
return Plugin_Continue;
|
||||
}
|
221
scripting/include/shavit/tas.inc
Normal file
221
scripting/include/shavit/tas.inc
Normal file
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
* shavit's Timer - tas.inc file
|
||||
* by: xutaxkamay, shavit
|
||||
*
|
||||
* This file is part of shavit's Timer.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined _shavit_tas_included
|
||||
#endinput
|
||||
#endif
|
||||
#define _shavit_tas_included
|
||||
|
||||
enum AutostrafeOverride
|
||||
{
|
||||
AutostrafeOverride_Normal, // only w/s disables autostrafe
|
||||
AutostrafeOverride_Surf, // w/s always disables, a/d only over surf ramps
|
||||
AutostrafeOverride_Surf_W_Okay, // s always disables, a/d only over surf ramps
|
||||
AutostrafeOverride_All, // all keys disable
|
||||
AutostrafeOverride_Size // size
|
||||
};
|
||||
|
||||
enum AutostrafeType
|
||||
{
|
||||
AutostrafeType_Any = -1,
|
||||
AutostrafeType_Disabled = 0,
|
||||
AutostrafeType_1Tick = 1, // xutaxkamay
|
||||
AutostrafeType_Autogain, // oblivious
|
||||
AutostrafeType_AutogainNoSpeedLoss, // oblivious
|
||||
AutostrafeType_Basic, //
|
||||
AutostrafeType_Size
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets whether the client has the autostrafe/strafehack enabled.
|
||||
*
|
||||
* @param client Client index
|
||||
* @param value New value to set the autostrafe/strafehack to.
|
||||
* @noreturn
|
||||
*/
|
||||
native void Shavit_SetAutostrafeEnabled(int client, bool value);
|
||||
|
||||
/**
|
||||
* Retrieves whether the client has the autostrafe/strafehack enabled.
|
||||
*
|
||||
* @param client Client index
|
||||
* @return The current autostrafe/strafehack enabled value.
|
||||
*/
|
||||
native bool Shavit_GetAutostrafeEnabled(int client);
|
||||
|
||||
/**
|
||||
* Sets the autostrafe/strafehack type on the given client index.
|
||||
*
|
||||
* @param client Client index of the player to set the autostrafe/strafehack on.
|
||||
* @param value New type to set the strafehack to.
|
||||
* @noreturn
|
||||
*/
|
||||
native void Shavit_SetAutostrafeType(int client, AutostrafeType value);
|
||||
|
||||
/**
|
||||
* Retrieves the current strafehack type for the given client index.
|
||||
*
|
||||
* @param client Client index of the player to get the strafehack type from.
|
||||
* @return The current strafehack type.
|
||||
*/
|
||||
native AutostrafeType Shavit_GetAutostrafeType(int client);
|
||||
|
||||
/**
|
||||
* Sets the strafehack power on the given client index. Power is the cut off point before it will turn into an autostrafe. 1.0 is the default.
|
||||
*
|
||||
* @param client Client index of the player to set the power on.
|
||||
* @param value New power setting.
|
||||
* @noreturn
|
||||
*/
|
||||
native void Shavit_SetAutostrafePower(int client, float value);
|
||||
|
||||
/**
|
||||
* Retrieves the current strafehack power for the given client index. Default is 1.0
|
||||
*
|
||||
* @param client Client index of the player to get the strafehack power.
|
||||
* @return The current strafehack power.
|
||||
*/
|
||||
native float Shavit_GetAutostrafePower(int client);
|
||||
|
||||
/**
|
||||
* Sets the key override type on the given client index.
|
||||
*
|
||||
* @param client Client index
|
||||
* @param value New type to set the key override to.
|
||||
* @noreturn
|
||||
*/
|
||||
native void Shavit_SetAutostrafeKeyOverride(int client, AutostrafeOverride value);
|
||||
|
||||
/**
|
||||
* Retrieves the current key override type for the given client index.
|
||||
*
|
||||
* @param client Client index
|
||||
* @return The current key override type.
|
||||
*/
|
||||
native AutostrafeOverride Shavit_GetAutostrafeKeyOverride(int client);
|
||||
|
||||
/**
|
||||
* Sets whether the client has automatic prestrafe enabled.
|
||||
*
|
||||
* @param client Client index
|
||||
* @param value New value to set the automatic prestrafe to.
|
||||
* @noreturn
|
||||
*/
|
||||
native void Shavit_SetAutoPrestrafe(int client, bool value);
|
||||
|
||||
/**
|
||||
* Retrieves whether the client has automatic prestrafe enabled.
|
||||
*
|
||||
* @param client Client index
|
||||
* @return The current auto prestrafe value.
|
||||
*/
|
||||
native bool Shavit_GetAutoPrestrafe(int client);
|
||||
|
||||
/**
|
||||
* Sets whether the client automatically jumps when they leave the start zone.
|
||||
*
|
||||
* @param client Client index
|
||||
* @param value New value to set the automatic jump to.
|
||||
* @noreturn
|
||||
*/
|
||||
native void Shavit_SetAutoJumpOnStart(int client, bool value);
|
||||
|
||||
/**
|
||||
* Retrieves hether the client automatically jumps when they leave the start zone.
|
||||
*
|
||||
* @param client Client index
|
||||
* @return The current auto jump value.
|
||||
*/
|
||||
native bool Shavit_GetAutoJumpOnStart(int client);
|
||||
|
||||
|
||||
// taken from shavit's oryx
|
||||
stock bool IsSurfing(int client)
|
||||
{
|
||||
float fPosition[3];
|
||||
GetClientAbsOrigin(client, fPosition);
|
||||
|
||||
float fEnd[3];
|
||||
fEnd = fPosition;
|
||||
fEnd[2] -= 64.0;
|
||||
|
||||
float fMins[3];
|
||||
GetEntPropVector(client, Prop_Send, "m_vecMins", fMins);
|
||||
|
||||
float fMaxs[3];
|
||||
GetEntPropVector(client, Prop_Send, "m_vecMaxs", fMaxs);
|
||||
|
||||
Handle hTR = TR_TraceHullFilterEx(fPosition, fEnd, fMins, fMaxs, MASK_PLAYERSOLID, TRFilter_NoPlayers, client);
|
||||
|
||||
if(TR_DidHit(hTR))
|
||||
{
|
||||
float fNormal[3];
|
||||
TR_GetPlaneNormal(hTR, fNormal);
|
||||
|
||||
delete hTR;
|
||||
|
||||
// If the plane normal's Z axis is 0.7 or below (alternatively, -0.7 when upside-down) then it's a surf ramp.
|
||||
// https://github.com/alliedmodders/hl2sdk/blob/92dcf04225a278b75170cc84917f04e98f5d08ec/game/server/physics_main.cpp#L1059
|
||||
// https://github.com/ValveSoftware/source-sdk-2013/blob/0d8dceea4310fde5706b3ce1c70609d72a38efdf/mp/src/game/server/physics_main.cpp#L1065
|
||||
|
||||
return (-0.7 <= fNormal[2] <= 0.7);
|
||||
}
|
||||
|
||||
delete hTR;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
stock bool TRFilter_NoPlayers(int entity, int mask, any data)
|
||||
{
|
||||
return !(entity < MaxClients);
|
||||
}
|
||||
|
||||
|
||||
public SharedPlugin __pl_shavit_tas =
|
||||
{
|
||||
name = "shavit-tas",
|
||||
file = "shavit-tas.smx",
|
||||
#if defined REQUIRE_PLUGIN
|
||||
required = 1
|
||||
#else
|
||||
required = 0
|
||||
#endif
|
||||
};
|
||||
|
||||
#if !defined REQUIRE_PLUGIN
|
||||
public void __pl_shavit_tas_SetNTVOptional()
|
||||
{
|
||||
MarkNativeAsOptional("Shavit_SetAutostrafeEnabled");
|
||||
MarkNativeAsOptional("Shavit_GetAutostrafeEnabled");
|
||||
MarkNativeAsOptional("Shavit_SetAutostrafeType");
|
||||
MarkNativeAsOptional("Shavit_GetAutostrafeType");
|
||||
MarkNativeAsOptional("Shavit_SetAutostrafePower");
|
||||
MarkNativeAsOptional("Shavit_GetAutostrafePower");
|
||||
MarkNativeAsOptional("Shavit_SetAutostrafeKeyOverride");
|
||||
MarkNativeAsOptional("Shavit_GetAutostrafeKeyOverride");
|
||||
MarkNativeAsOptional("Shavit_SetAutoPrestrafe");
|
||||
MarkNativeAsOptional("Shavit_GetAutoPrestrafe");
|
||||
MarkNativeAsOptional("Shavit_SetAutoJumpOnStart");
|
||||
MarkNativeAsOptional("Shavit_GetAutoJumpOnStart");
|
||||
MarkNativeAsOptional("Shavit_SetEdgeJump");
|
||||
MarkNativeAsOptional("Shavit_GetEdgeJump");
|
||||
}
|
||||
#endif
|
103
scripting/include/shavit/weapon-stocks.inc
Normal file
103
scripting/include/shavit/weapon-stocks.inc
Normal file
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* shavit's Timer - weapon stocks
|
||||
* by: shavit
|
||||
*
|
||||
* This file is part of shavit's Timer.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined _shavit_weapon_stocks_included
|
||||
#endinput
|
||||
#endif
|
||||
#define _shavit_weapon_stocks_included
|
||||
|
||||
stock int GiveSkinnedWeapon(int client, const char[] classname)
|
||||
{
|
||||
int target_team = 0;
|
||||
int current_team = 0;
|
||||
|
||||
if (StrContains(classname, "usp") != -1)
|
||||
{
|
||||
target_team = 3;
|
||||
}
|
||||
else if (StrContains(classname, "glock") != -1)
|
||||
{
|
||||
target_team = 2;
|
||||
}
|
||||
|
||||
if (target_team != 0)
|
||||
{
|
||||
current_team = GetEntProp(client, Prop_Send, "m_iTeamNum");
|
||||
|
||||
if (current_team != target_team)
|
||||
{
|
||||
SetEntProp(client, Prop_Send, "m_iTeamNum", target_team);
|
||||
}
|
||||
}
|
||||
|
||||
int weapon = GivePlayerItem(client, classname);
|
||||
|
||||
if (current_team != target_team)
|
||||
{
|
||||
SetEntProp(client, Prop_Send, "m_iTeamNum", current_team);
|
||||
}
|
||||
|
||||
return weapon;
|
||||
}
|
||||
|
||||
stock void RemoveAllWeapons(int client)
|
||||
{
|
||||
int weapon = -1, max = GetEntPropArraySize(client, Prop_Send, "m_hMyWeapons");
|
||||
for (int i = 0; i < max; i++)
|
||||
{
|
||||
if ((weapon = GetEntPropEnt(client, Prop_Send, "m_hMyWeapons", i)) == -1)
|
||||
continue;
|
||||
|
||||
if (RemovePlayerItem(client, weapon))
|
||||
{
|
||||
AcceptEntityInput(weapon, "Kill");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stock void SetMaxWeaponAmmo(int client, int weapon, bool setClip1)
|
||||
{
|
||||
static EngineVersion engine = Engine_Unknown;
|
||||
|
||||
if (engine == Engine_Unknown)
|
||||
{
|
||||
engine = GetEngineVersion();
|
||||
}
|
||||
|
||||
int iAmmo = GetEntProp(weapon, Prop_Send, "m_iPrimaryAmmoType");
|
||||
SetEntProp(client, Prop_Send, "m_iAmmo", 255, 4, iAmmo);
|
||||
|
||||
if (engine == Engine_CSGO)
|
||||
{
|
||||
SetEntProp(weapon, Prop_Send, "m_iPrimaryReserveAmmoCount", 255);
|
||||
}
|
||||
|
||||
if (setClip1)
|
||||
{
|
||||
int amount = GetEntProp(weapon, Prop_Send, "m_iClip1") + 1;
|
||||
|
||||
if (HasEntProp(weapon, Prop_Send, "m_bBurstMode") && GetEntProp(weapon, Prop_Send, "m_bBurstMode"))
|
||||
{
|
||||
amount += 2;
|
||||
}
|
||||
|
||||
SetEntProp(weapon, Prop_Data, "m_iClip1", amount);
|
||||
}
|
||||
}
|
254
scripting/include/shavit/wr.inc
Normal file
254
scripting/include/shavit/wr.inc
Normal file
|
@ -0,0 +1,254 @@
|
|||
/*
|
||||
* shavit's Timer - wr.inc file
|
||||
* by: shavit
|
||||
*
|
||||
* This file is part of shavit's Timer.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined _shavit_wr_included
|
||||
#endinput
|
||||
#endif
|
||||
#define _shavit_wr_included
|
||||
|
||||
/**
|
||||
* Like Shavit_OnFinish, but after the insertion query was called.
|
||||
* Called from shavit-wr
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param style Style the record was done on.
|
||||
* @param time Record time.
|
||||
* @param jumps Jumps amount.
|
||||
* @param strafes Amount of strafes.
|
||||
* @param sync Sync percentage (0.0 to 100.0) or -1.0 when not measured.
|
||||
* @param rank Rank on map.
|
||||
* @param overwrite 1 - brand new record. 2 - update.
|
||||
* @param track Timer track.
|
||||
* @param oldtime The player's best time on the map before this finish.
|
||||
* @param perfs Perfect jump percentage (0.0 to 100.0) or 100.0 when not measured.
|
||||
* @param avgvel Player's average velocity throughout the run.
|
||||
* @param maxvel Player's highest reached velocity.
|
||||
* @param timestamp System time of when player finished.
|
||||
* @noreturn
|
||||
*/
|
||||
forward void Shavit_OnFinish_Post(int client, int style, float time, int jumps, int strafes, float sync, int rank, int overwrite, int track, float oldtime, float perfs, float avgvel, float maxvel, int timestamp);
|
||||
|
||||
/**
|
||||
* Called when there's a new WR on the map.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param style Style the record was done on.
|
||||
* @param time Record time.
|
||||
* @param jumps Jumps amount.
|
||||
* @param strafes Amount of strafes.
|
||||
* @param sync Sync percentage (0.0 to 100.0) or -1.0 when not measured.
|
||||
* @param track Timer track.
|
||||
* @param oldwr Time of the old WR. 0.0 if there's none.
|
||||
* @param oldtime The player's best time on the map before this finish.
|
||||
* @param perfs Perfect jump percentage (0.0 to 100.0) or 100.0 when not measured.
|
||||
* @param avgvel Player's average velocity throughout the run.
|
||||
* @param maxvel Player's highest reached velocity.
|
||||
* @param timestamp System time of when player finished.
|
||||
* @noreturn
|
||||
*/
|
||||
forward void Shavit_OnWorldRecord(int client, int style, float time, int jumps, int strafes, float sync, int track, float oldwr, float oldtime, float perfs, float avgvel, float maxvel, int timestamp);
|
||||
|
||||
/**
|
||||
* Called when an admin deletes a WR.
|
||||
*
|
||||
* @param style Style the record was done on.
|
||||
* @param id Record ID. -1 if mass deletion.
|
||||
* @param track Timer track.
|
||||
* @param accountid The account ID of the wr holder
|
||||
* @param mapname The map name.
|
||||
* @noreturn
|
||||
*/
|
||||
forward void Shavit_OnWRDeleted(int style, int id, int track, int accountid, const char[] mapname);
|
||||
|
||||
/**
|
||||
* Called after shavit-wr caches the current map's WRs.
|
||||
*
|
||||
* @noreturn
|
||||
*/
|
||||
forward void Shavit_OnWorldRecordsCached();
|
||||
|
||||
/**
|
||||
* Called before the timer finish message is printed to the users.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param everyone Is the message printed to everyone, or just the client?
|
||||
* @param snapshot A snapshot of the client's timer when printing the message.
|
||||
* @param overwrite Modify the database? 0 - no. 1 - brand new record. 2 - new personal best.
|
||||
* @param rank Rank on map.
|
||||
* @param message The finish message.
|
||||
* @param maxlen Buffer size of message.
|
||||
* @param message2 A second line of info that is printed on finish.
|
||||
* @param maxlen2 Buffer size of message2.
|
||||
*
|
||||
* @return Plugin_Handled or Plugin_Stop to stop the message. Anything else to use new values.
|
||||
*/
|
||||
forward Action Shavit_OnFinishMessage(int client, bool &everyone, timer_snapshot_t snapshot, int overwrite, int rank, char[] message, int maxlen, char[] message2, int maxlen2);
|
||||
|
||||
/**
|
||||
* Retrieves the world record for the given style/track.
|
||||
*
|
||||
* @param style Style to get the WR for.
|
||||
* @param track Timer track.
|
||||
* @return World record for the specified settings.
|
||||
*/
|
||||
native float Shavit_GetWorldRecord(int style, int track);
|
||||
|
||||
/**
|
||||
* Reloads WR leaderboards cache for the current map.
|
||||
*
|
||||
* @noreturn
|
||||
*/
|
||||
native void Shavit_ReloadLeaderboards();
|
||||
|
||||
/**
|
||||
* Saves the WR's record ID for the current map on a variable.
|
||||
* Unused in base plugins, as of pre-1.4b.
|
||||
*
|
||||
* @param style Style to get the WR for.
|
||||
* @param time Reference to the time variable. 0.0 will be returned if no records.
|
||||
* @param track Timer track.
|
||||
* @noreturn
|
||||
*/
|
||||
native void Shavit_GetWRRecordID(int style, int &recordid, int track);
|
||||
|
||||
/**
|
||||
* Saves the WR's player name on the map on a variable.
|
||||
*
|
||||
* @param style Style to get the WR for.
|
||||
* @param wrname Reference to the name variable.
|
||||
* @param wrmaxlength Max length for the string.
|
||||
* @param track Timer track.
|
||||
* @return Returns true if the player's name has been cached. False if it hasn't. `wrname` is filled with the player's name if available, otherwise the steamid if the name isn't cached, and lastly the string "none" if neither the name or steamid is available.
|
||||
*/
|
||||
native bool Shavit_GetWRName(int style, char[] wrname, int wrmaxlength, int track);
|
||||
|
||||
/**
|
||||
* Retrieves the best time of a player.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param style Style to get the PB for.
|
||||
* @param track Timer track.
|
||||
* @return Floating number of the player's best time for given style/track.
|
||||
*/
|
||||
native float Shavit_GetClientPB(int client, int style, int track);
|
||||
|
||||
/**
|
||||
* Sets the cached pb directly for the given client, style and track.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param style Style to get the PB for.
|
||||
* @param track Timer track.
|
||||
* @param time Time to set
|
||||
* @noreturn
|
||||
*/
|
||||
native void Shavit_SetClientPB(int client, int style, int track, float time);
|
||||
|
||||
/**
|
||||
* Retrieves the completions of a player.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param style Style to get the Completions for.
|
||||
* @param track Timer track.
|
||||
* @return Number of the player's Completions for given style/track.
|
||||
*/
|
||||
native int Shavit_GetClientCompletions(int client, int style, int track);
|
||||
|
||||
/**
|
||||
* Get the amount of records on the current map/style on a track.
|
||||
*
|
||||
* @param style Style.
|
||||
* @param track Timer track.
|
||||
* @return Amount of records.
|
||||
*/
|
||||
native int Shavit_GetRecordAmount(int style, int track);
|
||||
|
||||
/**
|
||||
* Calculate potential rank for a given style and time.
|
||||
*
|
||||
* @param style Style.
|
||||
* @param time Time to check for.
|
||||
* @param track Timer track.
|
||||
* @return Map rank.
|
||||
*/
|
||||
native int Shavit_GetRankForTime(int style, float time, int track);
|
||||
|
||||
/**
|
||||
* Retrieves the time of a record from a specified rank.
|
||||
*
|
||||
* @param style Style.
|
||||
* @param rank Rank to retrieve the time from.
|
||||
* @param track Timer track.
|
||||
* @return Record time. 0.0 if none.
|
||||
*/
|
||||
native float Shavit_GetTimeForRank(int style, int rank, int track);
|
||||
|
||||
/*
|
||||
* Used to delete a WR. Used to ensure Shavit_OnWRDeleted is ran.
|
||||
*
|
||||
* @param style Record style.
|
||||
* @param track Record track.
|
||||
* @param map Record map.
|
||||
* @param accountid -1 if recordid is -1. Otherwise you need the WR holder's Steam account ID. ([U:1:x])
|
||||
* @param recordid -1 to pull ID & accountid from the database.
|
||||
* @param delete_sql If this function should delete the record from the database. False might be useful if you're deleting things in bulk like sm_wipeplayer does.
|
||||
* @param update_cache If this function should update the WR cache & record info. False might be useful if you're deleting things in bulk like sm_wipeplayer does.
|
||||
* @noreturn
|
||||
*/
|
||||
native void Shavit_DeleteWR(int style, int track, const char[] map, int accountid, int recordid, bool delete_sql, bool update_cache);
|
||||
|
||||
/**
|
||||
* Deletes all map records for the specified map.
|
||||
* Plugin will refresh if map is currently on.
|
||||
*
|
||||
* @param map Map name.
|
||||
* @noreturn
|
||||
*/
|
||||
native void Shavit_WR_DeleteMap(const char[] map);
|
||||
|
||||
public SharedPlugin __pl_shavit_wr =
|
||||
{
|
||||
name = "shavit-wr",
|
||||
file = "shavit-wr.smx",
|
||||
#if defined REQUIRE_PLUGIN
|
||||
required = 1
|
||||
#else
|
||||
required = 0
|
||||
#endif
|
||||
};
|
||||
|
||||
#if !defined REQUIRE_PLUGIN
|
||||
public void __pl_shavit_wr_SetNTVOptional()
|
||||
{
|
||||
MarkNativeAsOptional("Shavit_GetClientCompletions");
|
||||
MarkNativeAsOptional("Shavit_GetClientPB");
|
||||
MarkNativeAsOptional("Shavit_SetClientPB");
|
||||
MarkNativeAsOptional("Shavit_GetRankForTime");
|
||||
MarkNativeAsOptional("Shavit_GetRecordAmount");
|
||||
MarkNativeAsOptional("Shavit_GetWorldRecord");
|
||||
MarkNativeAsOptional("Shavit_GetWRName");
|
||||
MarkNativeAsOptional("Shavit_GetWRRecordID");
|
||||
MarkNativeAsOptional("Shavit_ReloadLeaderboards");
|
||||
MarkNativeAsOptional("Shavit_WR_DeleteMap");
|
||||
MarkNativeAsOptional("Shavit_GetTimeForRank");
|
||||
MarkNativeAsOptional("Shavit_DeleteWR");
|
||||
MarkNativeAsOptional("Shavit_GetStageWR");
|
||||
MarkNativeAsOptional("Shavit_GetStagePB");
|
||||
}
|
||||
#endif
|
378
scripting/include/shavit/zones.inc
Normal file
378
scripting/include/shavit/zones.inc
Normal file
|
@ -0,0 +1,378 @@
|
|||
/*
|
||||
* shavit's Timer - zones.inc file
|
||||
* by: shavit
|
||||
*
|
||||
* This file is part of shavit's Timer.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined _shavit_zones_included
|
||||
#endinput
|
||||
#endif
|
||||
#define _shavit_zones_included
|
||||
|
||||
#define MAX_ZONES 64
|
||||
#define MAX_STAGES 51 // 😐 kind of arbitrary but also some space between this and MAX_ZONES
|
||||
|
||||
enum
|
||||
{
|
||||
Zone_Start, // starts timer
|
||||
Zone_End, // stops timer
|
||||
Zone_Respawn, // respawns the player
|
||||
Zone_Stop, // stops the player's timer
|
||||
Zone_Slay, // slays (kills) players which come to this zone
|
||||
Zone_Freestyle, // ignores style physics when at this zone. e.g. WASD when SWing
|
||||
Zone_CustomSpeedLimit, // overwrites velocity limit in the zone
|
||||
Zone_Teleport, // teleports to a defined point
|
||||
Zone_CustomSpawn, // << unused
|
||||
Zone_Easybhop, // forces easybhop whether if the player is in non-easy styles or if the server has different settings
|
||||
Zone_Slide, // allows players to slide, in order to fix parts like the 5th stage of bhop_arcane
|
||||
Zone_Airaccelerate, // custom sv_airaccelerate inside this,
|
||||
Zone_Stage, // shows time when entering zone
|
||||
Zone_NoTimerGravity, // prevents the timer from setting gravity while inside this zone
|
||||
Zone_Gravity, // lets you set a specific gravity while inside this zone
|
||||
ZONETYPES_SIZE
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
ZF_ForceRender = (1 << 0),
|
||||
ZF_Prebuilt = (1 << 1), // comes from mod_zone_* entities
|
||||
};
|
||||
|
||||
// Zone Display type
|
||||
enum
|
||||
{
|
||||
ZoneDisplay_Default,
|
||||
ZoneDisplay_Flat,
|
||||
ZoneDisplay_Box,
|
||||
ZoneDisplay_None,
|
||||
ZoneDisplay_Size
|
||||
};
|
||||
|
||||
// Zone Color, maybe we just let the user decide what color they actually want..? maybe store rgba as hex string but that would be mega long for each track
|
||||
enum
|
||||
{
|
||||
ZoneColor_Default,
|
||||
ZoneColor_White,
|
||||
ZoneColor_Red,
|
||||
ZoneColor_Orange,
|
||||
ZoneColor_Yellow,
|
||||
ZoneColor_Green,
|
||||
ZoneColor_Cyan,
|
||||
ZoneColor_Blue,
|
||||
ZoneColor_Purple,
|
||||
ZoneColor_Pink,
|
||||
ZoneColor_Size
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
ZoneWidth_Default,
|
||||
ZoneWidth_UltraThin,
|
||||
ZoneWidth_Thin,
|
||||
ZoneWidth_Normal,
|
||||
ZoneWidth_Thick,
|
||||
ZoneWidth_Size
|
||||
};
|
||||
|
||||
#if 0
|
||||
enum struct zone_cache_t
|
||||
{
|
||||
bool bZoneInitialized;
|
||||
int iType;
|
||||
int iTrack; // 0 - main, 1 - bonus1 etc
|
||||
int iEntity;
|
||||
int iDatabaseID; // when ZF_Prebuilt, this is the entity's m_iHammerID
|
||||
int iFlags;
|
||||
int iData;
|
||||
float fCorner1[3];
|
||||
float fCorner2[3];
|
||||
float fDestination[3];
|
||||
}
|
||||
#else
|
||||
enum struct zone_cache_t
|
||||
{
|
||||
bool bZoneInitialized;
|
||||
bool bPrebuilt; // comes from mod_zone_* entities
|
||||
int iZoneType;
|
||||
int iZoneTrack; // 0 - main, 1 - bonus etc
|
||||
int iEntityID;
|
||||
int iDatabaseID;
|
||||
int iZoneFlags;
|
||||
int iZoneData;
|
||||
}
|
||||
#endif
|
||||
|
||||
stock void GetZoneName(int client, int zoneType, char[] output, int size)
|
||||
{
|
||||
static char sTranslationStrings[ZONETYPES_SIZE][] = {
|
||||
"Zone_Start",
|
||||
"Zone_End",
|
||||
"Zone_Respawn",
|
||||
"Zone_Stop",
|
||||
"Zone_Slay",
|
||||
"Zone_Freestyle",
|
||||
"Zone_CustomSpeedLimit",
|
||||
"Zone_Teleport",
|
||||
"Zone_CustomSpawn",
|
||||
"Zone_Easybhop",
|
||||
"Zone_Slide",
|
||||
"Zone_Airaccelerate",
|
||||
"Zone_Stage",
|
||||
"Zone_NoTimerGravity",
|
||||
"Zone_Gravity"
|
||||
};
|
||||
|
||||
if (zoneType >= ZONETYPES_SIZE)
|
||||
FormatEx(output, size, "%T", "Zone_Unknown", client);
|
||||
else
|
||||
FormatEx(output, size, "%T", sTranslationStrings[zoneType], client);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a player enters a zone.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param type Zone type.
|
||||
* @param track Zone track.
|
||||
* @param id Zone ID.
|
||||
* @param entity Zone trigger entity index.
|
||||
* @param data Zone data if any.
|
||||
* @noreturn
|
||||
*/
|
||||
forward void Shavit_OnEnterZone(int client, int type, int track, int id, int entity, int data);
|
||||
|
||||
/**
|
||||
* Called when a player leaves a zone.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param type Zone type.
|
||||
* @param track Zone track.
|
||||
* @param id Zone ID.
|
||||
* @param entity Zone trigger entity index.
|
||||
* @param data Zone data if any.
|
||||
* @noreturn
|
||||
*/
|
||||
forward void Shavit_OnLeaveZone(int client, int type, int track, int id, int entity, int data);
|
||||
|
||||
/**
|
||||
* Called when a player leaves a zone.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param stageNumber Stage number.
|
||||
* @param message The stage time message that will be printed.
|
||||
* @param maxlen The buffer size of message.
|
||||
* @return Plugin_Handled to block the timer from printing msg to the client. Plugin_Continue to let the timer print msg.
|
||||
*/
|
||||
forward Action Shavit_OnStageMessage(int client, int stageNumber, char[] message, int maxlen);
|
||||
|
||||
/**
|
||||
* Retrieve the zone ID for a given stage number.
|
||||
* Will return exception if stagenumber doesn't have a zone.
|
||||
*
|
||||
* @param stage Stage number.
|
||||
* @param track Track number.
|
||||
* @return Zone ID of stage.
|
||||
*/
|
||||
native int Shavit_GetStageZone(int stage, int track=Track_Main);
|
||||
|
||||
/**
|
||||
* Checks if a mapzone exists.
|
||||
*
|
||||
* @param type Mapzone type.
|
||||
* @param track Mapzone track, -1 to ignore track.
|
||||
* @return Boolean value.
|
||||
*/
|
||||
native bool Shavit_ZoneExists(int type, int track);
|
||||
|
||||
/**
|
||||
* Checks if a player is inside a mapzone.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param type Mapzone type.
|
||||
* @param track Mapzone track, -1 to ignore track.
|
||||
* @return Boolean value.
|
||||
*/
|
||||
native bool Shavit_InsideZone(int client, int type, int track);
|
||||
|
||||
/**
|
||||
* Gets the specified zone's data.
|
||||
*
|
||||
* @param zoneid ID of the zone we query the data of.
|
||||
* @return Zone data. 0 if none is specified.
|
||||
*/
|
||||
native int Shavit_GetZoneData(int zoneid);
|
||||
|
||||
/**
|
||||
* Gets the specified zone's flags.
|
||||
*
|
||||
* @param zoneid ID of the zone we query the flags of.
|
||||
* @return Zone flags. 0 if none is specified.
|
||||
*/
|
||||
native int Shavit_GetZoneFlags(int zoneid);
|
||||
|
||||
/**
|
||||
* Deletes all map zones for the specified map.
|
||||
* Plugin will refresh if map is currently on.
|
||||
*
|
||||
* @param map Map name.
|
||||
* @noreturn
|
||||
*/
|
||||
native void Shavit_Zones_DeleteMap(const char[] map);
|
||||
|
||||
/**
|
||||
* Checks if a player is inside a mapzone.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param type Mapzone type.
|
||||
* @param track Mapzone track, -1 to ignore track.
|
||||
* @param zoneid Reference to variable that will hold the zone's ID.
|
||||
* @return Boolean value.
|
||||
*/
|
||||
native bool Shavit_InsideZoneGetID(int client, int type, int track, int &zoneid);
|
||||
|
||||
/**
|
||||
* Checks if a player is in the process of creating a mapzone.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @return Boolean value.
|
||||
*/
|
||||
native bool Shavit_IsClientCreatingZone(int client);
|
||||
|
||||
/**
|
||||
* Retrieve the highest stage number for a given track.
|
||||
*
|
||||
* @param track Track number.
|
||||
* @return Number of stages.
|
||||
*/
|
||||
native int Shavit_GetHighestStage(int track);
|
||||
|
||||
/**
|
||||
* Retrieve the client's current stage number.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @return The client's current stage number.
|
||||
*/
|
||||
native int Shavit_GetClientLastStage(int client);
|
||||
|
||||
/**
|
||||
* Returns the zone index for the entity if available.
|
||||
*
|
||||
* @param entity Client index.
|
||||
* @return -1 if not a zone entity. >=0 for a zone index.
|
||||
*/
|
||||
native int Shavit_GetZoneID(int entity);
|
||||
|
||||
/**
|
||||
* Returns the zone track.
|
||||
*
|
||||
* @param zoneid Zone index.
|
||||
* @return Zone track.
|
||||
*/
|
||||
native int Shavit_GetZoneTrack(int zoneid);
|
||||
|
||||
/**
|
||||
* Returns the zone type.
|
||||
*
|
||||
* @param zoneid Zone index.
|
||||
* @return Zone type.
|
||||
*/
|
||||
native int Shavit_GetZoneType(int zoneid);
|
||||
|
||||
/**
|
||||
* Retrieve the WR's stage time.
|
||||
*
|
||||
* @param track Track index.
|
||||
* @param style Style index.
|
||||
* @param stage Stage number.
|
||||
* @return The stage time of the WR run. Can be 0.0 if the WR run didn't hit the stage or if the stage doesn't exist.
|
||||
*/
|
||||
native float Shavit_GetStageWR(int track, int style, int stage);
|
||||
|
||||
/**
|
||||
* Retrieve the client's PB stage time.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param track Track index.
|
||||
* @param style Style index.
|
||||
* @param stage Stage number.
|
||||
* @return The stage time of the PB run. Can be 0.0 if the PB run didn't hit the stage or if the stage doesn't exist.
|
||||
*/
|
||||
//native float Shavit_GetStagePB(int client, int track, int style, int stage);
|
||||
|
||||
//native float Shavit_GetStageWRCP(int track, int style, int stage);
|
||||
//native float Shavit_GetStagePBCP(int client, int track, int style, int stage);
|
||||
|
||||
/**
|
||||
* Sets the player's current location as their spawn location for the specified track.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param track Timer track.
|
||||
* @param anglesonly Whether to save angles only.
|
||||
* @noreturn
|
||||
*/
|
||||
native void Shavit_SetStart(int client, int track, bool anglesonly);
|
||||
|
||||
/**
|
||||
* Deletes the player's current set start position for the specified track.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param track Timer track.
|
||||
* @noreturn
|
||||
*/
|
||||
native void Shavit_DeleteSetStart(int client, int track);
|
||||
|
||||
#if 0
|
||||
native void Shavit_RemoveAllZones();
|
||||
|
||||
native int Shavit_GetZoneCount();
|
||||
|
||||
native void Shavit_GetZone(int index, any[] zonecache, int size = sizeof(zone_cache_t));
|
||||
|
||||
native int Shavit_AddZone(any[] zonecache, int size = sizeof(zone_cache_t));
|
||||
#endif
|
||||
|
||||
public SharedPlugin __pl_shavit_zones =
|
||||
{
|
||||
name = "shavit-zones",
|
||||
file = "shavit-zones.smx",
|
||||
#if defined REQUIRE_PLUGIN
|
||||
required = 1
|
||||
#else
|
||||
required = 0
|
||||
#endif
|
||||
};
|
||||
|
||||
#if !defined REQUIRE_PLUGIN
|
||||
public void __pl_shavit_zones_SetNTVOptional()
|
||||
{
|
||||
MarkNativeAsOptional("Shavit_GetZoneData");
|
||||
MarkNativeAsOptional("Shavit_GetZoneFlags");
|
||||
MarkNativeAsOptional("Shavit_GetStageZone");
|
||||
MarkNativeAsOptional("Shavit_GetStageCount");
|
||||
MarkNativeAsOptional("Shavit_InsideZone");
|
||||
MarkNativeAsOptional("Shavit_InsideZoneGetID");
|
||||
MarkNativeAsOptional("Shavit_IsClientCreatingZone");
|
||||
MarkNativeAsOptional("Shavit_ZoneExists");
|
||||
MarkNativeAsOptional("Shavit_Zones_DeleteMap");
|
||||
MarkNativeAsOptional("Shavit_SetStart");
|
||||
MarkNativeAsOptional("Shavit_DeleteSetStart");
|
||||
MarkNativeAsOptional("Shavit_GetClientLastStage");
|
||||
MarkNativeAsOptional("Shavit_GetZoneTrack");
|
||||
MarkNativeAsOptional("Shavit_GetZoneType");
|
||||
MarkNativeAsOptional("Shavit_GetZoneID");
|
||||
}
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue