mirror of
https://github.com/shavitush/bhoptimer.git
synced 2025-12-07 18:38:26 +00:00
Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
21a7b58c82 | ||
|
|
133c4e5b12 | ||
|
|
7cbb250541 | ||
|
|
a350d7982c | ||
|
|
a5bec0403b | ||
|
|
7d3913bc3e | ||
|
|
1993c22112 | ||
|
|
71c674663f | ||
|
|
0ebfa900b9 | ||
|
|
128940ff19 | ||
|
|
00feb624c2 | ||
|
|
309cdf3acf | ||
|
|
871c67deac | ||
|
|
f924177098 | ||
|
|
b1e8e15043 | ||
|
|
f14cbf5aff | ||
|
|
d08a3078e1 | ||
|
|
16ccd0cc7c | ||
|
|
70308f3d6a | ||
|
|
378a2eae70 | ||
|
|
0b0be25c78 | ||
|
|
dce67fada9 | ||
|
|
326caccb06 | ||
|
|
4f43b628ae | ||
|
|
466bcf62df | ||
|
|
0c4a0d139d | ||
|
|
c0d5efb309 | ||
|
|
14b9674962 | ||
|
|
ee96ef9f7f |
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
@ -33,6 +33,12 @@ jobs:
|
||||
wget https://github.com/hermansimensen/eventqueue-fix/archive/refs/heads/main.tar.gz
|
||||
tar --strip-components=1 -xvzf main.tar.gz -C addons/sourcemod
|
||||
rm -rf *.zip *.tar.gz addons/sourcemod/.git* addons/sourcemod/LICENSE
|
||||
wget https://github.com/srcwr/eventqueuefixfix/releases/download/v1.0.1/eventqueuefixfix-v1.0.1-def5b0e-windows-x32.zip
|
||||
unzip eventqueuefixfix-v1.0.1-def5b0e-windows-x32.zip "addons/sourcemod/extensions/*"
|
||||
rm "addons/sourcemod/extensions/eventqueuefixfix.pdb"
|
||||
wget https://github.com/srcwr/srcwrfloppy/releases/download/v2.0.4/srcwrfloppy-v2.0.4.zip
|
||||
unzip -qO UTF-8 srcwrfloppy-v2.0.4.zip "addons/sourcemod/extensions/*"
|
||||
rm "addons/sourcemod/extensions/srcwr💾.pdb"
|
||||
|
||||
- name: Run compiler
|
||||
shell: bash
|
||||
|
||||
@ -3,6 +3,13 @@ Note: Dates are UTC+0.
|
||||
|
||||
|
||||
|
||||
# v3.?.? - ? - 2025-??-? - rtldg
|
||||
what will go here? hmm i wonder... maybe vscript pull request? maybe updating tf2 gamedata because i forgot? who knows...
|
||||
|
||||
thank pixel for finding that the 0.5s on-ground start-timer thing wasn't working
|
||||
|
||||
|
||||
|
||||
# v3.5.1 - small things - 2025-06-24 - rtldg
|
||||
- fix olivia's name in the author lists https://github.com/shavitush/bhoptimer/commit/f0ccf6dc0aa45aa72d7c428d5c8866aae28467e4
|
||||
- shavit-wr.sp - add back buttons to !delete menus (QoL) https://github.com/shavitush/bhoptimer/commit/877b71aa4d8a7735ee0eec189dd0ef6a72249180 @mourningsickness @rtldg
|
||||
|
||||
@ -25,6 +25,10 @@ Includes a records system, map zones (start/end marks etc), bonuses, HUD with us
|
||||
* [eventqueuefix](https://github.com/hermansimensen/eventqueue-fix)
|
||||
* Allows for timescaling boosters and is used to fix some exploits. (Use this instead of `boosterfix`)
|
||||
* (included in bhoptimer release zips)
|
||||
* Along with using [eventqueuefixfix](https://github.com/srcwr/eventqueuefixfix) at the same time to fix eventqueuefix on Windows after the 2025-02-18 update.
|
||||
* [srcwr💾](https://github.com/srcwr/srcwrfloppy)
|
||||
* Saves replays asynchronously (read: doesn't lag the server when saving a replay).
|
||||
* (included in bhoptimer release zips)
|
||||
* [SteamWorks](https://forums.alliedmods.net/showthread.php?t=229556)
|
||||
* Used to grab `{serverip}` in advertisements.
|
||||
* [DynamicChannels](https://github.com/Vauff/DynamicChannels)
|
||||
|
||||
@ -162,10 +162,13 @@
|
||||
}
|
||||
// search "sv_maxusrcmdprocessticks_warning at server" to find CPlayerMove::RunCommand
|
||||
// then sig the the `mov REG1,dword ptr [REG2 + OFFSET_TO_BUTTON_DISABLED_HERE]`
|
||||
// looks like these in decompiled form:
|
||||
// (windows) `param_3[0xc] = param_3[0xc] & ~param_2[0x32b];`
|
||||
// (linux) `*(uint *)(param_3 + 0x30) = uVar12 & ~param_2[0x331];`
|
||||
"CBasePlayer->m_afButtonDisabled"
|
||||
{
|
||||
"windows" "\x8B\x87\x2A\x2A\x2A\x2A\xF7\xD0\x21\x43"
|
||||
"linux" "\x8B\x83\x2A\x2A\x2A\x2A\xF7\xD0"
|
||||
"windows" "\x8B\x86\x2A\x2A\x2A\x2A\xF7\xD0\x21\x47"
|
||||
"linux" "\x8b\x93\x2A\x2A\x2A\x2A\xF7\xD2\x21\xd0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -301,10 +301,11 @@ native bool Shavit_LoadCheckpointCache(int client, any[] cache, int index, int s
|
||||
* @param cache Output cp_cache_t
|
||||
* @param index -1 if you want the cp_cache_t to be saved as "persistent data". 0 if not. greater-than-zero if you what you're doing and intentionally want to spoof the cp_cache_t creation as a checkpoint index for some reason... I recommend looking at shavit-checkpoints.sp to see how "index" and "isPersistentData" are used to see what kind of difference there is.
|
||||
* @param size sizeof(cp_cache_t) to mostly ensure the calling plugin has a matching cp_cache_t.
|
||||
* @param saveReplay Whether or not replay frames will be saved.
|
||||
*
|
||||
* @noreturn
|
||||
*/
|
||||
native void Shavit_SaveCheckpointCache(int saver, int target, any[] cache, int index, int size = sizeof(cp_cache_t));
|
||||
native void Shavit_SaveCheckpointCache(int saver, int target, any[] cache, int index, int size = sizeof(cp_cache_t), bool saveReplay = false);
|
||||
|
||||
public SharedPlugin __pl_shavit_checkpoints =
|
||||
{
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
#endif
|
||||
#define _shavit_core_included
|
||||
|
||||
#define SHAVIT_VERSION "3.5.1"
|
||||
#define SHAVIT_VERSION "3.5.2a"
|
||||
#define STYLE_LIMIT 256
|
||||
|
||||
// god i fucking hate sourcemod. NULL_VECTOR isn't const so it's not guaranteed to be 0,0,0
|
||||
|
||||
@ -42,6 +42,7 @@
|
||||
#define HUD_GLOCK (1 << 14) // makes you spawn with a Glock
|
||||
#define HUD_DEBUGTARGETNAME (1 << 15) // admin option to show current targetname & classname
|
||||
#define HUD_SPECTATORSDEAD (1 << 16) // for only showing spectators list when you're dead/spectating.
|
||||
#define HUD_PERFS_CENTER (1 << 17) // for the perf percentage in the center hud. e.g. "Jumps: 20 (66.6%)"
|
||||
|
||||
// HUD2 - these settings will *disable* elements for the main hud
|
||||
#define HUD2_TIME (1 << 0)
|
||||
|
||||
@ -365,6 +365,35 @@ stock void WriteReplayHeader(File fFile, int style, int track, float time, int s
|
||||
fFile.WriteInt32(view_as<int>(fZoneOffset[1]));
|
||||
}
|
||||
|
||||
stock void cell2buf(char[] buf, int& pos, int cell)
|
||||
{
|
||||
buf[pos++] = cell & 0xFF;
|
||||
buf[pos++] = (cell >> 8) & 0xFF;
|
||||
buf[pos++] = (cell >> 16) & 0xFF;
|
||||
buf[pos++] = (cell >> 24) & 0xFF;
|
||||
}
|
||||
|
||||
stock int WriteReplayHeaderToBuffer(char[] buf, int style, int track, float time, int steamid, int preframes, int postframes, float fZoneOffset[2], int totalframes, float tickrate, const char[] sMap)
|
||||
{
|
||||
int pos = FormatEx(buf, 512, "%d:%s\n%s", REPLAY_FORMAT_SUBVERSION, REPLAY_FORMAT_FINAL, sMap);
|
||||
pos += 1; // skip past NUL
|
||||
buf[pos++] = style & 0xFF;
|
||||
buf[pos++] = track & 0xFF;
|
||||
cell2buf(buf, pos, preframes);
|
||||
|
||||
cell2buf(buf, pos, totalframes - preframes - postframes);
|
||||
cell2buf(buf, pos, view_as<int>(time));
|
||||
cell2buf(buf, pos, steamid);
|
||||
|
||||
cell2buf(buf, pos, postframes);
|
||||
cell2buf(buf, pos, view_as<int>(tickrate));
|
||||
|
||||
cell2buf(buf, pos, view_as<int>(fZoneOffset[0]));
|
||||
cell2buf(buf, pos, view_as<int>(fZoneOffset[1]));
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
// 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)
|
||||
|
||||
@ -48,8 +48,9 @@ forward Action Shavit_ShouldSaveReplayCopy(int client, int style, float time, in
|
||||
|
||||
/**
|
||||
* Called when either a WR replay or a copy of a replay has been saved.
|
||||
* NOTE: Can be called with a delay after a run is finished due to asynchronous replay saving through extensions.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param client Client index. Can be 0 if the replay was saved asynchronously & the client disconnected super duper quick...
|
||||
* @param style Style the record was done on.
|
||||
* @param time Record time.
|
||||
* @param jumps Jumps amount.
|
||||
|
||||
50
addons/sourcemod/scripting/include/srcwr/floppy.inc
Normal file
50
addons/sourcemod/scripting/include/srcwr/floppy.inc
Normal file
@ -0,0 +1,50 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright 2025 rtldg <rtldg@protonmail.com>
|
||||
|
||||
#if defined _srcwrfloppy_included
|
||||
#endinput
|
||||
#endif
|
||||
#define _srcwrfloppy_included
|
||||
#pragma semicolon 1
|
||||
|
||||
|
||||
typeset ReplaySavedCallback {
|
||||
function void(bool saved, any value, char[] sPath);
|
||||
}
|
||||
|
||||
|
||||
// Don't modify the `playerrecording` ArrayList until the ReplaySavedCallback is called... OR ELSE!!!!
|
||||
native void SRCWRFloppy_AsyncSaveReplay(
|
||||
ReplaySavedCallback callback // what to call when saved
|
||||
, any value // what to pass along to the callback
|
||||
, char[] wrpath
|
||||
, char[] copypath
|
||||
, char[] header
|
||||
, int headersize
|
||||
, ArrayList playerrecording
|
||||
, int totalframes
|
||||
);
|
||||
|
||||
|
||||
public Extension __ext_srcwrfloppy =
|
||||
{
|
||||
name = "srcwr💾",
|
||||
file = "srcwr💾.ext",
|
||||
#if defined AUTOLOAD_EXTENSIONS
|
||||
autoload = 1,
|
||||
#else
|
||||
autoload = 0,
|
||||
#endif
|
||||
#if defined REQUIRE_EXTENSIONS
|
||||
required = 1,
|
||||
#else
|
||||
required = 0,
|
||||
#endif
|
||||
};
|
||||
|
||||
#if !defined REQUIRE_EXTENSIONS
|
||||
public void __ext_srcwrfloppy_SetNTVOptional()
|
||||
{
|
||||
MarkNativeAsOptional("SRCWRFloppy_AsyncSaveReplay");
|
||||
}
|
||||
#endif
|
||||
@ -1573,7 +1573,7 @@ bool SaveCheckpoint(int client, bool duplicate = false)
|
||||
return true;
|
||||
}
|
||||
|
||||
void SaveCheckpointCache(int saver, int target, cp_cache_t cpcache, int index, Handle plugin)
|
||||
void SaveCheckpointCache(int saver, int target, cp_cache_t cpcache, int index, Handle plugin, bool saveReplay = false)
|
||||
{
|
||||
GetClientAbsOrigin(target, cpcache.fPosition);
|
||||
GetClientEyeAngles(target, cpcache.fAngles);
|
||||
@ -1687,7 +1687,7 @@ void SaveCheckpointCache(int saver, int target, cp_cache_t cpcache, int index, H
|
||||
cpcache.aSnapshot = snapshot;
|
||||
cpcache.bSegmented = CanSegment(target);
|
||||
|
||||
if (cpcache.bSegmented && gB_ReplayRecorder && index != -1 && cpcache.aFrames == null)
|
||||
if (saveReplay || (cpcache.bSegmented && gB_ReplayRecorder && index != -1 && cpcache.aFrames == null))
|
||||
{
|
||||
ArrayList frames = Shavit_GetReplayData(target, false);
|
||||
|
||||
@ -2218,6 +2218,7 @@ public any Native_SaveCheckpointCache(Handle plugin, int numParams)
|
||||
int target = GetNativeCell(2);
|
||||
cp_cache_t cache;
|
||||
int index = GetNativeCell(4);
|
||||
SaveCheckpointCache(saver, target, cache, index, plugin);
|
||||
bool saveReplay = (numParams >= 6 && GetNativeCell(5));
|
||||
SaveCheckpointCache(saver, target, cache, index, plugin, saveReplay);
|
||||
return SetNativeArray(3, cache, sizeof(cp_cache_t));
|
||||
}
|
||||
|
||||
@ -92,7 +92,8 @@ Handle gH_Forwards_OnProcessMovementPost = null;
|
||||
// player timer variables
|
||||
timer_snapshot_t gA_Timers[MAXPLAYERS+1];
|
||||
bool gB_Auto[MAXPLAYERS+1];
|
||||
int gI_FirstTouchedGround[MAXPLAYERS+1];
|
||||
// 0 is in air, 1 or greater is on ground, -1 means client was on ground with zero...ish... velocity
|
||||
int gI_FirstTouchedGroundForStartTimer[MAXPLAYERS+1];
|
||||
int gI_LastTickcount[MAXPLAYERS+1];
|
||||
|
||||
// these are here until the compiler bug is fixed
|
||||
@ -2300,7 +2301,7 @@ public int Native_SetPracticeMode(Handle handler, int numParams)
|
||||
bool practice = view_as<bool>(GetNativeCell(2));
|
||||
bool alert = view_as<bool>(GetNativeCell(3));
|
||||
|
||||
if(alert && practice && !gA_Timers[client].bPracticeMode && (!gB_HUD || (Shavit_GetHUDSettings(client) & HUD_NOPRACALERT) == 0))
|
||||
if(alert && practice && !gA_Timers[client].bPracticeMode && (!gB_HUD || (Shavit_GetHUDSettings(client) & HUD_NOPRACALERT) == 0) && !Shavit_InsideZone(client, Zone_Start, -1))
|
||||
{
|
||||
Shavit_PrintToChat(client, "%T", "PracticeModeAlert", client, gS_ChatStrings.sWarning, gS_ChatStrings.sText);
|
||||
}
|
||||
@ -2569,10 +2570,20 @@ bool CanStartTimer(int client, int track, bool skipGroundCheck)
|
||||
|
||||
if (skipGroundTimer) return true;
|
||||
|
||||
int halfSecOfTicks = RoundFloat(0.5 / GetTickInterval());
|
||||
int onGroundTicks = gI_LastTickcount[client] - gI_FirstTouchedGround[client];
|
||||
if (gI_FirstTouchedGroundForStartTimer[client] < 0)
|
||||
{
|
||||
// was on ground with zero...ish... velocity...
|
||||
return true;
|
||||
}
|
||||
else if (gI_FirstTouchedGroundForStartTimer[client] > 0)
|
||||
{
|
||||
int halfSecOfTicks = RoundFloat(0.5 / GetTickInterval());
|
||||
int onGroundTicks = gI_LastTickcount[client] - gI_FirstTouchedGroundForStartTimer[client];
|
||||
|
||||
return onGroundTicks >= halfSecOfTicks;
|
||||
return onGroundTicks >= halfSecOfTicks;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void StartTimer(int client, int track, bool skipGroundCheck)
|
||||
@ -2764,7 +2775,7 @@ public void OnClientPutInServer(int client)
|
||||
gA_Timers[client].fNextFrameTime = 0.0;
|
||||
gA_Timers[client].fplayer_speedmod = 1.0;
|
||||
gS_DeleteMap[client][0] = 0;
|
||||
gI_FirstTouchedGround[client] = 0;
|
||||
gI_FirstTouchedGroundForStartTimer[client] = 0;
|
||||
gI_LastTickcount[client] = 0;
|
||||
gI_HijackFrames[client] = 0;
|
||||
gI_LastPrintedSteamID[client] = 0;
|
||||
@ -3647,10 +3658,35 @@ public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3
|
||||
|
||||
gI_LastTickcount[client] = tickcount;
|
||||
|
||||
if (bOnGround)
|
||||
{
|
||||
if (gI_FirstTouchedGroundForStartTimer[client] == 0)
|
||||
{
|
||||
// just landed (or teleported to the ground or whatever)
|
||||
gI_FirstTouchedGroundForStartTimer[client] = tickcount;
|
||||
}
|
||||
|
||||
if (gI_FirstTouchedGroundForStartTimer[client] > 0)
|
||||
{
|
||||
float fSpeed[3];
|
||||
GetEntPropVector(client, Prop_Data, "m_vecAbsVelocity", fSpeed);
|
||||
|
||||
// zero...ish... velocity... (squared-ish (cubed?))
|
||||
if (GetVectorLength(fSpeed, true) <= 1000.0)
|
||||
{
|
||||
gI_FirstTouchedGroundForStartTimer[client] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gI_FirstTouchedGroundForStartTimer[client] = 0;
|
||||
}
|
||||
|
||||
if(bOnGround && !gA_Timers[client].bOnGround)
|
||||
{
|
||||
gA_Timers[client].iLandingTick = tickcount;
|
||||
gI_FirstTouchedGround[client] = tickcount;
|
||||
gI_FirstTouchedGroundForStartTimer[client] = tickcount;
|
||||
|
||||
if (gEV_Type != Engine_TF2 && GetStyleSettingBool(gA_Timers[client].bsStyle, "easybhop"))
|
||||
{
|
||||
|
||||
@ -209,6 +209,7 @@ public void OnPluginStart()
|
||||
..."HUD_USP 8192\n"
|
||||
..."HUD_GLOCK 16384\n"
|
||||
..."HUD_SPECTATORSDEAD 65536\n"
|
||||
..."HUD_PERFS_CENTER 131072\n"
|
||||
);
|
||||
|
||||
IntToString(HUD_DEFAULT2, defaultHUD, 8);
|
||||
@ -776,6 +777,10 @@ Action ShowHUDMenu(int client, int item)
|
||||
FormatEx(sHudItem, 64, "%T", "HudPerfs", client);
|
||||
menu.AddItem(sInfo, sHudItem);
|
||||
|
||||
FormatEx(sInfo, 16, "!%d", HUD_PERFS_CENTER);
|
||||
FormatEx(sHudItem, 64, "%T", "HudPerfsCenter", client);
|
||||
menu.AddItem(sInfo, sHudItem);
|
||||
|
||||
FormatEx(sInfo, 16, "@%d", HUD2_STYLE);
|
||||
FormatEx(sHudItem, 64, "%T", "HudStyleText", client);
|
||||
menu.AddItem(sInfo, sHudItem);
|
||||
@ -1369,7 +1374,15 @@ int AddHUDToBuffer_Source2013(int client, huddata_t data, char[] buffer, int max
|
||||
|
||||
if((gI_HUD2Settings[client] & HUD2_JUMPS) == 0)
|
||||
{
|
||||
FormatEx(sLine, 128, "%T: %d", "HudJumpsText", client, data.iJumps);
|
||||
if (!Shavit_GetStyleSettingBool(data.iStyle, "autobhop") && (gI_HUDSettings[client] & HUD_PERFS_CENTER))
|
||||
{
|
||||
FormatEx(sLine, 128, "%T: %d (%.1f%)", "HudJumpsText", client, data.iJumps, Shavit_GetPerfectJumps(data.iTarget));
|
||||
}
|
||||
else
|
||||
{
|
||||
FormatEx(sLine, 128, "%T: %d", "HudJumpsText", client, data.iJumps);
|
||||
}
|
||||
|
||||
AddHUDLine(buffer, maxlen, sLine, iLines);
|
||||
}
|
||||
|
||||
|
||||
@ -1929,7 +1929,16 @@ bool Teleport(int client, int targetserial)
|
||||
float vecPosition[3];
|
||||
GetClientAbsOrigin(iTarget, vecPosition);
|
||||
|
||||
Shavit_StopTimer(client);
|
||||
if(Shavit_GetTimerStatus(client) == Timer_Running || !gCV_PauseMovement.BoolValue)
|
||||
{
|
||||
if(ShouldDisplayStopWarning(client))
|
||||
{
|
||||
gI_LastStopInfo[client] = targetserial;
|
||||
OpenStopWarningMenu(client, DoTeleport);
|
||||
return true;
|
||||
}
|
||||
Shavit_StopTimer(client);
|
||||
}
|
||||
|
||||
TeleportEntity(client, vecPosition, NULL_VECTOR, NULL_VECTOR);
|
||||
|
||||
@ -2040,6 +2049,12 @@ void DoStopTimer(int client)
|
||||
Shavit_StopTimer(client);
|
||||
}
|
||||
|
||||
void DoTeleport(int client)
|
||||
{
|
||||
Shavit_StopTimer(client);
|
||||
Teleport(client, gI_LastStopInfo[client]);
|
||||
}
|
||||
|
||||
void OpenStopWarningMenu(int client, StopTimerCallback after)
|
||||
{
|
||||
gH_AfterWarningMenu[client] = after;
|
||||
@ -2439,7 +2454,7 @@ public void Shavit_OnRestart(int client, int track)
|
||||
{
|
||||
SetEntPropFloat(client, Prop_Send, "m_flStamina", 0.0);
|
||||
|
||||
if (gCV_RestartWithFullHP.BoolValue)
|
||||
if (gCV_RestartWithFullHP.BoolValue && GetClientHealth(client) <= 100)
|
||||
{
|
||||
SetEntityHealth(client, 100);
|
||||
SetEntProp(client, Prop_Send, "m_ArmorValue", 100);
|
||||
|
||||
@ -631,9 +631,11 @@ public Action Command_SetTier(int client, int args)
|
||||
|
||||
int tier = StringToInt(sArg);
|
||||
|
||||
if(args == 0 || tier < 1 || tier > 10)
|
||||
int maxtier = GetMaxTier();
|
||||
|
||||
if(args == 0 || tier < 1 || tier > maxtier)
|
||||
{
|
||||
ReplyToCommand(client, "%T", "ArgumentsMissing", client, "sm_settier <tier> (1-10) [map]");
|
||||
ReplyToCommand(client, "%T", "ArgumentsMissing", client, "sm_settier <tier> (1-%d) [map]", maxtier);
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
@ -1722,3 +1724,10 @@ public void SQL_DeleteMap_Callback(Database db, DBResultSet results, const char[
|
||||
UpdateAllPoints(true);
|
||||
}
|
||||
}
|
||||
|
||||
int GetMaxTier()
|
||||
{
|
||||
float val = 10.0;
|
||||
gCV_DefaultTier.GetBounds(ConVarBound_Upper, val);
|
||||
return RoundToFloor(val);
|
||||
}
|
||||
|
||||
@ -2763,6 +2763,12 @@ public void Player_Event(Event event, const char[] name, bool dontBroadcast)
|
||||
KickReplay(gA_BotInfo[index]);
|
||||
}
|
||||
}
|
||||
|
||||
if(IsPlayerAlive(client) && gB_InReplayMenu[client])
|
||||
{
|
||||
CancelClientMenu(client);
|
||||
gB_InReplayMenu[client] = false;
|
||||
}
|
||||
}
|
||||
|
||||
public Action BotEvents(Event event, const char[] name, bool dontBroadcast)
|
||||
@ -2995,18 +3001,21 @@ public int DeleteConfirmation_Callback(Menu menu, MenuAction action, int param1,
|
||||
menu.GetItem(param2, sInfo, 4);
|
||||
int style = StringToInt(sInfo);
|
||||
|
||||
if (style != -1 && DeleteReplay(style, gI_MenuTrack[param1], 0, gS_Map))
|
||||
if (style != -1)
|
||||
{
|
||||
char sTrack[32];
|
||||
GetTrackName(param1, gI_MenuTrack[param1], sTrack, 32);
|
||||
if (DeleteReplay(style, gI_MenuTrack[param1], 0, gS_Map))
|
||||
{
|
||||
char sTrack[32];
|
||||
GetTrackName(param1, gI_MenuTrack[param1], sTrack, 32);
|
||||
|
||||
LogAction(param1, param1, "Deleted replay for %s on map %s. (Track: %s)", gS_StyleStrings[style].sStyleName, gS_Map, sTrack);
|
||||
LogAction(param1, param1, "Deleted replay for %s on map %s. (Track: %s)", gS_StyleStrings[style].sStyleName, gS_Map, sTrack);
|
||||
|
||||
Shavit_PrintToChat(param1, "%T (%s%s%s)", "ReplayDeleted", param1, gS_ChatStrings.sStyle, gS_StyleStrings[style].sStyleName, gS_ChatStrings.sText, gS_ChatStrings.sVariable, sTrack, gS_ChatStrings.sText);
|
||||
}
|
||||
else
|
||||
{
|
||||
Shavit_PrintToChat(param1, "%T", "ReplayDeleteFailure", param1, gS_ChatStrings.sStyle, gS_StyleStrings[style].sStyleName, gS_ChatStrings.sText);
|
||||
Shavit_PrintToChat(param1, "%T (%s%s%s)", "ReplayDeleted", param1, gS_ChatStrings.sStyle, gS_StyleStrings[style].sStyleName, gS_ChatStrings.sText, gS_ChatStrings.sVariable, sTrack, gS_ChatStrings.sText);
|
||||
}
|
||||
else
|
||||
{
|
||||
Shavit_PrintToChat(param1, "%T", "ReplayDeleteFailure", param1, gS_ChatStrings.sStyle, gS_StyleStrings[style].sStyleName, gS_ChatStrings.sText);
|
||||
}
|
||||
}
|
||||
|
||||
Command_DeleteReplay(param1, 0);
|
||||
|
||||
@ -34,6 +34,10 @@
|
||||
#include <shavit/replay-file>
|
||||
#include <shavit/replay-stocks.sp>
|
||||
|
||||
#undef REQUIRE_EXTENSIONS
|
||||
#include <srcwr/floppy>
|
||||
|
||||
|
||||
public Plugin myinfo =
|
||||
{
|
||||
name = "[shavit] Replay Recorder",
|
||||
@ -94,6 +98,7 @@ float gF_HijackedAngles[MAXPLAYERS+1][2];
|
||||
bool gB_HijackFramesKeepOnStart[MAXPLAYERS+1];
|
||||
|
||||
bool gB_ReplayPlayback = false;
|
||||
bool gB_Floppy = false;
|
||||
|
||||
//#include <TickRateControl>
|
||||
forward void TickRate_OnTickRateChanged(float fOld, float fNew);
|
||||
@ -142,13 +147,14 @@ public void OnPluginStart()
|
||||
gCV_PlaybackPostRunTime = new Convar("shavit_replay_postruntime", "1.5", "Time (in seconds) to record after a player enters the end zone.", 0, true, 0.0, true, 2.0);
|
||||
gCV_PreRunAlways = new Convar("shavit_replay_prerun_always", "1", "Record prerun frames outside the start zone?", 0, true, 0.0, true, 1.0);
|
||||
gCV_PlaybackPreRunTime = new Convar("shavit_replay_preruntime", "1.5", "Time (in seconds) to record before a player leaves start zone.", 0, true, 0.0, true, 2.0);
|
||||
gCV_TimeLimit = new Convar("shavit_replay_timelimit", "7200.0", "Maximum amount of time (in seconds) to allow saving to disk.\nDefault is 7200 (2 hours)\n0 - Disabled", 0, true, 0.0);
|
||||
gCV_TimeLimit = new Convar("shavit_replay_timelimit", "7200.0", "Maximum amount of time (in seconds) to allow saving to disk.\nDefault is 7200 (2 hours)\n0 - Disabled (no replays will be recorded)", 0, true, 0.0);
|
||||
|
||||
Convar.AutoExecConfig();
|
||||
|
||||
gF_Tickrate = (1.0 / GetTickInterval());
|
||||
|
||||
gB_ReplayPlayback = LibraryExists("shavit-replay-playback");
|
||||
gB_Floppy = LibraryExists("srcwr💾");
|
||||
|
||||
if (gB_Late)
|
||||
{
|
||||
@ -170,6 +176,10 @@ public void OnLibraryAdded(const char[] name)
|
||||
{
|
||||
gB_ReplayPlayback = true;
|
||||
}
|
||||
else if (StrEqual(name, "srcwr💾"))
|
||||
{
|
||||
gB_Floppy = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnLibraryRemoved(const char[] name)
|
||||
@ -178,6 +188,10 @@ public void OnLibraryRemoved(const char[] name)
|
||||
{
|
||||
gB_ReplayPlayback = false;
|
||||
}
|
||||
else if (StrEqual(name, "srcwr💾"))
|
||||
{
|
||||
gB_Floppy = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnMapStart()
|
||||
@ -204,6 +218,8 @@ public void OnClientPutInServer(int client)
|
||||
|
||||
public void OnClientDisconnect(int client)
|
||||
{
|
||||
gB_RecordingEnabled[client] = false; // reset a little state...
|
||||
|
||||
if (gB_GrabbingPostFrames[client])
|
||||
{
|
||||
FinishGrabbingPostFrames(client, gA_FinishedRunInfo[client]);
|
||||
@ -376,13 +392,94 @@ void DoReplaySaverCallbacks(int iSteamID, int client, int style, float time, int
|
||||
|
||||
int postframes = gI_PlayerFrames[client] - gI_PlayerFinishFrame[client];
|
||||
|
||||
char sPath[PLATFORM_MAX_PATH];
|
||||
bool saved = SaveReplay(style, track, time, iSteamID, gI_PlayerPrerunFrames[client], gA_PlayerFrames[client], gI_PlayerFrames[client], postframes, timestamp, fZoneOffset, makeCopy, makeReplay, sPath, sizeof(sPath));
|
||||
ArrayList playerrecording = view_as<ArrayList>(CloneHandle(gA_PlayerFrames[client]));
|
||||
|
||||
DataPack dp = new DataPack();
|
||||
dp.WriteCell(GetClientSerial(client));
|
||||
dp.WriteCell(style);
|
||||
dp.WriteCell(time);
|
||||
dp.WriteCell(jumps);
|
||||
dp.WriteCell(strafes);
|
||||
dp.WriteCell(sync);
|
||||
dp.WriteCell(track);
|
||||
dp.WriteCell(oldtime);
|
||||
dp.WriteCell(perfs);
|
||||
dp.WriteCell(avgvel);
|
||||
dp.WriteCell(maxvel);
|
||||
dp.WriteCell(timestamp);
|
||||
dp.WriteCell(isBestReplay);
|
||||
dp.WriteCell(isTooLong);
|
||||
dp.WriteCell(makeCopy);
|
||||
dp.WriteCell(playerrecording);
|
||||
dp.WriteCell(gI_PlayerPrerunFrames[client]);
|
||||
dp.WriteCell(postframes);
|
||||
dp.WriteString(sName);
|
||||
|
||||
if (gB_Floppy)
|
||||
{
|
||||
char buf[512];
|
||||
int headersize = WriteReplayHeaderToBuffer(buf, style, track, time, iSteamID, gI_PlayerPrerunFrames[client], postframes, fZoneOffset, gI_PlayerFrames[client], gF_Tickrate, gS_Map);
|
||||
|
||||
char wrpath[PLATFORM_MAX_PATH], copypath[PLATFORM_MAX_PATH];
|
||||
if (makeReplay)
|
||||
FormatEx(wrpath, sizeof(wrpath),
|
||||
track>0?"%s/%d/%s_%d.replay" : "%s/%d/%s.replay",
|
||||
gS_ReplayFolder, style, gS_Map, track
|
||||
);
|
||||
if (makeCopy)
|
||||
FormatEx(copypath, sizeof(copypath), "%s/copy/%d_%d_%s.replay", gS_ReplayFolder, timestamp, iSteamID, gS_Map);
|
||||
|
||||
SRCWRFloppy_AsyncSaveReplay(
|
||||
FloppyAsynchronouslySavedMyReplayWhichWasNiceOfThem
|
||||
, dp
|
||||
, wrpath
|
||||
, copypath
|
||||
, buf
|
||||
, headersize
|
||||
, playerrecording
|
||||
, gI_PlayerFrames[client]
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
char sPath[PLATFORM_MAX_PATH];
|
||||
bool saved = SaveReplay(style, track, time, iSteamID, gI_PlayerPrerunFrames[client], playerrecording, gI_PlayerFrames[client], postframes, timestamp, fZoneOffset, makeCopy, makeReplay, sPath, sizeof(sPath));
|
||||
FloppyAsynchronouslySavedMyReplayWhichWasNiceOfThem(saved, dp, sPath)
|
||||
}
|
||||
|
||||
ClearFrames(client);
|
||||
}
|
||||
|
||||
void FloppyAsynchronouslySavedMyReplayWhichWasNiceOfThem(bool saved, any value, char[] sPath)
|
||||
{
|
||||
DataPack dp = value;
|
||||
dp.Reset();
|
||||
|
||||
int client = GetClientFromSerial(dp.ReadCell());
|
||||
int style = dp.ReadCell();
|
||||
float time = dp.ReadCell();
|
||||
int jumps = dp.ReadCell();
|
||||
int strafes = dp.ReadCell();
|
||||
float sync = dp.ReadCell();
|
||||
int track = dp.ReadCell();
|
||||
float oldtime = dp.ReadCell();
|
||||
float perfs = dp.ReadCell();
|
||||
float avgvel = dp.ReadCell();
|
||||
float maxvel = dp.ReadCell();
|
||||
int timestamp = dp.ReadCell();
|
||||
bool isBestReplay = dp.ReadCell();
|
||||
bool isTooLong = dp.ReadCell();
|
||||
bool makeCopy = dp.ReadCell();
|
||||
ArrayList playerrecording = dp.ReadCell();
|
||||
int preframes = dp.ReadCell();
|
||||
int postframes = dp.ReadCell();
|
||||
char sName[MAX_NAME_LENGTH];
|
||||
dp.ReadString(sName, sizeof(sName));
|
||||
|
||||
if (!saved)
|
||||
{
|
||||
LogError("SaveReplay() failed. Skipping OnReplaySaved")
|
||||
ClearFrames(client);
|
||||
LogError("Failed to save replay... Skipping OnReplaySaved");
|
||||
delete playerrecording; // importante!
|
||||
return;
|
||||
}
|
||||
|
||||
@ -403,13 +500,13 @@ void DoReplaySaverCallbacks(int iSteamID, int client, int style, float time, int
|
||||
Call_PushCell(isTooLong);
|
||||
Call_PushCell(makeCopy);
|
||||
Call_PushString(sPath);
|
||||
Call_PushCell(gA_PlayerFrames[client]);
|
||||
Call_PushCell(gI_PlayerPrerunFrames[client]);
|
||||
Call_PushCell(playerrecording);
|
||||
Call_PushCell(preframes);
|
||||
Call_PushCell(postframes);
|
||||
Call_PushString(sName);
|
||||
Call_Finish();
|
||||
|
||||
ClearFrames(client);
|
||||
delete playerrecording;
|
||||
}
|
||||
|
||||
public void Shavit_OnFinish(int client, int style, float time, int jumps, int strafes, float sync, int track, float oldtime, float perfs, float avgvel, float maxvel, int timestamp)
|
||||
@ -467,16 +564,6 @@ bool SaveReplay(int style, int track, float time, int steamid, int preframes, Ar
|
||||
File fWR = null;
|
||||
File fCopy = null;
|
||||
|
||||
if (saveWR)
|
||||
{
|
||||
FormatEx(sPath, sPathLen, "%s/%d/%s%s.replay", gS_ReplayFolder, style, gS_Map, (track > 0)? sTrack:"");
|
||||
|
||||
if (!(fWR = OpenFile(sPath, "wb+")))
|
||||
{
|
||||
LogError("Failed to open WR replay file for writing. ('%s')", sPath);
|
||||
}
|
||||
}
|
||||
|
||||
if (saveCopy)
|
||||
{
|
||||
FormatEx(sPath, sPathLen, "%s/copy/%d_%d_%s.replay", gS_ReplayFolder, timestamp, steamid, gS_Map);
|
||||
@ -487,6 +574,16 @@ bool SaveReplay(int style, int track, float time, int steamid, int preframes, Ar
|
||||
}
|
||||
}
|
||||
|
||||
if (saveWR)
|
||||
{
|
||||
FormatEx(sPath, sPathLen, "%s/%d/%s%s.replay", gS_ReplayFolder, style, gS_Map, (track > 0)? sTrack:"");
|
||||
|
||||
if (!(fWR = OpenFile(sPath, "wb+")))
|
||||
{
|
||||
LogError("Failed to open WR replay file for writing. ('%s')", sPath);
|
||||
}
|
||||
}
|
||||
|
||||
if (!fWR && !fCopy)
|
||||
{
|
||||
// I want to try and salvage the replay file so let's write it out to a random
|
||||
@ -658,6 +755,9 @@ public int Native_SetReplayData(Handle handler, int numParams)
|
||||
FinishGrabbingPostFrames(client, gA_FinishedRunInfo[client]);
|
||||
}
|
||||
|
||||
// Player starts run, reconnects, savestate reloads, and this needs to be true...
|
||||
gB_RecordingEnabled[client] = true;
|
||||
|
||||
if (cheapCloneHandle)
|
||||
{
|
||||
data = view_as<ArrayList>(CloneHandle(data));
|
||||
|
||||
@ -56,6 +56,7 @@ int gI_MapType[MAXPLAYERS+1];
|
||||
int gI_Style[MAXPLAYERS+1];
|
||||
int gI_MenuPos[MAXPLAYERS+1];
|
||||
int gI_Track[MAXPLAYERS+1];
|
||||
int gI_Tier[MAXPLAYERS+1];
|
||||
int gI_TargetSteamID[MAXPLAYERS+1];
|
||||
char gS_TargetName[MAXPLAYERS+1][MAX_NAME_LENGTH];
|
||||
|
||||
@ -436,7 +437,7 @@ void SavePlaytime222(int client, float now, Transaction&trans, int style, int iS
|
||||
if (gI_CurrentStyle[client] == style && gF_PlaytimeStyleStart[client] != 0.0)
|
||||
{
|
||||
diff += now - gF_PlaytimeStyleStart[client];
|
||||
gF_PlaytimeStyleStart[client] = IsPlayerAlive(client) ? now : 0.0;
|
||||
gF_PlaytimeStyleStart[client] = IsClientInGame(client) ? IsPlayerAlive(client) ? now : 0.0 : 0.0;
|
||||
}
|
||||
|
||||
gF_PlaytimeStyleSum[client][style] = 0.0;
|
||||
@ -753,10 +754,47 @@ public int MenuHandler_MapsDoneLeft_Track(Menu menu, MenuAction action, int para
|
||||
{
|
||||
if(action == MenuAction_Select)
|
||||
{
|
||||
char sInfo[8];
|
||||
char sInfo[8], sTier[16];
|
||||
menu.GetItem(param2, sInfo, 8);
|
||||
gI_Track[param1] = StringToInt(sInfo);
|
||||
|
||||
if(gB_Rankings)
|
||||
{
|
||||
Menu submenu = new Menu(MenuHandler_MapsDoneLeft_Tier);
|
||||
submenu.SetTitle("%T\n ", "SelectTier", param1);
|
||||
|
||||
submenu.AddItem("0", "All");
|
||||
|
||||
for(int i = 1; i <= 10; ++i)
|
||||
{
|
||||
IntToString(i, sInfo, 8);
|
||||
FormatEx(sTier, 16, "Tier %d", i);
|
||||
submenu.AddItem(sInfo, sTier);
|
||||
}
|
||||
|
||||
submenu.Display(param1, MENU_TIME_FOREVER);
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowMaps(param1);
|
||||
}
|
||||
}
|
||||
else if(action == MenuAction_End)
|
||||
{
|
||||
delete menu;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int MenuHandler_MapsDoneLeft_Tier(Menu menu, MenuAction action, int param1, int param2)
|
||||
{
|
||||
if(action == MenuAction_Select)
|
||||
{
|
||||
char sInfo[8];
|
||||
menu.GetItem(param2, sInfo, 8);
|
||||
gI_Tier[param1] = StringToInt(sInfo);
|
||||
|
||||
ShowMaps(param1);
|
||||
}
|
||||
else if(action == MenuAction_End)
|
||||
@ -1180,7 +1218,7 @@ public int MenuHandler_TypeHandler(Menu menu, MenuAction action, int param1, int
|
||||
{
|
||||
if(action == MenuAction_Select)
|
||||
{
|
||||
char sInfo[32];
|
||||
char sInfo[32], sTier[16];
|
||||
menu.GetItem(param2, sInfo, 32);
|
||||
|
||||
char sExploded[2][4];
|
||||
@ -1189,7 +1227,26 @@ public int MenuHandler_TypeHandler(Menu menu, MenuAction action, int param1, int
|
||||
gI_Track[param1] = StringToInt(sExploded[0]);
|
||||
gI_MapType[param1] = StringToInt(sExploded[1]);
|
||||
|
||||
ShowMaps(param1);
|
||||
if(gB_Rankings)
|
||||
{
|
||||
Menu submenu = new Menu(MenuHandler_MapsDoneLeft_Tier);
|
||||
submenu.SetTitle("%T\n ", "SelectTier", param1);
|
||||
|
||||
submenu.AddItem("0", "All");
|
||||
|
||||
for(int i = 1; i <= 10; ++i)
|
||||
{
|
||||
IntToString(i, sInfo, 8);
|
||||
FormatEx(sTier, 16, "Tier %d", i);
|
||||
submenu.AddItem(sInfo, sTier);
|
||||
}
|
||||
|
||||
submenu.Display(param1, MENU_TIME_FOREVER);
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowMaps(param1);
|
||||
}
|
||||
}
|
||||
else if(action == MenuAction_Cancel && param2 == MenuCancel_ExitBack)
|
||||
{
|
||||
@ -1210,21 +1267,39 @@ void ShowMaps(int client)
|
||||
return;
|
||||
}
|
||||
|
||||
char sQuery[512];
|
||||
char sQuery[512], tierStr[32];
|
||||
|
||||
if(gI_Tier[client] > 0)
|
||||
{
|
||||
FormatEx(tierStr, 32, " AND t.tier = %d", gI_Tier[client]);
|
||||
}
|
||||
else
|
||||
{
|
||||
gI_Tier[client] = 0;
|
||||
}
|
||||
|
||||
if(gI_MapType[client] == MAPSDONE)
|
||||
{
|
||||
FormatEx(sQuery, 512,
|
||||
"SELECT a.map, a.time, a.jumps, a.id, COUNT(b.map) + 1 as 'rank', a.points FROM %splayertimes a LEFT JOIN %splayertimes b ON a.time > b.time AND a.map = b.map AND a.style = b.style AND a.track = b.track WHERE a.auth = %d AND a.style = %d AND a.track = %d GROUP BY a.map, a.time, a.jumps, a.id, a.points ORDER BY a.%s;",
|
||||
gS_MySQLPrefix, gS_MySQLPrefix, gI_TargetSteamID[client], gI_Style[client], gI_Track[client], (gB_Rankings)? "points DESC":"map");
|
||||
if(gB_Rankings)
|
||||
{
|
||||
FormatEx(sQuery, 512,
|
||||
"SELECT a.map, a.time, a.jumps, a.id, COUNT(b.map) + 1 as 'rank', a.points FROM %splayertimes a LEFT JOIN %splayertimes b ON a.time > b.time AND a.map = b.map AND a.style = b.style AND a.track = b.track LEFT JOIN %smaptiers t ON a.map = t.map WHERE a.auth = %d AND a.style = %d AND a.track = %d%s GROUP BY a.map, a.time, a.jumps, a.id, a.points ORDER BY a.points DESC;",
|
||||
gS_MySQLPrefix, gS_MySQLPrefix, gS_MySQLPrefix, gI_TargetSteamID[client], gI_Style[client], gI_Track[client], tierStr);
|
||||
}
|
||||
else
|
||||
{
|
||||
FormatEx(sQuery, 512,
|
||||
"SELECT a.map, a.time, a.jumps, a.id, COUNT(b.map) + 1 as 'rank', a.points FROM %splayertimes a LEFT JOIN %splayertimes b ON a.time > b.time AND a.map = b.map AND a.style = b.style AND a.track = b.track WHERE a.auth = %d AND a.style = %d AND a.track = %d GROUP BY a.map, a.time, a.jumps, a.id, a.points ORDER BY a.map;",
|
||||
gS_MySQLPrefix, gS_MySQLPrefix, gI_TargetSteamID[client], gI_Style[client], gI_Track[client]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(gB_Rankings)
|
||||
{
|
||||
FormatEx(sQuery, 512,
|
||||
"SELECT DISTINCT m.map, t.tier FROM %smapzones m LEFT JOIN %smaptiers t ON m.map = t.map WHERE m.type = 0 AND m.track = %d AND m.map NOT IN (SELECT DISTINCT map FROM %splayertimes WHERE auth = %d AND style = %d AND track = %d) ORDER BY m.map;",
|
||||
gS_MySQLPrefix, gS_MySQLPrefix, gI_Track[client], gS_MySQLPrefix, gI_TargetSteamID[client], gI_Style[client], gI_Track[client]);
|
||||
"SELECT DISTINCT m.map, t.tier FROM %smapzones m LEFT JOIN %smaptiers t ON m.map = t.map WHERE m.type = 0 AND m.track = %d%s AND m.map NOT IN (SELECT DISTINCT map FROM %splayertimes WHERE auth = %d AND style = %d AND track = %d) ORDER BY m.map;",
|
||||
gS_MySQLPrefix, gS_MySQLPrefix, gI_Track[client], tierStr, gS_MySQLPrefix, gI_TargetSteamID[client], gI_Style[client], gI_Track[client]);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1328,13 +1403,19 @@ public void ShowMapsCallback(Database db, DBResultSet results, const char[] erro
|
||||
menu.AddItem(sRecordID, sDisplay);
|
||||
}
|
||||
|
||||
char sTier[8];
|
||||
if(gI_Tier[client] > 0)
|
||||
{
|
||||
FormatEx(sTier, 8, "T%d ", gI_Tier[client]);
|
||||
}
|
||||
|
||||
if(gI_MapType[client] == MAPSDONE)
|
||||
{
|
||||
menu.SetTitle("%T (%s)", "MapsDoneFor", client, gS_StyleStrings[gI_Style[client]].sShortName, gS_TargetName[client], rows, sTrack);
|
||||
menu.SetTitle("%s%T (%s)", sTier, "MapsDoneFor", client, gS_StyleStrings[gI_Style[client]].sShortName, gS_TargetName[client], rows, sTrack);
|
||||
}
|
||||
else
|
||||
{
|
||||
menu.SetTitle("%T (%s)", "MapsLeftFor", client, gS_StyleStrings[gI_Style[client]].sShortName, gS_TargetName[client], rows, sTrack);
|
||||
menu.SetTitle("%s%T (%s)", sTier, "MapsLeftFor", client, gS_StyleStrings[gI_Style[client]].sShortName, gS_TargetName[client], rows, sTrack);
|
||||
}
|
||||
|
||||
if(menu.ItemCount == 0)
|
||||
|
||||
@ -187,10 +187,15 @@ public void OnPluginStart()
|
||||
// player commands
|
||||
RegConsoleCmd("sm_wr", Command_WorldRecord, "View the leaderboard of a map. Usage: sm_wr [map]");
|
||||
RegConsoleCmd("sm_worldrecord", Command_WorldRecord, "View the leaderboard of a map. Usage: sm_worldrecord [map]");
|
||||
RegConsoleCmd("sm_sr", Command_WorldRecord, "View the leaderboard of a map. Usage: sm_sr [map]");
|
||||
RegConsoleCmd("sm_serverrecord", Command_WorldRecord, "View the leaderboard of a map. Usage: sm_serverrecord [map]");
|
||||
|
||||
RegConsoleCmd("sm_bwr", Command_WorldRecord, "View the leaderboard of a map. Usage: sm_bwr [map] [bonus number]");
|
||||
RegConsoleCmd("sm_bworldrecord", Command_WorldRecord, "View the leaderboard of a map. Usage: sm_bworldrecord [map] [bonus number]");
|
||||
RegConsoleCmd("sm_bonusworldrecord", Command_WorldRecord, "View the leaderboard of a map. Usage: sm_bonusworldrecord [map] [bonus number]");
|
||||
RegConsoleCmd("sm_bsr", Command_WorldRecord, "View the leaderboard of a map. Usage: sm_bsr [map] [bonus number]");
|
||||
RegConsoleCmd("sm_bserverrecord", Command_WorldRecord, "View the leaderboard of a map. Usage: sm_bserverrecord [map] [bonus number]");
|
||||
RegConsoleCmd("sm_bonusserverrecord", Command_WorldRecord, "View the leaderboard of a map. Usage: sm_bonusserverrecord [map] [bonus number]");
|
||||
|
||||
RegConsoleCmd("sm_recent", Command_RecentRecords, "View the recent #1 times set.");
|
||||
RegConsoleCmd("sm_recentrecords", Command_RecentRecords, "View the recent #1 times set.");
|
||||
@ -438,9 +443,17 @@ void RegisterWRCommands(int style)
|
||||
gSM_StyleCommands.SetValue(sCommand, style);
|
||||
RegConsoleCmd(sCommand, Command_WorldRecord_Style, sDescription);
|
||||
|
||||
FormatEx(sCommand, sizeof(sCommand), "sm_sr%s", sStyleCommands[x]);
|
||||
gSM_StyleCommands.SetValue(sCommand, style);
|
||||
RegConsoleCmd(sCommand, Command_WorldRecord_Style, sDescription);
|
||||
|
||||
FormatEx(sCommand, sizeof(sCommand), "sm_bwr%s", sStyleCommands[x]);
|
||||
gSM_StyleCommands.SetValue(sCommand, style);
|
||||
RegConsoleCmd(sCommand, Command_WorldRecord_Style, sDescription);
|
||||
|
||||
FormatEx(sCommand, sizeof(sCommand), "sm_bsr%s", sStyleCommands[x]);
|
||||
gSM_StyleCommands.SetValue(sCommand, style);
|
||||
RegConsoleCmd(sCommand, Command_WorldRecord_Style, sDescription);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -5347,7 +5347,7 @@ public void StartTouchPost(int entity, int other)
|
||||
|
||||
case Zone_Slay:
|
||||
{
|
||||
if (status != Timer_Stopped)
|
||||
if (status == Timer_Running)
|
||||
{
|
||||
Shavit_StopTimer(other);
|
||||
ACTUALLY_ForcePlayerSuicide(other);
|
||||
@ -5357,7 +5357,7 @@ public void StartTouchPost(int entity, int other)
|
||||
|
||||
case Zone_Stop:
|
||||
{
|
||||
if(status != Timer_Stopped)
|
||||
if(status == Timer_Running)
|
||||
{
|
||||
Shavit_StopTimer(other);
|
||||
Shavit_PrintToChat(other, "%T", "ZoneStopEnter", other, gS_ChatStrings.sWarning, gS_ChatStrings.sVariable2, gS_ChatStrings.sWarning);
|
||||
|
||||
@ -85,6 +85,10 @@
|
||||
{
|
||||
"en" "Perfect jumps"
|
||||
}
|
||||
"HudPerfsCenter"
|
||||
{
|
||||
"en" "Perfect jumps (center hud)"
|
||||
}
|
||||
"HudDefaultPistol"
|
||||
{
|
||||
"en" "Default Pistol: 1=USP 2=Glock"
|
||||
|
||||
@ -16,6 +16,10 @@
|
||||
{
|
||||
"en" "Select timer track:"
|
||||
}
|
||||
"SelectTier"
|
||||
{
|
||||
"en" "Select map tier:"
|
||||
}
|
||||
"MapsDone"
|
||||
{
|
||||
"en" "Maps done"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user