From 216c729c8762f4d0388d8750905a91fe1de64ccf Mon Sep 17 00:00:00 2001 From: aura Date: Sat, 25 Apr 2026 22:46:52 +0200 Subject: wip on removing gokz gamemode features --- source/sourcemod/scripting/gokz-anticheat.sp | 4 +- source/sourcemod/scripting/gokz-core.sp | 6 +- source/sourcemod/scripting/gokz-core/demofix.sp | 47 +- source/sourcemod/scripting/gokz-core/misc.sp | 9 +- source/sourcemod/scripting/gokz-errorboxfixer.sp | 89 --- source/sourcemod/scripting/gokz-global.sp | 740 ------------------ source/sourcemod/scripting/gokz-goto.sp | 231 ------ source/sourcemod/scripting/gokz-hud.sp | 3 +- source/sourcemod/scripting/gokz-mode-kztimer.sp | 709 ----------------- source/sourcemod/scripting/gokz-mode-simplekz.sp | 846 --------------------- source/sourcemod/scripting/gokz-paint.sp | 410 ---------- source/sourcemod/scripting/gokz-pistol.sp | 303 -------- source/sourcemod/scripting/gokz-playermodels.sp | 198 ----- source/sourcemod/scripting/gokz-profile.sp | 396 ---------- source/sourcemod/scripting/gokz-quiet.sp | 151 ---- source/sourcemod/scripting/gokz-racing.sp | 174 ----- source/sourcemod/scripting/gokz-replays.sp | 397 ---------- source/sourcemod/scripting/gokz-slayonend.sp | 190 ----- source/sourcemod/scripting/gokz-spec.sp | 323 -------- source/sourcemod/scripting/gokz-tips.sp | 357 --------- source/sourcemod/scripting/include/dhooks.inc | 731 ++++++++---------- source/sourcemod/scripting/include/gokz.inc | 44 +- source/sourcemod/scripting/include/movementapi.inc | 2 +- source/sourcemod/scripting/movementapi.sp | 239 ++++++ source/sourcemod/scripting/movementapi/forwards.sp | 268 +++++++ source/sourcemod/scripting/movementapi/hooks.sp | 580 ++++++++++++++ source/sourcemod/scripting/movementapi/natives.sp | 183 +++++ source/sourcemod/scripting/movementapi/stocks.sp | 200 +++++ 28 files changed, 1854 insertions(+), 5976 deletions(-) delete mode 100644 source/sourcemod/scripting/gokz-errorboxfixer.sp delete mode 100644 source/sourcemod/scripting/gokz-global.sp delete mode 100644 source/sourcemod/scripting/gokz-goto.sp delete mode 100644 source/sourcemod/scripting/gokz-mode-kztimer.sp delete mode 100644 source/sourcemod/scripting/gokz-mode-simplekz.sp delete mode 100644 source/sourcemod/scripting/gokz-paint.sp delete mode 100644 source/sourcemod/scripting/gokz-pistol.sp delete mode 100644 source/sourcemod/scripting/gokz-playermodels.sp delete mode 100644 source/sourcemod/scripting/gokz-profile.sp delete mode 100644 source/sourcemod/scripting/gokz-quiet.sp delete mode 100644 source/sourcemod/scripting/gokz-racing.sp delete mode 100644 source/sourcemod/scripting/gokz-replays.sp delete mode 100644 source/sourcemod/scripting/gokz-slayonend.sp delete mode 100644 source/sourcemod/scripting/gokz-spec.sp delete mode 100644 source/sourcemod/scripting/gokz-tips.sp create mode 100644 source/sourcemod/scripting/movementapi.sp create mode 100644 source/sourcemod/scripting/movementapi/forwards.sp create mode 100644 source/sourcemod/scripting/movementapi/hooks.sp create mode 100644 source/sourcemod/scripting/movementapi/natives.sp create mode 100644 source/sourcemod/scripting/movementapi/stocks.sp (limited to 'source/sourcemod/scripting') diff --git a/source/sourcemod/scripting/gokz-anticheat.sp b/source/sourcemod/scripting/gokz-anticheat.sp index 9925eca..e35f025 100644 --- a/source/sourcemod/scripting/gokz-anticheat.sp +++ b/source/sourcemod/scripting/gokz-anticheat.sp @@ -167,7 +167,7 @@ public MRESReturn DHooks_OnTeleport(int client, Handle params) public void GOKZ_OnFirstSpawn(int client) { - GOKZ_PrintToChat(client, false, "%t", "Anti-Cheat Warning"); + // GOKZ_PrintToChat(client, false, "%t", "Anti-Cheat Warning"); } public void GOKZ_AC_OnPlayerSuspected(int client, ACReason reason, const char[] notes, const char[] stats) @@ -315,4 +315,4 @@ static void AutoBanClient(int client, int minutes, const char[] reason, const ch { BanClient(client, minutes, BANFLAG_AUTO, reason, kickMessage, "gokz-anticheat", 0); } -} \ No newline at end of file +} diff --git a/source/sourcemod/scripting/gokz-core.sp b/source/sourcemod/scripting/gokz-core.sp index 897403f..429bab5 100644 --- a/source/sourcemod/scripting/gokz-core.sp +++ b/source/sourcemod/scripting/gokz-core.sp @@ -216,7 +216,7 @@ public void OnPlayerSpawn(Event event, const char[] name, bool dontBroadcast) // OnPlayerSpawn_Pause(client); OnPlayerSpawn_ValidJump(client); OnPlayerSpawn_FirstSpawn(client); - OnPlayerSpawn_GodMode(client); + // OnPlayerSpawn_GodMode(client); OnPlayerSpawn_PlayerCollision(client); } } @@ -439,7 +439,7 @@ public void OnRoundStart(Event event, const char[] name, bool dontBroadcast) // public Action CS_OnTerminateRound(float &delay, CSRoundEndReason &reason) { - return Plugin_Handled; + return Plugin_Continue; } public void GOKZ_OnModeUnloaded(int mode) @@ -540,4 +540,4 @@ static bool IsRealObjective(char[] objective) { return StrEqual(objective, "PRISON ESCAPE") || StrEqual(objective, "DEATHMATCH") || StrEqual(objective, "BOMB TARGET") || StrEqual(objective, "HOSTAGE RESCUE"); -} \ No newline at end of file +} diff --git a/source/sourcemod/scripting/gokz-core/demofix.sp b/source/sourcemod/scripting/gokz-core/demofix.sp index 84a9307..3839fad 100644 --- a/source/sourcemod/scripting/gokz-core/demofix.sp +++ b/source/sourcemod/scripting/gokz-core/demofix.sp @@ -8,7 +8,7 @@ void OnPluginStart_Demofix() CV_EnableDemofix = AutoExecConfig_CreateConVar("gokz_demofix", "1", "Whether GOKZ applies demo record fix to server. (0 = Disabled, 1 = Update warmup period once, 2 = Regularly reset warmup period)", _, true, 0.0, true, 2.0); CV_EnableDemofix.AddChangeHook(OnDemofixConVarChanged); // If the map is tweaking the warmup value, we need to rerun the fix again. - FindConVar("mp_warmuptime").AddChangeHook(OnDemofixConVarChanged); + // FindConVar("mp_warmuptime").AddChangeHook(OnDemofixConVarChanged); // We assume that the map is already loaded on late load. if (gB_LateLoad) { @@ -28,7 +28,7 @@ void OnMapEnd_Demofix() void OnRoundStart_Demofix() { - DoDemoFix(); + // DoDemoFix(); } public Action Command_Demorestart(int client, const char[] command, int argc) @@ -53,7 +53,7 @@ static void FixRecord(int client) public void OnDemofixConVarChanged(ConVar convar, const char[] oldValue, const char[] newValue) { - DoDemoFix(); + // DoDemoFix(); } public Action Timer_EnableDemoRecord(Handle timer) @@ -64,47 +64,10 @@ public Action Timer_EnableDemoRecord(Handle timer) static void DoDemoFix() { - if (H_DemofixTimer != null) - { - delete H_DemofixTimer; - } - // Setting the cvar value to 1 can avoid clogging the demo file and slightly increase performance. - switch (CV_EnableDemofix.IntValue) - { - case 0: - { - if (!mapRunning) - { - return; - } - GameRules_SetProp("m_bWarmupPeriod", 0); - } - case 1: - { - // Set warmup time to 2^31-1, effectively forever - if (FindConVar("mp_warmuptime").IntValue != 2147483647) - { - FindConVar("mp_warmuptime").SetInt(2147483647); - } - EnableDemoRecord(); - } - case 2: - { - H_DemofixTimer = CreateTimer(1.0, Timer_EnableDemoRecord, _, TIMER_REPEAT); - } - } } static void EnableDemoRecord() { - // Enable warmup to allow demo recording - // m_fWarmupPeriodEnd is set in the past to hide the timer UI - if (!mapRunning) - { - return; - } - GameRules_SetProp("m_bWarmupPeriod", 1); - GameRules_SetPropFloat("m_fWarmupPeriodStart", GetGameTime() - 1.0); - GameRules_SetPropFloat("m_fWarmupPeriodEnd", GetGameTime() - 1.0); -} \ No newline at end of file + +} diff --git a/source/sourcemod/scripting/gokz-core/misc.sp b/source/sourcemod/scripting/gokz-core/misc.sp index a117880..ae44a1d 100644 --- a/source/sourcemod/scripting/gokz-core/misc.sp +++ b/source/sourcemod/scripting/gokz-core/misc.sp @@ -208,7 +208,7 @@ void OnPlayerRunCmd_Turnbinds(int client, int buttons, int tickcount, float angl void OnPlayerSpawn_PlayerCollision(int client) { // Let players go through other players - SetEntProp(client, Prop_Send, "m_CollisionGroup", GOKZ_COLLISION_GROUP_STANDARD); + // SetEntProp(client, Prop_Send, "m_CollisionGroup", GOKZ_COLLISION_GROUP_STANDARD); } void OnSetModel_PlayerCollision(int client) @@ -230,7 +230,7 @@ void OnSetModel_PlayerCollision(int client) void OnRoundStart_ForceAllTalk() { - gCV_sv_full_alltalk.BoolValue = true; + // gCV_sv_full_alltalk.BoolValue = true; } @@ -350,7 +350,10 @@ void JoinTeam(int client, int newTeam, bool restorePos, bool forceBroadcast = fa // Need to teleport the player to a valid one. float spawnOrigin[3]; float spawnAngles[3]; - GetValidSpawn(spawnOrigin, spawnAngles); + if (newTeam == CS_TEAM_CT) + GetValidSpawnCT(spawnOrigin, spawnAngles); + else + GetValidSpawnT(spawnOrigin, spawnAngles); TeleportPlayer(client, spawnOrigin, spawnAngles); } hasSavedPosition[client] = false; diff --git a/source/sourcemod/scripting/gokz-errorboxfixer.sp b/source/sourcemod/scripting/gokz-errorboxfixer.sp deleted file mode 100644 index fd3f76a..0000000 --- a/source/sourcemod/scripting/gokz-errorboxfixer.sp +++ /dev/null @@ -1,89 +0,0 @@ -#include -#include - -#include - -#undef REQUIRE_PLUGIN -#include - -#pragma newdecls required -#pragma semicolon 1 - -public Plugin myinfo = -{ - name = "GOKZ KZErrorBoxFixer", - author = "1NutWunDeR", - description = "Adds missing models for KZ maps", - version = GOKZ_VERSION, - url = GOKZ_SOURCE_URL -}; - -#define UPDATER_URL GOKZ_UPDATER_BASE_URL..."gokz-errorboxfixer.txt" - -public void OnAllPluginsLoaded() -{ - if (LibraryExists("updater")) - { - Updater_AddPlugin(UPDATER_URL); - } -} - -public void OnLibraryAdded(const char[] name) -{ - if (StrEqual(name, "updater")) - { - Updater_AddPlugin(UPDATER_URL); - } -} - -public void OnMapStart() -{ - AddFileToDownloadsTable("models/kzmod/buttons/stand_button.vtf"); - AddFileToDownloadsTable("models/kzmod/buttons/stand_button.vmt"); - AddFileToDownloadsTable("models/kzmod/buttons/stand_button_normal.vtf"); - AddFileToDownloadsTable("models/kzmod/buttons/standing_button.mdl"); - AddFileToDownloadsTable("models/kzmod/buttons/standing_button.dx90.vtx"); - AddFileToDownloadsTable("models/kzmod/buttons/standing_button.phy"); - AddFileToDownloadsTable("models/kzmod/buttons/standing_button.vvd"); - AddFileToDownloadsTable("models/kzmod/buttons/stone_button.mdl"); - AddFileToDownloadsTable("models/kzmod/buttons/stone_button.dx90.vtx"); - AddFileToDownloadsTable("models/kzmod/buttons/stone_button.phy"); - AddFileToDownloadsTable("models/kzmod/buttons/stone_button.vvd"); - AddFileToDownloadsTable("models/props_wasteland/pipecluster002a.mdl"); - AddFileToDownloadsTable("models/props_wasteland/pipecluster002a.dx90.vtx"); - AddFileToDownloadsTable("models/props_wasteland/pipecluster002a.phy"); - AddFileToDownloadsTable("models/props_wasteland/pipecluster002a.vvd"); - AddFileToDownloadsTable("materials/kzmod/starttimersign.vmt"); - AddFileToDownloadsTable("materials/kzmod/starttimersign.vtf"); - AddFileToDownloadsTable("materials/kzmod/stoptimersign.vmt"); - AddFileToDownloadsTable("materials/kzmod/stoptimersign.vtf"); - AddFileToDownloadsTable("models/props/switch001.mdl"); - AddFileToDownloadsTable("models/props/switch001.vvd"); - AddFileToDownloadsTable("models/props/switch001.phy"); - AddFileToDownloadsTable("models/props/switch001.vtx"); - AddFileToDownloadsTable("models/props/switch001.dx90.vtx"); - AddFileToDownloadsTable("materials/models/props/switch.vmt"); - AddFileToDownloadsTable("materials/models/props/switch.vtf"); - AddFileToDownloadsTable("materials/models/props/switch001.vmt"); - AddFileToDownloadsTable("materials/models/props/switch001.vtf"); - AddFileToDownloadsTable("materials/models/props/switch001_normal.vmt"); - AddFileToDownloadsTable("materials/models/props/switch001_normal.vtf"); - AddFileToDownloadsTable("materials/models/props/switch001_lightwarp.vmt"); - AddFileToDownloadsTable("materials/models/props/switch001_lightwarp.vtf"); - AddFileToDownloadsTable("materials/models/props/switch001_exponent.vmt"); - AddFileToDownloadsTable("materials/models/props/switch001_exponent.vtf"); - AddFileToDownloadsTable("materials/models/props/startkztimer.vmt"); - AddFileToDownloadsTable("materials/models/props/startkztimer.vtf"); - AddFileToDownloadsTable("materials/models/props/stopkztimer.vmt"); - AddFileToDownloadsTable("materials/models/props/stopkztimer.vtf"); - - PrecacheModel("models/kzmod/buttons/stand_button.vmt", true); - PrecacheModel("models/props_wasteland/pipecluster002a.mdl", true); - PrecacheModel("models/kzmod/buttons/standing_button.mdl", true); - PrecacheModel("models/kzmod/buttons/stone_button.mdl", true); - PrecacheModel("materials/kzmod/starttimersign.vmt", true); - PrecacheModel("materials/kzmod/stoptimersign.vmt", true); - PrecacheModel("models/props/switch001.mdl", true); - PrecacheModel("materials/models/props/startkztimer.vmt", true); - PrecacheModel("materials/models/props/stopkztimer.vmt", true); -} diff --git a/source/sourcemod/scripting/gokz-global.sp b/source/sourcemod/scripting/gokz-global.sp deleted file mode 100644 index 79f8b6a..0000000 --- a/source/sourcemod/scripting/gokz-global.sp +++ /dev/null @@ -1,740 +0,0 @@ -#include - -#include - -#include -#include -#include -#include -#include -#include - -#include - -#undef REQUIRE_EXTENSIONS -#undef REQUIRE_PLUGIN -#include -#include -#include - -#include - -#pragma newdecls required -#pragma semicolon 1 - - - -public Plugin myinfo = -{ - name = "GOKZ Global", - author = "DanZay", - description = "Provides centralised records and bans via GlobalAPI", - version = GOKZ_VERSION, - url = GOKZ_SOURCE_URL -}; - -#define UPDATER_URL GOKZ_UPDATER_BASE_URL..."gokz-global.txt" - -bool gB_GOKZLocalDB; - -bool gB_APIKeyCheck; -bool gB_ModeCheck[MODE_COUNT]; -bool gB_BannedCommandsCheck; -char gC_CurrentMap[64]; -int gI_CurrentMapFileSize; -bool gB_InValidRun[MAXPLAYERS + 1]; -bool gB_GloballyVerified[MAXPLAYERS + 1]; -bool gB_EnforcerOnFreshMap; -bool gB_JustLateLoaded; -int gI_FPSMax[MAXPLAYERS + 1]; -bool gB_waitingForFPSKick[MAXPLAYERS + 1]; -bool gB_MapValidated; -int gI_MapID; -int gI_MapFileSize; -int gI_MapTier; - -ConVar gCV_gokz_settings_enforcer; -ConVar gCV_gokz_warn_for_non_global_map; -ConVar gCV_EnforcedCVar[ENFORCEDCVAR_COUNT]; - -#include "gokz-global/api.sp" -#include "gokz-global/ban_player.sp" -#include "gokz-global/commands.sp" -#include "gokz-global/maptop_menu.sp" -#include "gokz-global/print_records.sp" -#include "gokz-global/send_run.sp" -#include "gokz-global/points.sp" - - - -// =====[ PLUGIN EVENTS ]===== - -public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) -{ - CreateNatives(); - RegPluginLibrary("gokz-global"); - gB_JustLateLoaded = late; - return APLRes_Success; -} - -public void OnPluginStart() -{ - if (FloatAbs(1.0 / GetTickInterval() - 128.0) > EPSILON) - { - SetFailState("gokz-global currently only supports 128 tickrate servers."); - } - if (FindCommandLineParam("-insecure") || FindCommandLineParam("-tools")) - { - SetFailState("gokz-global currently only supports VAC-secured servers."); - } - LoadTranslations("gokz-common.phrases"); - LoadTranslations("gokz-global.phrases"); - - gB_APIKeyCheck = false; - gB_MapValidated = false; - gI_MapID = -1; - gI_MapFileSize = -1; - gI_MapTier = -1; - - for (int mode = 0; mode < MODE_COUNT; mode++) - { - gB_ModeCheck[mode] = false; - } - - CreateConVars(); - CreateGlobalForwards(); - RegisterCommands(); -} - -public void OnAllPluginsLoaded() -{ - if (LibraryExists("updater")) - { - Updater_AddPlugin(UPDATER_URL); - } - gB_GOKZLocalDB = LibraryExists("gokz-localdb"); - - for (int client = 1; client <= MaxClients; client++) - { - if (IsClientInGame(client)) - { - OnClientPutInServer(client); - } - } -} - -public void OnLibraryAdded(const char[] name) -{ - if (StrEqual(name, "updater")) - { - Updater_AddPlugin(UPDATER_URL); - } - gB_GOKZLocalDB = gB_GOKZLocalDB || StrEqual(name, "gokz-localdb"); -} - -public void OnLibraryRemoved(const char[] name) -{ - gB_GOKZLocalDB = gB_GOKZLocalDB && !StrEqual(name, "gokz-localdb"); -} - -Action IntegrityChecks(Handle timer) -{ - for (int client = 1; client <= MaxClients; client++) - { - if (IsValidClient(client) && !IsFakeClient(client)) - { - QueryClientConVar(client, "fps_max", FPSCheck, client); - QueryClientConVar(client, "m_yaw", MYAWCheck, client); - } - } - - for (int i = 0; i < BANNEDPLUGINCOMMAND_COUNT; i++) - { - if (CommandExists(gC_BannedPluginCommands[i])) - { - Handle bannedIterator = GetPluginIterator(); - char pluginName[128]; - bool foundPlugin = false; - while (MorePlugins(bannedIterator)) - { - Handle bannedPlugin = ReadPlugin(bannedIterator); - GetPluginInfo(bannedPlugin, PlInfo_Name, pluginName, sizeof(pluginName)); - if (StrEqual(pluginName, gC_BannedPlugins[i])) - { - char pluginPath[128]; - GetPluginFilename(bannedPlugin, pluginPath, sizeof(pluginPath)); - ServerCommand("sm plugins unload %s", pluginPath); - char disabledPath[256], enabledPath[256], pluginFile[4][128]; - int subfolders = ExplodeString(pluginPath, "/", pluginFile, sizeof(pluginFile), sizeof(pluginFile[])); - BuildPath(Path_SM, disabledPath, sizeof(disabledPath), "plugins/disabled/%s", pluginFile[subfolders - 1]); - BuildPath(Path_SM, enabledPath, sizeof(enabledPath), "plugins/%s", pluginPath); - RenameFile(disabledPath, enabledPath); - LogError("[KZ] %s cannot be loaded at the same time as gokz-global. %s has been disabled.", pluginName, pluginName); - delete bannedPlugin; - foundPlugin = true; - break; - } - delete bannedPlugin; - } - if (!foundPlugin && gB_BannedCommandsCheck) - { - gB_BannedCommandsCheck = false; - LogError("You can't have a plugin which implements the %s command. Please disable it and reload the map.", gC_BannedPluginCommands[i]); - } - delete bannedIterator; - } - } - - return Plugin_Handled; -} - -public void FPSCheck(QueryCookie cookie, int client, ConVarQueryResult result, const char[] cvarName, const char[] cvarValue, any value) -{ - if (IsValidClient(client) && !IsFakeClient(client)) - { - gI_FPSMax[client] = StringToInt(cvarValue); - if (gI_FPSMax[client] > 0 && gI_FPSMax[client] < GL_FPS_MAX_MIN_VALUE) - { - if (!gB_waitingForFPSKick[client]) - { - gB_waitingForFPSKick[client] = true; - CreateTimer(GL_FPS_MAX_KICK_TIMEOUT, FPSKickPlayer, GetClientUserId(client), TIMER_FLAG_NO_MAPCHANGE); - GOKZ_PrintToChat(client, true, "%t", "Warn Player fps_max"); - if (GOKZ_GetTimerRunning(client)) - { - GOKZ_StopTimer(client, true); - } - else - { - GOKZ_EmitSoundToClient(client, GOKZ_SOUND_TIMER_STOP, _, "Timer Stop"); - } - } - } - else - { - gB_waitingForFPSKick[client] = false; - } - } -} - -public void MYAWCheck(QueryCookie cookie, int client, ConVarQueryResult result, const char[] cvarName, const char[] cvarValue, any value) -{ - if (IsValidClient(client) && !IsFakeClient(client) && StringToFloat(cvarValue) > GL_MYAW_MAX_VALUE) - { - KickClient(client, "%T", "Kick Player m_yaw", client); - } -} - -Action FPSKickPlayer(Handle timer, int userid) -{ - int client = GetClientOfUserId(userid); - if (IsValidClient(client) && !IsFakeClient(client) && gB_waitingForFPSKick[client]) - { - KickClient(client, "%T", "Kick Player fps_max", client); - } - - return Plugin_Handled; -} - - - -// =====[ CLIENT EVENTS ]===== - -public void OnClientPutInServer(int client) -{ - gB_GloballyVerified[client] = false; - gB_waitingForFPSKick[client] = false; - OnClientPutInServer_PrintRecords(client); -} - -// OnClientAuthorized is apparently too early -public void OnClientPostAdminCheck(int client) -{ - ResetPoints(client); - - if (GlobalAPI_IsInit() && !IsFakeClient(client)) - { - CheckClientGlobalBan(client); - UpdatePoints(client); - } -} - -public void GlobalAPI_OnInitialized() -{ - SetupAPI(); -} - - -public Action GOKZ_OnTimerStart(int client, int course) -{ - KZPlayer player = KZPlayer(client); - int mode = player.Mode; - - // We check the timer running to prevent spam when standing inside VB. - if (gCV_gokz_warn_for_non_global_map.BoolValue - && GlobalAPI_HasAPIKey() - && !GlobalsEnabled(mode) - && !GOKZ_GetTimerRunning(client)) - { - GOKZ_PrintToChat(client, true, "%t", "Warn Player Not Global Run"); - } - - return Plugin_Continue; -} - -public void GOKZ_OnTimerStart_Post(int client, int course) -{ - KZPlayer player = KZPlayer(client); - int mode = player.Mode; - gB_InValidRun[client] = GlobalsEnabled(mode); -} - -public void GOKZ_OnTimerEnd_Post(int client, int course, float time, int teleportsUsed) -{ - if (gB_GloballyVerified[client] && gB_InValidRun[client]) - { - SendTime(client, course, time, teleportsUsed); - } -} - -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, tempReplay); - return Plugin_Handled; - } - return Plugin_Continue; -} - -public void GOKZ_OnRunInvalidated(int client) -{ - gB_InValidRun[client] = false; -} - -public void GOKZ_GL_OnNewTopTime(int client, int course, int mode, int timeType, int rank, int rankOverall, float runTime) -{ - AnnounceNewTopTime(client, course, mode, timeType, rank, rankOverall); -} - -public void GOKZ_AC_OnPlayerSuspected(int client, ACReason reason, const char[] notes, const char[] stats) -{ - if (!gB_GloballyVerified[client]) - { - return; - } - - GlobalBanPlayer(client, reason, notes, stats); - gB_GloballyVerified[client] = false; -} - - - -// =====[ OTHER EVENTS ]===== - -public void OnMapStart() -{ - LoadSounds(); - - GetCurrentMapDisplayName(gC_CurrentMap, sizeof(gC_CurrentMap)); - gI_CurrentMapFileSize = GetCurrentMapFileSize(); - - gB_BannedCommandsCheck = true; - - // Prevent just reloading the plugin after messing with the map - if (gB_JustLateLoaded) - { - gB_JustLateLoaded = false; - } - else - { - gB_EnforcerOnFreshMap = true; - } - - // In case of late loading - if (GlobalAPI_IsInit()) - { - GlobalAPI_OnInitialized(); - } - - // Setup a timer to monitor server/client integrity - CreateTimer(1.0, IntegrityChecks, INVALID_HANDLE, TIMER_FLAG_NO_MAPCHANGE | TIMER_REPEAT); -} - -public void OnMapEnd() -{ - // So it doesn't get carried over to the next map - gI_MapID = -1; - for (int client = 1; client < MaxClients; client++) - { - ResetMapPoints(client); - } -} - -public void GOKZ_OnOptionChanged(int client, const char[] option, any newValue) -{ - if (StrEqual(option, gC_CoreOptionNames[Option_Mode]) - && GlobalAPI_IsInit()) - { - UpdatePoints(client); - } -} - -public void GOKZ_OnModeUnloaded(int mode) -{ - gB_ModeCheck[mode] = false; -} - -public Action GOKZ_OnTimerNativeCalledExternally(Handle plugin, int client) -{ - char pluginName[64]; - GetPluginInfo(plugin, PlInfo_Name, pluginName, sizeof(pluginName)); - if (GOKZ_GetTimerRunning(client) && GOKZ_GetValidTimer(client)) - { - LogMessage("Invalidated %N's run as gokz-core native was called by \"%s\"", client, pluginName); - } - GOKZ_InvalidateRun(client); - return Plugin_Continue; -} - - - -// =====[ PUBLIC ]===== - -bool GlobalsEnabled(int mode) -{ - return gB_APIKeyCheck && gB_BannedCommandsCheck && gCV_gokz_settings_enforcer.BoolValue && gB_EnforcerOnFreshMap && MapCheck() && gB_ModeCheck[mode]; -} - -bool MapCheck() -{ - return gB_MapValidated - && gI_MapID > 0 - && gI_MapFileSize == gI_CurrentMapFileSize; -} - -void PrintGlobalCheckToChat(int client) -{ - GOKZ_PrintToChat(client, true, "%t", "Global Check Header"); - GOKZ_PrintToChat(client, false, "%t", "Global Check", - gB_APIKeyCheck ? "{green}✓" : "{darkred}X", - gB_BannedCommandsCheck ? "{green}✓" : "{darkred}X", - gCV_gokz_settings_enforcer.BoolValue && gB_EnforcerOnFreshMap ? "{green}✓" : "{darkred}X", - MapCheck() ? "{green}✓" : "{darkred}X", - gB_GloballyVerified[client] ? "{green}✓" : "{darkred}X"); - - char modeCheck[256]; - FormatEx(modeCheck, sizeof(modeCheck), "{purple}%s %s", gC_ModeNames[0], gB_ModeCheck[0] ? "{green}✓" : "{darkred}X"); - for (int i = 1; i < MODE_COUNT; i++) - { - FormatEx(modeCheck, sizeof(modeCheck), "%s {grey}| {purple}%s %s", modeCheck, gC_ModeNames[i], gB_ModeCheck[i] ? "{green}✓" : "{darkred}X"); - } - GOKZ_PrintToChat(client, false, "%s", modeCheck); -} - -void AnnounceNewTopTime(int client, int course, int mode, int timeType, int rank, int rankOverall) -{ - bool newRecord = false; - - if (timeType == TimeType_Nub && rankOverall != 0) - { - if (rankOverall == 1) - { - if (course == 0) - { - GOKZ_PrintToChatAll(true, "%t", "New Global Record (NUB)", client, gC_ModeNamesShort[mode]); - } - else - { - GOKZ_PrintToChatAll(true, "%t", "New Global Bonus Record (NUB)", client, course, gC_ModeNamesShort[mode]); - } - newRecord = true; - } - else - { - if (course == 0) - { - GOKZ_PrintToChatAll(true, "%t", "New Global Top Time (NUB)", client, rankOverall, gC_ModeNamesShort[mode]); - } - else - { - GOKZ_PrintToChatAll(true, "%t", "New Global Top Bonus Time (NUB)", client, rankOverall, course, gC_ModeNamesShort[mode]); - } - } - } - else if (timeType == TimeType_Pro) - { - if (rankOverall != 0) - { - if (rankOverall == 1) - { - if (course == 0) - { - GOKZ_PrintToChatAll(true, "%t", "New Global Record (NUB)", client, gC_ModeNamesShort[mode]); - } - else - { - GOKZ_PrintToChatAll(true, "%t", "New Global Bonus Record (NUB)", client, course, gC_ModeNamesShort[mode]); - } - newRecord = true; - } - else - { - if (course == 0) - { - GOKZ_PrintToChatAll(true, "%t", "New Global Top Time (NUB)", client, rankOverall, gC_ModeNamesShort[mode]); - } - else - { - GOKZ_PrintToChatAll(true, "%t", "New Global Top Bonus Time (NUB)", client, rankOverall, course, gC_ModeNamesShort[mode]); - } - } - } - - if (rank == 1) - { - if (course == 0) - { - GOKZ_PrintToChatAll(true, "%t", "New Global Record (PRO)", client, gC_ModeNamesShort[mode]); - } - else - { - GOKZ_PrintToChatAll(true, "%t", "New Global Bonus Record (PRO)", client, course, gC_ModeNamesShort[mode]); - } - newRecord = true; - } - else - { - if (course == 0) - { - GOKZ_PrintToChatAll(true, "%t", "New Global Top Time (PRO)", client, rank, gC_ModeNamesShort[mode]); - } - else - { - GOKZ_PrintToChatAll(true, "%t", "New Global Top Bonus Time (PRO)", client, rank, course, gC_ModeNamesShort[mode]); - } - } - } - - if (newRecord) - { - PlayBeatRecordSound(); - } -} - -void PlayBeatRecordSound() -{ - GOKZ_EmitSoundToAll(GL_SOUND_NEW_RECORD, _, "World Record"); -} - - - -// =====[ PRIVATE ]===== - -static void CreateConVars() -{ - AutoExecConfig_SetFile("gokz-global", "sourcemod/gokz"); - AutoExecConfig_SetCreateFile(true); - - gCV_gokz_settings_enforcer = AutoExecConfig_CreateConVar("gokz_settings_enforcer", "1", "Whether GOKZ enforces convars required for global records.", _, true, 0.0, true, 1.0); - gCV_gokz_warn_for_non_global_map = AutoExecConfig_CreateConVar("gokz_warn_for_non_global_map", "1", "Whether or not GOKZ should warn players if the global check does not pass.", _, true, 0.0, true, 1.0); - gCV_gokz_settings_enforcer.AddChangeHook(OnConVarChanged); - - AutoExecConfig_ExecuteFile(); - AutoExecConfig_CleanFile(); - - for (int i = 0; i < ENFORCEDCVAR_COUNT; i++) - { - gCV_EnforcedCVar[i] = FindConVar(gC_EnforcedCVars[i]); - gCV_EnforcedCVar[i].FloatValue = gF_EnforcedCVarValues[i]; - gCV_EnforcedCVar[i].AddChangeHook(OnEnforcedConVarChanged); - } -} - -public void OnConVarChanged(ConVar convar, const char[] oldValue, const char[] newValue) -{ - if (convar == gCV_gokz_settings_enforcer) - { - if (gCV_gokz_settings_enforcer.BoolValue) - { - for (int i = 0; i < ENFORCEDCVAR_COUNT; i++) - { - gCV_EnforcedCVar[i].FloatValue = gF_EnforcedCVarValues[i]; - } - } - else - { - for (int client = 1; client <= MaxClients; client++) - { - gB_InValidRun[client] = false; - } - - // You have to change map before you can re-activate that - gB_EnforcerOnFreshMap = false; - } - } -} - -public void OnEnforcedConVarChanged(ConVar convar, const char[] oldValue, const char[] newValue) -{ - if (gCV_gokz_settings_enforcer.BoolValue) - { - for (int i = 0; i < ENFORCEDCVAR_COUNT; i++) - { - if (convar == gCV_EnforcedCVar[i]) - { - gCV_EnforcedCVar[i].FloatValue = gF_EnforcedCVarValues[i]; - return; - } - } - } -} - -static void SetupAPI() -{ - GlobalAPI_GetAuthStatus(GetAuthStatusCallback); - GlobalAPI_GetModes(GetModeInfoCallback); - GlobalAPI_GetMapByName(GetMapCallback, _, gC_CurrentMap); - - for (int client = 1; client <= MaxClients; client++) - { - if (IsValidClient(client) && !IsFakeClient(client)) - { - CheckClientGlobalBan(client); - } - } -} - -public int GetAuthStatusCallback(JSON_Object auth_json, GlobalAPIRequestData request) -{ - if (request.Failure) - { - LogError("Failed to check API key with Global API."); - return 0; - } - - APIAuth auth = view_as(auth_json); - if (!auth.IsValid) - { - LogError("Global API key was found to be missing or invalid."); - } - gB_APIKeyCheck = auth.IsValid; - return 0; -} - -public int GetModeInfoCallback(JSON_Object modes, GlobalAPIRequestData request) -{ - if (request.Failure) - { - LogError("Failed to check mode versions with Global API."); - return 0; - } - - if (!modes.IsArray) - { - LogError("GlobalAPI returned a malformed response while looking up the modes."); - return 0; - } - - for (int i = 0; i < modes.Length; i++) - { - APIMode mode = view_as(modes.GetObjectIndexed(i)); - int mode_id = GOKZ_GL_FromGlobalMode(view_as(mode.Id)); - if (mode_id == -1) - { - LogError("GlobalAPI returned a malformed mode."); - } - else if (mode.LatestVersion <= GOKZ_GetModeVersion(mode_id)) - { - gB_ModeCheck[mode_id] = true; - } - else - { - char desc[128]; - - gB_ModeCheck[mode_id] = false; - mode.GetLatestVersionDesc(desc, sizeof(desc)); - LogError("Global API requires %s mode version %d (%s). You have version %d (%s).", - gC_ModeNames[mode_id], mode.LatestVersion, desc, GOKZ_GetModeVersion(mode_id), GOKZ_VERSION); - } - } - return 0; -} - -public int GetMapCallback(JSON_Object map_json, GlobalAPIRequestData request) -{ - if (request.Failure || map_json == INVALID_HANDLE) - { - LogError("Failed to get map info."); - return 0; - } - - APIMap map = view_as(map_json); - - gB_MapValidated = map.IsValidated; - gI_MapID = map.Id; - gI_MapFileSize = map.Filesize; - gI_MapTier = map.Difficulty; - - // We don't do that earlier cause we need the map ID - for (int client = 1; client <= MaxClients; client++) - { - if (IsValidClient(client) && IsClientAuthorized(client) && !IsFakeClient(client)) - { - UpdatePoints(client); - } - } - return 0; -} - -void CheckClientGlobalBan(int client) -{ - char steamid[32]; - GetClientAuthId(client, AuthId_Steam2, steamid, sizeof(steamid)); - GlobalAPI_GetPlayerBySteamId(CheckClientGlobalBan_Callback, client, steamid); -} - -public void CheckClientGlobalBan_Callback(JSON_Object player_json, GlobalAPIRequestData request, int client) -{ - if (!IsValidClient(client)) - { - return; - } - - if (request.Failure) - { - LogError("Failed to get ban info."); - return; - } - - char client_steamid[32], response_steamid[32]; - GetClientAuthId(client, AuthId_Steam2, client_steamid, sizeof(client_steamid)); - - if (!player_json.IsArray || player_json.Length != 1) - { - LogError("Got malformed reply when querying steamid %s", client_steamid); - return; - } - - APIPlayer player = view_as(player_json.GetObjectIndexed(0)); - player.GetSteamId(response_steamid, sizeof(response_steamid)); - if (!StrEqual(client_steamid, response_steamid)) - { - return; - } - - gB_GloballyVerified[client] = !player.IsBanned; - - if (player.IsBanned && gB_GOKZLocalDB) - { - GOKZ_DB_SetCheater(client, true); - } -} - -static void LoadSounds() -{ - char downloadPath[PLATFORM_MAX_PATH]; - FormatEx(downloadPath, sizeof(downloadPath), "sound/%s", GL_SOUND_NEW_RECORD); - AddFileToDownloadsTable(downloadPath); - PrecacheSound(GL_SOUND_NEW_RECORD, true); -} \ No newline at end of file diff --git a/source/sourcemod/scripting/gokz-goto.sp b/source/sourcemod/scripting/gokz-goto.sp deleted file mode 100644 index 7dd67cb..0000000 --- a/source/sourcemod/scripting/gokz-goto.sp +++ /dev/null @@ -1,231 +0,0 @@ -#include - -#include -#include - -#include - -#undef REQUIRE_EXTENSIONS -#undef REQUIRE_PLUGIN -#include - -#pragma newdecls required -#pragma semicolon 1 - - - -public Plugin myinfo = -{ - name = "GOKZ Goto", - author = "DanZay", - description = "Allows players to teleport to another player", - version = GOKZ_VERSION, - url = GOKZ_SOURCE_URL -}; - -#define UPDATER_URL GOKZ_UPDATER_BASE_URL..."gokz-goto.txt" - - - -// =====[ PLUGIN EVENTS ]===== - -public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) -{ - RegPluginLibrary("gokz-goto"); - return APLRes_Success; -} - -public void OnPluginStart() -{ - LoadTranslations("common.phrases"); - LoadTranslations("gokz-common.phrases"); - LoadTranslations("gokz-goto.phrases"); - - RegisterCommands(); -} - -public void OnAllPluginsLoaded() -{ - if (LibraryExists("updater")) - { - Updater_AddPlugin(UPDATER_URL); - } -} - -public void OnLibraryAdded(const char[] name) -{ - if (StrEqual(name, "updater")) - { - Updater_AddPlugin(UPDATER_URL); - } -} - - - -// =====[ GOTO ]===== - -// Returns whether teleport to target was successful -bool GotoPlayer(int client, int target, bool printMessage = true) -{ - if (GOKZ_GetCoreOption(client, Option_Safeguard) > Safeguard_Disabled && GOKZ_GetTimerRunning(client) && GOKZ_GetValidTimer(client)) - { - if (printMessage) - { - GOKZ_PrintToChat(client, true, "%t", "Safeguard - Blocked"); - GOKZ_PlayErrorSound(client); - } - return false; - } - if (target == client) - { - if (printMessage) - { - GOKZ_PrintToChat(client, true, "%t", "Goto Failure (Not Yourself)"); - GOKZ_PlayErrorSound(client); - } - return false; - } - if (!IsPlayerAlive(target)) - { - if (printMessage) - { - GOKZ_PrintToChat(client, true, "%t", "Goto Failure (Dead)"); - GOKZ_PlayErrorSound(client); - } - return false; - } - - float targetOrigin[3]; - float targetAngles[3]; - - Movement_GetOrigin(target, targetOrigin); - Movement_GetEyeAngles(target, targetAngles); - - if (!IsPlayerAlive(client)) - { - GOKZ_RespawnPlayer(client); - } - - TeleportPlayer(client, targetOrigin, targetAngles); - - GOKZ_PrintToChat(client, true, "%t", "Goto Success", target); - - if (GOKZ_GetTimerRunning(client)) - { - GOKZ_PrintToChat(client, true, "%t", "Timer Stopped (Goto)"); - GOKZ_StopTimer(client); - } - - return true; -} - - - -// =====[ GOTO MENU ]===== - -int DisplayGotoMenu(int client) -{ - Menu menu = new Menu(MenuHandler_Goto); - menu.SetTitle("%T", "Goto Menu - Title", client); - int menuItems = GotoMenuAddItems(client, menu); - if (menuItems == 0) - { - delete menu; - } - else - { - menu.Display(client, MENU_TIME_FOREVER); - } - return menuItems; -} - -public int MenuHandler_Goto(Menu menu, MenuAction action, int param1, int param2) -{ - if (action == MenuAction_Select) - { - char info[16]; - menu.GetItem(param2, info, sizeof(info)); - int target = GetClientOfUserId(StringToInt(info)); - - if (!IsValidClient(target)) - { - GOKZ_PrintToChat(param1, true, "%t", "Player No Longer Valid"); - GOKZ_PlayErrorSound(param1); - DisplayGotoMenu(param1); - } - else if (!GotoPlayer(param1, target)) - { - DisplayGotoMenu(param1); - } - } - else if (action == MenuAction_End) - { - delete menu; - } - return 0; -} - -// Returns number of items added to the menu -int GotoMenuAddItems(int client, Menu menu) -{ - char display[MAX_NAME_LENGTH + 4]; - int targetCount = 0; - - for (int i = 1; i <= MaxClients; i++) - { - if (!IsClientInGame(i) || !IsPlayerAlive(i) || i == client) - { - continue; - } - - if (IsFakeClient(i)) - { - FormatEx(display, sizeof(display), "BOT %N", i); - } - else - { - FormatEx(display, sizeof(display), "%N", i); - } - - menu.AddItem(IntToStringEx(GetClientUserId(i)), display, ITEMDRAW_DEFAULT); - targetCount++; - } - - return targetCount; -} - - - -// =====[ COMMANDS ]===== - -void RegisterCommands() -{ - RegConsoleCmd("sm_goto", CommandGoto, "[KZ] Teleport to another player. Usage: !goto "); -} - -public Action CommandGoto(int client, int args) -{ - // If no arguments, display the goto menu - if (args < 1) - { - if (DisplayGotoMenu(client) == 0) - { - // No targets, so show error - GOKZ_PrintToChat(client, true, "%t", "No Players Found"); - GOKZ_PlayErrorSound(client); - } - } - // Otherwise try to teleport to the specified player - else - { - char specifiedPlayer[MAX_NAME_LENGTH]; - GetCmdArg(1, specifiedPlayer, sizeof(specifiedPlayer)); - - int target = FindTarget(client, specifiedPlayer, false, false); - if (target != -1) - { - GotoPlayer(client, target); - } - } - return Plugin_Handled; -} \ No newline at end of file diff --git a/source/sourcemod/scripting/gokz-hud.sp b/source/sourcemod/scripting/gokz-hud.sp index e9db12a..3a5b7e9 100644 --- a/source/sourcemod/scripting/gokz-hud.sp +++ b/source/sourcemod/scripting/gokz-hud.sp @@ -196,7 +196,6 @@ public void OnPlayerSpawn(Event event, const char[] name, bool dontBroadcast) // public Action OnPlayerDeath(Event event, const char[] name, bool dontBroadcast) // player_death pre hook { - event.BroadcastDisabled = true; // Block death notices return Plugin_Continue; } @@ -331,4 +330,4 @@ static void SetHUDInfo(KZPlayer player, HUDInfo info, int cmdnum) info.IsTakeoff = Movement_GetTakeoffCmdNum(player.ID) == cmdnum; info.Buttons = player.Buttons; info.CurrentTeleport = player.TeleportCount; -} \ No newline at end of file +} diff --git a/source/sourcemod/scripting/gokz-mode-kztimer.sp b/source/sourcemod/scripting/gokz-mode-kztimer.sp deleted file mode 100644 index 272652b..0000000 --- a/source/sourcemod/scripting/gokz-mode-kztimer.sp +++ /dev/null @@ -1,709 +0,0 @@ -#include - -#include -#include -#include - -#include - -#undef REQUIRE_EXTENSIONS -#undef REQUIRE_PLUGIN -#include -#include - -#include - -#pragma newdecls required -#pragma semicolon 1 - - - -public Plugin myinfo = -{ - name = "GOKZ Mode - KZTimer", - author = "DanZay", - description = "KZTimer mode for GOKZ", - version = GOKZ_VERSION, - url = GOKZ_SOURCE_URL -}; - -#define UPDATER_URL GOKZ_UPDATER_BASE_URL..."gokz-mode-kztimer.txt" - -#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 - -float gF_ModeCVarValues[MODECVAR_COUNT] = -{ - 6.5, // sv_accelerate - 0.0, // sv_accelerate_use_weapon_speed - 100.0, // sv_airaccelerate - 30.0, // sv_air_max_wishspeed - 1.0, // sv_enablebunnyhopping - 5.0, // sv_friction - 800.0, // sv_gravity - 301.993377, // sv_jump_impulse - 1.0, // sv_ladder_scale_speed - 0.0, // sv_ledge_mantle_helper - 320.0, // sv_maxspeed - 2000.0, // sv_maxvelocity - 0.0, // sv_staminajumpcost - 0.0, // sv_staminalandcost - 0.0, // sv_staminamax - 0.0, // sv_staminarecoveryrate - 0.7, // sv_standable_normal - 0.0, // sv_timebetweenducks - 0.7, // sv_walkable_normal - 10.0, // sv_wateraccelerate - 0.8, // sv_water_movespeed_multiplier - 0.0, // sv_water_swim_mode - 0.0, // sv_weapon_encumbrance_per_item - 0.0 // sv_weapon_encumbrance_scale -}; - -bool gB_GOKZCore; -ConVar gCV_ModeCVar[MODECVAR_COUNT]; -float gF_PreVelMod[MAXPLAYERS + 1]; -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_OldVelocity[MAXPLAYERS + 1][3]; -bool gB_Jumpbugged[MAXPLAYERS + 1]; -int gI_OffsetCGameMovement_player; - - - -// =====[ PLUGIN EVENTS ]===== - -public void OnPluginStart() -{ - if (FloatAbs(1.0 / GetTickInterval() - 128.0) > EPSILON) - { - SetFailState("gokz-mode-kztimer only supports 128 tickrate servers."); - } - HookEvents(); - CreateConVars(); -} - -public void OnAllPluginsLoaded() -{ - if (LibraryExists("updater")) - { - Updater_AddPlugin(UPDATER_URL); - } - if (LibraryExists("gokz-core")) - { - gB_GOKZCore = true; - GOKZ_SetModeLoaded(Mode_KZTimer, true, MODE_VERSION); - } - - for (int client = 1; client <= MaxClients; client++) - { - if (IsClientInGame(client)) - { - OnClientPutInServer(client); - } - } -} - -public void OnPluginEnd() -{ - if (gB_GOKZCore) - { - GOKZ_SetModeLoaded(Mode_KZTimer, false); - } -} - -public void OnLibraryAdded(const char[] name) -{ - if (StrEqual(name, "updater")) - { - Updater_AddPlugin(UPDATER_URL); - } - else if (StrEqual(name, "gokz-core")) - { - gB_GOKZCore = true; - GOKZ_SetModeLoaded(Mode_KZTimer, true, MODE_VERSION); - } -} - -public void OnLibraryRemoved(const char[] name) -{ - gB_GOKZCore = gB_GOKZCore && !StrEqual(name, "gokz-core"); -} - - - -// =====[ CLIENT EVENTS ]===== - -public void OnClientPutInServer(int client) -{ - if (IsValidClient(client)) - { - HookClientEvents(client); - } - if (IsUsingMode(client)) - { - ReplicateConVars(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]) -{ - if (!IsPlayerAlive(client) || !IsUsingMode(client)) - { - return Plugin_Continue; - } - - KZPlayer player = KZPlayer(client); - RemoveCrouchJumpBind(player, buttons); - gF_RealPreVelMod[player.ID] = CalcPrestrafeVelMod(player); - ReduceDuckSlowdown(player); - FixWaterBoost(player, buttons); - FixDisplacementStuck(player); - - gB_Jumpbugged[player.ID] = false; - gI_OldButtons[player.ID] = buttons; - gI_OldFlags[player.ID] = GetEntityFlags(client); - gB_OldOnGround[player.ID] = Movement_GetOnGround(client); - gI_TickCount[player.ID] = tickcount; - Movement_GetVelocity(client, gF_OldVelocity[client]); - return Plugin_Continue; -} - -public MRESReturn DHooks_OnGetPlayerMaxSpeed(int client, Handle hReturn) -{ - if (!IsPlayerAlive(client) || !IsUsingMode(client)) - { - return MRES_Ignored; - } - - DHookSetReturn(hReturn, SPEED_NORMAL * gF_RealPreVelMod[client]); - return MRES_Supercede; -} - -public MRESReturn DHooks_OnAirAccelerate_Pre(Address pThis, DHookParam hParams) -{ - int client = GOKZGetClientFromGameMovementAddress(pThis, gI_OffsetCGameMovement_player); - if (!IsPlayerAlive(client) || !IsUsingMode(client)) - { - return MRES_Ignored; - } - - // NOTE: Prestrafing changes GetPlayerMaxSpeed, which changes - // air acceleration, so remove gF_PreVelMod[client] from wishspeed/maxspeed. - // This also applies to when the player is ducked: their wishspeed is - // 85 and with prestrafing can be ~93. - float wishspeed = DHookGetParam(hParams, 2); - if (gF_PreVelMod[client] > 1.0) - { - DHookSetParam(hParams, 2, wishspeed / gF_PreVelMod[client]); - return MRES_ChangedHandled; - } - - 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)) - { - return; - } - - // Don't tweak convars if GOKZ isn't running - if (gB_GOKZCore) - { - TweakConVars(); - } -} - -public Action Movement_OnCategorizePositionPost(int client, float origin[3], float velocity[3]) -{ - if (!IsPlayerAlive(client) || !IsUsingMode(client)) - { - return Plugin_Continue; - } - return SlopeFix(client, origin, velocity); -} - -public Action Movement_OnJumpPre(int client, float origin[3], float velocity[3]) -{ - if (!IsPlayerAlive(client) || !IsUsingMode(client)) - { - return Plugin_Continue; - } - - KZPlayer player = KZPlayer(client); - return TweakJump(player, velocity); -} - -public Action Movement_OnJumpPost(int client) -{ - if (!IsUsingMode(client)) - { - return Plugin_Continue; - } - - KZPlayer player = KZPlayer(client); - if (gB_GOKZCore) - { - player.GOKZHitPerf = player.HitPerf; - player.GOKZTakeoffSpeed = player.TakeoffSpeed; - } - return Plugin_Continue; -} - -public void Movement_OnStopTouchGround(int client) -{ - if (!IsUsingMode(client)) - { - return; - } - - KZPlayer player = KZPlayer(client); - if (gB_GOKZCore) - { - player.GOKZHitPerf = player.HitPerf; - player.GOKZTakeoffSpeed = player.TakeoffSpeed; - } -} - -public void Movement_OnChangeMovetype(int client, MoveType oldMovetype, MoveType newMovetype) -{ - if (!IsPlayerAlive(client) || !IsUsingMode(client)) - { - return; - } - - KZPlayer player = KZPlayer(client); - if (gB_GOKZCore && newMovetype == MOVETYPE_WALK) - { - player.GOKZHitPerf = false; - player.GOKZTakeoffSpeed = player.TakeoffSpeed; - } -} - -public void GOKZ_OnOptionChanged(int client, const char[] option, any newValue) -{ - if (StrEqual(option, gC_CoreOptionNames[Option_Mode]) && newValue == Mode_KZTimer) - { - ReplicateConVars(client); - } -} - -public void GOKZ_OnCountedTeleport_Post(int client) -{ - KZPlayer player = KZPlayer(client); - ResetPrestrafeVelMod(player); -} - - - -// =====[ GENERAL ]===== - -bool IsUsingMode(int client) -{ - // If GOKZ core isn't loaded, then apply mode at all times - return !gB_GOKZCore || GOKZ_GetCoreOption(client, Option_Mode) == Mode_KZTimer; -} - -void HookEvents() -{ - GameData gameData = LoadGameConfigFile("movementapi.games"); - if (gameData == INVALID_HANDLE) - { - SetFailState("Failed to find movementapi.games config"); - } - - int offset = gameData.GetOffset("GetPlayerMaxSpeed"); - if (offset == -1) - { - SetFailState("Failed to get GetPlayerMaxSpeed offset"); - } - gH_GetPlayerMaxSpeed = DHookCreate(offset, HookType_Entity, ReturnType_Float, ThisPointer_CBaseEntity, DHooks_OnGetPlayerMaxSpeed); - - gH_AirAccelerate = DynamicDetour.FromConf(gameData, "CGameMovement::AirAccelerate"); - if (gH_AirAccelerate == INVALID_HANDLE) - { - SetFailState("Failed to find CGameMovement::AirAccelerate function signature"); - } - - if (!gH_AirAccelerate.Enable(Hook_Pre, DHooks_OnAirAccelerate_Pre)) - { - SetFailState("Failed to enable detour on CGameMovement::AirAccelerate"); - } - - char buffer[16]; - if (!gameData.GetKeyValue("CGameMovement::player", buffer, sizeof(buffer))) - { - 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 ]===== - -void CreateConVars() -{ - for (int cvar = 0; cvar < MODECVAR_COUNT; cvar++) - { - gCV_ModeCVar[cvar] = FindConVar(gC_ModeCVars[cvar]); - } -} - -void TweakConVars() -{ - for (int i = 0; i < MODECVAR_COUNT; i++) - { - gCV_ModeCVar[i].FloatValue = gF_ModeCVarValues[i]; - } -} - -void ReplicateConVars(int client) -{ - // Replicate convars only when player changes mode in GOKZ - // so that lagg isn't caused by other players using other - // modes, and also as an optimisation. - - if (IsFakeClient(client)) - { - return; - } - - for (int i = 0; i < MODECVAR_COUNT; i++) - { - gCV_ModeCVar[i].ReplicateToClient(client, FloatToStringEx(gF_ModeCVarValues[i])); - } -} - - - -// =====[ VELOCITY MODIFIER ]===== - -void HookClientEvents(int client) -{ - DHookEntity(gH_GetPlayerMaxSpeed, true, client); - SDKHook(client, SDKHook_PreThinkPost, SDKHook_OnClientPreThink_Post); -} - -// Adapted from KZTimerGlobal -float CalcPrestrafeVelMod(KZPlayer player) -{ - if (!player.OnGround) - { - return gF_PreVelMod[player.ID]; - } - - if (!player.Turning) - { - if (GetEngineTime() - gF_PreVelModLastChange[player.ID] > 0.2) - { - gF_PreVelMod[player.ID] = 1.0; - gF_PreVelModLastChange[player.ID] = GetEngineTime(); - } - else if (gF_PreVelMod[player.ID] > PRE_VELMOD_MAX + 0.007) - { - return PRE_VELMOD_MAX - 0.001; // Returning without setting the variable is intentional - } - } - else if ((player.Buttons & IN_MOVELEFT || player.Buttons & IN_MOVERIGHT) && player.Speed > 248.9) - { - float increment = 0.0009; - if (gF_PreVelMod[player.ID] > 1.04) - { - increment = 0.001; - } - - bool forwards = GetClientMovingDirection(player.ID, false) > 0.0; - - if ((player.Buttons & IN_MOVERIGHT && player.TurningRight || player.TurningLeft && !forwards) - || (player.Buttons & IN_MOVELEFT && player.TurningLeft || player.TurningRight && !forwards)) - { - gI_PreTickCounter[player.ID]++; - - if (gI_PreTickCounter[player.ID] < 75) - { - gF_PreVelMod[player.ID] += increment; - if (gF_PreVelMod[player.ID] > PRE_VELMOD_MAX) - { - if (gF_PreVelMod[player.ID] > PRE_VELMOD_MAX + 0.007) - { - gF_PreVelMod[player.ID] = PRE_VELMOD_MAX - 0.001; - } - else - { - gF_PreVelMod[player.ID] -= 0.007; - } - } - gF_PreVelMod[player.ID] += increment; - } - else - { - gF_PreVelMod[player.ID] -= 0.0045; - gI_PreTickCounter[player.ID] -= 2; - - if (gF_PreVelMod[player.ID] < 1.0) - { - gF_PreVelMod[player.ID] = 1.0; - gI_PreTickCounter[player.ID] = 0; - } - } - } - else - { - gF_PreVelMod[player.ID] -= 0.04; - - if (gF_PreVelMod[player.ID] < 1.0) - { - gF_PreVelMod[player.ID] = 1.0; - } - } - - gF_PreVelModLastChange[player.ID] = GetEngineTime(); - } - else - { - gI_PreTickCounter[player.ID] = 0; - return 1.0; // Returning without setting the variable is intentional - } - - return gF_PreVelMod[player.ID]; -} - -// Adapted from KZTimerGlobal -float GetClientMovingDirection(int client, bool ladder) -{ - float fVelocity[3]; - GetEntPropVector(client, Prop_Data, "m_vecAbsVelocity", fVelocity); - - float fEyeAngles[3]; - GetClientEyeAngles(client, fEyeAngles); - - if (fEyeAngles[0] > 70.0)fEyeAngles[0] = 70.0; - if (fEyeAngles[0] < -70.0)fEyeAngles[0] = -70.0; - - float fViewDirection[3]; - - if (ladder) - { - GetEntPropVector(client, Prop_Send, "m_vecLadderNormal", fViewDirection); - } - else - { - GetAngleVectors(fEyeAngles, fViewDirection, NULL_VECTOR, NULL_VECTOR); - } - - NormalizeVector(fVelocity, fVelocity); - NormalizeVector(fViewDirection, fViewDirection); - - float direction = GetVectorDotProduct(fVelocity, fViewDirection); - if (ladder) - { - direction = direction * -1; - } - return direction; -} - -void ResetPrestrafeVelMod(KZPlayer player) -{ - gF_PreVelMod[player.ID] = 1.0; - gI_PreTickCounter[player.ID] = 0; -} - - - -// =====[ SLOPEFIX ]===== - -// ORIGINAL AUTHORS : Mev & Blacky -// URL : https://forums.alliedmods.net/showthread.php?p=2322788 -// NOTE : Modified by DanZay for this plugin - -Action SlopeFix(int client, float origin[3], float velocity[3]) -{ - KZPlayer player = KZPlayer(client); - // Check if player landed on the ground - if (Movement_GetOnGround(client) && !gB_OldOnGround[client]) - { - float vMins[] = {-16.0, -16.0, 0.0}; - // Always use ducked hull as the real hull size isn't updated yet. - // Might cause slight issues in extremely rare scenarios. - float vMaxs[] = {16.0, 16.0, 54.0}; - - float vEndPos[3]; - vEndPos[0] = origin[0]; - vEndPos[1] = origin[1]; - vEndPos[2] = origin[2] - gF_ModeCVarValues[ModeCVar_MaxVelocity]; - - // Set up and do tracehull to find out if the player landed on a slope - TR_TraceHullFilter(origin, vEndPos, vMins, vMaxs, MASK_PLAYERSOLID_BRUSHONLY, TraceRayDontHitSelf, client); - - if (TR_DidHit()) - { - // Gets the normal vector of the surface under the player - float vPlane[3], vLast[3]; - player.GetLandingVelocity(vLast); - TR_GetPlaneNormal(null, vPlane); - - // Make sure it's not flat ground and not a surf ramp (1.0 = flat ground, < 0.7 = surf ramp) - if (0.7 <= vPlane[2] < 1.0) - { - /* - Copy the ClipVelocity function from sdk2013 - (https://mxr.alliedmods.net/hl2sdk-sdk2013/source/game/shared/gamemovement.cpp#3145) - With some minor changes to make it actually work - */ - - float fBackOff = GetVectorDotProduct(vLast, vPlane); - - float change, vVel[3]; - for (int i; i < 2; i++) - { - change = vPlane[i] * fBackOff; - vVel[i] = vLast[i] - change; - } - - float fAdjust = GetVectorDotProduct(vVel, vPlane); - if (fAdjust < 0.0) - { - for (int i; i < 2; i++) - { - vVel[i] -= (vPlane[i] * fAdjust); - } - } - - vVel[2] = 0.0; - vLast[2] = 0.0; - - // Make sure the player is going down a ramp by checking if they actually will gain speed from the boost - if (GetVectorLength(vVel) > GetVectorLength(vLast)) - { - CopyVector(vVel, velocity); - player.SetLandingVelocity(velocity); - return Plugin_Changed; - } - } - } - } - return Plugin_Continue; -} - -public bool TraceRayDontHitSelf(int entity, int mask, any data) -{ - return entity != data && !(0 < entity <= MaxClients); -} - - - -// =====[ JUMPING ]===== - -Action TweakJump(KZPlayer player, float velocity[3]) -{ - if (player.HitPerf) - { - if (GetVectorHorizontalLength(velocity) > PERF_SPEED_CAP) - { - SetVectorHorizontalLength(velocity, PERF_SPEED_CAP); - return Plugin_Changed; - } - } - return Plugin_Continue; -} -// =====[ OTHER ]===== - -void FixWaterBoost(KZPlayer player, int buttons) -{ - if (GetEntProp(player.ID, Prop_Send, "m_nWaterLevel") >= 2) // WL_Waist = 2 - { - // If duck is being pressed and we're not already ducking or on ground - if (GetEntityFlags(player.ID) & (FL_DUCKING | FL_ONGROUND) == 0 - && buttons & IN_DUCK && ~gI_OldButtons[player.ID] & IN_DUCK) - { - float newOrigin[3]; - Movement_GetOrigin(player.ID, newOrigin); - newOrigin[2] += 9.0; - - TR_TraceHullFilter(newOrigin, newOrigin, view_as({-16.0, -16.0, 0.0}), view_as({16.0, 16.0, 54.0}), MASK_PLAYERSOLID, TraceEntityFilterPlayers); - if (!TR_DidHit()) - { - TeleportEntity(player.ID, newOrigin, NULL_VECTOR, NULL_VECTOR); - } - } - } -} - -void FixDisplacementStuck(KZPlayer player) -{ - int flags = GetEntityFlags(player.ID); - bool unducked = ~flags & FL_DUCKING && gI_OldFlags[player.ID] & FL_DUCKING; - - float standingMins[] = {-16.0, -16.0, 0.0}; - float standingMaxs[] = {16.0, 16.0, 72.0}; - - if (unducked) - { - // check if we're stuck after unducking and if we're stuck then force duck - float origin[3]; - Movement_GetOrigin(player.ID, origin); - TR_TraceHullFilter(origin, origin, standingMins, standingMaxs, MASK_PLAYERSOLID, TraceEntityFilterPlayers); - - if (TR_DidHit()) - { - player.SetVelocity(gF_OldVelocity[player.ID]); - SetEntProp(player.ID, Prop_Send, "m_bDucking", true); - } - } -} - -void RemoveCrouchJumpBind(KZPlayer player, int &buttons) -{ - if (player.OnGround && buttons & IN_JUMP && !(gI_OldButtons[player.ID] & IN_JUMP) && !(gI_OldButtons[player.ID] & IN_DUCK)) - { - buttons &= ~IN_DUCK; - } -} - -void ReduceDuckSlowdown(KZPlayer player) -{ - if (GetEntProp(player.ID, Prop_Data, "m_afButtonReleased") & IN_DUCK) - { - Movement_SetDuckSpeed(player.ID, DUCK_SPEED_NORMAL); - } -} diff --git a/source/sourcemod/scripting/gokz-mode-simplekz.sp b/source/sourcemod/scripting/gokz-mode-simplekz.sp deleted file mode 100644 index 99d76ac..0000000 --- a/source/sourcemod/scripting/gokz-mode-simplekz.sp +++ /dev/null @@ -1,846 +0,0 @@ -#include - -#include -#include -#include - -#include - -#undef REQUIRE_EXTENSIONS -#undef REQUIRE_PLUGIN -#include -#include - -#include - -#pragma newdecls required -#pragma semicolon 1 - - - -public Plugin myinfo = -{ - name = "GOKZ Mode - SimpleKZ", - author = "DanZay", - description = "SimpleKZ mode for GOKZ", - version = GOKZ_VERSION, - url = GOKZ_SOURCE_URL -}; - -#define UPDATER_URL GOKZ_UPDATER_BASE_URL..."gokz-mode-simplekz.txt" - -#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 -#define PS_SPEED_INCREMENT 0.35 // Units per tick -#define PS_SPEED_DECREMENT_MIDAIR 0.2824 // Units per tick (lose PS_SPEED_MAX in 0 offset jump i.e. 94 ticks) -#define PS_GRACE_TICKS 3 // No. of ticks allowed to fail prestrafe checks when prestrafing - helps players with low fps -#define DUCK_SPEED_NORMAL 8.0 -#define DUCK_SPEED_MINIMUM 6.0234375 // Equal to if you just ducked/unducked for the first time in a while - -float gF_ModeCVarValues[MODECVAR_COUNT] = -{ - 6.5, // sv_accelerate - 0.0, // sv_accelerate_use_weapon_speed - 100.0, // sv_airaccelerate - 30.0, // sv_air_max_wishspeed - 1.0, // sv_enablebunnyhopping - 5.2, // sv_friction - 800.0, // sv_gravity - 301.993377, // sv_jump_impulse - 1.0, // sv_ladder_scale_speed - 0.0, // sv_ledge_mantle_helper - 320.0, // sv_maxspeed - 3500.0, // sv_maxvelocity - 0.0, // sv_staminajumpcost - 0.0, // sv_staminalandcost - 0.0, // sv_staminamax - 0.0, // sv_staminarecoveryrate - 0.7, // sv_standable_normal - 0.0, // sv_timebetweenducks - 0.7, // sv_walkable_normal - 10.0, // sv_wateraccelerate - 0.8, // sv_water_movespeed_multiplier - 0.0, // sv_water_swim_mode - 0.0, // sv_weapon_encumbrance_per_item - 0.0 // sv_weapon_encumbrance_scale -}; - -bool gB_GOKZCore; -ConVar gCV_ModeCVar[MODECVAR_COUNT]; -bool gB_HitTweakedPerf[MAXPLAYERS + 1]; -int gI_Cmdnum[MAXPLAYERS + 1]; -float gF_PSBonusSpeed[MAXPLAYERS + 1]; -float gF_PSVelMod[MAXPLAYERS + 1]; -float gF_PSVelModLanding[MAXPLAYERS + 1]; -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]; -bool gB_OldOnGround[MAXPLAYERS + 1]; -float gF_OldOrigin[MAXPLAYERS + 1][3]; -float gF_OldAngles[MAXPLAYERS + 1][3]; -float gF_OldVelocity[MAXPLAYERS + 1][3]; -int gI_LastJumpButtonCmdnum[MAXPLAYERS + 1]; -int gI_OffsetCGameMovement_player; - - - -// =====[ PLUGIN EVENTS ]===== - -public void OnPluginStart() -{ - if (FloatAbs(1.0 / GetTickInterval() - 128.0) > EPSILON) - { - SetFailState("gokz-mode-simplekz only supports 128 tickrate servers."); - } - HookEvents(); - CreateConVars(); -} - -public void OnAllPluginsLoaded() -{ - if (LibraryExists("updater")) - { - Updater_AddPlugin(UPDATER_URL); - } - if (LibraryExists("gokz-core")) - { - gB_GOKZCore = true; - GOKZ_SetModeLoaded(Mode_SimpleKZ, true, MODE_VERSION); - } - - for (int client = 1; client <= MaxClients; client++) - { - if (IsClientInGame(client)) - { - OnClientPutInServer(client); - } - } -} - -public void OnPluginEnd() -{ - if (gB_GOKZCore) - { - GOKZ_SetModeLoaded(Mode_SimpleKZ, false); - } -} - -public void OnLibraryAdded(const char[] name) -{ - if (StrEqual(name, "updater")) - { - Updater_AddPlugin(UPDATER_URL); - } - else if (StrEqual(name, "gokz-core")) - { - gB_GOKZCore = true; - GOKZ_SetModeLoaded(Mode_SimpleKZ, true, MODE_VERSION); - } -} - -public void OnLibraryRemoved(const char[] name) -{ - gB_GOKZCore = gB_GOKZCore && !StrEqual(name, "gokz-core"); -} - - - -// =====[ CLIENT EVENTS ]===== - -public void OnClientPutInServer(int client) -{ - ResetClient(client); - if (IsValidClient(client)) - { - HookClientEvents(client); - } - if (IsUsingMode(client)) - { - ReplicateConVars(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]) -{ - if (!IsPlayerAlive(client) || !IsUsingMode(client)) - { - return Plugin_Continue; - } - - KZPlayer player = KZPlayer(client); - RemoveCrouchJumpBind(player, buttons); - ReduceDuckSlowdown(player); - CalcPrestrafeVelMod(player, angles); - FixWaterBoost(player, buttons); - FixDisplacementStuck(player); - - gB_HitTweakedPerf[player.ID] = false; - gI_Cmdnum[player.ID] = cmdnum; - 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]); - - return Plugin_Continue; -} - -public MRESReturn DHooks_OnGetPlayerMaxSpeed(int client, Handle hReturn) -{ - if (!IsUsingMode(client)) - { - return MRES_Ignored; - } - DHookSetReturn(hReturn, SPEED_NORMAL * gF_PSVelMod[client]); - return MRES_Supercede; -} - -public MRESReturn DHooks_OnAirAccelerate_Pre(Address pThis, DHookParam hParams) -{ - int client = GOKZGetClientFromGameMovementAddress(pThis, gI_OffsetCGameMovement_player); - if (!IsPlayerAlive(client) || !IsUsingMode(client)) - { - return MRES_Ignored; - } - - // NOTE: Prestrafing changes GetPlayerMaxSpeed, which changes - // air acceleration, so remove gF_PreVelMod[client] from wishspeed/maxspeed. - // This also applies to when the player is ducked: their wishspeed is - // 85 and with prestrafing can be ~93. - float wishspeed = DHookGetParam(hParams, 2); - if (gF_PSVelMod[client] > 1.0) - { - DHookSetParam(hParams, 2, wishspeed / gF_PSVelMod[client]); - return MRES_ChangedHandled; - } - - 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)) - { - return; - } - - if (buttons & IN_JUMP) - { - gI_LastJumpButtonCmdnum[client] = cmdnum; - } -} - -public void SDKHook_OnClientPreThink_Post(int client) -{ - if (!IsPlayerAlive(client) || !IsUsingMode(client)) - { - return; - } - - // Don't tweak convars if GOKZ isn't running - if (gB_GOKZCore) - { - TweakConVars(); - } -} - -public void Movement_OnStartTouchGround(int client) -{ - if (!IsUsingMode(client)) - { - return; - } - - KZPlayer player = KZPlayer(client); - gF_PSVelModLanding[player.ID] = gF_PSVelMod[player.ID]; -} - -public Action Movement_OnJumpPre(int client, float origin[3], float velocity[3]) -{ - if (!IsPlayerAlive(client) || !IsUsingMode(client)) - { - return Plugin_Continue; - } - - KZPlayer player = KZPlayer(client); - return TweakJump(player, origin, velocity); -} - -public Action Movement_OnCategorizePositionPost(int client, float origin[3], float velocity[3]) -{ - if (!IsPlayerAlive(client) || !IsUsingMode(client)) - { - return Plugin_Continue; - } - return SlopeFix(client, origin, velocity); -} - -public void Movement_OnChangeMovetype(int client, MoveType oldMovetype, MoveType newMovetype) -{ - if (!IsUsingMode(client)) - { - return; - } - - KZPlayer player = KZPlayer(client); - if (gB_GOKZCore && newMovetype == MOVETYPE_WALK) - { - player.GOKZHitPerf = false; - player.GOKZTakeoffSpeed = player.TakeoffSpeed; - } -} - -public void GOKZ_OnOptionChanged(int client, const char[] option, any newValue) -{ - if (StrEqual(option, gC_CoreOptionNames[Option_Mode]) && newValue == Mode_SimpleKZ) - { - ReplicateConVars(client); - } -} - -public void GOKZ_OnCountedTeleport_Post(int client) -{ - ResetClient(client); -} - - - -// =====[ GENERAL ]===== - -bool IsUsingMode(int client) -{ - // If GOKZ core isn't loaded, then apply mode at all times - return !gB_GOKZCore || GOKZ_GetCoreOption(client, Option_Mode) == Mode_SimpleKZ; -} - -void ResetClient(int client) -{ - KZPlayer player = KZPlayer(client); - ResetVelMod(player); -} - -void HookEvents() -{ - GameData gameData = LoadGameConfigFile("movementapi.games"); - if (gameData == INVALID_HANDLE) - { - SetFailState("Failed to find movementapi.games config"); - } - - int offset = gameData.GetOffset("GetPlayerMaxSpeed"); - if (offset == -1) - { - SetFailState("Failed to get GetPlayerMaxSpeed offset"); - } - gH_GetPlayerMaxSpeed = DHookCreate(offset, HookType_Entity, ReturnType_Float, ThisPointer_CBaseEntity, DHooks_OnGetPlayerMaxSpeed); - - gH_AirAccelerate = DynamicDetour.FromConf(gameData, "CGameMovement::AirAccelerate"); - if (gH_AirAccelerate == INVALID_HANDLE) - { - SetFailState("Failed to find CGameMovement::AirAccelerate function signature"); - } - - if (!gH_AirAccelerate.Enable(Hook_Pre, DHooks_OnAirAccelerate_Pre)) - { - SetFailState("Failed to enable detour on CGameMovement::AirAccelerate"); - } - - char buffer[16]; - if (!gameData.GetKeyValue("CGameMovement::player", buffer, sizeof(buffer))) - { - 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 ]===== - -void CreateConVars() -{ - for (int i = 0; i < MODECVAR_COUNT; i++) - { - gCV_ModeCVar[i] = FindConVar(gC_ModeCVars[i]); - } -} - -void TweakConVars() -{ - for (int i = 0; i < MODECVAR_COUNT; i++) - { - gCV_ModeCVar[i].FloatValue = gF_ModeCVarValues[i]; - } -} - -void ReplicateConVars(int client) -{ - /* - Replicate convars only when player changes mode in GOKZ - so that lagg isn't caused by other players using other - modes, and also as an optimisation. - */ - - if (IsFakeClient(client)) - { - return; - } - - for (int i = 0; i < MODECVAR_COUNT; i++) - { - gCV_ModeCVar[i].ReplicateToClient(client, FloatToStringEx(gF_ModeCVarValues[i])); - } -} - - - -// =====[ VELOCITY MODIFIER ]===== - -void HookClientEvents(int client) -{ - DHookEntity(gH_GetPlayerMaxSpeed, true, client); - SDKHook(client, SDKHook_PreThinkPost, SDKHook_OnClientPreThink_Post); -} - -void ResetVelMod(KZPlayer player) -{ - gF_PSBonusSpeed[player.ID] = 0.0; - gF_PSVelMod[player.ID] = 1.0; - gF_PSTurnRate[player.ID] = 0.0; -} - -void CalcPrestrafeVelMod(KZPlayer player, const float angles[3]) -{ - gI_PSTicksSinceIncrement[player.ID]++; - - // Short circuit if speed is 0 (also avoids divide by 0 errors) - if (player.Speed < EPSILON) - { - ResetVelMod(player); - return; - } - - // Current speed without bonus - float baseSpeed = FloatMin(SPEED_NORMAL, player.Speed / gF_PSVelMod[player.ID]); - - float newBonusSpeed = gF_PSBonusSpeed[player.ID]; - - // If player is in mid air, decrement their velocity modifier - if (!player.OnGround) - { - newBonusSpeed -= PS_SPEED_DECREMENT_MIDAIR; - } - // If player is turning at the required speed, and has the correct button inputs, reward it - else if (player.Turning && ValidPrestrafeButtons(player)) - { - // If player changes their prestrafe direction, reset it - if (player.TurningLeft && !gB_PSTurningLeft[player.ID] - || player.TurningRight && gB_PSTurningLeft[player.ID]) - { - ResetVelMod(player); - newBonusSpeed = 0.0; - } - - // Keep track of the direction of the turn - gB_PSTurningLeft[player.ID] = player.TurningLeft; - - // Step one of calculating new turn rate - float newTurningRate = FloatAbs(CalcDeltaAngle(gF_OldAngles[player.ID][1], angles[1])); - - // If no turning for just a few ticks, then forgive and calculate reward based on that no. of ticks - if (gI_PSTicksSinceIncrement[player.ID] <= PS_GRACE_TICKS) - { - // This turn occurred over multiple ticks, so scale appropriately - // Also cap turn rate at maximum reward turn rate - newTurningRate = FloatMin(PS_MAX_REWARD_TURN_RATE, - newTurningRate / gI_PSTicksSinceIncrement[player.ID]); - - // Limit how fast turn rate can decrease (also scaled appropriately) - gF_PSTurnRate[player.ID] = FloatMax(newTurningRate, - gF_PSTurnRate[player.ID] - PS_MAX_TURN_RATE_DECREMENT * gI_PSTicksSinceIncrement[player.ID]); - - newBonusSpeed += CalcPreRewardSpeed(gF_PSTurnRate[player.ID], baseSpeed) * gI_PSTicksSinceIncrement[player.ID]; - } - else - { - // Cap turn rate at maximum reward turn rate - newTurningRate = FloatMin(PS_MAX_REWARD_TURN_RATE, newTurningRate); - - // Limit how fast turn rate can decrease - gF_PSTurnRate[player.ID] = FloatMax(newTurningRate, - gF_PSTurnRate[player.ID] - PS_MAX_TURN_RATE_DECREMENT); - - // This is normal turning behaviour - newBonusSpeed += CalcPreRewardSpeed(gF_PSTurnRate[player.ID], baseSpeed); - } - - gI_PSTicksSinceIncrement[player.ID] = 0; - } - else if (gI_PSTicksSinceIncrement[player.ID] > PS_GRACE_TICKS) - { - // They definitely aren't turning, but limit how fast turn rate can decrease - gF_PSTurnRate[player.ID] = FloatMax(0.0, - gF_PSTurnRate[player.ID] - PS_MAX_TURN_RATE_DECREMENT); - } - - if (newBonusSpeed < 0.0) - { - // Keep velocity modifier positive - newBonusSpeed = 0.0; - } - else - { - // Scale the bonus speed based on current base speed and turn rate - float baseSpeedScaleFactor = baseSpeed / SPEED_NORMAL; // Max 1.0 - float turnRateScaleFactor = FloatMin(1.0, gF_PSTurnRate[player.ID] / PS_MAX_REWARD_TURN_RATE); - float scaledMaxBonusSpeed = PS_SPEED_MAX * baseSpeedScaleFactor * turnRateScaleFactor; - newBonusSpeed = FloatMin(newBonusSpeed, scaledMaxBonusSpeed); - } - - gF_PSBonusSpeed[player.ID] = newBonusSpeed; - gF_PSVelMod[player.ID] = 1.0 + (newBonusSpeed / baseSpeed); -} - -bool ValidPrestrafeButtons(KZPlayer player) -{ - bool forwardOrBack = player.Buttons & (IN_FORWARD | IN_BACK) && !(player.Buttons & IN_FORWARD && player.Buttons & IN_BACK); - bool leftOrRight = player.Buttons & (IN_MOVELEFT | IN_MOVERIGHT) && !(player.Buttons & IN_MOVELEFT && player.Buttons & IN_MOVERIGHT); - return forwardOrBack || leftOrRight; -} - -float CalcPreRewardSpeed(float yawDiff, float baseSpeed) -{ - // Formula - float reward; - if (yawDiff >= PS_MAX_REWARD_TURN_RATE) - { - reward = PS_SPEED_INCREMENT; - } - else - { - reward = PS_SPEED_INCREMENT * (yawDiff / PS_MAX_REWARD_TURN_RATE); - } - - return reward * baseSpeed / SPEED_NORMAL; -} - - - - -// =====[ JUMPING ]===== - -Action TweakJump(KZPlayer player, float origin[3], float velocity[3]) -{ - // TakeoffCmdnum and TakeoffSpeed is not defined here because the player technically hasn't taken off yet. - int cmdsSinceLanding = gI_Cmdnum[player.ID] - player.LandingCmdNum; - gB_HitTweakedPerf[player.ID] = cmdsSinceLanding <= 1 - || cmdsSinceLanding <= 3 && gI_Cmdnum[player.ID] - gI_LastJumpButtonCmdnum[player.ID] <= 3; - - if (gB_HitTweakedPerf[player.ID]) - { - if (cmdsSinceLanding <= 1) - { - NerfRealPerf(player, origin); - } - - ApplyTweakedTakeoffSpeed(player, velocity); - - if (cmdsSinceLanding > 1 || player.TakeoffSpeed > SPEED_NORMAL) - { - // Restore prestrafe lost due to briefly being on the ground - gF_PSVelMod[player.ID] = gF_PSVelModLanding[player.ID]; - } - return Plugin_Changed; - } - return Plugin_Continue; -} - -public Action Movement_OnJumpPost(int client) -{ - if (!IsUsingMode(client)) - { - return Plugin_Continue; - } - KZPlayer player = KZPlayer(client); - player.GOKZHitPerf = gB_HitTweakedPerf[player.ID]; - player.GOKZTakeoffSpeed = player.TakeoffSpeed; - return Plugin_Continue; -} - -public void Movement_OnStopTouchGround(int client) -{ - if (!IsUsingMode(client)) - { - return; - } - KZPlayer player = KZPlayer(client); - player.GOKZHitPerf = gB_HitTweakedPerf[player.ID]; - player.GOKZTakeoffSpeed = player.TakeoffSpeed; -} - -void NerfRealPerf(KZPlayer player, float origin[3]) -{ - // Not worth worrying about if player is already falling - // player.VerticalVelocity is not updated yet! Use processing velocity. - float velocity[3]; - Movement_GetProcessingVelocity(player.ID, velocity); - if (velocity[2] < EPSILON) - { - return; - } - - // Work out where the ground was when they bunnyhopped - float startPosition[3], endPosition[3], mins[3], maxs[3], groundOrigin[3]; - - startPosition = origin; - - endPosition = startPosition; - endPosition[2] = endPosition[2] - 2.0; // Should be less than 2.0 units away - - GetEntPropVector(player.ID, Prop_Send, "m_vecMins", mins); - GetEntPropVector(player.ID, Prop_Send, "m_vecMaxs", maxs); - - Handle trace = TR_TraceHullFilterEx( - startPosition, - endPosition, - mins, - maxs, - MASK_PLAYERSOLID, - TraceEntityFilterPlayers, - player.ID); - - // This is expected to always hit, previously this can fail upon jumpbugs. - if (TR_DidHit(trace)) - { - TR_GetEndPosition(groundOrigin, trace); - origin[2] = groundOrigin[2]; - } - - delete trace; -} - -void ApplyTweakedTakeoffSpeed(KZPlayer player, float velocity[3]) -{ - // Note that resulting velocity has same direction as landing velocity, not current velocity - // because current velocity direction can change drastically in just one tick (eg. walls) - // and it doesnt make sense for the new velocity to push you in that direction. - - float newVelocity[3], baseVelocity[3]; - player.GetLandingVelocity(newVelocity); - player.GetBaseVelocity(baseVelocity); - SetVectorHorizontalLength(newVelocity, CalcTweakedTakeoffSpeed(player)); - AddVectors(newVelocity, baseVelocity, newVelocity); // For backwards compatibility - velocity[0] = newVelocity[0]; - velocity[1] = newVelocity[1]; -} - -// Takeoff speed assuming player has met the conditions to need tweaking -float CalcTweakedTakeoffSpeed(KZPlayer player) -{ - // Formula - if (player.LandingSpeed > SPEED_NORMAL) - { - return FloatMin(player.LandingSpeed, (0.2 * player.LandingSpeed + 200) * gF_PSVelModLanding[player.ID]); - } - return player.LandingSpeed; -} - - - -// =====[ SLOPEFIX ]===== - -// ORIGINAL AUTHORS : Mev & Blacky -// URL : https://forums.alliedmods.net/showthread.php?p=2322788 -// NOTE : Modified by DanZay for this plugin - -Action SlopeFix(int client, float origin[3], float velocity[3]) -{ - KZPlayer player = KZPlayer(client); - // Check if player landed on the ground - if (Movement_GetOnGround(client) && !gB_OldOnGround[client]) - { - float vMins[] = {-16.0, -16.0, 0.0}; - // Always use ducked hull as the real hull size isn't updated yet. - // Might cause slight issues in extremely rare scenarios. - float vMaxs[] = {16.0, 16.0, 54.0}; - - float vEndPos[3]; - vEndPos[0] = origin[0]; - vEndPos[1] = origin[1]; - vEndPos[2] = origin[2] - gF_ModeCVarValues[ModeCVar_MaxVelocity]; - - // Set up and do tracehull to find out if the player landed on a slope - TR_TraceHullFilter(origin, vEndPos, vMins, vMaxs, MASK_PLAYERSOLID_BRUSHONLY, TraceRayDontHitSelf, client); - - if (TR_DidHit()) - { - // Gets the normal vector of the surface under the player - float vPlane[3], vLast[3]; - player.GetLandingVelocity(vLast); - TR_GetPlaneNormal(null, vPlane); - - // Make sure it's not flat ground and not a surf ramp (1.0 = flat ground, < 0.7 = surf ramp) - if (0.7 <= vPlane[2] < 1.0) - { - /* - Copy the ClipVelocity function from sdk2013 - (https://mxr.alliedmods.net/hl2sdk-sdk2013/source/game/shared/gamemovement.cpp#3145) - With some minor changes to make it actually work - */ - - float fBackOff = GetVectorDotProduct(vLast, vPlane); - - float change, vVel[3]; - for (int i; i < 2; i++) - { - change = vPlane[i] * fBackOff; - vVel[i] = vLast[i] - change; - } - - float fAdjust = GetVectorDotProduct(vVel, vPlane); - if (fAdjust < 0.0) - { - for (int i; i < 2; i++) - { - vVel[i] -= (vPlane[i] * fAdjust); - } - } - - vVel[2] = 0.0; - vLast[2] = 0.0; - - // Make sure the player is going down a ramp by checking if they actually will gain speed from the boost - if (GetVectorLength(vVel) > GetVectorLength(vLast)) - { - CopyVector(vVel, velocity); - player.SetLandingVelocity(velocity); - return Plugin_Changed; - } - } - } - } - return Plugin_Continue; -} - -public bool TraceRayDontHitSelf(int entity, int mask, any data) -{ - return entity != data && !(0 < entity <= MaxClients); -} - - - -// =====[ OTHER ]===== - -void FixWaterBoost(KZPlayer player, int buttons) -{ - if (GetEntProp(player.ID, Prop_Send, "m_nWaterLevel") >= 2) // WL_Waist = 2 - { - // If duck is being pressed and we're not already ducking or on ground - if (GetEntityFlags(player.ID) & (FL_DUCKING | FL_ONGROUND) == 0 - && buttons & IN_DUCK && ~gI_OldButtons[player.ID] & IN_DUCK) - { - float newOrigin[3]; - Movement_GetOrigin(player.ID, newOrigin); - newOrigin[2] += 9.0; - - TR_TraceHullFilter(newOrigin, newOrigin, view_as( { -16.0, -16.0, 0.0 } ), view_as( { 16.0, 16.0, 54.0 } ), MASK_PLAYERSOLID, TraceEntityFilterPlayers); - if (!TR_DidHit()) - { - TeleportEntity(player.ID, newOrigin, NULL_VECTOR, NULL_VECTOR); - } - } - } -} - -void FixDisplacementStuck(KZPlayer player) -{ - int flags = GetEntityFlags(player.ID); - bool unducked = ~flags & FL_DUCKING && gI_OldFlags[player.ID] & FL_DUCKING; - - float standingMins[] = {-16.0, -16.0, 0.0}; - float standingMaxs[] = {16.0, 16.0, 72.0}; - - if (unducked) - { - // check if we're stuck after unducking and if we're stuck then force duck - float origin[3]; - Movement_GetOrigin(player.ID, origin); - TR_TraceHullFilter(origin, origin, standingMins, standingMaxs, MASK_PLAYERSOLID, TraceEntityFilterPlayers); - - if (TR_DidHit()) - { - player.SetVelocity(gF_OldVelocity[player.ID]); - SetEntProp(player.ID, Prop_Send, "m_bDucking", true); - } - } -} - -void RemoveCrouchJumpBind(KZPlayer player, int &buttons) -{ - if (player.OnGround && buttons & IN_JUMP && !(gI_OldButtons[player.ID] & IN_JUMP) && !(gI_OldButtons[player.ID] & IN_DUCK)) - { - buttons &= ~IN_DUCK; - } -} - -void ReduceDuckSlowdown(KZPlayer player) -{ - /* - Duck speed is reduced by the game upon ducking or unducking. - The goal here is to accept that duck speed is reduced, but - stop it from being reduced further when spamming duck. - - This is done by enforcing a minimum duck speed equivalent to - the value as if the player only ducked once. When not in not - in the middle of ducking, duck speed is reset to its normal - value in effort to reduce the number of times the minimum - duck speed is enforced. This should reduce noticeable lagg. - */ - - if (!GetEntProp(player.ID, Prop_Send, "m_bDucking") - && player.DuckSpeed < DUCK_SPEED_NORMAL - EPSILON) - { - player.DuckSpeed = DUCK_SPEED_NORMAL; - } - else if (player.DuckSpeed < DUCK_SPEED_MINIMUM - EPSILON) - { - player.DuckSpeed = DUCK_SPEED_MINIMUM; - } -} diff --git a/source/sourcemod/scripting/gokz-paint.sp b/source/sourcemod/scripting/gokz-paint.sp deleted file mode 100644 index 3de93a7..0000000 --- a/source/sourcemod/scripting/gokz-paint.sp +++ /dev/null @@ -1,410 +0,0 @@ -#include - -#include -#include - -#undef REQUIRE_EXTENSIONS -#undef REQUIRE_PLUGIN -#include - -#pragma newdecls required -#pragma semicolon 1 - - - -// Credit to SlidyBat for a large part of the painting code (https://forums.alliedmods.net/showthread.php?p=2541664) -// Credit to Cabbage McGravel of the MomentumMod team for making the textures - -public Plugin myinfo = -{ - name = "GOKZ Paint", - author = "zealain", - description = "Provides client sided paint for visibility", - version = GOKZ_VERSION, - url = GOKZ_SOURCE_URL -}; - -#define UPDATER_URL GOKZ_UPDATER_BASE_URL..."gokz-paint.txt" - -char gC_PaintColors[][32] = -{ - "paint_red", - "paint_white", - "paint_black", - "paint_blue", - "paint_brown", - "paint_green", - "paint_yellow", - "paint_purple" -}; - -char gC_PaintSizePostfix[][8] = -{ - "_small", - "_med", - "_large" -}; - -int gI_Decals[sizeof(gC_PaintColors)][sizeof(gC_PaintSizePostfix)]; -float gF_LastPaintPos[MAXPLAYERS + 1][3]; -bool gB_IsPainting[MAXPLAYERS + 1]; - -TopMenu gTM_Options; -TopMenuObject gTMO_CatPaint; -TopMenuObject gTMO_ItemsPaint[PAINTOPTION_COUNT]; - - -// =====[ PLUGIN EVENTS ]===== - -public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) -{ - RegPluginLibrary("gokz-paint"); - return APLRes_Success; -} - -public void OnPluginStart() -{ - LoadTranslations("gokz-paint.phrases"); - - RegisterCommands(); -} - -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); - } -} - - - -// =====[ EVENTS ]===== - -public void GOKZ_OnOptionsMenuCreated(TopMenu topMenu) -{ - OnOptionsMenuCreated_OptionsMenu(topMenu); -} - -public void GOKZ_OnOptionsMenuReady(TopMenu topMenu) -{ - OnOptionsMenuReady_Options(); - OnOptionsMenuReady_OptionsMenu(topMenu); -} - -public void OnMapStart() -{ - char buffer[PLATFORM_MAX_PATH]; - - AddFileToDownloadsTable("materials/gokz/paint/paint_decal.vtf"); - for (int color = 0; color < sizeof(gC_PaintColors); color++) - { - for (int size = 0; size < sizeof(gC_PaintSizePostfix); size++) - { - Format(buffer, sizeof(buffer), "gokz/paint/%s%s.vmt", gC_PaintColors[color], gC_PaintSizePostfix[size]); - gI_Decals[color][size] = PrecachePaint(buffer); - } - } - - CreateTimer(0.1, Timer_Paint, _, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); -} - - - -// =====[ PAINT ]===== - -void Paint(int client) -{ - if (!IsValidClient(client) || - IsFakeClient(client)) - { - return; - } - - float position[3]; - bool hit = GetPlayerEyeViewPoint(client, position); - - if (!hit || GetVectorDistance(position, gF_LastPaintPos[client], true) < MIN_PAINT_SPACING) - { - return; - } - - int paint = GOKZ_GetOption(client, gC_PaintOptionNames[PaintOption_Color]); - int size = GOKZ_GetOption(client, gC_PaintOptionNames[PaintOption_Size]); - - TE_SetupWorldDecal(position, gI_Decals[paint][size]); - TE_SendToClient(client); - - gF_LastPaintPos[client] = position; -} - -public Action Timer_Paint(Handle timer) -{ - for (int client = 1; client <= MAXPLAYERS; client++) - { - if (gB_IsPainting[client]) - { - Paint(client); - } - } - return Plugin_Continue; -} - -void TE_SetupWorldDecal(const float origin[3], int index) -{ - TE_Start("World Decal"); - TE_WriteVector("m_vecOrigin", origin); - TE_WriteNum("m_nIndex", index); -} - -int PrecachePaint(char[] filename) -{ - char path[PLATFORM_MAX_PATH]; - Format(path, sizeof(path), "materials/%s", filename); - AddFileToDownloadsTable(path); - - return PrecacheDecal(filename, true); -} - -bool GetPlayerEyeViewPoint(int client, float position[3]) -{ - float angles[3]; - GetClientEyeAngles(client, angles); - - float origin[3]; - GetClientEyePosition(client, origin); - - Handle trace = TR_TraceRayFilterEx(origin, angles, MASK_PLAYERSOLID, RayType_Infinite, TraceEntityFilterPlayers); - if (TR_DidHit(trace)) - { - TR_GetEndPosition(position, trace); - delete trace; - return true; - } - delete trace; - return false; -} - - - -// =====[ OPTIONS ]===== - -void OnOptionsMenuReady_Options() -{ - RegisterOptions(); -} - -void RegisterOptions() -{ - for (PaintOption option; option < PAINTOPTION_COUNT; option++) - { - GOKZ_RegisterOption(gC_PaintOptionNames[option], gC_PaintOptionDescriptions[option], - OptionType_Int, gI_PaintOptionDefaults[option], 0, gI_PaintOptionCounts[option] - 1); - } -} - - - -// =====[ OPTIONS MENU ]===== - -void OnOptionsMenuCreated_OptionsMenu(TopMenu topMenu) -{ - if (gTM_Options == topMenu && gTMO_CatPaint != INVALID_TOPMENUOBJECT) - { - return; - } - - gTMO_CatPaint = topMenu.AddCategory(PAINT_OPTION_CATEGORY, TopMenuHandler_Categories); -} - -void OnOptionsMenuReady_OptionsMenu(TopMenu topMenu) -{ - // Make sure category exists - if (gTMO_CatPaint == INVALID_TOPMENUOBJECT) - { - GOKZ_OnOptionsMenuCreated(topMenu); - } - - if (gTM_Options == topMenu) - { - return; - } - - gTM_Options = topMenu; - - // Add gokz-paint option items - for (int option = 0; option < view_as(PAINTOPTION_COUNT); option++) - { - gTMO_ItemsPaint[option] = gTM_Options.AddItem(gC_PaintOptionNames[option], TopMenuHandler_Paint, gTMO_CatPaint); - } -} - -void DisplayPaintOptionsMenu(int client) -{ - gTM_Options.DisplayCategory(gTMO_CatPaint, client); -} - -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_CatPaint) - { - Format(buffer, maxlength, "%T", "Options Menu - Paint", param); - } - } -} - -public void TopMenuHandler_Paint(TopMenu topmenu, TopMenuAction action, TopMenuObject topobj_id, int param, char[] buffer, int maxlength) -{ - PaintOption option = PAINTOPTION_INVALID; - for (int i = 0; i < view_as(PAINTOPTION_COUNT); i++) - { - if (topobj_id == gTMO_ItemsPaint[i]) - { - option = view_as(i); - break; - } - } - - if (option == PAINTOPTION_INVALID) - { - return; - } - - if (action == TopMenuAction_DisplayOption) - { - switch (option) - { - case PaintOption_Color: - { - FormatEx(buffer, maxlength, "%T - %T", - gC_PaintOptionPhrases[option], param, - gC_PaintColorPhrases[GOKZ_GetOption(param, gC_PaintOptionNames[option])], param); - } - case PaintOption_Size: - { - FormatEx(buffer, maxlength, "%T - %T", - gC_PaintOptionPhrases[option], param, - gC_PaintSizePhrases[GOKZ_GetOption(param, gC_PaintOptionNames[option])], param); - } - } - } - else if (action == TopMenuAction_SelectOption) - { - if (option == PaintOption_Color) - { - DisplayColorMenu(param); - } - else - { - GOKZ_CycleOption(param, gC_PaintOptionNames[option]); - gTM_Options.Display(param, TopMenuPosition_LastCategory); - } - } -} - -void DisplayColorMenu(int client) -{ - char buffer[32]; - - Menu menu = new Menu(MenuHandler_PaintColor); - menu.ExitButton = true; - menu.ExitBackButton = true; - menu.SetTitle("%T", "Paint Color Menu - Title", client); - - for (int i = 0; i < PAINTCOLOR_COUNT; i++) - { - FormatEx(buffer, sizeof(buffer), "%T", gC_PaintColorPhrases[i], client); - menu.AddItem(gC_PaintColors[i], buffer); - } - - menu.Display(client, MENU_TIME_FOREVER); -} - -int MenuHandler_PaintColor(Menu menu, MenuAction action, int param1, int param2) -{ - switch (action) - { - case MenuAction_Select: - { - char item[32]; - menu.GetItem(param2, item, sizeof(item)); - - for (int i = 0; i < PAINTCOLOR_COUNT; i++) - { - if (StrEqual(gC_PaintColors[i], item)) - { - GOKZ_SetOption(param1, gC_PaintOptionNames[PaintOption_Color], i); - DisplayPaintOptionsMenu(param1); - return 0; - } - } - } - - case MenuAction_Cancel: - { - if (param2 == MenuCancel_ExitBack) - { - DisplayPaintOptionsMenu(param1); - } - } - - case MenuAction_End: - { - delete menu; - } - } - - return 0; -} - - - -// =====[ COMMANDS ]===== - -void RegisterCommands() -{ - RegConsoleCmd("+paint", CommandPaintStart, "[KZ] Start painting."); - RegConsoleCmd("-paint", CommandPaintEnd, "[KZ] Stop painting."); - RegConsoleCmd("sm_paint", CommandPaint, "[KZ] Place a paint."); - RegConsoleCmd("sm_paintoptions", CommandPaintOptions, "[KZ] Open the paint options."); -} - -public Action CommandPaintStart(int client, int args) -{ - gB_IsPainting[client] = true; - return Plugin_Handled; -} - -public Action CommandPaintEnd(int client, int args) -{ - gB_IsPainting[client] = false; - return Plugin_Handled; -} - -public Action CommandPaint(int client, int args) -{ - Paint(client); - return Plugin_Handled; -} - -public Action CommandPaintOptions(int client, int args) -{ - DisplayPaintOptionsMenu(client); - return Plugin_Handled; -} diff --git a/source/sourcemod/scripting/gokz-pistol.sp b/source/sourcemod/scripting/gokz-pistol.sp deleted file mode 100644 index 53f79d9..0000000 --- a/source/sourcemod/scripting/gokz-pistol.sp +++ /dev/null @@ -1,303 +0,0 @@ -#include - -#include -#include - -#include -#include - -#undef REQUIRE_EXTENSIONS -#undef REQUIRE_PLUGIN -#include - -#pragma newdecls required -#pragma semicolon 1 - - - -public Plugin myinfo = -{ - name = "GOKZ Pistol", - author = "DanZay", - description = "Allows players to pick a pistol to KZ with", - version = GOKZ_VERSION, - url = GOKZ_SOURCE_URL -}; - -#define UPDATER_URL GOKZ_UPDATER_BASE_URL..."gokz-pistols.txt" - -TopMenu gTM_Options; -TopMenuObject gTMO_CatGeneral; -TopMenuObject gTMO_ItemPistol; -bool gB_CameFromOptionsMenu[MAXPLAYERS + 1]; - - - -// =====[ PLUGIN EVENTS ]===== - -public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) -{ - RegPluginLibrary("gokz-pistol"); - return APLRes_Success; -} - -public void OnPluginStart() -{ - LoadTranslations("gokz-common.phrases"); - LoadTranslations("gokz-pistol.phrases"); - - HookEvents(); - RegisterCommands(); -} - -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 OnPlayerSpawn(Event event, const char[] name, bool dontBroadcast) // player_spawn post hook -{ - int client = GetClientOfUserId(event.GetInt("userid")); - if (IsValidClient(client)) - { - UpdatePistol(client); - } -} - -public void GOKZ_OnOptionChanged(int client, const char[] option, any newValue) -{ - if (StrEqual(option, PISTOL_OPTION_NAME)) - { - UpdatePistol(client); - } -} - - - -// =====[ OTHER EVENTS ]===== - -public void GOKZ_OnOptionsMenuReady(TopMenu topMenu) -{ - OnOptionsMenuReady_Options(); - OnOptionsMenuReady_OptionsMenu(topMenu); -} - - - -// =====[ GENERAL ]===== - -void HookEvents() -{ - HookEvent("player_spawn", OnPlayerSpawn, EventHookMode_Post); -} - - - -// =====[ PISTOL ]===== - -void UpdatePistol(int client) -{ - GivePistol(client, GOKZ_GetOption(client, PISTOL_OPTION_NAME)); -} - -void GivePistol(int client, int pistol) -{ - if (!IsClientInGame(client) || !IsPlayerAlive(client) - || GetClientTeam(client) == CS_TEAM_NONE) - { - return; - } - - int playerTeam = GetClientTeam(client); - bool switchedTeams = false; - - // Switch teams to the side that buys that gun so that gun skins load - if (gI_PistolTeams[pistol] == CS_TEAM_CT && playerTeam != CS_TEAM_CT) - { - CS_SwitchTeam(client, CS_TEAM_CT); - switchedTeams = true; - } - else if (gI_PistolTeams[pistol] == CS_TEAM_T && playerTeam != CS_TEAM_T) - { - CS_SwitchTeam(client, CS_TEAM_T); - switchedTeams = true; - } - - // Give the player this pistol (or remove it) - int currentPistol = GetPlayerWeaponSlot(client, CS_SLOT_SECONDARY); - if (currentPistol != -1) - { - RemovePlayerItem(client, currentPistol); - } - - if (pistol == Pistol_Disabled) - { - // Force switch to knife to avoid weird behaviour - // Doesn't use EquipPlayerWeapon because server hangs when player spawns - FakeClientCommand(client, "use weapon_knife"); - } - else - { - GivePlayerItem(client, gC_PistolClassNames[pistol]); - } - - // Go back to original team - if (switchedTeams) - { - CS_SwitchTeam(client, playerTeam); - } -} - - - -// =====[ PISTOL MENU ]===== - -void DisplayPistolMenu(int client, int atItem = 0, bool fromOptionsMenu = false) -{ - Menu menu = new Menu(MenuHandler_Pistol); - menu.SetTitle("%T", "Pistol Menu - Title", client); - PistolMenuAddItems(client, menu); - menu.DisplayAt(client, atItem, MENU_TIME_FOREVER); - - gB_CameFromOptionsMenu[client] = fromOptionsMenu; -} - -public int MenuHandler_Pistol(Menu menu, MenuAction action, int param1, int param2) -{ - if (action == MenuAction_Select) - { - GOKZ_SetOption(param1, PISTOL_OPTION_NAME, param2); - DisplayPistolMenu(param1, param2 / 6 * 6, gB_CameFromOptionsMenu[param1]); // Re-display menu at same spot - } - else if (action == MenuAction_Cancel && gB_CameFromOptionsMenu[param1]) - { - gTM_Options.Display(param1, TopMenuPosition_LastCategory); - } - else if (action == MenuAction_End) - { - delete menu; - } - return 0; -} - -void PistolMenuAddItems(int client, Menu menu) -{ - int selectedPistol = GOKZ_GetOption(client, PISTOL_OPTION_NAME); - char display[32]; - - for (int pistol = 0; pistol < PISTOL_COUNT; pistol++) - { - if (pistol == Pistol_Disabled) - { - FormatEx(display, sizeof(display), "%T", "Options Menu - Disabled", client); - } - else - { - FormatEx(display, sizeof(display), "%s", gC_PistolNames[pistol]); - } - - // Add asterisk to selected pistol - if (pistol == selectedPistol) - { - Format(display, sizeof(display), "%s*", display); - } - - menu.AddItem("", display, ITEMDRAW_DEFAULT); - } -} - - - -// =====[ OPTIONS ]===== - -void OnOptionsMenuReady_Options() -{ - RegisterOption(); -} - -void RegisterOption() -{ - GOKZ_RegisterOption(PISTOL_OPTION_NAME, PISTOL_OPTION_DESCRIPTION, - OptionType_Int, Pistol_USPS, 0, PISTOL_COUNT - 1); -} - - - -// =====[ OPTIONS MENU ]===== - -void OnOptionsMenuReady_OptionsMenu(TopMenu topMenu) -{ - if (gTM_Options == topMenu) - { - return; - } - - gTM_Options = topMenu; - gTMO_CatGeneral = gTM_Options.FindCategory(GENERAL_OPTION_CATEGORY); - gTMO_ItemPistol = gTM_Options.AddItem(PISTOL_OPTION_NAME, TopMenuHandler_Pistol, gTMO_CatGeneral); -} - -public void TopMenuHandler_Pistol(TopMenu topmenu, TopMenuAction action, TopMenuObject topobj_id, int param, char[] buffer, int maxlength) -{ - if (topobj_id != gTMO_ItemPistol) - { - return; - } - - if (action == TopMenuAction_DisplayOption) - { - int pistol = GOKZ_GetOption(param, PISTOL_OPTION_NAME); - if (pistol == Pistol_Disabled) - { - FormatEx(buffer, maxlength, "%T - %T", - "Options Menu - Pistol", param, - "Options Menu - Disabled", param); - } - else - { - FormatEx(buffer, maxlength, "%T - %s", - "Options Menu - Pistol", param, - gC_PistolNames[pistol]); - } - } - else if (action == TopMenuAction_SelectOption) - { - DisplayPistolMenu(param, _, true); - } -} - - - -// =====[ COMMANDS ]===== - -void RegisterCommands() -{ - RegConsoleCmd("sm_pistol", CommandPistolMenu, "[KZ] Open the pistol selection menu."); -} - -public Action CommandPistolMenu(int client, int args) -{ - DisplayPistolMenu(client); - return Plugin_Handled; -} \ No newline at end of file diff --git a/source/sourcemod/scripting/gokz-playermodels.sp b/source/sourcemod/scripting/gokz-playermodels.sp deleted file mode 100644 index 237b7df..0000000 --- a/source/sourcemod/scripting/gokz-playermodels.sp +++ /dev/null @@ -1,198 +0,0 @@ -#include - -#include -#include - -#include - -#include - -#undef REQUIRE_EXTENSIONS -#undef REQUIRE_PLUGIN -#include - -#pragma newdecls required -#pragma semicolon 1 - - - -public Plugin myinfo = -{ - name = "GOKZ Player Models", - author = "DanZay", - description = "Sets player's model upon spawning", - version = GOKZ_VERSION, - url = GOKZ_SOURCE_URL -}; - -#define UPDATER_URL GOKZ_UPDATER_BASE_URL..."gokz-playermodels.txt" -#define PLAYER_MODEL_T "models/player/tm_leet_varianta.mdl" -#define PLAYER_MODEL_CT "models/player/ctm_idf_variantc.mdl" -#define PLAYER_MODEL_T_BOT "models/player/custom_player/legacy/tm_leet_varianta.mdl" -#define PLAYER_MODEL_CT_BOT "models/player/custom_player/legacy/ctm_idf_variantc.mdl" -ConVar gCV_gokz_player_models_alpha; -ConVar gCV_sv_disable_immunity_alpha; - - - -// =====[ PLUGIN EVENTS ]===== - -public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) -{ - RegPluginLibrary("gokz-playermodels"); - return APLRes_Success; -} - -public void OnPluginStart() -{ - CreateConVars(); - HookEvents(); -} - -public void OnAllPluginsLoaded() -{ - if (LibraryExists("updater")) - { - Updater_AddPlugin(UPDATER_URL); - } -} - -public void OnLibraryAdded(const char[] name) -{ - if (StrEqual(name, "updater")) - { - Updater_AddPlugin(UPDATER_URL); - } -} - - - -// =====[ CLIENT EVENTS ]===== - -public void OnPlayerSpawn(Event event, const char[] name, bool dontBroadcast) // player_spawn post hook -{ - int client = GetClientOfUserId(event.GetInt("userid")); - if (IsValidClient(client)) - { - // Can't use a timer here because it's not precise enough. We want exactly 2 ticks of delay! - // 2 ticks is the minimum amount of time after which gloves will work. - // The reason we need precision is because SetEntityModel momentarily resets the - // player hull to standing (or something along those lines), so when a player - // spawns/gets reset to a crouch tunnel where there's a trigger less than 18 units from the top - // of the ducked player hull, then they touch that trigger! SetEntityModel interferes with the - // fix for that (JoinTeam in gokz-core/misc calls TeleportPlayer in gokz.inc, which fixes that bug). - RequestFrame(RequestFrame_UpdatePlayerModel, GetClientUserId(client)); - } -} - - - -// =====[ OTHER EVENTS ]===== - -public void OnMapStart() -{ - PrecachePlayerModels(); -} - - - -// =====[ GENERAL ]===== - -void HookEvents() -{ - HookEvent("player_spawn", OnPlayerSpawn, EventHookMode_Post); -} - - - -// =====[ CONVARS ]===== - -void CreateConVars() -{ - AutoExecConfig_SetFile("gokz-playermodels", "sourcemod/gokz"); - AutoExecConfig_SetCreateFile(true); - - gCV_gokz_player_models_alpha = AutoExecConfig_CreateConVar("gokz_player_models_alpha", "65", "Amount of alpha (transparency) to set player models to.", _, true, 0.0, true, 255.0); - gCV_gokz_player_models_alpha.AddChangeHook(OnConVarChanged); - - AutoExecConfig_ExecuteFile(); - AutoExecConfig_CleanFile(); - - gCV_sv_disable_immunity_alpha = FindConVar("sv_disable_immunity_alpha"); -} - -public void OnConVarChanged(ConVar convar, const char[] oldValue, const char[] newValue) -{ - if (convar == gCV_gokz_player_models_alpha) - { - for (int client = 1; client <= MaxClients; client++) - { - if (IsClientInGame(client) && IsPlayerAlive(client)) - { - UpdatePlayerModelAlpha(client); - } - } - } -} - - - -// =====[ PLAYER MODELS ]===== - -public void RequestFrame_UpdatePlayerModel(int userid) -{ - RequestFrame(RequestFrame_UpdatePlayerModel2, userid); -} - -public void RequestFrame_UpdatePlayerModel2(int userid) -{ - int client = GetClientOfUserId(userid); - if (!IsValidClient(client) || !IsPlayerAlive(client)) - { - return; - } - // Bots are unaffected by the bobbing animation caused by the new models. - switch (GetClientTeam(client)) - { - case CS_TEAM_T: - { - if (IsFakeClient(client)) - { - SetEntityModel(client, PLAYER_MODEL_T_BOT); - } - else - { - SetEntityModel(client, PLAYER_MODEL_T); - } - } - case CS_TEAM_CT: - { - if (IsFakeClient(client)) - { - SetEntityModel(client, PLAYER_MODEL_CT_BOT); - } - else - { - SetEntityModel(client, PLAYER_MODEL_CT); - } - } - } - - UpdatePlayerModelAlpha(client); -} - -void UpdatePlayerModelAlpha(int client) -{ - SetEntityRenderMode(client, RENDER_TRANSCOLOR); - SetEntityRenderColor(client, _, _, _, gCV_gokz_player_models_alpha.IntValue); -} - -void PrecachePlayerModels() -{ - gCV_sv_disable_immunity_alpha.IntValue = 1; // Ensures player transparency works - - PrecacheModel(PLAYER_MODEL_T, true); - PrecacheModel(PLAYER_MODEL_CT, true); - PrecacheModel(PLAYER_MODEL_T_BOT, true); - PrecacheModel(PLAYER_MODEL_CT_BOT, true); -} \ No newline at end of file diff --git a/source/sourcemod/scripting/gokz-profile.sp b/source/sourcemod/scripting/gokz-profile.sp deleted file mode 100644 index 9d92e61..0000000 --- a/source/sourcemod/scripting/gokz-profile.sp +++ /dev/null @@ -1,396 +0,0 @@ -#include - -#include - -#include -#include -#include - -#undef REQUIRE_EXTENSIONS -#undef REQUIRE_PLUGIN -#include -#include - -#pragma newdecls required -#pragma semicolon 1 - - - -public Plugin myinfo = -{ - name = "GOKZ Profile", - author = "zealain", - description = "Player profiles and ranks based on local and global data.", - version = GOKZ_VERSION, - url = GOKZ_SOURCE_URL -}; - -#define UPDATER_URL GOKZ_UPDATER_BASE_URL..."gokz-profile.txt" - -int gI_Rank[MAXPLAYERS + 1][MODE_COUNT]; -bool gB_Localranks; -bool gB_Chat; - -#include "gokz-profile/options.sp" -#include "gokz-profile/profile.sp" - - - -// =====[ PLUGIN EVENTS ]===== - -public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) -{ - CreateNatives(); - RegPluginLibrary("gokz-profile"); - return APLRes_Success; -} - -public void OnPluginStart() -{ - LoadTranslations("common.phrases"); - LoadTranslations("gokz-profile.phrases"); - CreateGlobalForwards(); - RegisterCommands(); -} - -public void OnAllPluginsLoaded() -{ - if (LibraryExists("updater")) - { - Updater_AddPlugin(UPDATER_URL); - } - gB_Localranks = LibraryExists("gokz-localranks"); - gB_Chat = LibraryExists("gokz-chat"); - - for (int client = 1; client <= MaxClients; client++) - { - if (IsValidClient(client) && !IsFakeClient(client)) - { - UpdateRank(client, GOKZ_GetCoreOption(client, Option_Mode)); - } - } - - 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); - } - gB_Localranks = gB_Localranks || StrEqual(name, "gokz-localranks"); - gB_Chat = gB_Chat || StrEqual(name, "gokz-chat"); -} - -public void OnLibraryRemoved(const char[] name) -{ - gB_Localranks = gB_Localranks && !StrEqual(name, "gokz-localranks"); - gB_Chat = gB_Chat && !StrEqual(name, "gokz-chat"); -} - - - -// =====[ EVENTS ]===== - -public Action OnClientCommandKeyValues(int client, KeyValues kv) -{ - // Block clan tag changes - Credit: GoD-Tony (https://forums.alliedmods.net/showpost.php?p=2337679&postcount=6) - char cmd[16]; - if (kv.GetSectionName(cmd, sizeof(cmd)) && StrEqual(cmd, "ClanTagChanged", false)) - { - return Plugin_Handled; - } - return Plugin_Continue; -} - -public void OnRebuildAdminCache(AdminCachePart part) -{ - for (int client = 1; client <= MaxClients; client++) - { - if (IsValidClient(client) && !IsFakeClient(client)) - { - int mode = GOKZ_GetCoreOption(client, Option_Mode); - UpdateRank(client, mode); - } - } -} - -public void GOKZ_OnOptionsMenuCreated(TopMenu topMenu) -{ - OnOptionsMenuCreated_OptionsMenu(topMenu); -} - -public void GOKZ_OnOptionsMenuReady(TopMenu topMenu) -{ - OnOptionsMenuReady_Options(); - OnOptionsMenuReady_OptionsMenu(topMenu); -} - -public void GOKZ_OnOptionsLoaded(int client) -{ - if (IsValidClient(client) && !IsFakeClient(client)) - { - int mode = GOKZ_GetCoreOption(client, Option_Mode); - UpdateTags(client, gI_Rank[client][mode], mode); - } -} - -public void OnClientConnected(int client) -{ - for (int mode = 0; mode < MODE_COUNT; mode++) - { - gI_Rank[client][mode] = 0; - } - Profile_OnClientConnected(client); -} - -public void OnClientDisconnect(int client) -{ - Profile_OnClientDisconnect(client); -} - -public void GOKZ_OnOptionChanged(int client, const char[] option, any newValue) -{ - Option coreOption; - if (GOKZ_IsCoreOption(option, coreOption) && coreOption == Option_Mode) - { - UpdateRank(client, newValue); - } - else if (StrEqual(option, gC_ProfileOptionNames[ProfileOption_ShowRankChat], true) - || StrEqual(option, gC_ProfileOptionNames[ProfileOption_ShowRankClanTag], true) - || StrEqual(option, gC_ProfileOptionNames[ProfileOption_TagType], true)) - { - UpdateRank(client, GOKZ_GetCoreOption(client, Option_Mode)); - } -} - -public void GOKZ_GL_OnPointsUpdated(int client, int mode) -{ - UpdateRank(client, mode); - Profile_OnPointsUpdated(client, mode); -} - -public void UpdateRank(int client, int mode) -{ - if (!IsValidClient(client) || IsFakeClient(client)) - { - return; - } - - int tagType = GetAvailableTagTypeOrDefault(client); - - if (tagType != ProfileTagType_Rank) - { - char clanTag[64], chatTag[32], color[64]; - - if (tagType == ProfileTagType_Admin) - { - FormatEx(clanTag, sizeof(clanTag), "[%s %T]", gC_ModeNamesShort[mode], "Tag - Admin", client); - FormatEx(chatTag, sizeof(chatTag), "%T", "Tag - Admin", client); - color = TAG_COLOR_ADMIN; - } - if (tagType == ProfileTagType_VIP) - { - FormatEx(clanTag, sizeof(clanTag), "[%s %T]", gC_ModeNamesShort[mode], "Tag - VIP", client); - FormatEx(chatTag, sizeof(chatTag), "%T", "Tag - VIP", client); - color = TAG_COLOR_VIP; - } - - if (GOKZ_GetOption(client, gC_ProfileOptionNames[ProfileOption_ShowRankClanTag]) != ProfileOptionBool_Enabled) - { - FormatEx(clanTag, sizeof(clanTag), "[%s]", gC_ModeNamesShort[mode]); - } - CS_SetClientClanTag(client, clanTag); - - if (gB_Chat) - { - if (GOKZ_GetOption(client, gC_ProfileOptionNames[ProfileOption_ShowRankChat]) == ProfileOptionBool_Enabled) - { - GOKZ_CH_SetChatTag(client, chatTag, color); - } - else - { - GOKZ_CH_SetChatTag(client, "", "{default}"); - } - } - return; - } - - int points = GOKZ_GL_GetRankPoints(client, mode); - int rank; - for (rank = 1; rank < RANK_COUNT; rank++) - { - if (points < gI_rankThreshold[mode][rank]) - { - break; - } - } - rank--; - - if (GOKZ_GetCoreOption(client, Option_Mode) == mode) - { - if (points == -1) - { - UpdateTags(client, -1, mode); - } - else - { - UpdateTags(client, rank, mode); - } - } - - if (gI_Rank[client][mode] != rank) - { - gI_Rank[client][mode] = rank; - Call_OnRankUpdated(client, mode, rank); - } -} - -void UpdateTags(int client, int rank, int mode) -{ - char str[64]; - if (rank != -1 && - GOKZ_GetOption(client, gC_ProfileOptionNames[ProfileOption_ShowRankClanTag]) == ProfileOptionBool_Enabled) - { - FormatEx(str, sizeof(str), "[%s %s]", gC_ModeNamesShort[mode], gC_rankName[rank]); - CS_SetClientClanTag(client, str); - } - else - { - FormatEx(str, sizeof(str), "[%s]", gC_ModeNamesShort[mode]); - CS_SetClientClanTag(client, str); - } - - if (gB_Chat) - { - if (rank != -1 && - GOKZ_GetOption(client, gC_ProfileOptionNames[ProfileOption_ShowRankChat]) == ProfileOptionBool_Enabled) - { - GOKZ_CH_SetChatTag(client, gC_rankName[rank], gC_rankColor[rank]); - } - else - { - GOKZ_CH_SetChatTag(client, "", "{default}"); - } - } -} - -bool CanUseTagType(int client, int tagType) -{ - switch (tagType) - { - case ProfileTagType_Rank: return true; - case ProfileTagType_VIP: return CheckCommandAccess(client, "gokz_flag_vip", ADMFLAG_CUSTOM1); - case ProfileTagType_Admin: return CheckCommandAccess(client, "gokz_flag_admin", ADMFLAG_GENERIC); - default: return false; - } -} - -int GetAvailableTagTypeOrDefault(int client) -{ - int tagType = GOKZ_GetOption(client, gC_ProfileOptionNames[ProfileOption_TagType]); - if (!CanUseTagType(client, tagType)) - { - return ProfileTagType_Rank; - } - - return tagType; -} - -// =====[ COMMANDS ]===== - -void RegisterCommands() -{ - RegConsoleCmd("sm_profile", CommandProfile, "[KZ] Show the profile of a player. Usage: !profile "); - RegConsoleCmd("sm_p", CommandProfile, "[KZ] Show the profile of a player. Usage: !p "); - RegConsoleCmd("sm_profileoptions", CommandProfileOptions, "[KZ] Show the profile options."); - RegConsoleCmd("sm_pfo", CommandProfileOptions, "[KZ] Show the profile options."); - RegConsoleCmd("sm_ranks", CommandRanks, "[KZ] Show all the available ranks."); -} - -public Action CommandProfile(int client, int args) -{ - if (args == 0) - { - ShowProfile(client, client); - } - else - { - char playerName[64]; - GetCmdArgString(playerName, sizeof(playerName)); - int player = FindTarget(client, playerName, true, false); - if (player != -1) - { - ShowProfile(client, player); - } - } - return Plugin_Handled; -} - -public Action CommandProfileOptions(int client, int args) -{ - DisplayProfileOptionsMenu(client); - return Plugin_Handled; -} - -public Action CommandRanks(int client, int args) -{ - char rankBuffer[256]; - char buffer[256]; - int mode = GOKZ_GetCoreOption(client, Option_Mode); - - Format(buffer, sizeof(buffer), "%s: ", gC_ModeNamesShort[mode]); - - for (int i = 0; i < RANK_COUNT; i++) { - Format(rankBuffer, sizeof(rankBuffer), "%s%s (%d) ", gC_rankColor[i], gC_rankName[i], gI_rankThreshold[mode][i]); - StrCat(buffer, sizeof(buffer), rankBuffer); - - if (i > 0 && i % 3 == 0) { - GOKZ_PrintToChat(client, true, buffer); - Format(buffer, sizeof(buffer), "%s: ", gC_ModeNamesShort[mode]); - } - } - - GOKZ_PrintToChat(client, true, buffer); - - return Plugin_Handled; -} - - -// =====[ FORWARDS ]===== - -static GlobalForward H_OnRankUpdated; - - -void CreateGlobalForwards() -{ - H_OnRankUpdated = new GlobalForward("GOKZ_PF_OnRankUpdated", ET_Ignore, Param_Cell, Param_Cell, Param_Cell); -} - -void Call_OnRankUpdated(int client, int mode, int rank) -{ - Call_StartForward(H_OnRankUpdated); - Call_PushCell(client); - Call_PushCell(mode); - Call_PushCell(rank); - Call_Finish(); -} - - - -// =====[ NATIVES ]===== - -void CreateNatives() -{ - CreateNative("GOKZ_PF_GetRank", Native_GetRank); -} - -public int Native_GetRank(Handle plugin, int numParams) -{ - return gI_Rank[GetNativeCell(1)][GetNativeCell(2)]; -} diff --git a/source/sourcemod/scripting/gokz-quiet.sp b/source/sourcemod/scripting/gokz-quiet.sp deleted file mode 100644 index 06cc246..0000000 --- a/source/sourcemod/scripting/gokz-quiet.sp +++ /dev/null @@ -1,151 +0,0 @@ -#include - -#include -#include -#include - -#include -#include - -#undef REQUIRE_EXTENSIONS -#undef REQUIRE_PLUGIN -#include - -#pragma newdecls required -#pragma semicolon 1 - - - -public Plugin myinfo = -{ - name = "GOKZ Quiet", - author = "DanZay", - description = "Provides options for a quieter KZ experience", - version = GOKZ_VERSION, - url = GOKZ_SOURCE_URL -}; - -#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" -#include "gokz-quiet/gokz-sounds.sp" -#include "gokz-quiet/options.sp" - -// =====[ PLUGIN EVENTS ]===== - -public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) -{ - RegPluginLibrary("gokz-quiet"); - return APLRes_Success; -} - -public void OnPluginStart() -{ - OnPluginStart_HidePlayers(); - OnPluginStart_FallDamage(); - OnPluginStart_Ambient(); - - LoadTranslations("gokz-common.phrases"); - LoadTranslations("gokz-quiet.phrases"); - - RegisterCommands(); -} - -public void OnAllPluginsLoaded() -{ - if (LibraryExists("updater")) - { - Updater_AddPlugin(UPDATER_URL); - } - - TopMenu topMenu; - if (LibraryExists("gokz-core") && ((topMenu = GOKZ_GetOptionsTopMenu()) != null)) - { - GOKZ_OnOptionsMenuReady(topMenu); - } - - for (int client = 1; client <= MaxClients; client++) - { - if (IsClientInGame(client)) - { - GOKZ_OnJoinTeam(client, GetClientTeam(client)); - } - } -} - -public void OnLibraryAdded(const char[] name) -{ - if (StrEqual(name, "updater")) - { - Updater_AddPlugin(UPDATER_URL); - } -} - - - -// =====[ CLIENT EVENTS ]===== - -public void GOKZ_OnJoinTeam(int client, int team) -{ - OnJoinTeam_HidePlayers(client, team); -} - -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)) - { - return; - } - - OnPlayerRunCmdPost_Soundscape(client); -} - - -// =====[ OTHER EVENTS ]===== - -public void GOKZ_OnOptionsMenuReady(TopMenu topMenu) -{ - OnOptionsMenuReady_Options(); - OnOptionsMenuReady_OptionsMenu(topMenu); -} - -public void GOKZ_OnOptionChanged(int client, const char[] option, any newValue) -{ - any qtOption; - if (GOKZ_QT_IsQTOption(option, qtOption)) - { - OnOptionChanged_Options(client, qtOption, newValue); - } -} - -public void GOKZ_OnOptionsMenuCreated(TopMenu topMenu) -{ - OnOptionsMenuCreated_OptionsMenu(topMenu); -} - -// =====[ STOP SOUNDS ]===== - -void StopSounds(int client) -{ - ClientCommand(client, "snd_playsounds Music.StopAllExceptMusic"); - GOKZ_PrintToChat(client, true, "%t", "Stopped Sounds"); -} - - -// =====[ COMMANDS ]===== - -void RegisterCommands() -{ - RegConsoleCmd("sm_hide", CommandToggleShowPlayers, "[KZ] Toggle the visibility of other players."); - RegConsoleCmd("sm_stopsound", CommandStopSound, "[KZ] Stop all sounds e.g. map soundscapes (music)."); -} - -public Action CommandStopSound(int client, int args) -{ - StopSounds(client); - return Plugin_Handled; -} \ No newline at end of file diff --git a/source/sourcemod/scripting/gokz-racing.sp b/source/sourcemod/scripting/gokz-racing.sp deleted file mode 100644 index 416d28a..0000000 --- a/source/sourcemod/scripting/gokz-racing.sp +++ /dev/null @@ -1,174 +0,0 @@ -#include - -#include -#include - -#undef REQUIRE_EXTENSIONS -#undef REQUIRE_PLUGIN -#include - -#pragma newdecls required -#pragma semicolon 1 - - - -public Plugin myinfo = -{ - name = "GOKZ Racing", - author = "DanZay", - description = "Lets players race against each other", - version = GOKZ_VERSION, - url = GOKZ_SOURCE_URL -}; - -#define UPDATER_URL GOKZ_UPDATER_BASE_URL..."gokz-racing.txt" - -#include "gokz-racing/announce.sp" -#include "gokz-racing/api.sp" -#include "gokz-racing/commands.sp" -#include "gokz-racing/duel_menu.sp" -#include "gokz-racing/race.sp" -#include "gokz-racing/race_menu.sp" -#include "gokz-racing/racer.sp" - - - -// =====[ PLUGIN EVENTS ]===== - -public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) -{ - CreateNatives(); - RegPluginLibrary("gokz-racing"); - return APLRes_Success; -} - -public void OnPluginStart() -{ - LoadTranslations("gokz-common.phrases"); - LoadTranslations("gokz-racing.phrases"); - - CreateGlobalForwards(); - RegisterCommands(); - - OnPluginStart_Race(); -} - -public void OnAllPluginsLoaded() -{ - if (LibraryExists("updater")) - { - Updater_AddPlugin(UPDATER_URL); - } -} - -public void OnLibraryAdded(const char[] name) -{ - if (StrEqual(name, "updater")) - { - Updater_AddPlugin(UPDATER_URL); - } -} - - - -// =====[ CLIENT EVENTS ]===== - -public void OnClientPutInServer(int client) -{ - OnClientPutInServer_Racer(client); -} - -public void OnClientDisconnect(int client) -{ - OnClientDisconnect_Racer(client); -} - -public Action GOKZ_OnTimerStart(int client, int course) -{ - Action action = OnTimerStart_Racer(client, course); - if (action != Plugin_Continue) - { - return action; - } - - return Plugin_Continue; -} - -public void GOKZ_OnTimerStart_Post(int client, int course) -{ - OnTimerStart_Post_Racer(client); -} - -public void GOKZ_OnTimerEnd_Post(int client, int course, float time, int teleportsUsed) -{ - FinishRacer(client, course); -} - -public Action GOKZ_OnMakeCheckpoint(int client) -{ - Action action = OnMakeCheckpoint_Racer(client); - if (action != Plugin_Continue) - { - return action; - } - - return Plugin_Continue; -} - -public void GOKZ_OnMakeCheckpoint_Post(int client) -{ - OnMakeCheckpoint_Post_Racer(client); -} - -public Action GOKZ_OnUndoTeleport(int client) -{ - Action action = OnUndoTeleport_Racer(client); - if (action != Plugin_Continue) - { - return action; - } - - return Plugin_Continue; -} - -public void GOKZ_RC_OnFinish(int client, int raceID, int place) -{ - OnFinish_Announce(client, raceID, place); - OnFinish_Race(raceID); -} - -public void GOKZ_RC_OnSurrender(int client, int raceID) -{ - OnSurrender_Announce(client, raceID); -} - -public void GOKZ_RC_OnRequestReceived(int client, int raceID) -{ - OnRequestReceived_Announce(client, raceID); -} - -public void GOKZ_RC_OnRequestAccepted(int client, int raceID) -{ - OnRequestAccepted_Announce(client, raceID); - OnRequestAccepted_Race(raceID); -} - -public void GOKZ_RC_OnRequestDeclined(int client, int raceID, bool timeout) -{ - OnRequestDeclined_Announce(client, raceID, timeout); - OnRequestDeclined_Race(raceID); -} - - - -// =====[ OTHER EVENTS ]===== - -public void GOKZ_RC_OnRaceStarted(int raceID) -{ - OnRaceStarted_Announce(raceID); -} - -public void GOKZ_RC_OnRaceAborted(int raceID) -{ - OnRaceAborted_Announce(raceID); -} \ No newline at end of file diff --git a/source/sourcemod/scripting/gokz-replays.sp b/source/sourcemod/scripting/gokz-replays.sp deleted file mode 100644 index bc826c4..0000000 --- a/source/sourcemod/scripting/gokz-replays.sp +++ /dev/null @@ -1,397 +0,0 @@ -#include - -#include -#include -#include -#include - -#include - -#include -#include -#include - -#undef REQUIRE_EXTENSIONS -#undef REQUIRE_PLUGIN -#include -#include -#include -#include - -#pragma newdecls required -#pragma semicolon 1 - -//#define DEBUG - - - -public Plugin myinfo = -{ - name = "GOKZ Replays", - author = "DanZay", - description = "Records runs to disk and allows playback using bots", - version = GOKZ_VERSION, - url = GOKZ_SOURCE_URL -}; - -#define UPDATER_URL GOKZ_UPDATER_BASE_URL..."gokz-replays.txt" - -bool gB_GOKZHUD; -bool gB_GOKZLocalDB; -char gC_CurrentMap[64]; -int gI_CurrentMapFileSize; -bool gB_HideNameChange; -bool gB_NubRecordMissed[MAXPLAYERS + 1]; -ArrayList g_ReplayInfoCache; -Address gA_BotDuckAddr; -int gI_BotDuckPatchRestore[40]; // Size of patched section in gamedata -int gI_BotDuckPatchLength; - -DynamicDetour gH_DHooks_TeamFull; - -#include "gokz-replays/commands.sp" -#include "gokz-replays/nav.sp" -#include "gokz-replays/playback.sp" -#include "gokz-replays/recording.sp" -#include "gokz-replays/replay_cache.sp" -#include "gokz-replays/replay_menu.sp" -#include "gokz-replays/api.sp" -#include "gokz-replays/controls.sp" - - - -// =====[ PLUGIN EVENTS ]===== - -public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) -{ - CreateNatives(); - RegPluginLibrary("gokz-replays"); - return APLRes_Success; -} - -public void OnPluginStart() -{ - LoadTranslations("gokz-common.phrases"); - LoadTranslations("gokz-replays.phrases"); - - CreateGlobalForwards(); - HookEvents(); - RegisterCommands(); -} - -public void OnAllPluginsLoaded() -{ - if (LibraryExists("updater")) - { - Updater_AddPlugin(UPDATER_URL); - } - gB_GOKZLocalDB = LibraryExists("gokz-localdb"); - gB_GOKZHUD = LibraryExists("gokz-hud"); - - for (int client = 1; client <= MaxClients; client++) - { - if (IsClientInGame(client)) - { - OnClientPutInServer(client); - } - } -} - -public void OnLibraryAdded(const char[] name) -{ - if (StrEqual(name, "updater")) - { - 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"); -} - -public void OnPluginEnd() -{ - // Restore bot auto duck behavior. - 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 ]===== - -public void OnMapStart() -{ - UpdateCurrentMap(); // Do first - OnMapStart_Nav(); - OnMapStart_Recording(); - OnMapStart_ReplayCache(); -} - -public void OnConfigsExecuted() -{ - FindConVar("mp_autoteambalance").BoolValue = false; - FindConVar("mp_limitteams").IntValue = 0; - // Stop the bots! - FindConVar("bot_stop").BoolValue = true; - FindConVar("bot_chatter").SetString("off"); - 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) -{ - // Block trigger and door interaction for bots - // Credit to shavit's simple bhop timer - https://github.com/shavitush/bhoptimer - - // trigger_once | trigger_multiple.. etc - // func_door | func_door_rotating - if (StrContains(classname, "trigger_") != -1 || StrContains(classname, "_door") != -1) - { - SDKHook(entity, SDKHook_StartTouch, HookTriggers); - SDKHook(entity, SDKHook_EndTouch, HookTriggers); - SDKHook(entity, SDKHook_Touch, HookTriggers); - } -} - -public Action HookTriggers(int entity, int other) -{ - if (other >= 1 && other <= MaxClients && IsFakeClient(other)) - { - return Plugin_Handled; - } - - return Plugin_Continue; -} - -public Action Hook_SayText2(UserMsg msg_id, any msg, const int[] players, int playersNum, bool reliable, bool init) -{ - // Name change supression - // Credit to shavit's simple bhop timer - https://github.com/shavitush/bhoptimer - if (!gB_HideNameChange) - { - return Plugin_Continue; - } - - char msgName[24]; - Protobuf pbmsg = msg; - pbmsg.ReadString("msg_name", msgName, sizeof(msgName)); - if (StrEqual(msgName, "#Cstrike_Name_Change")) - { - gB_HideNameChange = false; - return Plugin_Handled; - } - - return Plugin_Continue; -} - -public MRESReturn DHooks_OnTeamFull_Pre(Address pThis, DHookReturn hReturn, DHookParam hParams) -{ - DHookSetReturn(hReturn, false); - return MRES_Supercede; -} - -// =====[ CLIENT EVENTS ]===== - -public void OnClientPutInServer(int client) -{ - OnClientPutInServer_Playback(client); - OnClientPutInServer_Recording(client); -} - -public void OnClientAuthorized(int client, const char[] auth) -{ - OnClientAuthorized_Recording(client); -} - -public void OnClientDisconnect(int client) -{ - OnClientDisconnect_Playback(client); - OnClientDisconnect_Recording(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]) -{ - 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); -} - -public Action GOKZ_OnTimerStart(int client, int course) -{ - Action action = GOKZ_OnTimerStart_Recording(client); - if (action != Plugin_Continue) - { - return action; - } - - return Plugin_Continue; -} - -public void GOKZ_OnTimerStart_Post(int client, int course) -{ - gB_NubRecordMissed[client] = false; - GOKZ_OnTimerStart_Post_Recording(client); -} - -public void GOKZ_OnTimerEnd_Post(int client, int course, float time, int teleportsUsed) -{ - GOKZ_OnTimerEnd_Recording(client, course, time, teleportsUsed); -} - -public void GOKZ_OnPause_Post(int client) -{ - GOKZ_OnPause_Recording(client); -} - -public void GOKZ_OnResume_Post(int client) -{ - GOKZ_OnResume_Recording(client); -} - -public void GOKZ_OnTimerStopped(int client) -{ - GOKZ_OnTimerStopped_Recording(client); -} - -public void GOKZ_OnCountedTeleport_Post(int client) -{ - GOKZ_OnCountedTeleport_Recording(client); -} - -public void GOKZ_LR_OnRecordMissed(int client, float recordTime, int course, int mode, int style, int recordType) -{ - if (recordType == RecordType_Nub) - { - gB_NubRecordMissed[client] = true; - } - GOKZ_LR_OnRecordMissed_Recording(client, recordType); -} - -public void GOKZ_AC_OnPlayerSuspected(int client, ACReason reason) -{ - GOKZ_AC_OnPlayerSuspected_Recording(client, reason); -} - -public void GOKZ_DB_OnJumpstatPB(int client, int jumptype, int mode, float distance, int block, int strafes, float sync, float pre, float max, int airtime) -{ - GOKZ_DB_OnJumpstatPB_Recording(client, jumptype, distance, block, strafes, sync, pre, max, airtime); -} - -public void GOKZ_OnOptionsLoaded(int client) -{ - if (IsFakeClient(client)) - { - GOKZ_OnOptionsLoaded_Playback(client); - } -} - -// =====[ PRIVATE ]===== - -static void HookEvents() -{ - HookUserMessage(GetUserMessageId("SayText2"), Hook_SayText2, true); - GameData gameData = LoadGameConfigFile("gokz-replays.games"); - - gH_DHooks_TeamFull = DynamicDetour.FromConf(gameData, "CCSGameRules::TeamFull"); - if (gH_DHooks_TeamFull == INVALID_HANDLE) - { - SetFailState("Failed to find CCSGameRules::TeamFull function signature"); - } - - if (!gH_DHooks_TeamFull.Enable(Hook_Pre, DHooks_OnTeamFull_Pre)) - { - SetFailState("Failed to enable detour on CCSGameRules::TeamFull"); - } - - // Remove bot auto duck behavior. - 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; -} - -static void UpdateCurrentMap() -{ - GetCurrentMapDisplayName(gC_CurrentMap, sizeof(gC_CurrentMap)); - gI_CurrentMapFileSize = GetCurrentMapFileSize(); -} - - -// =====[ PUBLIC ]===== - -// NOTE: These serialisation functions were made because the internal data layout of enum structs can change. -void TickDataToArray(ReplayTickData tickData, any result[RP_V2_TICK_DATA_BLOCKSIZE]) -{ - // NOTE: HAS to match ReplayTickData exactly! - result[0] = tickData.deltaFlags; - result[1] = tickData.deltaFlags2; - result[2] = tickData.vel[0]; - result[3] = tickData.vel[1]; - result[4] = tickData.vel[2]; - result[5] = tickData.mouse[0]; - result[6] = tickData.mouse[1]; - result[7] = tickData.origin[0]; - result[8] = tickData.origin[1]; - result[9] = tickData.origin[2]; - result[10] = tickData.angles[0]; - result[11] = tickData.angles[1]; - result[12] = tickData.angles[2]; - result[13] = tickData.velocity[0]; - result[14] = tickData.velocity[1]; - result[15] = tickData.velocity[2]; - result[16] = tickData.flags; - result[17] = tickData.packetsPerSecond; - result[18] = tickData.laggedMovementValue; - result[19] = tickData.buttonsForced; -} - -void TickDataFromArray(any array[RP_V2_TICK_DATA_BLOCKSIZE], ReplayTickData result) -{ - // NOTE: HAS to match ReplayTickData exactly! - result.deltaFlags = array[0]; - result.deltaFlags2 = array[1]; - result.vel[0] = array[2]; - result.vel[1] = array[3]; - result.vel[2] = array[4]; - result.mouse[0] = array[5]; - result.mouse[1] = array[6]; - result.origin[0] = array[7]; - result.origin[1] = array[8]; - result.origin[2] = array[9]; - result.angles[0] = array[10]; - result.angles[1] = array[11]; - result.angles[2] = array[12]; - result.velocity[0] = array[13]; - result.velocity[1] = array[14]; - result.velocity[2] = array[15]; - result.flags = array[16]; - result.packetsPerSecond = array[17]; - result.laggedMovementValue = array[18]; - result.buttonsForced = array[19]; -} diff --git a/source/sourcemod/scripting/gokz-slayonend.sp b/source/sourcemod/scripting/gokz-slayonend.sp deleted file mode 100644 index c83c4e6..0000000 --- a/source/sourcemod/scripting/gokz-slayonend.sp +++ /dev/null @@ -1,190 +0,0 @@ -#include - -#include -#include - -#undef REQUIRE_EXTENSIONS -#undef REQUIRE_PLUGIN -#include - -#pragma newdecls required -#pragma semicolon 1 - - - -public Plugin myinfo = -{ - name = "GOKZ Slay On End", - author = "DanZay", - description = "Adds option to slay the player upon ending their timer", - version = GOKZ_VERSION, - url = GOKZ_SOURCE_URL -}; - -#define UPDATER_URL GOKZ_UPDATER_BASE_URL..."gokz-slayonend.txt" - -TopMenu gTM_Options; -TopMenuObject gTMO_CatGeneral; -TopMenuObject gTMO_ItemSlayOnEnd; - - - -// =====[ PLUGIN EVENTS ]===== - -public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) -{ - RegPluginLibrary("gokz-slayonend"); - return APLRes_Success; -} - -public void OnPluginStart() -{ - LoadTranslations("gokz-common.phrases"); - LoadTranslations("gokz-slayonend.phrases"); -} - -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_OnTimerEnd_Post(int client, int course, float time, int teleportsUsed) -{ - OnTimerEnd_SlayOnEnd(client); -} - -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); -} - - - -// =====[ SLAY ON END ]===== - -void OnTimerEnd_SlayOnEnd(int client) -{ - if (GOKZ_GetOption(client, SLAYONEND_OPTION_NAME) == SlayOnEnd_Enabled) - { - CreateTimer(3.0, Timer_SlayPlayer, GetClientUserId(client)); - } -} - -public Action Timer_SlayPlayer(Handle timer, int userid) -{ - int client = GetClientOfUserId(userid); - if (IsValidClient(client)) - { - ForcePlayerSuicide(client); - } - return Plugin_Continue; -} - - - -// =====[ OPTIONS ]===== - -void OnOptionsMenuReady_Options() -{ - RegisterOption(); -} - -void RegisterOption() -{ - GOKZ_RegisterOption(SLAYONEND_OPTION_NAME, SLAYONEND_OPTION_DESCRIPTION, - OptionType_Int, SlayOnEnd_Disabled, 0, SLAYONEND_COUNT - 1); -} - -void OnOptionChanged_Options(int client, const char[] option, any newValue) -{ - if (StrEqual(option, SLAYONEND_OPTION_NAME)) - { - switch (newValue) - { - case SlayOnEnd_Disabled: - { - GOKZ_PrintToChat(client, true, "%t", "Option - Slay On End - Disable"); - } - case SlayOnEnd_Enabled: - { - GOKZ_PrintToChat(client, true, "%t", "Option - Slay On End - 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_ItemSlayOnEnd = gTM_Options.AddItem(SLAYONEND_OPTION_NAME, TopMenuHandler_SlayOnEnd, gTMO_CatGeneral); -} - -public void TopMenuHandler_SlayOnEnd(TopMenu topmenu, TopMenuAction action, TopMenuObject topobj_id, int param, char[] buffer, int maxlength) -{ - if (topobj_id != gTMO_ItemSlayOnEnd) - { - return; - } - - if (action == TopMenuAction_DisplayOption) - { - if (GOKZ_GetOption(param, SLAYONEND_OPTION_NAME) == SlayOnEnd_Disabled) - { - FormatEx(buffer, maxlength, "%T - %T", - "Options Menu - Slay On End", param, - "Options Menu - Disabled", param); - } - else - { - FormatEx(buffer, maxlength, "%T - %T", - "Options Menu - Slay On End", param, - "Options Menu - Enabled", param); - } - } - else if (action == TopMenuAction_SelectOption) - { - GOKZ_CycleOption(param, SLAYONEND_OPTION_NAME); - gTM_Options.Display(param, TopMenuPosition_LastCategory); - } -} \ No newline at end of file diff --git a/source/sourcemod/scripting/gokz-spec.sp b/source/sourcemod/scripting/gokz-spec.sp deleted file mode 100644 index 29f842f..0000000 --- a/source/sourcemod/scripting/gokz-spec.sp +++ /dev/null @@ -1,323 +0,0 @@ -#include - -#include - -#include - -#undef REQUIRE_EXTENSIONS -#undef REQUIRE_PLUGIN -#include - -#pragma newdecls required -#pragma semicolon 1 - - - -public Plugin myinfo = -{ - name = "GOKZ Spectate Menu", - author = "DanZay", - description = "Provides easy ways to spectate players", - version = GOKZ_VERSION, - url = GOKZ_SOURCE_URL -}; - -#define UPDATER_URL GOKZ_UPDATER_BASE_URL..."gokz-spec.txt" - - - -// =====[ PLUGIN EVENTS ]===== - -public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) -{ - RegPluginLibrary("gokz-spec"); - return APLRes_Success; -} - -public void OnPluginStart() -{ - LoadTranslations("common.phrases"); - LoadTranslations("gokz-common.phrases"); - LoadTranslations("gokz-spec.phrases"); - - RegisterCommands(); -} - -public void OnAllPluginsLoaded() -{ - if (LibraryExists("updater")) - { - Updater_AddPlugin(UPDATER_URL); - } -} - -public void OnLibraryAdded(const char[] name) -{ - if (StrEqual(name, "updater")) - { - Updater_AddPlugin(UPDATER_URL); - } -} - - - -// =====[ SPEC MENU ]===== - -int DisplaySpecMenu(int client, bool useFilter = false, char[] filter = "") -{ - Menu menu = new Menu(MenuHandler_Spec); - menu.SetTitle("%T", "Spec Menu - Title", client); - int menuItems = SpecMenuAddItems(client, menu, useFilter, filter); - if (menuItems == 0 || menuItems == 1) - { - delete menu; - } - else - { - menu.Display(client, MENU_TIME_FOREVER); - } - return menuItems; -} - -bool Spectate(int client) -{ - if (!CanSpectate(client)) - { - return false; - } - - GOKZ_JoinTeam(client, CS_TEAM_SPECTATOR); - - // Put player in free look mode and apply according movetype - SetEntProp(client, Prop_Send, "m_iObserverMode", 6); - SetEntityMoveType(client, MOVETYPE_OBSERVER); - return true; -} - -// Returns whether change to spectating the target was successful -bool SpectatePlayer(int client, int target, bool printMessage = true) -{ - if (!CanSpectate(client)) - { - return false; - } - - if (target == client) - { - Spectate(client); - return true; - } - else if (!IsPlayerAlive(target)) - { - if (printMessage) - { - GOKZ_PrintToChat(client, true, "%t", "Spectate Failure (Dead)"); - GOKZ_PlayErrorSound(client); - } - return false; - } - - GOKZ_JoinTeam(client, CS_TEAM_SPECTATOR); - SetEntProp(client, Prop_Send, "m_iObserverMode", 4); - SetEntPropEnt(client, Prop_Send, "m_hObserverTarget", target); - - return true; -} - -bool CanSpectate(int client) -{ - return !IsPlayerAlive(client) || GOKZ_GetPaused(client) || GOKZ_GetCanPause(client); -} - -public int MenuHandler_Spec(Menu menu, MenuAction action, int param1, int param2) -{ - if (action == MenuAction_Select) - { - char info[16]; - menu.GetItem(param2, info, sizeof(info)); - int target = GetClientOfUserId(StringToInt(info)); - - if (!IsValidClient(target)) - { - GOKZ_PrintToChat(param1, true, "%t", "Player No Longer Valid"); - GOKZ_PlayErrorSound(param1); - DisplaySpecMenu(param1); - } - else if (!SpectatePlayer(param1, target)) - { - DisplaySpecMenu(param1); - } - } - else if (action == MenuAction_End) - { - delete menu; - } - return 0; -} - -// Returns number of items added to the menu -int SpecMenuAddItems(int client, Menu menu, bool useFilter, char[] filter) -{ - char display[MAX_NAME_LENGTH + 4]; - int targetCount = 0; - int latestResult; - - for (int i = 1; i <= MaxClients; i++) - { - if (!IsClientInGame(i) || !IsPlayerAlive(i) || i == client) - { - continue; - } - if (useFilter) - { - FormatEx(display, sizeof(display), "%N", i); - if (StrContains(display, filter, false) != -1) - { - if (IsFakeClient(i)) - { - FormatEx(display, sizeof(display), "BOT %N", i); - } - } - else // If it doesn't fit the filter, move on - { - continue; - } - } - else - { - if (IsFakeClient(i)) - { - FormatEx(display, sizeof(display), "BOT %N", i); - } - else - { - FormatEx(display, sizeof(display), "%N", i); - } - } - latestResult = i; - menu.AddItem(IntToStringEx(GetClientUserId(i)), display, ITEMDRAW_DEFAULT); - targetCount++; - } - // The only spectate-able player is the latest result, this happens when the player issuing the command also fits in the filter - if (targetCount == 1) - { - SpectatePlayer(client, latestResult); - } - - return targetCount; -} - - - -// =====[ COMMANDS ]===== - -void RegisterCommands() -{ - RegConsoleCmd("sm_spec", CommandSpec, "[KZ] Spectate another player. Usage: !spec "); - RegConsoleCmd("sm_specs", CommandSpecs, "[KZ] List currently spectating players in chat."); - RegConsoleCmd("sm_speclist", CommandSpecs, "[KZ] List currently spectating players in chat."); -} - -public Action CommandSpec(int client, int args) -{ - // If no arguments, display the spec menu - if (args < 1) - { - if (DisplaySpecMenu(client) == 0) - { - // No targets, so just join spec - Spectate(client); - } - } - // Otherwise try to spectate the player - else - { - char specifiedPlayer[MAX_NAME_LENGTH]; - GetCmdArg(1, specifiedPlayer, sizeof(specifiedPlayer)); - - char targetName[MAX_TARGET_LENGTH]; - int targetList[1], targetCount; - bool tnIsML; - int flags = COMMAND_FILTER_NO_MULTI | COMMAND_FILTER_NO_IMMUNITY | COMMAND_FILTER_ALIVE; - - if ((targetCount = ProcessTargetString( - specifiedPlayer, - client, - targetList, - 1, - flags, - targetName, - sizeof(targetName), - tnIsML)) == 1) - { - SpectatePlayer(client, targetList[0]); - } - else if (targetCount == COMMAND_TARGET_AMBIGUOUS) - { - DisplaySpecMenu(client, true, specifiedPlayer); - } - else - { - ReplyToTargetError(client, targetCount); - } - - } - return Plugin_Handled; -} - -public Action CommandSpecs(int client, int args) -{ - int specs = 0; - char specNames[1024]; - - int target = IsPlayerAlive(client) ? client : GetObserverTarget(client); - int targetSpecs = 0; - char targetSpecNames[1024]; - - for (int i = 1; i <= MaxClients; i++) - { - if (IsClientInGame(i) && !IsFakeClient(i) && IsSpectating(i)) - { - specs++; - if (specs == 1) - { - FormatEx(specNames, sizeof(specNames), "{lime}%N", i); - } - else - { - Format(specNames, sizeof(specNames), "%s{grey}, {lime}%N", specNames, i); - } - - if (target != -1 && GetObserverTarget(i) == target) - { - targetSpecs++; - if (targetSpecs == 1) - { - FormatEx(targetSpecNames, sizeof(targetSpecNames), "{lime}%N", i); - } - else - { - Format(targetSpecNames, sizeof(targetSpecNames), "%s{grey}, {lime}%N", targetSpecNames, i); - } - } - } - } - - if (specs == 0) - { - GOKZ_PrintToChat(client, true, "%t", "Spectator List (None)"); - } - else - { - GOKZ_PrintToChat(client, true, "%t", "Spectator List", specs, specNames); - if (targetSpecs == 0) - { - GOKZ_PrintToChat(client, false, "%t", "Target Spectator List (None)", target); - } - else - { - GOKZ_PrintToChat(client, false, "%t", "Target Spectator List", target, targetSpecs, targetSpecNames); - } - } - return Plugin_Handled; -} \ No newline at end of file diff --git a/source/sourcemod/scripting/gokz-tips.sp b/source/sourcemod/scripting/gokz-tips.sp deleted file mode 100644 index 8a84b9e..0000000 --- a/source/sourcemod/scripting/gokz-tips.sp +++ /dev/null @@ -1,357 +0,0 @@ -#include - -#include -#include - -#include - -#undef REQUIRE_EXTENSIONS -#undef REQUIRE_PLUGIN -#include - -#include - -#pragma newdecls required -#pragma semicolon 1 - - - -public Plugin myinfo = -{ - name = "GOKZ Tips", - author = "DanZay", - description = "Prints tips to chat periodically based on loaded plugins", - version = GOKZ_VERSION, - url = GOKZ_SOURCE_URL -}; - -#define UPDATER_URL GOKZ_UPDATER_BASE_URL..."gokz-tips.txt" - -bool gC_PluginsWithTipsLoaded[TIPS_PLUGINS_COUNT]; -ArrayList g_TipPhrases; -int gI_CurrentTip; -Handle gH_TipTimer; -TopMenu gTM_Options; -TopMenuObject gTMO_CatGeneral; -TopMenuObject gTMO_ItemTips; -ConVar gCV_gokz_tips_interval; - - - -// =====[ PLUGIN EVENTS ]===== - -public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) -{ - RegPluginLibrary("gokz-tips"); - return APLRes_Success; -} - -public void OnPluginStart() -{ - LoadTranslations("gokz-common.phrases"); - LoadTranslations("gokz-tips.phrases"); - LoadTranslations("gokz-tips-tips.phrases"); - LoadTranslations("gokz-tips-core.phrases"); - - // Load translations of tips for other GOKZ plugins - char translation[PLATFORM_MAX_PATH]; - for (int i = 0; i < TIPS_PLUGINS_COUNT; i++) - { - FormatEx(translation, sizeof(translation), "gokz-tips-%s.phrases", gC_PluginsWithTips[i]); - LoadTranslations(translation); - } - - CreateConVars(); - RegisterCommands(); - CreateTipsTimer(); -} - -public void OnAllPluginsLoaded() -{ - if (LibraryExists("updater")) - { - Updater_AddPlugin(UPDATER_URL); - } - - char gokzPlugin[PLATFORM_MAX_PATH]; - for (int i = 0; i < TIPS_PLUGINS_COUNT; i++) - { - FormatEx(gokzPlugin, sizeof(gokzPlugin), "gokz-%s", gC_PluginsWithTips[i]); - gC_PluginsWithTipsLoaded[i] = LibraryExists(gokzPlugin); - } - - 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); - } - - char gokzPlugin[PLATFORM_MAX_PATH]; - for (int i = 0; i < TIPS_PLUGINS_COUNT; i++) - { - FormatEx(gokzPlugin, sizeof(gokzPlugin), "gokz-%s", gC_PluginsWithTips[i]); - gC_PluginsWithTipsLoaded[i] = gC_PluginsWithTipsLoaded[i] || StrEqual(name, gokzPlugin); - } -} - -public void OnLibraryRemoved(const char[] name) -{ - char gokzPlugin[PLATFORM_MAX_PATH]; - for (int i = 0; i < TIPS_PLUGINS_COUNT; i++) - { - FormatEx(gokzPlugin, sizeof(gokzPlugin), "gokz-%s", gC_PluginsWithTips[i]); - gC_PluginsWithTipsLoaded[i] = gC_PluginsWithTipsLoaded[i] && !StrEqual(name, gokzPlugin); - } -} - - - -// =====[ CLIENT EVENTS ]===== - -public void GOKZ_OnOptionChanged(int client, const char[] option, any newValue) -{ - OnOptionChanged_Options(client, option, newValue); -} - - - -// =====[ OTHER EVENTS ]===== - -public void OnMapStart() -{ - LoadTipPhrases(); -} - -public void GOKZ_OnOptionsMenuReady(TopMenu topMenu) -{ - OnOptionsMenuReady_Options(); - OnOptionsMenuReady_OptionsMenu(topMenu); -} - - - -// =====[ CONVARS ]===== - -void CreateConVars() -{ - AutoExecConfig_SetFile("gokz-tips", "sourcemod/gokz"); - AutoExecConfig_SetCreateFile(true); - - gCV_gokz_tips_interval = AutoExecConfig_CreateConVar("gokz_tips_interval", "75", "How often GOKZ tips are printed to chat in seconds.", _, true, 1.0, false); - gCV_gokz_tips_interval.AddChangeHook(OnConVarChanged); - - AutoExecConfig_ExecuteFile(); - AutoExecConfig_CleanFile(); -} - -public void OnConVarChanged(ConVar convar, const char[] oldValue, const char[] newValue) -{ - if (convar == gCV_gokz_tips_interval) - { - CreateTipsTimer(); - } -} - - - -// =====[ TIPS ]===== - -void LoadTipPhrases() -{ - if (g_TipPhrases == null) - { - g_TipPhrases = new ArrayList(64, 0); - } - else - { - g_TipPhrases.Clear(); - } - - char tipsPath[PLATFORM_MAX_PATH]; - - BuildPath(Path_SM, tipsPath, sizeof(tipsPath), "translations/%s", TIPS_TIPS); - LoadTipPhrasesFromFile(tipsPath); - - BuildPath(Path_SM, tipsPath, sizeof(tipsPath), "translations/%s", TIPS_CORE); - LoadTipPhrasesFromFile(tipsPath); - - // Load tips for other loaded GOKZ plugins - for (int i = 0; i < TIPS_PLUGINS_COUNT; i++) - { - if (gC_PluginsWithTipsLoaded[i]) - { - BuildPath(Path_SM, tipsPath, sizeof(tipsPath), "translations/gokz-tips-%s.phrases.txt", gC_PluginsWithTips[i]); - LoadTipPhrasesFromFile(tipsPath); - } - } - - ShuffleTipPhrases(); -} - -void LoadTipPhrasesFromFile(const char[] filePath) -{ - KeyValues kv = new KeyValues("Phrases"); - if (!kv.ImportFromFile(filePath)) - { - SetFailState("Failed to load file: \"%s\".", filePath); - } - - char phraseName[64]; - kv.GotoFirstSubKey(true); - do - { - kv.GetSectionName(phraseName, sizeof(phraseName)); - g_TipPhrases.PushString(phraseName); - } while (kv.GotoNextKey(true)); - - delete kv; -} - -void ShuffleTipPhrases() -{ - for (int i = g_TipPhrases.Length - 1; i >= 1; i--) - { - int j = GetRandomInt(0, i); - char tempStringI[64]; - g_TipPhrases.GetString(i, tempStringI, sizeof(tempStringI)); - char tempStringJ[64]; - g_TipPhrases.GetString(j, tempStringJ, sizeof(tempStringJ)); - g_TipPhrases.SetString(i, tempStringJ); - g_TipPhrases.SetString(j, tempStringI); - } -} - -void CreateTipsTimer() -{ - if (gH_TipTimer != null) - { - delete gH_TipTimer; - } - gH_TipTimer = CreateTimer(gCV_gokz_tips_interval.FloatValue, Timer_PrintTip, _, TIMER_REPEAT); -} - -public Action Timer_PrintTip(Handle timer) -{ - char tip[256]; - g_TipPhrases.GetString(gI_CurrentTip, tip, sizeof(tip)); - - for (int client = 1; client <= MaxClients; client++) - { - KZPlayer player = KZPlayer(client); - if (player.InGame && player.Tips != Tips_Disabled) - { - GOKZ_PrintToChat(client, true, "%t", tip); - } - } - - gI_CurrentTip = NextIndex(gI_CurrentTip, g_TipPhrases.Length); - return Plugin_Continue; -} - - - -// =====[ OPTIONS ]===== - -void OnOptionsMenuReady_Options() -{ - RegisterOption(); -} - -void RegisterOption() -{ - GOKZ_RegisterOption(TIPS_OPTION_NAME, TIPS_OPTION_DESCRIPTION, - OptionType_Int, Tips_Enabled, 0, TIPS_COUNT - 1); -} - -void OnOptionChanged_Options(int client, const char[] option, any newValue) -{ - if (StrEqual(option, TIPS_OPTION_NAME)) - { - switch (newValue) - { - case Tips_Disabled: - { - GOKZ_PrintToChat(client, true, "%t", "Option - Tips - Disable"); - } - case Tips_Enabled: - { - GOKZ_PrintToChat(client, true, "%t", "Option - Tips - 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_ItemTips = gTM_Options.AddItem(TIPS_OPTION_NAME, TopMenuHandler_Tips, gTMO_CatGeneral); -} - -public void TopMenuHandler_Tips(TopMenu topmenu, TopMenuAction action, TopMenuObject topobj_id, int param, char[] buffer, int maxlength) -{ - if (topobj_id != gTMO_ItemTips) - { - return; - } - - if (action == TopMenuAction_DisplayOption) - { - if (GOKZ_GetOption(param, TIPS_OPTION_NAME) == Tips_Disabled) - { - FormatEx(buffer, maxlength, "%T - %T", - "Options Menu - Tips", param, - "Options Menu - Disabled", param); - } - else - { - FormatEx(buffer, maxlength, "%T - %T", - "Options Menu - Tips", param, - "Options Menu - Enabled", param); - } - } - else if (action == TopMenuAction_SelectOption) - { - GOKZ_CycleOption(param, TIPS_OPTION_NAME); - gTM_Options.Display(param, TopMenuPosition_LastCategory); - } -} - - - -// =====[ COMMANDS ]===== - -void RegisterCommands() -{ - RegConsoleCmd("sm_tips", CommandToggleTips, "[KZ] Toggle seeing help and tips."); -} - -public Action CommandToggleTips(int client, int args) -{ - if (GOKZ_GetOption(client, TIPS_OPTION_NAME) == Tips_Disabled) - { - GOKZ_SetOption(client, TIPS_OPTION_NAME, Tips_Enabled); - } - else - { - GOKZ_SetOption(client, TIPS_OPTION_NAME, Tips_Disabled); - } - return Plugin_Handled; -} \ No newline at end of file diff --git a/source/sourcemod/scripting/include/dhooks.inc b/source/sourcemod/scripting/include/dhooks.inc index 76ff8c4..5354b89 100644 --- a/source/sourcemod/scripting/include/dhooks.inc +++ b/source/sourcemod/scripting/include/dhooks.inc @@ -1,35 +1,3 @@ -/** - * vim: set ts=4 sw=4 tw=99 noet : - * ============================================================================= - * SourceMod (C)2021 AlliedModders LLC. All rights reserved. - * ============================================================================= - * - * This file is part of the SourceMod/SourcePawn SDK. - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, version 3.0, as published by the - * Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - * - * As a special exception, AlliedModders LLC gives you permission to link the - * code of this program (as well as its derivative works) to "Half-Life 2," the - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software - * by the Valve Corporation. You must obey the GNU General Public License in - * all respects for all other code used. Additionally, AlliedModders LLC grants - * this exception to all derivative works. AlliedModders LLC defines further - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), - * or . - * - * Version: $Id$ - */ - #if defined _dhooks_included #endinput #endif @@ -70,8 +38,8 @@ enum ReturnType ReturnType_Int, ReturnType_Bool, ReturnType_Float, - ReturnType_String, // Note this is a string_t - ReturnType_StringPtr, // Note this is a string_t * + ReturnType_String, //Note this is a string_t + ReturnType_StringPtr, //Note this is a string_t * ReturnType_CharPtr, ReturnType_Vector, ReturnType_VectorPtr, @@ -85,8 +53,8 @@ enum HookParamType HookParamType_Int, HookParamType_Bool, HookParamType_Float, - HookParamType_String, // Note this is a string_t - HookParamType_StringPtr, // Note this is a string_t * + HookParamType_String, //Note this is a string_t + HookParamType_StringPtr, //Note this is a string_t * HookParamType_CharPtr, HookParamType_VectorPtr, HookParamType_CBaseEntity, @@ -119,34 +87,34 @@ enum CallingConvention enum HookMode { - Hook_Pre, /**< Callback will be executed BEFORE the original function. */ - Hook_Post /**< Callback will be executed AFTER the original function. */ + Hook_Pre, // Callback will be executed BEFORE the original function. + Hook_Post // Callback will be executed AFTER the original function. }; enum MRESReturn { - MRES_ChangedHandled = -2, /**< Use changed values and return MRES_Handled */ - MRES_ChangedOverride, /**< Use changed values and return MRES_Override */ - MRES_Ignored, /**< plugin didn't take any action */ - MRES_Handled, /**< plugin did something, but real function should still be called */ - MRES_Override, /**< call real function, but use my return value */ - MRES_Supercede /**< skip real function; use my return value */ + MRES_ChangedHandled = -2, // Use changed values and return MRES_Handled + MRES_ChangedOverride, // Use changed values and return MRES_Override + MRES_Ignored, // plugin didn't take any action + MRES_Handled, // plugin did something, but real function should still be called + MRES_Override, // call real function, but use my return value + MRES_Supercede // skip real function; use my return value }; enum DHookPassFlag { - DHookPass_ByVal = (1<<0), /**< Passing by value */ - DHookPass_ByRef = (1<<1), /**< Passing by reference */ - DHookPass_ODTOR = (1<<2), /**< Object has a destructor */ - DHookPass_OCTOR = (1<<3), /**< Object has a constructor */ - DHookPass_OASSIGNOP = (1<<4), /**< Object has an assignment operator */ + DHookPass_ByVal = (1<<0), /**< Passing by value */ + DHookPass_ByRef = (1<<1), /**< Passing by reference */ + DHookPass_ODTOR = (1<<2), /**< Object has a destructor */ + DHookPass_OCTOR = (1<<3), /**< Object has a constructor */ + DHookPass_OASSIGNOP = (1<<4), /**< Object has an assignment operator */ }; enum DHookRegister { // Don't change the register and use the default for the calling convention. DHookRegister_Default, - + // 8-bit general purpose registers DHookRegister_AL, DHookRegister_CL, @@ -156,7 +124,7 @@ enum DHookRegister DHookRegister_CH, DHookRegister_DH, DHookRegister_BH, - + // 32-bit general purpose registers DHookRegister_EAX, DHookRegister_ECX, @@ -166,7 +134,7 @@ enum DHookRegister DHookRegister_EBP, DHookRegister_ESI, DHookRegister_EDI, - + // 128-bit XMM registers DHookRegister_XMM0, DHookRegister_XMM1, @@ -176,17 +144,17 @@ enum DHookRegister DHookRegister_XMM5, DHookRegister_XMM6, DHookRegister_XMM7, - + // 80-bit FPU registers DHookRegister_ST0 }; typeset ListenCB { - // Deleted + //Deleted function void (int entity); - - // Created + + //Created function void (int entity, const char[] classname); }; @@ -194,47 +162,46 @@ typeset DHookRemovalCB { function void (int hookid); }; - typeset DHookCallback { - // Function Example: void Ham::Test() with this pointer ignore + //Function Example: void Ham::Test() with this pointer ignore function MRESReturn (); - - // Function Example: void Ham::Test() with this pointer passed + + //Function Example: void Ham::Test() with this pointer passed function MRESReturn (int pThis); - - // Function Example: void Ham::Test(int cake) with this pointer ignore + + //Function Example: void Ham::Test(int cake) with this pointer ignore function MRESReturn (DHookParam hParams); - - // Function Example: void Ham::Test(int cake) with this pointer passed + + //Function Example: void Ham::Test(int cake) with this pointer passed function MRESReturn (int pThis, DHookParam hParams); - - // Function Example: int Ham::Test() with this pointer ignore + + //Function Example: int Ham::Test() with this pointer ignore function MRESReturn (DHookReturn hReturn); - - // Function Example: int Ham::Test() with this pointer passed + + //Function Example: int Ham::Test() with this pointer passed function MRESReturn (int pThis, DHookReturn hReturn); - - // Function Example: int Ham::Test(int cake) with this pointer ignore + + //Function Example: int Ham::Test(int cake) with this pointer ignore function MRESReturn (DHookReturn hReturn, DHookParam hParams); - - // Function Example: int Ham::Test(int cake) with this pointer passed + + //Function Example: int Ham::Test(int cake) with this pointer passed function MRESReturn (int pThis, DHookReturn hReturn, DHookParam hParams); - - // Address NOW - - // Function Example: void Ham::Test() with this pointer passed + + //Address NOW + + //Function Example: void Ham::Test() with this pointer passed function MRESReturn (Address pThis); - - // Function Example: void Ham::Test(int cake) with this pointer passed + + //Function Example: void Ham::Test(int cake) with this pointer passed function MRESReturn (Address pThis, DHookParam hParams); - - // Function Example: int Ham::Test() with this pointer passed + + //Function Example: int Ham::Test() with this pointer passed function MRESReturn (Address pThis, DHookReturn hReturn); - - // Function Example: int Ham::Test(int cake) with this pointer passed + + //Function Example: int Ham::Test(int cake) with this pointer passed function MRESReturn (Address pThis, DHookReturn hReturn, DHookParam hParams); - + }; // Represents the parameters of the hooked function. @@ -266,15 +233,13 @@ methodmap DHookParam < Handle // @param num Parameter number to get, starting at 1. // @param buffer String buffer to store result. // @param size Buffer size. - // + // // @error Invalid handle, invalid param number or invalid param type. public native void GetString(int num, char[] buffer, int size); // Set the value of a parameter. // Use only for: int, entity, edict, bool or float parameter types. // - // An entity parameter type can be set to NULL using INVALID_ENT_REFERENCE (-1). - // // The changes are only applied when MRES_ChangedHandled or MRES_ChangedOverride // is returned in the callback. // @@ -371,18 +336,9 @@ methodmap DHookParam < Handle // // @param num Parameter number to check, starting at 1. // - // @return true if null, false otherwise. + // @return True if null, false otherwise. // @error Non-pointer parameter. public native bool IsNull(int num); - - // Get param address (Use only for ptr param types) - // - // @param num Param number to get. (Example if the function has 2 params and you need the value - // of the first param num would be 1.) - // - // @return Address of the parameter. - // @error Invalid handle. Invalid param number. Invalid param type. - public native Address GetAddress(int num); }; @@ -392,8 +348,6 @@ methodmap DHookReturn < Handle // Retrieves or sets the return value. // Use only for: int, entity, edict, bool or float return types. // - // An entity return type can be set to NULL using INVALID_ENT_REFERENCE (-1). - // // The return value is only readable in a post hook. // The value is only applied when MRES_Override or MRES_Supercede is returned // in the callback. @@ -455,7 +409,7 @@ methodmap DHookSetup < Handle // @param source Whether to look in Offsets, Signatures, or Addresses. // @param name Name of the property to find. // - // @return true on success, false if nothing was found. + // @return True on success, false if nothing was found. // @error Invalid setup or gamedata handle. public native bool SetFromConf(Handle gameconf, SDKFuncConfSource source, const char[] name); @@ -465,7 +419,7 @@ methodmap DHookSetup < Handle // @param size Used for Objects (not Object ptr) to define the size of the object. // @param flag Used to change the pass type (ignored by detours). // @param custom_register The register this argument is passed in instead of the stack (ignored by vhooks). - // + // // @error Invalid setup handle or too many params added (request upping the max in thread). public native void AddParam(HookParamType type, int size=-1, DHookPassFlag flag=DHookPass_ByVal, DHookRegister custom_register=DHookRegister_Default); }; @@ -473,7 +427,7 @@ methodmap DHookSetup < Handle // A DynamicHook allows to hook a virtual function on any C++ object. // Currently CBaseEntity and CGameRules have a convenience API for easy entity hooking, // but it's possible to provide a raw this-pointer to hook any object in memory too. -// +// // Internally this intercepts function calls by replacing the function pointer // in the virtual table of the object with our own function. methodmap DynamicHook < DHookSetup @@ -484,7 +438,7 @@ methodmap DynamicHook < DHookSetup // @param hooktype Type of hook. // @param returntype Type of return value. // @param thistype Type of this pointer or ignore (ignore can be used if not needed). - // + // // @error Failed to create hook setup handle or invalid callback function. public native DynamicHook(int offset, HookType hooktype, ReturnType returntype, ThisPointerType thistype); @@ -506,14 +460,14 @@ methodmap DynamicHook < DHookSetup // If you need to read the return value of the function, choose a post hook. // // @param mode The desired hook mode - pre or post. - // A pre hook calls your callback BEFORE the original function is called. + // A pre hook calls your callback BEFORE the original function is called. // You can access the parameters, set the return value, and skip the original function. // A post hook calls your callback AFTER the original function executed. // You can access the parameters and get/set the return value. // @param entity Entity index to hook on. // @param callback Callback function. // @param removalcb Optional callback for when the hook is removed. - // + // // @return A hookid on success, INVALID_HOOK_ID otherwise. // @error Invalid setup handle, invalid address, invalid hook type or invalid callback. public native int HookEntity(HookMode mode, int entity, DHookCallback callback, DHookRemovalCB removalcb=INVALID_FUNCTION); @@ -524,13 +478,13 @@ methodmap DynamicHook < DHookSetup // If you need to read the return value of the function, choose a post hook. // // @param mode The desired hook mode - pre or post. - // A pre hook calls your callback BEFORE the original function is called. + // A pre hook calls your callback BEFORE the original function is called. // You can access the parameters, set the return value, and skip the original function. // A post hook calls your callback AFTER the original function executed. // You can access the parameters and get/set the return value. // @param callback Callback function. // @param removalcb Optional callback for when the hook is removed. - // + // // @return A hookid on success, INVALID_HOOK_ID otherwise. // @error Invalid setup handle, invalid address, invalid hook type or invalid callback. public native int HookGamerules(HookMode mode, DHookCallback callback, DHookRemovalCB removalcb=INVALID_FUNCTION); @@ -539,22 +493,23 @@ methodmap DynamicHook < DHookSetup // If you need to read the return value of the function, choose a post hook. // // @param mode The desired hook mode - pre or post. - // A pre hook calls your callback BEFORE the original function is called. + // A pre hook calls your callback BEFORE the original function is called. // You can access the parameters, set the return value, and skip the original function. // A post hook calls your callback AFTER the original function executed. // You can access the parameters and get/set the return value. // @param addr This pointer address. // @param callback Callback function. - // + // // @return A hookid on success, INVALID_HOOK_ID otherwise. // @error Invalid setup handle, invalid address, invalid hook type or invalid callback. public native int HookRaw(HookMode mode, Address addr, DHookCallback callback); - // Remove hook by hook id. - // + // Remove hook by hook id: + // This will NOT fire the removal callback! + // // @param hookid Hook id to remove. - // - // @return true on success, false otherwise + // + // @return True on success, false otherwise public static native bool RemoveHook(int hookid); }; @@ -566,7 +521,7 @@ methodmap DynamicHook < DHookSetup // Internally this works by replacing the first instructions of the function // with a jump to our own code. This means that the signature used to find // the function address in the first place might not match anymore after a detour. -// If you need to detour the same function in different plugins make sure to +// If you need to detour the same function in different plugins make sure to // wildcard \x2a the first 6 bytes of the signature to accommodate for the patched // jump introduced by the detour. methodmap DynamicDetour < DHookSetup @@ -599,13 +554,13 @@ methodmap DynamicDetour < DHookSetup // If you need to read the return value of the function, choose a post hook. // // @param mode The desired hook mode - pre or post. - // A pre hook calls your callback BEFORE the original function is called. + // A pre hook calls your callback BEFORE the original function is called. // You can access the parameters, set the return value, and skip the original function. // A post hook calls your callback AFTER the original function executed. // You can access the parameters and get/set the return value. // @param callback Callback function. // - // @return true if detour was enabled, false otherwise. + // @return True if detour was enabled, false otherwise. // @error Hook handle is not setup for a detour. public native bool Enable(HookMode mode, DHookCallback callback); @@ -614,405 +569,367 @@ methodmap DynamicDetour < DHookSetup // @param mode The hook mode to disable - pre or post. // @param callback Callback function. // - // @return true if detour was disabled, false otherwise. + // @return True if detour was disabled, false otherwise. // @error Hook handle is not setup for a detour or function is not detoured. public native bool Disable(HookMode mode, DHookCallback callback); }; -/** - * Adds an entity listener hook +/* Adds an entity listener hook * - * @param type Type of listener to add - * @param callback Callback to use - */ + * @param type Type of listener to add + * @param callback Callback to use + * + * @noreturn +*/ native void DHookAddEntityListener(ListenType type, ListenCB callback); -/** - * Removes an entity listener hook +/* Removes an entity listener hook * - * @param type Type of listener to remove - * @param callback Callback this listener was using + * @param type Type of listener to remove + * @param callback Callback this listener was using * - * @return true if one was removed, false otherwise - */ + * @return True if one was removed false otherwise. +*/ native bool DHookRemoveEntityListener(ListenType type, ListenCB callback); -/** - * Creates a hook - * - * @param offset vtable offset of function to hook - * @param hooktype Type of hook - * @param returntype Type of return value - * @param thistype Type of this pointer or ignore (ignore can be used if not needed) - * @param callback Optional callback function, if not set here must be set when hooking. +/* Creates a hook * - * @return Returns setup handle for the hook. - * @error Failed to create hook setup handle or invalid callback function. - */ + * @param offset vtable offset of function to hook + * @param hooktype Type of hook + * @param returntype Type of return value + * @param thistype Type of this pointer or ignore (ignore can be used if not needed) + * @param callback Optional callback function, if not set here must be set when hooking. + * + * @return Returns setup handle for the hook. + * @error Failed to create hook setup handle or invalid callback function. +*/ native DynamicHook DHookCreate(int offset, HookType hooktype, ReturnType returntype, ThisPointerType thistype, DHookCallback callback=INVALID_FUNCTION); /** * Creates a detour * - * @param funcaddr The address of the function to detour. - * Can be Address_Null if you want to load the address from gamedata using DHookSetFromConf. - * @param callConv Calling convention of the function. - * @param returnType Type of the return value. - * @param thisType Type of this pointer or ignore (ignore can be used if not needed) + * @param funcaddr The address of the function to detour. + * Can be Address_Null if you want to load the address from gamedata using DHookSetFromConf. + * @param callConv Calling convention of the function. + * @param returnType Type of the return value. + * @param thisType Type of this pointer or ignore (ignore can be used if not needed) * - * @return Setup handle for the detour. - * @error Failed to create detour setup handle. - */ + * @return Setup handle for the detour. + * @error Failed to create detour setup handle. + */ native DynamicDetour DHookCreateDetour(Address funcaddr, CallingConvention callConv, ReturnType returntype, ThisPointerType thisType); /** * Setup a detour or hook for a function as described in a "Functions" section in gamedata. * - * @param gameconf GameConfig handle - * @param name Name of the function in the gamedata to load. + * @param gameconf GameConfig handle + * @param name Name of the function in the gamedata to load. * - * @return Setup handle for the detour or INVALID_HANDLE if offset/signature/address wasn't found. - * @error Failed to create detour setup handle, invalid gamedata handle, invalid callback function or - * failed to find function in gamedata. + * @return Setup handle for the detour or INVALID_HANDLE if offset/signature/address wasn't found. + * @error Failed to create detour setup handle, invalid gamedata handle, invalid callback function or failed to find function in gamedata. */ native DHookSetup DHookCreateFromConf(Handle gameconf, const char[] name); /** * Load details for a vhook or detour from a gamedata file. * - * @param setup Hook setup handle to set the offset or address on. - * @param gameconf GameConfig handle - * @param source Whether to look in Offsets or Signatures. - * @param name Name of the property to find. + * @param setup Hook setup handle to set the offset or address on. + * @param gameconf GameConfig handle + * @param source Whether to look in Offsets or Signatures. + * @param name Name of the property to find. * - * @return true on success, false if nothing was found. - * @error Invalid setup or gamedata handle. + * @return True on success, false if nothing was found. + * @error Invalid setup or gamedata handle. */ native bool DHookSetFromConf(Handle setup, Handle gameconf, SDKFuncConfSource source, const char[] name); /** * Enable the detour of the function described in the hook setup handle. * - * @param setup Hook setup handle - * @param post true to make the hook a post hook. (If you need to change the return value or need the return - * value use a post hook! If you need to change params and return use a pre and post hook!) - * @param callback Callback function + * @param setup Hook setup handle + * @param post True to make the hook a post hook. (If you need to change the retunr value or need the return value use a post hook! If you need to change params and return use a pre and post hook!) + * @param callback Callback function * - * @return true if detour was enabled, false otherwise. - * @error Hook handle is not setup for a detour. + * @return True if detour was enabled, false otherwise. + * @error Hook handle is not setup for a detour. */ native bool DHookEnableDetour(Handle setup, bool post, DHookCallback callback); /** * Disable the detour of the function described in the hook setup handle. * - * @param setup Hook setup handle - * @param post true to disable a post hook. - * @param callback Callback function + * @param setup Hook setup handle + * @param post True to disable a post hook. + * @param callback Callback function * - * @return true if detour was disabled, false otherwise. - * @error Hook handle is not setup for a detour or function is not detoured. + * @return True if detour was disabled, false otherwise. + * @error Hook handle is not setup for a detour or function is not detoured. */ native bool DHookDisableDetour(Handle setup, bool post, DHookCallback callback); -/** - * Adds param to a hook setup - * - * @param setup Setup handle to add the param to. - * @param type Param type - * @param size Used for Objects (not Object ptr) to define the size of the object. - * @param flag Used to change the pass type. - * @param custom_register The register this argument is passed in instead of the stack. +/* Adds param to a hook setup * - * @error Invalid setup handle or too many params added (request upping the max in thread) - */ + * @param setup Setup handle to add the param to. + * @param type Param type + * @param size Used for Objects (not Object ptr) to define the size of the object. + * @param flag Used to change the pass type. + * @param custom_register The register this argument is passed in instead of the stack. + * + * @error Invalid setup handle or too many params added (request upping the max in thread) + * @noreturn +*/ native void DHookAddParam(Handle setup, HookParamType type, int size=-1, DHookPassFlag flag=DHookPass_ByVal, DHookRegister custom_register=DHookRegister_Default); -/** - * Hook entity - * - * @param setup Setup handle to use to add the hook. - * @param post true to make the hook a post hook. (If you need to change the return value or need the return - * value use a post hook! If you need to change params and return use a pre and post hook!) - * @param entity Entity index to hook on. - * @param removalcb Callback for when the hook is removed (Entity hooks are auto-removed on entity destroyed and - * will call this callback) - * @param callback Optional callback function, if not set here must be set when creating the hook. - * - * @return INVALID_HOOK_ID on fail a hookid on success - * @error Invalid setup handle, invalid address, invalid hook type or invalid callback. - */ +/* Hook entity + * + * @param setup Setup handle to use to add the hook. + * @param post True to make the hook a post hook. (If you need to change the return value or need the return value use a post hook! If you need to change params and return use a pre and post hook!) + * @param entity Entity index to hook on. + * @param removalcb Callback for when the hook is removed (Entity hooks are auto-removed on entity destroyed and will call this callback) + * @param callback Optional callback function, if not set here must be set when creating the hook. + * + * @error Invalid setup handle, invalid address, invalid hook type or invalid callback. + * @return INVALID_HOOK_ID on fail a hookid on success +*/ native int DHookEntity(Handle setup, bool post, int entity, DHookRemovalCB removalcb=INVALID_FUNCTION, DHookCallback callback=INVALID_FUNCTION); -/** - * Hook gamerules - * - * @param setup Setup handle to use to add the hook. - * @param post true to make the hook a post hook. (If you need to change the return value or need the return - * value use a post hook! If you need to change params and return use a pre and post hook!) - * @param removalcb Callback for when the hook is removed (Game rules hooks are auto-removed on map end and will - * call this callback) - * @param callback Optional callback function, if not set here must be set when creating the hook. - * - * @return INVALID_HOOK_ID on fail a hookid on success - * @error Invalid setup handle, invalid address, invalid hook type or invalid callback. - */ +/* Hook gamerules + * + * @param setup Setup handle to use to add the hook. + * @param post True to make the hook a post hook. (If you need to change the return value or need the return value use a post hook! If you need to change params and return use a pre and post hook!) + * @param removalcb Callback for when the hook is removed (Game rules hooks are auto-removed on map end and will call this callback) + * @param callback Optional callback function, if not set here must be set when creating the hook. + * + * @error Invalid setup handle, invalid address, invalid hook type or invalid callback. + * @return INVALID_HOOK_ID on fail a hookid on success +*/ native int DHookGamerules(Handle setup, bool post, DHookRemovalCB removalcb=INVALID_FUNCTION, DHookCallback callback=INVALID_FUNCTION); -/** - * Hook a raw pointer - * - * @param setup Setup handle to use to add the hook. - * @param post true to make the hook a post hook. (If you need to change the return value or need the return - * alue use a post hook! If you need to change params and return use a pre and post hook!) - * @param addr This pointer address. - * @param removalcb Callback for when the hook is removed (Entity hooks are auto-removed on entity destroyed and - * will call this callback) - * @param callback Optional callback function, if not set here must be set when creating the hook. - * - * @return INVALID_HOOK_ID on fail a hookid on success - * @error Invalid setup handle, invalid address, invalid hook type or invalid callback. - */ +/* Hook a raw pointer + * + * @param setup Setup handle to use to add the hook. + * @param post True to make the hook a post hook. (If you need to change the return value or need the return value use a post hook! If you need to change params and return use a pre and post hook!) + * @param addr This pointer address. + * @param removalcb Callback for when the hook is removed (Entity hooks are auto-removed on entity destroyed and will call this callback) + * @param callback Optional callback function, if not set here must be set when creating the hook. + * + * @error Invalid setup handle, invalid address, invalid hook type or invalid callback. + * @return INVALID_HOOK_ID on fail a hookid on success +*/ native int DHookRaw(Handle setup, bool post, Address addr, DHookRemovalCB removalcb=INVALID_FUNCTION, DHookCallback callback=INVALID_FUNCTION); -/** - * Remove hook by hook id - * - * @param hookid Hook id to remove - * - * @return true on success, false otherwise - */ +/* Remove hook by hook id + * + * @param hookid Hook id to remove + * + * @return true on success false otherwise + * @note This will not fire the removal callback! +*/ native bool DHookRemoveHookID(int hookid); -/** - * Get param value (Use only for: int, entity, edict, bool or float param types) - * - * @param hParams Handle to params structure - * @param num Param number to get. (Example if the function has 2 params and you need the value of the first - * param num would be 1. 0 Will return the number of params stored) - * - * @return value if num greater than 0. If 0 returns paramcount. - * @error Invalid handle. Invalid param number. Invalid param type. - */ +/* Get param value (Use only for: int, entity, bool or float param types) + * + * @param hParams Handle to params structure + * @param num Param number to get. (Example if the function has 2 params and you need the value of the first param num would be 1. 0 Will return the number of params stored) + * + * @error Invalid handle. Invalid param number. Invalid param type. + * @return value if num greater than 0. If 0 returns paramcount. +*/ native any DHookGetParam(Handle hParams, int num); -/** - * Get vector param value - * - * @param hParams Handle to params structure - * @param num Param number to get. (Example if the function has 2 params and you need the value of the first - * param num would be 1.) - * @param vec Vector buffer to store result. - * - * @error Invalid handle. Invalid param number. Invalid param type. - */ +/* Get vector param value + * + * @param hParams Handle to params structure + * @param num Param number to get. (Example if the function has 2 params and you need the value of the first param num would be 1.) + * @param vec Vector buffer to store result. + * + * @error Invalid handle. Invalid param number. Invalid param type. + * @noreturn +*/ native void DHookGetParamVector(Handle hParams, int num, float vec[3]); -/** - * Get string param value - * - * @param hParams Handle to params structure - * @param num Param number to get. (Example if the function has 2 params and you need the value of the first - * param num would be 1.) - * @param buffer String buffer to store result - * @param size Buffer size - * - * @error Invalid handle. Invalid param number. Invalid param type. - */ +/* Get string param value + * + * @param hParams Handle to params structure + * @param num Param number to get. (Example if the function has 2 params and you need the value of the first param num would be 1.) + * @param buffer String buffer to store result + * @param size Buffer size + * + * @error Invalid handle. Invalid param number. Invalid param type. + * @noreturn +*/ native void DHookGetParamString(Handle hParams, int num, char[] buffer, int size); -/** - * Set param value (Use only for: int, entity, edict, bool or float param types) - * - * An entity param type can be set to NULL using INVALID_ENT_REFERENCE (-1). - * - * @param hParams Handle to params structure - * @param num Param number to set (Example if the function has 2 params and you need to set the value of the - * first param num would be 1.) - * @param value Value to set it as (only pass int, bool, float or entity index) - * - * @error Invalid handle. Invalid param number. Invalid param type. - */ +/* Set param value (Use only for: int, entity, bool or float param types) + * + * @param hParams Handle to params structure + * @param num Param number to set (Example if the function has 2 params and you need to set the value of the first param num would be 1.) + * @param value Value to set it as (only pass int, bool, float or entity index) + * + * @error Invalid handle. Invalid param number. Invalid param type. + * @noreturn +*/ native void DHookSetParam(Handle hParams, int num, any value); -/** - * Set vector param value - * - * @param hParams Handle to params structure - * @param num Param number to set (Example if the function has 2 params and you need to set the value of the - * first param num would be 1.) - * @param vec Value to set vector as. - * - * @error Invalid handle. Invalid param number. Invalid param type. - */ +/* Set vector param value + * + * @param hParams Handle to params structure + * @param num Param number to set (Example if the function has 2 params and you need to set the value of the first param num would be 1.) + * @param vec Value to set vector as. + * + * @error Invalid handle. Invalid param number. Invalid param type. + * @noreturn +*/ native void DHookSetParamVector(Handle hParams, int num, float vec[3]); -/** - * Set string param value - * - * @param hParams Handle to params structure - * @param num Param number to set (Example if the function has 2 params and you need to set the value of the - * first param num would be 1.) - * @param value Value to set string as. - * - * @error Invalid handle. Invalid param number. Invalid param type. - */ +/* Set string param value + * + * @param hParams Handle to params structure + * @param num Param number to set (Example if the function has 2 params and you need to set the value of the first param num would be 1.) + * @param value Value to set string as. + * + * @error Invalid handle. Invalid param number. Invalid param type. + * @noreturn +*/ native void DHookSetParamString(Handle hParams, int num, char[] value); -/** - * Get return value (Use only for: int, entity, bool or float return types) - * - * @param hReturn Handle to return structure - * - * @error Invalid Handle, invalid type. - * @return Returns default value if prehook returns actual value if post hook. - */ +/* Get return value (Use only for: int, entity, bool or float return types) + * + * @param hReturn Handle to return structure + * + * @error Invalid Handle, invalid type. + * @return Returns default value if prehook returns actual value if post hook. +*/ native any DHookGetReturn(Handle hReturn); -/** - * Get return vector value - * - * @param hReturn Handle to return structure - * @param vec Vector buffer to store result in. (In pre hooks will be default value (0.0,0.0,0.0)) - * - * @error Invalid Handle, invalid type. - */ +/* Get return vector value + * + * @param hReturn Handle to return structure + * @param vec Vector buffer to store result in. (In pre hooks will be default value (0.0,0.0,0.0)) + * + * @error Invalid Handle, invalid type. + * @noreturn +*/ native void DHookGetReturnVector(Handle hReturn, float vec[3]); -/** - * Get return string value - * - * @param hReturn Handle to return structure - * @param buffer String buffer to store result in. (In pre hooks will be default value "") - * @param size String buffer size - * - * @error Invalid Handle, invalid type. - */ +/* Get return string value + * + * @param hReturn Handle to return structure + * @param buffer String buffer to store result in. (In pre hooks will be default value "") + * @param size String buffer size + * + * @error Invalid Handle, invalid type. + * @noreturn +*/ native void DHookGetReturnString(Handle hReturn, char[] buffer, int size); -/** - * Set return value (Use only for: int, entity, bool or float return types) - * - * An entity return type can be set to NULL using INVALID_ENT_REFERENCE (-1). - * - * @param hReturn Handle to return structure - * @param value Value to set return as - * - * @error Invalid Handle, invalid type. - */ +/* Set return value (Use only for: int, entity, bool or float return types) + * + * @param hReturn Handle to return structure + * @param value Value to set return as + * + * @error Invalid Handle, invalid type. + * @noreturn +*/ native void DHookSetReturn(Handle hReturn, any value); -/** - * Set return vector value - * - * @param hReturn Handle to return structure - * @param vec Value to set return vector as - * - * @error Invalid Handle, invalid type. - */ +/* Set return vector value + * + * @param hReturn Handle to return structure + * @param vec Value to set return vector as + * + * @error Invalid Handle, invalid type. + * @noreturn +*/ native void DHookSetReturnVector(Handle hReturn, float vec[3]); -/** - * Set return string value - * - * @param hReturn Handle to return structure - * @param value Value to set return string as - * - * @error Invalid Handle, invalid type. - */ +/* Set return string value + * + * @param hReturn Handle to return structure + * @param value Value to set return string as + * + * @error Invalid Handle, invalid type. + * @noreturn +*/ native void DHookSetReturnString(Handle hReturn, char[] value); //WE SHOULD WRAP THESE AROUND STOCKS FOR NON PTR AS WE SUPPORT BOTH WITH THESE NATIVE'S -/** - * Gets an objects variable value +/* Gets an objects variable value * - * @param hParams Handle to params structure - * @param num Param number to get. - * @param offset Offset within the object to the var to get. - * @param type Type of var it is + * @param hParams Handle to params structure + * @param num Param number to get. + * @param offset Offset within the object to the var to get. + * @param type Type of var it is * - * @error Invalid handle. Invalid param number. Invalid param type. Invalid Object type. - * @return Value of the objects var. If EHANDLE type or entity returns entity index. - */ + * @error Invalid handle. Invalid param number. Invalid param type. Invalid Object type. + * @return Value of the objects var. If EHANDLE type or entity returns entity index. +*/ native any DHookGetParamObjectPtrVar(Handle hParams, int num, int offset, ObjectValueType type); -/** - * Sets an objects variable value +/* Sets an objects variable value * - * @param hParams Handle to params structure - * @param num Param number to set. - * @param offset Offset within the object to the var to set. - * @param type Type of var it is - * @param value The value to set the var to. + * @param hParams Handle to params structure + * @param num Param number to set. + * @param offset Offset within the object to the var to set. + * @param type Type of var it is + * @param value The value to set the var to. * - * @error Invalid handle. Invalid param number. Invalid param type. Invalid Object type. - */ + * @error Invalid handle. Invalid param number. Invalid param type. Invalid Object type. + * @noreturn +*/ native void DHookSetParamObjectPtrVar(Handle hParams, int num, int offset, ObjectValueType type, any value); -/** - * Gets an objects vector variable value +/* Gets an objects vector variable value * - * @param hParams Handle to params structure - * @param num Param number to get. - * @param offset Offset within the object to the var to get. - * @param type Type of var it is - * @param buffer Buffer to store the result vector + * @param hParams Handle to params structure + * @param num Param number to get. + * @param offset Offset within the object to the var to get. + * @param type Type of var it is + * @param buffer Buffer to store the result vector * - * @error Invalid handle. Invalid param number. Invalid param type. Invalid Object type. - */ + * @error Invalid handle. Invalid param number. Invalid param type. Invalid Object type. + * @noreturn +*/ native void DHookGetParamObjectPtrVarVector(Handle hParams, int num, int offset, ObjectValueType type, float buffer[3]); -/** - * Sets an objects vector variable value +/* Sets an objects vector variable value * - * @param hParams Handle to params structure - * @param num Param number to set. - * @param offset Offset within the object to the var to set. - * @param type Type of var it is - * @param value The value to set the vector var to. + * @param hParams Handle to params structure + * @param num Param number to set. + * @param offset Offset within the object to the var to set. + * @param type Type of var it is + * @param value The value to set the vector var to. * - * @error Invalid handle. Invalid param number. Invalid param type. Invalid Object type. - */ + * @error Invalid handle. Invalid param number. Invalid param type. Invalid Object type. + * @noreturn +*/ native void DHookSetParamObjectPtrVarVector(Handle hParams, int num, int offset, ObjectValueType type, float value[3]); -/** - * Gets an objects string variable value +/* Gets an objects string variable value * - * @param hParams Handle to params structure - * @param num Param number to get. - * @param offset Offset within the object to the var to get. - * @param type Type of var it is - * @param buffer Buffer to store the result vector - * @param size Size of the buffer + * @param hParams Handle to params structure + * @param num Param number to get. + * @param offset Offset within the object to the var to get. + * @param type Type of var it is + * @param buffer Buffer to store the result vector + * @param size Size of the buffer * - * @error Invalid handle. Invalid param number. Invalid param type. Invalid Object type. - */ + * @error Invalid handle. Invalid param number. Invalid param type. Invalid Object type. + * @noreturn +*/ native void DHookGetParamObjectPtrString(Handle hParams, int num, int offset, ObjectValueType type, char[] buffer, int size); -/** - * Checks if a pointer param is null +/* Checks if a pointer param is null * - * @param hParams Handle to params structure - * @param num Param number to check. + * @param hParams Handle to params structure + * @param num Param number to check. * - * @return true if null, false otherwise. - * @error Non pointer param - */ + * @error Non pointer param + * @return True if null false otherwise. +*/ native bool DHookIsNullParam(Handle hParams, int num); -/** - * Get param address (Use only for ptr param types) - * - * @param hParams Handle to params structure - * @param num Param number to get. (Example if the function has 2 params and you need the value of the first - * param num would be 1.) - * - * @return Address of the parameter. - * @error Invalid handle. Invalid param number. Invalid param type. - */ -native Address DHookGetParamAddress(Handle hParams, int num); - public Extension __ext_dhooks = { name = "dhooks", @@ -1063,7 +980,6 @@ public __ext_dhooks_SetNTVOptional() MarkNativeAsOptional("DHookSetParamObjectPtrVarVector"); MarkNativeAsOptional("DHookIsNullParam"); MarkNativeAsOptional("DHookGetParamObjectPtrString"); - MarkNativeAsOptional("DHookGetParamAddress"); MarkNativeAsOptional("DHookParam.IsNull"); MarkNativeAsOptional("DHookParam.Get"); @@ -1077,7 +993,6 @@ public __ext_dhooks_SetNTVOptional() MarkNativeAsOptional("DHookParam.GetObjectVarString"); MarkNativeAsOptional("DHookParam.SetObjectVar"); MarkNativeAsOptional("DHookParam.SetObjectVarVector"); - MarkNativeAsOptional("DHookParam.GetAddress"); MarkNativeAsOptional("DHookReturn.Value.get"); MarkNativeAsOptional("DHookReturn.Value.set"); MarkNativeAsOptional("DHookReturn.GetVector"); @@ -1097,4 +1012,4 @@ public __ext_dhooks_SetNTVOptional() MarkNativeAsOptional("DynamicDetour.Enable"); MarkNativeAsOptional("DynamicDetour.Disable"); } -#endif +#endif \ No newline at end of file diff --git a/source/sourcemod/scripting/include/gokz.inc b/source/sourcemod/scripting/include/gokz.inc index edbd896..6e41ed1 100644 --- a/source/sourcemod/scripting/include/gokz.inc +++ b/source/sourcemod/scripting/include/gokz.inc @@ -769,7 +769,49 @@ stock bool GetValidSpawn(float origin[3], float angles[3]) { // Return true if the spawn found is truly valid (not in the ground or out of bounds) bool foundValidSpawn; - bool searchCT; + bool searchCT = false; + float spawnOrigin[3]; + float spawnAngles[3]; + int spawnEntity = -1; + while (!foundValidSpawn) + { + if (searchCT) + { + spawnEntity = FindEntityByClassname(spawnEntity, "info_player_counterterrorist"); + } + else + { + spawnEntity = FindEntityByClassname(spawnEntity, "info_player_terrorist"); + } + + if (spawnEntity != -1) + { + GetEntPropVector(spawnEntity, Prop_Data, "m_vecOrigin", spawnOrigin); + GetEntPropVector(spawnEntity, Prop_Data, "m_angRotation", spawnAngles); + if (IsSpawnValid(spawnOrigin)) + { + origin = spawnOrigin; + angles = spawnAngles; + foundValidSpawn = true; + } + } + else if (!searchCT) + { + searchCT = true; + } + else + { + break; + } + } + return foundValidSpawn; +} + +stock bool GetValidSpawnCT(float origin[3], float angles[3]) +{ + // Return true if the spawn found is truly valid (not in the ground or out of bounds) + bool foundValidSpawn; + bool searchCT = true; float spawnOrigin[3]; float spawnAngles[3]; int spawnEntity = -1; diff --git a/source/sourcemod/scripting/include/movementapi.inc b/source/sourcemod/scripting/include/movementapi.inc index 290c3f2..45ee263 100644 --- a/source/sourcemod/scripting/include/movementapi.inc +++ b/source/sourcemod/scripting/include/movementapi.inc @@ -660,4 +660,4 @@ public void __pl_movementapi_SetNTVOptional() MarkNativeAsOptional("Movement_SetLandingOrigin"); MarkNativeAsOptional("Movement_SetLandingVelocity"); } -#endif \ No newline at end of file +#endif diff --git a/source/sourcemod/scripting/movementapi.sp b/source/sourcemod/scripting/movementapi.sp new file mode 100644 index 0000000..79862bf --- /dev/null +++ b/source/sourcemod/scripting/movementapi.sp @@ -0,0 +1,239 @@ +#include + +#include +#include + +#include + +#pragma newdecls required +#pragma semicolon 1 + + + +public Plugin myinfo = +{ + name = "MovementAPI", + author = "DanZay", + description = "Provides API focused on player movement", + version = "2.4.2", + url = "https://github.com/danzayau/MovementAPI" +}; + +GameData gH_GameData; +Handle gH_GetMaxSpeed; +int gI_Cmdnum[MAXPLAYERS + 1]; +int gI_TickCount[MAXPLAYERS + 1]; + +bool gB_Jumped[MAXPLAYERS + 1]; +bool gB_HitPerf[MAXPLAYERS + 1]; +float gF_NobugLandingOrigin[MAXPLAYERS + 1][3]; +float gF_LandingOrigin[MAXPLAYERS + 1][3]; +float gF_LandingVelocity[MAXPLAYERS + 1][3]; +int gI_LandingTick[MAXPLAYERS + 1]; +int gI_LandingCmdNum[MAXPLAYERS + 1]; +float gF_TakeoffOrigin[MAXPLAYERS + 1][3]; +float gF_TakeoffVelocity[MAXPLAYERS + 1][3]; +int gI_TakeoffTick[MAXPLAYERS + 1]; +int gI_TakeoffCmdNum[MAXPLAYERS + 1]; +bool gB_Turning[MAXPLAYERS + 1]; +bool gB_TurningLeft[MAXPLAYERS + 1]; + +float gF_OldOrigin[MAXPLAYERS + 1][3]; +float gF_OldVelocity[MAXPLAYERS + 1][3]; +float gF_OldEyeAngles[MAXPLAYERS + 1][3]; +bool gB_OldOnGround[MAXPLAYERS + 1]; +bool gB_OldDucking[MAXPLAYERS + 1]; +MoveType gMT_OldMovetype[MAXPLAYERS + 1]; + +#include "movementapi/stocks.sp" +#include "movementapi/hooks.sp" +#include "movementapi/natives.sp" +#include "movementapi/forwards.sp" + +public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) +{ + CreateNatives(); + RegPluginLibrary("movementapi"); + return APLRes_Success; +} + +public void OnPluginStart() +{ + HookEvents(); + CreateGlobalForwards(); + HookEvent("player_spawn", OnPlayerSpawn, EventHookMode_Post); + HookEvent("player_jump", OnPlayerJump, EventHookMode_Post); + for (int client = 1; client <= MaxClients; client++) + { + if (IsClientInGame(client)) + { + OnClientPutInServer(client); + if (IsPlayerAlive(client)) + { + ResetClientData(client); + } + } + } +} + +void HookEvents() +{ + PrepSDKCalls(); + HookGameMovementFunctions(); +} + +public void OnClientPutInServer(int client) +{ + SDKHook(client, SDKHook_PostThinkPost, OnPlayerPostThinkPost); +} + +public void OnPlayerPostThinkPost(int client) +{ + if (!IsPlayerAlive(client)) + { + return; + } + + CheckGround(client); + float eyeAngles[3]; + Movement_GetEyeAngles(client, eyeAngles); + UpdateTurning(client, gF_OldEyeAngles[client], eyeAngles); + gF_OldEyeAngles[client] = eyeAngles; + + Movement_GetOrigin(client, gF_OldOrigin[client]); + Movement_GetVelocity(client, gF_OldVelocity[client]); + gB_OldOnGround[client] = Movement_GetOnGround(client); + gB_OldDucking[client] = gB_Ducking[client]; + gMT_OldMovetype[client] = Movement_GetMovetype(client); + gB_OldWalkMoved[client] = gB_WalkMoved[client]; +} + +public void OnPlayerSpawn(Event event, const char[] name, bool dontBroadcast) +{ + int client = GetClientOfUserId(GetEventInt(event, "userid")); + ResetClientData(client); +} + +public void OnPlayerJump(Event event, const char[] name, bool dontBroadcast) +{ + int client = GetClientOfUserId(GetEventInt(event, "userid")); + bool jumpbug = !gB_OldOnGround[client]; + Call_OnPlayerJump(client, jumpbug); +} + +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]) +{ + CheckNoclip(client); + CheckGround(client); + gI_Cmdnum[client] = cmdnum; + gI_TickCount[client] = tickcount; + return Plugin_Continue; +} + +float GetMaxSpeed(int client) +{ + return SDKCall(gH_GetMaxSpeed, client); +} + +static void PrepSDKCalls() +{ + gH_GameData = LoadGameConfigFile("movementapi.games"); + StartPrepSDKCall(SDKCall_Player); + PrepSDKCall_SetFromConf(gH_GameData, SDKConf_Virtual, "GetPlayerMaxSpeed"); + PrepSDKCall_SetReturnInfo(SDKType_Float, SDKPass_ByValue); + gH_GetMaxSpeed = EndPrepSDKCall(); +} + +static void ResetClientData(int client) +{ + gB_Jumped[client] = false; + gB_HitPerf[client] = false; + gF_TakeoffOrigin[client] = view_as( { 0.0, 0.0, 0.0 } ); + gF_TakeoffVelocity[client] = view_as( { 0.0, 0.0, 0.0 } ); + gI_TakeoffTick[client] = 0; + gF_LandingOrigin[client] = view_as( { 0.0, 0.0, 0.0 } ); + gF_LandingVelocity[client] = view_as( { 0.0, 0.0, 0.0 } ); + gI_LandingTick[client] = 0; + gB_Turning[client] = false; + gB_TurningLeft[client] = false; + + gF_OldOrigin[client] = view_as( { 0.0, 0.0, 0.0 } ); + gF_OldVelocity[client] = view_as( { 0.0, 0.0, 0.0 } ); + gF_OldEyeAngles[client] = view_as( { 0.0, 0.0, 0.0 } ); + gB_OldOnGround[client] = false; + gB_OldDucking[client] = false; + gMT_OldMovetype[client] = MOVETYPE_WALK; + + gB_ProcessingLadderMove[client] = false; + gF_PreLadderMoveVelocity[client] = view_as( { 0.0, 0.0, 0.0 } ); + gB_TakeoffFromLadder[client] = false; + gF_PostLadderMoveOrigin[client] = view_as( { 0.0, 0.0, 0.0 } ); + gF_PostLadderMoveVelocity[client] = view_as( { 0.0, 0.0, 0.0 } ); + gB_ProcessingDuck[client] = false; + gF_PreLadderMoveVelocity[client] = view_as( { 0.0, 0.0, 0.0 } ); + gB_Ducking[client] = false; + gB_PrevOnGround[client] = false; + gB_Duckbugged[client] = false; + gF_PostDuckOrigin[client] = view_as( { 0.0, 0.0, 0.0 } ); + + gB_Jumpbugged[client] = false; + + gB_WalkMoved[client] = false; + gF_PostWalkMoveVelocity[client] = view_as( { 0.0, 0.0, 0.0 } ); + gF_PostAAOrigin[client] = view_as( { 0.0, 0.0, 0.0 } ); + gF_PostAAVelocity[client] = view_as( { 0.0, 0.0, 0.0 } ); + + gB_OldWalkMoved[client] = false; + +} + +static void UpdateTurning(int client, const float oldEyeAngles[3], const float eyeAngles[3]) +{ + gB_Turning[client] = eyeAngles[1] != oldEyeAngles[1]; + gB_TurningLeft[client] = eyeAngles[1] < oldEyeAngles[1] - 180 + || eyeAngles[1] > oldEyeAngles[1] && eyeAngles[1] < oldEyeAngles[1] + 180; +} + +static void CheckNoclip(int client) +{ + // Leaving and entering noclip counts for leaving and touching ground is arbitrary. + // Though this is required for some GOKZ functions to work properly. + MoveType movetype = Movement_GetMovetype(client); + if (gMT_OldMovetype[client] != movetype) + { + // Entering noclip + if (movetype == MOVETYPE_NOCLIP) + { + gF_LandingOrigin[client] = gF_Origin[client]; + gF_LandingVelocity[client] = gF_Velocity[client]; + gI_LandingTick[client] = gI_TickCount[client]; + gI_LandingCmdNum[client] = gI_Cmdnum[client]; + } + else // Leaving noclip + { + gF_TakeoffOrigin[client] = gF_Origin[client]; + gF_TakeoffVelocity[client] = gF_Velocity[client]; + gI_TakeoffTick[client] = gI_TickCount[client]; + gI_TakeoffCmdNum[client] = gI_Cmdnum[client]; + gB_HitPerf[client] = false; + gB_Jumped[client] = false; + } + Call_OnChangeMovetype(client, gMT_OldMovetype[client], movetype); + } +} + +static void CheckGround(int client) +{ + // Check if the player somehow leaves the ground outside of movement processing (eg. triggers) + // The player can't touch the ground outside of movement processing, no need to check for that. + if (gB_OldOnGround[client] && !Movement_GetOnGround(client)) + { + Movement_GetOrigin(client, gF_TakeoffOrigin[client]); + Movement_GetVelocity(client, gF_TakeoffVelocity[client]); + gI_TakeoffTick[client] = gI_TickCount[client]; + gI_TakeoffCmdNum[client] = gI_Cmdnum[client]; + gB_HitPerf[client] = false; + gB_Jumped[client] = false; + Call_OnStopTouchGround(client, false, false, false); + } +} diff --git a/source/sourcemod/scripting/movementapi/forwards.sp b/source/sourcemod/scripting/movementapi/forwards.sp new file mode 100644 index 0000000..9cf0b72 --- /dev/null +++ b/source/sourcemod/scripting/movementapi/forwards.sp @@ -0,0 +1,268 @@ +static Handle H_OnStartDucking; +static Handle H_OnStopDucking; +static Handle H_OnStartTouchGround; +static Handle H_OnStopTouchGround; +static Handle H_OnChangeMovetype; +static Handle H_OnPlayerJump; + +static Handle H_OnPlayerMovePre; +static Handle H_OnPlayerMovePost; +static Handle H_OnDuckPre; +static Handle H_OnDuckPost; +static Handle H_OnLadderMovePre; +static Handle H_OnLadderMovePost; +static Handle H_OnFullLadderMovePre; +static Handle H_OnFullLadderMovePost; +static Handle H_OnJumpPre; +static Handle H_OnJumpPost; +static Handle H_OnAirAcceleratePre; +static Handle H_OnAirAcceleratePost; +static Handle H_OnWalkMovePre; +static Handle H_OnWalkMovePost; +static Handle H_OnCategorizePositionPre; +static Handle H_OnCategorizePositionPost; + +void CreateGlobalForwards() +{ + H_OnStartDucking = CreateGlobalForward("Movement_OnStartDucking", ET_Ignore, Param_Cell); + H_OnStopDucking = CreateGlobalForward("Movement_OnStopDucking", ET_Ignore, Param_Cell); + H_OnStartTouchGround = CreateGlobalForward("Movement_OnStartTouchGround", ET_Ignore, Param_Cell); + H_OnStopTouchGround = CreateGlobalForward("Movement_OnStopTouchGround", ET_Ignore, Param_Cell, Param_Cell, Param_Cell, Param_Cell); + H_OnChangeMovetype = CreateGlobalForward("Movement_OnChangeMovetype", ET_Ignore, Param_Cell, Param_Cell, Param_Cell); + H_OnPlayerJump = CreateGlobalForward("Movement_OnPlayerJump", ET_Ignore, Param_Cell, Param_Cell); + + H_OnPlayerMovePre = CreateGlobalForward("Movement_OnPlayerMovePre", ET_Event, Param_Cell, Param_Array, Param_Array); + H_OnPlayerMovePost = CreateGlobalForward("Movement_OnPlayerMovePost", ET_Event, Param_Cell, Param_Array, Param_Array); + + H_OnDuckPre = CreateGlobalForward("Movement_OnDuckPre", ET_Event, Param_Cell, Param_Array, Param_Array); + H_OnDuckPost = CreateGlobalForward("Movement_OnDuckPost", ET_Event, Param_Cell, Param_Array, Param_Array); + + H_OnLadderMovePre = CreateGlobalForward("Movement_OnLadderMovePre", ET_Event, Param_Cell, Param_Array, Param_Array); + H_OnLadderMovePost = CreateGlobalForward("Movement_OnLadderMovePost", ET_Event, Param_Cell, Param_Array, Param_Array); + + H_OnFullLadderMovePre = CreateGlobalForward("Movement_OnFullLadderMovePre", ET_Event, Param_Cell, Param_Array, Param_Array); + H_OnFullLadderMovePost = CreateGlobalForward("Movement_OnFullLadderMovePost", ET_Event, Param_Cell, Param_Array, Param_Array); + + H_OnJumpPre = CreateGlobalForward("Movement_OnJumpPre", ET_Event, Param_Cell, Param_Array, Param_Array); + H_OnJumpPost = CreateGlobalForward("Movement_OnJumpPost", ET_Event, Param_Cell, Param_Array, Param_Array); + + H_OnAirAcceleratePre = CreateGlobalForward("Movement_OnAirAcceleratePre", ET_Event, Param_Cell, Param_Array, Param_Array); + H_OnAirAcceleratePost = CreateGlobalForward("Movement_OnAirAcceleratePost", ET_Event, Param_Cell, Param_Array, Param_Array); + + H_OnWalkMovePre = CreateGlobalForward("Movement_OnWalkMovePre", ET_Event, Param_Cell, Param_Array, Param_Array); + H_OnWalkMovePost = CreateGlobalForward("Movement_OnWalkMovePost", ET_Event, Param_Cell, Param_Array, Param_Array); + + H_OnCategorizePositionPre = CreateGlobalForward("Movement_OnCategorizePositionPre", ET_Event, Param_Cell, Param_Array, Param_Array); + H_OnCategorizePositionPost = CreateGlobalForward("Movement_OnCategorizePositionPost", ET_Event, Param_Cell, Param_Array, Param_Array); +} + +void Call_OnStartDucking(int client) +{ + Call_StartForward(H_OnStartDucking); + Call_PushCell(client); + Call_Finish(); +} + +void Call_OnStopDucking(int client) +{ + Call_StartForward(H_OnStopDucking); + Call_PushCell(client); + Call_Finish(); +} + +void Call_OnStartTouchGround(int client) +{ + Call_StartForward(H_OnStartTouchGround); + Call_PushCell(client); + Call_Finish(); +} + +void Call_OnStopTouchGround(int client, bool jumped, bool ladderJump, bool jumpbug) +{ + Call_StartForward(H_OnStopTouchGround); + Call_PushCell(client); + Call_PushCell(jumped); + Call_PushCell(ladderJump); + Call_PushCell(jumpbug); + Call_Finish(); + // Immediately update OldOnGround state, so we can catch takeoffs that happen outside movement processing. + gB_OldOnGround[client] = false; +} + + +void Call_OnChangeMovetype(int client, MoveType oldMovetype, MoveType newMovetype) +{ + Call_StartForward(H_OnChangeMovetype); + Call_PushCell(client); + Call_PushCell(oldMovetype); + Call_PushCell(newMovetype); + Call_Finish(); +} + +void Call_OnPlayerJump(int client, bool jumpbug) +{ + Call_StartForward(H_OnPlayerJump); + Call_PushCell(client); + Call_PushCell(jumpbug); + Call_Finish(); +} + +Action Call_OnPlayerMovePre(int client, float origin[3], float velocity[3], Action &result) +{ + Call_StartForward(H_OnPlayerMovePre); + Call_PushCell(client); + Call_PushArrayEx(origin, 3, SM_PARAM_COPYBACK); + Call_PushArrayEx(velocity, 3, SM_PARAM_COPYBACK); + Call_Finish(result); + return result; +} + +Action Call_OnPlayerMovePost(int client, float origin[3], float velocity[3], Action &result) +{ + Call_StartForward(H_OnPlayerMovePost); + Call_PushCell(client); + Call_PushArrayEx(origin, 3, SM_PARAM_COPYBACK); + Call_PushArrayEx(velocity, 3, SM_PARAM_COPYBACK); + Call_Finish(result); + return result; +} + +Action Call_OnDuckPre(int client, float origin[3], float velocity[3], Action &result) +{ + Call_StartForward(H_OnDuckPre); + Call_PushCell(client); + Call_PushArrayEx(origin, 3, SM_PARAM_COPYBACK); + Call_PushArrayEx(velocity, 3, SM_PARAM_COPYBACK); + Call_Finish(result); + return result; +} + +Action Call_OnDuckPost(int client, float origin[3], float velocity[3], Action &result) +{ + Call_StartForward(H_OnDuckPost); + Call_PushCell(client); + Call_PushArrayEx(origin, 3, SM_PARAM_COPYBACK); + Call_PushArrayEx(velocity, 3, SM_PARAM_COPYBACK); + Call_Finish(result); + return result; +} + +Action Call_OnLadderMovePre(int client, float origin[3], float velocity[3], Action &result) +{ + Call_StartForward(H_OnLadderMovePre); + Call_PushCell(client); + Call_PushArrayEx(origin, 3, SM_PARAM_COPYBACK); + Call_PushArrayEx(velocity, 3, SM_PARAM_COPYBACK); + Call_Finish(result); + return result; +} + +Action Call_OnLadderMovePost(int client, float origin[3], float velocity[3], Action &result) +{ + Call_StartForward(H_OnLadderMovePost); + Call_PushCell(client); + Call_PushArrayEx(origin, 3, SM_PARAM_COPYBACK); + Call_PushArrayEx(velocity, 3, SM_PARAM_COPYBACK); + Call_Finish(result); + return result; +} + +Action Call_OnFullLadderMovePre(int client, float origin[3], float velocity[3], Action &result) +{ + Call_StartForward(H_OnFullLadderMovePre); + Call_PushCell(client); + Call_PushArrayEx(origin, 3, SM_PARAM_COPYBACK); + Call_PushArrayEx(velocity, 3, SM_PARAM_COPYBACK); + Call_Finish(result); + return result; +} + +Action Call_OnFullLadderMovePost(int client, float origin[3], float velocity[3], Action &result) +{ + Call_StartForward(H_OnFullLadderMovePost); + Call_PushCell(client); + Call_PushArrayEx(origin, 3, SM_PARAM_COPYBACK); + Call_PushArrayEx(velocity, 3, SM_PARAM_COPYBACK); + Call_Finish(result); + return result; +} + +Action Call_OnJumpPre(int client, float origin[3], float velocity[3], Action &result) +{ + Call_StartForward(H_OnJumpPre); + Call_PushCell(client); + Call_PushArrayEx(origin, 3, SM_PARAM_COPYBACK); + Call_PushArrayEx(velocity, 3, SM_PARAM_COPYBACK); + Call_Finish(result); + return result; +} + +Action Call_OnJumpPost(int client, float origin[3], float velocity[3], Action &result) +{ + Call_StartForward(H_OnJumpPost); + Call_PushCell(client); + Call_PushArrayEx(origin, 3, SM_PARAM_COPYBACK); + Call_PushArrayEx(velocity, 3, SM_PARAM_COPYBACK); + Call_Finish(result); + return result; +} + +Action Call_OnAirAcceleratePre(int client, float origin[3], float velocity[3], Action &result) +{ + Call_StartForward(H_OnAirAcceleratePre); + Call_PushCell(client); + Call_PushArrayEx(origin, 3, SM_PARAM_COPYBACK); + Call_PushArrayEx(velocity, 3, SM_PARAM_COPYBACK); + Call_Finish(result); + return result; +} + +Action Call_OnAirAcceleratePost(int client, float origin[3], float velocity[3], Action &result) +{ + Call_StartForward(H_OnAirAcceleratePost); + Call_PushCell(client); + Call_PushArrayEx(origin, 3, SM_PARAM_COPYBACK); + Call_PushArrayEx(velocity, 3, SM_PARAM_COPYBACK); + Call_Finish(result); + return result; +} + +Action Call_OnWalkMovePre(int client, float origin[3], float velocity[3], Action &result) +{ + Call_StartForward(H_OnWalkMovePre); + Call_PushCell(client); + Call_PushArrayEx(origin, 3, SM_PARAM_COPYBACK); + Call_PushArrayEx(velocity, 3, SM_PARAM_COPYBACK); + Call_Finish(result); + return result; +} + +Action Call_OnWalkMovePost(int client, float origin[3], float velocity[3], Action &result) +{ + Call_StartForward(H_OnWalkMovePost); + Call_PushCell(client); + Call_PushArrayEx(origin, 3, SM_PARAM_COPYBACK); + Call_PushArrayEx(velocity, 3, SM_PARAM_COPYBACK); + Call_Finish(result); + return result; +} + +Action Call_OnCategorizePositionPre(int client, float origin[3], float velocity[3], Action &result) +{ + Call_StartForward(H_OnCategorizePositionPre); + Call_PushCell(client); + Call_PushArrayEx(origin, 3, SM_PARAM_COPYBACK); + Call_PushArrayEx(velocity, 3, SM_PARAM_COPYBACK); + Call_Finish(result); + return result; +} + +Action Call_OnCategorizePositionPost(int client, float origin[3], float velocity[3], Action &result) +{ + Call_StartForward(H_OnCategorizePositionPost); + Call_PushCell(client); + Call_PushArrayEx(origin, 3, SM_PARAM_COPYBACK); + Call_PushArrayEx(velocity, 3, SM_PARAM_COPYBACK); + Call_Finish(result); + return result; +} \ No newline at end of file diff --git a/source/sourcemod/scripting/movementapi/hooks.sp b/source/sourcemod/scripting/movementapi/hooks.sp new file mode 100644 index 0000000..7b97b62 --- /dev/null +++ b/source/sourcemod/scripting/movementapi/hooks.sp @@ -0,0 +1,580 @@ +static DynamicDetour H_OnPlayerMove; +static DynamicDetour H_OnDuck; +static DynamicDetour H_OnLadderMove; +static DynamicDetour H_OnFullLadderMove; +static DynamicDetour H_OnJump; +static DynamicDetour H_OnAirAccelerate; +static DynamicDetour H_OnWalkMove; +static DynamicDetour H_OnCategorizePosition; + +float gF_Origin[MAXPLAYERS + 1][3]; +float gF_Velocity[MAXPLAYERS + 1][3]; + +bool gB_ProcessingLadderMove[MAXPLAYERS + 1]; +float gF_PreLadderMoveVelocity[MAXPLAYERS + 1][3]; +bool gB_TakeoffFromLadder[MAXPLAYERS + 1]; +float gF_PostLadderMoveOrigin[MAXPLAYERS + 1][3]; +float gF_PostLadderMoveVelocity[MAXPLAYERS + 1][3]; + +bool gB_ProcessingDuck[MAXPLAYERS + 1]; +bool gB_Ducking[MAXPLAYERS + 1]; +bool gB_PrevOnGround[MAXPLAYERS + 1]; +bool gB_Duckbugged[MAXPLAYERS + 1]; +float gF_PostDuckOrigin[MAXPLAYERS + 1][3]; + +bool gB_Jumpbugged[MAXPLAYERS + 1]; + +bool gB_WalkMoved[MAXPLAYERS + 1]; +float gF_PostWalkMoveVelocity[MAXPLAYERS + 1][3]; +float gF_PostAAOrigin[MAXPLAYERS + 1][3]; +float gF_PostAAVelocity[MAXPLAYERS + 1][3]; + +bool gB_OldWalkMoved[MAXPLAYERS + 1]; + +void HookGameMovementFunctions() +{ + HookGameMovementFunction(H_OnDuck, "CCSGameMovement::Duck", DHooks_OnDuck_Pre, DHooks_OnDuck_Post); + HookGameMovementFunction(H_OnLadderMove, "CGameMovement::LadderMove", DHooks_OnLadderMove_Pre, DHooks_OnLadderMove_Post); + HookGameMovementFunction(H_OnFullLadderMove, "CGameMovement::FullLadderMove", DHooks_OnFullLadderMove_Pre, DHooks_OnFullLadderMove_Post); + HookGameMovementFunction(H_OnAirAccelerate, "CGameMovement::AirAccelerate", DHooks_OnAirAccelerate_Pre, DHooks_OnAirAccelerate_Post); + HookGameMovementFunction(H_OnWalkMove, "CGameMovement::WalkMove", DHooks_OnWalkMove_Pre, DHooks_OnWalkMove_Post); + HookGameMovementFunction(H_OnJump, "CCSGameMovement::OnJump", DHooks_OnJump_Pre, DHooks_OnJump_Post); + HookGameMovementFunction(H_OnPlayerMove, "CCSGameMovement::PlayerMove", DHooks_OnPlayerMove_Pre, DHooks_OnPlayerMove_Post); + HookGameMovementFunction(H_OnCategorizePosition, "CGameMovement::CategorizePosition", DHooks_OnCategorizePosition_Pre, DHooks_OnCategorizePosition_Post); +} + +Action UpdateMoveData(Address pThis, int client, Function func) +{ + GameMove_GetOrigin(pThis, gF_Origin[client]); + GameMove_GetVelocity(pThis, gF_Velocity[client]); + Action result; + Call_StartFunction(INVALID_HANDLE, func); + Call_PushCell(client); + Call_PushArrayEx(gF_Origin[client], 3, SM_PARAM_COPYBACK); + Call_PushArrayEx(gF_Velocity[client], 3, SM_PARAM_COPYBACK); + Call_Finish(result); + if (result != Plugin_Continue) + { + GameMove_SetOrigin(pThis, gF_Origin[client]); + GameMove_SetVelocity(pThis, gF_Velocity[client]); + } + return result; +} + +public MRESReturn DHooks_OnDuck_Pre(Address pThis) +{ + int client = GetClientFromGameMovementAddress(pThis); + if (!IsPlayerAlive(client) || IsFakeClient(client) || Movement_GetMovetype(client) == MOVETYPE_NOCLIP) + { + return MRES_Ignored; + } + Action result = UpdateMoveData(pThis, client, Call_OnDuckPre); + + gB_Ducking[client] = Movement_GetDucking(client); + gB_ProcessingDuck[client] = true; + + if (result != Plugin_Continue) + { + return MRES_Handled; + } + else + { + return MRES_Ignored; + } +} + +public MRESReturn DHooks_OnDuck_Post(Address pThis) +{ + int client = GetClientFromGameMovementAddress(pThis); + if (!IsPlayerAlive(client) || IsFakeClient(client) || Movement_GetMovetype(client) == MOVETYPE_NOCLIP) + { + return MRES_Ignored; + } + + if (gB_Ducking[client] && !gB_OldDucking[client]) + { + Call_OnStartDucking(client); + } + else if (!gB_Ducking[client] && gB_OldDucking[client]) + { + Call_OnStopDucking(client); + } + gB_ProcessingDuck[client] = false; + GameMove_GetOrigin(pThis, gF_PostDuckOrigin[client]); + + Action result = UpdateMoveData(pThis, client, Call_OnDuckPost); + if (result != Plugin_Continue) + { + return MRES_Handled; + } + else + { + return MRES_Ignored; + } +} + +public MRESReturn DHooks_OnLadderMove_Pre(Address pThis) +{ + int client = GetClientFromGameMovementAddress(pThis); + if (!IsPlayerAlive(client) || IsFakeClient(client) || Movement_GetMovetype(client) == MOVETYPE_NOCLIP) + { + return MRES_Ignored; + } + Action result = UpdateMoveData(pThis, client, Call_OnLadderMovePre); + + gB_ProcessingLadderMove[client] = true; + GameMove_GetVelocity(pThis, gF_PreLadderMoveVelocity[client]); + + if (result != Plugin_Continue) + { + return MRES_Handled; + } + else + { + return MRES_Ignored; + } +} + +public MRESReturn DHooks_OnLadderMove_Post(Address pThis, DHookReturn hReturn) +{ + // While the movetype changed here, the vertical velocity is not yet updated. + // gF_PostLadderMoveVelocity can be incorrect here. + int client = GetClientFromGameMovementAddress(pThis); + if (!IsPlayerAlive(client) || IsFakeClient(client) || Movement_GetMovetype(client) == MOVETYPE_NOCLIP) + { + return MRES_Ignored; + } + + GameMove_GetOrigin(pThis, gF_PostLadderMoveOrigin[client]); + GameMove_GetVelocity(pThis, gF_PostLadderMoveVelocity[client]); + gB_ProcessingLadderMove[client] = false; + bool returnValue = DHookGetReturn(hReturn); + // If this returns false, and the movetype was originally MOVETYPE_LADDER, that means the player will change movetype and takeoff (LAJ) + // If this returns true, the movetype can still change in FullLadderMove by jumping (LAH) + // The current movetype here is still ladder, but it will change right after this function call. + if (!returnValue && Movement_GetMovetype(client) == MOVETYPE_LADDER) + { + gF_TakeoffVelocity[client] = gF_PostLadderMoveVelocity[client]; + gF_TakeoffOrigin[client] = gF_PostLadderMoveOrigin[client]; + gI_TakeoffTick[client] = gI_TickCount[client]; + gI_TakeoffCmdNum[client] = gI_Cmdnum[client]; + gB_Jumped[client] = false; + gB_HitPerf[client] = false; + Call_OnChangeMovetype(client, MOVETYPE_LADDER, MOVETYPE_WALK); + } + else if (returnValue && gMT_OldMovetype[client] != MOVETYPE_LADDER) + { + if (Movement_GetMovetype(client) == MOVETYPE_LADDER) + { + gF_LandingOrigin[client] = gF_PostLadderMoveOrigin[client]; + // We don't really care about nobug origin when player lands on ladder. + gF_NobugLandingOrigin[client] = gF_LandingOrigin[client]; + gF_LandingVelocity[client] = gF_PreLadderMoveVelocity[client]; + gI_LandingCmdNum[client] = gI_Cmdnum[client]; + gI_LandingTick[client] = gI_TickCount[client]; + Call_OnChangeMovetype(client, MOVETYPE_WALK, MOVETYPE_LADDER); + } + } + else if (returnValue && gMT_OldMovetype[client] == MOVETYPE_LADDER) + { + // Player is on the ladder and in the air, pressing jump pushes them away from the ladder. + float curtime = GetGameTime(); + int buttons = GetClientButtons(client); + float ignoreLadderJumpTime = GetEntPropFloat(client, Prop_Data, "m_ignoreLadderJumpTime"); + if (buttons & IN_JUMP && ignoreLadderJumpTime <= curtime) + { + gF_TakeoffVelocity[client] = gF_PostLadderMoveVelocity[client]; + gF_TakeoffOrigin[client] = gF_PostLadderMoveOrigin[client]; + gI_TakeoffTick[client] = gI_TickCount[client]; + gI_TakeoffCmdNum[client] = gI_Cmdnum[client]; + gB_Jumped[client] = false; + gB_HitPerf[client] = false; + gB_TakeoffFromLadder[client] = true; + Call_OnChangeMovetype(client, MOVETYPE_LADDER, MOVETYPE_WALK); + } + } + Action result = UpdateMoveData(pThis, client, Call_OnLadderMovePost); + if (result != Plugin_Continue) + { + return MRES_Handled; + } + else + { + return MRES_Ignored; + } +} + +public MRESReturn DHooks_OnFullLadderMove_Pre(Address pThis) +{ + int client = GetClientFromGameMovementAddress(pThis); + if (!IsPlayerAlive(client) || IsFakeClient(client)) + { + return MRES_Ignored; + } + Action result = UpdateMoveData(pThis, client, Call_OnFullLadderMovePre); + + if (result != Plugin_Continue) + { + return MRES_Handled; + } + else + { + return MRES_Ignored; + } +} + +public MRESReturn DHooks_OnJump_Pre(Address pThis, DHookParam hParams) +{ + int client = GetClientFromGameMovementAddress(pThis); + if (!IsPlayerAlive(client) || IsFakeClient(client)) + { + return MRES_Ignored; + } + + gB_Jumped[client] = true; + if (gB_Duckbugged[client]) + { + gB_Jumpbugged[client] = true; + } + + // HitPerf must be modified here so plugins can know if player hits a perf or not. + // Not a perf if last movetype was ladder, because jumping works differently on ladders. + if (gMT_OldMovetype[client] != MOVETYPE_LADDER) + { + // If you walked on the last tick then clearly it's not going to be a perf. + // Can't perf if you don't jump. + gB_HitPerf[client] = !gB_OldWalkMoved[client]; + } + else + { + gB_HitPerf[client] = false; + } + + Action result = UpdateMoveData(pThis, client, Call_OnJumpPre); + + if (result != Plugin_Continue) + { + return MRES_Handled; + } + else + { + return MRES_Ignored; + } +} + +public MRESReturn DHooks_OnJump_Post(Address pThis, DHookParam hParams) +{ + int client = GetClientFromGameMovementAddress(pThis); + if (!IsPlayerAlive(client) || IsFakeClient(client)) + { + return MRES_Ignored; + } + // We need to update LadderMove velocity again in case of jumping. + GameMove_GetVelocity(pThis, gF_PostLadderMoveVelocity[client]); + + // Current origin because the player hasn't moved yet. + gF_TakeoffOrigin[client] = gF_Origin[client]; + gF_TakeoffVelocity[client] = gF_Velocity[client]; + gI_TakeoffCmdNum[client] = gI_Cmdnum[client]; + gI_TakeoffTick[client] = gI_TickCount[client]; + + // OnJump will only be called if the client previously touched some sort of ground, so Call_OnStopTouchGround should always be called. + Call_OnStopTouchGround(client, true, gB_TakeoffFromLadder[client], gB_Jumpbugged[client]); + + Action result = UpdateMoveData(pThis, client, Call_OnJumpPost); + if (result != Plugin_Continue) + { + return MRES_Handled; + } + else + { + return MRES_Ignored; + } +} + +public MRESReturn DHooks_OnFullLadderMove_Post(Address pThis) +{ + int client = GetClientFromGameMovementAddress(pThis); + if (!IsPlayerAlive(client) || IsFakeClient(client) || Movement_GetMovetype(client) == MOVETYPE_NOCLIP) + { + return MRES_Ignored; + } + + Action result = UpdateMoveData(pThis, client, Call_OnFullLadderMovePost); + if (result != Plugin_Continue) + { + return MRES_Handled; + } + else + { + return MRES_Ignored; + } +} +// We hook AirAccelerate because TryPlayerMove in AirMove can change velocity +// AirAccelerate velocity is required for nobug landing origin. +public MRESReturn DHooks_OnAirAccelerate_Pre(Address pThis, DHookParam hParams) +{ + int client = GetClientFromGameMovementAddress(pThis); + if (!IsPlayerAlive(client) || IsFakeClient(client)) + { + return MRES_Ignored; + } + Action result = UpdateMoveData(pThis, client, Call_OnAirAcceleratePre); + + if (result != Plugin_Continue) + { + return MRES_Handled; + } + else + { + return MRES_Ignored; + } +} + +public MRESReturn DHooks_OnAirAccelerate_Post(Address pThis, DHookParam hParams) +{ + int client = GetClientFromGameMovementAddress(pThis); + if (!IsPlayerAlive(client) || IsFakeClient(client)) + { + return MRES_Ignored; + } + + GameMove_GetOrigin(pThis, gF_PostAAOrigin[client]); + GameMove_GetVelocity(pThis, gF_PostAAVelocity[client]); + + Action result = UpdateMoveData(pThis, client, Call_OnAirAcceleratePost); + if (result != Plugin_Continue) + { + return MRES_Handled; + } + else + { + return MRES_Ignored; + } +} + +// WalkMove is called too early to detect if the player is still on ground or not. +public MRESReturn DHooks_OnWalkMove_Pre(Address pThis) +{ + int client = GetClientFromGameMovementAddress(pThis); + if (!IsPlayerAlive(client) || IsFakeClient(client)) + { + return MRES_Ignored; + } + Action result = UpdateMoveData(pThis, client, Call_OnWalkMovePre); + + if (result != Plugin_Continue) + { + return MRES_Handled; + } + else + { + return MRES_Ignored; + } +} + +public MRESReturn DHooks_OnWalkMove_Post(Address pThis) +{ + int client = GetClientFromGameMovementAddress(pThis); + if (!IsPlayerAlive(client) || IsFakeClient(client)) + { + return MRES_Ignored; + } + + GameMove_GetVelocity(pThis, gF_PostWalkMoveVelocity[client]); + gB_WalkMoved[client] = true; + + Action result = UpdateMoveData(pThis, client, Call_OnWalkMovePost); + if (result != Plugin_Continue) + { + return MRES_Handled; + } + else + { + return MRES_Ignored; + } +} + +public MRESReturn DHooks_OnPlayerMove_Pre(Address pThis) +{ + int client = GetClientFromGameMovementAddress(pThis); + if (!IsPlayerAlive(client) || IsFakeClient(client)) + { + return MRES_Ignored; + } + + gB_Duckbugged[client] = false; + gB_WalkMoved[client] = false; + gB_Jumpbugged[client] = false; + gB_Jumped[client] = false; + gB_TakeoffFromLadder[client] = false; + + Action result = UpdateMoveData(pThis, client, Call_OnPlayerMovePre); + + if (result != Plugin_Continue) + { + return MRES_Handled; + } + else + { + return MRES_Ignored; + } +} + +public MRESReturn DHooks_OnPlayerMove_Post(Address pThis) +{ + int client = GetClientFromGameMovementAddress(pThis); + if (!IsPlayerAlive(client) || IsFakeClient(client)) + { + return MRES_Ignored; + } + Action result = UpdateMoveData(pThis, client, Call_OnPlayerMovePost); + + if (result != Plugin_Continue) + { + return MRES_Handled; + } + else + { + return MRES_Ignored; + } +} + +public MRESReturn DHooks_OnCategorizePosition_Pre(Address pThis) +{ + int client = GetClientFromGameMovementAddress(pThis); + if (!IsPlayerAlive(client) || IsFakeClient(client)) + { + return MRES_Ignored; + } + Action result = UpdateMoveData(pThis, client, Call_OnCategorizePositionPre); + + gB_PrevOnGround[client] = Movement_GetOnGround(client); + + if (result != Plugin_Continue) + { + return MRES_Handled; + } + else + { + return MRES_Ignored; + } +} + +public MRESReturn DHooks_OnCategorizePosition_Post(Address pThis) +{ + int client = GetClientFromGameMovementAddress(pThis); + if (!IsPlayerAlive(client) || IsFakeClient(client)) + { + return MRES_Ignored; + } + bool ground = Movement_GetOnGround(client); + // Ground state changed! + if (gB_PrevOnGround[client] != ground) + { + if (ground) // Landing + { + NobugLandingOrigin(client, gF_NobugLandingOrigin[client]); + + gF_LandingOrigin[client] = gF_Origin[client]; + gI_LandingCmdNum[client] = gI_Cmdnum[client]; + gI_LandingTick[client] = gI_TickCount[client]; + Call_OnStartTouchGround(client); + } + else // Takeoff + { + gF_TakeoffOrigin[client] = gF_OldOrigin[client]; + // Note: Jumping isn't detected here. + if (gB_WalkMoved[client]) + { + gF_TakeoffVelocity[client] = gF_PostWalkMoveVelocity[client]; + } + else + { + gF_TakeoffVelocity[client] = gF_PostLadderMoveVelocity[client]; + } + gI_TakeoffTick[client] = gI_TickCount[client]; + gI_TakeoffCmdNum[client] = gI_Cmdnum[client]; + gB_Jumped[client] = false; + gB_HitPerf[client] = false; + bool hadLadderMoveType = Movement_GetMovetype(client) == MOVETYPE_LADDER || gMT_OldMovetype[client] == MOVETYPE_LADDER; + Call_OnStopTouchGround(client, false, hadLadderMoveType && !gB_WalkMoved[client], false); + } + } + + Action result = UpdateMoveData(pThis, client, Call_OnCategorizePositionPost); + if (result != Plugin_Continue) + { + return MRES_Handled; + } + else + { + return MRES_Ignored; + } +} + +static void NobugLandingOrigin(int client, float landingOrigin[3]) +{ + // NOTE: Get ground position and distance to ground. + float groundEndPoint[3]; + groundEndPoint = gF_Origin[client]; + groundEndPoint[2] -= 2.0; + float mins[3] = {-16.0, -16.0, 0.0}; + float maxs[3] = {16.0, 16.0, 0.0}; + TR_TraceHullFilter(gF_Origin[client], groundEndPoint, mins, maxs, MASK_PLAYERSOLID, TraceEntityFilterPlayers, client); + + float groundPos[3]; + TR_GetEndPosition(groundPos); + + // NOTE: This is almost guaranteed to hit because CategorizePosition does + // the exact same trace to determine if the player is on the ground or not. + if (!TR_DidHit()) + { + // Use groundEndPoint if trace fails, because this MIGHT + // give less distance in this extremely rare case. + groundPos = groundEndPoint; + } + + gB_Duckbugged[client] = gB_ProcessingDuck[client]; + float distanceToGround = gF_Origin[client][2] - groundPos[2]; + float velocity[3], origin[3]; + // If there's any distance to the ground, then we'll trace it with this one. + + // It seems like sometimes the player can end up ever so slighly above this "ground" value, + // likely due to floating point precision error. Treat it as a bugged jump as well. + if (distanceToGround > 0.001 || gB_ProcessingDuck[client]) + { + // Use the current origin and velocity if we're not touching the ground + gF_LandingVelocity[client] = gF_Velocity[client]; + velocity = gF_Velocity[client]; + origin = gF_Origin[client]; + } + else + { + // NOTE: Use gF_OldVelocity and gF_OldOrigin if jump is potentially bugged. + gF_LandingVelocity[client] = gF_PostAAVelocity[client]; + velocity = gF_PostAAVelocity[client]; + origin = gF_PostAAOrigin[client]; + } + + float firstTraceEndpoint[3], scaledVelocity[3]; + scaledVelocity = velocity; + ScaleVector(scaledVelocity, GetTickInterval()); + AddVectors(origin, scaledVelocity, firstTraceEndpoint); + + TR_TraceHullFilter(origin, firstTraceEndpoint, mins, maxs, MASK_PLAYERSOLID, TraceEntityFilterPlayers, client); + if (!TR_DidHit()) + { + // It is possible to not hit the trace, if your vertical velocity is low enough. + // In an extreme case, you would need 10 more traces for this to hit. + // It is also possible to miss the trace on a flat jump, by hitting the very edge of a block. + + // Use groundPos, because this will give no distance advantage to the player, but + // it will let the player not have his jump invalidated. + landingOrigin = groundPos; + } + else + { + TR_GetEndPosition(landingOrigin); + } +} diff --git a/source/sourcemod/scripting/movementapi/natives.sp b/source/sourcemod/scripting/movementapi/natives.sp new file mode 100644 index 0000000..f8cd7a5 --- /dev/null +++ b/source/sourcemod/scripting/movementapi/natives.sp @@ -0,0 +1,183 @@ +void CreateNatives() +{ + CreateNative("Movement_GetJumped", Native_GetJumped); + CreateNative("Movement_GetHitPerf", Native_GetHitPerf); + CreateNative("Movement_GetTakeoffOrigin", Native_GetTakeoffOrigin); + CreateNative("Movement_GetTakeoffVelocity", Native_GetTakeoffVelocity); + CreateNative("Movement_GetTakeoffSpeed", Native_GetTakeoffSpeed); + CreateNative("Movement_GetTakeoffTick", Native_GetTakeoffTick); + CreateNative("Movement_GetTakeoffCmdNum", Native_GetTakeoffCmdNum); + CreateNative("Movement_GetNobugLandingOrigin", Native_GetNobugLandingOrigin); + CreateNative("Movement_GetLandingOrigin", Native_GetLandingOrigin); + CreateNative("Movement_GetLandingVelocity", Native_GetLandingVelocity); + CreateNative("Movement_GetLandingSpeed", Native_GetLandingSpeed); + CreateNative("Movement_GetLandingTick", Native_GetLandingTick); + CreateNative("Movement_GetLandingCmdNum", Native_GetLandingCmdNum); + CreateNative("Movement_GetTurning", Native_GetTurning); + CreateNative("Movement_GetTurningLeft", Native_GetTurningLeft); + CreateNative("Movement_GetTurningRight", Native_GetTurningRight); + CreateNative("Movement_GetMaxSpeed", Native_GetMaxSpeed); + CreateNative("Movement_GetDuckbugged", Native_GetDuckbugged); + CreateNative("Movement_GetJumpbugged", Native_GetJumpbugged); + CreateNative("Movement_GetProcessingOrigin", Native_GetProcessingOrigin); + CreateNative("Movement_GetProcessingVelocity", Native_GetProcessingVelocity); + CreateNative("Movement_SetTakeoffOrigin", Native_SetTakeoffOrigin); + CreateNative("Movement_SetTakeoffVelocity", Native_SetTakeoffVelocity); + CreateNative("Movement_SetLandingOrigin", Native_SetLandingOrigin); + CreateNative("Movement_SetLandingVelocity", Native_SetLandingVelocity); +} + +public int Native_GetJumped(Handle plugin, int numParams) +{ + return gB_Jumped[GetNativeCell(1)]; +} + +public int Native_GetHitPerf(Handle plugin, int numParams) +{ + return gB_HitPerf[GetNativeCell(1)]; +} + +public int Native_GetTakeoffOrigin(Handle plugin, int numParams) +{ + return SetNativeArray(2, gF_TakeoffOrigin[GetNativeCell(1)], 3); +} + +public int Native_GetTakeoffVelocity(Handle plugin, int numParams) +{ + return SetNativeArray(2, gF_TakeoffVelocity[GetNativeCell(1)], 3); +} + +public int Native_GetTakeoffSpeed(Handle plugin, int numParams) +{ + return view_as(GetVectorHorizontalLength(gF_TakeoffVelocity[GetNativeCell(1)])); +} + +public int Native_GetTakeoffTick(Handle plugin, int numParams) +{ + return gI_TakeoffTick[GetNativeCell(1)]; +} + +public int Native_GetTakeoffCmdNum(Handle plugin, int numParams) +{ + return gI_TakeoffCmdNum[GetNativeCell(1)]; +} + +public int Native_GetNobugLandingOrigin(Handle plugin, int numParams) +{ + return SetNativeArray(2, gF_NobugLandingOrigin[GetNativeCell(1)], 3); +} + +public int Native_GetLandingOrigin(Handle plugin, int numParams) +{ + return SetNativeArray(2, gF_LandingOrigin[GetNativeCell(1)], 3); +} + +public int Native_GetLandingVelocity(Handle plugin, int numParams) +{ + return SetNativeArray(2, gF_LandingVelocity[GetNativeCell(1)], 3); +} + +public int Native_GetLandingSpeed(Handle plugin, int numParams) +{ + return view_as(GetVectorHorizontalLength(gF_LandingVelocity[GetNativeCell(1)])); +} + +public int Native_GetLandingTick(Handle plugin, int numParams) +{ + return gI_LandingTick[GetNativeCell(1)]; +} + +public int Native_GetLandingCmdNum(Handle plugin, int numParams) +{ + return gI_LandingCmdNum[GetNativeCell(1)]; +} + +public int Native_GetTurning(Handle plugin, int numParams) +{ + return view_as(gB_Turning[GetNativeCell(1)]); +} + +public int Native_GetTurningLeft(Handle plugin, int numParams) +{ + return view_as(gB_TurningLeft[GetNativeCell(1)]); +} + +public int Native_GetTurningRight(Handle plugin, int numParams) +{ + int client = GetNativeCell(1); + return view_as(gB_Turning[client] && !gB_TurningLeft[client]); +} + +public int Native_GetMaxSpeed(Handle plugin, int numParams) +{ + int client = GetNativeCell(1); + return view_as(GetMaxSpeed(client)); +} + +public int Native_GetDuckbugged(Handle plugin, int numParams) +{ + return view_as(gB_Duckbugged[GetNativeCell(1)]); +} + +public int Native_GetJumpbugged(Handle plugin, int numParams) +{ + return view_as(gB_Jumpbugged[GetNativeCell(1)]); +} + +public int Native_GetProcessingOrigin(Handle plugin, int numParams) +{ + return SetNativeArray(2, gF_Origin[GetNativeCell(1)], 3); +} + +public int Native_GetProcessingVelocity(Handle plugin, int numParams) +{ + return SetNativeArray(2, gF_Velocity[GetNativeCell(1)], 3); +} + +public int Native_SetTakeoffOrigin(Handle plugin, int numParams) +{ + float array[3]; + GetNativeArray(2, array, sizeof(array)); + for (int i = 0; i < 3; i++) + { + gF_TakeoffOrigin[GetNativeCell(1)][i] = array[i]; + } + + return 0; +} + +public int Native_SetTakeoffVelocity(Handle plugin, int numParams) +{ + float array[3]; + GetNativeArray(2, array, sizeof(array)); + for (int i = 0; i < 3; i++) + { + gF_TakeoffVelocity[GetNativeCell(1)][i] = array[i]; + } + + return 0; +} + +public int Native_SetLandingOrigin(Handle plugin, int numParams) +{ + float array[3]; + GetNativeArray(2, array, sizeof(array)); + for (int i = 0; i < 3; i++) + { + gF_LandingOrigin[GetNativeCell(1)][i] = array[i]; + } + + return 0; +} + +public int Native_SetLandingVelocity(Handle plugin, int numParams) +{ + float array[3]; + GetNativeArray(2, array, sizeof(array)); + for (int i = 0; i < 3; i++) + { + gF_LandingVelocity[GetNativeCell(1)][i] = array[i]; + } + + return 0; +} \ No newline at end of file diff --git a/source/sourcemod/scripting/movementapi/stocks.sp b/source/sourcemod/scripting/movementapi/stocks.sp new file mode 100644 index 0000000..e080efc --- /dev/null +++ b/source/sourcemod/scripting/movementapi/stocks.sp @@ -0,0 +1,200 @@ +stock void GameMove_SetVelocity(Address addr, float velocity[3]) +{ + if (velocity[0] != velocity[0] || velocity[1] != velocity[1] || velocity[2] != velocity[2]) + { + return; + } + static int mvOffset; + static int velocityOffset; + if (!mvOffset) + { + char buffer[8]; + if (!gH_GameData.GetKeyValue("CGameMovement::mv", buffer, sizeof(buffer))) + { + ThrowError("Failed to get CGameMovement::mv offset."); + return; + } + mvOffset = StringToInt(buffer); + if (!gH_GameData.GetKeyValue("CMoveData::m_vecVelocity", buffer, sizeof(buffer))) + { + ThrowError("Failed to get CMoveData::m_vecVelocity offset."); + return; + } + velocityOffset = StringToInt(buffer); + } + + Address mvAddress = view_as
(LoadFromAddress(view_as
(view_as(addr) + mvOffset), NumberType_Int32)); + // TODO: idk if raw cast works here or not + StoreToAddress(view_as
(view_as(mvAddress) + velocityOffset), view_as(velocity[0]), NumberType_Int32); + StoreToAddress(view_as
(view_as(mvAddress) + velocityOffset + 4), view_as(velocity[1]), NumberType_Int32); + StoreToAddress(view_as
(view_as(mvAddress) + velocityOffset + 8), view_as(velocity[2]), NumberType_Int32); +} + +stock void GameMove_SetOrigin(Address addr, float origin[3]) +{ + if (origin[0] != origin[0] || origin[1] != origin[1] || origin[2] != origin[2]) + { + return; + } + static int mvOffset; + static int originOffset; + if (!mvOffset) + { + char buffer[8]; + if (!gH_GameData.GetKeyValue("CGameMovement::mv", buffer, sizeof(buffer))) + { + ThrowError("Failed to get CGameMovement::mv offset."); + return; + } + mvOffset = StringToInt(buffer); + if (!gH_GameData.GetKeyValue("CMoveData::m_vecAbsOrigin", buffer, sizeof(buffer))) + { + ThrowError("Failed to get CMoveData::m_vecAbsOrigin offset."); + return; + } + originOffset = StringToInt(buffer); + } + + Address mvAddress = view_as
(LoadFromAddress(view_as
(view_as(addr) + mvOffset), NumberType_Int32)); + // TODO: idk if raw cast works here or not + StoreToAddress(view_as
(view_as(mvAddress) + originOffset), view_as(origin[0]), NumberType_Int32); + StoreToAddress(view_as
(view_as(mvAddress) + originOffset + 4), view_as(origin[1]), NumberType_Int32); + StoreToAddress(view_as
(view_as(mvAddress) + originOffset + 8), view_as(origin[2]), NumberType_Int32); +} + +stock void GameMove_GetVelocity(Address addr, float result[3]) +{ + static int mvOffset; + static int velocityOffset; + if (!mvOffset) + { + char buffer[8]; + if (!gH_GameData.GetKeyValue("CGameMovement::mv", buffer, sizeof(buffer))) + { + ThrowError("Failed to get CGameMovement::mv offset."); + return; + } + mvOffset = StringToInt(buffer); + if (!gH_GameData.GetKeyValue("CMoveData::m_vecVelocity", buffer, sizeof(buffer))) + { + ThrowError("Failed to get CMoveData::m_vecVelocity offset."); + return; + } + velocityOffset = StringToInt(buffer); + } + + Address mvAddress = view_as
(LoadFromAddress(view_as
(view_as(addr) + mvOffset), NumberType_Int32)); + result[0] = view_as(LoadFromAddress(view_as
(view_as(mvAddress) + velocityOffset), NumberType_Int32)); + result[1] = view_as(LoadFromAddress(view_as
(view_as(mvAddress) + velocityOffset + 4), NumberType_Int32)); + result[2] = view_as(LoadFromAddress(view_as
(view_as(mvAddress) + velocityOffset + 8), NumberType_Int32)); +} + +stock void GameMove_GetOrigin(Address addr, float result[3]) +{ + static int mvOffset; + static int originOffset; + if (!mvOffset) + { + char buffer[8]; + if (!gH_GameData.GetKeyValue("CGameMovement::mv", buffer, sizeof(buffer))) + { + ThrowError("Failed to get CGameMovement::mv offset."); + return; + } + mvOffset = StringToInt(buffer); + if (!gH_GameData.GetKeyValue("CMoveData::m_vecAbsOrigin", buffer, sizeof(buffer))) + { + ThrowError("Failed to get CMoveData::m_vecAbsOrigin offset."); + return; + } + originOffset = StringToInt(buffer); + } + + Address mvAddress = view_as
(LoadFromAddress(view_as
(view_as(addr) + mvOffset), NumberType_Int32)); + result[0] = view_as(LoadFromAddress(view_as
(view_as(mvAddress) + originOffset), NumberType_Int32)); + result[1] = view_as(LoadFromAddress(view_as
(view_as(mvAddress) + originOffset + 4), NumberType_Int32)); + result[2] = view_as(LoadFromAddress(view_as
(view_as(mvAddress) + originOffset + 8), NumberType_Int32)); +} + +stock void GameMove_GetEyeAngles(Address addr, float result[3]) +{ + static int mvOffset; + static int viewAngleOffset; + if (!mvOffset) + { + char buffer[8]; + if (!gH_GameData.GetKeyValue("CGameMovement::mv", buffer, sizeof(buffer))) + { + ThrowError("Failed to get CGameMovement::mv offset."); + return; + } + mvOffset = StringToInt(buffer); + if (!gH_GameData.GetKeyValue("CMoveData::m_viewAngleOffset", buffer, sizeof(buffer))) + { + ThrowError("Failed to get CMoveData::m_viewAngleOffset offset."); + return; + } + viewAngleOffset = StringToInt(buffer); + } + + Address mvAddress = view_as
(LoadFromAddress(view_as
(view_as(addr) + mvOffset), NumberType_Int32)); + result[0] = view_as(LoadFromAddress(view_as
(view_as(mvAddress) + viewAngleOffset), NumberType_Int32)); + result[1] = view_as(LoadFromAddress(view_as
(view_as(mvAddress) + viewAngleOffset + 4), NumberType_Int32)); + result[2] = view_as(LoadFromAddress(view_as
(view_as(mvAddress) + viewAngleOffset + 8), NumberType_Int32)); +} + +stock int GetEntityFromAddress(Address pEntity) { + static int offs_RefEHandle; + if (offs_RefEHandle) { + return EntRefToEntIndex(LoadFromAddress(pEntity + view_as
(offs_RefEHandle), NumberType_Int32) | (1 << 31)); + } + + // if we don't have it already, attempt to lookup offset based on SDK information + // CWorld is derived from CBaseEntity so it should have both offsets + int offs_angRotation = FindDataMapInfo(0, "m_angRotation"), + offs_vecViewOffset = FindDataMapInfo(0, "m_vecViewOffset"); + if (offs_angRotation == -1) { + ThrowError("Could not find offset for ((CBaseEntity) CWorld)::m_angRotation"); + } else if (offs_vecViewOffset == -1) { + ThrowError("Could not find offset for ((CBaseEntity) CWorld)::m_vecViewOffset"); + } else if ((offs_angRotation + 0x0C) != (offs_vecViewOffset - 0x04)) { + char game[32]; + GetGameFolderName(game, sizeof(game)); + ThrowError("Could not confirm offset of CBaseEntity::m_RefEHandle " + ... "(incorrect assumption for game '%s'?)", game); + } + + // offset seems right, cache it for the next call + offs_RefEHandle = offs_angRotation + 0x0C; + return GetEntityFromAddress(pEntity); +} + +stock int GetClientFromGameMovementAddress(Address addr) +{ + char buffer[8]; + if (!gH_GameData.GetKeyValue("CGameMovement::player", buffer, sizeof(buffer))) + { + ThrowError("Failed to get CGameMovement::player offset."); + return -1; + } + int offset = StringToInt(buffer); + Address playerAddr = view_as
(LoadFromAddress(view_as
(view_as(addr) + offset), NumberType_Int32)); + return GetEntityFromAddress(playerAddr); +} + +stock void HookGameMovementFunction(DynamicDetour handle, char[] fName, DHookCallback preCallback, DHookCallback postCallback) +{ + handle = DynamicDetour.FromConf(gH_GameData, fName); + if (!handle) + { + SetFailState("Failed to find %s config", fName); + } + if (!handle.Enable(Hook_Pre, preCallback)) + { + SetFailState("Failed to enable detour on %s", fName); + } + if (!handle.Enable(Hook_Post, postCallback)) + { + SetFailState("Failed to enable detour on %s", fName); + } +} -- cgit v1.2.3