From 63063bedd6b52d87c4ae57361ba32db96ca47de4 Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Mon, 4 Apr 2022 19:53:11 +0200 Subject: [PATCH 01/47] Add spectator list, uses menu for replay control instead, fix replay control menu overriding other menus --- addons/sourcemod/scripting/gokz-hud.sp | 25 ++++ .../scripting/gokz-hud/info_panel.sp | 20 ++- addons/sourcemod/scripting/gokz-hud/menu.sp | 13 +- .../sourcemod/scripting/gokz-hud/natives.sp | 28 ++++ .../scripting/gokz-hud/options_menu.sp | 12 ++ .../scripting/gokz-hud/spectate_text.sp | 120 +++++++++++++++++ .../scripting/gokz-hud/timer_text.sp | 69 +++------- .../sourcemod/scripting/gokz-hud/tp_menu.sp | 96 +++++++++++++- addons/sourcemod/scripting/gokz-replays.sp | 6 +- .../sourcemod/scripting/gokz-replays/api.sp | 6 + .../scripting/gokz-replays/controls.sp | 125 +++++++++++------- .../sourcemod/scripting/include/gokz/hud.inc | 77 ++++++++++- .../scripting/include/gokz/kzplayer.inc | 26 ++++ .../scripting/include/gokz/replays.inc | 7 + .../translations/gokz-hud.phrases.txt | 40 ++++++ cfg/sourcemod/gokz/options_menu_sorting.cfg | 2 + 16 files changed, 556 insertions(+), 116 deletions(-) create mode 100644 addons/sourcemod/scripting/gokz-hud/natives.sp create mode 100644 addons/sourcemod/scripting/gokz-hud/spectate_text.sp diff --git a/addons/sourcemod/scripting/gokz-hud.sp b/addons/sourcemod/scripting/gokz-hud.sp index 188cf511..828c968a 100644 --- a/addons/sourcemod/scripting/gokz-hud.sp +++ b/addons/sourcemod/scripting/gokz-hud.sp @@ -30,7 +30,10 @@ public Plugin myinfo = bool gB_GOKZRacing; bool gB_GOKZReplays; bool gB_MenuShowing[MAXPLAYERS + 1]; +int gI_ObserverTarget[MAXPLAYERS + 1]; +#include "gokz-hud/spectate_text.sp" +#include "gokz-hud/natives.sp" #include "gokz-hud/commands.sp" #include "gokz-hud/hide_weapon.sp" #include "gokz-hud/info_panel.sp" @@ -48,6 +51,7 @@ bool gB_MenuShowing[MAXPLAYERS + 1]; public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) { + CreateNatives(); RegPluginLibrary("gokz-hud"); return APLRes_Success; } @@ -60,11 +64,17 @@ public void OnPluginStart() HookEvents(); RegisterCommands(); + UpdateSpectatorList(); OnPluginStart_RacingText(); OnPluginStart_SpeedText(); OnPluginStart_TimerText(); } +public void OnPluginEnd() +{ + OnPluginEnd_Menu(); +} + public void OnAllPluginsLoaded() { if (LibraryExists("updater")) @@ -103,6 +113,11 @@ public void OnLibraryRemoved(const char[] name) // =====[ CLIENT EVENTS ]===== +public void OnClientDisconnect(int client) +{ + gI_ObserverTarget[client] = -1; +} + public void OnPlayerRunCmdPost(int client, int buttons, int impulse, const float vel[3], const float angles[3], int weapon, int subtype, int cmdnum, int tickcount, int seed, const int mouse[2]) { if (!IsValidClient(client)) @@ -223,6 +238,15 @@ public void GOKZ_OnOptionChanged(int client, const char[] option, any newValue) // =====[ OTHER EVENTS ]===== +public void OnGameFrame() +{ + // Cache the spectator list every few ticks. + if (GetGameTickCount() % 4 == 0) + { + UpdateSpectatorList(); + } +} + public void GOKZ_OnOptionsMenuCreated(TopMenu topMenu) { OnOptionsMenuCreated_OptionsMenu(topMenu); @@ -267,4 +291,5 @@ static void SetHUDInfo(KZPlayer player, HUDInfo info, int cmdnum) info.TakeoffSpeed = player.GOKZTakeoffSpeed; info.IsTakeoff = Movement_GetTakeoffCmdNum(player.ID) == cmdnum; info.Buttons = player.Buttons; + info.CurrentTeleport = player.TeleportCount; } \ No newline at end of file diff --git a/addons/sourcemod/scripting/gokz-hud/info_panel.sp b/addons/sourcemod/scripting/gokz-hud/info_panel.sp index 54e8f94a..f29e42c7 100644 --- a/addons/sourcemod/scripting/gokz-hud/info_panel.sp +++ b/addons/sourcemod/scripting/gokz-hud/info_panel.sp @@ -63,9 +63,10 @@ static bool NothingEnabledInInfoPanel(KZPlayer player) static char[] GetInfoPanel(KZPlayer player, HUDInfo info) { - char infoPanelText[320]; + char infoPanelText[512]; FormatEx(infoPanelText, sizeof(infoPanelText), - "%s%s%s", + "%s%s%s%s", + GetSpectatorString(player, info), GetTimeString(player, info), GetSpeedString(player, info), GetKeysString(player, info)); @@ -73,6 +74,21 @@ static char[] GetInfoPanel(KZPlayer player, HUDInfo info) return infoPanelText; } +static char[] GetSpectatorString(KZPlayer player, HUDInfo info) +{ + char spectatorString[255]; + if (player.SpectatorListPosition != SpectatorListPosition_InfoPanel || player.SpectatorList == SpectatorList_Disabled) + { + return spectatorString; + } + // Only return something if the player is alive or observing someone else + if (player.Alive || player.ObserverTarget != -1) + { + FormatEx(spectatorString, sizeof(spectatorString), "%s", FormatSpectatorTextForInfoPanel(player, KZPlayer(info.ID))); + } + return spectatorString; +} + static char[] GetTimeString(KZPlayer player, HUDInfo info) { char timeString[128]; diff --git a/addons/sourcemod/scripting/gokz-hud/menu.sp b/addons/sourcemod/scripting/gokz-hud/menu.sp index 7e63b557..d62cd9da 100644 --- a/addons/sourcemod/scripting/gokz-hud/menu.sp +++ b/addons/sourcemod/scripting/gokz-hud/menu.sp @@ -74,4 +74,15 @@ void OnJoinTeam_Menu(int client) void OnStartPositionSet_Menu(int client) { CancelGOKZHUDMenu(client); -} \ No newline at end of file +} + +void OnPluginEnd_Menu() +{ + for (int client = 1; client <= MaxClients; client++) + { + if (IsValidClient(client)) + { + CancelGOKZHUDMenu(client); + } + } +} \ No newline at end of file diff --git a/addons/sourcemod/scripting/gokz-hud/natives.sp b/addons/sourcemod/scripting/gokz-hud/natives.sp new file mode 100644 index 00000000..5b228c28 --- /dev/null +++ b/addons/sourcemod/scripting/gokz-hud/natives.sp @@ -0,0 +1,28 @@ + +// =====[ NATIVES ]===== + +void CreateNatives() +{ + CreateNative("GOKZ_HUD_GetMenuShowing", Native_GetMenuShowing); + CreateNative("GOKZ_HUD_SetMenuShowing", Native_SetMenuShowing); + CreateNative("GOKZ_HUD_GetMenuSpectatorText", Native_GetSpectatorText); +} + +public int Native_GetMenuShowing(Handle plugin, int numParams) +{ + return view_as(gB_MenuShowing[GetNativeCell(1)]); +} + +public int Native_SetMenuShowing(Handle plugin, int numParams) +{ + gB_MenuShowing[GetNativeCell(1)] = view_as(GetNativeCell(2)); +} + +public int Native_GetSpectatorText(Handle plugin, int numParams) +{ + HUDInfo info; + GetNativeArray(2, info, sizeof(HUDInfo)); + KZPlayer player = KZPlayer(GetNativeCell(1)); + FormatNativeString(3, 0, 0, GetNativeCell(4), _, "", FormatSpectatorTextForMenu(player, info)); + return 1; +} \ No newline at end of file diff --git a/addons/sourcemod/scripting/gokz-hud/options_menu.sp b/addons/sourcemod/scripting/gokz-hud/options_menu.sp index 851e6b92..b2a9ca58 100644 --- a/addons/sourcemod/scripting/gokz-hud/options_menu.sp +++ b/addons/sourcemod/scripting/gokz-hud/options_menu.sp @@ -120,6 +120,18 @@ public void TopMenuHandler_HUD(TopMenu topmenu, TopMenuAction action, TopMenuObj gC_HUDOptionPhrases[option], param, gC_ShowControlsPhrases[GOKZ_HUD_GetOption(param, option)], param); } + case HUDOption_SpectatorList: + { + FormatEx(buffer, maxlength, "%T - %T", + gC_HUDOptionPhrases[option], param, + gC_SpectatorListPhrases[GOKZ_HUD_GetOption(param, option)], param); + } + case HUDOption_SpectatorListPosition: + { + FormatEx(buffer, maxlength, "%T - %T", + gC_HUDOptionPhrases[option], param, + gC_SpectatorListPositionPhrases[GOKZ_HUD_GetOption(param, option)], param); + } default:FormatToggleableOptionDisplay(param, option, buffer, maxlength); } } diff --git a/addons/sourcemod/scripting/gokz-hud/spectate_text.sp b/addons/sourcemod/scripting/gokz-hud/spectate_text.sp new file mode 100644 index 00000000..3cb8f0ae --- /dev/null +++ b/addons/sourcemod/scripting/gokz-hud/spectate_text.sp @@ -0,0 +1,120 @@ +/* + Responsible for spectator list on the HUD. +*/ + +#define SPECATATOR_LIST_MAX_COUNT 5 + +// =====[ PUBLIC ]===== + +char[] FormatSpectatorTextForMenu(KZPlayer player, HUDInfo info) +{ + int specCount; + char spectatorTextString[224]; + if (player.GetHUDOption(HUDOption_SpectatorList) >= SpectatorList_Simple) + { + for (int i = 1; i <= MaxClients; i++) + { + if (gI_ObserverTarget[i] == info.ID) + { + specCount++; + if (player.GetHUDOption(HUDOption_SpectatorList) == SpectatorList_Advanced) + { + char buffer[64]; + if (specCount < SPECATATOR_LIST_MAX_COUNT) + { + GetClientName(i, buffer, sizeof(buffer)); + Format(spectatorTextString, sizeof(spectatorTextString), "%s\n%s", spectatorTextString, buffer); + } + else if (specCount == SPECATATOR_LIST_MAX_COUNT) + { + StrCat(spectatorTextString, sizeof(spectatorTextString), "\n..."); + } + } + } + } + if (specCount > 0) + { + if (player.GetHUDOption(HUDOption_SpectatorList) == SpectatorList_Advanced) + { + Format(spectatorTextString, sizeof(spectatorTextString), "%t\n ", "Spectator List - Menu (Advanced)", specCount, spectatorTextString); + } + else + { + Format(spectatorTextString, sizeof(spectatorTextString), "%t\n ", "Spectator List - Menu (Simple)", specCount); + } + } + else + { + FormatEx(spectatorTextString, sizeof(spectatorTextString), ""); + } + } + return spectatorTextString; +} + +char[] FormatSpectatorTextForInfoPanel(KZPlayer player, KZPlayer targetPlayer) +{ + int specCount; + char spectatorTextString[160]; + if (player.GetHUDOption(HUDOption_SpectatorList) >= SpectatorList_Simple) + { + // TODO: Make faster logic + for (int i = 1; i <= MaxClients; i++) + { + if (gI_ObserverTarget[i] == targetPlayer.ID) + { + specCount++; + if (player.GetHUDOption(HUDOption_SpectatorList) == SpectatorList_Advanced) + { + char buffer[64]; + if (specCount < SPECATATOR_LIST_MAX_COUNT) + { + GetClientName(i, buffer, sizeof(buffer)); + if (specCount == 1) + { + Format(spectatorTextString, sizeof(spectatorTextString), "%s", buffer); + } + else + { + Format(spectatorTextString, sizeof(spectatorTextString), "%s, %s", spectatorTextString, buffer); + } + } + else if (specCount == SPECATATOR_LIST_MAX_COUNT) + { + Format(spectatorTextString, sizeof(spectatorTextString), " ..."); + } + } + } + } + if (specCount > 0) + { + if (player.GetHUDOption(HUDOption_SpectatorList) == SpectatorList_Advanced) + { + Format(spectatorTextString, sizeof(spectatorTextString), "%t\n", "Spectator List - Info Panel (Advanced)", specCount, spectatorTextString); + } + else + { + Format(spectatorTextString, sizeof(spectatorTextString), "%t\n", "Spectator List - Info Panel (Simple)", specCount); + } + } + else + { + FormatEx(spectatorTextString, sizeof(spectatorTextString), ""); + } + } + return spectatorTextString; +} + +void UpdateSpectatorList() +{ + for (int client = 1; client < MaxClients; client++) + { + if (IsValidClient(client) && !IsFakeClient(client)) + { + gI_ObserverTarget[client] = GetObserverTarget(client); + } + else + { + gI_ObserverTarget[client] = -1; + } + } +} \ No newline at end of file diff --git a/addons/sourcemod/scripting/gokz-hud/timer_text.sp b/addons/sourcemod/scripting/gokz-hud/timer_text.sp index 866e9aad..9c25acc4 100644 --- a/addons/sourcemod/scripting/gokz-hud/timer_text.sp +++ b/addons/sourcemod/scripting/gokz-hud/timer_text.sp @@ -16,18 +16,25 @@ static Handle timerHudSynchronizer; char[] FormatTimerTextForMenu(KZPlayer player, HUDInfo info) { char timerTextString[32]; - if (player.GetHUDOption(HUDOption_TimerType) == TimerType_Enabled) + if (info.TimerRunning) { - FormatEx(timerTextString, sizeof(timerTextString), - "%s %s", - gC_TimeTypeNames[info.TimeType], - GOKZ_HUD_FormatTime(player.ID, info.Time)); - } - else - { - FormatEx(timerTextString, sizeof(timerTextString), - "%s", - GOKZ_HUD_FormatTime(player.ID, info.Time)); + if (player.GetHUDOption(HUDOption_TimerType) == TimerType_Enabled) + { + FormatEx(timerTextString, sizeof(timerTextString), + "%s %s", + gC_TimeTypeNames[info.TimeType], + GOKZ_HUD_FormatTime(player.ID, info.Time)); + } + else + { + FormatEx(timerTextString, sizeof(timerTextString), + "%s", + GOKZ_HUD_FormatTime(player.ID, info.Time)); + } + if (info.Paused) + { + Format(timerTextString, sizeof(timerTextString), "%s %T", timerTextString, "Info Panel Text - PAUSED"); + } } return timerTextString; } @@ -67,15 +74,6 @@ void OnTimerStopped_TimerText(int client) ClearTimerText(client); } -public int PanelHandler_Menu(Menu menu, MenuAction action, int param1, int param2) -{ - if (action == MenuAction_Cancel) - { - gB_MenuShowing[param1] = false; - } -} - - // =====[ PRIVATE ]===== @@ -106,36 +104,7 @@ static void ShowTimerText(KZPlayer player, HUDInfo info) } return; } - - if (player.TimerText == TimerText_TPMenu) - { - // If there is no menu showing, or if the TP menu is currently showing; - // and if player is spectating, or is alive with TP menu disabled and not paused - - // Note that we don't mind if player we're spectating is paused etc. as there are too - // many variables to track whether we need to update the timer text for the spectator. - - if ((gB_MenuShowing[player.ID] || GetClientMenu(player.ID) == MenuSource_None) - && (player.ID != info.ID || player.TPMenu == TPMenu_Disabled && !player.Paused)) - { - // Use a Panel if want to show ONLY timer text (not TP menu) - // as it doesn't seem to be possible to display a Menu with no items. - Panel panel = new Panel(null); - panel.SetTitle(FormatTimerTextForMenu(player, info)); - int observerTarget = GetObserverTarget(player.ID); - if (observerTarget != -1 && IsFakeClient(observerTarget) - && info.TimeType == TimeType_Nub) - { - char text[32]; - FormatEx(text, sizeof(text), "%t", "TP Menu - Spectator Teleports", info.CurrentTeleport); - panel.DrawItem(text, ITEMDRAW_RAWLINE); - } - panel.Send(player.ID, PanelHandler_Menu, MENU_TIME_FOREVER); - delete panel; - gB_MenuShowing[player.ID] = true; - } - } - else if (player.TimerText == TimerText_Top || player.TimerText == TimerText_Bottom) + if (player.TimerText == TimerText_Top || player.TimerText == TimerText_Bottom) { int colour[4]; // RGBA if (player.GetHUDOption(HUDOption_TimerType) == TimerType_Enabled) diff --git a/addons/sourcemod/scripting/gokz-hud/tp_menu.sp b/addons/sourcemod/scripting/gokz-hud/tp_menu.sp index 54c1b8f5..f372dba6 100644 --- a/addons/sourcemod/scripting/gokz-hud/tp_menu.sp +++ b/addons/sourcemod/scripting/gokz-hud/tp_menu.sp @@ -27,6 +27,14 @@ void OnPlayerRunCmdPost_TPMenu(int client, int cmdnum, HUDInfo info) } } +public int PanelHandler_Menu(Menu menu, MenuAction action, int param1, int param2) +{ + if (action == MenuAction_Cancel) + { + gB_MenuShowing[param1] = false; + } +} + public int MenuHandler_TPMenu(Menu menu, MenuAction action, int param1, int param2) { if (action == MenuAction_Select) @@ -84,17 +92,75 @@ static void UpdateTPMenu(int client, HUDInfo info) { KZPlayer player = KZPlayer(client); - if (player.Fake || !player.Alive || player.TPMenu == TPMenu_Disabled) + if (player.Fake) { return; } - // If there is no menu showing, or if the TP menu is currently showing with timer text - if (GetClientMenu(client) == MenuSource_None - || gB_MenuShowing[player.ID] && GetClientAvgLoss(player.ID, NetFlow_Both) > EPSILON - || gB_MenuShowing[player.ID] && player.TimerRunning && !player.Paused && player.TimerText == TimerText_TPMenu) + if (player.Alive) + { + if (player.TPMenu != TPMenu_Disabled) + { + if (GetClientMenu(client) == MenuSource_None + || gB_MenuShowing[player.ID] && GetClientAvgLoss(player.ID, NetFlow_Both) > EPSILON + || gB_MenuShowing[player.ID] && player.TimerRunning && !player.Paused && player.TimerText == TimerText_TPMenu) + { + ShowTPMenu(player, info); + } + } + else + { + // There is no need to update this very often as there's no menu selection to be done here. + if (GetClientMenu(client) == MenuSource_None + || gB_MenuShowing[player.ID] && player.TimerRunning && !player.Paused && player.TimerText == TimerText_TPMenu) + { + ShowPanel(player, info); + } + } + } + else if (player.ObserverTarget != -1) // If the player is spectating someone else { - ShowTPMenu(player, info); + // Check if the replay plugins wants to display the replay control menu. + if (!(IsFakeClient(player.ObserverTarget) && gB_GOKZReplays && GOKZ_RP_UpdateReplayControlMenu(client))) + { + ShowPanel(player, info); + } + } +} + +static void ShowPanel(KZPlayer player, HUDInfo info) +{ + char panelTitle[256]; + // Spectator List + if (player.SpectatorList >= SpectatorList_Simple && player.SpectatorListPosition == SpectatorListPosition_TPMenu) + { + Format(panelTitle, sizeof(panelTitle), "%s", FormatSpectatorTextForMenu(player, info)); + } + // Timer panel + if (player.TimerText == TimerText_TPMenu && info.TimerRunning) + { + if (panelTitle[0] != '\0') + { + Format(panelTitle, sizeof(panelTitle), "%s \n%s", panelTitle, FormatTimerTextForMenu(player, info)); + } + else + { + Format(panelTitle, sizeof(panelTitle), "%s", FormatTimerTextForMenu(player, info)); + } + if (info.TimeType == TimeType_Nub) + { + Format(panelTitle, sizeof(panelTitle), "%s\n%t", panelTitle, "TP Menu - Spectator Teleports", info.CurrentTeleport); + } + } + + if (panelTitle[0] != '\0' && GetClientMenu(player.ID) == MenuSource_None || gB_MenuShowing[player.ID]) + { + Panel panel = new Panel(null); + panel.SetTitle(panelTitle); + panel.Send(player.ID, PanelHandler_Menu, MENU_TIME_FOREVER); + + delete panel; + gB_MenuShowing[player.ID] = true; } } @@ -112,9 +178,25 @@ static void ShowTPMenu(KZPlayer player, HUDInfo info) static void TPMenuSetTitle(KZPlayer player, Menu menu, HUDInfo info) { + char title[256]; + if (player.SpectatorList >= SpectatorList_Simple && player.SpectatorListPosition == SpectatorListPosition_TPMenu) + { + Format(title, sizeof(title), "%s", FormatSpectatorTextForMenu(player, info)); + } if (player.TimerRunning && player.TimerText == TimerText_TPMenu) { - menu.SetTitle(FormatTimerTextForMenu(player, info)); + if (title[0] != '\0') + { + Format(title, sizeof(title), "%s \n%s", title, FormatTimerTextForMenu(player, info)); + } + else + { + Format(title, sizeof(title), "%s", FormatTimerTextForMenu(player, info)); + } + } + if (title[0] != '\0') + { + menu.SetTitle(title); } } diff --git a/addons/sourcemod/scripting/gokz-replays.sp b/addons/sourcemod/scripting/gokz-replays.sp index c8468545..b2eb031f 100644 --- a/addons/sourcemod/scripting/gokz-replays.sp +++ b/addons/sourcemod/scripting/gokz-replays.sp @@ -35,6 +35,7 @@ public Plugin myinfo = #define UPDATER_URL GOKZ_UPDATER_BASE_URL..."gokz-replays.txt" +bool gB_GOKZHUD; bool gB_GOKZLocalDB; char gC_CurrentMap[64]; int gI_CurrentMapFileSize; @@ -80,7 +81,8 @@ public void OnAllPluginsLoaded() Updater_AddPlugin(UPDATER_URL); } gB_GOKZLocalDB = LibraryExists("gokz-localdb"); - + gB_GOKZHUD = LibraryExists("gokz-hud"); + for (int client = 1; client <= MaxClients; client++) { if (IsClientInGame(client)) @@ -97,11 +99,13 @@ public void OnLibraryAdded(const char[] name) Updater_AddPlugin(UPDATER_URL); } gB_GOKZLocalDB = gB_GOKZLocalDB || StrEqual(name, "gokz-localdb"); + gB_GOKZHUD = gB_GOKZHUD || StrEqual(name, "gokz-hud"); } public void OnLibraryRemoved(const char[] name) { gB_GOKZLocalDB = gB_GOKZLocalDB && !StrEqual(name, "gokz-localdb"); + gB_GOKZHUD = gB_GOKZHUD && !StrEqual(name, "gokz-hud"); } diff --git a/addons/sourcemod/scripting/gokz-replays/api.sp b/addons/sourcemod/scripting/gokz-replays/api.sp index 10e0425e..4fea95a7 100644 --- a/addons/sourcemod/scripting/gokz-replays/api.sp +++ b/addons/sourcemod/scripting/gokz-replays/api.sp @@ -8,6 +8,7 @@ void CreateNatives() { CreateNative("GOKZ_RP_GetPlaybackInfo", Native_RP_GetPlaybackInfo); CreateNative("GOKZ_RP_LoadJumpReplay", Native_RP_LoadJumpReplay); + CreateNative("GOKZ_RP_UpdateReplayControlMenu", Native_RP_UpdateReplayControlMenu); } public int Native_RP_GetPlaybackInfo(Handle plugin, int numParams) @@ -28,6 +29,11 @@ public int Native_RP_LoadJumpReplay(Handle plugin, int numParams) return botClient; } +public int Native_RP_UpdateReplayControlMenu(Handle plugin, int numParams) +{ + return view_as(UpdateReplayControlMenu(GetNativeCell(1))); +} + // =====[ FORWARDS ]===== void CreateGlobalForwards() diff --git a/addons/sourcemod/scripting/gokz-replays/controls.sp b/addons/sourcemod/scripting/gokz-replays/controls.sp index df1943b5..ea1c3f7d 100644 --- a/addons/sourcemod/scripting/gokz-replays/controls.sp +++ b/addons/sourcemod/scripting/gokz-replays/controls.sp @@ -2,6 +2,10 @@ Lets player control the replay bot. */ +#define ITEM_INFO_PAUSE "pause" +#define ITEM_INFO_SKIP "skip" +#define ITEM_INFO_REWIND "rewind" +#define ITEM_INFO_FREECAM "freecam" static int controllingPlayer[RP_MAX_BOTS]; static int botTeleports[RP_MAX_BOTS]; @@ -13,24 +17,25 @@ static bool showReplayControls[MAXPLAYERS + 1]; void OnPlayerRunCmdPost_ReplayControls(int client, int cmdnum) { - if (cmdnum % 6 == 3) + // Let the HUD plugin takes care of this if possible. + if (cmdnum % 6 == 3 && !gB_GOKZHUD) { UpdateReplayControlMenu(client); } } -void UpdateReplayControlMenu(int client) +bool UpdateReplayControlMenu(int client) { if (!IsValidClient(client) || IsFakeClient(client)) { - return; + return false; } int botClient = GetObserverTarget(client); int bot = GetBotFromClient(botClient); if (bot == -1) { - return; + return false; } if (!IsReplayBotControlled(bot, botClient) && !InBreather(bot)) @@ -40,73 +45,88 @@ void UpdateReplayControlMenu(int client) } else if (controllingPlayer[bot] != client) { - return; + return false; } - if (showReplayControls[client] && + if (showReplayControls[client] && GOKZ_HUD_GetOption(client, HUDOption_ShowControls) == ReplayControls_Enabled && - (GetClientMenu(client) == MenuSource_None || - GetClientAvgLoss(client, NetFlow_Both) > EPSILON || - GOKZ_HUD_GetOption(client, HUDOption_TimerText) == TimerText_TPMenu)) + (GetClientMenu(client) == MenuSource_None || + GOKZ_HUD_GetMenuShowing(client) && GetClientAvgLoss(client, NetFlow_Both) > EPSILON || + GOKZ_HUD_GetMenuShowing(client) && GOKZ_HUD_GetOption(client, HUDOption_TimerText) == TimerText_TPMenu)) { botTeleports[bot] = PlaybackGetTeleports(bot); ShowReplayControlMenu(client, bot); + return true; } + return false; } void ShowReplayControlMenu(int client, int bot) { - char text[32]; + char text[256]; - Panel panel = new Panel(); - - if (GOKZ_HUD_GetOption(client, HUDOption_TimerText) == TimerText_TPMenu) + Menu menu = new Menu(MenuHandler_ReplayControls); + menu.OptionFlags = MENUFLAG_NO_SOUND; + menu.Pagination = MENU_NO_PAGINATION; + menu.ExitButton = true; + if (gB_GOKZHUD) { - FormatEx(text, sizeof(text), "%T - %s", "Replay Controls - Title", client, - GOKZ_FormatTime(GetPlaybackTime(bot), GOKZ_HUD_GetOption(client, HUDOption_TimerStyle) == TimerStyle_Precise)); - panel.SetTitle(text); + if (GOKZ_HUD_GetOption(client, HUDOption_SpectatorList) != SpectatorList_Disabled && + GOKZ_HUD_GetOption(client, HUDOption_SpectatorListPosition) == SpectatorListPosition_TPMenu) + { + HUDInfo info; + GetPlaybackState(client, info); + GOKZ_HUD_GetMenuSpectatorText(client, info, text, sizeof(text)); + PrintToConsole(client, text); + } + if (GOKZ_HUD_GetOption(client, HUDOption_TimerText) == TimerText_TPMenu) + { + Format(text, sizeof(text), "%s\n%T - %s", text, "Replay Controls - Title", client, + GOKZ_FormatTime(GetPlaybackTime(bot), GOKZ_HUD_GetOption(client, HUDOption_TimerStyle) == TimerStyle_Precise)); + } + else + { + Format(text, sizeof(text), "%s%T", text, "Replay Controls - Title", client); + } } else { - FormatEx(text, sizeof(text), "%T", "Replay Controls - Title", client); - panel.SetTitle(text); + Format(text, sizeof(text), "%s%T", text, "Replay Controls - Title", client); } + if(PlaybackGetTeleports(bot) > 0) { - FormatEx(text, sizeof(text), "%T", "Replay Controls - Teleports", client, botTeleports[bot]); - panel.DrawItem(text, ITEMDRAW_RAWLINE); + Format(text, sizeof(text), "%s\n%T", text, "Replay Controls - Teleports", client, botTeleports[bot]); } + menu.SetTitle(text); if (PlaybackPaused(bot)) { FormatEx(text, sizeof(text), "%T", "Replay Controls - Resume", client); - panel.DrawItem(text); + menu.AddItem(ITEM_INFO_PAUSE, text); } else { FormatEx(text, sizeof(text), "%T", "Replay Controls - Pause", client); - panel.DrawItem(text); + menu.AddItem(ITEM_INFO_PAUSE, text); } FormatEx(text, sizeof(text), "%T", "Replay Controls - Skip", client); - panel.DrawItem(text); - - FormatEx(text, sizeof(text), "%T", "Replay Controls - Rewind", client); - panel.DrawItem(text); + menu.AddItem(ITEM_INFO_SKIP, text); - panel.DrawItem("", ITEMDRAW_SPACER); + FormatEx(text, sizeof(text), "%T\n ", "Replay Controls - Rewind", client); + menu.AddItem(ITEM_INFO_REWIND, text); FormatEx(text, sizeof(text), "%T", "Replay Controls - Freecam", client); - panel.DrawItem(text); - - panel.DrawItem("", ITEMDRAW_SPACER); - - FormatEx(text, sizeof(text), "%T", "Replay Controls - Exit", client); - panel.DrawItem(text); + menu.AddItem(ITEM_INFO_FREECAM, text); - panel.Send(client, PanelHandler_ReplayControls, MENU_TIME_FOREVER); - delete panel; + menu.Display(client, MENU_TIME_FOREVER); + + if (gB_GOKZHUD) + { + GOKZ_HUD_SetMenuShowing(client, true); + } } void ToggleReplayControls(int client) @@ -133,7 +153,7 @@ bool IsReplayBotControlled(int bot, int botClient) GetEntProp(controllingPlayer[bot], Prop_Send, "m_iObserverMode") == 6); } -int PanelHandler_ReplayControls(Menu menu, MenuAction action, int param1, int param2) +int MenuHandler_ReplayControls(Menu menu, MenuAction action, int param1, int param2) { switch (action) { @@ -141,45 +161,48 @@ int PanelHandler_ReplayControls(Menu menu, MenuAction action, int param1, int pa { if (!IsValidClient(param1)) { - return 0; + return; } int bot = GetBotFromClient(GetObserverTarget(param1)); if (bot == -1 || controllingPlayer[bot] != param1) { - return 0; + return; } - // Pause/Resume - if (param2 == 1) + char info[16]; + menu.GetItem(param2, info, sizeof(info)); + if (StrEqual(info, ITEM_INFO_PAUSE, false)) { PlaybackTogglePause(bot); - ShowReplayControlMenu(param1, bot); } - // Forward - else if (param2 == 2) + else if (StrEqual(info, ITEM_INFO_SKIP, false)) { PlaybackSkipForward(bot); } - // Rewind - else if (param2 == 3) + else if (StrEqual(info, ITEM_INFO_REWIND, false)) { PlaybackSkipBack(bot); } - // Freecam - else if (param2 == 4) + else if (StrEqual(info, ITEM_INFO_FREECAM, false)) { SetEntProp(param1, Prop_Send, "m_iObserverMode", 6); } - // Exit - else if (param2 == 7) + GOKZ_HUD_SetMenuShowing(param1, false); + } + case MenuAction_Cancel: + { + GOKZ_HUD_SetMenuShowing(param1, false); + if (param2 == MenuCancel_Exit) { CancelReplayControls(param1); - delete menu; } } + case MenuAction_End: + { + delete menu; + } } - return 0; } void CancelReplayControls(int client) diff --git a/addons/sourcemod/scripting/include/gokz/hud.inc b/addons/sourcemod/scripting/include/gokz/hud.inc index 9c229794..0b2e7050 100644 --- a/addons/sourcemod/scripting/include/gokz/hud.inc +++ b/addons/sourcemod/scripting/include/gokz/hud.inc @@ -25,6 +25,8 @@ enum HUDOption: HUDOption_SpeedText, HUDOption_ShowWeapon, HUDOption_ShowControls, + HUDOption_SpectatorList, + HUDOption_SpectatorListPosition, HUDOPTION_COUNT }; @@ -97,7 +99,20 @@ enum REPLAYCONTROLS_COUNT }; +enum +{ + SpectatorList_Disabled = 0, + SpectatorList_Simple, + SpectatorList_Advanced, + SPECTATORLIST_COUNT +}; +enum +{ + SpectatorListPosition_TPMenu = 0, + SpectatorListPosition_InfoPanel, + SPECTATORLISTPOSITION_COUNT +} // =====[ STRUCTS ]====== @@ -140,7 +155,9 @@ stock char gC_HUDOptionNames[HUDOPTION_COUNT][] = "GOKZ HUD - Show Time Type", "GOKZ HUD - Speed Text", "GOKZ HUD - Show Weapon", - "GOKZ HUD - Show Controls" + "GOKZ HUD - Show Controls", + "GOKZ HUD - Spectator List", + "GOKZ HUD - Spec List Pos", }; stock char gC_HUDOptionDescriptions[HUDOPTION_COUNT][] = @@ -153,7 +170,9 @@ stock char gC_HUDOptionDescriptions[HUDOPTION_COUNT][] = "Timer Type - 0 = Disabled, 1 = Enabled", "Speed Display - 0 = Disabled, 1 = Centre Panel, 2 = Bottom", "Weapon Viewmodel - 0 = Disabled, 1 = Enabled", - "Replay Controls Display - 0 = Disbled, 1 = Enabled" + "Replay Controls Display - 0 = Disbled, 1 = Enabled", + "Spectator List - 0 = Disabled, 1 = Player count, 2 = Player count and names", + "Spectator List Position - 0 = Teleport Menu, 2 = Center Panel" }; stock char gC_HUDOptionPhrases[HUDOPTION_COUNT][] = @@ -166,7 +185,9 @@ stock char gC_HUDOptionPhrases[HUDOPTION_COUNT][] = "Options Menu - Timer Type", "Options Menu - Speed Text", "Options Menu - Show Weapon", - "Options Menu - Show Controls" + "Options Menu - Show Controls", + "Options Menu - Spectator List", + "Options Menu - Spectator List Position" }; stock int gI_HUDOptionCounts[HUDOPTION_COUNT] = @@ -179,7 +200,9 @@ stock int gI_HUDOptionCounts[HUDOPTION_COUNT] = TIMERTYPE_COUNT, SPEEDTEXT_COUNT, SHOWWEAPON_COUNT, - REPLAYCONTROLS_COUNT + REPLAYCONTROLS_COUNT, + SPECTATORLIST_COUNT, + SPECTATORLISTPOSITION_COUNT }; stock int gI_HUDOptionDefaults[HUDOPTION_COUNT] = @@ -237,7 +260,44 @@ stock char gC_ShowControlsPhrases[REPLAYCONTROLS_COUNT][] = "Options Menu - Enabled" }; +stock char gC_SpectatorListPhrases[SPECTATORLIST_COUNT][] = +{ + "Options Menu - Disabled", + "Options Menu - Player Count", + "Options Menu - Player Count & Names" +}; + +stock char gC_SpectatorListPositionPhrases[SPECTATORLISTPOSITION_COUNT][] = +{ + "Options Menu - Teleport Menu", + "Options Menu - Info Panel" +} + +// =====[ NATIVES ]===== + +/** + * Returns whether the GOKZ HUD menu is showing for a client. + * + * @param client Client index. + * @return Whether the GOKZ HUD menu is showing. + */ +native bool GOKZ_HUD_GetMenuShowing(int client); + +/** + * Sets whether the GOKZ HUD menu would be showing for a client. + * + * @param client Client index. + * @param value Whether the GOKZ HUD menu would be showing for a client. + */ +native void GOKZ_HUD_SetMenuShowing(int client, bool value); +/** + * Gets the spectator text for the menu. Used by GOKZ-replays. + * + * @param client Client index. + * @param value Whether the GOKZ HUD menu would be showing for a client. + */ +native void GOKZ_HUD_GetMenuSpectatorText(int client, any[] info, char[] buffer, int size); // =====[ STOCKS ]===== @@ -327,3 +387,12 @@ public SharedPlugin __pl_gokz_hud = required = 0, #endif }; + +#if !defined REQUIRE_PLUGIN +public void __pl_gokz_hud_SetNTVOptional() +{ + MarkNativeAsOptional("GOKZ_HUD_GetMenuShowing"); + MarkNativeAsOptional("GOKZ_HUD_SetMenuShowing"); + MarkNativeAsOptional("GOKZ_HUD_GetMenuSpectatorText"); +} +#endif diff --git a/addons/sourcemod/scripting/include/gokz/kzplayer.inc b/addons/sourcemod/scripting/include/gokz/kzplayer.inc index cca3ac63..57a61b1b 100644 --- a/addons/sourcemod/scripting/include/gokz/kzplayer.inc +++ b/addons/sourcemod/scripting/include/gokz/kzplayer.inc @@ -421,6 +421,32 @@ methodmap KZPlayer < MovementAPIPlayer { } } + property int SpectatorList { + public get() { + return this.GetHUDOption(HUDOption_SpectatorList); + } + public set(int value){ + this.SetHUDOption(HUDOption_SpectatorList, value); + } + } + + property int SpectatorListPosition { + public get() { + return this.GetHUDOption(HUDOption_SpectatorListPosition); + } + public set(int value){ + this.SetHUDOption(HUDOption_SpectatorListPosition, value); + } + } + + property bool MenuShowing { + public get() { + return GOKZ_HUD_GetMenuShowing(this.ID); + } + public set(bool value) { + GOKZ_HUD_SetMenuShowing(this.ID, value); + } + } #endif // =====[ END HUD ]===== diff --git a/addons/sourcemod/scripting/include/gokz/replays.inc b/addons/sourcemod/scripting/include/gokz/replays.inc index 45fa813b..ea0e6c6f 100644 --- a/addons/sourcemod/scripting/include/gokz/replays.inc +++ b/addons/sourcemod/scripting/include/gokz/replays.inc @@ -223,6 +223,12 @@ native int GOKZ_RP_GetPlaybackInfo(int client, any[] info); */ native int GOKZ_RP_LoadJumpReplay(int client, char[] path); +/** + * Called by the HUD to show the replay control menu. + * + * @param client Client index. + */ +native bool GOKZ_RP_UpdateReplayControlMenu(int client); // =====[ DEPENDENCY ]===== @@ -243,5 +249,6 @@ public void __pl_gokz_replays_SetNTVOptional() { MarkNativeAsOptional("GOKZ_RP_GetPlaybackInfo"); MarkNativeAsOptional("GOKZ_RP_LoadJumpReplay"); + MarkNativeAsOptional("GOKZ_RP_UpdateReplayControlMenu"); } #endif diff --git a/addons/sourcemod/translations/gokz-hud.phrases.txt b/addons/sourcemod/translations/gokz-hud.phrases.txt index 00817a12..2927d3e5 100644 --- a/addons/sourcemod/translations/gokz-hud.phrases.txt +++ b/addons/sourcemod/translations/gokz-hud.phrases.txt @@ -230,6 +230,14 @@ { "en" "Show replay controls" } + "Options Menu - Spectator List" + { + "en" "Spectator list" + } + "Options Menu - Spectator List Position" + { + "en" "Spectator list position" + } // =====[ RACING ]===== @@ -243,4 +251,36 @@ "en" "GO!" "ru" "НАЧАЛИ!" } + + // =====[ SPECTATOR LIST ]===== + "Spectator List - Menu (Simple)" + { + "#format" "{1:d}" + "en" "Specs: {1}" + } + "Spectator List - Menu (Advanced)" + { + "#format" "{1:d},{2:s}" + "en" "Specs ({1})\n{2}" + } + "Spectator List - Info Panel (Simple)" + { + // Specs: 2 + "#format" "{1:d}" + "en" "Specs: {1}" + } + "Spectator List - Info Panel (Advanced)" + { + // Specs (2): P1, P2 + "#format" "{1:d},{2:s}" + "en" "Specs ({1}): {2}" + } + "Options Menu - Player Count" + { + "en" "Player count" + } + "Options Menu - Player Count & Names" + { + "en" "Player count & names" + } } \ No newline at end of file diff --git a/cfg/sourcemod/gokz/options_menu_sorting.cfg b/cfg/sourcemod/gokz/options_menu_sorting.cfg index 01b49c23..c20b06b7 100644 --- a/cfg/sourcemod/gokz/options_menu_sorting.cfg +++ b/cfg/sourcemod/gokz/options_menu_sorting.cfg @@ -32,6 +32,8 @@ "item" "GOKZ HUD - Show Weapon" "item" "GOKZ HUD - Show Controls" "item" "GOKZ HUD - Show Time Type" + "item" "GOKZ HUD - Spectator List" + "item" "GOKZ HUD - Spectator List Position" } "Jumpstats" { From 451bbb83a429c0c1c45a5e0aedf7e8901f96ea42 Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Mon, 18 Apr 2022 21:02:52 +0200 Subject: [PATCH 02/47] Also update the last client --- addons/sourcemod/scripting/gokz-hud/spectate_text.sp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/sourcemod/scripting/gokz-hud/spectate_text.sp b/addons/sourcemod/scripting/gokz-hud/spectate_text.sp index 3cb8f0ae..e34395f7 100644 --- a/addons/sourcemod/scripting/gokz-hud/spectate_text.sp +++ b/addons/sourcemod/scripting/gokz-hud/spectate_text.sp @@ -106,7 +106,7 @@ char[] FormatSpectatorTextForInfoPanel(KZPlayer player, KZPlayer targetPlayer) void UpdateSpectatorList() { - for (int client = 1; client < MaxClients; client++) + for (int client = 1; client <= MaxClients; client++) { if (IsValidClient(client) && !IsFakeClient(client)) { From bb1de5edb1b5aba35a6b7edc1993aa5fb77fdea3 Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Thu, 21 Apr 2022 01:46:06 +0200 Subject: [PATCH 03/47] Fix client language --- addons/sourcemod/scripting/gokz-hud/timer_text.sp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/sourcemod/scripting/gokz-hud/timer_text.sp b/addons/sourcemod/scripting/gokz-hud/timer_text.sp index 9c25acc4..98e10b38 100644 --- a/addons/sourcemod/scripting/gokz-hud/timer_text.sp +++ b/addons/sourcemod/scripting/gokz-hud/timer_text.sp @@ -33,7 +33,7 @@ char[] FormatTimerTextForMenu(KZPlayer player, HUDInfo info) } if (info.Paused) { - Format(timerTextString, sizeof(timerTextString), "%s %T", timerTextString, "Info Panel Text - PAUSED"); + Format(timerTextString, sizeof(timerTextString), "%s (%T)", timerTextString, "Info Panel Text - PAUSED", player.ID); } } return timerTextString; From 3b2e63cbf9cfc0934b6cac1d1cf1f0fe5b2aa888 Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Sun, 15 May 2022 13:50:03 +0200 Subject: [PATCH 04/47] Spec list name refactor, remove debug prints, fix playback time display being incorrect --- addons/sourcemod/scripting/gokz-hud.sp | 4 +- .../scripting/gokz-hud/info_panel.sp | 2 +- .../sourcemod/scripting/gokz-hud/options.sp | 32 ++++++++++++++++ .../scripting/gokz-hud/options_menu.sp | 8 ++-- .../scripting/gokz-hud/spectate_text.sp | 23 ++++++------ .../sourcemod/scripting/gokz-hud/tp_menu.sp | 4 +- .../scripting/gokz-replays/controls.sp | 5 +-- .../scripting/gokz-replays/playback.sp | 4 +- .../sourcemod/scripting/include/gokz/hud.inc | 30 +++++++-------- .../scripting/include/gokz/kzplayer.inc | 21 ++++++++--- .../translations/gokz-hud.phrases.txt | 37 ++++++++++++++----- 11 files changed, 114 insertions(+), 56 deletions(-) diff --git a/addons/sourcemod/scripting/gokz-hud.sp b/addons/sourcemod/scripting/gokz-hud.sp index 828c968a..6e3341f6 100644 --- a/addons/sourcemod/scripting/gokz-hud.sp +++ b/addons/sourcemod/scripting/gokz-hud.sp @@ -64,7 +64,7 @@ public void OnPluginStart() HookEvents(); RegisterCommands(); - UpdateSpectatorList(); + UpdateSpecList(); OnPluginStart_RacingText(); OnPluginStart_SpeedText(); OnPluginStart_TimerText(); @@ -243,7 +243,7 @@ public void OnGameFrame() // Cache the spectator list every few ticks. if (GetGameTickCount() % 4 == 0) { - UpdateSpectatorList(); + UpdateSpecList(); } } diff --git a/addons/sourcemod/scripting/gokz-hud/info_panel.sp b/addons/sourcemod/scripting/gokz-hud/info_panel.sp index f29e42c7..af09c1f1 100644 --- a/addons/sourcemod/scripting/gokz-hud/info_panel.sp +++ b/addons/sourcemod/scripting/gokz-hud/info_panel.sp @@ -77,7 +77,7 @@ static char[] GetInfoPanel(KZPlayer player, HUDInfo info) static char[] GetSpectatorString(KZPlayer player, HUDInfo info) { char spectatorString[255]; - if (player.SpectatorListPosition != SpectatorListPosition_InfoPanel || player.SpectatorList == SpectatorList_Disabled) + if (player.SpecListPosition != SpecListPosition_InfoPanel || player.SpecList == SpecList_Disabled) { return spectatorString; } diff --git a/addons/sourcemod/scripting/gokz-hud/options.sp b/addons/sourcemod/scripting/gokz-hud/options.sp index 694b97a2..6b1a4892 100644 --- a/addons/sourcemod/scripting/gokz-hud/options.sp +++ b/addons/sourcemod/scripting/gokz-hud/options.sp @@ -122,5 +122,37 @@ static void PrintOptionChangeMessage(int client, HUDOption option, any newValue) } } } + case HUDOption_SpecList: + { + switch (newValue) + { + case SpecList_Disabled: + { + GOKZ_PrintToChat(client, true, "%t", "Option - Spectator List - Disable"); + } + case SpecList_Number: + { + GOKZ_PrintToChat(client, true, "%t", "Option - Spectator List - Number"); + } + case SpecList_Full: + { + GOKZ_PrintToChat(client, true, "%t", "Option - Spectator List - Full"); + } + } + } + case HUDOption_SpecListPosition: + { + switch (newValue) + { + case SpecListPosition_InfoPanel: + { + GOKZ_PrintToChat(client, true, "%t", "Option - Spectator List Position - Info Panel"); + } + case SpecListPosition_TPMenu: + { + GOKZ_PrintToChat(client, true, "%t", "Option - Spectator List Position - TP Menu"); + } + } + } } } \ No newline at end of file diff --git a/addons/sourcemod/scripting/gokz-hud/options_menu.sp b/addons/sourcemod/scripting/gokz-hud/options_menu.sp index b2a9ca58..198dfcfa 100644 --- a/addons/sourcemod/scripting/gokz-hud/options_menu.sp +++ b/addons/sourcemod/scripting/gokz-hud/options_menu.sp @@ -120,17 +120,17 @@ public void TopMenuHandler_HUD(TopMenu topmenu, TopMenuAction action, TopMenuObj gC_HUDOptionPhrases[option], param, gC_ShowControlsPhrases[GOKZ_HUD_GetOption(param, option)], param); } - case HUDOption_SpectatorList: + case HUDOption_SpecList: { FormatEx(buffer, maxlength, "%T - %T", gC_HUDOptionPhrases[option], param, - gC_SpectatorListPhrases[GOKZ_HUD_GetOption(param, option)], param); + gC_SpecListPhrases[GOKZ_HUD_GetOption(param, option)], param); } - case HUDOption_SpectatorListPosition: + case HUDOption_SpecListPosition: { FormatEx(buffer, maxlength, "%T - %T", gC_HUDOptionPhrases[option], param, - gC_SpectatorListPositionPhrases[GOKZ_HUD_GetOption(param, option)], param); + gC_SpecListPositionPhrases[GOKZ_HUD_GetOption(param, option)], param); } default:FormatToggleableOptionDisplay(param, option, buffer, maxlength); } diff --git a/addons/sourcemod/scripting/gokz-hud/spectate_text.sp b/addons/sourcemod/scripting/gokz-hud/spectate_text.sp index e34395f7..5574721d 100644 --- a/addons/sourcemod/scripting/gokz-hud/spectate_text.sp +++ b/addons/sourcemod/scripting/gokz-hud/spectate_text.sp @@ -10,14 +10,14 @@ char[] FormatSpectatorTextForMenu(KZPlayer player, HUDInfo info) { int specCount; char spectatorTextString[224]; - if (player.GetHUDOption(HUDOption_SpectatorList) >= SpectatorList_Simple) + if (player.GetHUDOption(HUDOption_SpecList) >= SpecList_Number) { for (int i = 1; i <= MaxClients; i++) { if (gI_ObserverTarget[i] == info.ID) { specCount++; - if (player.GetHUDOption(HUDOption_SpectatorList) == SpectatorList_Advanced) + if (player.GetHUDOption(HUDOption_SpecList) == SpecList_Full) { char buffer[64]; if (specCount < SPECATATOR_LIST_MAX_COUNT) @@ -34,13 +34,13 @@ char[] FormatSpectatorTextForMenu(KZPlayer player, HUDInfo info) } if (specCount > 0) { - if (player.GetHUDOption(HUDOption_SpectatorList) == SpectatorList_Advanced) + if (player.GetHUDOption(HUDOption_SpecList) == SpecList_Full) { - Format(spectatorTextString, sizeof(spectatorTextString), "%t\n ", "Spectator List - Menu (Advanced)", specCount, spectatorTextString); + Format(spectatorTextString, sizeof(spectatorTextString), "%t\n ", "Spectator List - Menu (Full)", specCount, spectatorTextString); } else { - Format(spectatorTextString, sizeof(spectatorTextString), "%t\n ", "Spectator List - Menu (Simple)", specCount); + Format(spectatorTextString, sizeof(spectatorTextString), "%t\n ", "Spectator List - Menu (Number)", specCount); } } else @@ -55,15 +55,14 @@ char[] FormatSpectatorTextForInfoPanel(KZPlayer player, KZPlayer targetPlayer) { int specCount; char spectatorTextString[160]; - if (player.GetHUDOption(HUDOption_SpectatorList) >= SpectatorList_Simple) + if (player.GetHUDOption(HUDOption_SpecList) >= SpecList_Number) { - // TODO: Make faster logic for (int i = 1; i <= MaxClients; i++) { if (gI_ObserverTarget[i] == targetPlayer.ID) { specCount++; - if (player.GetHUDOption(HUDOption_SpectatorList) == SpectatorList_Advanced) + if (player.GetHUDOption(HUDOption_SpecList) == SpecList_Full) { char buffer[64]; if (specCount < SPECATATOR_LIST_MAX_COUNT) @@ -87,13 +86,13 @@ char[] FormatSpectatorTextForInfoPanel(KZPlayer player, KZPlayer targetPlayer) } if (specCount > 0) { - if (player.GetHUDOption(HUDOption_SpectatorList) == SpectatorList_Advanced) + if (player.GetHUDOption(HUDOption_SpecList) == SpecList_Full) { - Format(spectatorTextString, sizeof(spectatorTextString), "%t\n", "Spectator List - Info Panel (Advanced)", specCount, spectatorTextString); + Format(spectatorTextString, sizeof(spectatorTextString), "%t\n", "Spectator List - Info Panel (Full)", specCount, spectatorTextString); } else { - Format(spectatorTextString, sizeof(spectatorTextString), "%t\n", "Spectator List - Info Panel (Simple)", specCount); + Format(spectatorTextString, sizeof(spectatorTextString), "%t\n", "Spectator List - Info Panel (Number)", specCount); } } else @@ -104,7 +103,7 @@ char[] FormatSpectatorTextForInfoPanel(KZPlayer player, KZPlayer targetPlayer) return spectatorTextString; } -void UpdateSpectatorList() +void UpdateSpecList() { for (int client = 1; client <= MaxClients; client++) { diff --git a/addons/sourcemod/scripting/gokz-hud/tp_menu.sp b/addons/sourcemod/scripting/gokz-hud/tp_menu.sp index f372dba6..9b6d62ab 100644 --- a/addons/sourcemod/scripting/gokz-hud/tp_menu.sp +++ b/addons/sourcemod/scripting/gokz-hud/tp_menu.sp @@ -132,7 +132,7 @@ static void ShowPanel(KZPlayer player, HUDInfo info) { char panelTitle[256]; // Spectator List - if (player.SpectatorList >= SpectatorList_Simple && player.SpectatorListPosition == SpectatorListPosition_TPMenu) + if (player.SpecList >= SpecList_Number && player.SpecListPosition == SpecListPosition_TPMenu) { Format(panelTitle, sizeof(panelTitle), "%s", FormatSpectatorTextForMenu(player, info)); } @@ -179,7 +179,7 @@ static void ShowTPMenu(KZPlayer player, HUDInfo info) static void TPMenuSetTitle(KZPlayer player, Menu menu, HUDInfo info) { char title[256]; - if (player.SpectatorList >= SpectatorList_Simple && player.SpectatorListPosition == SpectatorListPosition_TPMenu) + if (player.SpecList >= SpecList_Number && player.SpecListPosition == SpecListPosition_TPMenu) { Format(title, sizeof(title), "%s", FormatSpectatorTextForMenu(player, info)); } diff --git a/addons/sourcemod/scripting/gokz-replays/controls.sp b/addons/sourcemod/scripting/gokz-replays/controls.sp index ea1c3f7d..50a21a16 100644 --- a/addons/sourcemod/scripting/gokz-replays/controls.sp +++ b/addons/sourcemod/scripting/gokz-replays/controls.sp @@ -71,13 +71,12 @@ void ShowReplayControlMenu(int client, int bot) menu.ExitButton = true; if (gB_GOKZHUD) { - if (GOKZ_HUD_GetOption(client, HUDOption_SpectatorList) != SpectatorList_Disabled && - GOKZ_HUD_GetOption(client, HUDOption_SpectatorListPosition) == SpectatorListPosition_TPMenu) + if (GOKZ_HUD_GetOption(client, HUDOption_SpecList) != SpecList_Disabled && + GOKZ_HUD_GetOption(client, HUDOption_SpecListPosition) == SpecListPosition_TPMenu) { HUDInfo info; GetPlaybackState(client, info); GOKZ_HUD_GetMenuSpectatorText(client, info, text, sizeof(text)); - PrintToConsole(client, text); } if (GOKZ_HUD_GetOption(client, HUDOption_TimerText) == TimerText_TPMenu) { diff --git a/addons/sourcemod/scripting/gokz-replays/playback.sp b/addons/sourcemod/scripting/gokz-replays/playback.sp index c41bd878..d5c49e5f 100644 --- a/addons/sourcemod/scripting/gokz-replays/playback.sp +++ b/addons/sourcemod/scripting/gokz-replays/playback.sp @@ -205,7 +205,7 @@ void TrySkipToTime(int client, int seconds) return; } - int tick = seconds * 128; + int tick = seconds * 128 + preAndPostRunTickCount; int bot = GetBotFromClient(GetObserverTarget(client)); if (tick >= 0 && tick < playbackTickData[bot].Length) @@ -224,7 +224,7 @@ float GetPlaybackTime(int bot) { return 0.0; } - if (playbackTick[bot] >= playbackTickData[bot].Length - (preAndPostRunTickCount * 2)) + if (playbackTick[bot] >= playbackTickData[bot].Length - preAndPostRunTickCount) { return botTime[bot]; } diff --git a/addons/sourcemod/scripting/include/gokz/hud.inc b/addons/sourcemod/scripting/include/gokz/hud.inc index 0b2e7050..5b948e62 100644 --- a/addons/sourcemod/scripting/include/gokz/hud.inc +++ b/addons/sourcemod/scripting/include/gokz/hud.inc @@ -25,8 +25,8 @@ enum HUDOption: HUDOption_SpeedText, HUDOption_ShowWeapon, HUDOption_ShowControls, - HUDOption_SpectatorList, - HUDOption_SpectatorListPosition, + HUDOption_SpecList, + HUDOption_SpecListPosition, HUDOPTION_COUNT }; @@ -101,17 +101,17 @@ enum enum { - SpectatorList_Disabled = 0, - SpectatorList_Simple, - SpectatorList_Advanced, - SPECTATORLIST_COUNT + SpecList_Disabled = 0, + SpecList_Number, + SpecList_Full, + SPECLIST_COUNT }; enum { - SpectatorListPosition_TPMenu = 0, - SpectatorListPosition_InfoPanel, - SPECTATORLISTPOSITION_COUNT + SpecListPosition_TPMenu = 0, + SpecListPosition_InfoPanel, + SPECLISTPOSITION_COUNT } // =====[ STRUCTS ]====== @@ -201,8 +201,8 @@ stock int gI_HUDOptionCounts[HUDOPTION_COUNT] = SPEEDTEXT_COUNT, SHOWWEAPON_COUNT, REPLAYCONTROLS_COUNT, - SPECTATORLIST_COUNT, - SPECTATORLISTPOSITION_COUNT + SPECLIST_COUNT, + SPECLISTPOSITION_COUNT }; stock int gI_HUDOptionDefaults[HUDOPTION_COUNT] = @@ -260,14 +260,14 @@ stock char gC_ShowControlsPhrases[REPLAYCONTROLS_COUNT][] = "Options Menu - Enabled" }; -stock char gC_SpectatorListPhrases[SPECTATORLIST_COUNT][] = +stock char gC_SpecListPhrases[SPECLIST_COUNT][] = { "Options Menu - Disabled", - "Options Menu - Player Count", - "Options Menu - Player Count & Names" + "Options Menu - Number", + "Options Menu - Number & Names" }; -stock char gC_SpectatorListPositionPhrases[SPECTATORLISTPOSITION_COUNT][] = +stock char gC_SpecListPositionPhrases[SPECLISTPOSITION_COUNT][] = { "Options Menu - Teleport Menu", "Options Menu - Info Panel" diff --git a/addons/sourcemod/scripting/include/gokz/kzplayer.inc b/addons/sourcemod/scripting/include/gokz/kzplayer.inc index 57a61b1b..a15ec08b 100644 --- a/addons/sourcemod/scripting/include/gokz/kzplayer.inc +++ b/addons/sourcemod/scripting/include/gokz/kzplayer.inc @@ -421,21 +421,30 @@ methodmap KZPlayer < MovementAPIPlayer { } } - property int SpectatorList { + property int ReplayControls { public get() { - return this.GetHUDOption(HUDOption_SpectatorList); + return this.GetHUDOption(HUDOption_ShowControls); + } + public set(int value) { + this.SetHUDOption(HUDOption_ShowControls, value); + } + } + + property int SpecList { + public get() { + return this.GetHUDOption(HUDOption_SpecList); } public set(int value){ - this.SetHUDOption(HUDOption_SpectatorList, value); + this.SetHUDOption(HUDOption_SpecList, value); } } - property int SpectatorListPosition { + property int SpecListPosition { public get() { - return this.GetHUDOption(HUDOption_SpectatorListPosition); + return this.GetHUDOption(HUDOption_SpecListPosition); } public set(int value){ - this.SetHUDOption(HUDOption_SpectatorListPosition, value); + this.SetHUDOption(HUDOption_SpecListPosition, value); } } diff --git a/addons/sourcemod/translations/gokz-hud.phrases.txt b/addons/sourcemod/translations/gokz-hud.phrases.txt index 2927d3e5..d787b33f 100644 --- a/addons/sourcemod/translations/gokz-hud.phrases.txt +++ b/addons/sourcemod/translations/gokz-hud.phrases.txt @@ -71,7 +71,26 @@ { "en" "{grey}Replay controls are now hidden." } - + "Option - Spectator List - Disable" + { + "en" "{grey}Spectator list is now hidden." + } + "Option - Spectator List - Number" + { + "en" "{grey}Number of spectators is now shown." + } + "Option - Spectator List - Full" + { + "en" "{grey}Number and names of spectators are now shown." + } + "Option - Spectator List Position - Info Panel" + { + "en" "{grey}Spectator list now displays in the centre panel." + } + "Option - Spectator List Position - TP Menu" + { + "en" "{grey}Spectator list now displays in the teleport menu." + } // =====[ INFO PANEL ]===== "Info Panel Text - Time" @@ -253,34 +272,34 @@ } // =====[ SPECTATOR LIST ]===== - "Spectator List - Menu (Simple)" + "Spectator List - Menu (Number)" { "#format" "{1:d}" "en" "Specs: {1}" } - "Spectator List - Menu (Advanced)" + "Spectator List - Menu (Full)" { "#format" "{1:d},{2:s}" "en" "Specs ({1})\n{2}" } - "Spectator List - Info Panel (Simple)" + "Spectator List - Info Panel (Number)" { // Specs: 2 "#format" "{1:d}" "en" "Specs: {1}" } - "Spectator List - Info Panel (Advanced)" + "Spectator List - Info Panel (Full)" { // Specs (2): P1, P2 "#format" "{1:d},{2:s}" "en" "Specs ({1}): {2}" } - "Options Menu - Player Count" + "Options Menu - Number" { - "en" "Player count" + "en" "Number" } - "Options Menu - Player Count & Names" + "Options Menu - Number & Names" { - "en" "Player count & names" + "en" "Number & names" } } \ No newline at end of file From 42c5c5248c149a365e815418cda4c616db7bf276 Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Sun, 15 May 2022 20:36:41 +0200 Subject: [PATCH 05/47] Fix TP count not being updated, fix time display with older replay version --- .../sourcemod/scripting/gokz-hud/tp_menu.sp | 4 ++-- .../scripting/gokz-replays/controls.sp | 19 ++++++++++++------- .../scripting/gokz-replays/playback.sp | 3 ++- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/addons/sourcemod/scripting/gokz-hud/tp_menu.sp b/addons/sourcemod/scripting/gokz-hud/tp_menu.sp index 9b6d62ab..b02b9d72 100644 --- a/addons/sourcemod/scripting/gokz-hud/tp_menu.sp +++ b/addons/sourcemod/scripting/gokz-hud/tp_menu.sp @@ -120,7 +120,7 @@ static void UpdateTPMenu(int client, HUDInfo info) } else if (player.ObserverTarget != -1) // If the player is spectating someone else { - // Check if the replay plugins wants to display the replay control menu. + // Check if the replay plugin wants to display the replay control menu. if (!(IsFakeClient(player.ObserverTarget) && gB_GOKZReplays && GOKZ_RP_UpdateReplayControlMenu(client))) { ShowPanel(player, info); @@ -147,7 +147,7 @@ static void ShowPanel(KZPlayer player, HUDInfo info) { Format(panelTitle, sizeof(panelTitle), "%s", FormatTimerTextForMenu(player, info)); } - if (info.TimeType == TimeType_Nub) + if (info.TimeType == TimeType_Nub && info.CurrentTeleport != 0) { Format(panelTitle, sizeof(panelTitle), "%s\n%t", panelTitle, "TP Menu - Spectator Teleports", info.CurrentTeleport); } diff --git a/addons/sourcemod/scripting/gokz-replays/controls.sp b/addons/sourcemod/scripting/gokz-replays/controls.sp index 50a21a16..8d33227c 100644 --- a/addons/sourcemod/scripting/gokz-replays/controls.sp +++ b/addons/sourcemod/scripting/gokz-replays/controls.sp @@ -49,13 +49,17 @@ bool UpdateReplayControlMenu(int client) } if (showReplayControls[client] && - GOKZ_HUD_GetOption(client, HUDOption_ShowControls) == ReplayControls_Enabled && - (GetClientMenu(client) == MenuSource_None || - GOKZ_HUD_GetMenuShowing(client) && GetClientAvgLoss(client, NetFlow_Both) > EPSILON || - GOKZ_HUD_GetMenuShowing(client) && GOKZ_HUD_GetOption(client, HUDOption_TimerText) == TimerText_TPMenu)) + GOKZ_HUD_GetOption(client, HUDOption_ShowControls) == ReplayControls_Enabled) { - botTeleports[bot] = PlaybackGetTeleports(bot); - ShowReplayControlMenu(client, bot); + // We have to update this often if bot uses teleports. + if (GetClientMenu(client) == MenuSource_None || + GOKZ_HUD_GetMenuShowing(client) && GetClientAvgLoss(client, NetFlow_Both) > EPSILON || + GOKZ_HUD_GetMenuShowing(client) && GOKZ_HUD_GetOption(client, HUDOption_TimerText) == TimerText_TPMenu || + GOKZ_HUD_GetMenuShowing(client) && PlaybackGetTeleports(bot) > 0) + { + botTeleports[bot] = PlaybackGetTeleports(bot); + ShowReplayControlMenu(client, bot); + } return true; } return false; @@ -94,10 +98,11 @@ void ShowReplayControlMenu(int client, int bot) } - if(PlaybackGetTeleports(bot) > 0) + if (botTeleports[bot] > 0) { Format(text, sizeof(text), "%s\n%T", text, "Replay Controls - Teleports", client, botTeleports[bot]); } + menu.SetTitle(text); if (PlaybackPaused(bot)) diff --git a/addons/sourcemod/scripting/gokz-replays/playback.sp b/addons/sourcemod/scripting/gokz-replays/playback.sp index d5c49e5f..2aa7f7c4 100644 --- a/addons/sourcemod/scripting/gokz-replays/playback.sp +++ b/addons/sourcemod/scripting/gokz-replays/playback.sp @@ -105,7 +105,7 @@ void GetPlaybackState(int client, HUDInfo info) info.TimerRunning = botReplayType[bot] == ReplayType_Jump ? false : true; if (botReplayVersion[bot] == 1) { - info.Time = botTime[bot]; + info.Time = playbackTick[bot] * GetTickInterval(); } else if (botReplayVersion[bot] == 2) { @@ -122,6 +122,7 @@ void GetPlaybackState(int client, HUDInfo info) info.Time = (playbackTick[bot] - preAndPostRunTickCount) * GetTickInterval(); } } + info.TimerRunning = true; info.TimeType = botTeleportsUsed[bot] > 0 ? TimeType_Nub : TimeType_Pro; info.Speed = botSpeed[bot]; info.Paused = false; From b1f27be70be359f320080d47a208d1449675652c Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Sun, 15 May 2022 21:23:42 +0200 Subject: [PATCH 06/47] Remove duplicate phrases --- addons/sourcemod/translations/gokz-hud.phrases.txt | 8 -------- 1 file changed, 8 deletions(-) diff --git a/addons/sourcemod/translations/gokz-hud.phrases.txt b/addons/sourcemod/translations/gokz-hud.phrases.txt index a956f5cc..f92e4003 100644 --- a/addons/sourcemod/translations/gokz-hud.phrases.txt +++ b/addons/sourcemod/translations/gokz-hud.phrases.txt @@ -271,14 +271,6 @@ { "en" "Show spectators" } - "Options Menu - Number" - { - "en" "Number" - } - "Options Menu - Number and Names" - { - "en" "Number and Names" - } // =====[ RACING ]===== From 578cacea77e33ae83c4f7eb38614cd7ff8723e6a Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Sun, 28 Aug 2022 23:54:20 +0700 Subject: [PATCH 07/47] Merge branch 'dev' of https://github.com/KZGlobalTeam/gokz into hud-speclist --- addons/sourcemod/scripting/gokz-core.sp | 1 + addons/sourcemod/scripting/gokz-core/misc.sp | 41 ++++++ .../sourcemod/scripting/gokz-core/natives.sp | 12 ++ .../scripting/gokz-core/timer/pause.sp | 62 +++++--- .../scripting/gokz-core/timer/timer.sp | 3 +- addons/sourcemod/scripting/gokz-global.sp | 6 +- .../scripting/gokz-global/send_run.sp | 20 ++- addons/sourcemod/scripting/gokz-hud.sp | 14 +- .../sourcemod/scripting/gokz-hud/natives.sp | 12 +- .../sourcemod/scripting/gokz-hud/options.sp | 18 +++ .../scripting/gokz-hud/options_menu.sp | 6 + .../sourcemod/scripting/gokz-hud/tp_menu.sp | 105 ++++++++++++-- addons/sourcemod/scripting/gokz-replays.sp | 2 + .../sourcemod/scripting/gokz-replays/api.sp | 9 +- .../scripting/gokz-replays/playback.sp | 133 ++++++++++-------- .../scripting/gokz-replays/recording.sp | 110 +++++++++++---- .../scripting/gokz-replays/replay_menu.sp | 2 +- addons/sourcemod/scripting/gokz-saveloc.sp | 18 ++- .../sourcemod/scripting/include/gokz/core.inc | 18 +++ .../sourcemod/scripting/include/gokz/hud.inc | 52 +++++-- .../scripting/include/gokz/kzplayer.inc | 20 +++ .../scripting/include/gokz/replays.inc | 16 ++- .../translations/gokz-common.phrases.txt | 4 + .../translations/gokz-core.phrases.txt | 8 ++ .../translations/gokz-hud.phrases.txt | 19 ++- cfg/sourcemod/gokz/gokz.cfg | 2 + cfg/sourcemod/gokz/options_menu_sorting.cfg | 1 + 27 files changed, 554 insertions(+), 160 deletions(-) diff --git a/addons/sourcemod/scripting/gokz-core.sp b/addons/sourcemod/scripting/gokz-core.sp index 1d177abc..04943eb3 100644 --- a/addons/sourcemod/scripting/gokz-core.sp +++ b/addons/sourcemod/scripting/gokz-core.sp @@ -179,6 +179,7 @@ public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3 { gI_CmdNum[client] = cmdnum; OnPlayerRunCmd_MapTriggers(client, buttons); + OnPlayerRunCmd_Turnbinds(client, buttons, tickcount, angles); return Plugin_Continue; } diff --git a/addons/sourcemod/scripting/gokz-core/misc.sp b/addons/sourcemod/scripting/gokz-core/misc.sp index 5b74ffcc..70efc7d1 100644 --- a/addons/sourcemod/scripting/gokz-core/misc.sp +++ b/addons/sourcemod/scripting/gokz-core/misc.sp @@ -139,6 +139,47 @@ void OnClientPutInServer_Noclip(int client) noclipReleaseTime[client] = 0; } +// =====[ TURNBINDS ]===== + +int turnbindsLastLeftStart[MAXPLAYERS + 1]; +int turnbindsLastRightStart[MAXPLAYERS + 1]; +float turnbindsLastValidYaw[MAXPLAYERS + 1]; +int turnbindsOldButtons[MAXPLAYERS + 1]; + +// Ensures that there is a minimum time between starting to turnbind in one direction +// and then starting to turnbind in the other direction +void OnPlayerRunCmd_Turnbinds(int client, int buttons, int tickcount, float angles[3]) +{ + if (buttons & IN_LEFT && tickcount < turnbindsLastRightStart[client] + GOKZ_TURNBIND_COOLDOWN) + { + angles[1] = turnbindsLastValidYaw[client]; + TeleportEntity(client, NULL_VECTOR, angles, NULL_VECTOR); + buttons = 0; + } + else if (buttons & IN_RIGHT && tickcount < turnbindsLastLeftStart[client] + GOKZ_TURNBIND_COOLDOWN) + { + angles[1] = turnbindsLastValidYaw[client]; + TeleportEntity(client, NULL_VECTOR, angles, NULL_VECTOR); + buttons = 0; + } + else + { + turnbindsLastValidYaw[client] = angles[1]; + + if (!(turnbindsOldButtons[client] & IN_LEFT) && (buttons & IN_LEFT)) + { + turnbindsLastLeftStart[client] = tickcount; + } + + if (!(turnbindsOldButtons[client] & IN_RIGHT) && (buttons & IN_RIGHT)) + { + turnbindsLastRightStart[client] = tickcount; + } + + turnbindsOldButtons[client] = buttons; + } +} + // =====[ PLAYER COLLISION ]===== diff --git a/addons/sourcemod/scripting/gokz-core/natives.sp b/addons/sourcemod/scripting/gokz-core/natives.sp index 9ae61555..1aa26c67 100644 --- a/addons/sourcemod/scripting/gokz-core/natives.sp +++ b/addons/sourcemod/scripting/gokz-core/natives.sp @@ -25,6 +25,7 @@ void CreateNatives() CreateNative("GOKZ_GetStartPositionType", Native_GetStartPositionType); CreateNative("GOKZ_SetStartPositionToMapStart", Native_SetStartPositionToMapStart); CreateNative("GOKZ_MakeCheckpoint", Native_MakeCheckpoint); + CreateNative("GOKZ_GetCanMakeCheckpoint", Native_GetCanMakeCheckpoint); CreateNative("GOKZ_TeleportToCheckpoint", Native_TeleportToCheckpoint); CreateNative("GOKZ_GetCanTeleportToCheckpoint", Native_GetCanTeleportToCheckpoint); CreateNative("GOKZ_PrevCheckpoint", Native_PrevCheckpoint); @@ -36,6 +37,7 @@ void CreateNatives() CreateNative("GOKZ_Pause", Native_Pause); CreateNative("GOKZ_GetCanPause", Native_GetCanPause); CreateNative("GOKZ_Resume", Native_Resume); + CreateNative("GOKZ_GetCanResume", Native_GetCanResume); CreateNative("GOKZ_TogglePause", Native_TogglePause); CreateNative("GOKZ_PlayErrorSound", Native_PlayErrorSound); CreateNative("GOKZ_SetValidJumpOrigin", Native_SetValidJumpOrigin); @@ -272,6 +274,11 @@ public int Native_MakeCheckpoint(Handle plugin, int numParams) MakeCheckpoint(GetNativeCell(1)); } +public int Native_GetCanMakeCheckpoint(Handle plugin, int numParams) +{ + return CanMakeCheckpoint(GetNativeCell(1)); +} + public int Native_TeleportToCheckpoint(Handle plugin, int numParams) { TeleportToCheckpoint(GetNativeCell(1)); @@ -327,6 +334,11 @@ public int Native_Resume(Handle plugin, int numParams) Resume(GetNativeCell(1)); } +public int Native_GetCanResume(Handle plugin, int numParams) +{ + return CanResume(GetNativeCell(1)); +} + public int Native_TogglePause(Handle plugin, int numParams) { TogglePause(GetNativeCell(1)); diff --git a/addons/sourcemod/scripting/gokz-core/timer/pause.sp b/addons/sourcemod/scripting/gokz-core/timer/pause.sp index d41d7e90..137b8b07 100644 --- a/addons/sourcemod/scripting/gokz-core/timer/pause.sp +++ b/addons/sourcemod/scripting/gokz-core/timer/pause.sp @@ -23,16 +23,18 @@ void SetPausedOnLadder(int client, bool onLadder) void Pause(int client) { - if (!CanPause(client)) + if (!CanPause(client, true)) { return; } - + // Call Pre Forward Action result; Call_GOKZ_OnPause(client, result); if (result != Plugin_Continue) { + GOKZ_PrintToChat(client, true, "%t", "Can't Pause (Generic)"); + GOKZ_PlayErrorSound(client); return; } @@ -53,7 +55,7 @@ void Pause(int client) Call_GOKZ_OnPause_Post(client); } -bool CanPause(int client) +bool CanPause(int client, bool showError = false) { if (paused[client]) { @@ -65,27 +67,39 @@ bool CanPause(int client) if (hasResumedInThisRun[client] && GetEngineTime() - lastResumeTime[client] < GOKZ_PAUSE_COOLDOWN) { - GOKZ_PrintToChat(client, true, "%t", "Can't Pause (Just Resumed)"); - GOKZ_PlayErrorSound(client); + if (showError) + { + GOKZ_PrintToChat(client, true, "%t", "Can't Pause (Just Resumed)"); + GOKZ_PlayErrorSound(client); + } return false; } else if (!Movement_GetOnGround(client) && !(Movement_GetSpeed(client) == 0 && Movement_GetVerticalVelocity(client) == 0)) { - GOKZ_PrintToChat(client, true, "%t", "Can't Pause (Midair)"); - GOKZ_PlayErrorSound(client); + if (showError) + { + GOKZ_PrintToChat(client, true, "%t", "Can't Pause (Midair)"); + GOKZ_PlayErrorSound(client); + } return false; } else if (BhopTriggersJustTouched(client)) { - GOKZ_PrintToChat(client, true, "%t", "Can't Pause (Just Landed)"); - GOKZ_PlayErrorSound(client); + if (showError) + { + GOKZ_PrintToChat(client, true, "%t", "Can't Pause (Just Landed)"); + GOKZ_PlayErrorSound(client); + } return false; } else if (AntiPauseTriggerIsTouched(client)) { - GOKZ_PrintToChat(client, true, "%t", "Can't Pause (Anti Pause Area)"); - GOKZ_PlayErrorSound(client); + if (showError) + { + GOKZ_PrintToChat(client, true, "%t", "Can't Pause (Anti Pause Area)"); + GOKZ_PlayErrorSound(client); + } return false; } } @@ -99,22 +113,21 @@ void Resume(int client) { return; } - if (GetTimerRunning(client) && hasPausedInThisRun[client] - && GetEngineTime() - lastPauseTime[client] < GOKZ_PAUSE_COOLDOWN) + if (!CanResume(client, true)) { - GOKZ_PrintToChat(client, true, "%t", "Can't Resume (Just Paused)"); - GOKZ_PlayErrorSound(client); return; } - + // Call Pre Forward Action result; Call_GOKZ_OnResume(client, result); if (result != Plugin_Continue) { + GOKZ_PrintToChat(client, true, "%t", "Can't Resume (Generic)"); + GOKZ_PlayErrorSound(client); return; } - + // Resume if (pausedOnLadder[client]) { @@ -140,6 +153,21 @@ void Resume(int client) Call_GOKZ_OnResume_Post(client); } +bool CanResume(int client, bool showError = false) +{ + if (GetTimerRunning(client) && hasPausedInThisRun[client] + && GetEngineTime() - lastPauseTime[client] < GOKZ_PAUSE_COOLDOWN) + { + if (showError) + { + GOKZ_PrintToChat(client, true, "%t", "Can't Resume (Just Paused)"); + GOKZ_PlayErrorSound(client); + } + return false; + } + return true; +} + void TogglePause(int client) { if (paused[client]) diff --git a/addons/sourcemod/scripting/gokz-core/timer/timer.sp b/addons/sourcemod/scripting/gokz-core/timer/timer.sp index 4887f770..9086852b 100644 --- a/addons/sourcemod/scripting/gokz-core/timer/timer.sp +++ b/addons/sourcemod/scripting/gokz-core/timer/timer.sp @@ -59,7 +59,8 @@ bool TimerStart(int client, int course, bool allowMidair = false, bool playSound || JustNoclipped(client) || !IsPlayerValidMoveType(client) || !allowMidair && (!Movement_GetOnGround(client) || JustLanded(client)) - || allowMidair && !Movement_GetOnGround(client) && (!GOKZ_GetValidJump(client) || GOKZ_GetHitPerf(client))) + || allowMidair && !Movement_GetOnGround(client) && (!GOKZ_GetValidJump(client) || GOKZ_GetHitPerf(client)) + || (GOKZ_GetTimerRunning(client) && GOKZ_GetCourse(client) != course)) { return false; } diff --git a/addons/sourcemod/scripting/gokz-global.sp b/addons/sourcemod/scripting/gokz-global.sp index c7d6eabc..1243e355 100644 --- a/addons/sourcemod/scripting/gokz-global.sp +++ b/addons/sourcemod/scripting/gokz-global.sp @@ -293,12 +293,14 @@ public void GOKZ_OnTimerEnd_Post(int client, int course, float time, int telepor } } -public void GOKZ_RP_OnReplaySaved(int client, int replayType, const char[] map, int course, int timeType, float time, const char[] filePath) +public Action GOKZ_RP_OnReplaySaved(int client, int replayType, const char[] map, int course, int timeType, float time, const char[] filePath, bool tempReplay) { if (gB_GloballyVerified[client] && gB_InValidRun[client]) { - OnReplaySaved_SendReplay(client, replayType, map, course, timeType, time, filePath); + OnReplaySaved_SendReplay(client, replayType, map, course, timeType, time, filePath, tempReplay); + return Plugin_Handled; } + return Plugin_Continue; } public void GOKZ_OnRunInvalidated(int client) diff --git a/addons/sourcemod/scripting/gokz-global/send_run.sp b/addons/sourcemod/scripting/gokz-global/send_run.sp index 5966d7db..95b4e01b 100644 --- a/addons/sourcemod/scripting/gokz-global/send_run.sp +++ b/addons/sourcemod/scripting/gokz-global/send_run.sp @@ -1,5 +1,5 @@ /* - Sends a run to the global API. + Sends a run to the global API and delete the replay if it is a temporary replay. */ @@ -7,6 +7,7 @@ char storedReplayPath[MAXPLAYERS + 1][512]; int lastRecordId[MAXPLAYERS + 1], storedCourse[MAXPLAYERS + 1], storedTimeType[MAXPLAYERS + 1], storedUserId[MAXPLAYERS + 1]; float storedTime[MAXPLAYERS + 1]; +bool deleteRecord[MAXPLAYERS + 1]; // =====[ PUBLIC ]===== @@ -80,7 +81,7 @@ public int SendTimeCallback(JSON_Object response, GlobalAPIRequestData request, } -public void OnReplaySaved_SendReplay(int client, int replayType, const char[] map, int course, int timeType, float time, const char[] filePath) +public void OnReplaySaved_SendReplay(int client, int replayType, const char[] map, int course, int timeType, float time, const char[] filePath, bool tempReplay) { strcopy(storedReplayPath[client], sizeof(storedReplayPath[]), filePath); if (IsReplayReadyToSend(client, course, timeType, time)) @@ -94,6 +95,7 @@ public void OnReplaySaved_SendReplay(int client, int replayType, const char[] ma storedCourse[client] = course; storedTimeType[client] = timeType; storedTime[client] = time; + deleteRecord[client] = tempReplay; } } @@ -119,12 +121,22 @@ bool IsReplayReadyToSend(int client, int course, int timeType, float time) public void SendReplay(int client) { - GlobalAPI_CreateReplayForRecordId(SendReplayCallback, DEFAULT_DATA, lastRecordId[client], storedReplayPath[client]); + DataPack dp; + dp.WriteString(deleteRecord[client] ? storedReplayPath[client] : ""); + GlobalAPI_CreateReplayForRecordId(SendReplayCallback, dp, lastRecordId[client], storedReplayPath[client]); lastRecordId[client] = -1; storedReplayPath[client] = ""; } public int SendReplayCallback(JSON_Object response, GlobalAPIRequestData request, DataPack dp) { - + // Delete the temporary replay file if needed. + dp.Reset(); + char replayPath[PLATFORM_MAX_PATH]; + dp.ReadString(replayPath, sizeof(replayPath)); + if (replayPath[0] != '\0') + { + DeleteFile(replayPath); + } + delete dp; } diff --git a/addons/sourcemod/scripting/gokz-hud.sp b/addons/sourcemod/scripting/gokz-hud.sp index 3e7c4be0..a816172d 100644 --- a/addons/sourcemod/scripting/gokz-hud.sp +++ b/addons/sourcemod/scripting/gokz-hud.sp @@ -34,9 +34,9 @@ bool gB_MenuShowing[MAXPLAYERS + 1]; int gI_ObserverTarget[MAXPLAYERS + 1]; bool gB_JBTakeoff[MAXPLAYERS + 1]; bool gB_FastUpdateRate[MAXPLAYERS + 1]; +int gI_DynamicMenu[MAXPLAYERS + 1]; #include "gokz-hud/spectate_text.sp" -#include "gokz-hud/natives.sp" #include "gokz-hud/commands.sp" #include "gokz-hud/hide_weapon.sp" #include "gokz-hud/info_panel.sp" @@ -47,7 +47,7 @@ bool gB_FastUpdateRate[MAXPLAYERS + 1]; #include "gokz-hud/speed_text.sp" #include "gokz-hud/timer_text.sp" #include "gokz-hud/tp_menu.sp" - +#include "gokz-hud/natives.sp" // =====[ PLUGIN EVENTS ]===== @@ -172,6 +172,11 @@ public void OnPlayerRunCmdPost(int client, int buttons, int impulse, const float return; } + if (!IsValidClient(info.ID)) + { + return; + } + OnPlayerRunCmdPost_InfoPanel(client, cmdnum, info); OnPlayerRunCmdPost_RacingText(client, cmdnum); OnPlayerRunCmdPost_SpeedText(client, cmdnum, info); @@ -255,12 +260,17 @@ public void GOKZ_OnOptionChanged(int client, const char[] option, any newValue) { gB_FastUpdateRate[client] = GOKZ_HUD_GetOption(client, HUDOption_UpdateRate) == UpdateRate_Fast; } + else if (hudOption == HUDOption_DynamicMenu) + { + gI_DynamicMenu[client] = GOKZ_HUD_GetOption(client, HUDOption_DynamicMenu); + } } } public void GOKZ_OnOptionsLoaded(int client) { gB_FastUpdateRate[client] = GOKZ_HUD_GetOption(client, HUDOption_UpdateRate) == UpdateRate_Fast; + gI_DynamicMenu[client] = GOKZ_HUD_GetOption(client, HUDOption_DynamicMenu); } // =====[ OTHER EVENTS ]===== diff --git a/addons/sourcemod/scripting/gokz-hud/natives.sp b/addons/sourcemod/scripting/gokz-hud/natives.sp index 5b228c28..113f360d 100644 --- a/addons/sourcemod/scripting/gokz-hud/natives.sp +++ b/addons/sourcemod/scripting/gokz-hud/natives.sp @@ -1,13 +1,16 @@ - -// =====[ NATIVES ]===== - void CreateNatives() { + CreateNative("GOKZ_HUD_ForceUpdateTPMenu", Native_ForceUpdateTPMenu); CreateNative("GOKZ_HUD_GetMenuShowing", Native_GetMenuShowing); CreateNative("GOKZ_HUD_SetMenuShowing", Native_SetMenuShowing); CreateNative("GOKZ_HUD_GetMenuSpectatorText", Native_GetSpectatorText); } +public int Native_ForceUpdateTPMenu(Handle plugin, int numParams) +{ + SetForceUpdateTPMenu(GetNativeCell(1)); + return 0; +} public int Native_GetMenuShowing(Handle plugin, int numParams) { return view_as(gB_MenuShowing[GetNativeCell(1)]); @@ -16,6 +19,7 @@ public int Native_GetMenuShowing(Handle plugin, int numParams) public int Native_SetMenuShowing(Handle plugin, int numParams) { gB_MenuShowing[GetNativeCell(1)] = view_as(GetNativeCell(2)); + return 0; } public int Native_GetSpectatorText(Handle plugin, int numParams) @@ -24,5 +28,5 @@ public int Native_GetSpectatorText(Handle plugin, int numParams) GetNativeArray(2, info, sizeof(HUDInfo)); KZPlayer player = KZPlayer(GetNativeCell(1)); FormatNativeString(3, 0, 0, GetNativeCell(4), _, "", FormatSpectatorTextForMenu(player, info)); - return 1; + return 0; } \ No newline at end of file diff --git a/addons/sourcemod/scripting/gokz-hud/options.sp b/addons/sourcemod/scripting/gokz-hud/options.sp index 8d17338d..84bbf2b3 100644 --- a/addons/sourcemod/scripting/gokz-hud/options.sp +++ b/addons/sourcemod/scripting/gokz-hud/options.sp @@ -168,5 +168,23 @@ static void PrintOptionChangeMessage(int client, HUDOption option, any newValue) } } } + case HUDOption_DynamicMenu: + { + switch (newValue) + { + case DynamicMenu_Legacy: + { + GOKZ_PrintToChat(client, true, "%t", "Option - Dynamic Menu - Legacy"); + } + case DynamicMenu_Disabled: + { + GOKZ_PrintToChat(client, true, "%t", "Option - Dynamic Menu - Disable"); + } + case DynamicMenu_Enabled: + { + GOKZ_PrintToChat(client, true, "%t", "Option - Dynamic Menu - Enable"); + } + } + } } } \ No newline at end of file diff --git a/addons/sourcemod/scripting/gokz-hud/options_menu.sp b/addons/sourcemod/scripting/gokz-hud/options_menu.sp index a053444b..705df27f 100644 --- a/addons/sourcemod/scripting/gokz-hud/options_menu.sp +++ b/addons/sourcemod/scripting/gokz-hud/options_menu.sp @@ -144,6 +144,12 @@ public void TopMenuHandler_HUD(TopMenu topmenu, TopMenuAction action, TopMenuObj gC_HUDOptionPhrases[option], param, gC_SpecListPositionPhrases[GOKZ_HUD_GetOption(param, option)], param); } + case HUDOption_DynamicMenu: + { + FormatEx(buffer, maxlength, "%T - %T", + gC_HUDOptionPhrases[option], param, + gC_DynamicMenuPhrases[GOKZ_HUD_GetOption(param, option)], param); + } default:FormatToggleableOptionDisplay(param, option, buffer, maxlength); } } diff --git a/addons/sourcemod/scripting/gokz-hud/tp_menu.sp b/addons/sourcemod/scripting/gokz-hud/tp_menu.sp index cfacf3a8..d61b33c3 100644 --- a/addons/sourcemod/scripting/gokz-hud/tp_menu.sp +++ b/addons/sourcemod/scripting/gokz-hud/tp_menu.sp @@ -15,7 +15,14 @@ #define ITEM_INFO_PAUSE "pause" #define ITEM_INFO_START "start" - +static bool oldCanMakeCP[MAXPLAYERS + 1]; +static bool oldCanTP[MAXPLAYERS + 1]; +static bool oldCanPrevCP[MAXPLAYERS + 1]; +static bool oldCanNextCP[MAXPLAYERS + 1]; +static bool oldCanUndoTP[MAXPLAYERS + 1]; +static bool oldCanPause[MAXPLAYERS + 1]; +static bool oldCanResume[MAXPLAYERS + 1]; +static bool forceRefresh[MAXPLAYERS + 1]; // =====[ EVENTS ]===== @@ -85,7 +92,11 @@ public int MenuHandler_TPMenu(Menu menu, MenuAction action, int param1, int para } } - +// =====[ PUBLIC ]===== +void SetForceUpdateTPMenu(int client) +{ + forceRefresh[client] = true; +} // =====[ PRIVATE ]===== @@ -98,13 +109,24 @@ static void UpdateTPMenu(int client, HUDInfo info) return; } + bool force = forceRefresh[client] + || player.CanMakeCheckpoint != oldCanMakeCP[client] + || player.CanTeleportToCheckpoint != oldCanTP[client] + || player.CanPrevCheckpoint != oldCanPrevCP[client] + || player.CanNextCheckpoint != oldCanNextCP[client] + || player.CanUndoTeleport != oldCanUndoTP[client] + || player.CanPause != oldCanPause[client] + || player.CanResume != oldCanResume[client]; + + if (player.Alive) { if (player.TPMenu != TPMenu_Disabled) { if (GetClientMenu(client) == MenuSource_None || gB_MenuShowing[player.ID] && GetClientAvgLoss(player.ID, NetFlow_Both) > EPSILON - || gB_MenuShowing[player.ID] && player.TimerRunning && !player.Paused && player.TimerText == TimerText_TPMenu) + || gB_MenuShowing[player.ID] && player.TimerRunning && !player.Paused && player.TimerText == TimerText_TPMenu + || gB_MenuShowing[player.ID] && force) { ShowTPMenu(player, info); } @@ -127,6 +149,15 @@ static void UpdateTPMenu(int client, HUDInfo info) ShowPanel(player, info); } } + + oldCanMakeCP[client] = player.CanMakeCheckpoint; + oldCanTP[client] = player.CanTeleportToCheckpoint; + oldCanPrevCP[client] = player.CanPrevCheckpoint; + oldCanNextCP[client] = player.CanNextCheckpoint; + oldCanUndoTP[client] = player.CanUndoTeleport; + oldCanPause[client] = player.CanPause; + oldCanResume[client] = player.CanResume; + forceRefresh[client] = false; } static void ShowPanel(KZPlayer player, HUDInfo info) @@ -233,8 +264,17 @@ static void TPMenuAddItemCheckpoint(KZPlayer player, Menu menu) { Format(display, sizeof(display), "%s #%d", display, player.CheckpointCount); } + + // Legacy behavior: Always able to make checkpoint attempts. + if (gI_DynamicMenu[player.ID] == DynamicMenu_Enabled && !player.CanMakeCheckpoint) + { + menu.AddItem(ITEM_INFO_CHECKPOINT, display, ITEMDRAW_DISABLED); + } + else + { + menu.AddItem(ITEM_INFO_CHECKPOINT, display, ITEMDRAW_DEFAULT); + } - menu.AddItem(ITEM_INFO_CHECKPOINT, display, ITEMDRAW_DEFAULT); } static void TPMenuAddItemTeleport(KZPlayer player, Menu menu) @@ -245,8 +285,9 @@ static void TPMenuAddItemTeleport(KZPlayer player, Menu menu) { Format(display, sizeof(display), "%s #%d", display, player.TeleportCount); } - - if (player.CanTeleportToCheckpoint) + + // Legacy behavior: Only able to make TP attempts when there is a checkpoint. + if (gI_DynamicMenu[player.ID] == DynamicMenu_Disabled || player.CanTeleportToCheckpoint) { menu.AddItem(ITEM_INFO_TELEPORT, display, ITEMDRAW_DEFAULT); } @@ -260,7 +301,9 @@ static void TPMenuAddItemPrevCheckpoint(KZPlayer player, Menu menu) { char display[24]; FormatEx(display, sizeof(display), "%T", "TP Menu - Prev CP", player.ID); - if (player.CanPrevCheckpoint) + + // Legacy behavior: Only able to do prev CP when there is a previous checkpoint to go back to. + if (gI_DynamicMenu[player.ID] == DynamicMenu_Disabled || player.CanPrevCheckpoint) { menu.AddItem(ITEM_INFO_PREV, display, ITEMDRAW_DEFAULT); } @@ -274,7 +317,9 @@ static void TPMenuAddItemNextCheckpoint(KZPlayer player, Menu menu) { char display[24]; FormatEx(display, sizeof(display), "%T", "TP Menu - Next CP", player.ID); - if (player.CanNextCheckpoint) + + // Legacy behavior: Only able to do prev CP when there is a next checkpoint to go forward to. + if (gI_DynamicMenu[player.ID] == DynamicMenu_Disabled || player.CanNextCheckpoint) { menu.AddItem(ITEM_INFO_NEXT, display, ITEMDRAW_DEFAULT); } @@ -288,7 +333,9 @@ static void TPMenuAddItemUndo(KZPlayer player, Menu menu) { char display[24]; FormatEx(display, sizeof(display), "%T", "TP Menu - Undo TP", player.ID); - if (player.CanUndoTeleport) + + // Legacy behavior: Only able to attempt to undo TP when it is allowed. + if (gI_DynamicMenu[player.ID] == DynamicMenu_Disabled || player.CanUndoTeleport) { menu.AddItem(ITEM_INFO_UNDO, display, ITEMDRAW_DEFAULT); } @@ -296,19 +343,51 @@ static void TPMenuAddItemUndo(KZPlayer player, Menu menu) { menu.AddItem(ITEM_INFO_UNDO, display, ITEMDRAW_DISABLED); } + } static void TPMenuAddItemPause(KZPlayer player, Menu menu) { char display[24]; - if (player.Paused) + + // Legacy behavior: Always able to attempt to pause. + if (gI_DynamicMenu[player.ID] == DynamicMenu_Enabled) { - FormatEx(display, sizeof(display), "%T", "TP Menu - Resume", player.ID); - menu.AddItem(ITEM_INFO_PAUSE, display, ITEMDRAW_DEFAULT); + if (player.Paused) + { + FormatEx(display, sizeof(display), "%T", "TP Menu - Resume", player.ID); + if (player.CanResume) + { + menu.AddItem(ITEM_INFO_PAUSE, display, ITEMDRAW_DEFAULT); + } + else + { + menu.AddItem(ITEM_INFO_PAUSE, display, ITEMDRAW_DISABLED); + } + } + else + { + FormatEx(display, sizeof(display), "%T", "TP Menu - Pause", player.ID); + if (player.CanPause) + { + menu.AddItem(ITEM_INFO_PAUSE, display, ITEMDRAW_DEFAULT); + } + else + { + menu.AddItem(ITEM_INFO_PAUSE, display, ITEMDRAW_DISABLED); + } + } } else { - FormatEx(display, sizeof(display), "%T", "TP Menu - Pause", player.ID); + if (player.Paused) + { + FormatEx(display, sizeof(display), "%T", "TP Menu - Resume", player.ID); + } + else + { + FormatEx(display, sizeof(display), "%T", "TP Menu - Pause", player.ID); + } menu.AddItem(ITEM_INFO_PAUSE, display, ITEMDRAW_DEFAULT); } } diff --git a/addons/sourcemod/scripting/gokz-replays.sp b/addons/sourcemod/scripting/gokz-replays.sp index 32e38fad..fa556952 100644 --- a/addons/sourcemod/scripting/gokz-replays.sp +++ b/addons/sourcemod/scripting/gokz-replays.sp @@ -128,6 +128,8 @@ public void OnConfigsExecuted() FindConVar("bot_zombie").BoolValue = true; FindConVar("bot_join_after_player").BoolValue = false; FindConVar("bot_quota_mode").SetString("normal"); + FindConVar("bot_quota").Flags &= ~FCVAR_NOTIFY; + FindConVar("bot_quota").Flags &= ~FCVAR_REPLICATED; } public void OnEntityCreated(int entity, const char[] classname) diff --git a/addons/sourcemod/scripting/gokz-replays/api.sp b/addons/sourcemod/scripting/gokz-replays/api.sp index 4fea95a7..3c115e1a 100644 --- a/addons/sourcemod/scripting/gokz-replays/api.sp +++ b/addons/sourcemod/scripting/gokz-replays/api.sp @@ -38,13 +38,14 @@ public int Native_RP_UpdateReplayControlMenu(Handle plugin, int numParams) void CreateGlobalForwards() { - H_OnReplaySaved = new GlobalForward("GOKZ_RP_OnReplaySaved", ET_Ignore, Param_Cell, Param_Cell, Param_String, Param_Cell, Param_Cell, Param_Float, Param_String); + H_OnReplaySaved = new GlobalForward("GOKZ_RP_OnReplaySaved", ET_Event, Param_Cell, Param_Cell, Param_String, Param_Cell, Param_Cell, Param_Float, Param_String, Param_Cell); H_OnReplayDiscarded = new GlobalForward("GOKZ_RP_OnReplayDiscarded", ET_Ignore, Param_Cell); H_OnTimerEnd_Post = new GlobalForward("GOKZ_RP_OnTimerEnd_Post", ET_Ignore, Param_Cell, Param_String, Param_Cell, Param_Float, Param_Cell); } -void Call_OnReplaySaved(int client, int replayType, const char[] map, int course, int timeType, float time, const char[] filePath) +Action Call_OnReplaySaved(int client, int replayType, const char[] map, int course, int timeType, float time, const char[] filePath, bool tempReplay) { + Action result; Call_StartForward(H_OnReplaySaved); Call_PushCell(client); Call_PushCell(replayType); @@ -53,7 +54,9 @@ void Call_OnReplaySaved(int client, int replayType, const char[] map, int course Call_PushCell(timeType); Call_PushFloat(time); Call_PushString(filePath); - Call_Finish(); + Call_PushCell(tempReplay); + Call_Finish(result); + return result; } void Call_OnReplayDiscarded(int client) diff --git a/addons/sourcemod/scripting/gokz-replays/playback.sp b/addons/sourcemod/scripting/gokz-replays/playback.sp index d1ae41e8..5653a272 100644 --- a/addons/sourcemod/scripting/gokz-replays/playback.sp +++ b/addons/sourcemod/scripting/gokz-replays/playback.sp @@ -15,6 +15,10 @@ static ArrayList playbackTickData[RP_MAX_BOTS]; static bool inBreather[RP_MAX_BOTS]; static float breatherStartTime[RP_MAX_BOTS]; +// Original bot caller, needed for OnClientPutInServer callback +static int botCaller[RP_MAX_BOTS]; +// Original bot name after creation by bot_add, needed for bot removal +static char botName[RP_MAX_BOTS][MAX_NAME_LENGTH]; static bool botInGame[RP_MAX_BOTS]; static int botClient[RP_MAX_BOTS]; static bool botDataLoaded[RP_MAX_BOTS]; @@ -40,6 +44,7 @@ static int timeInAir[RP_MAX_BOTS]; static int botTeleportsUsed[RP_MAX_BOTS]; static int botCurrentTeleport[RP_MAX_BOTS]; static int botButtons[RP_MAX_BOTS]; +static MoveType botMoveType[RP_MAX_BOTS]; static float botTakeoffSpeed[RP_MAX_BOTS]; static float botSpeed[RP_MAX_BOTS]; static float botLastOrigin[RP_MAX_BOTS][3]; @@ -54,12 +59,12 @@ static float botLandingSpeed[RP_MAX_BOTS]; // =====[ PUBLIC ]===== // Returns the client index of the replay bot, or -1 otherwise -int LoadReplayBot(int client, char[] path) +int LoadReplayBot(int client, char[] path, int timeType = -1) { int bot; if (GetBotsInUse() < RP_MAX_BOTS) { - bot = GetUnusedBot(); + bot = GetUnusedBot(timeType); } else { @@ -81,9 +86,7 @@ int LoadReplayBot(int client, char[] path) GOKZ_PlayErrorSound(client); return -1; } - - SetBotStuff(bot); - MakePlayerSpectate(client, botClient[bot]); + botCaller[bot] = client; return botClient[bot]; } @@ -126,7 +129,7 @@ void GetPlaybackState(int client, HUDInfo info) info.TimeType = botTeleportsUsed[bot] > 0 ? TimeType_Nub : TimeType_Pro; info.Speed = botSpeed[bot]; info.Paused = false; - info.OnLadder = false; + info.OnLadder = (botMoveType[bot] == MOVETYPE_LADDER); info.Noclipping = false; info.OnGround = Movement_GetOnGround(client); info.Ducking = botButtons[bot] & IN_DUCK > 0; @@ -251,10 +254,18 @@ void OnClientPutInServer_Playback(int client) // Check if an unassigned bot has joined, and assign it for (int bot; bot < RP_MAX_BOTS; bot++) { - if (!botInGame[bot]) + // Also check if the bot was created by us. + if (!botInGame[bot] && botCaller[bot] != 0) { botInGame[bot] = true; botClient[bot] = client; + GetClientName(client, botName[bot], sizeof(botName[])); + SetBotStuff(bot); + if (IsValidClient(botCaller[bot])) + { + MakePlayerSpectate(botCaller[bot], botClient[bot]); + botCaller[bot] = 0; + } break; } } @@ -715,7 +726,7 @@ static void PlaybackVersion1(int client, int bot, int &buttons) playbackTickData[bot].Clear(); // Clear it all out botDataLoaded[bot] = false; CancelReplayControlsForBot(bot); - KickClient(botClient[bot]); + ServerCommand("bot_kick %s", botName[bot]); } } } @@ -735,7 +746,7 @@ static void PlaybackVersion1(int client, int bot, int &buttons) playbackTickData[bot].Clear(); botDataLoaded[bot] = false; CancelReplayControlsForBot(bot); - KickClient(botClient[bot]); + ServerCommand("bot_kick %s", botName[bot]); return; } @@ -769,6 +780,7 @@ static void PlaybackVersion1(int client, int bot, int &buttons) CopyVector(repOrigin, botLastOrigin[bot]); botSpeed[bot] = GetVectorHorizontalLength(velocity); + buttons = repButtons; botButtons[bot] = repButtons; // Should the bot be ducking?! @@ -880,7 +892,7 @@ void PlaybackVersion2(int client, int bot, int &buttons) playbackTickData[bot].Clear(); // Clear it all out botDataLoaded[bot] = false; CancelReplayControlsForBot(bot); - KickClient(botClient[bot]); + ServerCommand("bot_kick %s", botName[bot]); } } } @@ -900,7 +912,7 @@ void PlaybackVersion2(int client, int bot, int &buttons) playbackTickData[bot].Clear(); botDataLoaded[bot] = false; CancelReplayControlsForBot(bot); - KickClient(botClient[bot]); + ServerCommand("bot_kick %s", botName[bot]); return; } @@ -936,59 +948,62 @@ void PlaybackVersion2(int client, int bot, int &buttons) botSpeed[bot] = GetVectorHorizontalLength(currentTickData.velocity); // Set buttons + int newButtons; if (currentTickData.flags & RP_IN_ATTACK) { - buttons |= IN_ATTACK; + newButtons |= IN_ATTACK; } if (currentTickData.flags & RP_IN_ATTACK2) { - buttons |= IN_ATTACK2; + newButtons |= IN_ATTACK2; } if (currentTickData.flags & RP_IN_JUMP) { - buttons |= IN_JUMP; + newButtons |= IN_JUMP; } if (currentTickData.flags & RP_IN_DUCK || currentTickData.flags & RP_FL_DUCKING) { - buttons |= IN_DUCK; + newButtons |= IN_DUCK; } if (currentTickData.flags & RP_IN_FORWARD) { - buttons |= IN_FORWARD; + newButtons |= IN_FORWARD; } if (currentTickData.flags & RP_IN_BACK) { - buttons |= IN_BACK; + newButtons |= IN_BACK; } if (currentTickData.flags & RP_IN_LEFT) { - buttons |= IN_LEFT; + newButtons |= IN_LEFT; } if (currentTickData.flags & RP_IN_RIGHT) { - buttons |= IN_RIGHT; + newButtons |= IN_RIGHT; } if (currentTickData.flags & RP_IN_MOVELEFT) { - buttons |= IN_MOVELEFT; + newButtons |= IN_MOVELEFT; } if (currentTickData.flags & RP_IN_MOVERIGHT) { - buttons |= IN_MOVERIGHT; + newButtons |= IN_MOVERIGHT; } if (currentTickData.flags & RP_IN_RELOAD) { - buttons |= IN_RELOAD; + newButtons |= IN_RELOAD; } if (currentTickData.flags & RP_IN_SPEED) { - buttons |= IN_SPEED; + newButtons |= IN_SPEED; } + buttons = newButtons; botButtons[bot] = buttons; int entityFlags = GetEntityFlags(client); // Set the bot's MoveType MoveType replayMoveType = view_as(currentTickData.flags & RP_MOVETYPE_MASK); + botMoveType[bot] = replayMoveType; if (Movement_GetSpeed(client) > SPEED_NORMAL * 2) { Movement_SetMovetype(client, MOVETYPE_NOCLIP); @@ -998,6 +1013,23 @@ void PlaybackVersion2(int client, int bot, int &buttons) botPaused[bot] = false; SetEntityFlags(client, entityFlags | FL_ONGROUND); Movement_SetMovetype(client, MOVETYPE_WALK); + // The bot is on the ground, so there must be a ground entity attributed to the bot. + int groundEnt = GetEntPropEnt(client, Prop_Send, "m_hGroundEntity"); + if (groundEnt == -1) + { + float endPosition[3], mins[3], maxs[3]; + GetEntPropVector(client, Prop_Send, "m_vecMaxs", maxs); + GetEntPropVector(client, Prop_Send, "m_vecMins", mins); + endPosition = currentTickData.origin; + endPosition[2] -= 2.0; + TR_TraceHullFilter(currentTickData.origin, endPosition, mins, maxs, MASK_PLAYERSOLID, TraceEntityFilterPlayers); + // This should always hit. + if (TR_DidHit()) + { + groundEnt = TR_GetEntityIndex(); + SetEntPropEnt(client, Prop_Data, "m_hGroundEntity", groundEnt); + } + } } else if (replayMoveType == MOVETYPE_LADDER) { @@ -1097,7 +1129,7 @@ static void SetBotStuff(int bot) { return; } - + int client = botClient[bot]; // Set its movement options just in case it could negatively affect the playback @@ -1108,17 +1140,6 @@ static void SetBotStuff(int bot) SetBotClanTag(bot); SetBotName(bot); - // Set the bot's team based on if it's NUB or PRO - if (botReplayType[bot] == ReplayType_Run - && GOKZ_GetTimeTypeEx(botTeleportsUsed[bot]) == TimeType_Pro) - { - GOKZ_JoinTeam(client, CS_TEAM_CT); - } - else - { - GOKZ_JoinTeam(client, CS_TEAM_T); - } - // Set bot weapons // Always start by removing the pistol and knife int currentPistol = GetPlayerWeaponSlot(client, CS_SLOT_SECONDARY); @@ -1248,13 +1269,21 @@ static int GetBotsInUse() } // Returns a bot that isn't currently replaying, or -1 if no unused bots found -static int GetUnusedBot() +static int GetUnusedBot(int timeType = -1) { for (int bot = 0; bot < RP_MAX_BOTS; bot++) { if (!botInGame[bot]) { - CreateFakeClient("botName"); + // Set the bot's team based on if it's NUB or PRO + if (timeType == TimeType_Pro) + { + ServerCommand("bot_add_ct"); + } + else + { + ServerCommand("bot_add_t"); + } return bot; } } @@ -1345,33 +1374,13 @@ static void MakePlayerSpectate(int client, int bot) DataPack data = new DataPack(); data.WriteCell(clientUserID); data.WriteCell(GetClientUserId(bot)); - - CreateTimer(0.2, Timer_ResetSpectate, clientUserID); - CreateTimer(0.3, Timer_SpectateBot, data); // After delay so name is correctly updated in client's HUD + CreateTimer(0.1, Timer_UpdateBotName, GetClientUserId(bot)); EnableReplayControls(client); } -public Action Timer_ResetSpectate(Handle timer, int clientUID) +public Action Timer_UpdateBotName(Handle timer, int botUID) { - int client = GetClientOfUserId(clientUID); - if (IsValidClient(client)) - { - SetEntProp(client, Prop_Send, "m_iObserverMode", -1); - SetEntPropEnt(client, Prop_Send, "m_hObserverTarget", -1); - } -} -public Action Timer_SpectateBot(Handle timer, DataPack data) -{ - data.Reset(); - int client = GetClientOfUserId(data.ReadCell()); - int bot = GetClientOfUserId(data.ReadCell()); - delete data; - - if (IsValidClient(client) && IsValidClient(bot)) - { - GOKZ_JoinTeam(client, CS_TEAM_SPECTATOR); - SetEntProp(client, Prop_Send, "m_iObserverMode", 4); - SetEntPropEnt(client, Prop_Send, "m_hObserverTarget", bot); - } - return Plugin_Continue; + Event e = CreateEvent("spec_target_updated"); + e.SetInt("userid", botUID); + e.Fire(); } \ No newline at end of file diff --git a/addons/sourcemod/scripting/gokz-replays/recording.sp b/addons/sourcemod/scripting/gokz-replays/recording.sp index e686adfc..07a5aab8 100644 --- a/addons/sourcemod/scripting/gokz-replays/recording.sp +++ b/addons/sourcemod/scripting/gokz-replays/recording.sp @@ -6,11 +6,13 @@ of the last 2 minutes of their actions. If a player is banned while their timer isn't running, those 2 minutes are saved. If the player has their timer running, the recording is done from - the beginning of the run. If the player misses the server record, + the beginning of the run. If the player can no longer beat their PB, then the recording goes back to only keeping track of the last - two minutes. Upon beating the server record, a binary file will be - written with a 'header' containing information about the run, + two minutes. Upon beating their PB, a temporary binary file will be + written with a 'header' containing information about the run, followed by the recorded tick data from OnPlayerRunCmdPost. + The binary file will be permanently locally saved on the server + if the run beats the server record. */ static float tickrate; @@ -20,7 +22,7 @@ static int recordingIndex[MAXPLAYERS + 1]; static float playerSensitivity[MAXPLAYERS + 1]; static float playerMYaw[MAXPLAYERS + 1]; static bool isTeleportTick[MAXPLAYERS + 1]; -static bool timerRunning[MAXPLAYERS + 1]; +static ReplaySaveState replaySaveState[MAXPLAYERS + 1]; static bool recordingPaused[MAXPLAYERS + 1]; static bool postRunRecording[MAXPLAYERS + 1]; static ArrayList recordedRecentData[MAXPLAYERS + 1]; @@ -121,18 +123,27 @@ void OnPlayerRunCmdPost_Recording(int client, int buttons, int tickCount, const isTeleportTick[client] = false; } - if (timerRunning[client]) + if (replaySaveState[client] != ReplaySave_Disabled) { int runTick = GetArraySize(recordedRunData[client]); - recordedRunData[client].Resize(runTick + 1); - recordedRunData[client].SetArray(runTick, tickData); + if (runTick < RP_MAX_DURATION) + { + // Resize might fail if the timer exceed the max duration, + // as it is not guaranteed to allocate more than 1GB of contiguous memory, + // causing mass lag spikes that kick everyone out of the server. + // We can still attempt to save the rest of the recording though. + recordedRunData[client].Resize(runTick + 1); + recordedRunData[client].SetArray(runTick, tickData); + } } - if (postRunRecording[client]) { int tick = GetArraySize(recordedPostRunData[client]); - recordedPostRunData[client].Resize(tick + 1); - recordedPostRunData[client].SetArray(tick, tickData); + if (tick < RP_MAX_DURATION) + { + recordedPostRunData[client].Resize(tick + 1); + recordedPostRunData[client].SetArray(tick, tickData); + } } int tick = recordingIndex[client]; @@ -163,13 +174,13 @@ Action GOKZ_OnTimerStart_Recording(int client) void GOKZ_OnTimerStart_Post_Recording(int client) { - timerRunning[client] = true; + replaySaveState[client] = ReplaySave_Local; StartRunRecording(client); } void GOKZ_OnTimerEnd_Recording(int client, int course, float time, int teleportsUsed) { - if (!timerRunning[client]) + if (replaySaveState[client] == ReplaySave_Disabled) { return; } @@ -179,7 +190,7 @@ void GOKZ_OnTimerEnd_Recording(int client, int course, float time, int teleports data.WriteCell(course); data.WriteFloat(time); data.WriteCell(teleportsUsed); - + data.WriteCell(replaySaveState[client]); // The previous run breather still did not finish, end it now or // we will start overwriting the data. if (runningRunBreatherTimer[client] != INVALID_HANDLE) @@ -187,7 +198,7 @@ void GOKZ_OnTimerEnd_Recording(int client, int course, float time, int teleports TriggerTimer(runningRunBreatherTimer[client], false); } - timerRunning[client] = false; + replaySaveState[client] = ReplaySave_Disabled; postRunRecording[client] = true; // Swap recordedRunData and recordedPostRunData. @@ -212,6 +223,7 @@ public Action Timer_EndRecording(Handle timer, DataPack data) int course = data.ReadCell(); float time = data.ReadFloat(); int teleportsUsed = data.ReadCell(); + ReplaySaveState saveState = data.ReadCell(); delete data; // The client left after the run was done but before the post-run @@ -227,12 +239,12 @@ public Action Timer_EndRecording(Handle timer, DataPack data) if (gB_GOKZLocalDB && GOKZ_DB_IsCheater(client)) { - Call_OnTimerEnd_Post(client, "", course, time, teleportsUsed); - return Plugin_Stop; + // Replay might be submitted globally, but will not be saved locally. + saveState = ReplaySave_Temp; } char path[PLATFORM_MAX_PATH]; - if (SaveRecordingOfRun(path, client, course, time, teleportsUsed)) + if (SaveRecordingOfRun(path, client, course, time, teleportsUsed, saveState == ReplaySave_Temp)) { Call_OnTimerEnd_Post(client, path, course, time, teleportsUsed); } @@ -256,14 +268,14 @@ void GOKZ_OnResume_Recording(int client) void GOKZ_OnTimerStopped_Recording(int client) { - timerRunning[client] = false; + replaySaveState[client] = ReplaySave_Disabled; } void GOKZ_OnCountedTeleport_Recording(int client) { if (gB_NubRecordMissed[client]) { - timerRunning[client] = false; + replaySaveState[client] = ReplaySave_Disabled; } isTeleportTick[client] = true; @@ -271,10 +283,14 @@ void GOKZ_OnCountedTeleport_Recording(int client) void GOKZ_LR_OnRecordMissed_Recording(int client, int recordType) { + if (replaySaveState[client] == ReplaySave_Disabled) + { + return; + } // If missed PRO record or both records, then can no longer beat a server record if (recordType == RecordType_NubAndPro || recordType == RecordType_Pro) { - timerRunning[client] = false; + replaySaveState[client] = ReplaySave_Temp; } // If on a NUB run and missed NUB record, then can no longer beat a server record @@ -283,7 +299,30 @@ void GOKZ_LR_OnRecordMissed_Recording(int client, int recordType) { if (GOKZ_GetTeleportCount(client) > 0) { - timerRunning[client] = false; + replaySaveState[client] = ReplaySave_Temp; + } + } +} + +public void GOKZ_LR_OnPBMissed(int client, float pbTime, int course, int mode, int style, int recordType) +{ + if (replaySaveState[client] == ReplaySave_Disabled) + { + return; + } + // If missed PRO record or both records, then can no longer beat PB + if (recordType == RecordType_NubAndPro || recordType == RecordType_Pro) + { + replaySaveState[client] = ReplaySave_Disabled; + } + + // If on a NUB run and missed NUB record, then can no longer beat PB + // Otherwise wait to see if they teleport before stopping the recording + if (recordType == RecordType_Nub) + { + if (GOKZ_GetTeleportCount(client) > 0) + { + replaySaveState[client] = ReplaySave_Disabled; } } } @@ -355,7 +394,7 @@ static void ClearClientRecordingState(int client) playerSensitivity[client] = -1.0; playerMYaw[client] = -1.0; isTeleportTick[client] = false; - timerRunning[client] = false; + replaySaveState[client] = ReplaySave_Disabled; recordingPaused[client] = false; postRunRecording[client] = false; runningRunBreatherTimer[client] = INVALID_HANDLE; @@ -436,7 +475,7 @@ static void ResumeRecording(int client) recordingPaused[client] = false; } -static bool SaveRecordingOfRun(char replayPath[PLATFORM_MAX_PATH], int client, int course, float time, int teleportsUsed) +static bool SaveRecordingOfRun(char replayPath[PLATFORM_MAX_PATH], int client, int course, float time, int teleportsUsed, bool temp) { // Prepare data int timeType = GOKZ_GetTimeTypeEx(teleportsUsed); @@ -452,12 +491,12 @@ static bool SaveRecordingOfRun(char replayPath[PLATFORM_MAX_PATH], int client, i runHeader.teleportsUsed = teleportsUsed; // Build path and create/overwrite associated file - FormatRunReplayPath(replayPath, sizeof(replayPath), course, generalHeader.mode, generalHeader.style, timeType); + FormatRunReplayPath(replayPath, sizeof(replayPath), course, generalHeader.mode, generalHeader.style, timeType, temp); if (FileExists(replayPath)) { DeleteFile(replayPath); } - else + else if (!temp) { AddToReplayInfoCache(course, generalHeader.mode, generalHeader.style, timeType); SortReplayInfoCache(); @@ -480,8 +519,11 @@ static bool SaveRecordingOfRun(char replayPath[PLATFORM_MAX_PATH], int client, i WriteTickData(file, client, ReplayType_Run); delete file; - - Call_OnReplaySaved(client, ReplayType_Run, gC_CurrentMap, course, timeType, time, replayPath); + // If there is no plugin that wants to take over the replay file, we will delete it ourselves. + if (Call_OnReplaySaved(client, ReplayType_Run, gC_CurrentMap, course, timeType, time, replayPath, temp) == Plugin_Continue && temp) + { + DeleteFile(replayPath); + } return true; } @@ -728,12 +770,20 @@ static void WriteTickDataToFile(File file, bool isFirstTick, ReplayTickData tick } } -static void FormatRunReplayPath(char[] buffer, int maxlength, int course, int mode, int style, int timeType) +static void FormatRunReplayPath(char[] buffer, int maxlength, int course, int mode, int style, int timeType, bool tempPath) { + // Use GetEngineTime to prevent accidental replay overrides. + // Technically it would still be possible to override this file by accident, + // if somehow the server restarts to this exact map and course, + // and this function is run at the exact same time, but that is extremely unlikely. + // Also by then this file should have already been deleted. + char tempTimeString[32]; + Format(tempTimeString, sizeof(tempTimeString), "%f_", GetEngineTime()); BuildPath(Path_SM, buffer, maxlength, - "%s/%s/%d_%s_%s_%s.%s", - RP_DIRECTORY_RUNS, + "%s/%s/%s%d_%s_%s_%s.%s", + tempPath ? RP_DIRECTORY_RUNS_TEMP : RP_DIRECTORY_RUNS, gC_CurrentMap, + tempPath ? tempTimeString : "", course, gC_ModeNamesShort[mode], gC_StyleNamesShort[style], diff --git a/addons/sourcemod/scripting/gokz-replays/replay_menu.sp b/addons/sourcemod/scripting/gokz-replays/replay_menu.sp index 028ce22e..1e77dc6d 100644 --- a/addons/sourcemod/scripting/gokz-replays/replay_menu.sp +++ b/addons/sourcemod/scripting/gokz-replays/replay_menu.sp @@ -69,7 +69,7 @@ public int MenuHandler_Replay(Menu menu, MenuAction action, int param1, int para } } - LoadReplayBot(param1, path); + LoadReplayBot(param1, path, replayInfo[3]); } else if (action == MenuAction_Cancel) { diff --git a/addons/sourcemod/scripting/gokz-saveloc.sp b/addons/sourcemod/scripting/gokz-saveloc.sp index eaccfc4a..256dc566 100644 --- a/addons/sourcemod/scripting/gokz-saveloc.sp +++ b/addons/sourcemod/scripting/gokz-saveloc.sp @@ -9,7 +9,7 @@ #undef REQUIRE_EXTENSIONS #undef REQUIRE_PLUGIN #include - +#include #pragma newdecls required #pragma semicolon 1 @@ -41,6 +41,7 @@ enum struct Location { ArrayList undoTeleportData; // Movement related states + int groundEnt; int flags; float position[3]; float angles[3]; @@ -61,6 +62,7 @@ enum struct Location { void Create(int client, int target) { GetClientName(client, this.locationCreator, sizeof(Location::locationCreator)); + this.groundEnt = GetEntPropEnt(target, Prop_Data, "m_hGroundEntity"); this.flags = GetEntityFlags(target); this.mode = GOKZ_GetCoreOption(target, Option_Mode); this.course = GOKZ_GetCourse(target); @@ -110,6 +112,7 @@ enum struct Location { GOKZ_SetTeleportCount(client, this.teleportCount); GOKZ_SetUndoTeleportData(client, this.undoTeleportData, GOKZ_CHECKPOINT_VERSION); + SetEntPropEnt(client, Prop_Data, "m_hGroundEntity", this.groundEnt); SetEntityFlags(client, this.flags); TeleportEntity(client, this.position, this.angles, this.velocity); SetEntPropFloat(client, Prop_Send, "m_flDuckAmount", this.duckAmount); @@ -135,7 +138,7 @@ bool gB_LocMenuOpen[MAXPLAYERS + 1]; bool gB_UsedLoc[MAXPLAYERS + 1]; int gI_MostRecentLocation[MAXPLAYERS + 1]; - +bool gB_GOKZHUD; // =====[ PLUGIN EVENTS ]===== @@ -160,6 +163,7 @@ public void OnAllPluginsLoaded() { Updater_AddPlugin(UPDATER_URL); } + gB_GOKZHUD = LibraryExists("gokz-hud"); } public void OnLibraryAdded(const char[] name) @@ -168,6 +172,12 @@ public void OnLibraryAdded(const char[] name) { Updater_AddPlugin(UPDATER_URL); } + gB_GOKZHUD = gB_GOKZHUD || StrEqual(name, "gokz-hud"); +} + +public void OnLibraryRemoved(const char[] name) +{ + gB_GOKZHUD = gB_GOKZHUD && !StrEqual(name, "gokz-hud"); } public void OnMapStart() @@ -605,6 +615,10 @@ bool LoadLocation(int client, int id) if (loc.Load(client)) { gB_UsedLoc[client] = true; + if (gB_GOKZHUD) + { + GOKZ_HUD_ForceUpdateTPMenu(client); + } } // print message if loading new location if (gI_MostRecentLocation[client] != id) diff --git a/addons/sourcemod/scripting/include/gokz/core.inc b/addons/sourcemod/scripting/include/gokz/core.inc index dc025e74..0ccf0834 100644 --- a/addons/sourcemod/scripting/include/gokz/core.inc +++ b/addons/sourcemod/scripting/include/gokz/core.inc @@ -215,6 +215,7 @@ enum TriggerType #define GOKZ_JUMPSTATS_NOCLIP_RESET_TICKS 4 #define GOKZ_TIMER_SOUND_COOLDOWN 0.15 #define GOKZ_VIRTUAL_BUTTON_USE_DETECTION_TIME 2.0 +#define GOKZ_TURNBIND_COOLDOWN 64 #define GOKZ_MAPPING_API_VERSION_NONE 0 // the map doesn't have a mapping api version #define GOKZ_MAPPING_API_VERSION 1 @@ -1205,6 +1206,13 @@ native void GOKZ_TeleportToEnd(int client, int course); */ native void GOKZ_MakeCheckpoint(int client); +/** + * Gets whether a player can make a new checkpoint. + * @param client Client index. + * @return Whether player can set a checkpoint. + */ +native bool GOKZ_GetCanMakeCheckpoint(int client); + /** * Teleports a player to their last checkpoint. * @@ -1291,6 +1299,14 @@ native bool GOKZ_GetCanPause(int client); */ native void GOKZ_Resume(int client); +/** + * Gets whether a player can resume. Resuming is not allowed + * under some circumstance when the timer is running. + * + * @param client Client index. + */ +native bool GOKZ_GetCanResume(int client); + /** * Toggles the paused state of a player. * @@ -1737,6 +1753,7 @@ public void __pl_gokz_core_SetNTVOptional() MarkNativeAsOptional("GOKZ_SetStartPositionToMapStart"); MarkNativeAsOptional("GOKZ_TeleportToEnd"); MarkNativeAsOptional("GOKZ_MakeCheckpoint"); + MarkNativeAsOptional("GOKZ_GetCanMakeCheckpoint"); MarkNativeAsOptional("GOKZ_TeleportToCheckpoint"); MarkNativeAsOptional("GOKZ_GetCanTeleportToCheckpoint"); MarkNativeAsOptional("GOKZ_PrevCheckpoint"); @@ -1748,6 +1765,7 @@ public void __pl_gokz_core_SetNTVOptional() MarkNativeAsOptional("GOKZ_Pause"); MarkNativeAsOptional("GOKZ_GetCanPause"); MarkNativeAsOptional("GOKZ_Resume"); + MarkNativeAsOptional("GOKZ_GetCanResume"); MarkNativeAsOptional("GOKZ_TogglePause"); MarkNativeAsOptional("GOKZ_PlayErrorSound"); MarkNativeAsOptional("GOKZ_SetValidJumpOrigin"); diff --git a/addons/sourcemod/scripting/include/gokz/hud.inc b/addons/sourcemod/scripting/include/gokz/hud.inc index c819738c..5d658ff8 100644 --- a/addons/sourcemod/scripting/include/gokz/hud.inc +++ b/addons/sourcemod/scripting/include/gokz/hud.inc @@ -26,9 +26,10 @@ enum HUDOption: HUDOption_ShowWeapon, HUDOption_ShowControls, HUDOption_DeadstrafeColor, - HUDOption_UpdateRate, HUDOption_ShowSpectators, HUDOption_SpecListPosition, + HUDOption_UpdateRate, + HUDOption_DynamicMenu, HUDOPTION_COUNT }; @@ -116,7 +117,6 @@ enum SHOWSPECS_COUNT }; - enum { SpecListPosition_TPMenu = 0, @@ -131,6 +131,14 @@ enum UPDATERATE_COUNT, }; +enum +{ + DynamicMenu_Legacy = 0, + DynamicMenu_Disabled, + DynamicMenu_Enabled, + DYNAMICMENU_COUNT +}; + // =====[ STRUCTS ]====== enum struct HUDInfo @@ -174,10 +182,11 @@ stock char gC_HUDOptionNames[HUDOPTION_COUNT][] = "GOKZ HUD - Speed Text", "GOKZ HUD - Show Weapon", "GOKZ HUD - Show Controls", + "GOKZ HUD - Dead Strafe", "GOKZ HUD - Show Spectators", "GOKZ HUD - Spec List Pos", - "GOKZ HUD - Dead Strafe", - "GOKZ HUD - Update Rate" + "GOKZ HUD - Update Rate", + "GOKZ HUD - Dynamic Menu" }; stock char gC_HUDOptionDescriptions[HUDOPTION_COUNT][] = @@ -191,10 +200,11 @@ stock char gC_HUDOptionDescriptions[HUDOPTION_COUNT][] = "Speed Display - 0 = Disabled, 1 = Centre Panel, 2 = Bottom", "Weapon Viewmodel - 0 = Disabled, 1 = Enabled", "Replay Controls Display - 0 = Disbled, 1 = Enabled", + "Dead Strafe Indicator - 0 = Disabled, 1 = Enabled", "Show Spectators - 0 = Disabled, 1 = Number Only, 2 = Number and Names", "Spectator List Position - 0 = Teleport Menu, 2 = Center Panel", - "Dead Strafe Indicator - 0 = Disabled, 1 = Enabled", - "HUD Update Rate - 0 = Slow, 1 = Fast" + "HUD Update Rate - 0 = Slow, 1 = Fast", + "Dynamic Menu - 0 = Legacy, 1 = Disabled, 2 = Enabled" }; stock char gC_HUDOptionPhrases[HUDOPTION_COUNT][] = @@ -208,10 +218,11 @@ stock char gC_HUDOptionPhrases[HUDOPTION_COUNT][] = "Options Menu - Speed Text", "Options Menu - Show Weapon", "Options Menu - Show Controls", + "Options Menu - Dead Strafe Indicator", "Options Menu - Show Spectators", "Options Menu - Spectator List Position", - "Options Menu - Dead Strafe Indicator", - "Options Menu - Update Rate" + "Options Menu - Update Rate", + "Options Menu - Dynamic Menu" }; stock int gI_HUDOptionCounts[HUDOPTION_COUNT] = @@ -225,10 +236,11 @@ stock int gI_HUDOptionCounts[HUDOPTION_COUNT] = SPEEDTEXT_COUNT, SHOWWEAPON_COUNT, REPLAYCONTROLS_COUNT, + DEADSTRAFECOLOR_COUNT, SHOWSPECS_COUNT, SPECLISTPOSITION_COUNT, - DEADSTRAFECOLOR_COUNT, - UPDATERATE_COUNT + UPDATERATE_COUNT, + DYNAMICMENU_COUNT }; stock int gI_HUDOptionDefaults[HUDOPTION_COUNT] = @@ -242,10 +254,11 @@ stock int gI_HUDOptionDefaults[HUDOPTION_COUNT] = SpeedText_InfoPanel, ShowWeapon_Enabled, ReplayControls_Enabled, + DeadstrafeColor_Disabled, ShowSpecs_Disabled, SpecListPosition_TPMenu, - DeadstrafeColor_Disabled, - UpdateRate_Slow + UpdateRate_Slow, + DynamicMenu_Legacy }; stock char gC_TPMenuPhrases[TPMENU_COUNT][] = @@ -315,6 +328,13 @@ stock char gC_HUDUpdateRatePhrases[UPDATERATE_COUNT][]= "Options Menu - Fast" }; +stock char gC_DynamicMenuPhrases[DYNAMICMENU_COUNT][]= +{ + "Options Menu - Legacy", + "Options Menu - Disabled", + "Options Menu - Enabled" +}; + // =====[ NATIVES ]===== /** @@ -341,6 +361,13 @@ native void GOKZ_HUD_SetMenuShowing(int client, bool value); */ native void GOKZ_HUD_GetMenuSpectatorText(int client, any[] info, char[] buffer, int size); +/** + * Forces the client's TP menu to update. + * + * @param client Client index. + */ +native void GOKZ_HUD_ForceUpdateTPMenu(int client); + // =====[ STOCKS ]===== /** @@ -436,5 +463,6 @@ public void __pl_gokz_hud_SetNTVOptional() MarkNativeAsOptional("GOKZ_HUD_GetMenuShowing"); MarkNativeAsOptional("GOKZ_HUD_SetMenuShowing"); MarkNativeAsOptional("GOKZ_HUD_GetMenuSpectatorText"); + MarkNativeAsOptional("GOKZ_HUD_ForceUpdateTPMenu"); } #endif diff --git a/addons/sourcemod/scripting/include/gokz/kzplayer.inc b/addons/sourcemod/scripting/include/gokz/kzplayer.inc index be58d00c..5959ddd7 100644 --- a/addons/sourcemod/scripting/include/gokz/kzplayer.inc +++ b/addons/sourcemod/scripting/include/gokz/kzplayer.inc @@ -106,6 +106,12 @@ methodmap KZPlayer < MovementAPIPlayer { GOKZ_MakeCheckpoint(this.ID); } + property bool CanMakeCheckpoint { + public get() { + return GOKZ_GetCanMakeCheckpoint(this.ID); + } + } + public void TeleportToCheckpoint() { GOKZ_TeleportToCheckpoint(this.ID); } @@ -160,6 +166,12 @@ methodmap KZPlayer < MovementAPIPlayer { GOKZ_Resume(this.ID); } + property bool CanResume { + public get() { + return GOKZ_GetCanResume(this.ID); + } + } + public void TogglePause() { GOKZ_TogglePause(this.ID); } @@ -456,6 +468,14 @@ methodmap KZPlayer < MovementAPIPlayer { GOKZ_HUD_SetMenuShowing(this.ID, value); } } + property int DynamicMenu { + public get() { + return this.GetHUDOption(HUDOption_DynamicMenu); + } + public set(int value) { + this.SetHUDOption(HUDOption_DynamicMenu, value); + } + } #endif // =====[ END HUD ]===== diff --git a/addons/sourcemod/scripting/include/gokz/replays.inc b/addons/sourcemod/scripting/include/gokz/replays.inc index ea0e6c6f..7c1c1dff 100644 --- a/addons/sourcemod/scripting/include/gokz/replays.inc +++ b/addons/sourcemod/scripting/include/gokz/replays.inc @@ -29,6 +29,13 @@ enum REPLAYTYPE_COUNT }; +enum ReplaySaveState +{ + ReplaySave_Local = 0, + ReplaySave_Temp, + ReplaySave_Disabled +}; + // NOTE: Replays use delta compression for storage. // This enum is the indices of the ReplayTickData enum struct. // NOTE: This has to match the ReplayTickData enum struct!!! @@ -121,6 +128,7 @@ enum struct ReplayTickData #define RP_DIRECTORY "data/gokz-replays" // In Path_SM #define RP_DIRECTORY_RUNS "data/gokz-replays/_runs" // In Path_SM +#define RP_DIRECTORY_RUNS_TEMP "data/gokz-replays/_tempRuns" // In Path_SM #define RP_DIRECTORY_CHEATERS "data/gokz-replays/_cheaters" // In Path_SM #define RP_DIRECTORY_JUMPS "data/gokz-replays/_jumps" // In Path_SM #define RP_DIRECTORY_BLOCKJUMPS "blocks" @@ -130,13 +138,13 @@ enum struct ReplayTickData #define RP_NAV_FILE "maps/gokz-replays.nav" #define RP_V1_TICK_DATA_BLOCKSIZE 7 #define RP_CACHE_BLOCKSIZE 4 -#define RP_MAX_BOTS 2 +#define RP_MAX_BOTS 4 #define RP_PLAYBACK_BREATHER_TIME 2.0 #define RP_MIN_CHEATER_REPLAY_LENGTH 30 // 30 seconds #define RP_MAX_CHEATER_REPLAY_LENGTH 120 // 2 minutes #define RP_MAX_BHOP_GROUND_TICKS 5 #define RP_SKIP_TIME 10 // 10 seconds - +#define RP_MAX_DURATION 6451200 // 14 hours on 128 tick #define RP_MOVETYPE_MASK (0xF) #define RP_IN_ATTACK (1 << 4) @@ -178,8 +186,10 @@ enum struct ReplayTickData * @param timeType The type of time (Pro/Nub). * @param time The time the run was completed in. * @param filePath Replay file path. + * @param tempReplay Whether the replay file should only be temporaily stored. + * @return Plugin_Handled to take over the temporary replay deletion, Plugin_Continue to allow temporary replay deletion by the replay plugin. */ -forward void GOKZ_RP_OnReplaySaved(int client, int replayType, const char[] map, int course, int timeType, float time, const char[] filePath); +forward Action GOKZ_RP_OnReplaySaved(int client, int replayType, const char[] map, int course, int timeType, float time, const char[] filePath, bool tempReplay); /** * Called when a currently being recorded replay is discarded from diff --git a/addons/sourcemod/translations/gokz-common.phrases.txt b/addons/sourcemod/translations/gokz-common.phrases.txt index 5b373251..43a4f478 100644 --- a/addons/sourcemod/translations/gokz-common.phrases.txt +++ b/addons/sourcemod/translations/gokz-common.phrases.txt @@ -74,6 +74,10 @@ "chi" "关闭" "ru" "Выключено" } + "Options Menu - Legacy" + { + "en" "Legacy" + } "Options Menu - Top" { "en" "Top" diff --git a/addons/sourcemod/translations/gokz-core.phrases.txt b/addons/sourcemod/translations/gokz-core.phrases.txt index bc0ac654..bdca8e52 100644 --- a/addons/sourcemod/translations/gokz-core.phrases.txt +++ b/addons/sourcemod/translations/gokz-core.phrases.txt @@ -119,6 +119,10 @@ { "en" "{darkred}You can't undo because you teleported while in an anti-checkpoint zone." } + "Can't Pause (Generic)" + { + "en" "{darkred}You can't pause right now." + } "Can't Pause (Just Resumed)" { "en" "{darkred}You can't pause because you just resumed." @@ -140,6 +144,10 @@ { "en" "{darkred}You can't pause because pausing is disabled in this area." } + "Can't Pause (Generic)" + { + "en" "{darkred}You can't resume right now." + } "Can't Resume (Just Paused)" { "en" "{darkred}You can't resume because you just paused." diff --git a/addons/sourcemod/translations/gokz-hud.phrases.txt b/addons/sourcemod/translations/gokz-hud.phrases.txt index 79609eb5..fff8edd0 100644 --- a/addons/sourcemod/translations/gokz-hud.phrases.txt +++ b/addons/sourcemod/translations/gokz-hud.phrases.txt @@ -91,6 +91,18 @@ { "en" "{grey}Number and names of spectators are now shown." } + "Option - Dynamic Menu - Legacy" + { + "en" "{grey}Dynamic menu is set to legacy mode." + } + "Option - Dynamic Menu - Disable" + { + "en" "{grey}Dynamic menu disabled. Every menu option is now selectable." + } + "Option - Dynamic Menu - Enable" + { + "en" "{grey}Dynamic menu enabled. Unavailable options are now unselectable. This option is not recommended with high latency!" + } "Option - Spectator List Position - Info Panel" { "en" "{grey}Spectator list now displays in the centre panel." @@ -277,18 +289,17 @@ } "Options Menu - Show Spectators" { - "en" "Spectator list" + "en" "Show spectators" } "Options Menu - Spectator List Position" { "en" "Spectator list position" } - "Options Menu - Show Spectators" + "Options Menu - Dynamic Menu" { - "en" "Show spectators" + "en" "Dynamic menu" } - // =====[ RACING ]===== "Get Ready" { diff --git a/cfg/sourcemod/gokz/gokz.cfg b/cfg/sourcemod/gokz/gokz.cfg index 79657137..6da09e45 100644 --- a/cfg/sourcemod/gokz/gokz.cfg +++ b/cfg/sourcemod/gokz/gokz.cfg @@ -57,6 +57,8 @@ mp_footsteps_serverside 1 sv_mincmdrate 128 sv_minupdaterate 128 mp_warmuptime_all_players_connected 0 +// Fix bots not spawning +mp_randomspawn 1 // Team picking mp_force_pick_time 60 diff --git a/cfg/sourcemod/gokz/options_menu_sorting.cfg b/cfg/sourcemod/gokz/options_menu_sorting.cfg index f216154f..7628d640 100644 --- a/cfg/sourcemod/gokz/options_menu_sorting.cfg +++ b/cfg/sourcemod/gokz/options_menu_sorting.cfg @@ -25,6 +25,7 @@ { "item" "GOKZ HUD - Update Rate" "item" "GOKZ HUD - Teleport Menu" + "item" "GOKZ HUD - Dynamic Menu" "item" "GOKZ HUD - Centre Panel" "item" "GOKZ HUD - Timer Text" "item" "GOKZ HUD - Timer Style" From 9e140c59d7b900979cf51ed087c825b6b29e4282 Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Wed, 5 Oct 2022 21:35:13 +0200 Subject: [PATCH 08/47] Fix players sliding off slopes upon teleporting to checkpoint, implement teleport angle fix for packet loss scenarios --- .../gamedata/gokz-tpanglefix.games.txt | 55 ++++ .../scripting/gokz-core/teleports.sp | 6 +- addons/sourcemod/scripting/gokz-tpanglefix.sp | 266 ++++++++++++++++++ addons/sourcemod/scripting/include/gokz.inc | 2 + .../sourcemod/scripting/include/gokz/core.inc | 6 +- .../scripting/include/gokz/tpanglefix.inc | 40 +++ .../gokz-tips-tpanglefix.phrases.txt | 7 + .../translations/gokz-tpanglefix.phrases.txt | 19 ++ 8 files changed, 398 insertions(+), 3 deletions(-) create mode 100644 addons/sourcemod/gamedata/gokz-tpanglefix.games.txt create mode 100644 addons/sourcemod/scripting/gokz-tpanglefix.sp create mode 100644 addons/sourcemod/scripting/include/gokz/tpanglefix.inc create mode 100644 addons/sourcemod/translations/gokz-tips-tpanglefix.phrases.txt create mode 100644 addons/sourcemod/translations/gokz-tpanglefix.phrases.txt diff --git a/addons/sourcemod/gamedata/gokz-tpanglefix.games.txt b/addons/sourcemod/gamedata/gokz-tpanglefix.games.txt new file mode 100644 index 00000000..eabef7bd --- /dev/null +++ b/addons/sourcemod/gamedata/gokz-tpanglefix.games.txt @@ -0,0 +1,55 @@ +"Games" +{ + "csgo" + { + "Functions" + { + "CGameClient::WriteViewAngleUpdate" + { + "signature" "CGameClient::WriteViewAngleUpdate" + "callconv" "thiscall" + "this" "address" + "return" "void" + } + } + "Addresses" + { + "WriteViewAngleUpdate" + { + "windows" + { + "signature" "CGameClient::WriteViewAngleUpdate" + } + "linux" + { + "signature" "CGameClient::WriteViewAngleUpdate" + } + } + } + + "Offsets" + { + "WriteViewAngleUpdateReliableOffset" + { + "windows" "363" + "linux" "290" + } + "ClientIndexOffset" + { + "linux" "116" + "windows" "116" + } + } + + "Signatures" + { + //A few functions after "%c00000000000000" string + "CGameClient::WriteViewAngleUpdate" + { + "library" "engine" + "windows" "\x55\x8B\xEC\x83\xEC\x40\x56\x57" + "linux" "\x55\x89\xE5\x83\xEC\x68\x89\x75\xF8\x8B\x75\x08\x89\x5D\xF4\x89\x7D\xFC\x8B\x06" + } + } + } +} diff --git a/addons/sourcemod/scripting/gokz-core/teleports.sp b/addons/sourcemod/scripting/gokz-core/teleports.sp index 4996e762..e6f2ea85 100644 --- a/addons/sourcemod/scripting/gokz-core/teleports.sp +++ b/addons/sourcemod/scripting/gokz-core/teleports.sp @@ -805,7 +805,11 @@ static void CheckpointTeleportDo(int client) checkpoints[client].GetArray(checkpointIndex[client], cp); TeleportDo(client, cp.origin, cp.angles); - + if (cp.groundEnt != INVALID_ENT_REFERENCE) + { + SetEntPropEnt(client, Prop_Data, "m_hGroundEntity", cp.groundEnt); + SetEntityFlags(client, GetEntityFlags(client) | FL_ONGROUND); + } // Handle ladder stuff if (cp.onLadder) { diff --git a/addons/sourcemod/scripting/gokz-tpanglefix.sp b/addons/sourcemod/scripting/gokz-tpanglefix.sp new file mode 100644 index 00000000..6c3d392a --- /dev/null +++ b/addons/sourcemod/scripting/gokz-tpanglefix.sp @@ -0,0 +1,266 @@ +#include + +#include + +#include +#include + +#include + +#undef REQUIRE_EXTENSIONS +#undef REQUIRE_PLUGIN +#include + +#pragma newdecls required +#pragma semicolon 1 + + + +public Plugin myinfo = +{ + name = "GOKZ Teleport Angle Fix", + author = "zer0.k", + description = "Fix teleporting not modifying player's view angles due to packet loss", + version = GOKZ_VERSION, + url = "https://github.com/KZGlobalTeam/gokz" +}; + +#define UPDATER_URL GOKZ_UPDATER_BASE_URL..."gokz-tpanglefix.txt" + +TopMenu gTM_Options; +TopMenuObject gTMO_CatGeneral; +TopMenuObject gTMO_ItemTPAngleFix; +Address gA_ViewAnglePatchAddress; +bool gB_EnableFix[MAXPLAYERS + 1]; +DynamicDetour gH_WriteViewAngleUpdate; +int gI_ClientOffset; + +// =====[ PLUGIN EVENTS ]===== + +public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) +{ + RegPluginLibrary("gokz-tpanglefix"); + return APLRes_Success; +} + +public void OnPluginStart() +{ + LoadTranslations("gokz-common.phrases"); + LoadTranslations("gokz-tpanglefix.phrases"); + + SetupPatch(); + HookEvents(); + RegisterCommands(); +} + +void SetupPatch() +{ + GameData gamedataConf = LoadGameConfigFile("gokz-tpanglefix.games"); + if (gamedataConf == null) + { + SetFailState("Failed to load gokz-tpanglefix gamedata"); + } + // Get the patching address + Address addr = GameConfGetAddress(gamedataConf, "WriteViewAngleUpdate"); + if(addr == Address_Null) + { + SetFailState("Can't find WriteViewAngleUpdate address."); + } + + // Get the offset from the start of the signature to the start of our patch area. + int offset = GameConfGetOffset(gamedataConf, "WriteViewAngleUpdateReliableOffset"); + if(offset == -1) + { + SetFailState("Can't find WriteViewAngleUpdateReliableOffset in gamedata."); + } + gA_ViewAnglePatchAddress = view_as
(addr + view_as
(offset)); +} + +void HookEvents() +{ + GameData gamedataConf = LoadGameConfigFile("gokz-tpanglefix.games"); + if (gamedataConf == null) + { + SetFailState("Failed to load gokz-tpanglefix gamedata"); + } + gH_WriteViewAngleUpdate = DynamicDetour.FromConf(gamedataConf, "CGameClient::WriteViewAngleUpdate"); + + if (gH_WriteViewAngleUpdate == INVALID_HANDLE) + { + SetFailState("Failed to find CGameClient::WriteViewAngleUpdate function signature"); + } + + if (!gH_WriteViewAngleUpdate.Enable(Hook_Pre, DHooks_OnWriteViewAngleUpdate_Pre)) + { + SetFailState("Failed to enable detour on CGameClient::WriteViewAngleUpdate"); + } + // Prevent the server from crashing. + FindConVar("sv_parallel_sendsnapshot").SetBool(false); + gI_ClientOffset = gamedataConf.GetOffset("ClientIndexOffset"); + if (gI_ClientOffset == -1) + { + SetFailState("Failed to get ClientIndexOffset offset."); + } +} +public MRESReturn DHooks_OnWriteViewAngleUpdate_Pre(Address pThis) +{ + int client = LoadFromAddress(pThis + view_as
(gI_ClientOffset), NumberType_Int32); + if (gB_EnableFix[client]) + { + PatchAngleFix(); + } + else + { + RestoreAngleFix(); + } + return MRES_Ignored; +} + +void PatchAngleFix() +{ + if (LoadFromAddress(gA_ViewAnglePatchAddress, NumberType_Int8) == 0) + { + StoreToAddress(gA_ViewAnglePatchAddress, 1, NumberType_Int8); + } +} + +void RestoreAngleFix() +{ + if (LoadFromAddress(gA_ViewAnglePatchAddress, NumberType_Int8) == 1) + { + StoreToAddress(gA_ViewAnglePatchAddress, 0, NumberType_Int8); + } +} + +bool ToggleAngleFix(int client) +{ + gB_EnableFix[client] = !gB_EnableFix[client]; + return gB_EnableFix[client]; +} + +public void OnAllPluginsLoaded() +{ + if (LibraryExists("updater")) + { + Updater_AddPlugin(UPDATER_URL); + } + + TopMenu topMenu; + if (LibraryExists("gokz-core") && ((topMenu = GOKZ_GetOptionsTopMenu()) != null)) + { + GOKZ_OnOptionsMenuReady(topMenu); + } +} + +public void OnLibraryAdded(const char[] name) +{ + if (StrEqual(name, "updater")) + { + Updater_AddPlugin(UPDATER_URL); + } + +} + +// =====[ CLIENT EVENTS ]===== + +public void GOKZ_OnOptionChanged(int client, const char[] option, any newValue) +{ + OnOptionChanged_Options(client, option, newValue); +} + +// =====[ OTHER EVENTS ]===== + +public void GOKZ_OnOptionsMenuReady(TopMenu topMenu) +{ + OnOptionsMenuReady_Options(); + OnOptionsMenuReady_OptionsMenu(topMenu); +} + + +// =====[ OPTIONS ]===== + +void OnOptionsMenuReady_Options() +{ + RegisterOption(); +} + +void RegisterOption() +{ + GOKZ_RegisterOption(TPANGLEFIX_OPTION_NAME, TPANGLEFIX_OPTION_DESCRIPTION, + OptionType_Int, TPAngleFix_Disabled, 0, TPANGLEFIX_COUNT - 1); +} + +void OnOptionChanged_Options(int client, const char[] option, any newValue) +{ + if (StrEqual(option, TPANGLEFIX_OPTION_NAME)) + { + gB_EnableFix[client] = newValue; + switch (newValue) + { + case TPAngleFix_Disabled: + { + GOKZ_PrintToChat(client, true, "%t", "Option - TP Angle Fix - Disable"); + } + case TPAngleFix_Enabled: + { + GOKZ_PrintToChat(client, true, "%t", "Option - TP Angle Fix - Enable"); + } + } + } +} + +// =====[ OPTIONS MENU ]===== + +void OnOptionsMenuReady_OptionsMenu(TopMenu topMenu) +{ + if (gTM_Options == topMenu) + { + return; + } + + gTM_Options = topMenu; + gTMO_CatGeneral = gTM_Options.FindCategory(GENERAL_OPTION_CATEGORY); + gTMO_ItemTPAngleFix = gTM_Options.AddItem(TPANGLEFIX_OPTION_NAME, TopMenuHandler_TPAngleFix, gTMO_CatGeneral); +} + +public void TopMenuHandler_TPAngleFix(TopMenu topmenu, TopMenuAction action, TopMenuObject topobj_id, int param, char[] buffer, int maxlength) +{ + if (topobj_id != gTMO_ItemTPAngleFix) + { + return; + } + + if (action == TopMenuAction_DisplayOption) + { + if (GOKZ_GetOption(param, TPANGLEFIX_OPTION_NAME) == TPAngleFix_Disabled) + { + FormatEx(buffer, maxlength, "%T - %T", + "Options Menu - TP Angle Fix", param, + "Options Menu - Disabled", param); + } + else + { + FormatEx(buffer, maxlength, "%T - %T", + "Options Menu - TP Angle Fix", param, + "Options Menu - Enabled", param); + } + } + else if (action == TopMenuAction_SelectOption) + { + GOKZ_CycleOption(param, TPANGLEFIX_OPTION_NAME); + gTM_Options.Display(param, TopMenuPosition_LastCategory); + } +} + +// =====[ COMMANDS ]===== + +void RegisterCommands() +{ + RegConsoleCmd("sm_tpafix", CommandTPAFix, "[KZ] Toggle teleport angle fix."); +} + +public Action CommandTPAFix(int client, int args) +{ + GOKZ_SetOption(client, TPANGLEFIX_OPTION_NAME, ToggleAngleFix(client)); + return Plugin_Handled; +} \ No newline at end of file diff --git a/addons/sourcemod/scripting/include/gokz.inc b/addons/sourcemod/scripting/include/gokz.inc index b1e23444..9f3adc29 100644 --- a/addons/sourcemod/scripting/include/gokz.inc +++ b/addons/sourcemod/scripting/include/gokz.inc @@ -433,6 +433,8 @@ stock void TeleportPlayer(int client, const float origin[3], const float angles[ AcceptEntityInput(client, "ClearParent"); Movement_SetOrigin(client, origin); + Movement_SetVelocity(client, view_as( { 0.0, 0.0, 0.0 } )); + Movement_SetBaseVelocity(client, view_as( { 0.0, 0.0, 0.0 } )); if (setAngles) { // NOTE: changing angles with TeleportEntity can fail due to packet loss!!! diff --git a/addons/sourcemod/scripting/include/gokz/core.inc b/addons/sourcemod/scripting/include/gokz/core.inc index 0ccf0834..0b2857f4 100644 --- a/addons/sourcemod/scripting/include/gokz/core.inc +++ b/addons/sourcemod/scripting/include/gokz/core.inc @@ -201,7 +201,7 @@ enum TriggerType // =====[ CONSTANTS ]===== -#define GOKZ_CHECKPOINT_VERSION 1 +#define GOKZ_CHECKPOINT_VERSION 2 #define GOKZ_MAX_CHECKPOINTS 2048 #define GOKZ_MAX_COURSES 100 @@ -442,6 +442,7 @@ enum struct Checkpoint float angles[3]; float ladderNormal[3]; bool onLadder; + int groundEnt; void Create(int client) { @@ -449,6 +450,7 @@ enum struct Checkpoint Movement_GetEyeAngles(client, this.angles); GetEntPropVector(client, Prop_Send, "m_vecLadderNormal", this.ladderNormal); this.onLadder = Movement_GetMovetype(client) == MOVETYPE_LADDER; + this.groundEnt = GetEntPropEnt(client, Prop_Data, "m_hGroundEntity"); } } @@ -457,7 +459,7 @@ enum struct UndoTeleportData float tempOrigin[3]; float tempAngles[3]; float origin[3]; - float angles[3]; + float angles[3]; // Undo TP properties bool lastTeleportOnGround; bool lastTeleportInBhopTrigger; diff --git a/addons/sourcemod/scripting/include/gokz/tpanglefix.inc b/addons/sourcemod/scripting/include/gokz/tpanglefix.inc new file mode 100644 index 00000000..fc8faa29 --- /dev/null +++ b/addons/sourcemod/scripting/include/gokz/tpanglefix.inc @@ -0,0 +1,40 @@ +/* + gokz-tpanglefix Plugin Include + + Website: https://github.com/KZGlobalTeam/gokz +*/ + +#if defined _gokz_tpanglefix_included_ +#endinput +#endif +#define _gokz_tpanglefix_included_ + + +// =====[ ENUMS ]===== + +enum +{ + TPAngleFix_Disabled = 0, + TPAngleFix_Enabled, + TPANGLEFIX_COUNT +}; + + +// =====[ CONSTANTS ]===== + +#define TPANGLEFIX_OPTION_NAME "GOKZ - TPAngleFix" +#define TPANGLEFIX_OPTION_DESCRIPTION "TPAngleFix - 0 = Disabled, 1 = Enabled" + + +// =====[ DEPENDENCY ]===== + +public SharedPlugin __pl_gokz_tpanglefix = +{ + name = "gokz-tpanglefix", + file = "gokz-tpanglefix.smx", + #if defined REQUIRE_PLUGIN + required = 1, + #else + required = 0, + #endif +}; \ No newline at end of file diff --git a/addons/sourcemod/translations/gokz-tips-tpanglefix.phrases.txt b/addons/sourcemod/translations/gokz-tips-tpanglefix.phrases.txt new file mode 100644 index 00000000..48961c15 --- /dev/null +++ b/addons/sourcemod/translations/gokz-tips-tpanglefix.phrases.txt @@ -0,0 +1,7 @@ +"Phrases" +{ + "TP Angle Fix" + { + "en" "{grey}Having high packet loss? Type {default}!tpafix {grey} to fix teleport angles being broken." + } +} \ No newline at end of file diff --git a/addons/sourcemod/translations/gokz-tpanglefix.phrases.txt b/addons/sourcemod/translations/gokz-tpanglefix.phrases.txt new file mode 100644 index 00000000..f60d187d --- /dev/null +++ b/addons/sourcemod/translations/gokz-tpanglefix.phrases.txt @@ -0,0 +1,19 @@ +"Phrases" +{ + // =====[ CHAT MESSAGES ]===== + "Option - TP Angle Fix - Enable" + { + "en" "{grey}Teleport angle fix enabled. All angle changes due to teleporting will be guaranteed. This helps with high packet loss situations." + } + "Option - TP Angle Fix - Disable" + { + "en" "{grey}Teleport angle fix disabled." + } + + + // =====[ OPTIONS MENU ]===== + "Options Menu - TP Angle Fix" + { + "en" "Reliable teleport angles" + } +} \ No newline at end of file From 01167fe3d1e874792ac448ec8cfb39fc49c1d270 Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Fri, 7 Oct 2022 00:32:55 +0200 Subject: [PATCH 09/47] Allow player to press buttons through players --- addons/sourcemod/scripting/gokz-core.sp | 6 + addons/sourcemod/scripting/gokz-core/misc.sp | 171 ++++++++++++++++++ addons/sourcemod/scripting/include/gokz.inc | 59 +++++- .../sourcemod/scripting/include/gokz/core.inc | 23 ++- .../translations/gokz-core.phrases.txt | 5 +- cfg/sourcemod/gokz/options_menu_sorting.cfg | 1 + 6 files changed, 258 insertions(+), 7 deletions(-) diff --git a/addons/sourcemod/scripting/gokz-core.sp b/addons/sourcemod/scripting/gokz-core.sp index 05596759..4dc00951 100644 --- a/addons/sourcemod/scripting/gokz-core.sp +++ b/addons/sourcemod/scripting/gokz-core.sp @@ -281,6 +281,11 @@ public void OnCSPlayerSpawnPost(int client) } } +public void OnClientPreThinkPost(int client) +{ + OnClientPreThinkPost_UseButtons(client); +} + public void Movement_OnChangeMovetype(int client, MoveType oldMovetype, MoveType newMovetype) { OnChangeMovetype_Timer(client, newMovetype); @@ -513,6 +518,7 @@ static void HookClientEvents(int client) DHookEntity(gH_DHooks_OnTeleport, true, client); DHookEntity(gH_DHooks_SetModel, true, client); SDKHook(client, SDKHook_SpawnPost, OnCSPlayerSpawnPost); + SDKHook(client, SDKHook_PreThinkPost, OnClientPreThinkPost); } static void UpdateTrackingVariables(int client, int cmdnum, int buttons) diff --git a/addons/sourcemod/scripting/gokz-core/misc.sp b/addons/sourcemod/scripting/gokz-core/misc.sp index fb1a5634..5e07a9c8 100644 --- a/addons/sourcemod/scripting/gokz-core/misc.sp +++ b/addons/sourcemod/scripting/gokz-core/misc.sp @@ -572,3 +572,174 @@ void OnMapStart_FixMissingSpawns() } } } + +// =====[ BUTTONS ]===== + +void OnClientPreThinkPost_UseButtons(int client) +{ + if (GOKZ_GetCoreOption(client, Option_ButtonThroughPlayers) == ButtonThroughPlayers_Enabled && GetEntProp(client, Prop_Data, "m_afButtonPressed") & IN_USE) + { + int entity = FindUseEntity(client); + if (entity != -1) + { + AcceptEntityInput(entity, "Use", client, client, 1); + } + } +} + +static int FindUseEntity(int client) +{ + float fwd[3]; + float angles[3]; + GetClientEyeAngles(client, angles); + GetAngleVectors(angles, fwd, NULL_VECTOR, NULL_VECTOR); + + Handle trace; + + float eyeOrigin[3]; + GetClientEyePosition(client, eyeOrigin); + int useableContents = (MASK_NPCSOLID_BRUSHONLY | MASK_OPAQUE_AND_NPCS) & ~CONTENTS_OPAQUE; + + float endpos[3]; + + // Check if +use trace collide with a player first, so we don't activate any button twice + trace = TR_TraceRayFilterEx(eyeOrigin, angles, useableContents, RayType_Infinite, TRFOtherPlayersOnly, client); + if (TR_DidHit(trace)) + { + int ent = TR_GetEntityIndex(trace); + if (ent < 1 || ent > MaxClients) + { + return -1; + } + // Search for a button behind it. + trace = TR_TraceRayFilterEx(eyeOrigin, angles, useableContents, RayType_Infinite, TraceEntityFilterPlayers); + if (TR_DidHit(trace)) + { + char buffer[20]; + ent = TR_GetEntityIndex(trace); + // Make sure that it is a button, and this button activates when pressed. + // If it is not a button, check its parent to see if it is a button. + bool isButton; + while (ent != -1) + { + GetEntityClassname(ent, buffer, sizeof(buffer)); + if (StrEqual("func_button", buffer, false) && GetEntProp(ent, Prop_Data, "m_spawnflags") & SF_BUTTON_USE_ACTIVATES) + { + isButton = true; + break; + } + else + { + ent = GetEntPropEnt(ent, Prop_Data, "m_hMoveParent"); + } + } + if (isButton) + { + TR_GetEndPosition(endpos, trace); + float delta[3]; + for (int i = 0; i < 2; i++) + { + delta[i] = endpos[i] - eyeOrigin[i]; + } + // Z distance is treated differently. + float m_vecMins[3]; + float m_vecMaxs[3]; + float m_vecOrigin[3]; + GetEntPropVector(ent, Prop_Send, "m_vecOrigin", m_vecOrigin); + GetEntPropVector(ent, Prop_Send, "m_vecMins", m_vecMins); + GetEntPropVector(ent, Prop_Send, "m_vecMaxs", m_vecMaxs); + + delta[2] = IntervalDistance(endpos[2], m_vecOrigin[2] + m_vecMins[2], m_vecOrigin[2] + m_vecMaxs[2]); + if (GetVectorLength(delta) < 80.0) + { + return ent; + } + } + } + } + + int nearestEntity; + float nearestPoint[3]; + float nearestDist = FLOAT_MAX; + ArrayList entities = new ArrayList(); + TR_EnumerateEntitiesSphere(eyeOrigin, 80.0, 1<<5, AddEntities, entities); + for (int i = 0; i < entities.Length; i++) + { + char buffer[64]; + int ent = entities.Get(i); + GetEntityClassname(ent, buffer, sizeof(buffer)); + // Check if the entity is a button and it is pressable. + if (StrEqual("func_button", buffer, false) && GetEntProp(ent, Prop_Data, "m_spawnflags") & SF_BUTTON_USE_ACTIVATES) + { + float point[3]; + CalcNearestPoint(ent, eyeOrigin, point); + + float dir[3]; + for (int j = 0; j < 3; j++) + { + dir[j] = point[j] - eyeOrigin[2]; + } + // Check the maximum angle the player can be away from the button. + float minimumDot = GetEntPropFloat(ent, Prop_Send, "m_flUseLookAtAngle"); + NormalizeVector(dir, dir); + float dot = GetVectorDotProduct(dir, fwd); + if (dot < minimumDot) + { + continue; + } + + float dist = CalcDistanceToLine(point, eyeOrigin, fwd); + if (dist < nearestDist) + { + trace = TR_TraceRayFilterEx(eyeOrigin, point, useableContents, RayType_EndPoint, TraceEntityFilterPlayers); + if (TR_GetFraction(trace) == 1.0 || TR_GetEntityIndex(trace) == ent) + { + CopyVector(point, nearestPoint); + nearestDist = dist; + nearestEntity = ent; + } + } + } + } + // We found the closest button, but we still need to check if there is a player in front of it or not. + // In the case that there isn't a player inbetween, we don't return the entity index, because that button will be pressed by the game function anyway. + // If there is, we will press two buttons at once, the "right" button found by this function and the "wrong" button that we only happen to press because + // there is a player in the way. + + trace = TR_TraceRayFilterEx(eyeOrigin, nearestPoint, useableContents, RayType_EndPoint, TRFOtherPlayersOnly); + if (TR_DidHit(trace)) + { + return nearestEntity; + } + return -1; +} + +public bool AddEntities(int entity, ArrayList entities) +{ + entities.Push(entity); + return true; +} + +static float IntervalDistance(float x, float x0, float x1) +{ + if (x0 > x1) + { + float tmp = x0; + x0 = x1; + x1 = tmp; + } + if (x < x0) + { + return x0 - x; + } + else if (x > x1) + { + return x - x1; + } + return 0.0; +} +// TraceRay filter for other players exclusively. +public bool TRFOtherPlayersOnly(int entity, int contentmask, int client) +{ + return (0 < entity <= MaxClients) && (entity != client); +} diff --git a/addons/sourcemod/scripting/include/gokz.inc b/addons/sourcemod/scripting/include/gokz.inc index bf06312e..d62a1dc9 100644 --- a/addons/sourcemod/scripting/include/gokz.inc +++ b/addons/sourcemod/scripting/include/gokz.inc @@ -40,7 +40,9 @@ enum ObsMode #define PI 3.14159265359 #define SPEED_NORMAL 250.0 #define SPEED_NO_WEAPON 260.0 -#define IGNORE_JUMP_TIME 0.2 +#define FLOAT_MAX view_as(0x7F7FFFFF) +#define SF_BUTTON_USE_ACTIVATES 1024 +#define IGNORE_JUMP_TIME 0.2 stock float PLAYER_MINS[3] = {-16.0, -16.0, 0.0}; stock float PLAYER_MAXS[3] = {16.0, 16.0, 72.0}; stock float PLAYER_MAXS_DUCKED[3] = {16.0, 16.0, 54.0}; @@ -1001,3 +1003,58 @@ stock int GOKZGetClientFromGameMovementAddress(Address addr, int offsetCGameMove Address playerAddr = view_as
(LoadFromAddress(view_as
(view_as(addr) + offsetCGameMovement_player), NumberType_Int32)); return GOKZGetEntityFromAddress(playerAddr); } + +/** + * Gets the nearest point in the oriented bounding box of an entity to a point. + * + * @param entity Entity index. + * @param origin Point's origin. + * @param result Result point. + */ +stock void CalcNearestPoint(int entity, float origin[3], float result[3]) +{ + float entOrigin[3], entMins[3], entMaxs[3], trueMins[3], trueMaxs[3]; + GetEntPropVector(entity, Prop_Send, "m_vecOrigin", entOrigin); + GetEntPropVector(entity, Prop_Send, "m_vecMaxs", entMaxs); + GetEntPropVector(entity, Prop_Send, "m_vecMins", entMins); + + AddVectors(entOrigin, entMins, trueMins); + AddVectors(entOrigin, entMaxs, trueMaxs); + + for (int i = 0; i < 3; i++) + { + result[i] = FloatClamp(origin[i], trueMins[i], trueMaxs[i]); + } +} + +/** + * Get the shortest distance from P to the (infinite) line through vLineA and vLineB. + * + * @param P Point's origin. + * @param vLineA Origin of the first point of the line. + * @param vLineB Origin of the first point of the line. + * @return The shortest distance from the point to the line. + */ +stock float CalcDistanceToLine(float P[3], float vLineA[3], float vLineB[3]) +{ + float vClosest[3]; + float vDir[3]; + float t; + float delta[3]; + SubtractVectors(vLineB, vLineA, vDir); + float div = GetVectorDotProduct(vDir, vDir); + if (div < EPSILON) + { + t = 0.0; + } + else + { + t = (GetVectorDotProduct(vDir, P) - GetVectorDotProduct(vDir, vLineA)) / div; + } + for (int i = 0; i < 3; i++) + { + vClosest[i] = vLineA[i] + vDir[i]*t; + } + SubtractVectors(P, vClosest, delta); + return GetVectorLength(delta); +} diff --git a/addons/sourcemod/scripting/include/gokz/core.inc b/addons/sourcemod/scripting/include/gokz/core.inc index 0ccf0834..6625abf6 100644 --- a/addons/sourcemod/scripting/include/gokz/core.inc +++ b/addons/sourcemod/scripting/include/gokz/core.inc @@ -79,6 +79,7 @@ enum Option: Option_ErrorSounds, Option_VirtualButtonIndicators, Option_TimerButtonZoneType, + Option_ButtonThroughPlayers, OPTION_COUNT }; @@ -139,6 +140,13 @@ enum TIMERBUTTONZONETYPE_COUNT }; +enum +{ + ButtonThroughPlayers_Disabled = 0, + ButtonThroughPlayers_Enabled, + BUTTONTHROUGHPLAYERS_COUNT +} + enum { ModeCVar_Accelerate = 0, @@ -347,7 +355,8 @@ stock char gC_CoreOptionNames[OPTION_COUNT][] = "GOKZ - Teleport Sounds", "GOKZ - Error Sounds", "GOKZ - VB Indicators", - "GOKZ - Timer Button Zone Type" + "GOKZ - Timer Button Zone Type", + "GOKZ - Button Through Players" }; stock char gC_CoreOptionDescriptions[OPTION_COUNT][] = @@ -359,7 +368,8 @@ stock char gC_CoreOptionDescriptions[OPTION_COUNT][] = "Teleport Sounds - 0 = Disabled, 1 = Enabled", "Error Sounds - 0 = Disabled, 1 = Enabled", "Virtual Button Indicators - 0 = Disabled, 1 = Enabled", - "Timer Button Zone Type - 0 = Both buttons, 1 = Only end zone, 2 = Both zones" + "Timer Button Zone Type - 0 = Both buttons, 1 = Only end zone, 2 = Both zones", + "Button Through Players - 0 = Disabled, 1 = Enabled" }; stock char gC_CoreOptionPhrases[OPTION_COUNT][] = @@ -371,7 +381,8 @@ stock char gC_CoreOptionPhrases[OPTION_COUNT][] = "Options Menu - Teleport Sounds", "Options Menu - Error Sounds", "Options Menu - Virtual Button Indicators", - "Options Menu - Timer Button Zone Type" + "Options Menu - Timer Button Zone Type", + "Options Menu - Button Through Players" }; stock char gC_TimerButtonZoneTypePhrases[TIMERBUTTONZONETYPE_COUNT][] = @@ -390,7 +401,8 @@ stock int gI_CoreOptionCounts[OPTION_COUNT] = TELEPORTSOUNDS_COUNT, ERRORSOUNDS_COUNT, VIRTUALBUTTONINDICATORS_COUNT, - TIMERBUTTONZONETYPE_COUNT + TIMERBUTTONZONETYPE_COUNT, + BUTTONTHROUGHPLAYERS_COUNT }; stock int gI_CoreOptionDefaults[OPTION_COUNT] = @@ -402,7 +414,8 @@ stock int gI_CoreOptionDefaults[OPTION_COUNT] = TeleportSounds_Disabled, ErrorSounds_Enabled, VirtualButtonIndicators_Disabled, - TimerButtonZoneType_BothButtons + TimerButtonZoneType_BothButtons, + ButtonThroughPlayers_Enabled }; stock char gC_ModeCVars[MODECVAR_COUNT][] = diff --git a/addons/sourcemod/translations/gokz-core.phrases.txt b/addons/sourcemod/translations/gokz-core.phrases.txt index 149a42f7..e006b3e7 100644 --- a/addons/sourcemod/translations/gokz-core.phrases.txt +++ b/addons/sourcemod/translations/gokz-core.phrases.txt @@ -289,7 +289,10 @@ { "en" "Timer button/zone type" } - + "Options Menu - Button Through Players" + { + "en" "Press button through players" + } // =====[ OPTION PHRASES ]===== "Timer Button Zone Type - Both Buttons" diff --git a/cfg/sourcemod/gokz/options_menu_sorting.cfg b/cfg/sourcemod/gokz/options_menu_sorting.cfg index 655b8cb8..c6e23a8c 100644 --- a/cfg/sourcemod/gokz/options_menu_sorting.cfg +++ b/cfg/sourcemod/gokz/options_menu_sorting.cfg @@ -20,6 +20,7 @@ "item" "GOKZ DB - Auto Load Timer Setup" "item" "GOKZ - Timer Button Zone Type" "item" "GOKZ QT - Map Sounds" + "item" "GOKZ - Button Through Players" } "HUD" { From 17349dc2c21fe23321e3be6ede8b3265053d336a Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Tue, 29 Nov 2022 16:34:44 +0100 Subject: [PATCH 10/47] Fix TP bot having broken interpolation after teleporting --- .../scripting/gokz-replays/playback.sp | 63 +++++++++++-------- 1 file changed, 37 insertions(+), 26 deletions(-) diff --git a/addons/sourcemod/scripting/gokz-replays/playback.sp b/addons/sourcemod/scripting/gokz-replays/playback.sp index 4acd0802..341916ed 100644 --- a/addons/sourcemod/scripting/gokz-replays/playback.sp +++ b/addons/sourcemod/scripting/gokz-replays/playback.sp @@ -52,6 +52,7 @@ static bool hitBhop[RP_MAX_BOTS]; static bool hitPerf[RP_MAX_BOTS]; static bool botJumped[RP_MAX_BOTS]; static bool botIsTakeoff[RP_MAX_BOTS]; +static bool botJustTeleported[RP_MAX_BOTS]; static float botLandingSpeed[RP_MAX_BOTS]; @@ -948,12 +949,17 @@ void PlaybackVersion2(int client, int bot, int &buttons) EmitSoundToClientSpectators(client, gC_ModeEndSounds[GOKZ_GetCoreOption(client, Option_Mode)]); } - // Set velocity to travel from current origin to recorded origin - float currentOrigin[3], velocity[3]; - Movement_GetOrigin(client, currentOrigin); - MakeVectorFromPoints(currentOrigin, currentTickData.origin, velocity); - ScaleVector(velocity, 1.0 / GetTickInterval()); - TeleportEntity(client, NULL_VECTOR, currentTickData.angles, velocity); + TeleportEntity(client, NULL_VECTOR, currentTickData.angles, currentTickData.velocity); + // TeleportEntity does not set the absolute origin and velocity so we need to do it + // to prevent inaccurate eye position interpolation. + SetEntPropVector(client, Prop_Data, "m_vecVelocity", currentTickData.velocity); + SetEntPropVector(client, Prop_Data, "m_vecAbsVelocity", currentTickData.velocity); + + SetEntPropVector(client, Prop_Data, "m_vecAbsOrigin", currentTickData.origin); + SetEntPropVector(client, Prop_Data, "m_vecOrigin", currentTickData.origin); + + SetEntPropFloat(client, Prop_Send, "m_angEyeAngles[0]", currentTickData.angles[0]); + SetEntPropFloat(client, Prop_Send, "m_angEyeAngles[1]", currentTickData.angles[1]); botSpeed[bot] = GetVectorHorizontalLength(currentTickData.velocity); @@ -1014,32 +1020,36 @@ void PlaybackVersion2(int client, int bot, int &buttons) // Set the bot's MoveType MoveType replayMoveType = view_as(currentTickData.flags & RP_MOVETYPE_MASK); botMoveType[bot] = replayMoveType; - if (Movement_GetSpeed(client) > SPEED_NORMAL * 2) - { - Movement_SetMovetype(client, MOVETYPE_NOCLIP); - } - else if (replayMoveType == MOVETYPE_WALK && currentTickData.flags & RP_FL_ONGROUND) + if (replayMoveType == MOVETYPE_WALK) { - botPaused[bot] = false; - SetEntityFlags(client, entityFlags | FL_ONGROUND); Movement_SetMovetype(client, MOVETYPE_WALK); - // The bot is on the ground, so there must be a ground entity attributed to the bot. - int groundEnt = GetEntPropEnt(client, Prop_Send, "m_hGroundEntity"); - if (groundEnt == -1) + if (currentTickData.flags & RP_FL_ONGROUND) { - float endPosition[3], mins[3], maxs[3]; - GetEntPropVector(client, Prop_Send, "m_vecMaxs", maxs); - GetEntPropVector(client, Prop_Send, "m_vecMins", mins); - endPosition = currentTickData.origin; - endPosition[2] -= 2.0; - TR_TraceHullFilter(currentTickData.origin, endPosition, mins, maxs, MASK_PLAYERSOLID, TraceEntityFilterPlayers); - // This should always hit. - if (TR_DidHit()) + botPaused[bot] = false; + SetEntityFlags(client, entityFlags | FL_ONGROUND); + // The bot is on the ground, so there must be a ground entity attributed to the bot. + int groundEnt = GetEntPropEnt(client, Prop_Send, "m_hGroundEntity"); + if (groundEnt == -1 && botJustTeleported[bot]) { - groundEnt = TR_GetEntityIndex(); - SetEntPropEnt(client, Prop_Data, "m_hGroundEntity", groundEnt); + SetEntPropFloat(client, Prop_Send, "m_flFallVelocity", 0.0); + float endPosition[3], mins[3], maxs[3]; + GetEntPropVector(client, Prop_Send, "m_vecMaxs", maxs); + GetEntPropVector(client, Prop_Send, "m_vecMins", mins); + endPosition = currentTickData.origin; + endPosition[2] -= 2.0; + TR_TraceHullFilter(currentTickData.origin, endPosition, mins, maxs, MASK_PLAYERSOLID, TraceEntityFilterPlayers); + // This should always hit. + if (TR_DidHit()) + { + groundEnt = TR_GetEntityIndex(); + SetEntPropEnt(client, Prop_Data, "m_hGroundEntity", groundEnt); + } } } + else + { + botJustTeleported[bot] = false; + } } else if (replayMoveType == MOVETYPE_LADDER) { @@ -1059,6 +1069,7 @@ void PlaybackVersion2(int client, int bot, int &buttons) // Set some variables if (currentTickData.flags & RP_TELEPORT_TICK) { + botJustTeleported[bot] = true; botCurrentTeleport[bot]++; Movement_SetMovetype(client, MOVETYPE_NOCLIP); } From a2ec23f957533235549d1670abd70e2a9ed0005d Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Thu, 1 Dec 2022 01:44:13 +0100 Subject: [PATCH 11/47] Fix missing bot sounds in playback --- .../sourcemod/gamedata/gokz-replays.games.txt | 20 ++ addons/sourcemod/scripting/gokz-replays.sp | 20 +- .../scripting/gokz-replays/playback.sp | 173 ++++++++++++------ .../scripting/include/gokz/replays.inc | 2 + 4 files changed, 153 insertions(+), 62 deletions(-) diff --git a/addons/sourcemod/gamedata/gokz-replays.games.txt b/addons/sourcemod/gamedata/gokz-replays.games.txt index ed559119..fb3dabfc 100644 --- a/addons/sourcemod/gamedata/gokz-replays.games.txt +++ b/addons/sourcemod/gamedata/gokz-replays.games.txt @@ -2,6 +2,13 @@ { "csgo" { + "Addresses" + { + "SetDuckUntilOnGround" + { + "signature" "SetDuckUntilOnGroundSig" + } + } "Functions" { "CCSGameRules::TeamFull" @@ -26,6 +33,19 @@ "windows" "\x55\x8B\xEC\x56\x8B\xF1\xE8\x2A\x2A\x2A\x2A\x8B\x45\x08\x83\xE8\x01" "linux" "\x55\x89\xE5\x83\xEC\x18\x89\x5D\xF8\x8B\x5D\x08\x89\x75\xFC\x8B\x75\x0C\x89\x1C\x24\xE8\x2A\x2A\x2A\x2A\x83\xFE\x02" } + "SetDuckUntilOnGroundSig" + { + "windows" "\xC6\x80\x6C\x2C\x00\x00\x01\x8B\x06" + "linux" "\xC6\x80\x84\x2C\x00\x00\x01\x8B\x03" + } + } + "Offsets" + { + "SetDuckUntilOnGroundOffset" + { + "windows" "6" + "linux" "6" + } } } } diff --git a/addons/sourcemod/scripting/gokz-replays.sp b/addons/sourcemod/scripting/gokz-replays.sp index ce47b798..721aad71 100644 --- a/addons/sourcemod/scripting/gokz-replays.sp +++ b/addons/sourcemod/scripting/gokz-replays.sp @@ -42,6 +42,7 @@ int gI_CurrentMapFileSize; bool gB_HideNameChange; bool gB_NubRecordMissed[MAXPLAYERS + 1]; ArrayList g_ReplayInfoCache; +Address gA_SetDuckUntilOnGroundAddr; DynamicDetour gH_DHooks_TeamFull; #include "gokz-replays/commands.sp" @@ -105,7 +106,11 @@ public void OnLibraryRemoved(const char[] name) gB_GOKZLocalDB = gB_GOKZLocalDB && !StrEqual(name, "gokz-localdb"); } - +public void OnPluginEnd() +{ + // Restore bot auto duck behavior. + StoreToAddress(gA_SetDuckUntilOnGroundAddr, 1, NumberType_Int8); +} // =====[ OTHER EVENTS ]===== @@ -204,12 +209,17 @@ public void OnClientDisconnect(int client) public Action OnPlayerRunCmd(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]) { - OnPlayerRunCmd_Playback(client, buttons); - return Plugin_Continue; + if (!IsFakeClient(client)) + { + return Plugin_Continue; + } + OnPlayerRunCmd_Playback(client, buttons, vel, angles); + return Plugin_Changed; } public void OnPlayerRunCmdPost(int client, int buttons, int impulse, const float vel[3], const float angles[3], int weapon, int subtype, int cmdnum, int tickcount, int seed, const int mouse[2]) { + OnPlayerRunCmdPost_Playback(client); OnPlayerRunCmdPost_Recording(client, buttons, tickcount, vel, mouse); OnPlayerRunCmdPost_ReplayControls(client, cmdnum); } @@ -300,6 +310,10 @@ static void HookEvents() { SetFailState("Failed to enable detour on CCSGameRules::TeamFull"); } + + // Remove bot auto duck behavior. + gA_SetDuckUntilOnGroundAddr = gameData.GetAddress("SetDuckUntilOnGround") + view_as
(gameData.GetOffset("SetDuckUntilOnGroundOffset")); + StoreToAddress(gA_SetDuckUntilOnGroundAddr, 0, NumberType_Int8); delete gameData; } diff --git a/addons/sourcemod/scripting/gokz-replays/playback.sp b/addons/sourcemod/scripting/gokz-replays/playback.sp index 027da73d..6bd4a1dd 100644 --- a/addons/sourcemod/scripting/gokz-replays/playback.sp +++ b/addons/sourcemod/scripting/gokz-replays/playback.sp @@ -302,7 +302,7 @@ void OnClientDisconnect_Playback(int client) } } -void OnPlayerRunCmd_Playback(int client, int &buttons) +void OnPlayerRunCmd_Playback(int client, int &buttons, float vel[3], float angles[3]) { if (!IsFakeClient(client)) { @@ -320,7 +320,24 @@ void OnPlayerRunCmd_Playback(int client, int &buttons) switch (botReplayVersion[bot]) { case 1: PlaybackVersion1(client, bot, buttons); - case 2: PlaybackVersion2(client, bot, buttons); + case 2: PlaybackVersion2(client, bot, buttons, vel, angles); + } + break; + } +} + +void OnPlayerRunCmdPost_Playback(int client) +{ + for (int bot; bot < RP_MAX_BOTS; bot++) + { + // Check if not the bot we're looking for + if (!botInGame[bot] || botClient[bot] != client || !botDataLoaded[bot]) + { + continue; + } + if (botReplayVersion[bot] == 2) + { + PlaybackVersion2Post(client, bot); } break; } @@ -338,7 +355,6 @@ void GOKZ_OnOptionsLoaded_Playback(int client) } } } - // =====[ PRIVATE ]===== // Returns false if there was a problem loading the playback e.g. doesn't exist @@ -883,7 +899,7 @@ static void PlaybackVersion1(int client, int bot, int &buttons) playbackTick[bot]++; } } -void PlaybackVersion2(int client, int bot, int &buttons) +void PlaybackVersion2(int client, int bot, int &buttons, float vel[3], float angles[3]) { int size = playbackTickData[bot].Length; ReplayTickData prevTickData; @@ -961,22 +977,20 @@ void PlaybackVersion2(int client, int bot, int &buttons) { EmitSoundToClientSpectators(client, gC_ModeEndSounds[GOKZ_GetCoreOption(client, Option_Mode)]); } - - TeleportEntity(client, NULL_VECTOR, currentTickData.angles, currentTickData.velocity); + // We use the previous position/velocity data to recreate sounds accurately. + // This might not be necessary as we already did do this in OnPlayerRunCmdPost of last tick, + // but we do it again just in case the values don't match up somehow (eg. collision with moving objects?) + TeleportEntity(client, NULL_VECTOR, prevTickData.angles, prevTickData.velocity); // TeleportEntity does not set the absolute origin and velocity so we need to do it // to prevent inaccurate eye position interpolation. - SetEntPropVector(client, Prop_Data, "m_vecVelocity", currentTickData.velocity); - SetEntPropVector(client, Prop_Data, "m_vecAbsVelocity", currentTickData.velocity); + SetEntPropVector(client, Prop_Data, "m_vecVelocity", prevTickData.velocity); + SetEntPropVector(client, Prop_Data, "m_vecAbsVelocity", prevTickData.velocity); - SetEntPropVector(client, Prop_Data, "m_vecAbsOrigin", currentTickData.origin); - SetEntPropVector(client, Prop_Data, "m_vecOrigin", currentTickData.origin); + SetEntPropVector(client, Prop_Data, "m_vecAbsOrigin", prevTickData.origin); + SetEntPropVector(client, Prop_Data, "m_vecOrigin", prevTickData.origin); - SetEntPropFloat(client, Prop_Send, "m_angEyeAngles[0]", currentTickData.angles[0]); - SetEntPropFloat(client, Prop_Send, "m_angEyeAngles[1]", currentTickData.angles[1]); - - botSpeed[bot] = GetVectorHorizontalLength(currentTickData.velocity); - // Set buttons + // Set buttons and potential inputs. int newButtons; if (currentTickData.flags & RP_IN_ATTACK) { @@ -994,29 +1008,35 @@ void PlaybackVersion2(int client, int bot, int &buttons) { newButtons |= IN_DUCK; } + // Few assumptions here because the replay doesn't track them: Player doesn't use +klook or +strafe. + // If the assumptions are wrong we will just end up with wrong sound prediction, no big deal. if (currentTickData.flags & RP_IN_FORWARD) { newButtons |= IN_FORWARD; + vel[0] += RP_PLAYER_ACCELSPEED; } if (currentTickData.flags & RP_IN_BACK) { newButtons |= IN_BACK; - } - if (currentTickData.flags & RP_IN_LEFT) - { - newButtons |= IN_LEFT; - } - if (currentTickData.flags & RP_IN_RIGHT) - { - newButtons |= IN_RIGHT; + vel[0] -= RP_PLAYER_ACCELSPEED; } if (currentTickData.flags & RP_IN_MOVELEFT) { newButtons |= IN_MOVELEFT; + vel[1] -= RP_PLAYER_ACCELSPEED; } if (currentTickData.flags & RP_IN_MOVERIGHT) { newButtons |= IN_MOVERIGHT; + vel[1] += RP_PLAYER_ACCELSPEED; + } + if (currentTickData.flags & RP_IN_LEFT) + { + newButtons |= IN_LEFT; + } + if (currentTickData.flags & RP_IN_RIGHT) + { + newButtons |= IN_RIGHT; } if (currentTickData.flags & RP_IN_RELOAD) { @@ -1028,41 +1048,15 @@ void PlaybackVersion2(int client, int bot, int &buttons) } buttons = newButtons; botButtons[bot] = buttons; + // The angles might be wrong if the player teleports, but this should only affect sound prediction. + angles = currentTickData.angles; - int entityFlags = GetEntityFlags(client); // Set the bot's MoveType - MoveType replayMoveType = view_as(currentTickData.flags & RP_MOVETYPE_MASK); + MoveType replayMoveType = view_as(prevTickData.flags & RP_MOVETYPE_MASK); botMoveType[bot] = replayMoveType; if (replayMoveType == MOVETYPE_WALK) { Movement_SetMovetype(client, MOVETYPE_WALK); - if (currentTickData.flags & RP_FL_ONGROUND) - { - botPaused[bot] = false; - SetEntityFlags(client, entityFlags | FL_ONGROUND); - // The bot is on the ground, so there must be a ground entity attributed to the bot. - int groundEnt = GetEntPropEnt(client, Prop_Send, "m_hGroundEntity"); - if (groundEnt == -1 && botJustTeleported[bot]) - { - SetEntPropFloat(client, Prop_Send, "m_flFallVelocity", 0.0); - float endPosition[3], mins[3], maxs[3]; - GetEntPropVector(client, Prop_Send, "m_vecMaxs", maxs); - GetEntPropVector(client, Prop_Send, "m_vecMins", mins); - endPosition = currentTickData.origin; - endPosition[2] -= 2.0; - TR_TraceHullFilter(currentTickData.origin, endPosition, mins, maxs, MASK_PLAYERSOLID, TraceEntityFilterPlayers); - // This should always hit. - if (TR_DidHit()) - { - groundEnt = TR_GetEntityIndex(); - SetEntPropEnt(client, Prop_Data, "m_hGroundEntity", groundEnt); - } - } - } - else - { - botJustTeleported[bot] = false; - } } else if (replayMoveType == MOVETYPE_LADDER) { @@ -1073,18 +1067,11 @@ void PlaybackVersion2(int client, int bot, int &buttons) { Movement_SetMovetype(client, MOVETYPE_NOCLIP); } - - if (currentTickData.flags & RP_UNDER_WATER) - { - SetEntityFlags(client, entityFlags | FL_INWATER); - } - // Set some variables if (currentTickData.flags & RP_TELEPORT_TICK) { botJustTeleported[bot] = true; botCurrentTeleport[bot]++; - Movement_SetMovetype(client, MOVETYPE_NOCLIP); } if (currentTickData.flags & RP_TAKEOFF_TICK) @@ -1151,7 +1138,75 @@ void PlaybackVersion2(int client, int bot, int &buttons) PrintToServer("=============================================================="); } #endif + } +} + +void PlaybackVersion2Post(int client, int bot) +{ + if (botPlaybackPaused[bot]) + { + return; + } + int size = playbackTickData[bot].Length; + if (playbackTick[bot] != 0 && playbackTick[bot] != (size - 1)) + { + ReplayTickData currentTickData; + ReplayTickData prevTickData; + playbackTickData[bot].GetArray(playbackTick[bot], currentTickData); + playbackTickData[bot].GetArray(IntMax(playbackTick[bot] - 1, 0), prevTickData); + + // TeleportEntity does not set the absolute origin and velocity so we need to do it + // to prevent inaccurate eye position interpolation. + SetEntPropVector(client, Prop_Data, "m_vecVelocity", currentTickData.velocity); + SetEntPropVector(client, Prop_Data, "m_vecAbsVelocity", currentTickData.velocity); + + SetEntPropVector(client, Prop_Data, "m_vecAbsOrigin", currentTickData.origin); + SetEntPropVector(client, Prop_Data, "m_vecOrigin", currentTickData.origin); + + SetEntPropFloat(client, Prop_Send, "m_angEyeAngles[0]", currentTickData.angles[0]); + SetEntPropFloat(client, Prop_Send, "m_angEyeAngles[1]", currentTickData.angles[1]); + + MoveType replayMoveType = view_as(currentTickData.flags & RP_MOVETYPE_MASK); + botMoveType[bot] = replayMoveType; + int entityFlags = GetEntityFlags(client); + if (replayMoveType == MOVETYPE_WALK) + { + if (currentTickData.flags & RP_FL_ONGROUND) + { + SetEntityFlags(client, entityFlags | FL_ONGROUND); + botPaused[bot] = false; + // The bot is on the ground, so there must be a ground entity attributed to the bot. + int groundEnt = GetEntPropEnt(client, Prop_Send, "m_hGroundEntity"); + if (groundEnt == -1 && botJustTeleported[bot]) + { + SetEntPropFloat(client, Prop_Send, "m_flFallVelocity", 0.0); + float endPosition[3], mins[3], maxs[3]; + GetEntPropVector(client, Prop_Send, "m_vecMaxs", maxs); + GetEntPropVector(client, Prop_Send, "m_vecMins", mins); + endPosition = currentTickData.origin; + endPosition[2] -= 2.0; + TR_TraceHullFilter(currentTickData.origin, endPosition, mins, maxs, MASK_PLAYERSOLID, TraceEntityFilterPlayers); + // This should always hit. + if (TR_DidHit()) + { + groundEnt = TR_GetEntityIndex(); + SetEntPropEnt(client, Prop_Data, "m_hGroundEntity", groundEnt); + } + } + } + else + { + botJustTeleported[bot] = false; + } + } + + if (currentTickData.flags & RP_UNDER_WATER) + { + SetEntityFlags(client, entityFlags | FL_INWATER); + } + + botSpeed[bot] = GetVectorHorizontalLength(currentTickData.velocity); playbackTick[bot]++; } } diff --git a/addons/sourcemod/scripting/include/gokz/replays.inc b/addons/sourcemod/scripting/include/gokz/replays.inc index 9f601033..cde212c6 100644 --- a/addons/sourcemod/scripting/include/gokz/replays.inc +++ b/addons/sourcemod/scripting/include/gokz/replays.inc @@ -154,6 +154,8 @@ enum struct ReplayTickData #define RP_MAX_BHOP_GROUND_TICKS 5 #define RP_SKIP_TIME 10 // 10 seconds #define RP_MAX_DURATION 6451200 // 14 hours on 128 tick +#define RP_JUMP_STEP_SOUND_THRESHOLD 140.0 +#define RP_PLAYER_ACCELSPEED 450.0 #define RP_MOVETYPE_MASK (0xF) #define RP_IN_ATTACK (1 << 4) From 66441ba58590ad9615c88b483a0176ae35e11aef Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Fri, 9 Dec 2022 17:15:36 +0100 Subject: [PATCH 12/47] Rewrite bot autoduck behavior --- .../sourcemod/gamedata/gokz-replays.games.txt | 16 ++++++------- addons/sourcemod/scripting/gokz-replays.sp | 23 +++++++++++++++---- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/addons/sourcemod/gamedata/gokz-replays.games.txt b/addons/sourcemod/gamedata/gokz-replays.games.txt index fb3dabfc..f4b7f80b 100644 --- a/addons/sourcemod/gamedata/gokz-replays.games.txt +++ b/addons/sourcemod/gamedata/gokz-replays.games.txt @@ -4,9 +4,9 @@ { "Addresses" { - "SetDuckUntilOnGround" + "BotDuck" { - "signature" "SetDuckUntilOnGroundSig" + "signature" "BotDuckSig" } } "Functions" @@ -33,18 +33,18 @@ "windows" "\x55\x8B\xEC\x56\x8B\xF1\xE8\x2A\x2A\x2A\x2A\x8B\x45\x08\x83\xE8\x01" "linux" "\x55\x89\xE5\x83\xEC\x18\x89\x5D\xF8\x8B\x5D\x08\x89\x75\xFC\x8B\x75\x0C\x89\x1C\x24\xE8\x2A\x2A\x2A\x2A\x83\xFE\x02" } - "SetDuckUntilOnGroundSig" + "BotDuckSig" { - "windows" "\xC6\x80\x6C\x2C\x00\x00\x01\x8B\x06" - "linux" "\xC6\x80\x84\x2C\x00\x00\x01\x8B\x03" + "windows" "\x8B\x86\x54\x0E\x00\x00\x8B\xCE" + "linux" "\x8B\x83\x54\x0E\x00\x00\xC6\x80\x84\x2C\x00\x00\x01\x8B\x03" } } "Offsets" { - "SetDuckUntilOnGroundOffset" + "BotDuckPatchLength" { - "windows" "6" - "linux" "6" + "windows" "23" + "linux" "24" } } } diff --git a/addons/sourcemod/scripting/gokz-replays.sp b/addons/sourcemod/scripting/gokz-replays.sp index 721aad71..71b3fbef 100644 --- a/addons/sourcemod/scripting/gokz-replays.sp +++ b/addons/sourcemod/scripting/gokz-replays.sp @@ -42,7 +42,10 @@ int gI_CurrentMapFileSize; bool gB_HideNameChange; bool gB_NubRecordMissed[MAXPLAYERS + 1]; ArrayList g_ReplayInfoCache; -Address gA_SetDuckUntilOnGroundAddr; +Address gA_BotDuckAddr; +int gI_BotDuckPatchRestore[24]; // Size of patched section in gamedata +int gI_BotDuckPatchLength; + DynamicDetour gH_DHooks_TeamFull; #include "gokz-replays/commands.sp" @@ -109,7 +112,14 @@ public void OnLibraryRemoved(const char[] name) public void OnPluginEnd() { // Restore bot auto duck behavior. - StoreToAddress(gA_SetDuckUntilOnGroundAddr, 1, NumberType_Int8); + if (gA_BotDuckAddr == Address_Null) + { + return; + } + for (int i = 0; i < gI_BotDuckPatchLength; i++) + { + StoreToAddress(gA_BotDuckAddr + view_as
(i), gI_BotDuckPatchRestore[i], NumberType_Int8); + } } // =====[ OTHER EVENTS ]===== @@ -312,8 +322,13 @@ static void HookEvents() } // Remove bot auto duck behavior. - gA_SetDuckUntilOnGroundAddr = gameData.GetAddress("SetDuckUntilOnGround") + view_as
(gameData.GetOffset("SetDuckUntilOnGroundOffset")); - StoreToAddress(gA_SetDuckUntilOnGroundAddr, 0, NumberType_Int8); + gA_BotDuckAddr = gameData.GetAddress("BotDuck"); + gI_BotDuckPatchLength = gameData.GetOffset("BotDuckPatchLength"); + for (int i = 0; i < gI_BotDuckPatchLength; i++) + { + gI_BotDuckPatchRestore[i] = LoadFromAddress(gA_BotDuckAddr + view_as
(i), NumberType_Int8); + StoreToAddress(gA_BotDuckAddr + view_as
(i), 0x90, NumberType_Int8); + } delete gameData; } From 6129474b2fa172b99edfa63bf4d08de7973a63ad Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Sun, 1 Jan 2023 14:39:35 +0100 Subject: [PATCH 13/47] Use clientside footsteps --- cfg/sourcemod/gokz/gokz.cfg | 134 ++++++++++++++++++------------------ 1 file changed, 67 insertions(+), 67 deletions(-) diff --git a/cfg/sourcemod/gokz/gokz.cfg b/cfg/sourcemod/gokz/gokz.cfg index a0ed7bc8..efd2d9f1 100644 --- a/cfg/sourcemod/gokz/gokz.cfg +++ b/cfg/sourcemod/gokz/gokz.cfg @@ -1,67 +1,67 @@ -// GOKZ Server Config - -// This is executed at the start of each map -// These settings are all but required for GOKZ -// You should not need to edit this file - -// No fun allowed -sv_holiday_mode 0 -sv_party_mode 0 - -// Remove restriction that affects some maps -sv_clamp_unsafe_velocities 0 - -// Respawn on death -mp_respawn_on_death_ct 1 -mp_respawn_on_death_t 1 -mp_respawn_immunitytime -1 -sv_spec_post_death_additional_time 1 - -// Hide money -mp_playercashawards 0 -mp_teamcashawards 0 - -// Stop dropping guns -mp_death_drop_c4 0 -mp_death_drop_defuser 0 -mp_death_drop_grenade 0 -mp_death_drop_gun 0 -mp_drop_knife_enable 0 -mp_weapons_allow_map_placed 0 -mp_t_default_secondary "" -mp_ct_default_secondary "" -mp_disconnect_kills_players 0 - -// No limits on joining teams -mp_autoteambalance 0 -mp_limitteams 0 -mp_spectators_max 64 - -// Performance -sv_occlude_players 0 - -// General -sv_pure 0 -bot_quota 0 -sv_allow_votes 0 -sv_infinite_ammo 2 -mp_free_armor 2 -mp_buytime 0 -mp_freezetime 0 -mp_do_warmup_period 0 -mp_ignore_round_win_conditions 1 -mp_match_end_changelevel 1 -sv_ignoregrenaderadio 1 -sv_disable_radar 1 -mp_footsteps_serverside 1 -sv_mincmdrate 128 -sv_minupdaterate 128 -mp_warmuptime_all_players_connected 0 -// Fix bots not spawning -mp_randomspawn 1 - -// Team picking -mp_force_pick_time 60 - -// Restart round to ensure settings (e.g. mp_weapons_allow_map_placed) are applied -mp_restartgame 1 +// GOKZ Server Config + +// This is executed at the start of each map +// These settings are all but required for GOKZ +// You should not need to edit this file + +// No fun allowed +sv_holiday_mode 0 +sv_party_mode 0 + +// Remove restriction that affects some maps +sv_clamp_unsafe_velocities 0 + +// Respawn on death +mp_respawn_on_death_ct 1 +mp_respawn_on_death_t 1 +mp_respawn_immunitytime -1 +sv_spec_post_death_additional_time 1 + +// Hide money +mp_playercashawards 0 +mp_teamcashawards 0 + +// Stop dropping guns +mp_death_drop_c4 0 +mp_death_drop_defuser 0 +mp_death_drop_grenade 0 +mp_death_drop_gun 0 +mp_drop_knife_enable 0 +mp_weapons_allow_map_placed 0 +mp_t_default_secondary "" +mp_ct_default_secondary "" +mp_disconnect_kills_players 0 + +// No limits on joining teams +mp_autoteambalance 0 +mp_limitteams 0 +mp_spectators_max 64 + +// Performance +sv_occlude_players 0 + +// General +sv_pure 0 +bot_quota 0 +sv_allow_votes 0 +sv_infinite_ammo 2 +mp_free_armor 2 +mp_buytime 0 +mp_freezetime 0 +mp_do_warmup_period 0 +mp_ignore_round_win_conditions 1 +mp_match_end_changelevel 1 +sv_ignoregrenaderadio 1 +sv_disable_radar 1 +mp_footsteps_serverside 0 +sv_mincmdrate 128 +sv_minupdaterate 128 +mp_warmuptime_all_players_connected 0 +// Fix bots not spawning +mp_randomspawn 1 + +// Team picking +mp_force_pick_time 60 + +// Restart round to ensure settings (e.g. mp_weapons_allow_map_placed) are applied +mp_restartgame 1 From 29b8e159e66e22d37579e4603687cb0951b1826c Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Sun, 1 Jan 2023 14:41:44 +0100 Subject: [PATCH 14/47] Fix line ending...? --- cfg/sourcemod/gokz/gokz.cfg | 134 ++++++++++++++++++------------------ 1 file changed, 67 insertions(+), 67 deletions(-) diff --git a/cfg/sourcemod/gokz/gokz.cfg b/cfg/sourcemod/gokz/gokz.cfg index efd2d9f1..b1c68c71 100644 --- a/cfg/sourcemod/gokz/gokz.cfg +++ b/cfg/sourcemod/gokz/gokz.cfg @@ -1,67 +1,67 @@ -// GOKZ Server Config - -// This is executed at the start of each map -// These settings are all but required for GOKZ -// You should not need to edit this file - -// No fun allowed -sv_holiday_mode 0 -sv_party_mode 0 - -// Remove restriction that affects some maps -sv_clamp_unsafe_velocities 0 - -// Respawn on death -mp_respawn_on_death_ct 1 -mp_respawn_on_death_t 1 -mp_respawn_immunitytime -1 -sv_spec_post_death_additional_time 1 - -// Hide money -mp_playercashawards 0 -mp_teamcashawards 0 - -// Stop dropping guns -mp_death_drop_c4 0 -mp_death_drop_defuser 0 -mp_death_drop_grenade 0 -mp_death_drop_gun 0 -mp_drop_knife_enable 0 -mp_weapons_allow_map_placed 0 -mp_t_default_secondary "" -mp_ct_default_secondary "" -mp_disconnect_kills_players 0 - -// No limits on joining teams -mp_autoteambalance 0 -mp_limitteams 0 -mp_spectators_max 64 - -// Performance -sv_occlude_players 0 - -// General -sv_pure 0 -bot_quota 0 -sv_allow_votes 0 -sv_infinite_ammo 2 -mp_free_armor 2 -mp_buytime 0 -mp_freezetime 0 -mp_do_warmup_period 0 -mp_ignore_round_win_conditions 1 -mp_match_end_changelevel 1 -sv_ignoregrenaderadio 1 -sv_disable_radar 1 -mp_footsteps_serverside 0 -sv_mincmdrate 128 -sv_minupdaterate 128 -mp_warmuptime_all_players_connected 0 -// Fix bots not spawning -mp_randomspawn 1 - -// Team picking -mp_force_pick_time 60 - -// Restart round to ensure settings (e.g. mp_weapons_allow_map_placed) are applied -mp_restartgame 1 +// GOKZ Server Config + +// This is executed at the start of each map +// These settings are all but required for GOKZ +// You should not need to edit this file + +// No fun allowed +sv_holiday_mode 0 +sv_party_mode 0 + +// Remove restriction that affects some maps +sv_clamp_unsafe_velocities 0 + +// Respawn on death +mp_respawn_on_death_ct 1 +mp_respawn_on_death_t 1 +mp_respawn_immunitytime -1 +sv_spec_post_death_additional_time 1 + +// Hide money +mp_playercashawards 0 +mp_teamcashawards 0 + +// Stop dropping guns +mp_death_drop_c4 0 +mp_death_drop_defuser 0 +mp_death_drop_grenade 0 +mp_death_drop_gun 0 +mp_drop_knife_enable 0 +mp_weapons_allow_map_placed 0 +mp_t_default_secondary "" +mp_ct_default_secondary "" +mp_disconnect_kills_players 0 + +// No limits on joining teams +mp_autoteambalance 0 +mp_limitteams 0 +mp_spectators_max 64 + +// Performance +sv_occlude_players 0 + +// General +sv_pure 0 +bot_quota 0 +sv_allow_votes 0 +sv_infinite_ammo 2 +mp_free_armor 2 +mp_buytime 0 +mp_freezetime 0 +mp_do_warmup_period 0 +mp_ignore_round_win_conditions 1 +mp_match_end_changelevel 1 +sv_ignoregrenaderadio 1 +sv_disable_radar 1 +mp_footsteps_serverside 0 +sv_mincmdrate 128 +sv_minupdaterate 128 +mp_warmuptime_all_players_connected 0 +// Fix bots not spawning +mp_randomspawn 1 + +// Team picking +mp_force_pick_time 60 + +// Restart round to ensure settings (e.g. mp_weapons_allow_map_placed) are applied +mp_restartgame 1 From 4c4cfb3388d9d6e87d206619d0d5dff847bc36cc Mon Sep 17 00:00:00 2001 From: "zer0.k" <61156310+zer0k-z@users.noreply.github.com> Date: Sat, 7 Jan 2023 12:30:35 +0100 Subject: [PATCH 15/47] Update gokz-tpanglefix.games.txt --- addons/sourcemod/gamedata/gokz-tpanglefix.games.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/sourcemod/gamedata/gokz-tpanglefix.games.txt b/addons/sourcemod/gamedata/gokz-tpanglefix.games.txt index eabef7bd..ecc5f692 100644 --- a/addons/sourcemod/gamedata/gokz-tpanglefix.games.txt +++ b/addons/sourcemod/gamedata/gokz-tpanglefix.games.txt @@ -36,8 +36,8 @@ } "ClientIndexOffset" { - "linux" "116" - "windows" "116" + "linux" "112" + "windows" "112" } } From 945a3aa062d983c4388821f265cbd1026bd21977 Mon Sep 17 00:00:00 2001 From: "zer0.k" <61156310+zer0k-z@users.noreply.github.com> Date: Sat, 7 Jan 2023 17:33:42 +0100 Subject: [PATCH 16/47] Update gokz-tpanglefix.games.txt --- addons/sourcemod/gamedata/gokz-tpanglefix.games.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/sourcemod/gamedata/gokz-tpanglefix.games.txt b/addons/sourcemod/gamedata/gokz-tpanglefix.games.txt index ecc5f692..f9febd54 100644 --- a/addons/sourcemod/gamedata/gokz-tpanglefix.games.txt +++ b/addons/sourcemod/gamedata/gokz-tpanglefix.games.txt @@ -36,7 +36,7 @@ } "ClientIndexOffset" { - "linux" "112" + "linux" "116" "windows" "112" } } From c98555ec8b14186165e05ca40902e645c9fe7efd Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Mon, 9 Jan 2023 01:03:16 +0100 Subject: [PATCH 17/47] Rewrite gokz-quiet structure --- addons/sourcemod/scripting/gokz-quiet.sp | 462 +----------------- .../scripting/gokz-quiet/hideplayers.sp | 305 ++++++++++++ .../sourcemod/scripting/gokz-quiet/options.sp | 162 ++++++ .../scripting/gokz-quiet/soundscape.sp | 32 ++ .../scripting/include/gokz/quiet.inc | 11 +- .../translations/gokz-quiet.phrases.txt | 5 +- cfg/sourcemod/gokz/options_menu_sorting.cfg | 129 ++--- 7 files changed, 582 insertions(+), 524 deletions(-) create mode 100644 addons/sourcemod/scripting/gokz-quiet/hideplayers.sp create mode 100644 addons/sourcemod/scripting/gokz-quiet/options.sp create mode 100644 addons/sourcemod/scripting/gokz-quiet/soundscape.sp diff --git a/addons/sourcemod/scripting/gokz-quiet.sp b/addons/sourcemod/scripting/gokz-quiet.sp index b7ddc51f..8ce77026 100644 --- a/addons/sourcemod/scripting/gokz-quiet.sp +++ b/addons/sourcemod/scripting/gokz-quiet.sp @@ -26,16 +26,12 @@ public Plugin myinfo = #define UPDATER_URL GOKZ_UPDATER_BASE_URL..."gokz-quiet.txt" -// Search for "coopcementplant.missionselect_blank" id with sv_soundscape_printdebuginfo. -#define BLANK_SOUNDSCAPEINDEX 482 #define EFFECT_IMPACT 8 #define EFFECT_KNIFESLASH 2 -TopMenu gTM_Options; -TopMenuObject gTMO_CatGeneral; -TopMenuObject gTMO_ItemsQuiet[QTOPTION_COUNT]; - -int gI_CurrentSoundscapeIndex[MAXPLAYERS + 1] = {BLANK_SOUNDSCAPEINDEX, ...}; +#include "gokz-quiet/soundscape.sp" +#include "gokz-quiet/hideplayers.sp" +#include "gokz-quiet/options.sp" // =====[ PLUGIN EVENTS ]===== @@ -47,23 +43,12 @@ public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max public void OnPluginStart() { - AddNormalSoundHook(Hook_NormalSound); - AddTempEntHook("Shotgun Shot", Hook_ShotgunShot); - AddTempEntHook("EffectDispatch", Hook_EffectDispatch); - HookUserMessage(GetUserMessageId("WeaponSound"), Hook_WeaponSound, true); + OnPluginStart_HidePlayers(); LoadTranslations("gokz-common.phrases"); LoadTranslations("gokz-quiet.phrases"); RegisterCommands(); - - for (int client = 1; client <= MaxClients; client++) - { - if (IsValidClient(client)) - { - OnJoinTeam_HidePlayers(client, GetClientTeam(client)); - } - } } public void OnAllPluginsLoaded() @@ -112,23 +97,10 @@ public void OnPlayerRunCmdPost(int client, int buttons, int impulse, const float return; } - int soundscapeIndex = GetEntProp(client, Prop_Data, "soundscapeIndex"); - if (GOKZ_GetOption(client, gC_QTOptionNames[QTOption_MapSounds]) == MapSounds_Disabled) - { - if (soundscapeIndex != BLANK_SOUNDSCAPEINDEX) - { - gI_CurrentSoundscapeIndex[client] = soundscapeIndex; - } - SetEntProp(client, Prop_Data, "soundscapeIndex", BLANK_SOUNDSCAPEINDEX); - } - else - { - gI_CurrentSoundscapeIndex[client] = soundscapeIndex; - } + OnPlayerRunCmdPost_Soundscape(client); } - // =====[ OTHER EVENTS ]===== public void GOKZ_OnOptionsMenuReady(TopMenu topMenu) @@ -146,276 +118,11 @@ public void GOKZ_OnOptionChanged(int client, const char[] option, any newValue) } } - - -// =====[ HIDE PLAYERS ]===== - -void OnJoinTeam_HidePlayers(int client, int team) -{ - // Make sure client is only ever hooked once - SDKUnhook(client, SDKHook_SetTransmit, OnSetTransmitClient); - - if (team == CS_TEAM_T || team == CS_TEAM_CT) - { - SDKHook(client, SDKHook_SetTransmit, OnSetTransmitClient); - } -} - -public Action OnSetTransmitClient(int entity, int client) -{ - if (GOKZ_GetOption(client, gC_QTOptionNames[QTOption_ShowPlayers]) == ShowPlayers_Disabled - && entity != client - && entity != GetObserverTarget(client)) - { - return Plugin_Handled; - } - return Plugin_Continue; -} - -public Action Hook_WeaponSound(UserMsg msg_id, Protobuf msg, const int[] players, int playersNum, bool reliable, bool init) -{ - int newClients[MAXPLAYERS], newTotal = 0; - int entidx = msg.ReadInt("entidx"); - for (int i = 0; i < playersNum; i++) - { - int client = players[i]; - if (GOKZ_GetOption(client, gC_QTOptionNames[QTOption_ShowPlayers]) == ShowPlayers_Enabled - || entidx == client - || entidx == GetObserverTarget(client)) - { - newClients[newTotal] = client; - newTotal++; - } - } - - // Nothing's changed, let the engine handle it. - if (newTotal == playersNum) - { - return Plugin_Continue; - } - - // Only way to modify the recipient list is to RequestFrame and create our own user message. - char path[PLATFORM_MAX_PATH]; - msg.ReadString("sound", path, sizeof(path)); - int flags = USERMSG_BLOCKHOOKS; - if (reliable) - { - flags |= USERMSG_RELIABLE; - } - if (init) - { - flags |= USERMSG_INITMSG; - } - - DataPack dp = new DataPack(); - dp.WriteCell(msg_id); - dp.WriteCell(newTotal); - dp.WriteCellArray(newClients, newTotal); - dp.WriteCell(flags); - dp.WriteCell(entidx); - dp.WriteFloat(msg.ReadFloat("origin_x")); - dp.WriteFloat(msg.ReadFloat("origin_y")); - dp.WriteFloat(msg.ReadFloat("origin_z")); - dp.WriteString(path); - dp.WriteFloat(msg.ReadFloat("timestamp")); - - RequestFrame(RequestFrame_WeaponSound, dp); - return Plugin_Handled; -} - -public void RequestFrame_WeaponSound(DataPack dp) -{ - dp.Reset(); - - UserMsg msg_id = dp.ReadCell(); - int newTotal = dp.ReadCell(); - int newClients[MAXPLAYERS]; - dp.ReadCellArray(newClients, newTotal); - int flags = dp.ReadCell(); - - Protobuf newMsg = view_as(StartMessageEx(msg_id, newClients, newTotal, flags)); - - newMsg.AddInt("entidx", dp.ReadCell()); - newMsg.AddFloat("origin_x", dp.ReadFloat()); - newMsg.AddFloat("origin_y", dp.ReadFloat()); - newMsg.AddFloat("origin_z", dp.ReadFloat()); - char path[PLATFORM_MAX_PATH]; - dp.ReadString(path, sizeof(path)); - newMsg.AddString("sound", path); - newMsg.AddFloat("timestamp", dp.ReadFloat()); - - EndMessage(); - - delete dp; -} - -public Action Hook_NormalSound(int clients[MAXPLAYERS], int& numClients, char sample[PLATFORM_MAX_PATH], int& entity, int& channel, float& volume, int& level, int& pitch, int& flags, char soundEntry[PLATFORM_MAX_PATH], int& seed) -{ - if (StrContains(sample, "Player.EquipArmor") != -1 || StrContains(sample, "BaseCombatCharacter.AmmoPickup") != -1) - { - // When the sound is emitted, the owner of these entities are not set yet. - // Hence we cannot do the entity parent stuff below. - // In that case, we just straight up block armor and ammo pickup sounds. - return Plugin_Stop; - } - int ent = entity; - while (ent > MAXPLAYERS) - { - // Block some gun and knife sounds by trying to find its parent entity. - ent = GetEntPropEnt(ent, Prop_Send, "moveparent"); - if (ent < MAXPLAYERS) - { - break; - } - else if (ent == -1) - { - return Plugin_Continue; - } - } - int numNewClients = 0; - for (int i = 0; i < numClients; i++) - { - int client = clients[i]; - if (GOKZ_GetOption(client, gC_QTOptionNames[QTOption_ShowPlayers]) == ShowPlayers_Enabled - || ent == client - || ent == GetObserverTarget(client)) - { - clients[numNewClients] = client; - numNewClients++; - } - } - - if (numNewClients != numClients) - { - numClients = numNewClients; - return Plugin_Changed; - } - - return Plugin_Continue; -} - -public Action Hook_ShotgunShot(const char[] te_name, const int[] players, int numClients, float delay) +public void GOKZ_OnOptionsMenuCreated(TopMenu topMenu) { - int newClients[MAXPLAYERS], newTotal = 0; - for (int i = 0; i < numClients; i++) - { - int client = players[i]; - if (GOKZ_GetOption(client, gC_QTOptionNames[QTOption_ShowPlayers]) == ShowPlayers_Enabled - || TE_ReadNum("m_iPlayer") + 1 == GetObserverTarget(client)) - { - newClients[newTotal] = client; - newTotal++; - } - } - - // Noone wants the sound - if (newTotal == 0) - { - return Plugin_Stop; - } - - // Nothing's changed, let the engine handle it. - if (newTotal == numClients) - { - return Plugin_Continue; - } - - float origin[3]; - TE_ReadVector("m_vecOrigin", origin); - - float angles[2]; - angles[0] = TE_ReadFloat("m_vecAngles[0]"); - angles[1] = TE_ReadFloat("m_vecAngles[1]"); - - int weapon = TE_ReadNum("m_weapon"); - int mode = TE_ReadNum("m_iMode"); - int seed = TE_ReadNum("m_iSeed"); - int player = TE_ReadNum("m_iPlayer"); - float inaccuracy = TE_ReadFloat("m_fInaccuracy"); - float recoilIndex = TE_ReadFloat("m_flRecoilIndex"); - float spread = TE_ReadFloat("m_fSpread"); - int itemIdx = TE_ReadNum("m_nItemDefIndex"); - int soundType = TE_ReadNum("m_iSoundType"); - - TE_Start("Shotgun Shot"); - TE_WriteVector("m_vecOrigin", origin); - TE_WriteFloat("m_vecAngles[0]", angles[0]); - TE_WriteFloat("m_vecAngles[1]", angles[1]); - TE_WriteNum("m_weapon", weapon); - TE_WriteNum("m_iMode", mode); - TE_WriteNum("m_iSeed", seed); - TE_WriteNum("m_iPlayer", player); - TE_WriteFloat("m_fInaccuracy", inaccuracy); - TE_WriteFloat("m_flRecoilIndex", recoilIndex); - TE_WriteFloat("m_fSpread", spread); - TE_WriteNum("m_nItemDefIndex", itemIdx); - TE_WriteNum("m_iSoundType", soundType); - - // Send the TE and stop the engine from processing its own. - TE_Send(newClients, newTotal, delay); - return Plugin_Stop; + OnOptionsMenuCreated_OptionsMenu(topMenu); } -public Action Hook_EffectDispatch(const char[] te_name, const int[] players, int numClients, float delay) -{ - // Block bullet impact effects. - int effIndex = TE_ReadNum("m_iEffectName"); - if (effIndex != EFFECT_IMPACT && effIndex != EFFECT_KNIFESLASH) - { - return Plugin_Continue; - } - int newClients[MAXPLAYERS], newTotal = 0; - for (int i = 0; i < numClients; i++) - { - int client = players[i]; - if (GOKZ_GetOption(client, gC_QTOptionNames[QTOption_ShowPlayers]) == ShowPlayers_Enabled) - { - newClients[newTotal] = client; - newTotal++; - } - } - // Noone wants the sound - if (newTotal == 0) - { - return Plugin_Stop; - } - - // Nothing's changed, let the engine handle it. - if (newTotal == numClients) - { - return Plugin_Continue; - } - float origin[3], start[3]; - origin[0] = TE_ReadFloat("m_vOrigin.x"); - origin[1] = TE_ReadFloat("m_vOrigin.y"); - origin[2] = TE_ReadFloat("m_vOrigin.z"); - start[0] = TE_ReadFloat("m_vStart.x"); - start[1] = TE_ReadFloat("m_vStart.y"); - start[2] = TE_ReadFloat("m_vStart.z"); - int flags = TE_ReadNum("m_fFlags"); - float scale = TE_ReadFloat("m_flScale"); - int surfaceProp = TE_ReadNum("m_nSurfaceProp"); - int damageType = TE_ReadNum("m_nDamageType"); - int entindex = TE_ReadNum("entindex"); - int positionsAreRelativeToEntity = TE_ReadNum("m_bPositionsAreRelativeToEntity"); - - TE_Start("EffectDispatch"); - TE_WriteNum("m_iEffectName", effIndex); - TE_WriteFloatArray("m_vOrigin.x", origin, 3); - TE_WriteFloatArray("m_vStart.x", start, 3); - TE_WriteFloat("m_flScale", scale); - TE_WriteNum("m_nSurfaceProp", surfaceProp); - TE_WriteNum("m_nDamageType", damageType); - TE_WriteNum("entindex", entindex); - TE_WriteNum("m_bPositionsAreRelativeToEntity", positionsAreRelativeToEntity); - TE_WriteNum("m_fFlags", flags); - - // Send the TE and stop the engine from processing its own. - TE_Send(newClients, newTotal, delay); - return Plugin_Stop; -} - - // =====[ STOP SOUNDS ]===== void StopSounds(int client) @@ -425,148 +132,6 @@ void StopSounds(int client) } - -// =====[ OPTIONS ]===== - -void OnOptionsMenuReady_Options() -{ - RegisterOptions(); -} - -void OnOptionChanged_Options(int client, QTOption option, any newValue) -{ - if (option == QTOption_MapSounds && newValue == MapSounds_Enabled) - { - if (gI_CurrentSoundscapeIndex[client] != BLANK_SOUNDSCAPEINDEX) - { - SetEntProp(client, Prop_Data, "soundscapeIndex", gI_CurrentSoundscapeIndex[client]); - } - } - PrintOptionChangeMessage(client, option, newValue); -} - -void PrintOptionChangeMessage(int client, QTOption option, any newValue) -{ - switch (option) - { - case QTOption_ShowPlayers: - { - switch (newValue) - { - case ShowPlayers_Disabled: - { - GOKZ_PrintToChat(client, true, "%t", "Option - Show Players - Disable"); - } - case ShowPlayers_Enabled: - { - GOKZ_PrintToChat(client, true, "%t", "Option - Show Players - Enable"); - } - } - } - case QTOption_MapSounds: - { - switch (newValue) - { - case MapSounds_Disabled: - { - GOKZ_PrintToChat(client, true, "%t", "Option - Map Sounds - Disable"); - } - case MapSounds_Enabled: - { - GOKZ_PrintToChat(client, true, "%t", "Option - Map Sounds - Enable"); - } - } - } - } -} - -void RegisterOptions() -{ - for (QTOption option; option < QTOPTION_COUNT; option++) - { - GOKZ_RegisterOption(gC_QTOptionNames[option], gC_QTOptionDescriptions[option], - OptionType_Int, gI_QTOptionDefaultValues[option], 0, gI_QTOptionCounts[option] - 1); - } -} - - - -// =====[ OPTIONS MENU ]===== - -void OnOptionsMenuReady_OptionsMenu(TopMenu topMenu) -{ - if (gTM_Options == topMenu) - { - return; - } - - gTM_Options = topMenu; - gTMO_CatGeneral = gTM_Options.FindCategory(GENERAL_OPTION_CATEGORY); - - // Add gokz-quiet option items - for (int option = 0; option < view_as(QTOPTION_COUNT); option++) - { - gTMO_ItemsQuiet[option] = gTM_Options.AddItem(gC_QTOptionNames[option], TopMenuHandler_QT, gTMO_CatGeneral); - } -} - - -public void TopMenuHandler_QT(TopMenu topmenu, TopMenuAction action, TopMenuObject topobj_id, int param, char[] buffer, int maxlength) -{ - QTOption option = QTOPTION_INVALID; - for (int i = 0; i < view_as(QTOPTION_COUNT); i++) - { - if (topobj_id == gTMO_ItemsQuiet[i]) - { - option = view_as(i); - break; - } - } - - if (option == QTOPTION_INVALID) - { - return; - } - - if (action == TopMenuAction_DisplayOption) - { - switch (option) - { - case QTOption_ShowPlayers: - { - FormatToggleableOptionDisplay(param, QTOption_ShowPlayers, buffer, maxlength); - } - case QTOption_MapSounds: - { - FormatToggleableOptionDisplay(param, QTOption_MapSounds, buffer, maxlength); - } - } - } - else if (action == TopMenuAction_SelectOption) - { - GOKZ_CycleOption(param, gC_QTOptionNames[option]); - gTM_Options.Display(param, TopMenuPosition_LastCategory); - } -} - -void FormatToggleableOptionDisplay(int client, QTOption option, char[] buffer, int maxlength) -{ - if (GOKZ_GetOption(client, gC_QTOptionNames[option]) == MapSounds_Disabled) - { - FormatEx(buffer, maxlength, "%T - %T", - gC_QTOptionPhrases[option], client, - "Options Menu - Disabled", client); - } - else - { - FormatEx(buffer, maxlength, "%T - %T", - gC_QTOptionPhrases[option], client, - "Options Menu - Enabled", client); - } -} - - - // =====[ COMMANDS ]===== void RegisterCommands() @@ -575,19 +140,6 @@ void RegisterCommands() RegConsoleCmd("sm_stopsound", CommandStopSound, "[KZ] Stop all sounds e.g. map soundscapes (music)."); } -public Action CommandToggleShowPlayers(int client, int args) -{ - if (GOKZ_GetOption(client, gC_QTOptionNames[QTOption_ShowPlayers]) == ShowPlayers_Disabled) - { - GOKZ_SetOption(client, gC_QTOptionNames[QTOption_ShowPlayers], ShowPlayers_Enabled); - } - else - { - GOKZ_SetOption(client, gC_QTOptionNames[QTOption_ShowPlayers], ShowPlayers_Disabled); - } - return Plugin_Handled; -} - public Action CommandStopSound(int client, int args) { StopSounds(client); diff --git a/addons/sourcemod/scripting/gokz-quiet/hideplayers.sp b/addons/sourcemod/scripting/gokz-quiet/hideplayers.sp new file mode 100644 index 00000000..fff53894 --- /dev/null +++ b/addons/sourcemod/scripting/gokz-quiet/hideplayers.sp @@ -0,0 +1,305 @@ +/* + Hide sounds and effects from other players. +*/ + +void OnPluginStart_HidePlayers() +{ + AddNormalSoundHook(Hook_NormalSound); + AddTempEntHook("Shotgun Shot", Hook_ShotgunShot); + AddTempEntHook("EffectDispatch", Hook_EffectDispatch); + HookUserMessage(GetUserMessageId("WeaponSound"), Hook_WeaponSound, true); + + // Lateload support + for (int client = 1; client <= MaxClients; client++) + { + if (IsValidClient(client)) + { + OnJoinTeam_HidePlayers(client, GetClientTeam(client)); + } + } +} + +void OnJoinTeam_HidePlayers(int client, int team) +{ + // Make sure client is only ever hooked once + SDKUnhook(client, SDKHook_SetTransmit, OnSetTransmitClient); + + if (team == CS_TEAM_T || team == CS_TEAM_CT) + { + SDKHook(client, SDKHook_SetTransmit, OnSetTransmitClient); + } +} + +Action CommandToggleShowPlayers(int client, int args) +{ + if (GOKZ_GetOption(client, gC_QTOptionNames[QTOption_ShowPlayers]) == ShowPlayers_Disabled) + { + GOKZ_SetOption(client, gC_QTOptionNames[QTOption_ShowPlayers], ShowPlayers_Enabled); + } + else + { + GOKZ_SetOption(client, gC_QTOptionNames[QTOption_ShowPlayers], ShowPlayers_Disabled); + } + return Plugin_Handled; +} + +// =====[ PRIVATE ]===== + +// Hide most of the other players' actions. This function is expensive. +static Action OnSetTransmitClient(int entity, int client) +{ + if (GOKZ_GetOption(client, gC_QTOptionNames[QTOption_ShowPlayers]) == ShowPlayers_Disabled + && entity != client + && entity != GetObserverTarget(client)) + { + return Plugin_Handled; + } + return Plugin_Continue; +} + +// Hide reload sounds. Required if other players were visible at one point during the gameplay. +static Action Hook_WeaponSound(UserMsg msg_id, Protobuf msg, const int[] players, int playersNum, bool reliable, bool init) +{ + int newClients[MAXPLAYERS], newTotal = 0; + int entidx = msg.ReadInt("entidx"); + for (int i = 0; i < playersNum; i++) + { + int client = players[i]; + if (GOKZ_GetOption(client, gC_QTOptionNames[QTOption_ShowPlayers]) == ShowPlayers_Enabled + || entidx == client + || entidx == GetObserverTarget(client)) + { + newClients[newTotal] = client; + newTotal++; + } + } + + // Nothing's changed, let the engine handle it. + if (newTotal == playersNum) + { + return Plugin_Continue; + } + + // Only way to modify the recipient list is to RequestFrame and create our own user message. + char path[PLATFORM_MAX_PATH]; + msg.ReadString("sound", path, sizeof(path)); + int flags = USERMSG_BLOCKHOOKS; + if (reliable) + { + flags |= USERMSG_RELIABLE; + } + if (init) + { + flags |= USERMSG_INITMSG; + } + + DataPack dp = new DataPack(); + dp.WriteCell(msg_id); + dp.WriteCell(newTotal); + dp.WriteCellArray(newClients, newTotal); + dp.WriteCell(flags); + dp.WriteCell(entidx); + dp.WriteFloat(msg.ReadFloat("origin_x")); + dp.WriteFloat(msg.ReadFloat("origin_y")); + dp.WriteFloat(msg.ReadFloat("origin_z")); + dp.WriteString(path); + dp.WriteFloat(msg.ReadFloat("timestamp")); + + RequestFrame(RequestFrame_WeaponSound, dp); + return Plugin_Handled; +} + +static void RequestFrame_WeaponSound(DataPack dp) +{ + dp.Reset(); + + UserMsg msg_id = dp.ReadCell(); + int newTotal = dp.ReadCell(); + int newClients[MAXPLAYERS]; + dp.ReadCellArray(newClients, newTotal); + int flags = dp.ReadCell(); + + Protobuf newMsg = view_as(StartMessageEx(msg_id, newClients, newTotal, flags)); + + newMsg.AddInt("entidx", dp.ReadCell()); + newMsg.AddFloat("origin_x", dp.ReadFloat()); + newMsg.AddFloat("origin_y", dp.ReadFloat()); + newMsg.AddFloat("origin_z", dp.ReadFloat()); + char path[PLATFORM_MAX_PATH]; + dp.ReadString(path, sizeof(path)); + newMsg.AddString("sound", path); + newMsg.AddFloat("timestamp", dp.ReadFloat()); + + EndMessage(); + + delete dp; +} + +// Hide various sounds that don't get blocked by SetTransmit hook. +static Action Hook_NormalSound(int clients[MAXPLAYERS], int& numClients, char sample[PLATFORM_MAX_PATH], int& entity, int& channel, float& volume, int& level, int& pitch, int& flags, char soundEntry[PLATFORM_MAX_PATH], int& seed) +{ + if (StrContains(sample, "Player.EquipArmor") != -1 || StrContains(sample, "BaseCombatCharacter.AmmoPickup") != -1) + { + // When the sound is emitted, the owner of these entities are not set yet. + // Hence we cannot do the entity parent stuff below. + // In that case, we just straight up block armor and ammo pickup sounds. + return Plugin_Stop; + } + int ent = entity; + while (ent > MAXPLAYERS) + { + // Block some gun and knife sounds by trying to find its parent entity. + ent = GetEntPropEnt(ent, Prop_Send, "moveparent"); + if (ent < MAXPLAYERS) + { + break; + } + else if (ent == -1) + { + return Plugin_Continue; + } + } + int numNewClients = 0; + for (int i = 0; i < numClients; i++) + { + int client = clients[i]; + if (GOKZ_GetOption(client, gC_QTOptionNames[QTOption_ShowPlayers]) == ShowPlayers_Enabled + || ent == client + || ent == GetObserverTarget(client)) + { + clients[numNewClients] = client; + numNewClients++; + } + } + + if (numNewClients != numClients) + { + numClients = numNewClients; + return Plugin_Changed; + } + + return Plugin_Continue; +} + +// Hide firing sounds. +static Action Hook_ShotgunShot(const char[] te_name, const int[] players, int numClients, float delay) +{ + int newClients[MAXPLAYERS], newTotal = 0; + for (int i = 0; i < numClients; i++) + { + int client = players[i]; + if (GOKZ_GetOption(client, gC_QTOptionNames[QTOption_ShowPlayers]) == ShowPlayers_Enabled + || TE_ReadNum("m_iPlayer") + 1 == GetObserverTarget(client)) + { + newClients[newTotal] = client; + newTotal++; + } + } + + // Noone wants the sound + if (newTotal == 0) + { + return Plugin_Stop; + } + + // Nothing's changed, let the engine handle it. + if (newTotal == numClients) + { + return Plugin_Continue; + } + + float origin[3]; + TE_ReadVector("m_vecOrigin", origin); + + float angles[2]; + angles[0] = TE_ReadFloat("m_vecAngles[0]"); + angles[1] = TE_ReadFloat("m_vecAngles[1]"); + + int weapon = TE_ReadNum("m_weapon"); + int mode = TE_ReadNum("m_iMode"); + int seed = TE_ReadNum("m_iSeed"); + int player = TE_ReadNum("m_iPlayer"); + float inaccuracy = TE_ReadFloat("m_fInaccuracy"); + float recoilIndex = TE_ReadFloat("m_flRecoilIndex"); + float spread = TE_ReadFloat("m_fSpread"); + int itemIdx = TE_ReadNum("m_nItemDefIndex"); + int soundType = TE_ReadNum("m_iSoundType"); + + TE_Start("Shotgun Shot"); + TE_WriteVector("m_vecOrigin", origin); + TE_WriteFloat("m_vecAngles[0]", angles[0]); + TE_WriteFloat("m_vecAngles[1]", angles[1]); + TE_WriteNum("m_weapon", weapon); + TE_WriteNum("m_iMode", mode); + TE_WriteNum("m_iSeed", seed); + TE_WriteNum("m_iPlayer", player); + TE_WriteFloat("m_fInaccuracy", inaccuracy); + TE_WriteFloat("m_flRecoilIndex", recoilIndex); + TE_WriteFloat("m_fSpread", spread); + TE_WriteNum("m_nItemDefIndex", itemIdx); + TE_WriteNum("m_iSoundType", soundType); + + // Send the TE and stop the engine from processing its own. + TE_Send(newClients, newTotal, delay); + return Plugin_Stop; +} + +// Hide knife and blood effect caused by other players. +static Action Hook_EffectDispatch(const char[] te_name, const int[] players, int numClients, float delay) +{ + // Block bullet impact effects. + int effIndex = TE_ReadNum("m_iEffectName"); + if (effIndex != EFFECT_IMPACT && effIndex != EFFECT_KNIFESLASH) + { + return Plugin_Continue; + } + int newClients[MAXPLAYERS], newTotal = 0; + for (int i = 0; i < numClients; i++) + { + int client = players[i]; + if (GOKZ_GetOption(client, gC_QTOptionNames[QTOption_ShowPlayers]) == ShowPlayers_Enabled) + { + newClients[newTotal] = client; + newTotal++; + } + } + // Noone wants the sound + if (newTotal == 0) + { + return Plugin_Stop; + } + + // Nothing's changed, let the engine handle it. + if (newTotal == numClients) + { + return Plugin_Continue; + } + float origin[3], start[3]; + origin[0] = TE_ReadFloat("m_vOrigin.x"); + origin[1] = TE_ReadFloat("m_vOrigin.y"); + origin[2] = TE_ReadFloat("m_vOrigin.z"); + start[0] = TE_ReadFloat("m_vStart.x"); + start[1] = TE_ReadFloat("m_vStart.y"); + start[2] = TE_ReadFloat("m_vStart.z"); + int flags = TE_ReadNum("m_fFlags"); + float scale = TE_ReadFloat("m_flScale"); + int surfaceProp = TE_ReadNum("m_nSurfaceProp"); + int damageType = TE_ReadNum("m_nDamageType"); + int entindex = TE_ReadNum("entindex"); + int positionsAreRelativeToEntity = TE_ReadNum("m_bPositionsAreRelativeToEntity"); + + TE_Start("EffectDispatch"); + TE_WriteNum("m_iEffectName", effIndex); + TE_WriteFloatArray("m_vOrigin.x", origin, 3); + TE_WriteFloatArray("m_vStart.x", start, 3); + TE_WriteFloat("m_flScale", scale); + TE_WriteNum("m_nSurfaceProp", surfaceProp); + TE_WriteNum("m_nDamageType", damageType); + TE_WriteNum("entindex", entindex); + TE_WriteNum("m_bPositionsAreRelativeToEntity", positionsAreRelativeToEntity); + TE_WriteNum("m_fFlags", flags); + + // Send the TE and stop the engine from processing its own. + TE_Send(newClients, newTotal, delay); + return Plugin_Stop; +} diff --git a/addons/sourcemod/scripting/gokz-quiet/options.sp b/addons/sourcemod/scripting/gokz-quiet/options.sp new file mode 100644 index 00000000..cd97eff4 --- /dev/null +++ b/addons/sourcemod/scripting/gokz-quiet/options.sp @@ -0,0 +1,162 @@ +// =====[ OPTIONS ]===== + +void OnOptionsMenuReady_Options() +{ + RegisterOptions(); +} + +void RegisterOptions() +{ + for (QTOption option; option < QTOPTION_COUNT; option++) + { + GOKZ_RegisterOption(gC_QTOptionNames[option], gC_QTOptionDescriptions[option], + OptionType_Int, gI_QTOptionDefaultValues[option], 0, gI_QTOptionCounts[option] - 1); + } +} + +void OnOptionChanged_Options(int client, QTOption option, any newValue) +{ + if (option == QTOption_MapSounds && newValue == MapSounds_Enabled) + { + EnableSoundscape(client); + } + PrintOptionChangeMessage(client, option, newValue); +} + +void PrintOptionChangeMessage(int client, QTOption option, any newValue) +{ + switch (option) + { + case QTOption_ShowPlayers: + { + switch (newValue) + { + case ShowPlayers_Disabled: + { + GOKZ_PrintToChat(client, true, "%t", "Option - Show Players - Disable"); + } + case ShowPlayers_Enabled: + { + GOKZ_PrintToChat(client, true, "%t", "Option - Show Players - Enable"); + } + } + } + case QTOption_MapSounds: + { + switch (newValue) + { + case MapSounds_Disabled: + { + GOKZ_PrintToChat(client, true, "%t", "Option - Map Sounds - Disable"); + } + case MapSounds_Enabled: + { + GOKZ_PrintToChat(client, true, "%t", "Option - Map Sounds - Enable"); + } + } + } + } +} + +// =====[ OPTIONS MENU ]===== + +TopMenu gTM_Options; +TopMenuObject gTMO_CatQuiet; +TopMenuObject gTMO_ItemsQuiet[QTOPTION_COUNT]; + +void OnOptionsMenuCreated_OptionsMenu(TopMenu topMenu) +{ + if (gTM_Options == topMenu && gTMO_CatQuiet != INVALID_TOPMENUOBJECT) + { + return; + } + + gTMO_CatQuiet = topMenu.AddCategory(QUIET_OPTION_CATEGORY, TopMenuHandler_Categories); +} + +void OnOptionsMenuReady_OptionsMenu(TopMenu topMenu) +{ + // Make sure category exists + if (gTMO_CatQuiet == INVALID_TOPMENUOBJECT) + { + GOKZ_OnOptionsMenuCreated(topMenu); + } + + if (gTM_Options == topMenu) + { + return; + } + + gTM_Options = topMenu; + + // Add gokz-profile option items + for (int option = 0; option < view_as(QTOPTION_COUNT); option++) + { + gTMO_ItemsQuiet[option] = gTM_Options.AddItem(gC_QTOptionNames[option], TopMenuHandler_QT, gTMO_CatQuiet); + } +} + +public void TopMenuHandler_Categories(TopMenu topmenu, TopMenuAction action, TopMenuObject topobj_id, int param, char[] buffer, int maxlength) +{ + if (action == TopMenuAction_DisplayOption || action == TopMenuAction_DisplayTitle) + { + if (topobj_id == gTMO_CatQuiet) + { + Format(buffer, maxlength, "%T", "Options Menu - Quiet", param); + } + } +} + +public void TopMenuHandler_QT(TopMenu topmenu, TopMenuAction action, TopMenuObject topobj_id, int param, char[] buffer, int maxlength) +{ + QTOption option = QTOPTION_INVALID; + for (int i = 0; i < view_as(QTOPTION_COUNT); i++) + { + if (topobj_id == gTMO_ItemsQuiet[i]) + { + option = view_as(i); + break; + } + } + + if (option == QTOPTION_INVALID) + { + return; + } + + if (action == TopMenuAction_DisplayOption) + { + switch (option) + { + case QTOption_ShowPlayers: + { + FormatToggleableOptionDisplay(param, QTOption_ShowPlayers, buffer, maxlength); + } + case QTOption_MapSounds: + { + FormatToggleableOptionDisplay(param, QTOption_MapSounds, buffer, maxlength); + } + } + } + else if (action == TopMenuAction_SelectOption) + { + GOKZ_CycleOption(param, gC_QTOptionNames[option]); + gTM_Options.Display(param, TopMenuPosition_LastCategory); + } +} + +void FormatToggleableOptionDisplay(int client, QTOption option, char[] buffer, int maxlength) +{ + if (GOKZ_GetOption(client, gC_QTOptionNames[option]) == 0) + { + FormatEx(buffer, maxlength, "%T - %T", + gC_QTOptionPhrases[option], client, + "Options Menu - Disabled", client); + } + else + { + FormatEx(buffer, maxlength, "%T - %T", + gC_QTOptionPhrases[option], client, + "Options Menu - Enabled", client); + } +} \ No newline at end of file diff --git a/addons/sourcemod/scripting/gokz-quiet/soundscape.sp b/addons/sourcemod/scripting/gokz-quiet/soundscape.sp new file mode 100644 index 00000000..dbe10c97 --- /dev/null +++ b/addons/sourcemod/scripting/gokz-quiet/soundscape.sp @@ -0,0 +1,32 @@ +/* + Toggle soundscapes. +*/ + +// Search for "coopcementplant.missionselect_blank" id with sv_soundscape_printdebuginfo. +#define BLANK_SOUNDSCAPEINDEX 482 +int gI_CurrentSoundscapeIndex[MAXPLAYERS + 1] = {BLANK_SOUNDSCAPEINDEX, ...}; + +void EnableSoundscape(int client) +{ + if (gI_CurrentSoundscapeIndex[client] != BLANK_SOUNDSCAPEINDEX) + { + SetEntProp(client, Prop_Data, "soundscapeIndex", gI_CurrentSoundscapeIndex[client]); + } +} + +void OnPlayerRunCmdPost_Soundscape(int client) +{ + int soundscapeIndex = GetEntProp(client, Prop_Data, "soundscapeIndex"); + if (GOKZ_GetOption(client, gC_QTOptionNames[QTOption_MapSounds]) == MapSounds_Disabled) + { + if (soundscapeIndex != BLANK_SOUNDSCAPEINDEX) + { + gI_CurrentSoundscapeIndex[client] = soundscapeIndex; + } + SetEntProp(client, Prop_Data, "soundscapeIndex", BLANK_SOUNDSCAPEINDEX); + } + else + { + gI_CurrentSoundscapeIndex[client] = soundscapeIndex; + } +} \ No newline at end of file diff --git a/addons/sourcemod/scripting/include/gokz/quiet.inc b/addons/sourcemod/scripting/include/gokz/quiet.inc index c6d8d3a1..4d7ea565 100644 --- a/addons/sourcemod/scripting/include/gokz/quiet.inc +++ b/addons/sourcemod/scripting/include/gokz/quiet.inc @@ -23,15 +23,15 @@ enum QTOption: enum { - ShowPlayers_Disabled = 0, - ShowPlayers_Enabled, + ShowPlayers_Disabled = 0, + ShowPlayers_Enabled, SHOWPLAYERS_COUNT }; enum { - MapSounds_Enabled = 0, - MapSounds_Disabled, + MapSounds_Disabled = 0, + MapSounds_Enabled, MAPSOUNDS_COUNT }; @@ -48,7 +48,7 @@ stock char gC_QTOptionNames[QTOPTION_COUNT][] = stock char gC_QTOptionDescriptions[QTOPTION_COUNT][] = { "Visibility of Other Players - 0 = Disabled, 1 = Enabled", - "Play Ambient Map Sounds/Music - 0 = Enabled, 1 = Disabled" + "Play Ambient Map Sounds/Music - 0 = Disabled, 1 = Enabled" }; stock int gI_QTOptionDefaultValues[QTOPTION_COUNT] = @@ -70,6 +70,7 @@ stock char gC_QTOptionPhrases[QTOPTION_COUNT][] = }; +#define QUIET_OPTION_CATEGORY "Quiet" // =====[ STOCKS ]===== diff --git a/addons/sourcemod/translations/gokz-quiet.phrases.txt b/addons/sourcemod/translations/gokz-quiet.phrases.txt index f16b725a..e1ee3331 100644 --- a/addons/sourcemod/translations/gokz-quiet.phrases.txt +++ b/addons/sourcemod/translations/gokz-quiet.phrases.txt @@ -32,6 +32,10 @@ Phrases // =====[ OPTIONS MENU ]===== + "Options Menu - Quiet" + { + "en" "Quiet" + } "Options Menu - Show Players" { "en" "Show players" @@ -41,6 +45,5 @@ Phrases "Options Menu - Map Sounds" { "en" "Play map sounds" - "ru" "Play map sounds" } } \ No newline at end of file diff --git a/cfg/sourcemod/gokz/options_menu_sorting.cfg b/cfg/sourcemod/gokz/options_menu_sorting.cfg index 655b8cb8..937edf54 100644 --- a/cfg/sourcemod/gokz/options_menu_sorting.cfg +++ b/cfg/sourcemod/gokz/options_menu_sorting.cfg @@ -1,63 +1,66 @@ -// Controls the order that options appear in the options menu -// It is not recommended to edit this file unless you are adding options - -"Menu" -{ - "General" - { - "item" "GOKZ - Mode" - "item" "GOKZ - Checkpoint Messages" - "item" "GOKZ - Checkpoint Sounds" - "item" "GOKZ - Teleport Sounds" - "item" "GOKZ - Error Sounds" - "item" "GOKZ QT - Show Players" - "item" "GOKZ - Pistol" - "item" "GOKZ JB - Jump Beam Type" - "item" "GOKZ - Auto Restart" - "item" "GOKZ - Tips" - "item" "GOKZ - Slay On End" - "item" "GOKZ - VB Indicators" - "item" "GOKZ DB - Auto Load Timer Setup" - "item" "GOKZ - Timer Button Zone Type" - "item" "GOKZ QT - Map Sounds" - } - "HUD" - { - "item" "GOKZ HUD - Update Rate" - "item" "GOKZ HUD - Teleport Menu" - "item" "GOKZ HUD - Dynamic Menu" - "item" "GOKZ HUD - Centre Panel" - "item" "GOKZ HUD - Timer Text" - "item" "GOKZ HUD - Timer Style" - "item" "GOKZ HUD - Speed Text" - "item" "GOKZ HUD - Dead Strafe" - "item" "GOKZ HUD - Show Keys" - "item" "GOKZ HUD - Show Weapon" - "item" "GOKZ HUD - Show Controls" - "item" "GOKZ HUD - Show Time Type" - } - "Jumpstats" - { - "item" "GOKZ JS - Master Switch" - "item" "GOKZ JS - Chat Report" - "item" "GOKZ JS - Console Report" - "item" "GOKZ JS - Sounds" - "item" "GOKZ JS - Failstats Console" - "item" "GOKZ JS - Failstats Chat" - "item" "GOKZ JS - Jumpstats Always" - "item" "GOKZ JS - Extended Chat Report" - "item" "GOKZ JS - Minimal Chat Broadcast Tier" - "item" "GOKZ JS - Minimal Sound Broadcast Tier" - } - "Paint" - { - "item" "GOKZ Paint - Color" - "item" "GOKZ Paint - Size" - } - "Profile" - { - "item" "GOKZ Profile - Tag Type" - "item" "GOKZ Profile - Show Rank Chat" - "item" "GOKZ Profile - Show Rank Clan" - } -} +// Controls the order that options appear in the options menu +// It is not recommended to edit this file unless you are adding options + +"Menu" +{ + "General" + { + "item" "GOKZ - Mode" + "item" "GOKZ - Checkpoint Messages" + "item" "GOKZ - Checkpoint Sounds" + "item" "GOKZ - Teleport Sounds" + "item" "GOKZ - Error Sounds" + "item" "GOKZ - Pistol" + "item" "GOKZ JB - Jump Beam Type" + "item" "GOKZ - Auto Restart" + "item" "GOKZ - Tips" + "item" "GOKZ - Slay On End" + "item" "GOKZ - VB Indicators" + "item" "GOKZ DB - Auto Load Timer Setup" + "item" "GOKZ - Timer Button Zone Type" + } + "HUD" + { + "item" "GOKZ HUD - Update Rate" + "item" "GOKZ HUD - Teleport Menu" + "item" "GOKZ HUD - Dynamic Menu" + "item" "GOKZ HUD - Centre Panel" + "item" "GOKZ HUD - Timer Text" + "item" "GOKZ HUD - Timer Style" + "item" "GOKZ HUD - Speed Text" + "item" "GOKZ HUD - Dead Strafe" + "item" "GOKZ HUD - Show Keys" + "item" "GOKZ HUD - Show Weapon" + "item" "GOKZ HUD - Show Controls" + "item" "GOKZ HUD - Show Time Type" + } + "Jumpstats" + { + "item" "GOKZ JS - Master Switch" + "item" "GOKZ JS - Chat Report" + "item" "GOKZ JS - Console Report" + "item" "GOKZ JS - Sounds" + "item" "GOKZ JS - Failstats Console" + "item" "GOKZ JS - Failstats Chat" + "item" "GOKZ JS - Jumpstats Always" + "item" "GOKZ JS - Extended Chat Report" + "item" "GOKZ JS - Minimal Chat Broadcast Tier" + "item" "GOKZ JS - Minimal Sound Broadcast Tier" + } + "Paint" + { + "item" "GOKZ Paint - Color" + "item" "GOKZ Paint - Size" + } + "Profile" + { + "item" "GOKZ Profile - Tag Type" + "item" "GOKZ Profile - Show Rank Chat" + "item" "GOKZ Profile - Show Rank Clan" + } + "Quiet" + { + "item" "GOKZ QT - Show Players" + "item" "GOKZ QT - Map Sounds" + } +} From 669e50f51fe62c3e1aca8e751f2c34ae227472bb Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Mon, 9 Jan 2023 01:24:39 +0100 Subject: [PATCH 18/47] Fix line ending (again) --- cfg/sourcemod/gokz/options_menu_sorting.cfg | 132 ++++++++++---------- 1 file changed, 66 insertions(+), 66 deletions(-) diff --git a/cfg/sourcemod/gokz/options_menu_sorting.cfg b/cfg/sourcemod/gokz/options_menu_sorting.cfg index 937edf54..dc7c0182 100644 --- a/cfg/sourcemod/gokz/options_menu_sorting.cfg +++ b/cfg/sourcemod/gokz/options_menu_sorting.cfg @@ -1,66 +1,66 @@ -// Controls the order that options appear in the options menu -// It is not recommended to edit this file unless you are adding options - -"Menu" -{ - "General" - { - "item" "GOKZ - Mode" - "item" "GOKZ - Checkpoint Messages" - "item" "GOKZ - Checkpoint Sounds" - "item" "GOKZ - Teleport Sounds" - "item" "GOKZ - Error Sounds" - "item" "GOKZ - Pistol" - "item" "GOKZ JB - Jump Beam Type" - "item" "GOKZ - Auto Restart" - "item" "GOKZ - Tips" - "item" "GOKZ - Slay On End" - "item" "GOKZ - VB Indicators" - "item" "GOKZ DB - Auto Load Timer Setup" - "item" "GOKZ - Timer Button Zone Type" - } - "HUD" - { - "item" "GOKZ HUD - Update Rate" - "item" "GOKZ HUD - Teleport Menu" - "item" "GOKZ HUD - Dynamic Menu" - "item" "GOKZ HUD - Centre Panel" - "item" "GOKZ HUD - Timer Text" - "item" "GOKZ HUD - Timer Style" - "item" "GOKZ HUD - Speed Text" - "item" "GOKZ HUD - Dead Strafe" - "item" "GOKZ HUD - Show Keys" - "item" "GOKZ HUD - Show Weapon" - "item" "GOKZ HUD - Show Controls" - "item" "GOKZ HUD - Show Time Type" - } - "Jumpstats" - { - "item" "GOKZ JS - Master Switch" - "item" "GOKZ JS - Chat Report" - "item" "GOKZ JS - Console Report" - "item" "GOKZ JS - Sounds" - "item" "GOKZ JS - Failstats Console" - "item" "GOKZ JS - Failstats Chat" - "item" "GOKZ JS - Jumpstats Always" - "item" "GOKZ JS - Extended Chat Report" - "item" "GOKZ JS - Minimal Chat Broadcast Tier" - "item" "GOKZ JS - Minimal Sound Broadcast Tier" - } - "Paint" - { - "item" "GOKZ Paint - Color" - "item" "GOKZ Paint - Size" - } - "Profile" - { - "item" "GOKZ Profile - Tag Type" - "item" "GOKZ Profile - Show Rank Chat" - "item" "GOKZ Profile - Show Rank Clan" - } - "Quiet" - { - "item" "GOKZ QT - Show Players" - "item" "GOKZ QT - Map Sounds" - } -} +// Controls the order that options appear in the options menu +// It is not recommended to edit this file unless you are adding options + +"Menu" +{ + "General" + { + "item" "GOKZ - Mode" + "item" "GOKZ - Checkpoint Messages" + "item" "GOKZ - Checkpoint Sounds" + "item" "GOKZ - Teleport Sounds" + "item" "GOKZ - Error Sounds" + "item" "GOKZ - Pistol" + "item" "GOKZ JB - Jump Beam Type" + "item" "GOKZ - Auto Restart" + "item" "GOKZ - Tips" + "item" "GOKZ - Slay On End" + "item" "GOKZ - VB Indicators" + "item" "GOKZ DB - Auto Load Timer Setup" + "item" "GOKZ - Timer Button Zone Type" + } + "HUD" + { + "item" "GOKZ HUD - Update Rate" + "item" "GOKZ HUD - Teleport Menu" + "item" "GOKZ HUD - Dynamic Menu" + "item" "GOKZ HUD - Centre Panel" + "item" "GOKZ HUD - Timer Text" + "item" "GOKZ HUD - Timer Style" + "item" "GOKZ HUD - Speed Text" + "item" "GOKZ HUD - Dead Strafe" + "item" "GOKZ HUD - Show Keys" + "item" "GOKZ HUD - Show Weapon" + "item" "GOKZ HUD - Show Controls" + "item" "GOKZ HUD - Show Time Type" + } + "Jumpstats" + { + "item" "GOKZ JS - Master Switch" + "item" "GOKZ JS - Chat Report" + "item" "GOKZ JS - Console Report" + "item" "GOKZ JS - Sounds" + "item" "GOKZ JS - Failstats Console" + "item" "GOKZ JS - Failstats Chat" + "item" "GOKZ JS - Jumpstats Always" + "item" "GOKZ JS - Extended Chat Report" + "item" "GOKZ JS - Minimal Chat Broadcast Tier" + "item" "GOKZ JS - Minimal Sound Broadcast Tier" + } + "Paint" + { + "item" "GOKZ Paint - Color" + "item" "GOKZ Paint - Size" + } + "Profile" + { + "item" "GOKZ Profile - Tag Type" + "item" "GOKZ Profile - Show Rank Chat" + "item" "GOKZ Profile - Show Rank Clan" + } + "Quiet" + { + "item" "GOKZ QT - Show Players" + "item" "GOKZ QT - Map Sounds" + } +} From 36bbdea999b38400cec2fe833606c9ddfc6b22ca Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Mon, 9 Jan 2023 01:44:57 +0100 Subject: [PATCH 19/47] Change soundscape variable to be local instead, move defines to quiet.inc --- addons/sourcemod/scripting/gokz-quiet/soundscape.sp | 12 +++++------- addons/sourcemod/scripting/include/gokz/quiet.inc | 3 +++ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/addons/sourcemod/scripting/gokz-quiet/soundscape.sp b/addons/sourcemod/scripting/gokz-quiet/soundscape.sp index dbe10c97..fbb85f72 100644 --- a/addons/sourcemod/scripting/gokz-quiet/soundscape.sp +++ b/addons/sourcemod/scripting/gokz-quiet/soundscape.sp @@ -2,15 +2,13 @@ Toggle soundscapes. */ -// Search for "coopcementplant.missionselect_blank" id with sv_soundscape_printdebuginfo. -#define BLANK_SOUNDSCAPEINDEX 482 -int gI_CurrentSoundscapeIndex[MAXPLAYERS + 1] = {BLANK_SOUNDSCAPEINDEX, ...}; +static int currentSoundscapeIndex[MAXPLAYERS + 1] = {BLANK_SOUNDSCAPEINDEX, ...}; void EnableSoundscape(int client) { - if (gI_CurrentSoundscapeIndex[client] != BLANK_SOUNDSCAPEINDEX) + if (currentSoundscapeIndex[client] != BLANK_SOUNDSCAPEINDEX) { - SetEntProp(client, Prop_Data, "soundscapeIndex", gI_CurrentSoundscapeIndex[client]); + SetEntProp(client, Prop_Data, "soundscapeIndex", currentSoundscapeIndex[client]); } } @@ -21,12 +19,12 @@ void OnPlayerRunCmdPost_Soundscape(int client) { if (soundscapeIndex != BLANK_SOUNDSCAPEINDEX) { - gI_CurrentSoundscapeIndex[client] = soundscapeIndex; + currentSoundscapeIndex[client] = soundscapeIndex; } SetEntProp(client, Prop_Data, "soundscapeIndex", BLANK_SOUNDSCAPEINDEX); } else { - gI_CurrentSoundscapeIndex[client] = soundscapeIndex; + currentSoundscapeIndex[client] = soundscapeIndex; } } \ No newline at end of file diff --git a/addons/sourcemod/scripting/include/gokz/quiet.inc b/addons/sourcemod/scripting/include/gokz/quiet.inc index 4d7ea565..c66b1328 100644 --- a/addons/sourcemod/scripting/include/gokz/quiet.inc +++ b/addons/sourcemod/scripting/include/gokz/quiet.inc @@ -71,6 +71,9 @@ stock char gC_QTOptionPhrases[QTOPTION_COUNT][] = #define QUIET_OPTION_CATEGORY "Quiet" +#define EFFECT_IMPACT 8 +#define EFFECT_KNIFESLASH 2 +#define BLANK_SOUNDSCAPEINDEX 482 // Search for "coopcementplant.missionselect_blank" id with sv_soundscape_printdebuginfo. // =====[ STOCKS ]===== From f5d02238b076705fb88b30a23a06929015b4c728 Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Mon, 9 Jan 2023 15:47:48 +0100 Subject: [PATCH 20/47] Speculative fix for reload sound hook exception --- addons/sourcemod/scripting/gokz-quiet/hideplayers.sp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/addons/sourcemod/scripting/gokz-quiet/hideplayers.sp b/addons/sourcemod/scripting/gokz-quiet/hideplayers.sp index fff53894..b4e1be4e 100644 --- a/addons/sourcemod/scripting/gokz-quiet/hideplayers.sp +++ b/addons/sourcemod/scripting/gokz-quiet/hideplayers.sp @@ -79,7 +79,11 @@ static Action Hook_WeaponSound(UserMsg msg_id, Protobuf msg, const int[] players { return Plugin_Continue; } - + // No one to send to so it doesn't matter if we block or not. We block just to end the function early. + if (newTotal == 0) + { + return Plugin_Handled; + } // Only way to modify the recipient list is to RequestFrame and create our own user message. char path[PLATFORM_MAX_PATH]; msg.ReadString("sound", path, sizeof(path)); From 7ccf6c270fe5c132fbd12ad52e5a993be5dffa11 Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Mon, 9 Jan 2023 16:48:34 +0100 Subject: [PATCH 21/47] Move defines to include file, cleanup duplicate defines --- addons/sourcemod/scripting/gokz-quiet.sp | 2 -- addons/sourcemod/scripting/include/gokz/quiet.inc | 12 +++++------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/addons/sourcemod/scripting/gokz-quiet.sp b/addons/sourcemod/scripting/gokz-quiet.sp index 8ce77026..f6e3de52 100644 --- a/addons/sourcemod/scripting/gokz-quiet.sp +++ b/addons/sourcemod/scripting/gokz-quiet.sp @@ -26,8 +26,6 @@ public Plugin myinfo = #define UPDATER_URL GOKZ_UPDATER_BASE_URL..."gokz-quiet.txt" -#define EFFECT_IMPACT 8 -#define EFFECT_KNIFESLASH 2 #include "gokz-quiet/soundscape.sp" #include "gokz-quiet/hideplayers.sp" diff --git a/addons/sourcemod/scripting/include/gokz/quiet.inc b/addons/sourcemod/scripting/include/gokz/quiet.inc index c66b1328..55d1f571 100644 --- a/addons/sourcemod/scripting/include/gokz/quiet.inc +++ b/addons/sourcemod/scripting/include/gokz/quiet.inc @@ -35,9 +35,13 @@ enum MAPSOUNDS_COUNT }; +// =====[ CONSTANTS ]===== +#define QUIET_OPTION_CATEGORY "Quiet" -// =====[ CONSTANTS ]===== +#define EFFECT_IMPACT 8 +#define EFFECT_KNIFESLASH 2 +#define BLANK_SOUNDSCAPEINDEX 482 // Search for "coopcementplant.missionselect_blank" id with sv_soundscape_printdebuginfo. stock char gC_QTOptionNames[QTOPTION_COUNT][] = { @@ -69,12 +73,6 @@ stock char gC_QTOptionPhrases[QTOPTION_COUNT][] = "Options Menu - Map Sounds" }; - -#define QUIET_OPTION_CATEGORY "Quiet" -#define EFFECT_IMPACT 8 -#define EFFECT_KNIFESLASH 2 -#define BLANK_SOUNDSCAPEINDEX 482 // Search for "coopcementplant.missionselect_blank" id with sv_soundscape_printdebuginfo. - // =====[ STOCKS ]===== /** From a2a54ca7ea4ccffb68a24c2ee0db6066b499ca17 Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Mon, 9 Jan 2023 16:51:35 +0100 Subject: [PATCH 22/47] Add fall damage volume slider --- addons/sourcemod/scripting/gokz-quiet.sp | 2 + .../scripting/gokz-quiet/falldamage.sp | 40 ++++++++++++++++ .../sourcemod/scripting/gokz-quiet/options.sp | 12 +++++ .../scripting/include/gokz/quiet.inc | 48 +++++++++++-------- .../translations/gokz-quiet.phrases.txt | 4 ++ cfg/sourcemod/gokz/options_menu_sorting.cfg | 1 + 6 files changed, 87 insertions(+), 20 deletions(-) create mode 100644 addons/sourcemod/scripting/gokz-quiet/falldamage.sp diff --git a/addons/sourcemod/scripting/gokz-quiet.sp b/addons/sourcemod/scripting/gokz-quiet.sp index f6e3de52..f1106802 100644 --- a/addons/sourcemod/scripting/gokz-quiet.sp +++ b/addons/sourcemod/scripting/gokz-quiet.sp @@ -29,6 +29,7 @@ public Plugin myinfo = #include "gokz-quiet/soundscape.sp" #include "gokz-quiet/hideplayers.sp" +#include "gokz-quiet/falldamage.sp" #include "gokz-quiet/options.sp" // =====[ PLUGIN EVENTS ]===== @@ -42,6 +43,7 @@ public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max public void OnPluginStart() { OnPluginStart_HidePlayers(); + OnPluginStart_FallDamage(); LoadTranslations("gokz-common.phrases"); LoadTranslations("gokz-quiet.phrases"); diff --git a/addons/sourcemod/scripting/gokz-quiet/falldamage.sp b/addons/sourcemod/scripting/gokz-quiet/falldamage.sp new file mode 100644 index 00000000..a55c6912 --- /dev/null +++ b/addons/sourcemod/scripting/gokz-quiet/falldamage.sp @@ -0,0 +1,40 @@ +/* + Toggle player's fall damage sounds. +*/ + +void OnPluginStart_FallDamage() +{ + AddNormalSoundHook(Hook_NormalSound); +} + +static Action Hook_NormalSound(int clients[MAXPLAYERS], int& numClients, char sample[PLATFORM_MAX_PATH], int& entity, int& channel, float& volume, int& level, int& pitch, int& flags, char soundEntry[PLATFORM_MAX_PATH], int& seed) +{ + if (!StrEqual(soundEntry, "Player.FallDamage")) + { + return Plugin_Continue; + } + + for (int i = 0; i < numClients; i++) + { + int client = clients[i]; + if (!IsValidClient(client)) + { + continue; + } + int clientArray[1]; + clientArray[0] = client; + float newVolume; + if (GOKZ_QT_GetOption(client, QTOption_FallDamageSound) == -1 || GOKZ_QT_GetOption(client, QTOption_FallDamageSound) == 10) + { + newVolume = volume; + } + else + { + float volumeFactor = float(GOKZ_QT_GetOption(client, QTOption_FallDamageSound)) * 0.1; + newVolume = volume * volumeFactor; + } + + EmitSoundEntry(clientArray, 1, soundEntry, sample, entity, channel, level, seed, flags, newVolume, pitch); + } + return Plugin_Handled; +} \ No newline at end of file diff --git a/addons/sourcemod/scripting/gokz-quiet/options.sp b/addons/sourcemod/scripting/gokz-quiet/options.sp index cd97eff4..dfc2869f 100644 --- a/addons/sourcemod/scripting/gokz-quiet/options.sp +++ b/addons/sourcemod/scripting/gokz-quiet/options.sp @@ -136,6 +136,10 @@ public void TopMenuHandler_QT(TopMenu topmenu, TopMenuAction action, TopMenuObje { FormatToggleableOptionDisplay(param, QTOption_MapSounds, buffer, maxlength); } + case QTOption_FallDamageSound: + { + FormatVolumeOptionDisplay(param, QTOption_FallDamageSound, buffer, maxlength); + } } } else if (action == TopMenuAction_SelectOption) @@ -159,4 +163,12 @@ void FormatToggleableOptionDisplay(int client, QTOption option, char[] buffer, i gC_QTOptionPhrases[option], client, "Options Menu - Enabled", client); } +} + +void FormatVolumeOptionDisplay(int client, QTOption option, char[] buffer, int maxlength) +{ + // Assume 10% volume steps. + FormatEx(buffer, maxlength, "%T - %i%", + gC_QTOptionPhrases[option], client, + GOKZ_QT_GetOption(client, option) * 10); } \ No newline at end of file diff --git a/addons/sourcemod/scripting/include/gokz/quiet.inc b/addons/sourcemod/scripting/include/gokz/quiet.inc index 55d1f571..02191c01 100644 --- a/addons/sourcemod/scripting/include/gokz/quiet.inc +++ b/addons/sourcemod/scripting/include/gokz/quiet.inc @@ -1,6 +1,6 @@ /* gokz-quiet Plugin Include - + Website: https://bitbucket.org/kztimerglobalteam/gokz */ @@ -15,9 +15,10 @@ enum QTOption: { - QTOPTION_INVALID = -1, - QTOption_ShowPlayers, - QTOption_MapSounds, + QTOPTION_INVALID = -1, + QTOption_ShowPlayers, + QTOption_MapSounds, + QTOption_FallDamageSound, QTOPTION_COUNT }; @@ -38,39 +39,46 @@ enum // =====[ CONSTANTS ]===== #define QUIET_OPTION_CATEGORY "Quiet" +#define DEFAULT_VOLUME 10 +#define VOLUME_COUNT 21 // Maximum of 200% #define EFFECT_IMPACT 8 #define EFFECT_KNIFESLASH 2 #define BLANK_SOUNDSCAPEINDEX 482 // Search for "coopcementplant.missionselect_blank" id with sv_soundscape_printdebuginfo. -stock char gC_QTOptionNames[QTOPTION_COUNT][] = +stock char gC_QTOptionNames[QTOPTION_COUNT][] = { "GOKZ QT - Show Players", - "GOKZ QT - Map Sounds" + "GOKZ QT - Map Sounds", + "GOKZ QT - Fall Damage Sound" }; -stock char gC_QTOptionDescriptions[QTOPTION_COUNT][] = +stock char gC_QTOptionDescriptions[QTOPTION_COUNT][] = { "Visibility of Other Players - 0 = Disabled, 1 = Enabled", - "Play Ambient Map Sounds/Music - 0 = Disabled, 1 = Enabled" + "Play Ambient Map Sounds/Music - 0 = Disabled, 1 = Enabled", + "Play Fall Damage Sound - 0 to 20 = 0% to 200%" }; -stock int gI_QTOptionDefaultValues[QTOPTION_COUNT] = +stock int gI_QTOptionDefaultValues[QTOPTION_COUNT] = { ShowPlayers_Enabled, - MapSounds_Enabled + MapSounds_Enabled, + DEFAULT_VOLUME, // Fall damage volume }; -stock int gI_QTOptionCounts[QTOPTION_COUNT] = +stock int gI_QTOptionCounts[QTOPTION_COUNT] = { SHOWPLAYERS_COUNT, - MAPSOUNDS_COUNT + MAPSOUNDS_COUNT, + VOLUME_COUNT, // Fall damage volume }; -stock char gC_QTOptionPhrases[QTOPTION_COUNT][] = +stock char gC_QTOptionPhrases[QTOPTION_COUNT][] = { "Options Menu - Show Players", - "Options Menu - Map Sounds" + "Options Menu - Map Sounds", + "Options Menu - Fall Damage Sounds" }; // =====[ STOCKS ]===== @@ -137,13 +145,13 @@ stock bool GOKZ_QT_CycleOption(int client, QTOption option) // =====[ DEPENDENCY ]===== -public SharedPlugin __pl_gokz_quiet = +public SharedPlugin __pl_gokz_quiet = { - name = "gokz-quiet", - file = "gokz-quiet.smx", + name = "gokz-quiet", + file = "gokz-quiet.smx", #if defined REQUIRE_PLUGIN - required = 1, + required = 1, #else - required = 0, + required = 0, #endif -}; \ No newline at end of file +}; \ No newline at end of file diff --git a/addons/sourcemod/translations/gokz-quiet.phrases.txt b/addons/sourcemod/translations/gokz-quiet.phrases.txt index dee39ec3..90120e7b 100644 --- a/addons/sourcemod/translations/gokz-quiet.phrases.txt +++ b/addons/sourcemod/translations/gokz-quiet.phrases.txt @@ -49,4 +49,8 @@ Phrases "en" "Play map sounds" "chi" "播放地图音乐" } + "Options Menu - Fall Damage Sounds" + { + "en" "Fall damage sounds" + } } \ No newline at end of file diff --git a/cfg/sourcemod/gokz/options_menu_sorting.cfg b/cfg/sourcemod/gokz/options_menu_sorting.cfg index dc7c0182..beea95b8 100644 --- a/cfg/sourcemod/gokz/options_menu_sorting.cfg +++ b/cfg/sourcemod/gokz/options_menu_sorting.cfg @@ -62,5 +62,6 @@ { "item" "GOKZ QT - Show Players" "item" "GOKZ QT - Map Sounds" + "item" "GOKZ QT - Fall Damage Sound" } } From 0a6b8a50abaf8f41c08925e601451892a5a0b17c Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Mon, 9 Jan 2023 16:53:49 +0100 Subject: [PATCH 23/47] Add fall damage volume slider --- addons/sourcemod/scripting/gokz-quiet.sp | 2 + .../scripting/gokz-quiet/falldamage.sp | 40 ++++++++++++++++ .../sourcemod/scripting/gokz-quiet/options.sp | 12 +++++ .../scripting/include/gokz/quiet.inc | 48 +++++++++++-------- .../translations/gokz-quiet.phrases.txt | 4 ++ cfg/sourcemod/gokz/options_menu_sorting.cfg | 1 + 6 files changed, 87 insertions(+), 20 deletions(-) create mode 100644 addons/sourcemod/scripting/gokz-quiet/falldamage.sp diff --git a/addons/sourcemod/scripting/gokz-quiet.sp b/addons/sourcemod/scripting/gokz-quiet.sp index f6e3de52..f1106802 100644 --- a/addons/sourcemod/scripting/gokz-quiet.sp +++ b/addons/sourcemod/scripting/gokz-quiet.sp @@ -29,6 +29,7 @@ public Plugin myinfo = #include "gokz-quiet/soundscape.sp" #include "gokz-quiet/hideplayers.sp" +#include "gokz-quiet/falldamage.sp" #include "gokz-quiet/options.sp" // =====[ PLUGIN EVENTS ]===== @@ -42,6 +43,7 @@ public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max public void OnPluginStart() { OnPluginStart_HidePlayers(); + OnPluginStart_FallDamage(); LoadTranslations("gokz-common.phrases"); LoadTranslations("gokz-quiet.phrases"); diff --git a/addons/sourcemod/scripting/gokz-quiet/falldamage.sp b/addons/sourcemod/scripting/gokz-quiet/falldamage.sp new file mode 100644 index 00000000..a55c6912 --- /dev/null +++ b/addons/sourcemod/scripting/gokz-quiet/falldamage.sp @@ -0,0 +1,40 @@ +/* + Toggle player's fall damage sounds. +*/ + +void OnPluginStart_FallDamage() +{ + AddNormalSoundHook(Hook_NormalSound); +} + +static Action Hook_NormalSound(int clients[MAXPLAYERS], int& numClients, char sample[PLATFORM_MAX_PATH], int& entity, int& channel, float& volume, int& level, int& pitch, int& flags, char soundEntry[PLATFORM_MAX_PATH], int& seed) +{ + if (!StrEqual(soundEntry, "Player.FallDamage")) + { + return Plugin_Continue; + } + + for (int i = 0; i < numClients; i++) + { + int client = clients[i]; + if (!IsValidClient(client)) + { + continue; + } + int clientArray[1]; + clientArray[0] = client; + float newVolume; + if (GOKZ_QT_GetOption(client, QTOption_FallDamageSound) == -1 || GOKZ_QT_GetOption(client, QTOption_FallDamageSound) == 10) + { + newVolume = volume; + } + else + { + float volumeFactor = float(GOKZ_QT_GetOption(client, QTOption_FallDamageSound)) * 0.1; + newVolume = volume * volumeFactor; + } + + EmitSoundEntry(clientArray, 1, soundEntry, sample, entity, channel, level, seed, flags, newVolume, pitch); + } + return Plugin_Handled; +} \ No newline at end of file diff --git a/addons/sourcemod/scripting/gokz-quiet/options.sp b/addons/sourcemod/scripting/gokz-quiet/options.sp index cd97eff4..dfc2869f 100644 --- a/addons/sourcemod/scripting/gokz-quiet/options.sp +++ b/addons/sourcemod/scripting/gokz-quiet/options.sp @@ -136,6 +136,10 @@ public void TopMenuHandler_QT(TopMenu topmenu, TopMenuAction action, TopMenuObje { FormatToggleableOptionDisplay(param, QTOption_MapSounds, buffer, maxlength); } + case QTOption_FallDamageSound: + { + FormatVolumeOptionDisplay(param, QTOption_FallDamageSound, buffer, maxlength); + } } } else if (action == TopMenuAction_SelectOption) @@ -159,4 +163,12 @@ void FormatToggleableOptionDisplay(int client, QTOption option, char[] buffer, i gC_QTOptionPhrases[option], client, "Options Menu - Enabled", client); } +} + +void FormatVolumeOptionDisplay(int client, QTOption option, char[] buffer, int maxlength) +{ + // Assume 10% volume steps. + FormatEx(buffer, maxlength, "%T - %i%", + gC_QTOptionPhrases[option], client, + GOKZ_QT_GetOption(client, option) * 10); } \ No newline at end of file diff --git a/addons/sourcemod/scripting/include/gokz/quiet.inc b/addons/sourcemod/scripting/include/gokz/quiet.inc index 55d1f571..02191c01 100644 --- a/addons/sourcemod/scripting/include/gokz/quiet.inc +++ b/addons/sourcemod/scripting/include/gokz/quiet.inc @@ -1,6 +1,6 @@ /* gokz-quiet Plugin Include - + Website: https://bitbucket.org/kztimerglobalteam/gokz */ @@ -15,9 +15,10 @@ enum QTOption: { - QTOPTION_INVALID = -1, - QTOption_ShowPlayers, - QTOption_MapSounds, + QTOPTION_INVALID = -1, + QTOption_ShowPlayers, + QTOption_MapSounds, + QTOption_FallDamageSound, QTOPTION_COUNT }; @@ -38,39 +39,46 @@ enum // =====[ CONSTANTS ]===== #define QUIET_OPTION_CATEGORY "Quiet" +#define DEFAULT_VOLUME 10 +#define VOLUME_COUNT 21 // Maximum of 200% #define EFFECT_IMPACT 8 #define EFFECT_KNIFESLASH 2 #define BLANK_SOUNDSCAPEINDEX 482 // Search for "coopcementplant.missionselect_blank" id with sv_soundscape_printdebuginfo. -stock char gC_QTOptionNames[QTOPTION_COUNT][] = +stock char gC_QTOptionNames[QTOPTION_COUNT][] = { "GOKZ QT - Show Players", - "GOKZ QT - Map Sounds" + "GOKZ QT - Map Sounds", + "GOKZ QT - Fall Damage Sound" }; -stock char gC_QTOptionDescriptions[QTOPTION_COUNT][] = +stock char gC_QTOptionDescriptions[QTOPTION_COUNT][] = { "Visibility of Other Players - 0 = Disabled, 1 = Enabled", - "Play Ambient Map Sounds/Music - 0 = Disabled, 1 = Enabled" + "Play Ambient Map Sounds/Music - 0 = Disabled, 1 = Enabled", + "Play Fall Damage Sound - 0 to 20 = 0% to 200%" }; -stock int gI_QTOptionDefaultValues[QTOPTION_COUNT] = +stock int gI_QTOptionDefaultValues[QTOPTION_COUNT] = { ShowPlayers_Enabled, - MapSounds_Enabled + MapSounds_Enabled, + DEFAULT_VOLUME, // Fall damage volume }; -stock int gI_QTOptionCounts[QTOPTION_COUNT] = +stock int gI_QTOptionCounts[QTOPTION_COUNT] = { SHOWPLAYERS_COUNT, - MAPSOUNDS_COUNT + MAPSOUNDS_COUNT, + VOLUME_COUNT, // Fall damage volume }; -stock char gC_QTOptionPhrases[QTOPTION_COUNT][] = +stock char gC_QTOptionPhrases[QTOPTION_COUNT][] = { "Options Menu - Show Players", - "Options Menu - Map Sounds" + "Options Menu - Map Sounds", + "Options Menu - Fall Damage Sounds" }; // =====[ STOCKS ]===== @@ -137,13 +145,13 @@ stock bool GOKZ_QT_CycleOption(int client, QTOption option) // =====[ DEPENDENCY ]===== -public SharedPlugin __pl_gokz_quiet = +public SharedPlugin __pl_gokz_quiet = { - name = "gokz-quiet", - file = "gokz-quiet.smx", + name = "gokz-quiet", + file = "gokz-quiet.smx", #if defined REQUIRE_PLUGIN - required = 1, + required = 1, #else - required = 0, + required = 0, #endif -}; \ No newline at end of file +}; \ No newline at end of file diff --git a/addons/sourcemod/translations/gokz-quiet.phrases.txt b/addons/sourcemod/translations/gokz-quiet.phrases.txt index dee39ec3..90120e7b 100644 --- a/addons/sourcemod/translations/gokz-quiet.phrases.txt +++ b/addons/sourcemod/translations/gokz-quiet.phrases.txt @@ -49,4 +49,8 @@ Phrases "en" "Play map sounds" "chi" "播放地图音乐" } + "Options Menu - Fall Damage Sounds" + { + "en" "Fall damage sounds" + } } \ No newline at end of file diff --git a/cfg/sourcemod/gokz/options_menu_sorting.cfg b/cfg/sourcemod/gokz/options_menu_sorting.cfg index dc7c0182..beea95b8 100644 --- a/cfg/sourcemod/gokz/options_menu_sorting.cfg +++ b/cfg/sourcemod/gokz/options_menu_sorting.cfg @@ -62,5 +62,6 @@ { "item" "GOKZ QT - Show Players" "item" "GOKZ QT - Map Sounds" + "item" "GOKZ QT - Fall Damage Sound" } } From 95f991184e4dbc9042d547b61215006b77b11835 Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Sat, 14 Jan 2023 13:08:08 +0100 Subject: [PATCH 24/47] Make info panel text non reliable to increase update speed on high ping scenarios --- addons/sourcemod/scripting/gokz-hud/info_panel.sp | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/addons/sourcemod/scripting/gokz-hud/info_panel.sp b/addons/sourcemod/scripting/gokz-hud/info_panel.sp index 83606552..c766af9e 100644 --- a/addons/sourcemod/scripting/gokz-hud/info_panel.sp +++ b/addons/sourcemod/scripting/gokz-hud/info_panel.sp @@ -27,14 +27,7 @@ bool IsDrawingInfoPanel(int client) void OnPlayerRunCmdPost_InfoPanel(int client, int cmdnum, HUDInfo info) { - int updateSpeed = 10; - if (gB_FastUpdateRate[client]) - { - // The hint text panel update speed depends on the client ping. - // To optimize resource usage, we scale the update speed with it. - // The fastest speed the client can get is around once every 2 ticks. - updateSpeed = IntMax(1, RoundToFloor(GetClientAvgLatency(client, NetFlow_Outgoing) / GetTickInterval())); - } + int updateSpeed = gB_FastUpdateRate[client] ? 3 : 6; if (cmdnum % updateSpeed == 0 || info.IsTakeoff) { UpdateInfoPanel(client, info); @@ -273,7 +266,7 @@ void PrintCSGOHUDText(int client, const char[] format) buff[sizeof(buff) - 1] = '\0'; - Protobuf pb = view_as(StartMessageOne("TextMsg", client, USERMSG_RELIABLE | USERMSG_BLOCKHOOKS)); + Protobuf pb = view_as(StartMessageOne("TextMsg", client, USERMSG_BLOCKHOOKS)); pb.SetInt("msg_dst", 4); pb.AddString("params", "#SFUI_ContractKillStart"); pb.AddString("params", buff); From ce1f932309da9be8e991112aac553df8ff2c0929 Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Sun, 15 Jan 2023 03:29:52 +0100 Subject: [PATCH 25/47] Remove 56+ height perfs --- addons/sourcemod/gamedata/gokz-core.games.txt | 17 + .../sourcemod/scripting/gokz-mode-kztimer.sp | 35 +- .../sourcemod/scripting/gokz-mode-simplekz.sp | 31 + .../scripting/include/movementapi.inc | 1304 +++++++++-------- 4 files changed, 743 insertions(+), 644 deletions(-) diff --git a/addons/sourcemod/gamedata/gokz-core.games.txt b/addons/sourcemod/gamedata/gokz-core.games.txt index a42f7547..ae25eb3a 100644 --- a/addons/sourcemod/gamedata/gokz-core.games.txt +++ b/addons/sourcemod/gamedata/gokz-core.games.txt @@ -2,6 +2,17 @@ { "#default" { + "Functions" + { + "CCSGameMovement::CanUnduck" + { + "signature" "CCSGameMovement::CanUnduck" + "callconv" "thiscall" + "this" "address" + "return" "bool" + } + } + "Keys" { "IGameMovement" "GameMovement001" @@ -17,6 +28,12 @@ "windows" "@CreateInterface" "linux" "@CreateInterface" } + "CCSGameMovement::CanUnduck" + { + "library" "server" + "windows" "\x55\x8B\xEC\x81\xEC\x8C\x00\x00\x00\x57\x8B\xF9\x8B\x87\x54\x0E\x00\x00" + "linux" "\x55\x89\xE5\x56\x53\x83\xEC\x50\x8B\x5D\x08\x8B\x43\x08\xF3\x0F\x10\x80\xAC\x00\x00\x00\xF3\x0F\x11\x45\xEC" + } } "Offsets" diff --git a/addons/sourcemod/scripting/gokz-mode-kztimer.sp b/addons/sourcemod/scripting/gokz-mode-kztimer.sp index d7237b4b..1791c3ce 100644 --- a/addons/sourcemod/scripting/gokz-mode-kztimer.sp +++ b/addons/sourcemod/scripting/gokz-mode-kztimer.sp @@ -69,11 +69,12 @@ float gF_PreVelModLastChange[MAXPLAYERS + 1]; float gF_RealPreVelMod[MAXPLAYERS + 1]; int gI_PreTickCounter[MAXPLAYERS + 1]; Handle gH_GetPlayerMaxSpeed; +DynamicDetour gH_CanUnduck; +int gI_TickCount[MAXPLAYERS + 1]; DynamicDetour gH_AirAccelerate; int gI_OldButtons[MAXPLAYERS + 1]; int gI_OldFlags[MAXPLAYERS + 1]; bool gB_OldOnGround[MAXPLAYERS + 1]; -float gF_OldAngles[MAXPLAYERS + 1][3]; float gF_OldVelocity[MAXPLAYERS + 1][3]; bool gB_Jumpbugged[MAXPLAYERS + 1]; int gI_OffsetCGameMovement_player; @@ -173,9 +174,8 @@ public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3 gI_OldButtons[player.ID] = buttons; gI_OldFlags[player.ID] = GetEntityFlags(client); gB_OldOnGround[player.ID] = Movement_GetOnGround(client); - gF_OldAngles[player.ID] = angles; + gI_TickCount[player.ID] = tickcount; Movement_GetVelocity(client, gF_OldVelocity[client]); - return Plugin_Continue; } @@ -212,6 +212,22 @@ public MRESReturn DHooks_OnAirAccelerate_Pre(Address pThis, DHookParam hParams) return MRES_Ignored; } +public MRESReturn DHooks_OnCanUnduck_Pre(Address pThis, DHookReturn hReturn) +{ + int client = GOKZGetClientFromGameMovementAddress(pThis, gI_OffsetCGameMovement_player); + if (!IsPlayerAlive(client) || !IsUsingMode(client)) + { + return MRES_Ignored; + } + // Just landed fully ducked, you can't unduck. + if (Movement_GetLandingTick(client) == (gI_TickCount[client] - 1) && GetEntPropFloat(client, Prop_Send, "m_flDuckAmount") >= 1.0 && GetEntProp(client, Prop_Send, "m_bDucked")) + { + hReturn.Value = false; + return MRES_Supercede; + } + return MRES_Ignored; +} + public void SDKHook_OnClientPreThink_Post(int client) { if (!IsPlayerAlive(client) || !IsUsingMode(client)) @@ -348,6 +364,19 @@ void HookEvents() SetFailState("Failed to get CGameMovement::player offset."); } gI_OffsetCGameMovement_player = StringToInt(buffer); + + gameData = LoadGameConfigFile("gokz-core.games"); + gH_CanUnduck = DynamicDetour.FromConf(gameData, "CCSGameMovement::CanUnduck"); + if (gH_CanUnduck == INVALID_HANDLE) + { + SetFailState("Failed to find CCSGameMovement::CanUnduck function signature"); + } + + if (!gH_CanUnduck.Enable(Hook_Pre, DHooks_OnCanUnduck_Pre)) + { + SetFailState("Failed to enable detour on CCSGameMovement::CanUnduck"); + } + delete gameData; } // =====[ CONVARS ]===== diff --git a/addons/sourcemod/scripting/gokz-mode-simplekz.sp b/addons/sourcemod/scripting/gokz-mode-simplekz.sp index 7d0f7738..230614df 100644 --- a/addons/sourcemod/scripting/gokz-mode-simplekz.sp +++ b/addons/sourcemod/scripting/gokz-mode-simplekz.sp @@ -78,6 +78,8 @@ bool gB_PSTurningLeft[MAXPLAYERS + 1]; float gF_PSTurnRate[MAXPLAYERS + 1]; int gI_PSTicksSinceIncrement[MAXPLAYERS + 1]; Handle gH_GetPlayerMaxSpeed; +DynamicDetour gH_CanUnduck; +int gI_TickCount[MAXPLAYERS + 1]; DynamicDetour gH_AirAccelerate; int gI_OldButtons[MAXPLAYERS + 1]; int gI_OldFlags[MAXPLAYERS + 1]; @@ -224,6 +226,22 @@ public MRESReturn DHooks_OnAirAccelerate_Pre(Address pThis, DHookParam hParams) return MRES_Ignored; } +public MRESReturn DHooks_OnCanUnduck_Pre(Address pThis, DHookReturn hReturn) +{ + int client = GOKZGetClientFromGameMovementAddress(pThis, gI_OffsetCGameMovement_player); + if (!IsPlayerAlive(client) || !IsUsingMode(client)) + { + return MRES_Ignored; + } + // Just landed fully ducked, you can't unduck. + if (Movement_GetLandingTick(client) == (gI_TickCount[client] - 1) && GetEntPropFloat(client, Prop_Send, "m_flDuckAmount") >= 1.0 && GetEntProp(client, Prop_Send, "m_bDucked")) + { + hReturn.Value = false; + return MRES_Supercede; + } + return MRES_Ignored; +} + public void OnPlayerRunCmdPost(int client, int buttons, int impulse, const float vel[3], const float angles[3], int weapon, int subtype, int cmdnum, int tickcount, int seed, const int mouse[2]) { if (!IsValidClient(client) || !IsPlayerAlive(client) || !IsUsingMode(client)) @@ -358,6 +376,19 @@ void HookEvents() SetFailState("Failed to get CGameMovement::player offset."); } gI_OffsetCGameMovement_player = StringToInt(buffer); + + gameData = LoadGameConfigFile("gokz-core.games"); + gH_CanUnduck = DynamicDetour.FromConf(gameData, "CCSGameMovement::CanUnduck"); + if (gH_CanUnduck == INVALID_HANDLE) + { + SetFailState("Failed to find CCSGameMovement::CanUnduck function signature"); + } + + if (!gH_CanUnduck.Enable(Hook_Pre, DHooks_OnCanUnduck_Pre)) + { + SetFailState("Failed to enable detour on CCSGameMovement::CanUnduck"); + } + delete gameData; } // =====[ CONVARS ]===== diff --git a/addons/sourcemod/scripting/include/movementapi.inc b/addons/sourcemod/scripting/include/movementapi.inc index c0d87e3c..0bf592bc 100644 --- a/addons/sourcemod/scripting/include/movementapi.inc +++ b/addons/sourcemod/scripting/include/movementapi.inc @@ -1,641 +1,663 @@ -/* - MovementAPI Plugin Include - - Website: https://github.com/danzayau/MovementAPI -*/ - -#if defined _movementapi_included_ - #endinput -#endif -#define _movementapi_included_ - -#include - - - -/* - Terminology - - Takeoff - Becoming airborne, including jumping, falling, getting off a ladder and leaving noclip. - - Landing - Leaving the air, including landing on the ground, grabbing a ladder and entering noclip. - - Perfect Bunnyhop (Perf) - When the player has jumped in the tick after landing and keeps their speed. - - Duckbug/Crouchbug - When the player sucessfully lands due to uncrouching from mid air and not by falling - down. This causes no stamina loss or fall damage upon landing. - - Jumpbug - This is achieved by duckbugging and jumping at the same time. The player is never seen - as 'on ground' when bunnyhopping from a tick by tick perspective. A jumpbug inherits - the same behavior as a duckbug/crouchbug, along with its effects such as maintaining - speed due to no stamina loss. - - Distbug - Landing behavior varies depending on whether the player lands close to the edge of a - block or not: - - 1. If the player lands close to the edge of a block, this causes the jump duration to - be one tick longer and the player can "slide" on the ground during the landing tick, - using the position post-tick as landing position becomes inaccurate. - - 2. On the other hand, if the player does not land close to the edge, the player will - be considered on the ground one tick earlier, using this position as landing position - is not accurate as the player has yet to be fully on the ground. - - In scenario 1, GetNobugLandingOrigin calculates the correct landing position of the - player before the sliding effect takes effect. - - In scenario 2, GetNobugLandingOrigin attempts to extrapolate the player's fully on - ground position to make landing positions consistent across scenarios. -*/ - - - -// =====[ FORWARDS ]===== - -/** - * Called when a player's movetype changes. - * - * @param client Client index. - * @param oldMovetype Player's old movetype. - * @param newMovetype Player's new movetype. - */ -forward void Movement_OnChangeMovetype(int client, MoveType oldMovetype, MoveType newMovetype); - -/** - * Called when a player touches the ground. - * - * @param client Client index. - */ -forward void Movement_OnStartTouchGround(int client); - -/** - * Called when a player leaves the ground. - * - * @param client Client index. - * @param jumped Whether player jumped to leave ground. - * @param ladderJump Whether player jumped from a ladder. - * @param jumpbug Whether player performed a jumpbug. - */ -forward void Movement_OnStopTouchGround(int client, bool jumped, bool ladderJump, bool jumpbug); - -/** - * Called when a player starts ducking. - * - * @param client Client index. - */ -forward void Movement_OnStartDucking(int client); - -/** - * Called when a player stops ducking. - * - * @param client Client index. - */ -forward void Movement_OnStopDucking(int client); - -/** - * Called when a player jumps (player_jump event), including 'jumpbugs'. - * Setting velocity when this is called may not be effective. - * - * @param client Client index. - * @param jumpbug Whether player 'jumpbugged'. - */ -forward void Movement_OnPlayerJump(int client, bool jumpbug); - -/** - * Called before Duck movement function is called. - * Modifying origin or velocity parameters will change player's origin and velocity accordingly. - * - * @param client Client index. - * @param origin Player origin. - * @param velocity Player velocity. - * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. - */ -forward Action Movement_OnDuckPre(int client, float origin[3], float velocity[3]); - -/** - * Called after Duck movement function is called. - * Modifying origin or velocity parameters will change player's origin and velocity accordingly. - * - * @param client Client index. - * @param origin Player origin. - * @param velocity Player velocity. - * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. - */ -forward Action Movement_OnDuckPost(int client, float origin[3], float velocity[3]); - -/** - * Called before LadderMove movement function is called. - * Modifying origin or velocity parameters will change player's origin and velocity accordingly. - * - * @param client Client index. - * @param origin Player origin. - * @param velocity Player velocity. - * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. - */ -forward Action Movement_OnLadderMovePre(int client, float origin[3], float velocity[3]); - -/** - * Called after LadderMove movement function is called. - * Modifying origin or velocity parameters will change player's origin and velocity accordingly. - * - * @param client Client index. - * @param origin Player origin. - * @param velocity Player velocity. - * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. - */ -forward Action Movement_OnLadderMovePost(int client, float origin[3], float velocity[3]); - -/** - * Called before FullLadderMove movement function is called. - * Modifying origin or velocity parameters will change player's origin and velocity accordingly. - * - * @param client Client index. - * @param origin Player origin. - * @param velocity Player velocity. - * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. - */ -forward Action Movement_OnFullLadderMovePre(int client, float origin[3], float velocity[3]); - -/** - * Called after FullLadderMove movement function is called. - * Modifying origin or velocity parameters will change player's origin and velocity accordingly. - * - * @param client Client index. - * @param origin Player origin. - * @param velocity Player velocity. - * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. - */ -forward Action Movement_OnFullLadderMovePost(int client, float origin[3], float velocity[3]); - -/** - * Called after the player jumps, but before jumping stamina is applied and takeoff variables are not set yet. - * Modifying origin or velocity parameters will change player's origin and velocity accordingly. - * - * @param client Client index. - * @param origin Player origin. - * @param velocity Player velocity. - * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. - */ -forward Action Movement_OnJumpPre(int client, float origin[3], float velocity[3]); - -/** - * Called after the player jumps and after jumping stamina is applied and takeoff variables are already set here. - * Modifying origin or velocity parameters will change player's origin and velocity accordingly. - * - * @param client Client index. - * @param origin Player origin. - * @param velocity Player velocity. - * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. - */ -forward Action Movement_OnJumpPost(int client, float origin[3], float velocity[3]); - -/** - * Called before AirAccelerate movement function is called. - * Modifying origin or velocity parameters will change player's origin and velocity accordingly. - * - * @param client Client index. - * @param origin Player origin. - * @param velocity Player velocity. - * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. - */ -forward Action Movement_OnAirAcceleratePre(int client, float origin[3], float velocity[3]); - -/** - * Called after AirAccelerate movement function is called. - * Modifying origin or velocity parameters will change player's origin and velocity accordingly. - * - * @param client Client index. - * @param origin Player origin. - * @param velocity Player velocity. - * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. - */ -forward Action Movement_OnAirAcceleratePost(int client, float origin[3], float velocity[3]); - -/** - * Called before WalkMove movement function is called. - * Modifying origin or velocity parameters will change player's origin and velocity accordingly. - * - * @param client Client index. - * @param origin Player origin. - * @param velocity Player velocity. - * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. - */ -forward Action Movement_OnWalkMovePre(int client, float origin[3], float velocity[3]); - -/** - * Called after WalkMove movement function is called. - * Modifying origin or velocity parameters will change player's origin and velocity accordingly. - * - * @param client Client index. - * @param origin Player origin. - * @param velocity Player velocity. - * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. - */ -forward Action Movement_OnWalkMovePost(int client, float origin[3], float velocity[3]); - -/** - * Called before CategorizePosition movement function is called. - * Modifying origin or velocity parameters will change player's origin and velocity accordingly. - * - * @param client Client index. - * @param origin Player origin. - * @param velocity Player velocity. - * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. - */ -forward Action Movement_OnCategorizePositionPre(int client, float origin[3], float velocity[3]); - -/** - * Called after CategorizePosition movement function is called. - * Modifying origin or velocity parameters will change player's origin and velocity accordingly. - * - * @param client Client index. - * @param origin Player origin. - * @param velocity Player velocity. - * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. - */ -forward Action Movement_OnCategorizePositionPost(int client, float origin[3], float velocity[3]); - -// =====[ NATIVES ]===== - -/** - * Gets whether a player's last takeoff was a jump. - * - * @param client Client index. - * @return Whether player's last takeoff was a jump. - */ -native bool Movement_GetJumped(int client); - -/** - * Gets whether a player's last takeoff was a perfect bunnyhop. - * - * @param client Client index. - * @return Whether player's last takeoff was a perfect bunnyhop. - */ -native bool Movement_GetHitPerf(int client); - -/** - * Gets a player's origin at the time of their last takeoff. - * - * @param client Client index. - * @param result Resultant vector. - */ -native void Movement_GetTakeoffOrigin(int client, float result[3]); - -/** - * Gets a player's velocity at the time of their last takeoff. - * - * If sv_enablebunnyhopping is 0, CS:GO may adjust the player's - * velocity after the takeoff velocity has already been measured. - * - * @param client Client index. - * @param result Resultant vector. - */ -native void Movement_GetTakeoffVelocity(int client, float result[3]); - -/** - * Gets a player's horizontal speed at the time of their last takeoff. - * - * If sv_enablebunnyhopping is 0, CS:GO may adjust the player's - * velocity after the takeoff velocity has already been measured. - * - * @param client Client index. - * @return Player's last takeoff speed. - */ -native float Movement_GetTakeoffSpeed(int client); - -/** - * Gets a player's 'tickcount' at the time of their last takeoff. - * - * @param client Client index. - * @return Player's last takeoff 'tickcount'. - */ -native int Movement_GetTakeoffTick(int client); - -/** - * Gets a player's 'cmdnum' at the time of their last takeoff. - * - * @param client Client index. - * @return Player's last takeoff 'cmdnum'. - */ -native int Movement_GetTakeoffCmdNum(int client); - -/** - * Gets a player's origin at the time of their last landing with the distbug fixed. - * - * @param client Client index. - * @param result Resultant vector. - */ -native void Movement_GetNobugLandingOrigin(int client, float result[3]); - -/** - * Gets a player's origin at the time of their last landing. - * - * @param client Client index. - * @param result Resultant vector. - */ -native void Movement_GetLandingOrigin(int client, float result[3]); - -/** - * Gets a player's velocity at the time of their last landing. - * - * @param client Client index. - * @param result Resultant vector. - */ -native void Movement_GetLandingVelocity(int client, float result[3]); - -/** - * Gets a player's horizontal speed at the time of their last landing. - * - * @param client Client index. - * @return Last landing speed of the player (horizontal). - */ -native float Movement_GetLandingSpeed(int client); - -/** - * Gets a player's 'tickcount' at the time of their last landing. - * - * @param client Client index. - * @return Player's last landing 'tickcount'. - */ -native int Movement_GetLandingTick(int client); - -/** - * Gets a player's 'cmdnum' at the time of their last landing. - * - * @param client Client index. - * @return Player's last landing 'cmdnum'. - */ -native int Movement_GetLandingCmdNum(int client); - -/** - * Gets whether a player is turning their aim horizontally. - * - * @param client Client index. - * @return Whether player is turning their aim horizontally. - */ -native bool Movement_GetTurning(int client); - -/** - * Gets whether a player is turning their aim left. - * - * @param client Client index. - * @return Whether player is turning their aim left. - */ -native bool Movement_GetTurningLeft(int client); - -/** - * Gets whether a player is turning their aim right. - * - * @param client Client index. - * @return Whether player is turning their aim right. - */ -native bool Movement_GetTurningRight(int client); - -/** - * Gets result of CCSPlayer::GetPlayerMaxSpeed(client), which - * is the player's max speed as limited by their weapon. - * - * @param client Client index. - * @return Player's max speed as limited by their weapon. - */ -native float Movement_GetMaxSpeed(int client); - -/** - * Gets whether a player duckbugged on this tick. - * - * @param client Client index. - * @return Whether a player duckbugged on this tick. - */ -native bool Movement_GetDuckbugged(int client); - -/** - * Gets whether a player jumpbugged on this tick. - * - * @param client Client index. - * @return Whether a player jumpbugged on this tick. - */ -native bool Movement_GetJumpbugged(int client); - -/** - * Get the player's origin during movement processing. - * - * @param client Client index. - * @param result Resultant vector. - */ -native void Movement_GetProcessingOrigin(int client, float result[3]); - -/** - * Get the player's velocity during movement processing. - * - * @param client Param description - * @param result Resultant vector. - */ -native void Movement_GetProcessingVelocity(int client, float result[3]); - -/** - * Set the player's takeoff origin. - * - * @param client Client index. - * @param origin Desired origin. - */ -native void Movement_SetTakeoffOrigin(int client, float origin[3]); - -/** - * Set the player's takeoff velocity. - * - * @param client Client index. - * @param origin Desired velocity. - */ -native void Movement_SetTakeoffVelocity(int client, float velocity[3]); - -/** - * Set the player's landing origin. - * - * @param client Client index. - * @param origin Desired origin. - */ -native void Movement_SetLandingOrigin(int client, float origin[3]); - -/** - * Set the player's landing velocity. - * - * @param client Client index. - * @param origin Desired velocity. - */ -native void Movement_SetLandingVelocity(int client, float velocity[3]); - -// =====[ METHODMAP ]===== - -methodmap MovementAPIPlayer < MovementPlayer { - - public MovementAPIPlayer(int client) { - return view_as(MovementPlayer(client)); - } - - property bool Jumped { - public get() { - return Movement_GetJumped(this.ID); - } - } - - property bool HitPerf { - public get() { - return Movement_GetHitPerf(this.ID); - } - } - - public void GetTakeoffOrigin(float buffer[3]) { - Movement_GetTakeoffOrigin(this.ID, buffer); - } - - public void GetTakeoffVelocity(float buffer[3]) { - Movement_GetTakeoffVelocity(this.ID, buffer); - } - - public void SetTakeoffOrigin(float buffer[3]) - { - Movement_SetTakeoffOrigin(this.ID, buffer); - } - - public void SetTakeoffVelocity(float buffer[3]) - { - Movement_SetTakeoffVelocity(this.ID, buffer); - } - - property float TakeoffSpeed { - public get() { - return Movement_GetTakeoffSpeed(this.ID); - } - } - - property int TakeoffTick { - public get() { - return Movement_GetTakeoffTick(this.ID); - } - } - - property int TakeoffCmdNum { - public get() { - return Movement_GetTakeoffCmdNum(this.ID); - } - } - - public void GetLandingOrigin(float buffer[3]) { - Movement_GetLandingOrigin(this.ID, buffer); - } - - public void GetLandingVelocity(float buffer[3]) { - Movement_GetLandingVelocity(this.ID, buffer); - } - - public void SetLandingOrigin(float buffer[3]) - { - Movement_SetLandingOrigin(this.ID, buffer); - } - - public void SetLandingVelocity(float buffer[3]) - { - Movement_SetLandingVelocity(this.ID, buffer); - } - - property float LandingSpeed { - public get() { - return Movement_GetLandingSpeed(this.ID); - } - } - - property int LandingTick { - public get() { - return Movement_GetLandingTick(this.ID); - } - } - - property int LandingCmdNum { - public get() { - return Movement_GetLandingCmdNum(this.ID); - } - } - - property bool Turning { - public get() { - return Movement_GetTurning(this.ID); - } - } - - property bool TurningLeft { - public get() { - return Movement_GetTurningLeft(this.ID); - } - } - - property bool TurningRight { - public get() { - return Movement_GetTurningRight(this.ID); - } - } - - property float MaxSpeed { - public get() { - return Movement_GetMaxSpeed(this.ID); - } - } - - public void GetProcessingVelocity(float buffer[3]) - { - Movement_GetProcessingVelocity(this.ID, buffer); - } - - public void GetProcessingOrigin(float buffer[3]) - { - Movement_GetProcessingOrigin(this.ID, buffer); - } -} - - - -// =====[ DEPENDENCY ]===== - -public SharedPlugin __pl_movementapi = -{ - name = "movementapi", - file = "movementapi.smx", - #if defined REQUIRE_PLUGIN - required = 1, - #else - required = 0, - #endif -}; - -#if !defined REQUIRE_PLUGIN -public void __pl_movementapi_SetNTVOptional() -{ - MarkNativeAsOptional("Movement_GetJumped"); - MarkNativeAsOptional("Movement_GetHitPerf"); - MarkNativeAsOptional("Movement_GetTakeoffOrigin"); - MarkNativeAsOptional("Movement_GetTakeoffVelocity"); - MarkNativeAsOptional("Movement_GetTakeoffSpeed"); - MarkNativeAsOptional("Movement_GetTakeoffTick"); - MarkNativeAsOptional("Movement_GetTakeoffCmdNum"); - MarkNativeAsOptional("Movement_GetLandingOrigin"); - MarkNativeAsOptional("Movement_GetLandingVelocity"); - MarkNativeAsOptional("Movement_GetLandingSpeed"); - MarkNativeAsOptional("Movement_GetLandingTick"); - MarkNativeAsOptional("Movement_GetLandingCmdNum"); - MarkNativeAsOptional("Movement_GetTurning"); - MarkNativeAsOptional("Movement_GetTurningLeft"); - MarkNativeAsOptional("Movement_GetTurningRight"); - MarkNativeAsOptional("Movement_GetMaxSpeed"); - MarkNativeAsOptional("Movement_GetProcessingOrigin"); - MarkNativeAsOptional("Movement_GetProcessingVelocity"); - MarkNativeAsOptional("Movement_SetTakeoffOrigin"); - MarkNativeAsOptional("Movement_SetTakeoffVelocity"); - MarkNativeAsOptional("Movement_SetLandingOrigin"); - MarkNativeAsOptional("Movement_SetLandingVelocity"); -} -#endif +/* + MovementAPI Plugin Include + + Website: https://github.com/danzayau/MovementAPI +*/ + +#if defined _movementapi_included_ + #endinput +#endif +#define _movementapi_included_ + +#include + + + +/* + Terminology + + Takeoff + Becoming airborne, including jumping, falling, getting off a ladder and leaving noclip. + + Landing + Leaving the air, including landing on the ground, grabbing a ladder and entering noclip. + + Perfect Bunnyhop (Perf) + When the player has jumped in the tick after landing and keeps their speed. + + Duckbug/Crouchbug + When the player sucessfully lands due to uncrouching from mid air and not by falling + down. This causes no stamina loss or fall damage upon landing. + + Jumpbug + This is achieved by duckbugging and jumping at the same time. The player is never seen + as 'on ground' when bunnyhopping from a tick by tick perspective. A jumpbug inherits + the same behavior as a duckbug/crouchbug, along with its effects such as maintaining + speed due to no stamina loss. + + Distbug + Landing behavior varies depending on whether the player lands close to the edge of a + block or not: + + 1. If the player lands close to the edge of a block, this causes the jump duration to + be one tick longer and the player can "slide" on the ground during the landing tick, + using the position post-tick as landing position becomes inaccurate. + + 2. On the other hand, if the player does not land close to the edge, the player will + be considered on the ground one tick earlier, using this position as landing position + is not accurate as the player has yet to be fully on the ground. + + In scenario 1, GetNobugLandingOrigin calculates the correct landing position of the + player before the sliding effect takes effect. + + In scenario 2, GetNobugLandingOrigin attempts to extrapolate the player's fully on + ground position to make landing positions consistent across scenarios. +*/ + + + +// =====[ FORWARDS ]===== + +/** + * Called when a player's movetype changes. + * + * @param client Client index. + * @param oldMovetype Player's old movetype. + * @param newMovetype Player's new movetype. + */ +forward void Movement_OnChangeMovetype(int client, MoveType oldMovetype, MoveType newMovetype); + +/** + * Called when a player touches the ground. + * + * @param client Client index. + */ +forward void Movement_OnStartTouchGround(int client); + +/** + * Called when a player leaves the ground. + * + * @param client Client index. + * @param jumped Whether player jumped to leave ground. + * @param ladderJump Whether player jumped from a ladder. + * @param jumpbug Whether player performed a jumpbug. + */ +forward void Movement_OnStopTouchGround(int client, bool jumped, bool ladderJump, bool jumpbug); + +/** + * Called when a player starts ducking. + * + * @param client Client index. + */ +forward void Movement_OnStartDucking(int client); + +/** + * Called when a player stops ducking. + * + * @param client Client index. + */ +forward void Movement_OnStopDucking(int client); + +/** + * Called when a player jumps (player_jump event), including 'jumpbugs'. + * Setting velocity when this is called may not be effective. + * + * @param client Client index. + * @param jumpbug Whether player 'jumpbugged'. + */ +forward void Movement_OnPlayerJump(int client, bool jumpbug); + +/** + * Called before PlayerMove movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnPlayerMovePre(int client, float origin[3], float velocity[3]); + +/** + * Called after PlayerMove movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnPlayerMovePost(int client, float origin[3], float velocity[3]); + +/** + * Called before Duck movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnDuckPre(int client, float origin[3], float velocity[3]); + +/** + * Called after Duck movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnDuckPost(int client, float origin[3], float velocity[3]); + +/** + * Called before LadderMove movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnLadderMovePre(int client, float origin[3], float velocity[3]); + +/** + * Called after LadderMove movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnLadderMovePost(int client, float origin[3], float velocity[3]); + +/** + * Called before FullLadderMove movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnFullLadderMovePre(int client, float origin[3], float velocity[3]); + +/** + * Called after FullLadderMove movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnFullLadderMovePost(int client, float origin[3], float velocity[3]); + +/** + * Called after the player jumps, but before jumping stamina is applied and takeoff variables are not set yet. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnJumpPre(int client, float origin[3], float velocity[3]); + +/** + * Called after the player jumps and after jumping stamina is applied and takeoff variables are already set here. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnJumpPost(int client, float origin[3], float velocity[3]); + +/** + * Called before AirAccelerate movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnAirAcceleratePre(int client, float origin[3], float velocity[3]); + +/** + * Called after AirAccelerate movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnAirAcceleratePost(int client, float origin[3], float velocity[3]); + +/** + * Called before WalkMove movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnWalkMovePre(int client, float origin[3], float velocity[3]); + +/** + * Called after WalkMove movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnWalkMovePost(int client, float origin[3], float velocity[3]); + +/** + * Called before CategorizePosition movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnCategorizePositionPre(int client, float origin[3], float velocity[3]); + +/** + * Called after CategorizePosition movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnCategorizePositionPost(int client, float origin[3], float velocity[3]); + +// =====[ NATIVES ]===== + +/** + * Gets whether a player's last takeoff was a jump. + * + * @param client Client index. + * @return Whether player's last takeoff was a jump. + */ +native bool Movement_GetJumped(int client); + +/** + * Gets whether a player's last takeoff was a perfect bunnyhop. + * + * @param client Client index. + * @return Whether player's last takeoff was a perfect bunnyhop. + */ +native bool Movement_GetHitPerf(int client); + +/** + * Gets a player's origin at the time of their last takeoff. + * + * @param client Client index. + * @param result Resultant vector. + */ +native void Movement_GetTakeoffOrigin(int client, float result[3]); + +/** + * Gets a player's velocity at the time of their last takeoff. + * + * If sv_enablebunnyhopping is 0, CS:GO may adjust the player's + * velocity after the takeoff velocity has already been measured. + * + * @param client Client index. + * @param result Resultant vector. + */ +native void Movement_GetTakeoffVelocity(int client, float result[3]); + +/** + * Gets a player's horizontal speed at the time of their last takeoff. + * + * If sv_enablebunnyhopping is 0, CS:GO may adjust the player's + * velocity after the takeoff velocity has already been measured. + * + * @param client Client index. + * @return Player's last takeoff speed. + */ +native float Movement_GetTakeoffSpeed(int client); + +/** + * Gets a player's 'tickcount' at the time of their last takeoff. + * + * @param client Client index. + * @return Player's last takeoff 'tickcount'. + */ +native int Movement_GetTakeoffTick(int client); + +/** + * Gets a player's 'cmdnum' at the time of their last takeoff. + * + * @param client Client index. + * @return Player's last takeoff 'cmdnum'. + */ +native int Movement_GetTakeoffCmdNum(int client); + +/** + * Gets a player's origin at the time of their last landing with the distbug fixed. + * + * @param client Client index. + * @param result Resultant vector. + */ +native void Movement_GetNobugLandingOrigin(int client, float result[3]); + +/** + * Gets a player's origin at the time of their last landing. + * + * @param client Client index. + * @param result Resultant vector. + */ +native void Movement_GetLandingOrigin(int client, float result[3]); + +/** + * Gets a player's velocity at the time of their last landing. + * + * @param client Client index. + * @param result Resultant vector. + */ +native void Movement_GetLandingVelocity(int client, float result[3]); + +/** + * Gets a player's horizontal speed at the time of their last landing. + * + * @param client Client index. + * @return Last landing speed of the player (horizontal). + */ +native float Movement_GetLandingSpeed(int client); + +/** + * Gets a player's 'tickcount' at the time of their last landing. + * + * @param client Client index. + * @return Player's last landing 'tickcount'. + */ +native int Movement_GetLandingTick(int client); + +/** + * Gets a player's 'cmdnum' at the time of their last landing. + * + * @param client Client index. + * @return Player's last landing 'cmdnum'. + */ +native int Movement_GetLandingCmdNum(int client); + +/** + * Gets whether a player is turning their aim horizontally. + * + * @param client Client index. + * @return Whether player is turning their aim horizontally. + */ +native bool Movement_GetTurning(int client); + +/** + * Gets whether a player is turning their aim left. + * + * @param client Client index. + * @return Whether player is turning their aim left. + */ +native bool Movement_GetTurningLeft(int client); + +/** + * Gets whether a player is turning their aim right. + * + * @param client Client index. + * @return Whether player is turning their aim right. + */ +native bool Movement_GetTurningRight(int client); + +/** + * Gets result of CCSPlayer::GetPlayerMaxSpeed(client), which + * is the player's max speed as limited by their weapon. + * + * @param client Client index. + * @return Player's max speed as limited by their weapon. + */ +native float Movement_GetMaxSpeed(int client); + +/** + * Gets whether a player duckbugged on this tick. + * + * @param client Client index. + * @return Whether a player duckbugged on this tick. + */ +native bool Movement_GetDuckbugged(int client); + +/** + * Gets whether a player jumpbugged on this tick. + * + * @param client Client index. + * @return Whether a player jumpbugged on this tick. + */ +native bool Movement_GetJumpbugged(int client); + +/** + * Get the player's origin during movement processing. + * + * @param client Client index. + * @param result Resultant vector. + */ +native void Movement_GetProcessingOrigin(int client, float result[3]); + +/** + * Get the player's velocity during movement processing. + * + * @param client Param description + * @param result Resultant vector. + */ +native void Movement_GetProcessingVelocity(int client, float result[3]); + +/** + * Set the player's takeoff origin. + * + * @param client Client index. + * @param origin Desired origin. + */ +native void Movement_SetTakeoffOrigin(int client, float origin[3]); + +/** + * Set the player's takeoff velocity. + * + * @param client Client index. + * @param origin Desired velocity. + */ +native void Movement_SetTakeoffVelocity(int client, float velocity[3]); + +/** + * Set the player's landing origin. + * + * @param client Client index. + * @param origin Desired origin. + */ +native void Movement_SetLandingOrigin(int client, float origin[3]); + +/** + * Set the player's landing velocity. + * + * @param client Client index. + * @param origin Desired velocity. + */ +native void Movement_SetLandingVelocity(int client, float velocity[3]); + +// =====[ METHODMAP ]===== + +methodmap MovementAPIPlayer < MovementPlayer { + + public MovementAPIPlayer(int client) { + return view_as(MovementPlayer(client)); + } + + property bool Jumped { + public get() { + return Movement_GetJumped(this.ID); + } + } + + property bool HitPerf { + public get() { + return Movement_GetHitPerf(this.ID); + } + } + + public void GetTakeoffOrigin(float buffer[3]) { + Movement_GetTakeoffOrigin(this.ID, buffer); + } + + public void GetTakeoffVelocity(float buffer[3]) { + Movement_GetTakeoffVelocity(this.ID, buffer); + } + + public void SetTakeoffOrigin(float buffer[3]) + { + Movement_SetTakeoffOrigin(this.ID, buffer); + } + + public void SetTakeoffVelocity(float buffer[3]) + { + Movement_SetTakeoffVelocity(this.ID, buffer); + } + + property float TakeoffSpeed { + public get() { + return Movement_GetTakeoffSpeed(this.ID); + } + } + + property int TakeoffTick { + public get() { + return Movement_GetTakeoffTick(this.ID); + } + } + + property int TakeoffCmdNum { + public get() { + return Movement_GetTakeoffCmdNum(this.ID); + } + } + + public void GetLandingOrigin(float buffer[3]) { + Movement_GetLandingOrigin(this.ID, buffer); + } + + public void GetLandingVelocity(float buffer[3]) { + Movement_GetLandingVelocity(this.ID, buffer); + } + + public void SetLandingOrigin(float buffer[3]) + { + Movement_SetLandingOrigin(this.ID, buffer); + } + + public void SetLandingVelocity(float buffer[3]) + { + Movement_SetLandingVelocity(this.ID, buffer); + } + + property float LandingSpeed { + public get() { + return Movement_GetLandingSpeed(this.ID); + } + } + + property int LandingTick { + public get() { + return Movement_GetLandingTick(this.ID); + } + } + + property int LandingCmdNum { + public get() { + return Movement_GetLandingCmdNum(this.ID); + } + } + + property bool Turning { + public get() { + return Movement_GetTurning(this.ID); + } + } + + property bool TurningLeft { + public get() { + return Movement_GetTurningLeft(this.ID); + } + } + + property bool TurningRight { + public get() { + return Movement_GetTurningRight(this.ID); + } + } + + property float MaxSpeed { + public get() { + return Movement_GetMaxSpeed(this.ID); + } + } + + public void GetProcessingVelocity(float buffer[3]) + { + Movement_GetProcessingVelocity(this.ID, buffer); + } + + public void GetProcessingOrigin(float buffer[3]) + { + Movement_GetProcessingOrigin(this.ID, buffer); + } +} + + + +// =====[ DEPENDENCY ]===== + +public SharedPlugin __pl_movementapi = +{ + name = "movementapi", + file = "movementapi.smx", + #if defined REQUIRE_PLUGIN + required = 1, + #else + required = 0, + #endif +}; + +#if !defined REQUIRE_PLUGIN +public void __pl_movementapi_SetNTVOptional() +{ + MarkNativeAsOptional("Movement_GetJumped"); + MarkNativeAsOptional("Movement_GetHitPerf"); + MarkNativeAsOptional("Movement_GetTakeoffOrigin"); + MarkNativeAsOptional("Movement_GetTakeoffVelocity"); + MarkNativeAsOptional("Movement_GetTakeoffSpeed"); + MarkNativeAsOptional("Movement_GetTakeoffTick"); + MarkNativeAsOptional("Movement_GetTakeoffCmdNum"); + MarkNativeAsOptional("Movement_GetLandingOrigin"); + MarkNativeAsOptional("Movement_GetLandingVelocity"); + MarkNativeAsOptional("Movement_GetLandingSpeed"); + MarkNativeAsOptional("Movement_GetLandingTick"); + MarkNativeAsOptional("Movement_GetLandingCmdNum"); + MarkNativeAsOptional("Movement_GetTurning"); + MarkNativeAsOptional("Movement_GetTurningLeft"); + MarkNativeAsOptional("Movement_GetTurningRight"); + MarkNativeAsOptional("Movement_GetMaxSpeed"); + MarkNativeAsOptional("Movement_GetProcessingOrigin"); + MarkNativeAsOptional("Movement_GetProcessingVelocity"); + MarkNativeAsOptional("Movement_SetTakeoffOrigin"); + MarkNativeAsOptional("Movement_SetTakeoffVelocity"); + MarkNativeAsOptional("Movement_SetLandingOrigin"); + MarkNativeAsOptional("Movement_SetLandingVelocity"); +} +#endif From ce3faf242c02c5042bc784705b17bd8926b3b459 Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Sun, 15 Jan 2023 03:32:26 +0100 Subject: [PATCH 26/47] Fix EOL --- .../scripting/include/movementapi.inc | 1326 ++++++++--------- 1 file changed, 663 insertions(+), 663 deletions(-) diff --git a/addons/sourcemod/scripting/include/movementapi.inc b/addons/sourcemod/scripting/include/movementapi.inc index 0bf592bc..45ee2637 100644 --- a/addons/sourcemod/scripting/include/movementapi.inc +++ b/addons/sourcemod/scripting/include/movementapi.inc @@ -1,663 +1,663 @@ -/* - MovementAPI Plugin Include - - Website: https://github.com/danzayau/MovementAPI -*/ - -#if defined _movementapi_included_ - #endinput -#endif -#define _movementapi_included_ - -#include - - - -/* - Terminology - - Takeoff - Becoming airborne, including jumping, falling, getting off a ladder and leaving noclip. - - Landing - Leaving the air, including landing on the ground, grabbing a ladder and entering noclip. - - Perfect Bunnyhop (Perf) - When the player has jumped in the tick after landing and keeps their speed. - - Duckbug/Crouchbug - When the player sucessfully lands due to uncrouching from mid air and not by falling - down. This causes no stamina loss or fall damage upon landing. - - Jumpbug - This is achieved by duckbugging and jumping at the same time. The player is never seen - as 'on ground' when bunnyhopping from a tick by tick perspective. A jumpbug inherits - the same behavior as a duckbug/crouchbug, along with its effects such as maintaining - speed due to no stamina loss. - - Distbug - Landing behavior varies depending on whether the player lands close to the edge of a - block or not: - - 1. If the player lands close to the edge of a block, this causes the jump duration to - be one tick longer and the player can "slide" on the ground during the landing tick, - using the position post-tick as landing position becomes inaccurate. - - 2. On the other hand, if the player does not land close to the edge, the player will - be considered on the ground one tick earlier, using this position as landing position - is not accurate as the player has yet to be fully on the ground. - - In scenario 1, GetNobugLandingOrigin calculates the correct landing position of the - player before the sliding effect takes effect. - - In scenario 2, GetNobugLandingOrigin attempts to extrapolate the player's fully on - ground position to make landing positions consistent across scenarios. -*/ - - - -// =====[ FORWARDS ]===== - -/** - * Called when a player's movetype changes. - * - * @param client Client index. - * @param oldMovetype Player's old movetype. - * @param newMovetype Player's new movetype. - */ -forward void Movement_OnChangeMovetype(int client, MoveType oldMovetype, MoveType newMovetype); - -/** - * Called when a player touches the ground. - * - * @param client Client index. - */ -forward void Movement_OnStartTouchGround(int client); - -/** - * Called when a player leaves the ground. - * - * @param client Client index. - * @param jumped Whether player jumped to leave ground. - * @param ladderJump Whether player jumped from a ladder. - * @param jumpbug Whether player performed a jumpbug. - */ -forward void Movement_OnStopTouchGround(int client, bool jumped, bool ladderJump, bool jumpbug); - -/** - * Called when a player starts ducking. - * - * @param client Client index. - */ -forward void Movement_OnStartDucking(int client); - -/** - * Called when a player stops ducking. - * - * @param client Client index. - */ -forward void Movement_OnStopDucking(int client); - -/** - * Called when a player jumps (player_jump event), including 'jumpbugs'. - * Setting velocity when this is called may not be effective. - * - * @param client Client index. - * @param jumpbug Whether player 'jumpbugged'. - */ -forward void Movement_OnPlayerJump(int client, bool jumpbug); - -/** - * Called before PlayerMove movement function is called. - * Modifying origin or velocity parameters will change player's origin and velocity accordingly. - * - * @param client Client index. - * @param origin Player origin. - * @param velocity Player velocity. - * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. - */ -forward Action Movement_OnPlayerMovePre(int client, float origin[3], float velocity[3]); - -/** - * Called after PlayerMove movement function is called. - * Modifying origin or velocity parameters will change player's origin and velocity accordingly. - * - * @param client Client index. - * @param origin Player origin. - * @param velocity Player velocity. - * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. - */ -forward Action Movement_OnPlayerMovePost(int client, float origin[3], float velocity[3]); - -/** - * Called before Duck movement function is called. - * Modifying origin or velocity parameters will change player's origin and velocity accordingly. - * - * @param client Client index. - * @param origin Player origin. - * @param velocity Player velocity. - * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. - */ -forward Action Movement_OnDuckPre(int client, float origin[3], float velocity[3]); - -/** - * Called after Duck movement function is called. - * Modifying origin or velocity parameters will change player's origin and velocity accordingly. - * - * @param client Client index. - * @param origin Player origin. - * @param velocity Player velocity. - * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. - */ -forward Action Movement_OnDuckPost(int client, float origin[3], float velocity[3]); - -/** - * Called before LadderMove movement function is called. - * Modifying origin or velocity parameters will change player's origin and velocity accordingly. - * - * @param client Client index. - * @param origin Player origin. - * @param velocity Player velocity. - * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. - */ -forward Action Movement_OnLadderMovePre(int client, float origin[3], float velocity[3]); - -/** - * Called after LadderMove movement function is called. - * Modifying origin or velocity parameters will change player's origin and velocity accordingly. - * - * @param client Client index. - * @param origin Player origin. - * @param velocity Player velocity. - * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. - */ -forward Action Movement_OnLadderMovePost(int client, float origin[3], float velocity[3]); - -/** - * Called before FullLadderMove movement function is called. - * Modifying origin or velocity parameters will change player's origin and velocity accordingly. - * - * @param client Client index. - * @param origin Player origin. - * @param velocity Player velocity. - * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. - */ -forward Action Movement_OnFullLadderMovePre(int client, float origin[3], float velocity[3]); - -/** - * Called after FullLadderMove movement function is called. - * Modifying origin or velocity parameters will change player's origin and velocity accordingly. - * - * @param client Client index. - * @param origin Player origin. - * @param velocity Player velocity. - * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. - */ -forward Action Movement_OnFullLadderMovePost(int client, float origin[3], float velocity[3]); - -/** - * Called after the player jumps, but before jumping stamina is applied and takeoff variables are not set yet. - * Modifying origin or velocity parameters will change player's origin and velocity accordingly. - * - * @param client Client index. - * @param origin Player origin. - * @param velocity Player velocity. - * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. - */ -forward Action Movement_OnJumpPre(int client, float origin[3], float velocity[3]); - -/** - * Called after the player jumps and after jumping stamina is applied and takeoff variables are already set here. - * Modifying origin or velocity parameters will change player's origin and velocity accordingly. - * - * @param client Client index. - * @param origin Player origin. - * @param velocity Player velocity. - * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. - */ -forward Action Movement_OnJumpPost(int client, float origin[3], float velocity[3]); - -/** - * Called before AirAccelerate movement function is called. - * Modifying origin or velocity parameters will change player's origin and velocity accordingly. - * - * @param client Client index. - * @param origin Player origin. - * @param velocity Player velocity. - * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. - */ -forward Action Movement_OnAirAcceleratePre(int client, float origin[3], float velocity[3]); - -/** - * Called after AirAccelerate movement function is called. - * Modifying origin or velocity parameters will change player's origin and velocity accordingly. - * - * @param client Client index. - * @param origin Player origin. - * @param velocity Player velocity. - * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. - */ -forward Action Movement_OnAirAcceleratePost(int client, float origin[3], float velocity[3]); - -/** - * Called before WalkMove movement function is called. - * Modifying origin or velocity parameters will change player's origin and velocity accordingly. - * - * @param client Client index. - * @param origin Player origin. - * @param velocity Player velocity. - * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. - */ -forward Action Movement_OnWalkMovePre(int client, float origin[3], float velocity[3]); - -/** - * Called after WalkMove movement function is called. - * Modifying origin or velocity parameters will change player's origin and velocity accordingly. - * - * @param client Client index. - * @param origin Player origin. - * @param velocity Player velocity. - * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. - */ -forward Action Movement_OnWalkMovePost(int client, float origin[3], float velocity[3]); - -/** - * Called before CategorizePosition movement function is called. - * Modifying origin or velocity parameters will change player's origin and velocity accordingly. - * - * @param client Client index. - * @param origin Player origin. - * @param velocity Player velocity. - * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. - */ -forward Action Movement_OnCategorizePositionPre(int client, float origin[3], float velocity[3]); - -/** - * Called after CategorizePosition movement function is called. - * Modifying origin or velocity parameters will change player's origin and velocity accordingly. - * - * @param client Client index. - * @param origin Player origin. - * @param velocity Player velocity. - * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. - */ -forward Action Movement_OnCategorizePositionPost(int client, float origin[3], float velocity[3]); - -// =====[ NATIVES ]===== - -/** - * Gets whether a player's last takeoff was a jump. - * - * @param client Client index. - * @return Whether player's last takeoff was a jump. - */ -native bool Movement_GetJumped(int client); - -/** - * Gets whether a player's last takeoff was a perfect bunnyhop. - * - * @param client Client index. - * @return Whether player's last takeoff was a perfect bunnyhop. - */ -native bool Movement_GetHitPerf(int client); - -/** - * Gets a player's origin at the time of their last takeoff. - * - * @param client Client index. - * @param result Resultant vector. - */ -native void Movement_GetTakeoffOrigin(int client, float result[3]); - -/** - * Gets a player's velocity at the time of their last takeoff. - * - * If sv_enablebunnyhopping is 0, CS:GO may adjust the player's - * velocity after the takeoff velocity has already been measured. - * - * @param client Client index. - * @param result Resultant vector. - */ -native void Movement_GetTakeoffVelocity(int client, float result[3]); - -/** - * Gets a player's horizontal speed at the time of their last takeoff. - * - * If sv_enablebunnyhopping is 0, CS:GO may adjust the player's - * velocity after the takeoff velocity has already been measured. - * - * @param client Client index. - * @return Player's last takeoff speed. - */ -native float Movement_GetTakeoffSpeed(int client); - -/** - * Gets a player's 'tickcount' at the time of their last takeoff. - * - * @param client Client index. - * @return Player's last takeoff 'tickcount'. - */ -native int Movement_GetTakeoffTick(int client); - -/** - * Gets a player's 'cmdnum' at the time of their last takeoff. - * - * @param client Client index. - * @return Player's last takeoff 'cmdnum'. - */ -native int Movement_GetTakeoffCmdNum(int client); - -/** - * Gets a player's origin at the time of their last landing with the distbug fixed. - * - * @param client Client index. - * @param result Resultant vector. - */ -native void Movement_GetNobugLandingOrigin(int client, float result[3]); - -/** - * Gets a player's origin at the time of their last landing. - * - * @param client Client index. - * @param result Resultant vector. - */ -native void Movement_GetLandingOrigin(int client, float result[3]); - -/** - * Gets a player's velocity at the time of their last landing. - * - * @param client Client index. - * @param result Resultant vector. - */ -native void Movement_GetLandingVelocity(int client, float result[3]); - -/** - * Gets a player's horizontal speed at the time of their last landing. - * - * @param client Client index. - * @return Last landing speed of the player (horizontal). - */ -native float Movement_GetLandingSpeed(int client); - -/** - * Gets a player's 'tickcount' at the time of their last landing. - * - * @param client Client index. - * @return Player's last landing 'tickcount'. - */ -native int Movement_GetLandingTick(int client); - -/** - * Gets a player's 'cmdnum' at the time of their last landing. - * - * @param client Client index. - * @return Player's last landing 'cmdnum'. - */ -native int Movement_GetLandingCmdNum(int client); - -/** - * Gets whether a player is turning their aim horizontally. - * - * @param client Client index. - * @return Whether player is turning their aim horizontally. - */ -native bool Movement_GetTurning(int client); - -/** - * Gets whether a player is turning their aim left. - * - * @param client Client index. - * @return Whether player is turning their aim left. - */ -native bool Movement_GetTurningLeft(int client); - -/** - * Gets whether a player is turning their aim right. - * - * @param client Client index. - * @return Whether player is turning their aim right. - */ -native bool Movement_GetTurningRight(int client); - -/** - * Gets result of CCSPlayer::GetPlayerMaxSpeed(client), which - * is the player's max speed as limited by their weapon. - * - * @param client Client index. - * @return Player's max speed as limited by their weapon. - */ -native float Movement_GetMaxSpeed(int client); - -/** - * Gets whether a player duckbugged on this tick. - * - * @param client Client index. - * @return Whether a player duckbugged on this tick. - */ -native bool Movement_GetDuckbugged(int client); - -/** - * Gets whether a player jumpbugged on this tick. - * - * @param client Client index. - * @return Whether a player jumpbugged on this tick. - */ -native bool Movement_GetJumpbugged(int client); - -/** - * Get the player's origin during movement processing. - * - * @param client Client index. - * @param result Resultant vector. - */ -native void Movement_GetProcessingOrigin(int client, float result[3]); - -/** - * Get the player's velocity during movement processing. - * - * @param client Param description - * @param result Resultant vector. - */ -native void Movement_GetProcessingVelocity(int client, float result[3]); - -/** - * Set the player's takeoff origin. - * - * @param client Client index. - * @param origin Desired origin. - */ -native void Movement_SetTakeoffOrigin(int client, float origin[3]); - -/** - * Set the player's takeoff velocity. - * - * @param client Client index. - * @param origin Desired velocity. - */ -native void Movement_SetTakeoffVelocity(int client, float velocity[3]); - -/** - * Set the player's landing origin. - * - * @param client Client index. - * @param origin Desired origin. - */ -native void Movement_SetLandingOrigin(int client, float origin[3]); - -/** - * Set the player's landing velocity. - * - * @param client Client index. - * @param origin Desired velocity. - */ -native void Movement_SetLandingVelocity(int client, float velocity[3]); - -// =====[ METHODMAP ]===== - -methodmap MovementAPIPlayer < MovementPlayer { - - public MovementAPIPlayer(int client) { - return view_as(MovementPlayer(client)); - } - - property bool Jumped { - public get() { - return Movement_GetJumped(this.ID); - } - } - - property bool HitPerf { - public get() { - return Movement_GetHitPerf(this.ID); - } - } - - public void GetTakeoffOrigin(float buffer[3]) { - Movement_GetTakeoffOrigin(this.ID, buffer); - } - - public void GetTakeoffVelocity(float buffer[3]) { - Movement_GetTakeoffVelocity(this.ID, buffer); - } - - public void SetTakeoffOrigin(float buffer[3]) - { - Movement_SetTakeoffOrigin(this.ID, buffer); - } - - public void SetTakeoffVelocity(float buffer[3]) - { - Movement_SetTakeoffVelocity(this.ID, buffer); - } - - property float TakeoffSpeed { - public get() { - return Movement_GetTakeoffSpeed(this.ID); - } - } - - property int TakeoffTick { - public get() { - return Movement_GetTakeoffTick(this.ID); - } - } - - property int TakeoffCmdNum { - public get() { - return Movement_GetTakeoffCmdNum(this.ID); - } - } - - public void GetLandingOrigin(float buffer[3]) { - Movement_GetLandingOrigin(this.ID, buffer); - } - - public void GetLandingVelocity(float buffer[3]) { - Movement_GetLandingVelocity(this.ID, buffer); - } - - public void SetLandingOrigin(float buffer[3]) - { - Movement_SetLandingOrigin(this.ID, buffer); - } - - public void SetLandingVelocity(float buffer[3]) - { - Movement_SetLandingVelocity(this.ID, buffer); - } - - property float LandingSpeed { - public get() { - return Movement_GetLandingSpeed(this.ID); - } - } - - property int LandingTick { - public get() { - return Movement_GetLandingTick(this.ID); - } - } - - property int LandingCmdNum { - public get() { - return Movement_GetLandingCmdNum(this.ID); - } - } - - property bool Turning { - public get() { - return Movement_GetTurning(this.ID); - } - } - - property bool TurningLeft { - public get() { - return Movement_GetTurningLeft(this.ID); - } - } - - property bool TurningRight { - public get() { - return Movement_GetTurningRight(this.ID); - } - } - - property float MaxSpeed { - public get() { - return Movement_GetMaxSpeed(this.ID); - } - } - - public void GetProcessingVelocity(float buffer[3]) - { - Movement_GetProcessingVelocity(this.ID, buffer); - } - - public void GetProcessingOrigin(float buffer[3]) - { - Movement_GetProcessingOrigin(this.ID, buffer); - } -} - - - -// =====[ DEPENDENCY ]===== - -public SharedPlugin __pl_movementapi = -{ - name = "movementapi", - file = "movementapi.smx", - #if defined REQUIRE_PLUGIN - required = 1, - #else - required = 0, - #endif -}; - -#if !defined REQUIRE_PLUGIN -public void __pl_movementapi_SetNTVOptional() -{ - MarkNativeAsOptional("Movement_GetJumped"); - MarkNativeAsOptional("Movement_GetHitPerf"); - MarkNativeAsOptional("Movement_GetTakeoffOrigin"); - MarkNativeAsOptional("Movement_GetTakeoffVelocity"); - MarkNativeAsOptional("Movement_GetTakeoffSpeed"); - MarkNativeAsOptional("Movement_GetTakeoffTick"); - MarkNativeAsOptional("Movement_GetTakeoffCmdNum"); - MarkNativeAsOptional("Movement_GetLandingOrigin"); - MarkNativeAsOptional("Movement_GetLandingVelocity"); - MarkNativeAsOptional("Movement_GetLandingSpeed"); - MarkNativeAsOptional("Movement_GetLandingTick"); - MarkNativeAsOptional("Movement_GetLandingCmdNum"); - MarkNativeAsOptional("Movement_GetTurning"); - MarkNativeAsOptional("Movement_GetTurningLeft"); - MarkNativeAsOptional("Movement_GetTurningRight"); - MarkNativeAsOptional("Movement_GetMaxSpeed"); - MarkNativeAsOptional("Movement_GetProcessingOrigin"); - MarkNativeAsOptional("Movement_GetProcessingVelocity"); - MarkNativeAsOptional("Movement_SetTakeoffOrigin"); - MarkNativeAsOptional("Movement_SetTakeoffVelocity"); - MarkNativeAsOptional("Movement_SetLandingOrigin"); - MarkNativeAsOptional("Movement_SetLandingVelocity"); -} -#endif +/* + MovementAPI Plugin Include + + Website: https://github.com/danzayau/MovementAPI +*/ + +#if defined _movementapi_included_ + #endinput +#endif +#define _movementapi_included_ + +#include + + + +/* + Terminology + + Takeoff + Becoming airborne, including jumping, falling, getting off a ladder and leaving noclip. + + Landing + Leaving the air, including landing on the ground, grabbing a ladder and entering noclip. + + Perfect Bunnyhop (Perf) + When the player has jumped in the tick after landing and keeps their speed. + + Duckbug/Crouchbug + When the player sucessfully lands due to uncrouching from mid air and not by falling + down. This causes no stamina loss or fall damage upon landing. + + Jumpbug + This is achieved by duckbugging and jumping at the same time. The player is never seen + as 'on ground' when bunnyhopping from a tick by tick perspective. A jumpbug inherits + the same behavior as a duckbug/crouchbug, along with its effects such as maintaining + speed due to no stamina loss. + + Distbug + Landing behavior varies depending on whether the player lands close to the edge of a + block or not: + + 1. If the player lands close to the edge of a block, this causes the jump duration to + be one tick longer and the player can "slide" on the ground during the landing tick, + using the position post-tick as landing position becomes inaccurate. + + 2. On the other hand, if the player does not land close to the edge, the player will + be considered on the ground one tick earlier, using this position as landing position + is not accurate as the player has yet to be fully on the ground. + + In scenario 1, GetNobugLandingOrigin calculates the correct landing position of the + player before the sliding effect takes effect. + + In scenario 2, GetNobugLandingOrigin attempts to extrapolate the player's fully on + ground position to make landing positions consistent across scenarios. +*/ + + + +// =====[ FORWARDS ]===== + +/** + * Called when a player's movetype changes. + * + * @param client Client index. + * @param oldMovetype Player's old movetype. + * @param newMovetype Player's new movetype. + */ +forward void Movement_OnChangeMovetype(int client, MoveType oldMovetype, MoveType newMovetype); + +/** + * Called when a player touches the ground. + * + * @param client Client index. + */ +forward void Movement_OnStartTouchGround(int client); + +/** + * Called when a player leaves the ground. + * + * @param client Client index. + * @param jumped Whether player jumped to leave ground. + * @param ladderJump Whether player jumped from a ladder. + * @param jumpbug Whether player performed a jumpbug. + */ +forward void Movement_OnStopTouchGround(int client, bool jumped, bool ladderJump, bool jumpbug); + +/** + * Called when a player starts ducking. + * + * @param client Client index. + */ +forward void Movement_OnStartDucking(int client); + +/** + * Called when a player stops ducking. + * + * @param client Client index. + */ +forward void Movement_OnStopDucking(int client); + +/** + * Called when a player jumps (player_jump event), including 'jumpbugs'. + * Setting velocity when this is called may not be effective. + * + * @param client Client index. + * @param jumpbug Whether player 'jumpbugged'. + */ +forward void Movement_OnPlayerJump(int client, bool jumpbug); + +/** + * Called before PlayerMove movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnPlayerMovePre(int client, float origin[3], float velocity[3]); + +/** + * Called after PlayerMove movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnPlayerMovePost(int client, float origin[3], float velocity[3]); + +/** + * Called before Duck movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnDuckPre(int client, float origin[3], float velocity[3]); + +/** + * Called after Duck movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnDuckPost(int client, float origin[3], float velocity[3]); + +/** + * Called before LadderMove movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnLadderMovePre(int client, float origin[3], float velocity[3]); + +/** + * Called after LadderMove movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnLadderMovePost(int client, float origin[3], float velocity[3]); + +/** + * Called before FullLadderMove movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnFullLadderMovePre(int client, float origin[3], float velocity[3]); + +/** + * Called after FullLadderMove movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnFullLadderMovePost(int client, float origin[3], float velocity[3]); + +/** + * Called after the player jumps, but before jumping stamina is applied and takeoff variables are not set yet. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnJumpPre(int client, float origin[3], float velocity[3]); + +/** + * Called after the player jumps and after jumping stamina is applied and takeoff variables are already set here. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnJumpPost(int client, float origin[3], float velocity[3]); + +/** + * Called before AirAccelerate movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnAirAcceleratePre(int client, float origin[3], float velocity[3]); + +/** + * Called after AirAccelerate movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnAirAcceleratePost(int client, float origin[3], float velocity[3]); + +/** + * Called before WalkMove movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnWalkMovePre(int client, float origin[3], float velocity[3]); + +/** + * Called after WalkMove movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnWalkMovePost(int client, float origin[3], float velocity[3]); + +/** + * Called before CategorizePosition movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnCategorizePositionPre(int client, float origin[3], float velocity[3]); + +/** + * Called after CategorizePosition movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnCategorizePositionPost(int client, float origin[3], float velocity[3]); + +// =====[ NATIVES ]===== + +/** + * Gets whether a player's last takeoff was a jump. + * + * @param client Client index. + * @return Whether player's last takeoff was a jump. + */ +native bool Movement_GetJumped(int client); + +/** + * Gets whether a player's last takeoff was a perfect bunnyhop. + * + * @param client Client index. + * @return Whether player's last takeoff was a perfect bunnyhop. + */ +native bool Movement_GetHitPerf(int client); + +/** + * Gets a player's origin at the time of their last takeoff. + * + * @param client Client index. + * @param result Resultant vector. + */ +native void Movement_GetTakeoffOrigin(int client, float result[3]); + +/** + * Gets a player's velocity at the time of their last takeoff. + * + * If sv_enablebunnyhopping is 0, CS:GO may adjust the player's + * velocity after the takeoff velocity has already been measured. + * + * @param client Client index. + * @param result Resultant vector. + */ +native void Movement_GetTakeoffVelocity(int client, float result[3]); + +/** + * Gets a player's horizontal speed at the time of their last takeoff. + * + * If sv_enablebunnyhopping is 0, CS:GO may adjust the player's + * velocity after the takeoff velocity has already been measured. + * + * @param client Client index. + * @return Player's last takeoff speed. + */ +native float Movement_GetTakeoffSpeed(int client); + +/** + * Gets a player's 'tickcount' at the time of their last takeoff. + * + * @param client Client index. + * @return Player's last takeoff 'tickcount'. + */ +native int Movement_GetTakeoffTick(int client); + +/** + * Gets a player's 'cmdnum' at the time of their last takeoff. + * + * @param client Client index. + * @return Player's last takeoff 'cmdnum'. + */ +native int Movement_GetTakeoffCmdNum(int client); + +/** + * Gets a player's origin at the time of their last landing with the distbug fixed. + * + * @param client Client index. + * @param result Resultant vector. + */ +native void Movement_GetNobugLandingOrigin(int client, float result[3]); + +/** + * Gets a player's origin at the time of their last landing. + * + * @param client Client index. + * @param result Resultant vector. + */ +native void Movement_GetLandingOrigin(int client, float result[3]); + +/** + * Gets a player's velocity at the time of their last landing. + * + * @param client Client index. + * @param result Resultant vector. + */ +native void Movement_GetLandingVelocity(int client, float result[3]); + +/** + * Gets a player's horizontal speed at the time of their last landing. + * + * @param client Client index. + * @return Last landing speed of the player (horizontal). + */ +native float Movement_GetLandingSpeed(int client); + +/** + * Gets a player's 'tickcount' at the time of their last landing. + * + * @param client Client index. + * @return Player's last landing 'tickcount'. + */ +native int Movement_GetLandingTick(int client); + +/** + * Gets a player's 'cmdnum' at the time of their last landing. + * + * @param client Client index. + * @return Player's last landing 'cmdnum'. + */ +native int Movement_GetLandingCmdNum(int client); + +/** + * Gets whether a player is turning their aim horizontally. + * + * @param client Client index. + * @return Whether player is turning their aim horizontally. + */ +native bool Movement_GetTurning(int client); + +/** + * Gets whether a player is turning their aim left. + * + * @param client Client index. + * @return Whether player is turning their aim left. + */ +native bool Movement_GetTurningLeft(int client); + +/** + * Gets whether a player is turning their aim right. + * + * @param client Client index. + * @return Whether player is turning their aim right. + */ +native bool Movement_GetTurningRight(int client); + +/** + * Gets result of CCSPlayer::GetPlayerMaxSpeed(client), which + * is the player's max speed as limited by their weapon. + * + * @param client Client index. + * @return Player's max speed as limited by their weapon. + */ +native float Movement_GetMaxSpeed(int client); + +/** + * Gets whether a player duckbugged on this tick. + * + * @param client Client index. + * @return Whether a player duckbugged on this tick. + */ +native bool Movement_GetDuckbugged(int client); + +/** + * Gets whether a player jumpbugged on this tick. + * + * @param client Client index. + * @return Whether a player jumpbugged on this tick. + */ +native bool Movement_GetJumpbugged(int client); + +/** + * Get the player's origin during movement processing. + * + * @param client Client index. + * @param result Resultant vector. + */ +native void Movement_GetProcessingOrigin(int client, float result[3]); + +/** + * Get the player's velocity during movement processing. + * + * @param client Param description + * @param result Resultant vector. + */ +native void Movement_GetProcessingVelocity(int client, float result[3]); + +/** + * Set the player's takeoff origin. + * + * @param client Client index. + * @param origin Desired origin. + */ +native void Movement_SetTakeoffOrigin(int client, float origin[3]); + +/** + * Set the player's takeoff velocity. + * + * @param client Client index. + * @param origin Desired velocity. + */ +native void Movement_SetTakeoffVelocity(int client, float velocity[3]); + +/** + * Set the player's landing origin. + * + * @param client Client index. + * @param origin Desired origin. + */ +native void Movement_SetLandingOrigin(int client, float origin[3]); + +/** + * Set the player's landing velocity. + * + * @param client Client index. + * @param origin Desired velocity. + */ +native void Movement_SetLandingVelocity(int client, float velocity[3]); + +// =====[ METHODMAP ]===== + +methodmap MovementAPIPlayer < MovementPlayer { + + public MovementAPIPlayer(int client) { + return view_as(MovementPlayer(client)); + } + + property bool Jumped { + public get() { + return Movement_GetJumped(this.ID); + } + } + + property bool HitPerf { + public get() { + return Movement_GetHitPerf(this.ID); + } + } + + public void GetTakeoffOrigin(float buffer[3]) { + Movement_GetTakeoffOrigin(this.ID, buffer); + } + + public void GetTakeoffVelocity(float buffer[3]) { + Movement_GetTakeoffVelocity(this.ID, buffer); + } + + public void SetTakeoffOrigin(float buffer[3]) + { + Movement_SetTakeoffOrigin(this.ID, buffer); + } + + public void SetTakeoffVelocity(float buffer[3]) + { + Movement_SetTakeoffVelocity(this.ID, buffer); + } + + property float TakeoffSpeed { + public get() { + return Movement_GetTakeoffSpeed(this.ID); + } + } + + property int TakeoffTick { + public get() { + return Movement_GetTakeoffTick(this.ID); + } + } + + property int TakeoffCmdNum { + public get() { + return Movement_GetTakeoffCmdNum(this.ID); + } + } + + public void GetLandingOrigin(float buffer[3]) { + Movement_GetLandingOrigin(this.ID, buffer); + } + + public void GetLandingVelocity(float buffer[3]) { + Movement_GetLandingVelocity(this.ID, buffer); + } + + public void SetLandingOrigin(float buffer[3]) + { + Movement_SetLandingOrigin(this.ID, buffer); + } + + public void SetLandingVelocity(float buffer[3]) + { + Movement_SetLandingVelocity(this.ID, buffer); + } + + property float LandingSpeed { + public get() { + return Movement_GetLandingSpeed(this.ID); + } + } + + property int LandingTick { + public get() { + return Movement_GetLandingTick(this.ID); + } + } + + property int LandingCmdNum { + public get() { + return Movement_GetLandingCmdNum(this.ID); + } + } + + property bool Turning { + public get() { + return Movement_GetTurning(this.ID); + } + } + + property bool TurningLeft { + public get() { + return Movement_GetTurningLeft(this.ID); + } + } + + property bool TurningRight { + public get() { + return Movement_GetTurningRight(this.ID); + } + } + + property float MaxSpeed { + public get() { + return Movement_GetMaxSpeed(this.ID); + } + } + + public void GetProcessingVelocity(float buffer[3]) + { + Movement_GetProcessingVelocity(this.ID, buffer); + } + + public void GetProcessingOrigin(float buffer[3]) + { + Movement_GetProcessingOrigin(this.ID, buffer); + } +} + + + +// =====[ DEPENDENCY ]===== + +public SharedPlugin __pl_movementapi = +{ + name = "movementapi", + file = "movementapi.smx", + #if defined REQUIRE_PLUGIN + required = 1, + #else + required = 0, + #endif +}; + +#if !defined REQUIRE_PLUGIN +public void __pl_movementapi_SetNTVOptional() +{ + MarkNativeAsOptional("Movement_GetJumped"); + MarkNativeAsOptional("Movement_GetHitPerf"); + MarkNativeAsOptional("Movement_GetTakeoffOrigin"); + MarkNativeAsOptional("Movement_GetTakeoffVelocity"); + MarkNativeAsOptional("Movement_GetTakeoffSpeed"); + MarkNativeAsOptional("Movement_GetTakeoffTick"); + MarkNativeAsOptional("Movement_GetTakeoffCmdNum"); + MarkNativeAsOptional("Movement_GetLandingOrigin"); + MarkNativeAsOptional("Movement_GetLandingVelocity"); + MarkNativeAsOptional("Movement_GetLandingSpeed"); + MarkNativeAsOptional("Movement_GetLandingTick"); + MarkNativeAsOptional("Movement_GetLandingCmdNum"); + MarkNativeAsOptional("Movement_GetTurning"); + MarkNativeAsOptional("Movement_GetTurningLeft"); + MarkNativeAsOptional("Movement_GetTurningRight"); + MarkNativeAsOptional("Movement_GetMaxSpeed"); + MarkNativeAsOptional("Movement_GetProcessingOrigin"); + MarkNativeAsOptional("Movement_GetProcessingVelocity"); + MarkNativeAsOptional("Movement_SetTakeoffOrigin"); + MarkNativeAsOptional("Movement_SetTakeoffVelocity"); + MarkNativeAsOptional("Movement_SetLandingOrigin"); + MarkNativeAsOptional("Movement_SetLandingVelocity"); +} +#endif From e38dd9e4c48f6ef4cc02932c93bc71fa0531bf52 Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Sun, 15 Jan 2023 03:44:24 +0100 Subject: [PATCH 27/47] fix linux gamedata --- addons/sourcemod/gamedata/gokz-core.games.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/sourcemod/gamedata/gokz-core.games.txt b/addons/sourcemod/gamedata/gokz-core.games.txt index ae25eb3a..ef6e9aef 100644 --- a/addons/sourcemod/gamedata/gokz-core.games.txt +++ b/addons/sourcemod/gamedata/gokz-core.games.txt @@ -32,7 +32,7 @@ { "library" "server" "windows" "\x55\x8B\xEC\x81\xEC\x8C\x00\x00\x00\x57\x8B\xF9\x8B\x87\x54\x0E\x00\x00" - "linux" "\x55\x89\xE5\x56\x53\x83\xEC\x50\x8B\x5D\x08\x8B\x43\x08\xF3\x0F\x10\x80\xAC\x00\x00\x00\xF3\x0F\x11\x45\xEC" + "linux" "\x55\x89\xE5\x8B\x45\x08\x8B\x90\x54\x0E\x00\x00" } } From 0cbf07838388233f3fb03c021941bdb499146e39 Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Sun, 15 Jan 2023 03:52:09 +0100 Subject: [PATCH 28/47] Fix SKZ tickcount not being set --- addons/sourcemod/scripting/gokz-mode-simplekz.sp | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/sourcemod/scripting/gokz-mode-simplekz.sp b/addons/sourcemod/scripting/gokz-mode-simplekz.sp index 230614df..dea2c41b 100644 --- a/addons/sourcemod/scripting/gokz-mode-simplekz.sp +++ b/addons/sourcemod/scripting/gokz-mode-simplekz.sp @@ -187,6 +187,7 @@ public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3 gI_OldButtons[player.ID] = buttons; gI_OldFlags[player.ID] = GetEntityFlags(player.ID); gB_OldOnGround[player.ID] = player.OnGround; + gI_TickCount[player.ID] = tickcount; player.GetOrigin(gF_OldOrigin[player.ID]); player.GetEyeAngles(gF_OldAngles[player.ID]); player.GetVelocity(gF_OldVelocity[player.ID]); From 6e2d90871a3d022e2db266e07757cfcfd3a1a989 Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Wed, 25 Jan 2023 02:01:06 +0100 Subject: [PATCH 29/47] Add ambient sound volume control, rename map sound option to soundscape option --- .../sourcemod/gamedata/gokz-quiet.games.txt | 24 +++++ addons/sourcemod/scripting/gokz-quiet.sp | 3 + .../sourcemod/scripting/gokz-quiet/ambient.sp | 100 ++++++++++++++++++ .../sourcemod/scripting/gokz-quiet/options.sp | 20 ++-- .../scripting/gokz-quiet/soundscape.sp | 2 +- .../scripting/include/gokz/quiet.inc | 30 +++--- .../translations/gokz-quiet.phrases.txt | 21 ++-- cfg/sourcemod/gokz/options_menu_sorting.cfg | 3 +- 8 files changed, 170 insertions(+), 33 deletions(-) create mode 100644 addons/sourcemod/gamedata/gokz-quiet.games.txt create mode 100644 addons/sourcemod/scripting/gokz-quiet/ambient.sp diff --git a/addons/sourcemod/gamedata/gokz-quiet.games.txt b/addons/sourcemod/gamedata/gokz-quiet.games.txt new file mode 100644 index 00000000..5cd4fde8 --- /dev/null +++ b/addons/sourcemod/gamedata/gokz-quiet.games.txt @@ -0,0 +1,24 @@ +"Games" +{ + "csgo" + { + "Signatures" + { + "CGameClient::SendSound" + { + "library" "engine" + "windows" "\x55\x8B\xEC\x51\x56\x8B\xF1\x8B\x46\x04" + "linux" "\x55\x89\xE5\x57\x56\x53\x83\xEC\x4C\x8B\x5D\x08\x8B\x7D\x0C\x0F\xB6\x75\x10" + } + } + + "Offsets" + { + "CBaseClient::GetPlayerSlot" + { + "windows" "16" + "linux" "17" + } + } + } +} diff --git a/addons/sourcemod/scripting/gokz-quiet.sp b/addons/sourcemod/scripting/gokz-quiet.sp index 6e694d3a..196f8da1 100644 --- a/addons/sourcemod/scripting/gokz-quiet.sp +++ b/addons/sourcemod/scripting/gokz-quiet.sp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -27,6 +28,7 @@ public Plugin myinfo = #define UPDATER_URL GOKZ_UPDATER_BASE_URL..."gokz-quiet.txt" +#include "gokz-quiet/ambient.sp" #include "gokz-quiet/soundscape.sp" #include "gokz-quiet/hideplayers.sp" #include "gokz-quiet/falldamage.sp" @@ -44,6 +46,7 @@ public void OnPluginStart() { OnPluginStart_HidePlayers(); OnPluginStart_FallDamage(); + OnPluginStart_Ambient(); LoadTranslations("gokz-common.phrases"); LoadTranslations("gokz-quiet.phrases"); diff --git a/addons/sourcemod/scripting/gokz-quiet/ambient.sp b/addons/sourcemod/scripting/gokz-quiet/ambient.sp new file mode 100644 index 00000000..d138a5ff --- /dev/null +++ b/addons/sourcemod/scripting/gokz-quiet/ambient.sp @@ -0,0 +1,100 @@ +/* + Hide sound effect from ambient_generics. + Credit to Haze - https://github.com/Haze1337/Sound-Manager +*/ + +Handle getPlayerSlot; + +void OnPluginStart_Ambient() +{ + HookSendSound(); +} +static void HookSendSound() +{ + GameData gd = LoadGameConfigFile("gokz-quiet.games"); + + DynamicDetour sendSoundDetour = DHookCreateDetour(Address_Null, CallConv_THISCALL, ReturnType_Void, ThisPointer_Address); + DHookSetFromConf(sendSoundDetour, gd, SDKConf_Signature, "CGameClient::SendSound"); + DHookAddParam(sendSoundDetour, HookParamType_ObjectPtr); + DHookAddParam(sendSoundDetour, HookParamType_Bool); + if (!DHookEnableDetour(sendSoundDetour, false, DHooks_OnSendSound)) + { + SetFailState("Couldn't enable CGameClient::SendSound detour."); + } + + StartPrepSDKCall(SDKCall_Raw); + PrepSDKCall_SetFromConf(gd, SDKConf_Virtual, "CBaseClient::GetPlayerSlot"); + PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); + getPlayerSlot = EndPrepSDKCall(); + if (getPlayerSlot == null) + { + SetFailState("Could not initialize call to CBaseClient::GetPlayerSlot."); + } +} + + +/*struct SoundInfo_t +{ + Vector vOrigin; Offset: 0 | Size: 12 + Vector vDirection Offset: 12 | Size: 12 + Vector vListenerOrigin; Offset: 24 | Size: 12 + const char *pszName; Offset: 36 | Size: 4 + float fVolume; Offset: 40 | Size: 4 + float fDelay; Offset: 44 | Size: 4 + float fTickTime; Offset: 48 | Size: 4 + int nSequenceNumber; Offset: 52 | Size: 4 + int nEntityIndex; Offset: 56 | Size: 4 + int nChannel; Offset: 60 | Size: 4 + int nPitch; Offset: 64 | Size: 4 + int nFlags; Offset: 68 | Size: 4 + unsigned int nSoundNum; Offset: 72 | Size: 4 + int nSpeakerEntity; Offset: 76 | Size: 4 + int nRandomSeed; Offset: 80 | Size: 4 + soundlevel_t Soundlevel; Offset: 84 | Size: 4 + bool bIsSentence; Offset: 88 | Size: 1 + bool bIsAmbient; Offset: 89 | Size: 1 + bool bLooping; Offset: 90 | Size: 1 +};*/ + +//void CGameClient::SendSound( SoundInfo_t &sound, bool isReliable ) +public MRESReturn DHooks_OnSendSound(Address pThis, Handle hParams) +{ + // Check volume + float volume = DHookGetParamObjectPtrVar(hParams, 1, 40, ObjectValueType_Float); + if(volume == 0.0) + { + return MRES_Ignored; + } + + Address pIClient = pThis + view_as
(0x4); + int client = view_as(SDKCall(getPlayerSlot, pIClient)) + 1; + + if(!IsValidClient(client)) + { + return MRES_Ignored; + } + + bool isAmbient = DHookGetParamObjectPtrVar(hParams, 1, 89, ObjectValueType_Bool); + if (!isAmbient) + { + return MRES_Ignored; + } + + float newVolume; + if (GOKZ_QT_GetOption(client, QTOption_AmbientSounds) == -1 || GOKZ_QT_GetOption(client, QTOption_AmbientSounds) == 10) + { + newVolume = volume; + } + else + { + float volumeFactor = float(GOKZ_QT_GetOption(client, QTOption_AmbientSounds)) * 0.1; + newVolume = volume * volumeFactor; + } + + if (newVolume <= 0.0) + { + return MRES_Supercede; + } + DHookSetParamObjectPtrVar(hParams, 1, 40, ObjectValueType_Float, newVolume); + return MRES_ChangedHandled; +} \ No newline at end of file diff --git a/addons/sourcemod/scripting/gokz-quiet/options.sp b/addons/sourcemod/scripting/gokz-quiet/options.sp index dfc2869f..8fa8e3ea 100644 --- a/addons/sourcemod/scripting/gokz-quiet/options.sp +++ b/addons/sourcemod/scripting/gokz-quiet/options.sp @@ -16,7 +16,7 @@ void RegisterOptions() void OnOptionChanged_Options(int client, QTOption option, any newValue) { - if (option == QTOption_MapSounds && newValue == MapSounds_Enabled) + if (option == QTOption_Soundscapes && newValue == Soundscapes_Enabled) { EnableSoundscape(client); } @@ -41,17 +41,17 @@ void PrintOptionChangeMessage(int client, QTOption option, any newValue) } } } - case QTOption_MapSounds: + case QTOption_Soundscapes: { switch (newValue) { - case MapSounds_Disabled: + case Soundscapes_Disabled: { - GOKZ_PrintToChat(client, true, "%t", "Option - Map Sounds - Disable"); + GOKZ_PrintToChat(client, true, "%t", "Option - Soundscapes - Disable"); } - case MapSounds_Enabled: + case Soundscapes_Enabled: { - GOKZ_PrintToChat(client, true, "%t", "Option - Map Sounds - Enable"); + GOKZ_PrintToChat(client, true, "%t", "Option - Soundscapes - Enable"); } } } @@ -132,14 +132,18 @@ public void TopMenuHandler_QT(TopMenu topmenu, TopMenuAction action, TopMenuObje { FormatToggleableOptionDisplay(param, QTOption_ShowPlayers, buffer, maxlength); } - case QTOption_MapSounds: + case QTOption_Soundscapes: { - FormatToggleableOptionDisplay(param, QTOption_MapSounds, buffer, maxlength); + FormatToggleableOptionDisplay(param, QTOption_Soundscapes, buffer, maxlength); } case QTOption_FallDamageSound: { FormatVolumeOptionDisplay(param, QTOption_FallDamageSound, buffer, maxlength); } + case QTOption_AmbientSounds: + { + FormatVolumeOptionDisplay(param, QTOption_AmbientSounds, buffer, maxlength); + } } } else if (action == TopMenuAction_SelectOption) diff --git a/addons/sourcemod/scripting/gokz-quiet/soundscape.sp b/addons/sourcemod/scripting/gokz-quiet/soundscape.sp index fbb85f72..5e740e12 100644 --- a/addons/sourcemod/scripting/gokz-quiet/soundscape.sp +++ b/addons/sourcemod/scripting/gokz-quiet/soundscape.sp @@ -15,7 +15,7 @@ void EnableSoundscape(int client) void OnPlayerRunCmdPost_Soundscape(int client) { int soundscapeIndex = GetEntProp(client, Prop_Data, "soundscapeIndex"); - if (GOKZ_GetOption(client, gC_QTOptionNames[QTOption_MapSounds]) == MapSounds_Disabled) + if (GOKZ_GetOption(client, gC_QTOptionNames[QTOption_Soundscapes]) == Soundscapes_Disabled) { if (soundscapeIndex != BLANK_SOUNDSCAPEINDEX) { diff --git a/addons/sourcemod/scripting/include/gokz/quiet.inc b/addons/sourcemod/scripting/include/gokz/quiet.inc index 02191c01..f53a9e48 100644 --- a/addons/sourcemod/scripting/include/gokz/quiet.inc +++ b/addons/sourcemod/scripting/include/gokz/quiet.inc @@ -17,8 +17,9 @@ enum QTOption: { QTOPTION_INVALID = -1, QTOption_ShowPlayers, - QTOption_MapSounds, + QTOption_Soundscapes, QTOption_FallDamageSound, + QTOption_AmbientSounds, QTOPTION_COUNT }; @@ -31,9 +32,9 @@ enum enum { - MapSounds_Disabled = 0, - MapSounds_Enabled, - MAPSOUNDS_COUNT + Soundscapes_Disabled = 0, + Soundscapes_Enabled, + SOUNDSCAPES_COUNT }; // =====[ CONSTANTS ]===== @@ -49,36 +50,41 @@ enum stock char gC_QTOptionNames[QTOPTION_COUNT][] = { "GOKZ QT - Show Players", - "GOKZ QT - Map Sounds", - "GOKZ QT - Fall Damage Sound" + "GOKZ QT - Soundscapes", + "GOKZ QT - Fall Damage Sound", + "GOKZ QT - Ambient Sounds" }; stock char gC_QTOptionDescriptions[QTOPTION_COUNT][] = { "Visibility of Other Players - 0 = Disabled, 1 = Enabled", - "Play Ambient Map Sounds/Music - 0 = Disabled, 1 = Enabled", - "Play Fall Damage Sound - 0 to 20 = 0% to 200%" + "Play Soundscapes - 0 = Disabled, 1 = Enabled", + "Play Fall Damage Sound - 0 to 20 = 0% to 200%", + "Play Ambient Sounds - 0 to 20 = 0% to 200%" }; stock int gI_QTOptionDefaultValues[QTOPTION_COUNT] = { ShowPlayers_Enabled, - MapSounds_Enabled, + Soundscapes_Enabled, DEFAULT_VOLUME, // Fall damage volume + DEFAULT_VOLUME // Ambient volume }; stock int gI_QTOptionCounts[QTOPTION_COUNT] = { SHOWPLAYERS_COUNT, - MAPSOUNDS_COUNT, + SOUNDSCAPES_COUNT, VOLUME_COUNT, // Fall damage volume + VOLUME_COUNT // Ambient volume }; stock char gC_QTOptionPhrases[QTOPTION_COUNT][] = { "Options Menu - Show Players", - "Options Menu - Map Sounds", - "Options Menu - Fall Damage Sounds" + "Options Menu - Soundscapes", + "Options Menu - Fall Damage Sounds", + "Options Menu - Ambient Sounds" }; // =====[ STOCKS ]===== diff --git a/addons/sourcemod/translations/gokz-quiet.phrases.txt b/addons/sourcemod/translations/gokz-quiet.phrases.txt index 90120e7b..1c408fa1 100644 --- a/addons/sourcemod/translations/gokz-quiet.phrases.txt +++ b/addons/sourcemod/translations/gokz-quiet.phrases.txt @@ -19,17 +19,13 @@ Phrases "chi" "{grey}已屏蔽其他玩家模型." "ru" "{grey}Теперь вы не видите остальных игроков." } - "Option - Map Sounds - Enable" + "Option - Soundscapes - Enable" { - "en" "{grey}Map sounds are now enabled." - "chi" "{grey}地图音乐已开启." - "ru" "{grey}Звуки карты теперь включены." + "en" "{grey}Soundscapes are now enabled." } - "Option - Map Sounds - Disable" + "Option - Soundscapes - Disable" { - "en" "{grey}Map sounds are now disabled." - "chi" "{grey}地图音乐已关闭." - "ru" "{grey}Звуки карты теперь выключены." + "en" "{grey}Soundscapes are now disabled." } @@ -44,13 +40,16 @@ Phrases "chi" "屏蔽其他玩家" "ru" "Показать игроков" } - "Options Menu - Map Sounds" + "Options Menu - Soundscapes" { - "en" "Play map sounds" - "chi" "播放地图音乐" + "en" "Play soundscapes" } "Options Menu - Fall Damage Sounds" { "en" "Fall damage sounds" } + "Options Menu - Ambient Sounds" + { + "en" "Ambient sounds" + } } \ No newline at end of file diff --git a/cfg/sourcemod/gokz/options_menu_sorting.cfg b/cfg/sourcemod/gokz/options_menu_sorting.cfg index beea95b8..d2bab9b4 100644 --- a/cfg/sourcemod/gokz/options_menu_sorting.cfg +++ b/cfg/sourcemod/gokz/options_menu_sorting.cfg @@ -61,7 +61,8 @@ "Quiet" { "item" "GOKZ QT - Show Players" - "item" "GOKZ QT - Map Sounds" + "item" "GOKZ QT - Soundscapes" "item" "GOKZ QT - Fall Damage Sound" + "item" "GOKZ QT - Ambient Sounds" } } From 286ca45c02591923906a08cfc833a712519cab32 Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Fri, 3 Feb 2023 21:51:04 +0100 Subject: [PATCH 30/47] Fix linux signature --- addons/sourcemod/gamedata/gokz-core.games.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/sourcemod/gamedata/gokz-core.games.txt b/addons/sourcemod/gamedata/gokz-core.games.txt index ef6e9aef..644b554b 100644 --- a/addons/sourcemod/gamedata/gokz-core.games.txt +++ b/addons/sourcemod/gamedata/gokz-core.games.txt @@ -32,7 +32,7 @@ { "library" "server" "windows" "\x55\x8B\xEC\x81\xEC\x8C\x00\x00\x00\x57\x8B\xF9\x8B\x87\x54\x0E\x00\x00" - "linux" "\x55\x89\xE5\x8B\x45\x08\x8B\x90\x54\x0E\x00\x00" + "linux" "\x55\x89\xE5\x57\x56\x53\x81\xEC\xFC\x00\x00\x00\x8B\x5D\x08\x8B\x83\x54\x0E\x00\x00" } } From c24ace7eee8bcba6c8525eaa2d33f4092060da59 Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Fri, 3 Feb 2023 21:54:39 +0100 Subject: [PATCH 31/47] Fix linux signature --- addons/sourcemod/gamedata/gokz-quiet.games.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/sourcemod/gamedata/gokz-quiet.games.txt b/addons/sourcemod/gamedata/gokz-quiet.games.txt index 5cd4fde8..06f52203 100644 --- a/addons/sourcemod/gamedata/gokz-quiet.games.txt +++ b/addons/sourcemod/gamedata/gokz-quiet.games.txt @@ -8,7 +8,7 @@ { "library" "engine" "windows" "\x55\x8B\xEC\x51\x56\x8B\xF1\x8B\x46\x04" - "linux" "\x55\x89\xE5\x57\x56\x53\x83\xEC\x4C\x8B\x5D\x08\x8B\x7D\x0C\x0F\xB6\x75\x10" + "linux" "\x55\x89\xE5\x57\x56\x53\x83\xEC\x2C\x8B\x5D\x08\x8B\x75\x10\x8B\x03" } } From 714e6bc183346aa8da7bcacec9099ef6acf61153 Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Fri, 3 Feb 2023 22:02:02 +0100 Subject: [PATCH 32/47] Fix linux gamedata --- addons/sourcemod/gamedata/gokz-replays.games.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/sourcemod/gamedata/gokz-replays.games.txt b/addons/sourcemod/gamedata/gokz-replays.games.txt index f4b7f80b..3e351c0b 100644 --- a/addons/sourcemod/gamedata/gokz-replays.games.txt +++ b/addons/sourcemod/gamedata/gokz-replays.games.txt @@ -36,7 +36,7 @@ "BotDuckSig" { "windows" "\x8B\x86\x54\x0E\x00\x00\x8B\xCE" - "linux" "\x8B\x83\x54\x0E\x00\x00\xC6\x80\x84\x2C\x00\x00\x01\x8B\x03" + "linux" "\x8B\x83\x54\x0E\x00\x00\x83\xEC\x0C" } } "Offsets" @@ -44,7 +44,7 @@ "BotDuckPatchLength" { "windows" "23" - "linux" "24" + "linux" "38" } } } From aa7b97ad03a966ea2f42dc9b7372f3c9adcd7fe1 Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Fri, 3 Feb 2023 22:13:56 +0100 Subject: [PATCH 33/47] Fix linux signature --- addons/sourcemod/gamedata/gokz-tpanglefix.games.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/sourcemod/gamedata/gokz-tpanglefix.games.txt b/addons/sourcemod/gamedata/gokz-tpanglefix.games.txt index eabef7bd..cf8026f9 100644 --- a/addons/sourcemod/gamedata/gokz-tpanglefix.games.txt +++ b/addons/sourcemod/gamedata/gokz-tpanglefix.games.txt @@ -48,7 +48,7 @@ { "library" "engine" "windows" "\x55\x8B\xEC\x83\xEC\x40\x56\x57" - "linux" "\x55\x89\xE5\x83\xEC\x68\x89\x75\xF8\x8B\x75\x08\x89\x5D\xF4\x89\x7D\xFC\x8B\x06" + "linux" "\x55\x89\xE5\x57\x56\x53\x83\xEC\x4C\x8B\x5D\x08\x8B\x03" } } } From 10924dac1b8c1ad721b3d217db60fdae36dca39b Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Thu, 9 Feb 2023 21:30:03 +0100 Subject: [PATCH 34/47] Fix triggerfix infinitely looping on triggers using OnTrigger --- addons/sourcemod/scripting/gokz-core/triggerfix.sp | 14 ++++++++------ addons/sourcemod/scripting/include/gokz/core.inc | 3 +++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/addons/sourcemod/scripting/gokz-core/triggerfix.sp b/addons/sourcemod/scripting/gokz-core/triggerfix.sp index 4f3f53a8..84c499f7 100644 --- a/addons/sourcemod/scripting/gokz-core/triggerfix.sp +++ b/addons/sourcemod/scripting/gokz-core/triggerfix.sp @@ -12,7 +12,7 @@ static int processMovementTicks[MAXPLAYERS+1]; static float playerFrameTime[MAXPLAYERS+1]; static bool touchingTrigger[MAXPLAYERS+1][2048]; -static bool triggerTouchFired[MAXPLAYERS+1][2048]; +static int triggerTouchFired[MAXPLAYERS+1][2048]; static int lastGroundEnt[MAXPLAYERS + 1]; static bool duckedLastTick[MAXPLAYERS + 1]; static bool mapTeleportedSequentialTicks[MAXPLAYERS+1]; @@ -171,7 +171,7 @@ public void OnClientConnected_Triggerfix(int client) for (int i = 0; i < sizeof(touchingTrigger[]); i++) { touchingTrigger[client][i] = false; - triggerTouchFired[client][i] = false; + triggerTouchFired[client][i] = 0; } } @@ -201,7 +201,7 @@ public void OnGameFrame_Triggerfix() // so this should not be a big problem. for (int trigger = 0; trigger < sizeof(triggerTouchFired[]); trigger++) { - triggerTouchFired[client][trigger] = false; + triggerTouchFired[client][trigger] = 0; } } } @@ -246,7 +246,7 @@ static Action Hook_TriggerTouch(int entity, int other) { if (1 <= other <= MaxClients) { - triggerTouchFired[other][entity] = true; + triggerTouchFired[other][entity]++; } return Plugin_Continue; } @@ -335,13 +335,14 @@ static bool DoTriggerFix(int client, bool filterFix = false) // Completely ignore push triggers. continue; } - if (filterFix && SDKCall(passesTriggerFilters, trigger, client)) + if (filterFix && SDKCall(passesTriggerFilters, trigger, client) && triggerTouchFired[client][trigger] < GOKZ_MAX_RETOUCH_TRIGGER_COUNT) { // MarkEntitiesAsTouching always fires the Touch function even if it was already fired this tick. SDKCall(markEntitiesAsTouching, serverGameEnts, client, trigger); // Player properties might be changed right after this so it will need to be triggered again. - triggerTouchFired[client][trigger] = false; + // Triggers changing this filter will loop onto itself infintely so we need to avoid that. + triggerTouchFired[client][trigger]++; didSomething = true; } else if (!triggerTouchFired[client][trigger]) @@ -349,6 +350,7 @@ static bool DoTriggerFix(int client, bool filterFix = false) // If the player is still touching the trigger on this tick, and Touch was not called for whatever reason // in the last tick, we make sure that it is called now. SDKCall(markEntitiesAsTouching, serverGameEnts, client, trigger); + triggerTouchFired[client][trigger]++; didSomething = true; } } diff --git a/addons/sourcemod/scripting/include/gokz/core.inc b/addons/sourcemod/scripting/include/gokz/core.inc index c21678c6..0c1f5127 100644 --- a/addons/sourcemod/scripting/include/gokz/core.inc +++ b/addons/sourcemod/scripting/include/gokz/core.inc @@ -285,6 +285,9 @@ enum TriggerType #define GOKZ_SAFEGUARD_RESTART_MIN_DELAY 0.6 #define GOKZ_SAFEGUARD_RESTART_MAX_DELAY 5.0 +// Prevents the player from retouching a trigger too often. +#define GOKZ_MAX_RETOUCH_TRIGGER_COUNT 4 + stock char gC_TimeTypeNames[TIMETYPE_COUNT][] = { "NUB", From 011f303d56f4af948403b03b72c4783ee14c1443 Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Thu, 9 Feb 2023 22:03:30 +0100 Subject: [PATCH 35/47] Reset the touch count on client tick as well --- addons/sourcemod/scripting/gokz-core.sp | 1 + addons/sourcemod/scripting/gokz-core/triggerfix.sp | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/addons/sourcemod/scripting/gokz-core.sp b/addons/sourcemod/scripting/gokz-core.sp index e0a04ab3..ea0aab5c 100644 --- a/addons/sourcemod/scripting/gokz-core.sp +++ b/addons/sourcemod/scripting/gokz-core.sp @@ -182,6 +182,7 @@ public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3 { gI_CmdNum[client] = cmdnum; gI_TickCount[client] = tickcount; + OnPlayerRunCmd_Triggerfix(client); OnPlayerRunCmd_MapTriggers(client, buttons); OnPlayerRunCmd_Turnbinds(client, buttons, tickcount, angles); return Plugin_Continue; diff --git a/addons/sourcemod/scripting/gokz-core/triggerfix.sp b/addons/sourcemod/scripting/gokz-core/triggerfix.sp index 84c499f7..424928d9 100644 --- a/addons/sourcemod/scripting/gokz-core/triggerfix.sp +++ b/addons/sourcemod/scripting/gokz-core/triggerfix.sp @@ -207,6 +207,17 @@ public void OnGameFrame_Triggerfix() } } +void OnPlayerRunCmd_Triggerfix(int client) +{ + // Reset the Touch tracking. + // While this is mostly unnecessary, it can also happen that the server runs multiple ticks of player movement at once, + // therefore the triggers need to be checked again. + for (int trigger = 0; trigger < sizeof(triggerTouchFired[]); trigger++) + { + triggerTouchFired[client][trigger] = 0; + } +} + static void Event_PlayerJump(Event event, const char[] name, bool dontBroadcast) { int client = GetClientOfUserId(event.GetInt("userid")); From c10eb915cb903bd9d97213805b2ad3042181f665 Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Sun, 12 Feb 2023 15:02:05 +0100 Subject: [PATCH 36/47] Remove unused variable --- addons/sourcemod/scripting/gokz-jumpstats.sp | 5 ----- .../sourcemod/scripting/gokz-jumpstats/jump_tracking.sp | 9 --------- 2 files changed, 14 deletions(-) diff --git a/addons/sourcemod/scripting/gokz-jumpstats.sp b/addons/sourcemod/scripting/gokz-jumpstats.sp index d5ef58f4..74d92202 100644 --- a/addons/sourcemod/scripting/gokz-jumpstats.sp +++ b/addons/sourcemod/scripting/gokz-jumpstats.sp @@ -122,11 +122,6 @@ public void Movement_OnStartTouchGround(int client) OnStartTouchGround_JumpTracking(client); } -public void Movement_OnChangeMovetype(int client, MoveType oldMovetype, MoveType newMovetype) -{ - OnChangeMovetype_JumpTracking(client, oldMovetype, newMovetype); -} - public void GOKZ_OnJumpInvalidated(int client) { OnJumpInvalidated_JumpTracking(client); diff --git a/addons/sourcemod/scripting/gokz-jumpstats/jump_tracking.sp b/addons/sourcemod/scripting/gokz-jumpstats/jump_tracking.sp index e8efb59e..ffa848d3 100644 --- a/addons/sourcemod/scripting/gokz-jumpstats/jump_tracking.sp +++ b/addons/sourcemod/scripting/gokz-jumpstats/jump_tracking.sp @@ -60,7 +60,6 @@ enum struct JumpTracker int jumpoffTick; int poseIndex; int strafeDirection; - int ladderGrabTick; int lastJumpTick; int lastTeleportTick; int lastType; @@ -1451,14 +1450,6 @@ public void OnPlayerRunCmdPost_JumpTracking(int client) } } -public void OnChangeMovetype_JumpTracking(int client, MoveType oldMovetype, MoveType newMovetype) -{ - if (newMovetype == MOVETYPE_LADDER) - { - jumpTrackers[client].ladderGrabTick = jumpTrackers[client].tickCount; - } -} - static MRESReturn DHooks_AcceptInput(int client, DHookReturn hReturn, DHookParam hParams) { if (!IsValidClient(client) || !IsPlayerAlive(client)) From 36a671dc14612791a1021fccbde4466360fc9811 Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Sun, 12 Feb 2023 15:02:27 +0100 Subject: [PATCH 37/47] Update movementapi include file --- .../scripting/include/movementapi.inc | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/addons/sourcemod/scripting/include/movementapi.inc b/addons/sourcemod/scripting/include/movementapi.inc index c0d87e3c..290c3f2a 100644 --- a/addons/sourcemod/scripting/include/movementapi.inc +++ b/addons/sourcemod/scripting/include/movementapi.inc @@ -107,6 +107,28 @@ forward void Movement_OnStopDucking(int client); */ forward void Movement_OnPlayerJump(int client, bool jumpbug); +/** + * Called before PlayerMove movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnPlayerMovePre(int client, float origin[3], float velocity[3]); + +/** + * Called after PlayerMove movement function is called. + * Modifying origin or velocity parameters will change player's origin and velocity accordingly. + * + * @param client Client index. + * @param origin Player origin. + * @param velocity Player velocity. + * @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise. + */ +forward Action Movement_OnPlayerMovePost(int client, float origin[3], float velocity[3]); + /** * Called before Duck movement function is called. * Modifying origin or velocity parameters will change player's origin and velocity accordingly. @@ -638,4 +660,4 @@ public void __pl_movementapi_SetNTVOptional() MarkNativeAsOptional("Movement_SetLandingOrigin"); MarkNativeAsOptional("Movement_SetLandingVelocity"); } -#endif +#endif \ No newline at end of file From 773f4bdc262979cdae6125901fdf5c566c9ca6aa Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Sun, 12 Feb 2023 15:03:43 +0100 Subject: [PATCH 38/47] Fix ladder takeoff on the ground counting as long jump --- .../scripting/gokz-jumpstats/jump_tracking.sp | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/addons/sourcemod/scripting/gokz-jumpstats/jump_tracking.sp b/addons/sourcemod/scripting/gokz-jumpstats/jump_tracking.sp index ffa848d3..acd94428 100644 --- a/addons/sourcemod/scripting/gokz-jumpstats/jump_tracking.sp +++ b/addons/sourcemod/scripting/gokz-jumpstats/jump_tracking.sp @@ -26,6 +26,8 @@ static ArrayList entityTouchList[MAXPLAYERS + 1]; static int entityTouchDuration[MAXPLAYERS + 1]; static int lastNoclipTime[MAXPLAYERS + 1]; static int lastDuckbugTime[MAXPLAYERS + 1]; +static int lastGroundSpeedCappedTime[MAXPLAYERS + 1]; +static int lastMovementProcessedTime[MAXPLAYERS + 1]; static float lastJumpButtonTime[MAXPLAYERS + 1]; static bool validCmd[MAXPLAYERS + 1]; // Whether no illegal action is detected static const float playerMins[3] = { -16.0, -16.0, 0.0 }; @@ -349,7 +351,11 @@ enum struct JumpTracker return JumpType_Other; } } - return this.HitDuckbugRecently() ? JumpType_Invalid : JumpType_LongJump; + if (this.HitDuckbugRecently() || !this.GroundSpeedCappedRecently()) + { + return JumpType_Invalid; + } + return JumpType_LongJump; } bool HitBhop() @@ -376,6 +382,12 @@ enum struct JumpTracker return this.tickCount - lastDuckbugTime[this.jumper] <= JS_MAX_DUCKBUG_RESET_TICKS; } + bool GroundSpeedCappedRecently() + { + // A valid longjump needs to have their ground speed capped the tick right before. + return lastGroundSpeedCappedTime[this.jumper] == lastMovementProcessedTime[this.jumper]; + } + // =====[ UPDATE HELPERS ]==================================================== // We split that up in two functions to get a reference to the pose so we @@ -1407,6 +1419,18 @@ void OnPlayerRunCmd_JumpTracking(int client, int buttons, int tickcount) } } +public Action Movement_OnWalkMovePost(int client) +{ + lastGroundSpeedCappedTime[client] = jumpTrackers[client].tickCount; + return Plugin_Continue; +} + +public Action Movement_OnPlayerMovePost(int client) +{ + lastMovementProcessedTime[client] = jumpTrackers[client].tickCount; + return Plugin_Continue; +} + public void OnPlayerRunCmdPost_JumpTracking(int client) { if (!IsValidClient(client) || !IsPlayerAlive(client)) From 48714edf0ff5b975674388aab16bf345441f27fe Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Thu, 23 Feb 2023 23:02:54 +0100 Subject: [PATCH 39/47] Revert the update speed to use the values of the previous implementation --- addons/sourcemod/scripting/gokz-hud/info_panel.sp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/sourcemod/scripting/gokz-hud/info_panel.sp b/addons/sourcemod/scripting/gokz-hud/info_panel.sp index c766af9e..f0f99990 100644 --- a/addons/sourcemod/scripting/gokz-hud/info_panel.sp +++ b/addons/sourcemod/scripting/gokz-hud/info_panel.sp @@ -27,7 +27,7 @@ bool IsDrawingInfoPanel(int client) void OnPlayerRunCmdPost_InfoPanel(int client, int cmdnum, HUDInfo info) { - int updateSpeed = gB_FastUpdateRate[client] ? 3 : 6; + int updateSpeed = gB_FastUpdateRate[client] ? 1 : 10; if (cmdnum % updateSpeed == 0 || info.IsTakeoff) { UpdateInfoPanel(client, info); From a994f2f606c1e9b70a92c2fd1f3225674ca9b9e9 Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Fri, 24 Feb 2023 02:46:46 +0100 Subject: [PATCH 40/47] Add GOKZ sound options to quiet module --- addons/sourcemod/scripting/gokz-quiet.sp | 1 + .../scripting/gokz-quiet/gokz-sounds.sp | 71 +++++++++++++++++++ .../sourcemod/scripting/gokz-quiet/options.sp | 36 ++++++++-- .../scripting/include/gokz/quiet.inc | 52 ++++++++++++-- .../translations/gokz-quiet.phrases.txt | 28 ++++++++ cfg/sourcemod/gokz/options_menu_sorting.cfg | 7 ++ 6 files changed, 186 insertions(+), 9 deletions(-) create mode 100644 addons/sourcemod/scripting/gokz-quiet/gokz-sounds.sp diff --git a/addons/sourcemod/scripting/gokz-quiet.sp b/addons/sourcemod/scripting/gokz-quiet.sp index 196f8da1..06cc2466 100644 --- a/addons/sourcemod/scripting/gokz-quiet.sp +++ b/addons/sourcemod/scripting/gokz-quiet.sp @@ -32,6 +32,7 @@ public Plugin myinfo = #include "gokz-quiet/soundscape.sp" #include "gokz-quiet/hideplayers.sp" #include "gokz-quiet/falldamage.sp" +#include "gokz-quiet/gokz-sounds.sp" #include "gokz-quiet/options.sp" // =====[ PLUGIN EVENTS ]===== diff --git a/addons/sourcemod/scripting/gokz-quiet/gokz-sounds.sp b/addons/sourcemod/scripting/gokz-quiet/gokz-sounds.sp new file mode 100644 index 00000000..bf38d6e6 --- /dev/null +++ b/addons/sourcemod/scripting/gokz-quiet/gokz-sounds.sp @@ -0,0 +1,71 @@ +/* + Volume options for various GOKZ sounds. +*/ + +public Action GOKZ_OnEmitSoundToClient(int client, const char[] sample, float &volume, const char[] description) +{ + int volumeFactor = 10; + if (StrEqual(description, "Checkpoint") || StrEqual(description, "Set Start Position")) + { + volumeFactor = GOKZ_QT_GetOption(client, QTOption_CheckpointVolume); + if (volumeFactor == -1) + { + return Plugin_Continue; + } + } + else if (StrEqual(description, "Checkpoint")) + { + volumeFactor = GOKZ_QT_GetOption(client, QTOption_TeleportVolume); + if (volumeFactor == -1) + { + return Plugin_Continue; + } + } + else if (StrEqual(description, "Timer Start") || StrEqual(description, "Timer End") || StrEqual(description, "Timer False End") || StrEqual(description, "Missed PB")) + { + volumeFactor = GOKZ_QT_GetOption(client, QTOption_TimerVolume); + if (volumeFactor == -1) + { + return Plugin_Continue; + } + } + else if (StrEqual(description, "Error")) + { + volumeFactor = GOKZ_QT_GetOption(client, QTOption_ErrorVolume); + if (volumeFactor == -1) + { + return Plugin_Continue; + } + } + else if (StrEqual(description, "Server Record")) + { + volumeFactor = GOKZ_QT_GetOption(client, QTOption_ServerRecordVolume); + if (volumeFactor == -1) + { + return Plugin_Continue; + } + } + else if (StrEqual(description, "World Record")) + { + volumeFactor = GOKZ_QT_GetOption(client, QTOption_WorldRecordVolume); + if (volumeFactor == -1) + { + return Plugin_Continue; + } + } + else if (StrEqual(description, "Jumpstats")) + { + volumeFactor = GOKZ_QT_GetOption(client, QTOption_JumpstatsVolume); + if (volumeFactor == -1) + { + return Plugin_Continue; + } + } + + if (volumeFactor == 10) + { + return Plugin_Continue; + } + volume *= float(volumeFactor) * 0.1; + return Plugin_Changed; +} \ No newline at end of file diff --git a/addons/sourcemod/scripting/gokz-quiet/options.sp b/addons/sourcemod/scripting/gokz-quiet/options.sp index 8fa8e3ea..a9da3d7f 100644 --- a/addons/sourcemod/scripting/gokz-quiet/options.sp +++ b/addons/sourcemod/scripting/gokz-quiet/options.sp @@ -130,19 +130,47 @@ public void TopMenuHandler_QT(TopMenu topmenu, TopMenuAction action, TopMenuObje { case QTOption_ShowPlayers: { - FormatToggleableOptionDisplay(param, QTOption_ShowPlayers, buffer, maxlength); + FormatToggleableOptionDisplay(param, option, buffer, maxlength); } case QTOption_Soundscapes: { - FormatToggleableOptionDisplay(param, QTOption_Soundscapes, buffer, maxlength); + FormatToggleableOptionDisplay(param, option, buffer, maxlength); } case QTOption_FallDamageSound: { - FormatVolumeOptionDisplay(param, QTOption_FallDamageSound, buffer, maxlength); + FormatVolumeOptionDisplay(param, option, buffer, maxlength); } case QTOption_AmbientSounds: { - FormatVolumeOptionDisplay(param, QTOption_AmbientSounds, buffer, maxlength); + FormatVolumeOptionDisplay(param, option, buffer, maxlength); + } + case QTOption_CheckpointVolume: + { + FormatVolumeOptionDisplay(param, option, buffer, maxlength); + } + case QTOption_TeleportVolume: + { + FormatVolumeOptionDisplay(param, option, buffer, maxlength); + } + case QTOption_TimerVolume: + { + FormatVolumeOptionDisplay(param, option, buffer, maxlength); + } + case QTOption_ErrorVolume: + { + FormatVolumeOptionDisplay(param, option, buffer, maxlength); + } + case QTOption_ServerRecordVolume: + { + FormatVolumeOptionDisplay(param, option, buffer, maxlength); + } + case QTOption_WorldRecordVolume: + { + FormatVolumeOptionDisplay(param, option, buffer, maxlength); + } + case QTOption_JumpstatsVolume: + { + FormatVolumeOptionDisplay(param, option, buffer, maxlength); } } } diff --git a/addons/sourcemod/scripting/include/gokz/quiet.inc b/addons/sourcemod/scripting/include/gokz/quiet.inc index f53a9e48..a328b7ee 100644 --- a/addons/sourcemod/scripting/include/gokz/quiet.inc +++ b/addons/sourcemod/scripting/include/gokz/quiet.inc @@ -20,6 +20,13 @@ enum QTOption: QTOption_Soundscapes, QTOption_FallDamageSound, QTOption_AmbientSounds, + QTOption_CheckpointVolume, + QTOption_TeleportVolume, + QTOption_TimerVolume, + QTOption_ErrorVolume, + QTOption_ServerRecordVolume, + QTOption_WorldRecordVolume, + QTOption_JumpstatsVolume, QTOPTION_COUNT }; @@ -52,7 +59,14 @@ stock char gC_QTOptionNames[QTOPTION_COUNT][] = "GOKZ QT - Show Players", "GOKZ QT - Soundscapes", "GOKZ QT - Fall Damage Sound", - "GOKZ QT - Ambient Sounds" + "GOKZ QT - Ambient Sounds", + "GOKZ QT - Checkpoint Volume", + "GOKZ QT - Teleport Volume", + "GOKZ QT - Timer Volume", + "GOKZ QT - Error Volume", + "GOKZ QT - Server Record Volume", + "GOKZ QT - World Record Volume", + "GOKZ QT - Jumpstats Volume" }; stock char gC_QTOptionDescriptions[QTOPTION_COUNT][] = @@ -60,7 +74,14 @@ stock char gC_QTOptionDescriptions[QTOPTION_COUNT][] = "Visibility of Other Players - 0 = Disabled, 1 = Enabled", "Play Soundscapes - 0 = Disabled, 1 = Enabled", "Play Fall Damage Sound - 0 to 20 = 0% to 200%", - "Play Ambient Sounds - 0 to 20 = 0% to 200%" + "Play Ambient Sounds - 0 to 20 = 0% to 200%", + "Checkpoint Volume - 0 to 20 = 0% to 200%", + "Teleport Volume - 0 to 20 = 0% to 200%", + "Timer Volume - 0 to 20 = 0% to 200%", + "Error Volume - 0 to 20 = 0% to 200%", + "Server Record Volume - 0 to 20 = 0% to 200%", + "World Record Volume - 0 to 20 = 0% to 200%", + "Jumpstats Volume - 0 to 20 = 0% to 200%" }; stock int gI_QTOptionDefaultValues[QTOPTION_COUNT] = @@ -68,7 +89,14 @@ stock int gI_QTOptionDefaultValues[QTOPTION_COUNT] = ShowPlayers_Enabled, Soundscapes_Enabled, DEFAULT_VOLUME, // Fall damage volume - DEFAULT_VOLUME // Ambient volume + DEFAULT_VOLUME, // Ambient volume + DEFAULT_VOLUME, // Checkpoint volume + DEFAULT_VOLUME, // Teleport volume + DEFAULT_VOLUME, // Timer volume + DEFAULT_VOLUME, // Error volume + DEFAULT_VOLUME, // Server Record Volume + DEFAULT_VOLUME, // World Record Volume + DEFAULT_VOLUME // Jumpstats Volume }; stock int gI_QTOptionCounts[QTOPTION_COUNT] = @@ -76,7 +104,14 @@ stock int gI_QTOptionCounts[QTOPTION_COUNT] = SHOWPLAYERS_COUNT, SOUNDSCAPES_COUNT, VOLUME_COUNT, // Fall damage volume - VOLUME_COUNT // Ambient volume + VOLUME_COUNT, // Ambient volume + VOLUME_COUNT, // Checkpoint volume + VOLUME_COUNT, // Teleport volume + VOLUME_COUNT, // Timer volume + VOLUME_COUNT, // Error volume + VOLUME_COUNT, // Server Record volume + VOLUME_COUNT, // World Record volume + VOLUME_COUNT // Jumpstats volume }; stock char gC_QTOptionPhrases[QTOPTION_COUNT][] = @@ -84,7 +119,14 @@ stock char gC_QTOptionPhrases[QTOPTION_COUNT][] = "Options Menu - Show Players", "Options Menu - Soundscapes", "Options Menu - Fall Damage Sounds", - "Options Menu - Ambient Sounds" + "Options Menu - Ambient Sounds", + "Options Menu - Checkpoint Volume", + "Options Menu - Teleport Volume", + "Options Menu - Timer Volume", + "Options Menu - Error Volume", + "Options Menu - Server Record Volume", + "Options Menu - World Record Volume", + "Options Menu - Jumpstats Volume" }; // =====[ STOCKS ]===== diff --git a/addons/sourcemod/translations/gokz-quiet.phrases.txt b/addons/sourcemod/translations/gokz-quiet.phrases.txt index 1c408fa1..6025e22c 100644 --- a/addons/sourcemod/translations/gokz-quiet.phrases.txt +++ b/addons/sourcemod/translations/gokz-quiet.phrases.txt @@ -52,4 +52,32 @@ Phrases { "en" "Ambient sounds" } + "Options Menu - Checkpoint Volume" + { + "en" "Checkpoint volume" + } + "Options Menu - Teleport Volume" + { + "en" "Teleport volume" + } + "Options Menu - Timer Volume" + { + "en" "Timer volume" + } + "Options Menu - Error Volume" + { + "en" "Error volume" + } + "Options Menu - Server Record Volume" + { + "en" "Server record volume" + } + "Options Menu - World Record Volume" + { + "en" "World record volume" + } + "Options Menu - Jumpstats Volume" + { + "en" "Jumpstats volume" + } } \ No newline at end of file diff --git a/cfg/sourcemod/gokz/options_menu_sorting.cfg b/cfg/sourcemod/gokz/options_menu_sorting.cfg index 534cac61..e511ef73 100644 --- a/cfg/sourcemod/gokz/options_menu_sorting.cfg +++ b/cfg/sourcemod/gokz/options_menu_sorting.cfg @@ -66,5 +66,12 @@ "item" "GOKZ QT - Soundscapes" "item" "GOKZ QT - Fall Damage Sound" "item" "GOKZ QT - Ambient Sounds" + "item" "GOKZ QT - Checkpoint Volume" + "item" "GOKZ QT - Teleport Volume" + "item" "GOKZ QT - Timer Volume" + "item" "GOKZ QT - Error Volume" + "item" "GOKZ QT - Server Record Volume" + "item" "GOKZ QT - World Record Volume" + "item" "GOKZ QT - Jumpstats Volume" } } From 7744dd3515897999c22883efc38a5b445257abc8 Mon Sep 17 00:00:00 2001 From: Yuera <422913045@qq.com> Date: Tue, 7 Mar 2023 01:31:07 +0800 Subject: [PATCH 41/47] Update gametrace.sp --- addons/sourcemod/scripting/momsurffix/gametrace.sp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/sourcemod/scripting/momsurffix/gametrace.sp b/addons/sourcemod/scripting/momsurffix/gametrace.sp index 25d7892a..d2e3b929 100644 --- a/addons/sourcemod/scripting/momsurffix/gametrace.sp +++ b/addons/sourcemod/scripting/momsurffix/gametrace.sp @@ -297,7 +297,7 @@ methodmap CTraceFilterSimple < AllocatableBase property Address m_pExtraShouldHitCheckFunction { public get() { return view_as
(LoadFromAddress(this.Address + offsets.ctfsoffsets.m_pExtraShouldHitCheckFunction, NumberType_Int32)); } - public set(Address _checkfnc) { StoreToAddress(this.Address + offsets.ctfsoffsets.m_pExtraShouldHitCheckFunction, view_as(_checkfnc), NumberType_Int32), false; } + public set(Address _checkfnc) { StoreToAddress(this.Address + offsets.ctfsoffsets.m_pExtraShouldHitCheckFunction, view_as(_checkfnc), NumberType_Int32, false); } } public CTraceFilterSimple() @@ -477,4 +477,4 @@ stock void TraceRayAgainstLeafAndEntityList(Ray_t ray, ITraceListData traceData, stock void TraceRay(Ray_t ray, int mask, CTraceFilterSimple filter, CGameTrace trace) { SDKCall(gTraceRay, gEngineTrace, ray.Address, mask, filter.Address, trace.Address); -} \ No newline at end of file +} From 12779c190610d384fbe639570346345edf6af039 Mon Sep 17 00:00:00 2001 From: Yuera <422913045@qq.com> Date: Tue, 7 Mar 2023 03:07:24 +0800 Subject: [PATCH 42/47] Update gokz-replays.sp --- addons/sourcemod/scripting/gokz-replays.sp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/sourcemod/scripting/gokz-replays.sp b/addons/sourcemod/scripting/gokz-replays.sp index 1a679cea..bc826c4c 100644 --- a/addons/sourcemod/scripting/gokz-replays.sp +++ b/addons/sourcemod/scripting/gokz-replays.sp @@ -44,7 +44,7 @@ bool gB_HideNameChange; bool gB_NubRecordMissed[MAXPLAYERS + 1]; ArrayList g_ReplayInfoCache; Address gA_BotDuckAddr; -int gI_BotDuckPatchRestore[24]; // Size of patched section in gamedata +int gI_BotDuckPatchRestore[40]; // Size of patched section in gamedata int gI_BotDuckPatchLength; DynamicDetour gH_DHooks_TeamFull; From 8553e2d6f0e1085aa2236bfb3ebc44f010ecd2a9 Mon Sep 17 00:00:00 2001 From: Walliski Date: Mon, 6 Mar 2023 21:37:33 +0200 Subject: [PATCH 43/47] Update momsurffix with upstream changes Mostly some things that have been badly copied over, or have been changed later on. Original find by Yue-Ra, which made me recheck bigger parts of the code. --- addons/sourcemod/scripting/gokz-momsurffix.sp | 6 ++++-- addons/sourcemod/scripting/momsurffix/gametrace.sp | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/addons/sourcemod/scripting/gokz-momsurffix.sp b/addons/sourcemod/scripting/gokz-momsurffix.sp index ae87d2bd..2738e902 100644 --- a/addons/sourcemod/scripting/gokz-momsurffix.sp +++ b/addons/sourcemod/scripting/gokz-momsurffix.sp @@ -22,7 +22,7 @@ public Plugin myinfo = { #define FLT_EPSILON 1.192092896e-07 #define MAX_CLIP_PLANES 5 -#define ASM_PATCH_LEN 24 +#define ASM_PATCH_LEN 17 #define ASM_START_OFFSET 100 #define WALKABLE_PLANE_NORMAL 0.7 @@ -151,7 +151,7 @@ public Action SM_Prof(int client, int args) if(gProfTime <= 0.1) { - ReplyToCommand(client, SNAME..."Time should be higher then 0.1 seconds.") + ReplyToCommand(client, SNAME..."Time should be higher then 0.1 seconds."); return Plugin_Handled; } @@ -193,6 +193,8 @@ public Action Prof_Check_Timer(Handle timer, int client) delete gProf; delete gProfData; + + return Plugin_Handled; } #endif diff --git a/addons/sourcemod/scripting/momsurffix/gametrace.sp b/addons/sourcemod/scripting/momsurffix/gametrace.sp index d2e3b929..e8db1ad9 100644 --- a/addons/sourcemod/scripting/momsurffix/gametrace.sp +++ b/addons/sourcemod/scripting/momsurffix/gametrace.sp @@ -75,7 +75,7 @@ methodmap Cplane_t < AddressBase property float dist { - public get() { return view_as(LoadFromAddress(this.Address + offsets.cptoffsets.normal, NumberType_Int32)); } + public get() { return view_as(LoadFromAddress(this.Address + offsets.cptoffsets.dist, NumberType_Int32)); } } property char type From ed2d5d857ddf6d2ff9e979edae44596dc423c4d4 Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Fri, 14 Apr 2023 00:37:53 +0200 Subject: [PATCH 44/47] Fix client freezing with empty hud text --- .../sourcemod/scripting/gokz-hud/info_panel.sp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/addons/sourcemod/scripting/gokz-hud/info_panel.sp b/addons/sourcemod/scripting/gokz-hud/info_panel.sp index e6984e91..35634047 100644 --- a/addons/sourcemod/scripting/gokz-hud/info_panel.sp +++ b/addons/sourcemod/scripting/gokz-hud/info_panel.sp @@ -48,8 +48,12 @@ static void UpdateInfoPanel(int client, HUDInfo info) { return; } - - PrintCSGOHUDText(player.ID, GetInfoPanel(player, info)); + char infoPanelText[512]; + FormatEx(infoPanelText, sizeof(infoPanelText), GetInfoPanel(player, info)); + if (infoPanelText[0] != '\0') + { + PrintCSGOHUDText(player.ID, infoPanelText); + } } static bool NothingEnabledInInfoPanel(KZPlayer player) @@ -65,11 +69,19 @@ static char[] GetInfoPanel(KZPlayer player, HUDInfo info) { char infoPanelText[512]; FormatEx(infoPanelText, sizeof(infoPanelText), - "%s%s%s%s", + "%s%s%s%s", GetSpectatorString(player, info), GetTimeString(player, info), GetSpeedString(player, info), GetKeysString(player, info)); + if (infoPanelText[0] == '\0') + { + return infoPanelText; + } + else + { + Format(infoPanelText, sizeof(infoPanelText), "%s", infoPanelText); + } TrimString(infoPanelText); return infoPanelText; } From c48ba492f0b776ac790e33aebf994cfc94b05e3a Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Tue, 2 May 2023 02:45:25 +0200 Subject: [PATCH 45/47] Fix ladder tp abuse --- addons/sourcemod/scripting/include/gokz.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/sourcemod/scripting/include/gokz.inc b/addons/sourcemod/scripting/include/gokz.inc index 63baaa3a..bf707eb8 100644 --- a/addons/sourcemod/scripting/include/gokz.inc +++ b/addons/sourcemod/scripting/include/gokz.inc @@ -550,7 +550,7 @@ stock void ForcePlayerDuck(int client) { // these are both necessary, because on their own the player will sometimes still be in a state that isn't fully ducked. SetEntPropFloat(client, Prop_Send, "m_flDuckAmount", 1.0, 0); - SetEntProp(client, Prop_Send, "m_bDucking", true); + SetEntProp(client, Prop_Send, "m_bDucked", true); } /** From 4802370675e61e73bdce9be1b94d84e24b864cd4 Mon Sep 17 00:00:00 2001 From: "zer0.k" Date: Tue, 2 May 2023 22:33:03 +0200 Subject: [PATCH 46/47] Make sure ducking and ducked aren't simutaneously true --- addons/sourcemod/scripting/include/gokz.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/sourcemod/scripting/include/gokz.inc b/addons/sourcemod/scripting/include/gokz.inc index bf707eb8..c79f93cd 100644 --- a/addons/sourcemod/scripting/include/gokz.inc +++ b/addons/sourcemod/scripting/include/gokz.inc @@ -550,6 +550,7 @@ stock void ForcePlayerDuck(int client) { // these are both necessary, because on their own the player will sometimes still be in a state that isn't fully ducked. SetEntPropFloat(client, Prop_Send, "m_flDuckAmount", 1.0, 0); + SetEntProp(client, Prop_Send, "m_bDucking", false); SetEntProp(client, Prop_Send, "m_bDucked", true); } From 7e5ee571ad2191ae65aba0e3d31ee3a2eb9183ef Mon Sep 17 00:00:00 2001 From: zealain Date: Wed, 3 May 2023 20:27:38 +0200 Subject: [PATCH 47/47] Bumped mode versions --- addons/sourcemod/scripting/gokz-mode-kztimer.sp | 2 +- addons/sourcemod/scripting/gokz-mode-simplekz.sp | 2 +- addons/sourcemod/scripting/gokz-mode-vanilla.sp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/sourcemod/scripting/gokz-mode-kztimer.sp b/addons/sourcemod/scripting/gokz-mode-kztimer.sp index d4c807f7..272652b1 100644 --- a/addons/sourcemod/scripting/gokz-mode-kztimer.sp +++ b/addons/sourcemod/scripting/gokz-mode-kztimer.sp @@ -29,7 +29,7 @@ public Plugin myinfo = #define UPDATER_URL GOKZ_UPDATER_BASE_URL..."gokz-mode-kztimer.txt" -#define MODE_VERSION 216 +#define MODE_VERSION 217 #define DUCK_SPEED_NORMAL 8.0 #define PRE_VELMOD_MAX 1.104 // Calculated 276/250 #define PERF_SPEED_CAP 380.0 diff --git a/addons/sourcemod/scripting/gokz-mode-simplekz.sp b/addons/sourcemod/scripting/gokz-mode-simplekz.sp index 6c226402..99d76ac6 100644 --- a/addons/sourcemod/scripting/gokz-mode-simplekz.sp +++ b/addons/sourcemod/scripting/gokz-mode-simplekz.sp @@ -29,7 +29,7 @@ public Plugin myinfo = #define UPDATER_URL GOKZ_UPDATER_BASE_URL..."gokz-mode-simplekz.txt" -#define MODE_VERSION 20 +#define MODE_VERSION 21 #define PS_MAX_REWARD_TURN_RATE 0.703125 // Degrees per tick (90 degrees per second) #define PS_MAX_TURN_RATE_DECREMENT 0.015625 // Degrees per tick (2 degrees per second) #define PS_SPEED_MAX 26.54321 // Units diff --git a/addons/sourcemod/scripting/gokz-mode-vanilla.sp b/addons/sourcemod/scripting/gokz-mode-vanilla.sp index 14a1fc76..aecc201b 100644 --- a/addons/sourcemod/scripting/gokz-mode-vanilla.sp +++ b/addons/sourcemod/scripting/gokz-mode-vanilla.sp @@ -29,7 +29,7 @@ public Plugin myinfo = #define UPDATER_URL GOKZ_UPDATER_BASE_URL..."gokz-mode-vanilla.txt" -#define MODE_VERSION 16 +#define MODE_VERSION 17 float gF_ModeCVarValues[MODECVAR_COUNT] = {