summaryrefslogtreecommitdiff
path: root/sourcemod/scripting/gokz-core
diff options
context:
space:
mode:
Diffstat (limited to 'sourcemod/scripting/gokz-core')
-rw-r--r--sourcemod/scripting/gokz-core/commands.sp385
-rw-r--r--sourcemod/scripting/gokz-core/demofix.sp110
-rw-r--r--sourcemod/scripting/gokz-core/forwards.sp401
-rw-r--r--sourcemod/scripting/gokz-core/map/buttons.sp138
-rw-r--r--sourcemod/scripting/gokz-core/map/end.sp155
-rw-r--r--sourcemod/scripting/gokz-core/map/mapfile.sp502
-rw-r--r--sourcemod/scripting/gokz-core/map/prefix.sp48
-rw-r--r--sourcemod/scripting/gokz-core/map/starts.sp219
-rw-r--r--sourcemod/scripting/gokz-core/map/triggers.sp855
-rw-r--r--sourcemod/scripting/gokz-core/map/zones.sp183
-rw-r--r--sourcemod/scripting/gokz-core/menus/mode_menu.sp40
-rw-r--r--sourcemod/scripting/gokz-core/menus/options_menu.sp174
-rw-r--r--sourcemod/scripting/gokz-core/misc.sp803
-rw-r--r--sourcemod/scripting/gokz-core/modes.sp106
-rw-r--r--sourcemod/scripting/gokz-core/natives.sp647
-rw-r--r--sourcemod/scripting/gokz-core/options.sp438
-rw-r--r--sourcemod/scripting/gokz-core/teamnumfix.sp68
-rw-r--r--sourcemod/scripting/gokz-core/teleports.sp917
-rw-r--r--sourcemod/scripting/gokz-core/timer/pause.sp257
-rw-r--r--sourcemod/scripting/gokz-core/timer/timer.sp368
-rw-r--r--sourcemod/scripting/gokz-core/timer/virtual_buttons.sp322
-rw-r--r--sourcemod/scripting/gokz-core/triggerfix.sp622
22 files changed, 0 insertions, 7758 deletions
diff --git a/sourcemod/scripting/gokz-core/commands.sp b/sourcemod/scripting/gokz-core/commands.sp
deleted file mode 100644
index 6aba82c..0000000
--- a/sourcemod/scripting/gokz-core/commands.sp
+++ /dev/null
@@ -1,385 +0,0 @@
-void RegisterCommands()
-{
- RegConsoleCmd("sm_options", CommandOptions, "[KZ] Open the options menu.");
- RegConsoleCmd("sm_o", CommandOptions, "[KZ] Open the options menu.");
- RegConsoleCmd("sm_checkpoint", CommandMakeCheckpoint, "[KZ] Set a checkpoint.");
- RegConsoleCmd("sm_gocheck", CommandTeleportToCheckpoint, "[KZ] Teleport to your current checkpoint.");
- RegConsoleCmd("sm_prev", CommandPrevCheckpoint, "[KZ] Go back a checkpoint.");
- RegConsoleCmd("sm_next", CommandNextCheckpoint, "[KZ] Go forward a checkpoint.");
- RegConsoleCmd("sm_undo", CommandUndoTeleport, "[KZ] Undo teleport.");
- RegConsoleCmd("sm_start", CommandTeleportToStart, "[KZ] Teleport to the start.");
- RegConsoleCmd("sm_searchstart", CommandSearchStart, "[KZ] Teleport to the start zone/button of a specified course.");
- RegConsoleCmd("sm_end", CommandTeleportToEnd, "[KZ] Teleport to the end.");
- RegConsoleCmd("sm_restart", CommandTeleportToStart, "[KZ] Teleport to your start position.");
- RegConsoleCmd("sm_r", CommandTeleportToStart, "[KZ] Teleport to your start position.");
- RegConsoleCmd("sm_setstartpos", CommandSetStartPos, "[KZ] Set your custom start position to your current position.");
- RegConsoleCmd("sm_ssp", CommandSetStartPos, "[KZ] Set your custom start position to your current position.");
- RegConsoleCmd("sm_clearstartpos", CommandClearStartPos, "[KZ] Clear your custom start position.");
- RegConsoleCmd("sm_csp", CommandClearStartPos, "[KZ] Clear your custom start position.");
- RegConsoleCmd("sm_main", CommandMain, "[KZ] Teleport to the start of the main course.");
- RegConsoleCmd("sm_m", CommandMain, "[KZ] Teleport to the start of the main course.");
- RegConsoleCmd("sm_bonus", CommandBonus, "[KZ] Teleport to the start of a bonus. Usage: `!bonus <#bonus>");
- RegConsoleCmd("sm_b", CommandBonus, "[KZ] Teleport to the start of a bonus. Usage: `!b <#bonus>");
- RegConsoleCmd("sm_pause", CommandTogglePause, "[KZ] Toggle pausing your timer and stopping you in your position.");
- RegConsoleCmd("sm_resume", CommandTogglePause, "[KZ] Toggle pausing your timer and stopping you in your position.");
- RegConsoleCmd("sm_stop", CommandStopTimer, "[KZ] Stop your timer.");
- RegConsoleCmd("sm_virtualbuttonindicators", CommandToggleVirtualButtonIndicators, "[KZ] Toggle virtual button indicators.");
- RegConsoleCmd("sm_vbi", CommandToggleVirtualButtonIndicators, "[KZ] Toggle virtual button indicators.");
- RegConsoleCmd("sm_virtualbuttons", CommandToggleVirtualButtonsLock, "[KZ] Toggle locking virtual buttons, preventing them from being moved.");
- RegConsoleCmd("sm_vb", CommandToggleVirtualButtonsLock, "[KZ] Toggle locking virtual buttons, preventing them from being moved.");
- RegConsoleCmd("sm_mode", CommandMode, "[KZ] Open the movement mode selection menu.");
- RegConsoleCmd("sm_vanilla", CommandVanilla, "[KZ] Switch to the Vanilla mode.");
- RegConsoleCmd("sm_vnl", CommandVanilla, "[KZ] Switch to the Vanilla mode.");
- RegConsoleCmd("sm_v", CommandVanilla, "[KZ] Switch to the Vanilla mode.");
- RegConsoleCmd("sm_simplekz", CommandSimpleKZ, "[KZ] Switch to the SimpleKZ mode.");
- RegConsoleCmd("sm_skz", CommandSimpleKZ, "[KZ] Switch to the SimpleKZ mode.");
- RegConsoleCmd("sm_s", CommandSimpleKZ, "[KZ] Switch to the SimpleKZ mode.");
- RegConsoleCmd("sm_kztimer", CommandKZTimer, "[KZ] Switch to the KZTimer mode.");
- RegConsoleCmd("sm_kzt", CommandKZTimer, "[KZ] Switch to the KZTimer mode.");
- RegConsoleCmd("sm_k", CommandKZTimer, "[KZ] Switch to the KZTimer mode.");
- RegConsoleCmd("sm_nc", CommandToggleNoclip, "[KZ] Toggle noclip.");
- RegConsoleCmd("+noclip", CommandEnableNoclip, "[KZ] Noclip on.");
- RegConsoleCmd("-noclip", CommandDisableNoclip, "[KZ] Noclip off.");
- RegConsoleCmd("sm_ncnt", CommandToggleNoclipNotrigger, "[KZ] Toggle noclip-notrigger.");
- RegConsoleCmd("+noclipnt", CommandEnableNoclipNotrigger, "[KZ] Noclip-notrigger on.");
- RegConsoleCmd("-noclipnt", CommandDisableNoclipNotrigger, "[KZ] Noclip-notrigger off.");
- RegConsoleCmd("sm_sg", CommandNubSafeGuard, "[KZ] Toggle NUB safeguard.");
- RegConsoleCmd("sm_safe", CommandNubSafeGuard, "[KZ] Toggle NUB safeguard.");
- RegConsoleCmd("sm_safeguard", CommandNubSafeGuard, "[KZ] Toggle NUB safeguard.");
- RegConsoleCmd("sm_pro", CommandProSafeGuard, "[KZ] Toggle PRO safeguard.");
- RegConsoleCmd("kill", CommandKill);
- RegConsoleCmd("killvector", CommandKill);
- RegConsoleCmd("explode", CommandKill);
- RegConsoleCmd("explodevector", CommandKill);
-}
-
-void AddCommandsListeners()
-{
- AddCommandListener(CommandJoinTeam, "jointeam");
-}
-
-bool SwitchToModeIfAvailable(int client, int mode)
-{
- if (!GOKZ_GetModeLoaded(mode))
- {
- GOKZ_PrintToChat(client, true, "%t", "Mode Not Available", gC_ModeNames[mode]);
- return false;
- }
- else
- {
- // Safeguard Check
- if (GOKZ_GetCoreOption(client, Option_Safeguard) > Safeguard_Disabled && GOKZ_GetTimerRunning(client) && GOKZ_GetValidTimer(client))
- {
- GOKZ_PrintToChat(client, true, "%t", "Safeguard - Blocked");
- GOKZ_PlayErrorSound(client);
- return false;
- }
- GOKZ_SetCoreOption(client, Option_Mode, mode);
- return true;
- }
-}
-
-public Action CommandKill(int client, int args)
-{
- if (IsPlayerAlive(client) && GOKZ_GetCoreOption(client, Option_Safeguard) > Safeguard_Disabled && GOKZ_GetTimerRunning(client) && GOKZ_GetValidTimer(client))
- {
- GOKZ_PrintToChat(client, true, "%t", "Safeguard - Blocked");
- GOKZ_PlayErrorSound(client);
- return Plugin_Handled;
- }
- return Plugin_Continue;
-}
-
-public Action CommandOptions(int client, int args)
-{
- DisplayOptionsMenu(client);
- return Plugin_Handled;
-}
-
-public Action CommandJoinTeam(int client, const char[] command, int argc)
-{
- char teamString[4];
- GetCmdArgString(teamString, sizeof(teamString));
- int team = StringToInt(teamString);
-
- if (team == CS_TEAM_SPECTATOR)
- {
- if (!GOKZ_GetPaused(client) && !GOKZ_GetCanPause(client))
- {
- SendFakeTeamEvent(client);
- return Plugin_Handled;
- }
- }
- else if (IsPlayerAlive(client) && GOKZ_GetCoreOption(client, Option_Safeguard) > Safeguard_Disabled && GOKZ_GetTimerRunning(client) && GOKZ_GetValidTimer(client))
- {
- GOKZ_PrintToChat(client, true, "%t", "Safeguard - Blocked");
- GOKZ_PlayErrorSound(client);
- SendFakeTeamEvent(client);
- return Plugin_Handled;
- }
- GOKZ_JoinTeam(client, team);
- return Plugin_Handled;
-}
-
-public Action CommandMakeCheckpoint(int client, int args)
-{
- GOKZ_MakeCheckpoint(client);
- return Plugin_Handled;
-}
-
-public Action CommandTeleportToCheckpoint(int client, int args)
-{
- GOKZ_TeleportToCheckpoint(client);
- return Plugin_Handled;
-}
-
-public Action CommandPrevCheckpoint(int client, int args)
-{
- GOKZ_PrevCheckpoint(client);
- return Plugin_Handled;
-}
-
-public Action CommandNextCheckpoint(int client, int args)
-{
- GOKZ_NextCheckpoint(client);
- return Plugin_Handled;
-}
-
-public Action CommandUndoTeleport(int client, int args)
-{
- GOKZ_UndoTeleport(client);
- return Plugin_Handled;
-}
-
-public Action CommandTeleportToStart(int client, int args)
-{
- GOKZ_TeleportToStart(client);
- return Plugin_Handled;
-}
-
-public Action CommandSearchStart(int client, int args)
-{
- if (args == 0)
- {
- GOKZ_TeleportToSearchStart(client, GetCurrentCourse(client));
- return Plugin_Handled;
- }
- else
- {
- char argCourse[4];
- GetCmdArg(1, argCourse, sizeof(argCourse));
- int course = StringToInt(argCourse);
- if (GOKZ_IsValidCourse(course, false))
- {
- GOKZ_TeleportToSearchStart(client, course);
- }
- else if (StrEqual(argCourse, "main", false) || course == 0)
- {
- GOKZ_TeleportToSearchStart(client, 0);
- }
- else
- {
- GOKZ_PrintToChat(client, true, "%t", "Invalid Course Number", argCourse);
- }
- }
- return Plugin_Handled;
-}
-
-public Action CommandTeleportToEnd(int client, int args)
-{
- if (args == 0)
- {
- GOKZ_TeleportToEnd(client, GetCurrentCourse(client));
- }
- else
- {
- char argCourse[4];
- GetCmdArg(1, argCourse, sizeof(argCourse));
- int course = StringToInt(argCourse);
- if (GOKZ_IsValidCourse(course, false))
- {
- GOKZ_TeleportToEnd(client, course);
- }
- else if (StrEqual(argCourse, "main", false) || course == 0)
- {
- GOKZ_TeleportToEnd(client, 0);
- }
- else
- {
- GOKZ_PrintToChat(client, true, "%t", "Invalid Course Number", argCourse);
- }
- }
- return Plugin_Handled;
-}
-
-public Action CommandSetStartPos(int client, int args)
-{
- SetStartPositionToCurrent(client, StartPositionType_Custom);
-
- GOKZ_PrintToChat(client, true, "%t", "Set Custom Start Position");
- if (GOKZ_GetCoreOption(client, Option_CheckpointSounds) == CheckpointSounds_Enabled)
- {
- GOKZ_EmitSoundToClient(client, GOKZ_SOUND_CHECKPOINT, _, "Set Start Position");
- }
-
- return Plugin_Handled;
-}
-
-public Action CommandClearStartPos(int client, int args)
-{
- if (ClearCustomStartPosition(client))
- {
- GOKZ_PrintToChat(client, true, "%t", "Cleared Custom Start Position");
- }
-
- return Plugin_Handled;
-}
-
-public Action CommandMain(int client, int args)
-{
- TeleportToCourseStart(client, 0);
- return Plugin_Handled;
-}
-
-public Action CommandBonus(int client, int args)
-{
- if (args == 0)
- { // Go to Bonus 1
- TeleportToCourseStart(client, 1);
- }
- else
- { // Go to specified Bonus #
- char argBonus[4];
- GetCmdArg(1, argBonus, sizeof(argBonus));
- int bonus = StringToInt(argBonus);
- if (GOKZ_IsValidCourse(bonus, true))
- {
- TeleportToCourseStart(client, bonus);
- }
- else
- {
- GOKZ_PrintToChat(client, true, "%t", "Invalid Bonus Number", argBonus);
- }
- }
- return Plugin_Handled;
-}
-
-public Action CommandTogglePause(int client, int args)
-{
- if (!IsPlayerAlive(client))
- {
- GOKZ_RespawnPlayer(client);
- }
- else
- {
- TogglePause(client);
- }
- return Plugin_Handled;
-}
-
-public Action CommandStopTimer(int client, int args)
-{
- if (TimerStop(client))
- {
- GOKZ_PrintToChat(client, true, "%t", "Timer Stopped");
- }
- return Plugin_Handled;
-}
-
-public Action CommandToggleVirtualButtonIndicators(int client, int args)
-{
- if (GOKZ_GetCoreOption(client, Option_VirtualButtonIndicators) == VirtualButtonIndicators_Disabled)
- {
- GOKZ_SetCoreOption(client, Option_VirtualButtonIndicators, VirtualButtonIndicators_Enabled);
- }
- else
- {
- GOKZ_SetCoreOption(client, Option_VirtualButtonIndicators, VirtualButtonIndicators_Disabled);
- }
- return Plugin_Handled;
-}
-
-public Action CommandToggleVirtualButtonsLock(int client, int args)
-{
- if (ToggleVirtualButtonsLock(client))
- {
- GOKZ_PrintToChat(client, true, "%t", "Locked Virtual Buttons");
- }
- else
- {
- GOKZ_PrintToChat(client, true, "%t", "Unlocked Virtual Buttons");
- }
- return Plugin_Handled;
-}
-
-public Action CommandMode(int client, int args)
-{
- DisplayModeMenu(client);
- return Plugin_Handled;
-}
-
-public Action CommandVanilla(int client, int args)
-{
- SwitchToModeIfAvailable(client, Mode_Vanilla);
- return Plugin_Handled;
-}
-
-public Action CommandSimpleKZ(int client, int args)
-{
- SwitchToModeIfAvailable(client, Mode_SimpleKZ);
- return Plugin_Handled;
-}
-
-public Action CommandKZTimer(int client, int args)
-{
- SwitchToModeIfAvailable(client, Mode_KZTimer);
- return Plugin_Handled;
-}
-
-public Action CommandToggleNoclip(int client, int args)
-{
- ToggleNoclip(client);
- return Plugin_Handled;
-}
-
-public Action CommandEnableNoclip(int client, int args)
-{
- EnableNoclip(client);
- return Plugin_Handled;
-}
-
-public Action CommandDisableNoclip(int client, int args)
-{
- DisableNoclip(client);
- return Plugin_Handled;
-}
-
-public Action CommandToggleNoclipNotrigger(int client, int args)
-{
- ToggleNoclipNotrigger(client);
- return Plugin_Handled;
-}
-
-public Action CommandEnableNoclipNotrigger(int client, int args)
-{
- EnableNoclipNotrigger(client);
- return Plugin_Handled;
-}
-
-public Action CommandDisableNoclipNotrigger(int client, int args)
-{
- DisableNoclipNotrigger(client);
- return Plugin_Handled;
-}
-
-public Action CommandNubSafeGuard(int client, int args)
-{
- ToggleNubSafeGuard(client);
- return Plugin_Handled;
-}
-
-public Action CommandProSafeGuard(int client, int args)
-{
- ToggleProSafeGuard(client);
- return Plugin_Handled;
-} \ No newline at end of file
diff --git a/sourcemod/scripting/gokz-core/demofix.sp b/sourcemod/scripting/gokz-core/demofix.sp
deleted file mode 100644
index 84a9307..0000000
--- a/sourcemod/scripting/gokz-core/demofix.sp
+++ /dev/null
@@ -1,110 +0,0 @@
-static ConVar CV_EnableDemofix;
-static Handle H_DemofixTimer;
-static bool mapRunning;
-
-void OnPluginStart_Demofix()
-{
- AddCommandListener(Command_Demorestart, "demorestart");
- 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);
- // We assume that the map is already loaded on late load.
- if (gB_LateLoad)
- {
- mapRunning = true;
- }
-}
-
-void OnMapStart_Demofix()
-{
- mapRunning = true;
-}
-
-void OnMapEnd_Demofix()
-{
- mapRunning = false;
-}
-
-void OnRoundStart_Demofix()
-{
- DoDemoFix();
-}
-
-public Action Command_Demorestart(int client, const char[] command, int argc)
-{
- FixRecord(client);
- return Plugin_Continue;
-}
-
-static void FixRecord(int client)
-{
- // For some reasons, demo playback speed is absolute trash without a round_start event.
- // So whenever the client starts recording a demo, we create the event and send it to them.
- Event e = CreateEvent("round_start", true);
- int timelimit = FindConVar("mp_timelimit").IntValue;
- e.SetInt("timelimit", timelimit);
- e.SetInt("fraglimit", 0);
- e.SetString("objective", "demofix");
-
- e.FireToClient(client);
- delete e;
-}
-
-public void OnDemofixConVarChanged(ConVar convar, const char[] oldValue, const char[] newValue)
-{
- DoDemoFix();
-}
-
-public Action Timer_EnableDemoRecord(Handle timer)
-{
- EnableDemoRecord();
- return Plugin_Continue;
-}
-
-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/sourcemod/scripting/gokz-core/forwards.sp b/sourcemod/scripting/gokz-core/forwards.sp
deleted file mode 100644
index efb064f..0000000
--- a/sourcemod/scripting/gokz-core/forwards.sp
+++ /dev/null
@@ -1,401 +0,0 @@
-static GlobalForward H_OnOptionsLoaded;
-static GlobalForward H_OnOptionChanged;
-static GlobalForward H_OnTimerStart;
-static GlobalForward H_OnTimerStart_Post;
-static GlobalForward H_OnTimerEnd;
-static GlobalForward H_OnTimerEnd_Post;
-static GlobalForward H_OnTimerEndMessage;
-static GlobalForward H_OnTimerStopped;
-static GlobalForward H_OnPause;
-static GlobalForward H_OnPause_Post;
-static GlobalForward H_OnResume;
-static GlobalForward H_OnResume_Post;
-static GlobalForward H_OnMakeCheckpoint;
-static GlobalForward H_OnMakeCheckpoint_Post;
-static GlobalForward H_OnTeleportToCheckpoint;
-static GlobalForward H_OnTeleportToCheckpoint_Post;
-static GlobalForward H_OnTeleport;
-static GlobalForward H_OnPrevCheckpoint;
-static GlobalForward H_OnPrevCheckpoint_Post;
-static GlobalForward H_OnNextCheckpoint;
-static GlobalForward H_OnNextCheckpoint_Post;
-static GlobalForward H_OnTeleportToStart;
-static GlobalForward H_OnTeleportToStart_Post;
-static GlobalForward H_OnTeleportToEnd;
-static GlobalForward H_OnTeleportToEnd_Post;
-static GlobalForward H_OnUndoTeleport;
-static GlobalForward H_OnUndoTeleport_Post;
-static GlobalForward H_OnCountedTeleport_Post;
-static GlobalForward H_OnStartPositionSet_Post;
-static GlobalForward H_OnJumpValidated;
-static GlobalForward H_OnJumpInvalidated;
-static GlobalForward H_OnJoinTeam;
-static GlobalForward H_OnFirstSpawn;
-static GlobalForward H_OnModeLoaded;
-static GlobalForward H_OnModeUnloaded;
-static GlobalForward H_OnTimerNativeCalledExternally;
-static GlobalForward H_OnOptionsMenuCreated;
-static GlobalForward H_OnOptionsMenuReady;
-static GlobalForward H_OnCourseRegistered;
-static GlobalForward H_OnRunInvalidated;
-static GlobalForward H_OnEmitSoundToClient;
-
-void CreateGlobalForwards()
-{
- H_OnOptionsLoaded = new GlobalForward("GOKZ_OnOptionsLoaded", ET_Ignore, Param_Cell);
- H_OnOptionChanged = new GlobalForward("GOKZ_OnOptionChanged", ET_Ignore, Param_Cell, Param_String, Param_Cell);
- H_OnTimerStart = new GlobalForward("GOKZ_OnTimerStart", ET_Hook, Param_Cell, Param_Cell);
- H_OnTimerStart_Post = new GlobalForward("GOKZ_OnTimerStart_Post", ET_Ignore, Param_Cell, Param_Cell);
- H_OnTimerEnd = new GlobalForward("GOKZ_OnTimerEnd", ET_Hook, Param_Cell, Param_Cell, Param_Float, Param_Cell);
- H_OnTimerEnd_Post = new GlobalForward("GOKZ_OnTimerEnd_Post", ET_Ignore, Param_Cell, Param_Cell, Param_Float, Param_Cell);
- H_OnTimerEndMessage = new GlobalForward("GOKZ_OnTimerEndMessage", ET_Hook, Param_Cell, Param_Cell, Param_Float, Param_Cell);
- H_OnTimerStopped = new GlobalForward("GOKZ_OnTimerStopped", ET_Ignore, Param_Cell);
- H_OnPause = new GlobalForward("GOKZ_OnPause", ET_Hook, Param_Cell);
- H_OnPause_Post = new GlobalForward("GOKZ_OnPause_Post", ET_Ignore, Param_Cell);
- H_OnResume = new GlobalForward("GOKZ_OnResume", ET_Hook, Param_Cell);
- H_OnResume_Post = new GlobalForward("GOKZ_OnResume_Post", ET_Ignore, Param_Cell);
- H_OnMakeCheckpoint = new GlobalForward("GOKZ_OnMakeCheckpoint", ET_Hook, Param_Cell);
- H_OnMakeCheckpoint_Post = new GlobalForward("GOKZ_OnMakeCheckpoint_Post", ET_Ignore, Param_Cell);
- H_OnTeleportToCheckpoint = new GlobalForward("GOKZ_OnTeleportToCheckpoint", ET_Hook, Param_Cell);
- H_OnTeleportToCheckpoint_Post = new GlobalForward("GOKZ_OnTeleportToCheckpoint_Post", ET_Ignore, Param_Cell);
- H_OnTeleport = new GlobalForward("GOKZ_OnTeleport", ET_Hook, Param_Cell);
- H_OnPrevCheckpoint = new GlobalForward("GOKZ_OnPrevCheckpoint", ET_Hook, Param_Cell);
- H_OnPrevCheckpoint_Post = new GlobalForward("GOKZ_OnPrevCheckpoint_Post", ET_Ignore, Param_Cell);
- H_OnNextCheckpoint = new GlobalForward("GOKZ_OnNextCheckpoint", ET_Hook, Param_Cell);
- H_OnNextCheckpoint_Post = new GlobalForward("GOKZ_OnNextCheckpoint_Post", ET_Ignore, Param_Cell);
- H_OnTeleportToStart = new GlobalForward("GOKZ_OnTeleportToStart", ET_Hook, Param_Cell, Param_Cell);
- H_OnTeleportToStart_Post = new GlobalForward("GOKZ_OnTeleportToStart_Post", ET_Ignore, Param_Cell, Param_Cell);
- H_OnTeleportToEnd = new GlobalForward("GOKZ_OnTeleportToEnd", ET_Hook, Param_Cell, Param_Cell);
- H_OnTeleportToEnd_Post = new GlobalForward("GOKZ_OnTeleportToEnd_Post", ET_Ignore, Param_Cell, Param_Cell);
- H_OnUndoTeleport = new GlobalForward("GOKZ_OnUndoTeleport", ET_Hook, Param_Cell);
- H_OnUndoTeleport_Post = new GlobalForward("GOKZ_OnUndoTeleport_Post", ET_Ignore, Param_Cell);
- H_OnStartPositionSet_Post = new GlobalForward("GOKZ_OnStartPositionSet_Post", ET_Ignore, Param_Cell, Param_Cell, Param_Array, Param_Array);
- H_OnCountedTeleport_Post = new GlobalForward("GOKZ_OnCountedTeleport_Post", ET_Ignore, Param_Cell);
- H_OnJumpValidated = new GlobalForward("GOKZ_OnJumpValidated", ET_Ignore, Param_Cell, Param_Cell, Param_Cell, Param_Cell);
- H_OnJumpInvalidated = new GlobalForward("GOKZ_OnJumpInvalidated", ET_Ignore, Param_Cell);
- H_OnJoinTeam = new GlobalForward("GOKZ_OnJoinTeam", ET_Ignore, Param_Cell, Param_Cell);
- H_OnFirstSpawn = new GlobalForward("GOKZ_OnFirstSpawn", ET_Ignore, Param_Cell);
- H_OnModeLoaded = new GlobalForward("GOKZ_OnModeLoaded", ET_Ignore, Param_Cell);
- H_OnModeUnloaded = new GlobalForward("GOKZ_OnModeUnloaded", ET_Ignore, Param_Cell);
- H_OnTimerNativeCalledExternally = new GlobalForward("GOKZ_OnTimerNativeCalledExternally", ET_Event, Param_Cell, Param_Cell);
- H_OnOptionsMenuCreated = new GlobalForward("GOKZ_OnOptionsMenuCreated", ET_Ignore, Param_Cell);
- H_OnOptionsMenuReady = new GlobalForward("GOKZ_OnOptionsMenuReady", ET_Ignore, Param_Cell);
- H_OnCourseRegistered = new GlobalForward("GOKZ_OnCourseRegistered", ET_Ignore, Param_Cell);
- H_OnRunInvalidated = new GlobalForward("GOKZ_OnRunInvalidated", ET_Ignore, Param_Cell);
- H_OnEmitSoundToClient = new GlobalForward("GOKZ_OnEmitSoundToClient", ET_Hook, Param_Cell, Param_String, Param_FloatByRef, Param_String);
-}
-
-void Call_GOKZ_OnOptionsLoaded(int client)
-{
- Call_StartForward(H_OnOptionsLoaded);
- Call_PushCell(client);
- Call_Finish();
-}
-
-void Call_GOKZ_OnOptionChanged(int client, const char[] option, int optionValue)
-{
- Call_StartForward(H_OnOptionChanged);
- Call_PushCell(client);
- Call_PushString(option);
- Call_PushCell(optionValue);
- Call_Finish();
-}
-
-void Call_GOKZ_OnTimerStart(int client, int course, Action &result)
-{
- Call_StartForward(H_OnTimerStart);
- Call_PushCell(client);
- Call_PushCell(course);
- Call_Finish(result);
-}
-
-void Call_GOKZ_OnTimerStart_Post(int client, int course)
-{
- Call_StartForward(H_OnTimerStart_Post);
- Call_PushCell(client);
- Call_PushCell(course);
- Call_Finish();
-}
-
-void Call_GOKZ_OnTimerEnd(int client, int course, float time, int teleportsUsed, Action &result)
-{
- Call_StartForward(H_OnTimerEnd);
- Call_PushCell(client);
- Call_PushCell(course);
- Call_PushFloat(time);
- Call_PushCell(teleportsUsed);
- Call_Finish(result);
-}
-
-void Call_GOKZ_OnTimerEnd_Post(int client, int course, float time, int teleportsUsed)
-{
- Call_StartForward(H_OnTimerEnd_Post);
- Call_PushCell(client);
- Call_PushCell(course);
- Call_PushFloat(time);
- Call_PushCell(teleportsUsed);
- Call_Finish();
-}
-
-void Call_GOKZ_OnTimerEndMessage(int client, int course, float time, int teleportsUsed, Action &result)
-{
- Call_StartForward(H_OnTimerEndMessage);
- Call_PushCell(client);
- Call_PushCell(course);
- Call_PushFloat(time);
- Call_PushCell(teleportsUsed);
- Call_Finish(result);
-}
-
-void Call_GOKZ_OnTimerStopped(int client)
-{
- Call_StartForward(H_OnTimerStopped);
- Call_PushCell(client);
- Call_Finish();
-}
-
-void Call_GOKZ_OnPause(int client, Action &result)
-{
- Call_StartForward(H_OnPause);
- Call_PushCell(client);
- Call_Finish(result);
-}
-
-void Call_GOKZ_OnPause_Post(int client)
-{
- Call_StartForward(H_OnPause_Post);
- Call_PushCell(client);
- Call_Finish();
-}
-
-void Call_GOKZ_OnResume(int client, Action &result)
-{
- Call_StartForward(H_OnResume);
- Call_PushCell(client);
- Call_Finish(result);
-}
-
-void Call_GOKZ_OnResume_Post(int client)
-{
- Call_StartForward(H_OnResume_Post);
- Call_PushCell(client);
- Call_Finish();
-}
-
-void Call_GOKZ_OnMakeCheckpoint(int client, Action &result)
-{
- Call_StartForward(H_OnMakeCheckpoint);
- Call_PushCell(client);
- Call_Finish(result);
-}
-
-void Call_GOKZ_OnMakeCheckpoint_Post(int client)
-{
- Call_StartForward(H_OnMakeCheckpoint_Post);
- Call_PushCell(client);
- Call_Finish();
-}
-
-void Call_GOKZ_OnTeleportToCheckpoint(int client, Action &result)
-{
- Call_StartForward(H_OnTeleportToCheckpoint);
- Call_PushCell(client);
- Call_Finish(result);
-}
-
-void Call_GOKZ_OnTeleportToCheckpoint_Post(int client)
-{
- Call_StartForward(H_OnTeleportToCheckpoint_Post);
- Call_PushCell(client);
- Call_Finish();
-}
-
-void Call_GOKZ_OnTeleport(int client)
-{
- Call_StartForward(H_OnTeleport);
- Call_PushCell(client);
- Call_Finish();
-}
-
-void Call_GOKZ_OnPrevCheckpoint(int client, Action &result)
-{
- Call_StartForward(H_OnPrevCheckpoint);
- Call_PushCell(client);
- Call_Finish(result);
-}
-
-void Call_GOKZ_OnPrevCheckpoint_Post(int client)
-{
- Call_StartForward(H_OnPrevCheckpoint_Post);
- Call_PushCell(client);
- Call_Finish();
-}
-
-void Call_GOKZ_OnNextCheckpoint(int client, Action &result)
-{
- Call_StartForward(H_OnNextCheckpoint);
- Call_PushCell(client);
- Call_Finish(result);
-}
-
-void Call_GOKZ_OnNextCheckpoint_Post(int client)
-{
- Call_StartForward(H_OnNextCheckpoint_Post);
- Call_PushCell(client);
- Call_Finish();
-}
-
-void Call_GOKZ_OnTeleportToStart(int client, int course, Action &result)
-{
- Call_StartForward(H_OnTeleportToStart);
- Call_PushCell(client);
- Call_PushCell(course);
- Call_Finish(result);
-}
-
-void Call_GOKZ_OnTeleportToStart_Post(int client, int course)
-{
- Call_StartForward(H_OnTeleportToStart_Post);
- Call_PushCell(client);
- Call_PushCell(course);
- Call_Finish();
-}
-
-void Call_GOKZ_OnTeleportToEnd(int client, int course, Action &result)
-{
- Call_StartForward(H_OnTeleportToEnd);
- Call_PushCell(client);
- Call_PushCell(course);
- Call_Finish(result);
-}
-
-void Call_GOKZ_OnTeleportToEnd_Post(int client, int course)
-{
- Call_StartForward(H_OnTeleportToEnd_Post);
- Call_PushCell(client);
- Call_PushCell(course);
- Call_Finish();
-}
-
-void Call_GOKZ_OnUndoTeleport(int client, Action &result)
-{
- Call_StartForward(H_OnUndoTeleport);
- Call_PushCell(client);
- Call_Finish(result);
-}
-
-void Call_GOKZ_OnUndoTeleport_Post(int client)
-{
- Call_StartForward(H_OnUndoTeleport_Post);
- Call_PushCell(client);
- Call_Finish();
-}
-
-void Call_GOKZ_OnCountedTeleport_Post(int client)
-{
- Call_StartForward(H_OnCountedTeleport_Post);
- Call_PushCell(client);
- Call_Finish();
-}
-
-void Call_GOKZ_OnStartPositionSet_Post(int client, StartPositionType type, const float origin[3], const float angles[3])
-{
- Call_StartForward(H_OnStartPositionSet_Post);
- Call_PushCell(client);
- Call_PushCell(type);
- Call_PushArray(origin, 3);
- Call_PushArray(angles, 3);
- Call_Finish();
-}
-
-void Call_GOKZ_OnJumpValidated(int client, bool jumped, bool ladderJump, bool jumpbug)
-{
- Call_StartForward(H_OnJumpValidated);
- Call_PushCell(client);
- Call_PushCell(jumped);
- Call_PushCell(ladderJump);
- Call_PushCell(jumpbug);
- Call_Finish();
-}
-
-void Call_GOKZ_OnJumpInvalidated(int client)
-{
- Call_StartForward(H_OnJumpInvalidated);
- Call_PushCell(client);
- Call_Finish();
-}
-
-void Call_GOKZ_OnJoinTeam(int client, int team)
-{
- Call_StartForward(H_OnJoinTeam);
- Call_PushCell(client);
- Call_PushCell(team);
- Call_Finish();
-}
-
-void Call_GOKZ_OnFirstSpawn(int client)
-{
- Call_StartForward(H_OnFirstSpawn);
- Call_PushCell(client);
- Call_Finish();
-}
-
-void Call_GOKZ_OnModeLoaded(int mode)
-{
- Call_StartForward(H_OnModeLoaded);
- Call_PushCell(mode);
- Call_Finish();
-}
-
-void Call_GOKZ_OnModeUnloaded(int mode)
-{
- Call_StartForward(H_OnModeUnloaded);
- Call_PushCell(mode);
- Call_Finish();
-}
-
-void Call_GOKZ_OnTimerNativeCalledExternally(Handle plugin, int client, Action &result)
-{
- Call_StartForward(H_OnTimerNativeCalledExternally);
- Call_PushCell(plugin);
- Call_PushCell(client);
- Call_Finish(result);
-}
-
-void Call_GOKZ_OnOptionsMenuCreated(TopMenu topMenu)
-{
- Call_StartForward(H_OnOptionsMenuCreated);
- Call_PushCell(topMenu);
- Call_Finish();
-}
-
-void Call_GOKZ_OnOptionsMenuReady(TopMenu topMenu)
-{
- Call_StartForward(H_OnOptionsMenuReady);
- Call_PushCell(topMenu);
- Call_Finish();
-}
-
-void Call_GOKZ_OnCourseRegistered(int course)
-{
- Call_StartForward(H_OnCourseRegistered);
- Call_PushCell(course);
- Call_Finish();
-}
-
-void Call_GOKZ_OnRunInvalidated(int client)
-{
- Call_StartForward(H_OnRunInvalidated);
- Call_PushCell(client);
- Call_Finish();
-}
-
-void Call_GOKZ_OnEmitSoundToClient(int client, const char[] sample, float &volume, const char[] description, Action &result)
-{
- Call_StartForward(H_OnEmitSoundToClient);
- Call_PushCell(client);
- Call_PushString(sample);
- Call_PushFloatRef(volume);
- Call_PushString(description);
- Call_Finish(result);
-} \ No newline at end of file
diff --git a/sourcemod/scripting/gokz-core/map/buttons.sp b/sourcemod/scripting/gokz-core/map/buttons.sp
deleted file mode 100644
index 8923fbd..0000000
--- a/sourcemod/scripting/gokz-core/map/buttons.sp
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- Hooks between specifically named func_buttons and GOKZ.
-*/
-
-
-
-static Regex RE_BonusStartButton;
-static Regex RE_BonusEndButton;
-
-
-
-// =====[ EVENTS ]=====
-
-void OnPluginStart_MapButtons()
-{
- RE_BonusStartButton = CompileRegex(GOKZ_BONUS_START_BUTTON_NAME_REGEX);
- RE_BonusEndButton = CompileRegex(GOKZ_BONUS_END_BUTTON_NAME_REGEX);
-}
-
-void OnEntitySpawned_MapButtons(int entity)
-{
- char buffer[32];
-
- GetEntityClassname(entity, buffer, sizeof(buffer));
- if (!StrEqual("func_button", buffer, false))
- {
- return;
- }
-
- if (GetEntityName(entity, buffer, sizeof(buffer)) == 0)
- {
- return;
- }
-
- int course = 0;
- if (StrEqual(GOKZ_START_BUTTON_NAME, buffer, false))
- {
- HookSingleEntityOutput(entity, "OnPressed", OnStartButtonPress);
- RegisterCourseStart(course);
- }
- else if (StrEqual(GOKZ_END_BUTTON_NAME, buffer, false))
- {
- HookSingleEntityOutput(entity, "OnPressed", OnEndButtonPress);
- RegisterCourseEnd(course);
- }
- else if ((course = GetStartButtonBonusNumber(entity)) != -1)
- {
- HookSingleEntityOutput(entity, "OnPressed", OnBonusStartButtonPress);
- RegisterCourseStart(course);
- }
- else if ((course = GetEndButtonBonusNumber(entity)) != -1)
- {
- HookSingleEntityOutput(entity, "OnPressed", OnBonusEndButtonPress);
- RegisterCourseEnd(course);
- }
-}
-
-public void OnStartButtonPress(const char[] name, int caller, int activator, float delay)
-{
- if (!IsValidEntity(caller) || !IsValidClient(activator))
- {
- return;
- }
-
- ProcessStartButtonPress(activator, 0);
-}
-
-public void OnEndButtonPress(const char[] name, int caller, int activator, float delay)
-{
- if (!IsValidEntity(caller) || !IsValidClient(activator))
- {
- return;
- }
-
- ProcessEndButtonPress(activator, 0);
-}
-
-public void OnBonusStartButtonPress(const char[] name, int caller, int activator, float delay)
-{
- if (!IsValidEntity(caller) || !IsValidClient(activator))
- {
- return;
- }
-
- int course = GetStartButtonBonusNumber(caller);
- if (!GOKZ_IsValidCourse(course, true))
- {
- return;
- }
-
- ProcessStartButtonPress(activator, course);
-}
-
-public void OnBonusEndButtonPress(const char[] name, int caller, int activator, float delay)
-{
- if (!IsValidEntity(caller) || !IsValidClient(activator))
- {
- return;
- }
-
- int course = GetEndButtonBonusNumber(caller);
- if (!GOKZ_IsValidCourse(course, true))
- {
- return;
- }
-
- ProcessEndButtonPress(activator, course);
-}
-
-
-
-// =====[ PRIVATE ]=====
-
-static void ProcessStartButtonPress(int client, int course)
-{
- if (GOKZ_StartTimer(client, course))
- {
- // Only calling on success is intended behaviour (and prevents virtual button exploits)
- OnStartButtonPress_Teleports(client, course);
- OnStartButtonPress_VirtualButtons(client, course);
- }
-}
-
-static void ProcessEndButtonPress(int client, int course)
-{
- GOKZ_EndTimer(client, course);
- OnEndButtonPress_VirtualButtons(client, course);
-}
-
-static int GetStartButtonBonusNumber(int entity)
-{
- return GOKZ_MatchIntFromEntityName(entity, RE_BonusStartButton, 1);
-}
-
-static int GetEndButtonBonusNumber(int entity)
-{
- return GOKZ_MatchIntFromEntityName(entity, RE_BonusEndButton, 1);
-} \ No newline at end of file
diff --git a/sourcemod/scripting/gokz-core/map/end.sp b/sourcemod/scripting/gokz-core/map/end.sp
deleted file mode 100644
index d119084..0000000
--- a/sourcemod/scripting/gokz-core/map/end.sp
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- Hooks between specifically named end destinations and GOKZ
-*/
-
-
-
-static Regex RE_BonusEndButton;
-static Regex RE_BonusEndZone;
-static CourseTimerType endType[GOKZ_MAX_COURSES];
-static float endOrigin[GOKZ_MAX_COURSES][3];
-static float endAngles[GOKZ_MAX_COURSES][3];
-
-
-
-// =====[ EVENTS ]=====
-
-void OnPluginStart_MapEnd()
-{
- RE_BonusEndButton = CompileRegex(GOKZ_BONUS_END_BUTTON_NAME_REGEX);
- RE_BonusEndZone = CompileRegex(GOKZ_BONUS_END_ZONE_NAME_REGEX);
-}
-
-void OnEntitySpawnedPost_MapEnd(int entity)
-{
- char buffer[32];
-
- GetEntityClassname(entity, buffer, sizeof(buffer));
-
- if (StrEqual("trigger_multiple", buffer, false))
- {
- bool isEndZone;
- if (GetEntityName(entity, buffer, sizeof(buffer)) != 0)
- {
- if (StrEqual(GOKZ_END_ZONE_NAME, buffer, false))
- {
- isEndZone = true;
- StoreEnd(0, entity, CourseTimerType_ZoneNew);
- }
- else if (GetEndZoneBonusNumber(entity) != -1)
- {
- int course = GetEndZoneBonusNumber(entity);
- if (GOKZ_IsValidCourse(course, true))
- {
- isEndZone = true;
- StoreEnd(course, entity, CourseTimerType_ZoneNew);
- }
- }
- }
- if (!isEndZone)
- {
- TimerButtonTrigger trigger;
- if (IsTimerButtonTrigger(entity, trigger) && !trigger.isStartTimer)
- {
- StoreEnd(trigger.course, entity, CourseTimerType_ZoneLegacy);
- }
- }
- }
- else if (StrEqual("func_button", buffer, false))
- {
- bool isEndButton;
- if (GetEntityName(entity, buffer, sizeof(buffer)) != 0)
- {
- if (StrEqual(GOKZ_END_BUTTON_NAME, buffer, false))
- {
- isEndButton = true;
- StoreEnd(0, entity, CourseTimerType_Button);
- }
- else
- {
- int course = GetEndButtonBonusNumber(entity);
- if (GOKZ_IsValidCourse(course, true))
- {
- isEndButton = true;
- StoreEnd(course, entity, CourseTimerType_Button);
- }
- }
- }
- if (!isEndButton)
- {
- TimerButtonTrigger trigger;
- if (IsTimerButtonTrigger(entity, trigger) && !trigger.isStartTimer)
- {
- StoreEnd(trigger.course, entity, CourseTimerType_Button);
- }
- }
- }
-}
-
-void OnMapStart_MapEnd()
-{
- for (int course = 0; course < GOKZ_MAX_COURSES; course++)
- {
- endType[course] = CourseTimerType_None;
- }
-}
-
-bool GetMapEndPosition(int course, float origin[3], float angles[3])
-{
- if (endType[course] == CourseTimerType_None)
- {
- return false;
- }
-
- origin = endOrigin[course];
- angles = endAngles[course];
-
- return true;
-}
-
-
-
-// =====[ PRIVATE ]=====
-
-static void StoreEnd(int course, int entity, CourseTimerType type)
-{
- // If StoreEnd is called, then there is at least an end position (even though it might not be a valid one)
- if (endType[course] < CourseTimerType_Default)
- {
- endType[course] = CourseTimerType_Default;
- }
-
- // Real zone is always better than "fake" zones which are better than buttons
- // as the buttons found in a map with fake zones aren't meant to be visible.
- if (endType[course] >= type)
- {
- return;
- }
-
- float origin[3], distFromCenter[3];
- GetEntityPositions(entity, origin, endOrigin[course], endAngles[course], distFromCenter);
-
- // If it is a button or the center of the center of the zone is invalid
- if (type == CourseTimerType_Button || !IsSpawnValid(endOrigin[course]))
- {
- // Attempt with various positions around the entity, pick the first valid one.
- if (!FindValidPositionAroundTimerEntity(entity, endOrigin[course], endAngles[course], type == CourseTimerType_Button))
- {
- endOrigin[course][2] -= 64.0; // Move the origin down so the eye position is directly on top of the button/zone.
- return;
- }
- }
-
- // Only update the CourseTimerType if a valid position is found.
- endType[course] = type;
-}
-
-static int GetEndButtonBonusNumber(int entity)
-{
- return GOKZ_MatchIntFromEntityName(entity, RE_BonusEndButton, 1);
-}
-
-static int GetEndZoneBonusNumber(int entity)
-{
- return GOKZ_MatchIntFromEntityName(entity, RE_BonusEndZone, 1);
-}
diff --git a/sourcemod/scripting/gokz-core/map/mapfile.sp b/sourcemod/scripting/gokz-core/map/mapfile.sp
deleted file mode 100644
index db60e7e..0000000
--- a/sourcemod/scripting/gokz-core/map/mapfile.sp
+++ /dev/null
@@ -1,502 +0,0 @@
-/*
- Mapping API
-
- Reads data from the current map file.
-*/
-
-static Regex RE_BonusStartButton;
-static Regex RE_BonusEndButton;
-
-// NOTE: 4 megabyte array for entity lump reading.
-static char gEntityLump[4194304];
-
-// =====[ PUBLIC ]=====
-
-void EntlumpParse(StringMap antiBhopTriggers, StringMap teleportTriggers, StringMap timerButtonTriggers, int &mappingApiVersion)
-{
- char mapPath[512];
- GetCurrentMap(mapPath, sizeof(mapPath));
- Format(mapPath, sizeof(mapPath), "maps/%s.bsp", mapPath);
-
- // https://developer.valvesoftware.com/wiki/Source_BSP_File_Format
-
- File file = OpenFile(mapPath, "rb");
- if (file != INVALID_HANDLE)
- {
- int identifier;
- file.ReadInt32(identifier);
-
- if (identifier == GOKZ_BSP_HEADER_IDENTIFIER)
- {
- // skip version number
- file.Seek(4, SEEK_CUR);
-
- // the entity lump info is the first lump in the array, so we don't need to seek any further.
- int offset;
- int length;
- file.ReadInt32(offset);
- file.ReadInt32(length);
-
- // jump to the start of the entity lump
- file.Seek(offset, SEEK_SET);
-
- int charactersRead = file.ReadString(gEntityLump, sizeof(gEntityLump), length);
- delete file;
- if (charactersRead >= sizeof(gEntityLump) - 1)
- {
- PushMappingApiError("ERROR: Entity lump: The map's entity lump is too big! Reduce the amount of entities in your map.");
- return;
- }
- gEntityLump[length] = '\0';
-
- int index = 0;
-
- StringMap entity = new StringMap();
- bool gotWorldSpawn = false;
- while (EntlumpParseEntity(entity, gEntityLump, index))
- {
- char classname[128];
- char targetName[GOKZ_ENTLUMP_MAX_VALUE];
- entity.GetString("classname", classname, sizeof(classname));
-
- if (!gotWorldSpawn && StrEqual("worldspawn", classname, false))
- {
- gotWorldSpawn = true;
- char versionString[32];
- if (entity.GetString("climb_mapping_api_version", versionString, sizeof(versionString)))
- {
- if (StringToIntEx(versionString, mappingApiVersion) == 0)
- {
- PushMappingApiError("ERROR: Entity lump: Couldn't parse Mapping API version from map properties: \"%s\".", versionString);
- mappingApiVersion = GOKZ_MAPPING_API_VERSION_NONE;
- }
- }
- else
- {
- // map doesn't have a mapping api version.
- mappingApiVersion = GOKZ_MAPPING_API_VERSION_NONE;
- }
- }
- else if (StrEqual("trigger_multiple", classname, false))
- {
- TriggerType triggerType;
- if (!gotWorldSpawn || mappingApiVersion != GOKZ_MAPPING_API_VERSION_NONE)
- {
- if (entity.GetString("targetname", targetName, sizeof(targetName)))
- {
- // get trigger properties if applicable
- triggerType = GetTriggerType(targetName);
- if (triggerType == TriggerType_Antibhop)
- {
- AntiBhopTrigger trigger;
- if (GetAntiBhopTriggerEntityProperties(trigger, entity))
- {
- char key[32];
- IntToString(trigger.hammerID, key, sizeof(key));
- antiBhopTriggers.SetArray(key, trigger, sizeof(trigger));
- }
- }
- else if (triggerType == TriggerType_Teleport)
- {
- TeleportTrigger trigger;
- if (GetTeleportTriggerEntityProperties(trigger, entity))
- {
- char key[32];
- IntToString(trigger.hammerID, key, sizeof(key));
- teleportTriggers.SetArray(key, trigger, sizeof(trigger));
- }
- }
- }
- }
-
- // Tracking legacy timer triggers that press the timer buttons upon triggered.
- if (triggerType == TriggerType_Invalid)
- {
- char touchOutput[128];
- ArrayList value;
-
- if (entity.GetString("OnStartTouch", touchOutput, sizeof(touchOutput)))
- {
- TimerButtonTriggerCheck(touchOutput, sizeof(touchOutput), entity, timerButtonTriggers);
- }
- else if (entity.GetValue("OnStartTouch", value)) // If there are multiple outputs, we have to check for all of them.
- {
- for (int i = 0; i < value.Length; i++)
- {
- value.GetString(i, touchOutput, sizeof(touchOutput));
- TimerButtonTriggerCheck(touchOutput, sizeof(touchOutput), entity, timerButtonTriggers);
- }
- }
- }
- }
- else if (StrEqual("func_button", classname, false))
- {
- char pressOutput[128];
- ArrayList value;
-
- if (entity.GetString("OnPressed", pressOutput, sizeof(pressOutput)))
- {
- TimerButtonTriggerCheck(pressOutput, sizeof(pressOutput), entity, timerButtonTriggers);
- }
- else if (entity.GetValue("OnPressed", value)) // If there are multiple outputs, we have to check for all of them.
- {
- for (int i = 0; i < value.Length; i++)
- {
- value.GetString(i, pressOutput, sizeof(pressOutput));
- TimerButtonTriggerCheck(pressOutput, sizeof(pressOutput), entity, timerButtonTriggers);
- }
- }
- }
- // clear for next loop
- entity.Clear();
- }
- delete entity;
- }
- delete file;
- }
- else
- {
- // TODO: do something more elegant
- SetFailState("Catastrophic extreme hyperfailure! Mapping API Couldn't open the map file for reading! %s. The map file might be gone or another program is using it.", mapPath);
- }
-}
-
-
-// =====[ EVENTS ]=====
-
-void OnPluginStart_MapFile()
-{
- char buffer[64];
- char press[8];
- FormatEx(press, sizeof(press), "%s%s", CHAR_ESCAPE, "Press");
-
- buffer = GOKZ_BONUS_START_BUTTON_NAME_REGEX;
- ReplaceStringEx(buffer, sizeof(buffer), "$", "");
- StrCat(buffer, sizeof(buffer), press);
- RE_BonusStartButton = CompileRegex(buffer);
-
- buffer = GOKZ_BONUS_END_BUTTON_NAME_REGEX;
- ReplaceStringEx(buffer, sizeof(buffer), "$", "");
- StrCat(buffer, sizeof(buffer), press);
- RE_BonusEndButton = CompileRegex(buffer);
-}
-
-
-// =====[ PRIVATE ]=====
-
-static void EntlumpSkipAllWhiteSpace(char[] entityLump, int &index)
-{
- while (IsCharSpace(entityLump[index]) && entityLump[index] != '\0')
- {
- index++;
- }
-}
-
-static int EntlumpGetString(char[] result, int maxLength, int copyCount, char[] entityLump, int entlumpIndex)
-{
- int finalLength;
- for (int i = 0; i < maxLength - 1 && i < copyCount; i++)
- {
- if (entityLump[entlumpIndex + i] == '\0')
- {
- break;
- }
- result[i] = entityLump[entlumpIndex + i];
- finalLength++;
- }
-
- result[finalLength] = '\0';
- return finalLength;
-}
-
-static EntlumpToken EntlumpGetToken(char[] entityLump, int &entlumpIndex)
-{
- EntlumpToken result;
-
- EntlumpSkipAllWhiteSpace(entityLump, entlumpIndex);
-
- switch (entityLump[entlumpIndex])
- {
- case '{':
- {
- result.type = EntlumpTokenType_OpenBrace;
- EntlumpGetString(result.string, sizeof(result.string), 1, entityLump, entlumpIndex);
- entlumpIndex++;
- }
- case '}':
- {
- result.type = EntlumpTokenType_CloseBrace;
- EntlumpGetString(result.string, sizeof(result.string), 1, entityLump, entlumpIndex);
- entlumpIndex++;
- }
- case '\0':
- {
- result.type = EntlumpTokenType_EndOfStream;
- EntlumpGetString(result.string, sizeof(result.string), 1, entityLump, entlumpIndex);
- entlumpIndex++;
- }
- case '\"':
- {
- result.type = EntlumpTokenType_Identifier;
- int identifierLen;
- entlumpIndex++;
- for (int i = 0; i < sizeof(result.string) - 1; i++)
- {
- // NOTE: Unterminated strings can probably never happen, since the map has to be
- // loaded by the game first and the engine will fail the load before we get to it.
- if (entityLump[entlumpIndex + i] == '\0')
- {
- result.type = EntlumpTokenType_Unknown;
- break;
- }
- if (entityLump[entlumpIndex + i] == '\"')
- {
- break;
- }
- result.string[i] = entityLump[entlumpIndex + i];
- identifierLen++;
- }
-
- entlumpIndex += identifierLen + 1; // +1 to skip over last quotation mark
- result.string[identifierLen] = '\0';
- }
- default:
- {
- result.type = EntlumpTokenType_Unknown;
- result.string[0] = entityLump[entlumpIndex];
- result.string[1] = '\0';
- }
- }
-
- return result;
-}
-
-static bool EntlumpParseEntity(StringMap result, char[] entityLump, int &entlumpIndex)
-{
- EntlumpToken token;
- token = EntlumpGetToken(entityLump, entlumpIndex);
- if (token.type == EntlumpTokenType_EndOfStream)
- {
- return false;
- }
-
- // NOTE: The following errors will very very likely never happen, since the entity lump has to be
- // loaded by the game first and the engine will fail the load before we get to it.
- // But if there's an obscure bug in this code, then we'll know!!!
- for (;;)
- {
- token = EntlumpGetToken(entityLump, entlumpIndex);
- switch (token.type)
- {
- case EntlumpTokenType_OpenBrace:
- {
- continue;
- }
- case EntlumpTokenType_Identifier:
- {
- EntlumpToken valueToken;
- valueToken = EntlumpGetToken(entityLump, entlumpIndex);
- if (valueToken.type == EntlumpTokenType_Identifier)
- {
- char tempString[GOKZ_ENTLUMP_MAX_VALUE];
- ArrayList values;
- if (result.GetString(token.string, tempString, sizeof(tempString)))
- {
- result.Remove(token.string);
- values = new ArrayList(ByteCountToCells(GOKZ_ENTLUMP_MAX_VALUE));
- values.PushString(tempString);
- values.PushString(valueToken.string);
- result.SetValue(token.string, values);
- }
- else if (result.GetValue(token.string, values))
- {
- values.PushString(valueToken.string);
- }
- else
- {
- result.SetString(token.string, valueToken.string);
- }
- }
- else
- {
- PushMappingApiError("ERROR: Entity lump: Unexpected token \"%s\".", valueToken.string);
- return false;
- }
- }
- case EntlumpTokenType_CloseBrace:
- {
- break;
- }
- case EntlumpTokenType_EndOfStream:
- {
- PushMappingApiError("ERROR: Entity lump: Unexpected end of entity lump! Entity lump parsing failed.");
- return false;
- }
- default:
- {
- PushMappingApiError("ERROR: Entity lump: Invalid token \"%s\". Entity lump parsing failed.", token.string);
- return false;
- }
- }
- }
-
- return true;
-}
-
-static bool GetHammerIDFromEntityStringMap(int &result, StringMap entity)
-{
- char hammerID[32];
- if (!entity.GetString("hammerid", hammerID, sizeof(hammerID))
- || StringToIntEx(hammerID, result) == 0)
- {
- // if we don't have the hammer id, then we can't match the entity to an existing one!
- char origin[64];
- entity.GetString("origin", origin, sizeof(origin));
- PushMappingApiError("ERROR: Failed to parse \"hammerid\" keyvalue on trigger! \"%i\" origin: %s.", result, origin);
- return false;
- }
- return true;
-}
-
-static bool GetAntiBhopTriggerEntityProperties(AntiBhopTrigger result, StringMap entity)
-{
- if (!GetHammerIDFromEntityStringMap(result.hammerID, entity))
- {
- return false;
- }
-
- char time[32];
- if (!entity.GetString("climb_anti_bhop_time", time, sizeof(time))
- || StringToFloatEx(time, result.time) == 0)
- {
- result.time = GOKZ_ANTI_BHOP_TRIGGER_DEFAULT_DELAY;
- }
-
- return true;
-}
-
-static bool GetTeleportTriggerEntityProperties(TeleportTrigger result, StringMap entity)
-{
- if (!GetHammerIDFromEntityStringMap(result.hammerID, entity))
- {
- return false;
- }
-
- char buffer[64];
- if (!entity.GetString("climb_teleport_type", buffer, sizeof(buffer))
- || StringToIntEx(buffer, view_as<int>(result.type)) == 0)
- {
- result.type = GOKZ_TELEPORT_TRIGGER_DEFAULT_TYPE;
- }
-
- if (!entity.GetString("climb_teleport_destination", result.tpDestination, sizeof(result.tpDestination)))
- {
- // We don't want triggers without destinations dangling about, so we need to tell everyone about it!!!
- PushMappingApiError("ERROR: Could not find \"climb_teleport_destination\" keyvalue on a climb_teleport trigger! hammer id \"%i\".",
- result.hammerID);
- return false;
- }
-
- if (!entity.GetString("climb_teleport_delay", buffer, sizeof(buffer))
- || StringToFloatEx(buffer, result.delay) == 0)
- {
- result.delay = GOKZ_TELEPORT_TRIGGER_DEFAULT_DELAY;
- }
-
- if (!entity.GetString("climb_teleport_use_dest_angles", buffer, sizeof(buffer))
- || StringToIntEx(buffer, result.useDestAngles) == 0)
- {
- result.useDestAngles = GOKZ_TELEPORT_TRIGGER_DEFAULT_USE_DEST_ANGLES;
- }
-
- if (!entity.GetString("climb_teleport_reset_speed", buffer, sizeof(buffer))
- || StringToIntEx(buffer, result.resetSpeed) == 0)
- {
- result.resetSpeed = GOKZ_TELEPORT_TRIGGER_DEFAULT_RESET_SPEED;
- }
-
- if (!entity.GetString("climb_teleport_reorient_player", buffer, sizeof(buffer))
- || StringToIntEx(buffer, result.reorientPlayer) == 0)
- {
- result.reorientPlayer = GOKZ_TELEPORT_TRIGGER_DEFAULT_REORIENT_PLAYER;
- }
-
- if (!entity.GetString("climb_teleport_relative", buffer, sizeof(buffer))
- || StringToIntEx(buffer, result.relativeDestination) == 0)
- {
- result.relativeDestination = GOKZ_TELEPORT_TRIGGER_DEFAULT_RELATIVE_DESTINATION;
- }
-
- // NOTE: Clamping
- if (IsBhopTrigger(result.type))
- {
- result.delay = FloatMax(result.delay, GOKZ_TELEPORT_TRIGGER_BHOP_MIN_DELAY);
- }
- else
- {
- result.delay = FloatMax(result.delay, 0.0);
- }
-
- return true;
-}
-
-static void TimerButtonTriggerCheck(char[] touchOutput, int size, StringMap entity, StringMap timerButtonTriggers)
-{
- int course = 0;
- char startOutput[128];
- char endOutput[128];
- FormatEx(startOutput, sizeof(startOutput), "%s%s%s", GOKZ_START_BUTTON_NAME, CHAR_ESCAPE, "Press");
- FormatEx(endOutput, sizeof(endOutput), "%s%s%s", GOKZ_END_BUTTON_NAME, CHAR_ESCAPE, "Press");
- if (StrContains(touchOutput, startOutput, false) != -1)
- {
- TimerButtonTrigger trigger;
- if (GetHammerIDFromEntityStringMap(trigger.hammerID, entity))
- {
- trigger.course = 0;
- trigger.isStartTimer = true;
- }
- char key[32];
- IntToString(trigger.hammerID, key, sizeof(key));
- timerButtonTriggers.SetArray(key, trigger, sizeof(trigger));
- }
- else if (StrContains(touchOutput, endOutput, false) != -1)
- {
- TimerButtonTrigger trigger;
- if (GetHammerIDFromEntityStringMap(trigger.hammerID, entity))
- {
- trigger.course = 0;
- trigger.isStartTimer = false;
- }
- char key[32];
- IntToString(trigger.hammerID, key, sizeof(key));
- timerButtonTriggers.SetArray(key, trigger, sizeof(trigger));
- }
- else if (RE_BonusStartButton.Match(touchOutput) > 0)
- {
- RE_BonusStartButton.GetSubString(1, touchOutput, sizeof(size));
- course = StringToInt(touchOutput);
- TimerButtonTrigger trigger;
- if (GetHammerIDFromEntityStringMap(trigger.hammerID, entity))
- {
- trigger.course = course;
- trigger.isStartTimer = true;
- }
- char key[32];
- IntToString(trigger.hammerID, key, sizeof(key));
- timerButtonTriggers.SetArray(key, trigger, sizeof(trigger));
- }
- else if (RE_BonusEndButton.Match(touchOutput) > 0)
- {
- RE_BonusEndButton.GetSubString(1, touchOutput, sizeof(size));
- course = StringToInt(touchOutput);
- TimerButtonTrigger trigger;
- if (GetHammerIDFromEntityStringMap(trigger.hammerID, entity))
- {
- trigger.course = course;
- trigger.isStartTimer = false;
- }
- char key[32];
- IntToString(trigger.hammerID, key, sizeof(key));
- timerButtonTriggers.SetArray(key, trigger, sizeof(trigger));
- }
-} \ No newline at end of file
diff --git a/sourcemod/scripting/gokz-core/map/prefix.sp b/sourcemod/scripting/gokz-core/map/prefix.sp
deleted file mode 100644
index 3ecbf89..0000000
--- a/sourcemod/scripting/gokz-core/map/prefix.sp
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- Mapping API - Prefix
-
- Detects the map's prefix.
-*/
-
-
-
-static int currentMapPrefix;
-
-
-
-// =====[ PUBLIC ]=====
-
-int GetCurrentMapPrefix()
-{
- return currentMapPrefix;
-}
-
-
-
-// =====[ LISTENERS ]=====
-
-void OnMapStart_Prefix()
-{
- char map[PLATFORM_MAX_PATH], mapPrefix[PLATFORM_MAX_PATH];
- GetCurrentMapDisplayName(map, sizeof(map));
-
- // Get all characters before the first '_' character
- for (int i = 0; i < sizeof(mapPrefix); i++)
- {
- if (map[i] == '\0' || map[i] == '_')
- {
- break;
- }
-
- mapPrefix[i] = map[i];
- }
-
- if (StrEqual(mapPrefix[0], "kzpro", false))
- {
- currentMapPrefix = MapPrefix_KZPro;
- }
- else
- {
- currentMapPrefix = MapPrefix_Other;
- }
-} \ No newline at end of file
diff --git a/sourcemod/scripting/gokz-core/map/starts.sp b/sourcemod/scripting/gokz-core/map/starts.sp
deleted file mode 100644
index 94d5b33..0000000
--- a/sourcemod/scripting/gokz-core/map/starts.sp
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- Hooks between start destinations and GOKZ.
-*/
-
-
-
-static Regex RE_BonusStart;
-static bool startExists[GOKZ_MAX_COURSES];
-static float startOrigin[GOKZ_MAX_COURSES][3];
-static float startAngles[GOKZ_MAX_COURSES][3];
-
-// Used for SearchStart
-static Regex RE_BonusStartButton;
-static Regex RE_BonusStartZone;
-static CourseTimerType startType[GOKZ_MAX_COURSES];
-static float searchStartOrigin[GOKZ_MAX_COURSES][3];
-static float searchStartAngles[GOKZ_MAX_COURSES][3];
-
-// =====[ EVENTS ]=====
-
-void OnPluginStart_MapStarts()
-{
- RE_BonusStart = CompileRegex(GOKZ_BONUS_START_NAME_REGEX);
- RE_BonusStartButton = CompileRegex(GOKZ_BONUS_START_BUTTON_NAME_REGEX);
- RE_BonusStartZone = CompileRegex(GOKZ_BONUS_START_ZONE_NAME_REGEX);
-}
-
-void OnEntitySpawned_MapStarts(int entity)
-{
- char buffer[32];
-
- GetEntityClassname(entity, buffer, sizeof(buffer));
- if (!StrEqual("info_teleport_destination", buffer, false))
- {
- return;
- }
-
- if (GetEntityName(entity, buffer, sizeof(buffer)) == 0)
- {
- return;
- }
-
- if (StrEqual(GOKZ_START_NAME, buffer, false))
- {
- StoreStart(0, entity);
- }
- else
- {
- int course = GetStartBonusNumber(entity);
- if (GOKZ_IsValidCourse(course, true))
- {
- StoreStart(course, entity);
- }
- }
-}
-
-void OnEntitySpawnedPost_MapStarts(int entity)
-{
- char buffer[32];
- GetEntityClassname(entity, buffer, sizeof(buffer));
-
- if (StrEqual("trigger_multiple", buffer, false))
- {
- bool isStartZone;
- if (GetEntityName(entity, buffer, sizeof(buffer)) != 0)
- {
- if (StrEqual(GOKZ_START_ZONE_NAME, buffer, false))
- {
- isStartZone = true;
- StoreSearchStart(0, entity, CourseTimerType_ZoneNew);
- }
- else if (GetStartZoneBonusNumber(entity) != -1)
- {
- int course = GetStartZoneBonusNumber(entity);
- if (GOKZ_IsValidCourse(course, true))
- {
- isStartZone = true;
- StoreSearchStart(course, entity, CourseTimerType_ZoneNew);
- }
- }
- }
- if (!isStartZone)
- {
- TimerButtonTrigger trigger;
- if (IsTimerButtonTrigger(entity, trigger) && trigger.isStartTimer)
- {
- StoreSearchStart(trigger.course, entity, CourseTimerType_ZoneLegacy);
- }
- }
-
- }
- else if (StrEqual("func_button", buffer, false))
- {
- bool isStartButton;
- if (GetEntityName(entity, buffer, sizeof(buffer)) != 0)
- {
- if (StrEqual(GOKZ_START_BUTTON_NAME, buffer, false))
- {
- isStartButton = true;
- StoreSearchStart(0, entity, CourseTimerType_Button);
- }
- else
- {
- int course = GetStartButtonBonusNumber(entity);
- if (GOKZ_IsValidCourse(course, true))
- {
- isStartButton = true;
- StoreSearchStart(course, entity, CourseTimerType_Button);
- }
- }
- }
- if (!isStartButton)
- {
- TimerButtonTrigger trigger;
- if (IsTimerButtonTrigger(entity, trigger) && trigger.isStartTimer)
- {
- StoreSearchStart(trigger.course, entity, CourseTimerType_Button);
- }
- }
- }
-}
-
-void OnMapStart_MapStarts()
-{
- for (int course = 0; course < GOKZ_MAX_COURSES; course++)
- {
- startExists[course] = false;
- startType[course] = CourseTimerType_None;
- }
-}
-
-bool GetMapStartPosition(int course, float origin[3], float angles[3])
-{
- if (!startExists[course])
- {
- return false;
- }
-
- origin = startOrigin[course];
- angles = startAngles[course];
-
- return true;
-}
-
-bool GetSearchStartPosition(int course, float origin[3], float angles[3])
-{
- if (startType[course] == CourseTimerType_None)
- {
- return false;
- }
-
- origin = searchStartOrigin[course];
- angles = searchStartAngles[course];
-
- return true;
-}
-
-// =====[ PRIVATE ]=====
-
-static void StoreStart(int course, int entity)
-{
- float origin[3], angles[3];
- GetEntPropVector(entity, Prop_Send, "m_vecOrigin", origin);
- GetEntPropVector(entity, Prop_Data, "m_angRotation", angles);
- angles[2] = 0.0; // Roll should always be 0.0
-
- startExists[course] = true;
- startOrigin[course] = origin;
- startAngles[course] = angles;
-}
-
-static void StoreSearchStart(int course, int entity, CourseTimerType type)
-{
- // If StoreSearchStart is called, then there is at least an end position (even though it might not be a valid one)
- if (startType[course] < CourseTimerType_Default)
- {
- startType[course] = CourseTimerType_Default;
- }
-
- // Real zone is always better than "fake" zones which are better than buttons
- // as the buttons found in a map with fake zones aren't meant to be visible.
- if (startType[course] >= type)
- {
- return;
- }
-
- float origin[3], distFromCenter[3];
- GetEntityPositions(entity, origin, searchStartOrigin[course], searchStartAngles[course], distFromCenter);
-
- // If it is a button or the center of the center of the zone is invalid
- if (type == CourseTimerType_Button || !IsSpawnValid(searchStartOrigin[course]))
- {
- // Attempt with various positions around the entity, pick the first valid one.
- if (!FindValidPositionAroundTimerEntity(entity, searchStartOrigin[course], searchStartAngles[course], type == CourseTimerType_Button))
- {
- searchStartOrigin[course][2] -= 64.0; // Move the origin down so the eye position is directly on top of the button/zone.
- return;
- }
- }
-
- // Only update the CourseTimerType if a valid position is found.
- startType[course] = type;
-}
-
-
-static int GetStartBonusNumber(int entity)
-{
- return GOKZ_MatchIntFromEntityName(entity, RE_BonusStart, 1);
-}
-
-static int GetStartButtonBonusNumber(int entity)
-{
- return GOKZ_MatchIntFromEntityName(entity, RE_BonusStartButton, 1);
-}
-
-static int GetStartZoneBonusNumber(int entity)
-{
- return GOKZ_MatchIntFromEntityName(entity, RE_BonusStartZone, 1);
-} \ No newline at end of file
diff --git a/sourcemod/scripting/gokz-core/map/triggers.sp b/sourcemod/scripting/gokz-core/map/triggers.sp
deleted file mode 100644
index 2444493..0000000
--- a/sourcemod/scripting/gokz-core/map/triggers.sp
+++ /dev/null
@@ -1,855 +0,0 @@
-/*
- Mapping API - Triggers
-
- Implements trigger related features.
-*/
-
-
-
-static float lastTrigMultiTouchTime[MAXPLAYERS + 1];
-static float lastTrigTeleTouchTime[MAXPLAYERS + 1];
-static float lastTouchGroundOrLadderTime[MAXPLAYERS + 1];
-static int lastTouchSingleBhopEntRef[MAXPLAYERS + 1];
-static ArrayList lastTouchSequentialBhopEntRefs[MAXPLAYERS + 1];
-static int triggerTouchCount[MAXPLAYERS + 1];
-static int antiCpTriggerTouchCount[MAXPLAYERS + 1];
-static int antiPauseTriggerTouchCount[MAXPLAYERS + 1];
-static int antiJumpstatTriggerTouchCount[MAXPLAYERS + 1];
-static int mapMappingApiVersion = GOKZ_MAPPING_API_VERSION_NONE;
-static int bhopTouchCount[MAXPLAYERS + 1];
-static bool jumpedThisTick[MAXPLAYERS + 1];
-static float jumpOrigin[MAXPLAYERS + 1][3];
-static float jumpVelocity[MAXPLAYERS + 1][3];
-static ArrayList triggerTouchList[MAXPLAYERS + 1]; // arraylist of TouchedTrigger that the player is currently touching. this array won't ever get long (unless the mapper does something weird).
-static StringMap triggerTouchCounts[MAXPLAYERS + 1]; // stringmap of int touch counts with key being a string of the entity reference.
-static StringMap antiBhopTriggers; // stringmap of AntiBhopTrigger with key being a string of the m_iHammerID entprop.
-static StringMap teleportTriggers; // stringmap of TeleportTrigger with key being a string of the m_iHammerID entprop.
-static StringMap timerButtonTriggers; // stringmap of legacy timer zone triggers with key being a string of the m_iHammerID entprop.
-static ArrayList parseErrorStrings;
-
-
-
-// =====[ PUBLIC ]=====
-
-bool BhopTriggersJustTouched(int client)
-{
- // NOTE: This is slightly incorrect since we touch triggers in the air, but
- // it doesn't matter since we can't checkpoint in the air.
- if (bhopTouchCount[client] > 0)
- {
- return true;
- }
- // GetEngineTime return changes between calls. We only call it once at the beginning.
- float engineTime = GetEngineTime();
- // If the player touches a teleport trigger, increase the delay required
- if (engineTime - lastTouchGroundOrLadderTime[client] < GOKZ_MULT_NO_CHECKPOINT_TIME // Just touched ground or ladder
- && engineTime - lastTrigMultiTouchTime[client] < GOKZ_MULT_NO_CHECKPOINT_TIME // Just touched trigger_multiple
- || engineTime - lastTrigTeleTouchTime[client] < GOKZ_BHOP_NO_CHECKPOINT_TIME) // Just touched trigger_teleport
- {
- return true;
- }
-
- return Movement_GetMovetype(client) == MOVETYPE_LADDER
- && triggerTouchCount[client] > 0
- && engineTime - lastTrigTeleTouchTime[client] < GOKZ_LADDER_NO_CHECKPOINT_TIME;
-}
-
-bool AntiCpTriggerIsTouched(int client)
-{
- return antiCpTriggerTouchCount[client] > 0;
-}
-
-bool AntiPauseTriggerIsTouched(int client)
-{
- return antiPauseTriggerTouchCount[client] > 0;
-}
-
-void PushMappingApiError(char[] format, any ...)
-{
- char error[GOKZ_MAX_MAPTRIGGERS_ERROR_LENGTH];
- VFormat(error, sizeof(error), format, 2);
- parseErrorStrings.PushString(error);
-}
-
-TriggerType GetTriggerType(char[] targetName)
-{
- TriggerType result = TriggerType_Invalid;
-
- if (StrEqual(targetName, GOKZ_ANTI_BHOP_TRIGGER_NAME))
- {
- result = TriggerType_Antibhop;
- }
- else if (StrEqual(targetName, GOKZ_TELEPORT_TRIGGER_NAME))
- {
- result = TriggerType_Teleport;
- }
-
- return result;
-}
-
-bool IsBhopTrigger(TeleportType type)
-{
- return type == TeleportType_MultiBhop
- || type == TeleportType_SingleBhop
- || type == TeleportType_SequentialBhop;
-}
-
-bool IsTimerButtonTrigger(int entity, TimerButtonTrigger trigger)
-{
- char hammerID[32];
- bool gotHammerID = GetEntityHammerIDString(entity, hammerID, sizeof(hammerID));
- if (gotHammerID && timerButtonTriggers.GetArray(hammerID, trigger, sizeof(trigger)))
- {
- return true;
- }
- return false;
-}
-
-// =====[ EVENTS ]=====
-
-void OnPluginStart_MapTriggers()
-{
- parseErrorStrings = new ArrayList(ByteCountToCells(GOKZ_MAX_MAPTRIGGERS_ERROR_LENGTH));
- antiBhopTriggers = new StringMap();
- teleportTriggers = new StringMap();
- timerButtonTriggers = new StringMap();
-}
-
-void OnMapStart_MapTriggers()
-{
- parseErrorStrings.Clear();
- antiBhopTriggers.Clear();
- teleportTriggers.Clear();
- timerButtonTriggers.Clear();
- mapMappingApiVersion = GOKZ_MAPPING_API_VERSION_NONE;
- EntlumpParse(antiBhopTriggers, teleportTriggers, timerButtonTriggers, mapMappingApiVersion);
-
- if (mapMappingApiVersion > GOKZ_MAPPING_API_VERSION)
- {
- SetFailState("Map's mapping api version is too big! Maximum supported version is %i, but map has %i. If you're not on the latest GOKZ version, then update!",
- GOKZ_MAPPING_API_VERSION, mapMappingApiVersion);
- }
-}
-
-void OnClientPutInServer_MapTriggers(int client)
-{
- triggerTouchCount[client] = 0;
- antiCpTriggerTouchCount[client] = 0;
- antiPauseTriggerTouchCount[client] = 0;
- antiJumpstatTriggerTouchCount[client] = 0;
-
- if (triggerTouchList[client] == null)
- {
- triggerTouchList[client] = new ArrayList(sizeof(TouchedTrigger));
- }
- else
- {
- triggerTouchList[client].Clear();
- }
-
- if (triggerTouchCounts[client] == null)
- {
- triggerTouchCounts[client] = new StringMap();
- }
- else
- {
- triggerTouchCounts[client].Clear();
- }
-
- bhopTouchCount[client] = 0;
-
- if (lastTouchSequentialBhopEntRefs[client] == null)
- {
- lastTouchSequentialBhopEntRefs[client] = new ArrayList();
- }
- else
- {
- lastTouchSequentialBhopEntRefs[client].Clear();
- }
-}
-
-void OnPlayerRunCmd_MapTriggers(int client, int &buttons)
-{
- int flags = GetEntityFlags(client);
- MoveType moveType = GetEntityMoveType(client);
-
- // if the player isn't touching any bhop triggers on ground/a ladder, then
- // reset the singlebhop and sequential bhop state.
- if ((flags & FL_ONGROUND || moveType == MOVETYPE_LADDER)
- && bhopTouchCount[client] == 0)
- {
- ResetBhopState(client);
- }
-
- if (antiJumpstatTriggerTouchCount[client] > 0)
- {
- if (GetFeatureStatus(FeatureType_Native, "GOKZ_JS_InvalidateJump") == FeatureStatus_Available)
- {
- GOKZ_JS_InvalidateJump(client);
- }
- }
-
- // Check if we're touching any triggers and act accordingly.
- // NOTE: Read through the touch list in reverse order, so some
- // trigger behaviours will be better. Trust me!
- int triggerTouchListLength = triggerTouchList[client].Length;
- for (int i = triggerTouchListLength - 1; i >= 0; i--)
- {
- TouchedTrigger touched;
- triggerTouchList[client].GetArray(i, touched);
-
- if (touched.triggerType == TriggerType_Antibhop)
- {
- TouchAntibhopTrigger(client, touched, buttons, flags);
- }
- else if (touched.triggerType == TriggerType_Teleport)
- {
- // Sometimes due to lag or whatever, the player can be
- // teleported twice by the same trigger. This fixes that.
- if (TouchTeleportTrigger(client, touched, flags))
- {
- RemoveTriggerFromTouchList(client, EntRefToEntIndex(touched.entRef));
- i--;
- triggerTouchListLength--;
- }
- }
- }
- jumpedThisTick[client] = false;
-}
-
-void OnPlayerSpawn_MapTriggers(int client)
-{
- // Print trigger errors every time a player spawns so that
- // mappers and testers can very easily spot mistakes in names
- // and get them fixed asap.
- if (parseErrorStrings.Length > 0)
- {
- char errStart[] = "ERROR: Errors detected when trying to load triggers!";
- CPrintToChat(client, "{red}%s", errStart);
- PrintToConsole(client, "\n%s", errStart);
-
- int length = parseErrorStrings.Length;
- for (int err = 0; err < length; err++)
- {
- char error[GOKZ_MAX_MAPTRIGGERS_ERROR_LENGTH];
- parseErrorStrings.GetString(err, error, sizeof(error));
- CPrintToChat(client, "{red}%s", error);
- PrintToConsole(client, error);
- }
- CPrintToChat(client, "{red}If the errors get clipped off in the chat, then look in your developer console!\n");
- }
-}
-
-public void OnPlayerJump_Triggers(int client)
-{
- jumpedThisTick[client] = true;
- GetClientAbsOrigin(client, jumpOrigin[client]);
- Movement_GetVelocity(client, jumpVelocity[client]);
-}
-
-void OnEntitySpawned_MapTriggers(int entity)
-{
- char classname[32];
- GetEntityClassname(entity, classname, sizeof(classname));
- char name[64];
- GetEntityName(entity, name, sizeof(name));
-
- bool triggerMultiple = StrEqual("trigger_multiple", classname);
- if (triggerMultiple)
- {
- char hammerID[32];
- bool gotHammerID = GetEntityHammerIDString(entity, hammerID, sizeof(hammerID));
-
- if (StrEqual(GOKZ_TELEPORT_TRIGGER_NAME, name))
- {
- TeleportTrigger teleportTrigger;
- if (gotHammerID && teleportTriggers.GetArray(hammerID, teleportTrigger, sizeof(teleportTrigger)))
- {
- HookSingleEntityOutput(entity, "OnStartTouch", OnTeleportTrigTouchStart_MapTriggers);
- HookSingleEntityOutput(entity, "OnEndTouch", OnTeleportTrigTouchEnd_MapTriggers);
- }
- else
- {
- PushMappingApiError("ERROR: Couldn't match teleport trigger's Hammer ID %s with any Hammer ID from the map.", hammerID);
- }
- }
- else if (StrEqual(GOKZ_ANTI_BHOP_TRIGGER_NAME, name))
- {
- AntiBhopTrigger antiBhopTrigger;
- if (gotHammerID && antiBhopTriggers.GetArray(hammerID, antiBhopTrigger, sizeof(antiBhopTrigger)))
- {
- HookSingleEntityOutput(entity, "OnStartTouch", OnAntiBhopTrigTouchStart_MapTriggers);
- HookSingleEntityOutput(entity, "OnEndTouch", OnAntiBhopTrigTouchEnd_MapTriggers);
- }
- else
- {
- PushMappingApiError("ERROR: Couldn't match antibhop trigger's Hammer ID %s with any Hammer ID from the map.", hammerID);
- }
- }
- else if (StrEqual(GOKZ_BHOP_RESET_TRIGGER_NAME, name))
- {
- HookSingleEntityOutput(entity, "OnStartTouch", OnBhopResetTouchStart_MapTriggers);
- }
- else if (StrEqual(GOKZ_ANTI_CP_TRIGGER_NAME, name, false))
- {
- HookSingleEntityOutput(entity, "OnStartTouch", OnAntiCpTrigTouchStart_MapTriggers);
- HookSingleEntityOutput(entity, "OnEndTouch", OnAntiCpTrigTouchEnd_MapTriggers);
- }
- else if (StrEqual(GOKZ_ANTI_PAUSE_TRIGGER_NAME, name, false))
- {
- HookSingleEntityOutput(entity, "OnStartTouch", OnAntiPauseTrigTouchStart_MapTriggers);
- HookSingleEntityOutput(entity, "OnEndTouch", OnAntiPauseTrigTouchEnd_MapTriggers);
- }
- else if (StrEqual(GOKZ_ANTI_JUMPSTAT_TRIGGER_NAME, name, false))
- {
- HookSingleEntityOutput(entity, "OnStartTouch", OnAntiJumpstatTrigTouchStart_MapTriggers);
- HookSingleEntityOutput(entity, "OnEndTouch", OnAntiJumpstatTrigTouchEnd_MapTriggers);
- }
- else
- {
- // NOTE: SDKHook touch hooks bypass trigger filters. We want that only with
- // non mapping api triggers because it prevents checkpointing on bhop blocks.
- SDKHook(entity, SDKHook_StartTouchPost, OnTrigMultTouchStart_MapTriggers);
- SDKHook(entity, SDKHook_EndTouchPost, OnTrigMultTouchEnd_MapTriggers);
- }
- }
- else if (StrEqual("trigger_teleport", classname))
- {
- SDKHook(entity, SDKHook_StartTouchPost, OnTrigTeleTouchStart_MapTriggers);
- SDKHook(entity, SDKHook_EndTouchPost, OnTrigTeleTouchEnd_MapTriggers);
- }
-}
-
-public void OnAntiBhopTrigTouchStart_MapTriggers(const char[] output, int entity, int other, float delay)
-{
- if (!IsValidClient(other))
- {
- return;
- }
-
- int touchCount = IncrementTriggerTouchCount(other, entity);
- if (touchCount <= 0)
- {
- // The trigger has fired a matching endtouch output before
- // the starttouch output, so ignore it.
- return;
- }
-
- if (jumpedThisTick[other])
- {
- TeleportEntity(other, jumpOrigin[other], NULL_VECTOR, jumpVelocity[other]);
- }
-
- AddTriggerToTouchList(other, entity, TriggerType_Antibhop);
-}
-
-public void OnAntiBhopTrigTouchEnd_MapTriggers(const char[] output, int entity, int other, float delay)
-{
- if (!IsValidClient(other))
- {
- return;
- }
-
- DecrementTriggerTouchCount(other, entity);
- RemoveTriggerFromTouchList(other, entity);
-}
-
-public void OnTeleportTrigTouchStart_MapTriggers(const char[] output, int entity, int other, float delay)
-{
- if (!IsValidClient(other))
- {
- return;
- }
-
- int touchCount = IncrementTriggerTouchCount(other, entity);
- if (touchCount <= 0)
- {
- // The trigger has fired a matching endtouch output before
- // the starttouch output, so ignore it.
- return;
- }
-
- char key[32];
- GetEntityHammerIDString(entity, key, sizeof(key));
- TeleportTrigger trigger;
- if (teleportTriggers.GetArray(key, trigger, sizeof(trigger))
- && IsBhopTrigger(trigger.type))
- {
- bhopTouchCount[other]++;
- }
-
- AddTriggerToTouchList(other, entity, TriggerType_Teleport);
-}
-
-public void OnTeleportTrigTouchEnd_MapTriggers(const char[] output, int entity, int other, float delay)
-{
- if (!IsValidClient(other))
- {
- return;
- }
-
- DecrementTriggerTouchCount(other, entity);
-
- char key[32];
- GetEntityHammerIDString(entity, key, sizeof(key));
- TeleportTrigger trigger;
- if (teleportTriggers.GetArray(key, trigger, sizeof(trigger))
- && IsBhopTrigger(trigger.type))
- {
- bhopTouchCount[other]--;
- }
-
- RemoveTriggerFromTouchList(other, entity);
-}
-
-public void OnBhopResetTouchStart_MapTriggers(const char[] output, int entity, int other, float delay)
-{
- if (!IsValidClient(other))
- {
- return;
- }
-
- ResetBhopState(other);
-}
-
-public void OnAntiCpTrigTouchStart_MapTriggers(const char[] output, int entity, int other, float delay)
-{
- if (!IsValidClient(other))
- {
- return;
- }
-
- antiCpTriggerTouchCount[other]++;
-}
-
-public void OnAntiCpTrigTouchEnd_MapTriggers(const char[] output, int entity, int other, float delay)
-{
- if (!IsValidClient(other))
- {
- return;
- }
-
- antiCpTriggerTouchCount[other]--;
-}
-
-public void OnAntiPauseTrigTouchStart_MapTriggers(const char[] output, int entity, int other, float delay)
-{
- if (!IsValidClient(other))
- {
- return;
- }
-
- antiPauseTriggerTouchCount[other]++;
-}
-
-public void OnAntiPauseTrigTouchEnd_MapTriggers(const char[] output, int entity, int other, float delay)
-{
- if (!IsValidClient(other))
- {
- return;
- }
-
- antiPauseTriggerTouchCount[other]--;
-}
-
-public void OnAntiJumpstatTrigTouchStart_MapTriggers(const char[] output, int entity, int other, float delay)
-{
- if (!IsValidClient(other))
- {
- return;
- }
-
- antiJumpstatTriggerTouchCount[other]++;
-}
-
-public void OnAntiJumpstatTrigTouchEnd_MapTriggers(const char[] output, int entity, int other, float delay)
-{
- if (!IsValidClient(other))
- {
- return;
- }
-
- antiJumpstatTriggerTouchCount[other]--;
-}
-
-public void OnTrigMultTouchStart_MapTriggers(int entity, int other)
-{
- if (!IsValidClient(other))
- {
- return;
- }
-
- lastTrigMultiTouchTime[other] = GetEngineTime();
- triggerTouchCount[other]++;
-}
-
-public void OnTrigMultTouchEnd_MapTriggers(int entity, int other)
-{
- if (!IsValidClient(other))
- {
- return;
- }
-
- triggerTouchCount[other]--;
-}
-
-public void OnTrigTeleTouchStart_MapTriggers(int entity, int other)
-{
- if (!IsValidClient(other))
- {
- return;
- }
-
- lastTrigTeleTouchTime[other] = GetEngineTime();
- triggerTouchCount[other]++;
-}
-
-public void OnTrigTeleTouchEnd_MapTriggers(int entity, int other)
-{
- if (!IsValidClient(other))
- {
- return;
- }
-
- triggerTouchCount[other]--;
-}
-
-void OnStartTouchGround_MapTriggers(int client)
-{
- lastTouchGroundOrLadderTime[client] = GetEngineTime();
-
- for (int i = 0; i < triggerTouchList[client].Length; i++)
- {
- TouchedTrigger touched;
- triggerTouchList[client].GetArray(i, touched);
- // set the touched tick to the tick that the player touches the ground.
- touched.groundTouchTick = gI_TickCount[client];
- triggerTouchList[client].SetArray(i, touched);
- }
-}
-
-void OnStopTouchGround_MapTriggers(int client)
-{
- for (int i = 0; i < triggerTouchList[client].Length; i++)
- {
- TouchedTrigger touched;
- triggerTouchList[client].GetArray(i, touched);
-
- if (touched.triggerType == TriggerType_Teleport)
- {
- char key[32];
- GetEntityHammerIDString(touched.entRef, key, sizeof(key));
- TeleportTrigger trigger;
- // set last touched triggers for single and sequential bhop.
- if (teleportTriggers.GetArray(key, trigger, sizeof(trigger))
- && IsBhopTrigger(trigger.type))
- {
- if (trigger.type == TeleportType_SequentialBhop)
- {
- lastTouchSequentialBhopEntRefs[client].Push(touched.entRef);
- }
- // NOTE: For singlebhops, we don't care which type of bhop we last touched, because
- // otherwise jumping back and forth between a multibhop and a singlebhop wouldn't work.
- if (i == 0 && IsBhopTrigger(trigger.type))
- {
- // We only want to set this once in this loop.
- lastTouchSingleBhopEntRef[client] = touched.entRef;
- }
- }
- }
- }
-}
-
-void OnChangeMovetype_MapTriggers(int client, MoveType newMovetype)
-{
- if (newMovetype == MOVETYPE_LADDER)
- {
- lastTouchGroundOrLadderTime[client] = GetEngineTime();
- }
-}
-
-
-
-// =====[ PRIVATE ]=====
-
-static void AddTriggerToTouchList(int client, int trigger, TriggerType triggerType)
-{
- int triggerEntRef = EntIndexToEntRef(trigger);
-
- TouchedTrigger touched;
- touched.triggerType = triggerType;
- touched.entRef = triggerEntRef;
- touched.startTouchTick = gI_TickCount[client];
- touched.groundTouchTick = -1;
- if (GetEntityFlags(client) & FL_ONGROUND)
- {
- touched.groundTouchTick = gI_TickCount[client];
- }
-
- triggerTouchList[client].PushArray(touched);
-}
-
-static void RemoveTriggerFromTouchList(int client, int trigger)
-{
- int triggerEntRef = EntIndexToEntRef(trigger);
- for (int i = 0; i < triggerTouchList[client].Length; i++)
- {
- TouchedTrigger touched;
- triggerTouchList[client].GetArray(i, touched);
- if (touched.entRef == triggerEntRef)
- {
- triggerTouchList[client].Erase(i);
- break;
- }
- }
-}
-
-static int IncrementTriggerTouchCount(int client, int trigger)
-{
- int entref = EntIndexToEntRef(trigger);
- char szEntref[64];
- FormatEx(szEntref, sizeof(szEntref), "%i", entref);
-
- int value = 0;
- triggerTouchCounts[client].GetValue(szEntref, value);
-
- value += 1;
- triggerTouchCounts[client].SetValue(szEntref, value);
-
- return value;
-}
-
-static void DecrementTriggerTouchCount(int client, int trigger)
-{
- int entref = EntIndexToEntRef(trigger);
- char szEntref[64];
- FormatEx(szEntref, sizeof(szEntref), "%i", entref);
-
- int value = 0;
- triggerTouchCounts[client].GetValue(szEntref, value);
-
- value -= 1;
- triggerTouchCounts[client].SetValue(szEntref, value);
-}
-
-static void TouchAntibhopTrigger(int client, TouchedTrigger touched, int &newButtons, int flags)
-{
- if (!(flags & FL_ONGROUND))
- {
- // Disable jump when the player is in the air.
- // This is a very simple way to fix jumpbugging antibhop triggers.
- newButtons &= ~IN_JUMP;
- return;
- }
-
- if (touched.groundTouchTick == -1)
- {
- // The player hasn't touched the ground inside this trigger yet.
- return;
- }
-
- char key[32];
- GetEntityHammerIDString(touched.entRef, key, sizeof(key));
- AntiBhopTrigger trigger;
- if (antiBhopTriggers.GetArray(key, trigger, sizeof(trigger)))
- {
- float touchTime = CalculateGroundTouchTime(client, touched);
- if (trigger.time == 0.0 || touchTime <= trigger.time)
- {
- // disable jump
- newButtons &= ~IN_JUMP;
- }
- }
-}
-
-static bool TouchTeleportTrigger(int client, TouchedTrigger touched, int flags)
-{
- bool shouldTeleport = false;
-
- char key[32];
- GetEntityHammerIDString(touched.entRef, key, sizeof(key));
- TeleportTrigger trigger;
- if (!teleportTriggers.GetArray(key, trigger, sizeof(trigger)))
- {
- // Couldn't get the teleport trigger from the trigger array for some reason.
- return shouldTeleport;
- }
-
- bool isBhopTrigger = IsBhopTrigger(trigger.type);
- // NOTE: Player hasn't touched the ground inside this trigger yet.
- if (touched.groundTouchTick == -1 && isBhopTrigger)
- {
- return shouldTeleport;
- }
-
- float destOrigin[3];
- float destAngles[3];
- bool gotDestOrigin;
- bool gotDestAngles;
- int destinationEnt = GetTeleportDestinationAndOrientation(trigger.tpDestination, destOrigin, destAngles, gotDestOrigin, gotDestAngles);
-
- float triggerOrigin[3];
- bool gotTriggerOrigin = GetEntityAbsOrigin(touched.entRef, triggerOrigin);
-
- // NOTE: We only use the trigger's origin if we're using a relative destination, so if
- // we're not using a relative destination and don't have it, then it's fine.
- if (!IsValidEntity(destinationEnt) || !gotDestOrigin
- || (!gotTriggerOrigin && trigger.relativeDestination))
- {
- PrintToConsole(client, "[KZ] Invalid teleport destination \"%s\" on trigger with hammerID %i.", trigger.tpDestination, trigger.hammerID);
- return shouldTeleport;
- }
-
- // NOTE: Find out if we should actually teleport.
- if (isBhopTrigger && (flags & FL_ONGROUND))
- {
- float touchTime = CalculateGroundTouchTime(client, touched);
- if (touchTime > trigger.delay)
- {
- shouldTeleport = true;
- }
- else if (trigger.type == TeleportType_SingleBhop)
- {
- shouldTeleport = lastTouchSingleBhopEntRef[client] == touched.entRef;
- }
- else if (trigger.type == TeleportType_SequentialBhop)
- {
- int length = lastTouchSequentialBhopEntRefs[client].Length;
- for (int j = 0; j < length; j++)
- {
- int entRef = lastTouchSequentialBhopEntRefs[client].Get(j);
- if (entRef == touched.entRef)
- {
- shouldTeleport = true;
- break;
- }
- }
- }
- }
- else if (trigger.type == TeleportType_Normal)
- {
- float touchTime = CalculateStartTouchTime(client, touched);
- shouldTeleport = touchTime > trigger.delay || (trigger.delay == 0.0);
- }
-
- if (!shouldTeleport)
- {
- return shouldTeleport;
- }
-
- bool shouldReorientPlayer = trigger.reorientPlayer
- && gotDestAngles && (destAngles[1] != 0.0);
-
- float zAxis[3];
- zAxis = view_as<float>({0.0, 0.0, 1.0});
-
- // NOTE: Work out finalOrigin.
- float finalOrigin[3];
- if (trigger.relativeDestination)
- {
- float playerOrigin[3];
- Movement_GetOrigin(client, playerOrigin);
-
- float playerOffsetFromTrigger[3];
- SubtractVectors(playerOrigin, triggerOrigin, playerOffsetFromTrigger);
-
- if (shouldReorientPlayer)
- {
- // NOTE: rotate player offset by the destination trigger's yaw.
- RotateVectorAxis(playerOffsetFromTrigger, zAxis, DegToRad(destAngles[1]), playerOffsetFromTrigger);
- }
-
- AddVectors(destOrigin, playerOffsetFromTrigger, finalOrigin);
- }
- else
- {
- finalOrigin = destOrigin;
- }
-
- // NOTE: Work out finalPlayerAngles.
- float finalPlayerAngles[3];
- Movement_GetEyeAngles(client, finalPlayerAngles);
- if (shouldReorientPlayer)
- {
- finalPlayerAngles[1] -= destAngles[1];
-
- float velocity[3];
- Movement_GetVelocity(client, velocity);
-
- // NOTE: rotate velocity by the destination trigger's yaw.
- RotateVectorAxis(velocity, zAxis, DegToRad(destAngles[1]), velocity);
- Movement_SetVelocity(client, velocity);
- }
- else if (!trigger.reorientPlayer && trigger.useDestAngles)
- {
- finalPlayerAngles = destAngles;
- }
-
- if (shouldTeleport)
- {
- TeleportPlayer(client, finalOrigin, finalPlayerAngles, gotDestAngles && trigger.useDestAngles, trigger.resetSpeed);
- }
-
- return shouldTeleport;
-}
-
-static float CalculateGroundTouchTime(int client, TouchedTrigger touched)
-{
- float result = float(gI_TickCount[client] - touched.groundTouchTick) * GetTickInterval();
- return result;
-}
-
-static float CalculateStartTouchTime(int client, TouchedTrigger touched)
-{
- float result = float(gI_TickCount[client] - touched.startTouchTick) * GetTickInterval();
- return result;
-}
-
-static void ResetBhopState(int client)
-{
- lastTouchSingleBhopEntRef[client] = INVALID_ENT_REFERENCE;
- lastTouchSequentialBhopEntRefs[client].Clear();
-}
-
-static bool GetEntityHammerIDString(int entity, char[] buffer, int maxLength)
-{
- if (!IsValidEntity(entity))
- {
- return false;
- }
-
- if (!HasEntProp(entity, Prop_Data, "m_iHammerID"))
- {
- return false;
- }
-
- int hammerID = GetEntProp(entity, Prop_Data, "m_iHammerID");
- IntToString(hammerID, buffer, maxLength);
-
- return true;
-}
-
-// NOTE: returns an entity reference (possibly invalid).
-static int GetTeleportDestinationAndOrientation(char[] targetName, float origin[3], float angles[3] = NULL_VECTOR, bool &gotOrigin = false, bool &gotAngles = false)
-{
- // NOTE: We're not caching the teleport destination because it could change.
- int destination = GOKZFindEntityByName(targetName, .ignorePlayers = true);
- if (!IsValidEntity(destination))
- {
- return destination;
- }
-
- gotOrigin = GetEntityAbsOrigin(destination, origin);
-
- if (HasEntProp(destination, Prop_Data, "m_angAbsRotation"))
- {
- GetEntPropVector(destination, Prop_Data, "m_angAbsRotation", angles);
- gotAngles = true;
- }
- else
- {
- gotAngles = false;
- }
-
- return destination;
-} \ No newline at end of file
diff --git a/sourcemod/scripting/gokz-core/map/zones.sp b/sourcemod/scripting/gokz-core/map/zones.sp
deleted file mode 100644
index 684e42d..0000000
--- a/sourcemod/scripting/gokz-core/map/zones.sp
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- Hooks between specifically named trigger_multiples and GOKZ.
-*/
-
-
-
-static Regex RE_BonusStartZone;
-static Regex RE_BonusEndZone;
-static bool touchedGroundSinceTouchingStartZone[MAXPLAYERS + 1];
-
-
-
-// =====[ EVENTS ]=====
-
-void OnPluginStart_MapZones()
-{
- RE_BonusStartZone = CompileRegex(GOKZ_BONUS_START_ZONE_NAME_REGEX);
- RE_BonusEndZone = CompileRegex(GOKZ_BONUS_END_ZONE_NAME_REGEX);
-}
-
-void OnStartTouchGround_MapZones(int client)
-{
- touchedGroundSinceTouchingStartZone[client] = true;
-}
-
-void OnEntitySpawned_MapZones(int entity)
-{
- char buffer[32];
-
- GetEntityClassname(entity, buffer, sizeof(buffer));
- if (!StrEqual("trigger_multiple", buffer, false))
- {
- return;
- }
-
- if (GetEntityName(entity, buffer, sizeof(buffer)) == 0)
- {
- return;
- }
-
- int course = 0;
- if (StrEqual(GOKZ_START_ZONE_NAME, buffer, false))
- {
- HookSingleEntityOutput(entity, "OnStartTouch", OnStartZoneStartTouch);
- HookSingleEntityOutput(entity, "OnEndTouch", OnStartZoneEndTouch);
- RegisterCourseStart(course);
- }
- else if (StrEqual(GOKZ_END_ZONE_NAME, buffer, false))
- {
- HookSingleEntityOutput(entity, "OnStartTouch", OnEndZoneStartTouch);
- RegisterCourseEnd(course);
- }
- else if ((course = GetStartZoneBonusNumber(entity)) != -1)
- {
- HookSingleEntityOutput(entity, "OnStartTouch", OnBonusStartZoneStartTouch);
- HookSingleEntityOutput(entity, "OnEndTouch", OnBonusStartZoneEndTouch);
- RegisterCourseStart(course);
- }
- else if ((course = GetEndZoneBonusNumber(entity)) != -1)
- {
- HookSingleEntityOutput(entity, "OnStartTouch", OnBonusEndZoneStartTouch);
- RegisterCourseEnd(course);
- }
-}
-
-public void OnStartZoneStartTouch(const char[] name, int caller, int activator, float delay)
-{
- if (!IsValidEntity(caller) || !IsValidClient(activator))
- {
- return;
- }
-
- ProcessStartZoneStartTouch(activator, 0);
-}
-
-public void OnStartZoneEndTouch(const char[] name, int caller, int activator, float delay)
-{
- if (!IsValidEntity(caller) || !IsValidClient(activator))
- {
- return;
- }
-
- ProcessStartZoneEndTouch(activator, 0);
-}
-
-public void OnEndZoneStartTouch(const char[] name, int caller, int activator, float delay)
-{
- if (!IsValidEntity(caller) || !IsValidClient(activator))
- {
- return;
- }
-
- ProcessEndZoneStartTouch(activator, 0);
-}
-
-public void OnBonusStartZoneStartTouch(const char[] name, int caller, int activator, float delay)
-{
- if (!IsValidEntity(caller) || !IsValidClient(activator))
- {
- return;
- }
-
- int course = GetStartZoneBonusNumber(caller);
- if (!GOKZ_IsValidCourse(course, true))
- {
- return;
- }
-
- ProcessStartZoneStartTouch(activator, course);
-}
-
-public void OnBonusStartZoneEndTouch(const char[] name, int caller, int activator, float delay)
-{
- if (!IsValidEntity(caller) || !IsValidClient(activator))
- {
- return;
- }
-
- int course = GetStartZoneBonusNumber(caller);
- if (!GOKZ_IsValidCourse(course, true))
- {
- return;
- }
-
- ProcessStartZoneEndTouch(activator, course);
-}
-
-public void OnBonusEndZoneStartTouch(const char[] name, int caller, int activator, float delay)
-{
- if (!IsValidEntity(caller) || !IsValidClient(activator))
- {
- return;
- }
-
- int course = GetEndZoneBonusNumber(caller);
- if (!GOKZ_IsValidCourse(course, true))
- {
- return;
- }
-
- ProcessEndZoneStartTouch(activator, course);
-}
-
-
-
-// =====[ PRIVATE ]=====
-
-static void ProcessStartZoneStartTouch(int client, int course)
-{
- touchedGroundSinceTouchingStartZone[client] = Movement_GetOnGround(client);
-
- GOKZ_StopTimer(client, false);
- SetCurrentCourse(client, course);
-
- OnStartZoneStartTouch_Teleports(client, course);
-}
-
-static void ProcessStartZoneEndTouch(int client, int course)
-{
- if (!touchedGroundSinceTouchingStartZone[client])
- {
- return;
- }
-
- GOKZ_StartTimer(client, course, true);
- GOKZ_ResetVirtualButtonPosition(client, true);
-}
-
-static void ProcessEndZoneStartTouch(int client, int course)
-{
- GOKZ_EndTimer(client, course);
- GOKZ_ResetVirtualButtonPosition(client, false);
-}
-
-static int GetStartZoneBonusNumber(int entity)
-{
- return GOKZ_MatchIntFromEntityName(entity, RE_BonusStartZone, 1);
-}
-
-static int GetEndZoneBonusNumber(int entity)
-{
- return GOKZ_MatchIntFromEntityName(entity, RE_BonusEndZone, 1);
-} \ No newline at end of file
diff --git a/sourcemod/scripting/gokz-core/menus/mode_menu.sp b/sourcemod/scripting/gokz-core/menus/mode_menu.sp
deleted file mode 100644
index 934d29c..0000000
--- a/sourcemod/scripting/gokz-core/menus/mode_menu.sp
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- Lets players choose their mode.
-*/
-
-
-
-// =====[ PUBLIC ]=====
-
-void DisplayModeMenu(int client)
-{
- Menu menu = new Menu(MenuHandler_Mode);
- menu.SetTitle("%T", "Mode Menu - Title", client);
- GOKZ_MenuAddModeItems(client, menu, true);
- menu.Display(client, MENU_TIME_FOREVER);
-}
-
-
-
-// =====[ EVENTS ]=====
-
-public int MenuHandler_Mode(Menu menu, MenuAction action, int param1, int param2)
-{
- if (action == MenuAction_Select)
- {
- GOKZ_SetCoreOption(param1, Option_Mode, param2);
- if (GetCameFromOptionsMenu(param1))
- {
- DisplayOptionsMenu(param1, TopMenuPosition_LastCategory);
- }
- }
- else if (action == MenuAction_Cancel && GetCameFromOptionsMenu(param1))
- {
- DisplayOptionsMenu(param1, TopMenuPosition_LastCategory);
- }
- else if (action == MenuAction_End)
- {
- delete menu;
- }
- return 0;
-} \ No newline at end of file
diff --git a/sourcemod/scripting/gokz-core/menus/options_menu.sp b/sourcemod/scripting/gokz-core/menus/options_menu.sp
deleted file mode 100644
index 240ee81..0000000
--- a/sourcemod/scripting/gokz-core/menus/options_menu.sp
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- TopMenu that allows users to browse categories of options.
-
- Adds core options to the general category where players
- can cycle the value of each core option.
-*/
-
-
-
-static TopMenu optionsMenu;
-static TopMenuObject catGeneral;
-static TopMenuObject itemsGeneral[OPTION_COUNT];
-static bool cameFromOptionsMenu[MAXPLAYERS + 1];
-
-
-
-// =====[ PUBLIC ]=====
-
-void DisplayOptionsMenu(int client, TopMenuPosition position = TopMenuPosition_Start)
-{
- optionsMenu.Display(client, position);
- cameFromOptionsMenu[client] = false;
-}
-
-TopMenu GetOptionsTopMenu()
-{
- return optionsMenu;
-}
-
-bool GetCameFromOptionsMenu(int client)
-{
- return cameFromOptionsMenu[client];
-}
-
-
-
-// =====[ LISTENERS ]=====
-
-void OnAllPluginsLoaded_OptionsMenu()
-{
- optionsMenu = new TopMenu(TopMenuHandler_Options);
- Call_GOKZ_OnOptionsMenuCreated(optionsMenu);
- Call_GOKZ_OnOptionsMenuReady(optionsMenu);
-}
-
-void OnConfigsExecuted_OptionsMenu()
-{
- SortOptionsMenu();
-}
-
-void OnOptionsMenuCreated_OptionsMenu()
-{
- catGeneral = optionsMenu.AddCategory(GENERAL_OPTION_CATEGORY, TopMenuHandler_Options);
-}
-
-void OnOptionsMenuReady_OptionsMenu()
-{
- for (int option = 0; option < view_as<int>(OPTION_COUNT); option++)
- {
- if (option == view_as<int>(Option_Style))
- {
- continue; // TODO Currently hard-coded to skip style
- }
- itemsGeneral[option] = optionsMenu.AddItem(gC_CoreOptionNames[option], TopMenuHandler_General, catGeneral);
- }
-}
-
-
-
-// =====[ HANDLER ]=====
-
-public void TopMenuHandler_Options(TopMenu topmenu, TopMenuAction action, TopMenuObject topobj_id, int param, char[] buffer, int maxlength)
-{
- if (action == TopMenuAction_DisplayOption || action == TopMenuAction_DisplayTitle)
- {
- if (topobj_id == INVALID_TOPMENUOBJECT)
- {
- Format(buffer, maxlength, "%T", "Options Menu - Title", param);
- }
- else if (topobj_id == catGeneral)
- {
- Format(buffer, maxlength, "%T", "Options Menu - General", param);
- }
- }
-}
-
-public void TopMenuHandler_General(TopMenu topmenu, TopMenuAction action, TopMenuObject topobj_id, int param, char[] buffer, int maxlength)
-{
- Option option = OPTION_INVALID;
- for (int i = 0; i < view_as<int>(OPTION_COUNT); i++)
- {
- if (topobj_id == itemsGeneral[i])
- {
- option = view_as<Option>(i);
- break;
- }
- }
-
- if (option == OPTION_INVALID)
- {
- return;
- }
-
- if (action == TopMenuAction_DisplayOption)
- {
- switch (option)
- {
- case Option_Mode:
- {
- FormatEx(buffer, maxlength, "%T - %s",
- gC_CoreOptionPhrases[option], param,
- gC_ModeNames[GOKZ_GetCoreOption(param, option)]);
- }
- case Option_TimerButtonZoneType:
- {
- FormatEx(buffer, maxlength, "%T - %T",
- gC_CoreOptionPhrases[option], param,
- gC_TimerButtonZoneTypePhrases[GOKZ_GetCoreOption(param, option)], param);
- }
- case Option_Safeguard:
- {
- FormatEx(buffer, maxlength, "%T - %T",
- gC_CoreOptionPhrases[option], param,
- gC_SafeGuardPhrases[GOKZ_GetCoreOption(param, option)], param);
- }
- default:FormatToggleableOptionDisplay(param, option, buffer, maxlength);
- }
- }
- else if (action == TopMenuAction_SelectOption)
- {
- switch (option)
- {
- case Option_Mode:
- {
- cameFromOptionsMenu[param] = true;
- DisplayModeMenu(param);
- }
- default:
- {
- GOKZ_CycleCoreOption(param, option);
- optionsMenu.Display(param, TopMenuPosition_LastCategory);
- }
- }
- }
-}
-
-
-
-// =====[ PRIVATE ]=====
-
-static void SortOptionsMenu()
-{
- char error[256];
- if (!optionsMenu.LoadConfig(GOKZ_CFG_OPTIONS_SORTING, error, sizeof(error)))
- {
- LogError("Failed to load file: \"%s\". Error: %s", GOKZ_CFG_OPTIONS_SORTING, error);
- }
-}
-
-static void FormatToggleableOptionDisplay(int client, Option option, char[] buffer, int maxlength)
-{
- if (GOKZ_GetCoreOption(client, option) == 0)
- {
- FormatEx(buffer, maxlength, "%T - %T",
- gC_CoreOptionPhrases[option], client,
- "Options Menu - Disabled", client);
- }
- else
- {
- FormatEx(buffer, maxlength, "%T - %T",
- gC_CoreOptionPhrases[option], client,
- "Options Menu - Enabled", client);
- }
-} \ No newline at end of file
diff --git a/sourcemod/scripting/gokz-core/misc.sp b/sourcemod/scripting/gokz-core/misc.sp
deleted file mode 100644
index a117880..0000000
--- a/sourcemod/scripting/gokz-core/misc.sp
+++ /dev/null
@@ -1,803 +0,0 @@
-/*
- Small features that aren't worth splitting into their own file.
-*/
-
-
-
-// =====[ GOKZ.CFG ]=====
-
-void OnMapStart_KZConfig()
-{
- char gokzCfgFullPath[PLATFORM_MAX_PATH];
- FormatEx(gokzCfgFullPath, sizeof(gokzCfgFullPath), "cfg/%s", GOKZ_CFG_SERVER);
-
- if (FileExists(gokzCfgFullPath))
- {
- ServerCommand("exec %s", GOKZ_CFG_SERVER);
- }
- else
- {
- SetFailState("Failed to load file: \"%s\". Check that it exists.", gokzCfgFullPath);
- }
-}
-
-
-
-// =====[ GODMODE ]=====
-
-void OnPlayerSpawn_GodMode(int client)
-{
- // Stop players from taking damage
- SetEntProp(client, Prop_Data, "m_takedamage", 0);
- SetEntityFlags(client, GetEntityFlags(client) | FL_GODMODE);
-}
-
-
-
-// =====[ NOCLIP ]=====
-
-int noclipReleaseTime[MAXPLAYERS + 1];
-
-void ToggleNoclip(int client)
-{
- if (Movement_GetMovetype(client) != MOVETYPE_NOCLIP)
- {
- EnableNoclip(client);
- }
- else
- {
- DisableNoclip(client);
- }
-}
-
-void EnableNoclip(int client)
-{
- if (IsValidClient(client) && IsPlayerAlive(client))
- {
- if (GOKZ_GetCoreOption(client, Option_Safeguard) > Safeguard_Disabled && GOKZ_GetTimerRunning(client) && GOKZ_GetValidTimer(client))
- {
- GOKZ_PrintToChat(client, true, "%t", "Safeguard - Blocked");
- GOKZ_PlayErrorSound(client);
- return;
- }
- Movement_SetMovetype(client, MOVETYPE_NOCLIP);
- GOKZ_StopTimer(client);
- }
-}
-
-void DisableNoclip(int client)
-{
- if (IsValidClient(client) && IsPlayerAlive(client) && Movement_GetMovetype(client) == MOVETYPE_NOCLIP)
- {
- noclipReleaseTime[client] = GetGameTickCount();
- Movement_SetMovetype(client, MOVETYPE_WALK);
- SetEntProp(client, Prop_Send, "m_CollisionGroup", GOKZ_COLLISION_GROUP_STANDARD);
-
- // Prevents an exploit that would let you noclip out of start zones
- RemoveNoclipGroundFlag(client);
- }
-}
-
-void ToggleNoclipNotrigger(int client)
-{
- if (Movement_GetMovetype(client) != MOVETYPE_NOCLIP)
- {
- EnableNoclipNotrigger(client);
- }
- else
- {
- DisableNoclipNotrigger(client);
- }
-}
-
-void EnableNoclipNotrigger(int client)
-{
- if (IsValidClient(client) && IsPlayerAlive(client))
- {
- if (GOKZ_GetCoreOption(client, Option_Safeguard) > Safeguard_Disabled && GOKZ_GetTimerRunning(client) && GOKZ_GetValidTimer(client))
- {
- GOKZ_PrintToChat(client, true, "%t", "Safeguard - Blocked");
- GOKZ_PlayErrorSound(client);
- return;
- }
- Movement_SetMovetype(client, MOVETYPE_NOCLIP);
- SetEntProp(client, Prop_Send, "m_CollisionGroup", GOKZ_COLLISION_GROUP_NOTRIGGER);
- GOKZ_StopTimer(client);
- }
-}
-
-void DisableNoclipNotrigger(int client)
-{
- if (IsValidClient(client) && IsPlayerAlive(client) && Movement_GetMovetype(client) == MOVETYPE_NOCLIP)
- {
- noclipReleaseTime[client] = GetGameTickCount();
- Movement_SetMovetype(client, MOVETYPE_WALK);
- SetEntProp(client, Prop_Send, "m_CollisionGroup", GOKZ_COLLISION_GROUP_STANDARD);
-
- // Prevents an exploit that would let you noclip out of start zones
- RemoveNoclipGroundFlag(client);
- }
-}
-
-void RemoveNoclipGroundFlag(int client)
-{
- float startPosition[3], endPosition[3];
- GetClientAbsOrigin(client, startPosition);
- endPosition = startPosition;
- endPosition[2] = startPosition[2] - 2.0;
- Handle trace = TR_TraceHullFilterEx(
- startPosition,
- endPosition,
- view_as<float>( { -16.0, -16.0, 0.0 } ),
- view_as<float>( { 16.0, 16.0, 72.0 } ),
- MASK_PLAYERSOLID,
- TraceEntityFilterPlayers,
- client);
-
- if (!TR_DidHit(trace))
- {
- SetEntityFlags(client, GetEntityFlags(client) & ~FL_ONGROUND);
- }
- delete trace;
-}
-
-bool JustNoclipped(int client)
-{
- return GetGameTickCount() - noclipReleaseTime[client] <= GOKZ_TIMER_START_NOCLIP_TICKS;
-}
-
-void OnClientPutInServer_Noclip(int client)
-{
- noclipReleaseTime[client] = 0;
-}
-
-// =====[ TURNBINDS ]=====
-
-static int turnbindsLastLeftStart[MAXPLAYERS + 1];
-static int turnbindsLastRightStart[MAXPLAYERS + 1];
-static float turnbindsLastValidYaw[MAXPLAYERS + 1];
-static int turnbindsOldButtons[MAXPLAYERS + 1];
-
-void OnClientPutInServer_Turnbinds(int client)
-{
- turnbindsLastLeftStart[client] = 0;
- turnbindsLastRightStart[client] = 0;
-}
-// Ensures that there is a minimum time between starting to turnbind in one direction
-// and then starting to turnbind in the other direction
-void OnPlayerRunCmd_Turnbinds(int client, int buttons, int tickcount, float angles[3])
-{
- if (IsFakeClient(client))
- {
- return;
- }
- if (buttons & IN_LEFT && tickcount < turnbindsLastRightStart[client] + RoundToNearest(GOKZ_TURNBIND_COOLDOWN / GetTickInterval()))
- {
- angles[1] = turnbindsLastValidYaw[client];
- TeleportEntity(client, NULL_VECTOR, angles, NULL_VECTOR);
- buttons = 0;
- }
- else if (buttons & IN_RIGHT && tickcount < turnbindsLastLeftStart[client] + RoundToNearest(GOKZ_TURNBIND_COOLDOWN / GetTickInterval()))
- {
- angles[1] = turnbindsLastValidYaw[client];
- TeleportEntity(client, NULL_VECTOR, angles, NULL_VECTOR);
- buttons = 0;
- }
- else
- {
- turnbindsLastValidYaw[client] = angles[1];
-
- if (!(turnbindsOldButtons[client] & IN_LEFT) && (buttons & IN_LEFT))
- {
- turnbindsLastLeftStart[client] = tickcount;
- }
-
- if (!(turnbindsOldButtons[client] & IN_RIGHT) && (buttons & IN_RIGHT))
- {
- turnbindsLastRightStart[client] = tickcount;
- }
-
- turnbindsOldButtons[client] = buttons;
- }
-}
-
-
-
-// =====[ PLAYER COLLISION ]=====
-
-void OnPlayerSpawn_PlayerCollision(int client)
-{
- // Let players go through other players
- SetEntProp(client, Prop_Send, "m_CollisionGroup", GOKZ_COLLISION_GROUP_STANDARD);
-}
-
-void OnSetModel_PlayerCollision(int client)
-{
- // Fix custom models temporarily changing player collisions
- SetEntPropVector(client, Prop_Data, "m_vecMins", PLAYER_MINS);
- if (GetEntityFlags(client) & FL_DUCKING == 0)
- {
- SetEntPropVector(client, Prop_Data, "m_vecMaxs", PLAYER_MAXS);
- }
- else
- {
- SetEntPropVector(client, Prop_Data, "m_vecMaxs", PLAYER_MAXS_DUCKED);
- }
-}
-
-
-// =====[ FORCE SV_FULL_ALLTALK 1 ]=====
-
-void OnRoundStart_ForceAllTalk()
-{
- gCV_sv_full_alltalk.BoolValue = true;
-}
-
-
-
-// =====[ ERROR SOUNDS ]=====
-
-#define SOUND_ERROR "buttons/button10.wav"
-
-void PlayErrorSound(int client)
-{
- if (GOKZ_GetCoreOption(client, Option_ErrorSounds) == ErrorSounds_Enabled)
- {
- GOKZ_EmitSoundToClient(client, SOUND_ERROR, _, "Error");
- }
-}
-
-
-
-// =====[ STOP SOUNDS ]=====
-
-Action OnNormalSound_StopSounds(int entity)
-{
- char className[20];
- GetEntityClassname(entity, className, sizeof(className));
- if (StrEqual(className, "func_button", false))
- {
- return Plugin_Handled; // No sounds directly from func_button
- }
- return Plugin_Continue;
-}
-
-
-
-// =====[ JOIN TEAM HANDLING ]=====
-
-static bool hasSavedPosition[MAXPLAYERS + 1];
-static float savedOrigin[MAXPLAYERS + 1][3];
-static float savedAngles[MAXPLAYERS + 1][3];
-static bool savedOnLadder[MAXPLAYERS + 1];
-
-void OnClientPutInServer_JoinTeam(int client)
-{
- // Automatically put the player on a team if he doesn't choose one.
- // The mp_force_pick_time convar is the built in way to do this, but that obviously
- // does not call GOKZ_JoinTeam which includes a fix for spawning in the void when
- // there is no valid spawns available.
- CreateTimer(12.0, Timer_ForceJoinTeam, GetClientUserId(client), TIMER_FLAG_NO_MAPCHANGE);
-
- hasSavedPosition[client] = false;
-}
-
-public Action Timer_ForceJoinTeam(Handle timer, int userid)
-{
- int client = GetClientOfUserId(userid);
- if (IsValidClient(client))
- {
- int team = GetClientTeam(client);
- if (team == CS_TEAM_NONE)
- {
- GOKZ_JoinTeam(client, CS_TEAM_SPECTATOR, false);
- }
- }
- return Plugin_Stop;
-}
-
-void OnTimerStart_JoinTeam(int client)
-{
- hasSavedPosition[client] = false;
-}
-
-void JoinTeam(int client, int newTeam, bool restorePos, bool forceBroadcast = false)
-{
- KZPlayer player = KZPlayer(client);
- int currentTeam = GetClientTeam(client);
-
- // Don't use CS_TEAM_NONE
- if (newTeam == CS_TEAM_NONE)
- {
- newTeam = CS_TEAM_SPECTATOR;
- }
-
- if (newTeam == CS_TEAM_SPECTATOR && currentTeam != CS_TEAM_SPECTATOR)
- {
- if (currentTeam != CS_TEAM_NONE)
- {
- player.GetOrigin(savedOrigin[client]);
- player.GetEyeAngles(savedAngles[client]);
- savedOnLadder[client] = player.Movetype == MOVETYPE_LADDER;
- hasSavedPosition[client] = true;
- }
-
- if (!player.Paused && !player.CanPause)
- {
- player.StopTimer();
- }
- ChangeClientTeam(client, CS_TEAM_SPECTATOR);
- Call_GOKZ_OnJoinTeam(client, newTeam);
- }
- else if (newTeam == CS_TEAM_CT && currentTeam != CS_TEAM_CT
- || newTeam == CS_TEAM_T && currentTeam != CS_TEAM_T)
- {
- ForcePlayerSuicide(client);
- CS_SwitchTeam(client, newTeam);
- CS_RespawnPlayer(client);
- if (restorePos && hasSavedPosition[client])
- {
- TeleportPlayer(client, savedOrigin[client], savedAngles[client]);
- if (savedOnLadder[client])
- {
- player.Movetype = MOVETYPE_LADDER;
- }
- }
- else
- {
- player.StopTimer();
- // Just joining a team alone can put you into weird invalid spawns.
- // Need to teleport the player to a valid one.
- float spawnOrigin[3];
- float spawnAngles[3];
- GetValidSpawn(spawnOrigin, spawnAngles);
- TeleportPlayer(client, spawnOrigin, spawnAngles);
- }
- hasSavedPosition[client] = false;
- Call_GOKZ_OnJoinTeam(client, newTeam);
- }
- else if (forceBroadcast)
- {
- Call_GOKZ_OnJoinTeam(client, newTeam);
- }
-}
-
-void SendFakeTeamEvent(int client)
-{
- // Send a fake event to close the team menu
- Event event = CreateEvent("player_team");
- event.SetInt("userid", GetClientUserId(client));
- event.FireToClient(client);
- event.Cancel();
-}
-
-// =====[ VALID JUMP TRACKING ]=====
-
-/*
- Valid jump tracking is intended to detect when the player
- has performed a normal jump that hasn't been affected by
- (unexpected) teleports or other cases that may result in
- the player becoming airborne, such as spawning.
-
- There are ways to trick the plugin, but it is rather
- unlikely to happen during normal gameplay.
-*/
-
-static bool validJump[MAXPLAYERS + 1];
-static float validJumpTeleportOrigin[MAXPLAYERS + 1][3];
-static int lastInvalidatedTick[MAXPLAYERS + 1];
-bool GetValidJump(int client)
-{
- return validJump[client];
-}
-
-static void InvalidateJump(int client)
-{
- lastInvalidatedTick[client] = GetGameTickCount();
- if (validJump[client])
- {
- validJump[client] = false;
- Call_GOKZ_OnJumpInvalidated(client);
- }
-}
-
-void OnStopTouchGround_ValidJump(int client, bool jumped, bool ladderJump, bool jumpbug)
-{
- if (Movement_GetMovetype(client) == MOVETYPE_WALK && lastInvalidatedTick[client] != GetGameTickCount())
- {
- validJump[client] = true;
- Call_GOKZ_OnJumpValidated(client, jumped, ladderJump, jumpbug);
- }
- else
- {
- InvalidateJump(client);
- }
-}
-
-void OnPlayerRunCmdPost_ValidJump(int client)
-{
- if (gB_VelocityTeleported[client] || gB_OriginTeleported[client])
- {
- InvalidateJump(client);
- }
-}
-
-void OnChangeMovetype_ValidJump(int client, MoveType oldMovetype, MoveType newMovetype)
-{
- if (oldMovetype == MOVETYPE_LADDER && newMovetype == MOVETYPE_WALK && lastInvalidatedTick[client] != GetGameTickCount()) // Ladderjump
- {
- validJump[client] = true;
- Call_GOKZ_OnJumpValidated(client, false, true, false);
- }
- else
- {
- InvalidateJump(client);
- }
-}
-
-void OnClientDisconnect_ValidJump(int client)
-{
- InvalidateJump(client);
-}
-
-void OnPlayerSpawn_ValidJump(int client)
-{
- // That should definitely be out of bounds
- CopyVector({ 40000.0, 40000.0, 40000.0 }, validJumpTeleportOrigin[client]);
- InvalidateJump(client);
-}
-
-void OnPlayerDeath_ValidJump(int client)
-{
- InvalidateJump(client);
-}
-
-void OnValidOriginChange_ValidJump(int client, const float origin[3])
-{
- CopyVector(origin, validJumpTeleportOrigin[client]);
-}
-
-void OnTeleport_ValidJump(int client)
-{
- float origin[3];
- Movement_GetOrigin(client, origin);
- if (gB_OriginTeleported[client] && GetVectorDistance(validJumpTeleportOrigin[client], origin, true) <= EPSILON)
- {
- gB_OriginTeleported[client] = false;
- CopyVector({ 40000.0, 40000.0, 40000.0 }, validJumpTeleportOrigin[client]);
- return;
- }
-
- if (gB_OriginTeleported[client])
- {
- InvalidateJump(client);
- Call_GOKZ_OnTeleport(client);
- }
-
- if (gB_VelocityTeleported[client])
- {
- InvalidateJump(client);
- }
-}
-
-
-
-// =====[ FIRST SPAWN ]=====
-
-static bool hasSpawned[MAXPLAYERS + 1];
-
-void OnClientPutInServer_FirstSpawn(int client)
-{
- hasSpawned[client] = false;
-}
-
-void OnPlayerSpawn_FirstSpawn(int client)
-{
- int team = GetClientTeam(client);
- if (!hasSpawned[client] && (team == CS_TEAM_CT || team == CS_TEAM_T))
- {
- hasSpawned[client] = true;
- Call_GOKZ_OnFirstSpawn(client);
- }
-}
-
-
-
-// =====[ TIME LIMIT ]=====
-
-void OnConfigsExecuted_TimeLimit()
-{
- CreateTimer(1.0, Timer_TimeLimit, _, TIMER_REPEAT);
-}
-
-public Action Timer_TimeLimit(Handle timer)
-{
- int timelimit;
- if (!GetMapTimeLimit(timelimit) || timelimit == 0)
- {
- return Plugin_Continue;
- }
-
- int timeleft;
- // Check for less than -1 in case we miss 0 - ignore -1 because that means infinite time limit
- if (GetMapTimeLeft(timeleft) && (timeleft == 0 || timeleft < -1))
- {
- CreateTimer(5.0, Timer_EndRound); // End the round after a delay or it won't end the map
- return Plugin_Stop;
- }
-
- return Plugin_Continue;
-}
-
-public Action Timer_EndRound(Handle timer)
-{
- CS_TerminateRound(1.0, CSRoundEnd_Draw, true);
- return Plugin_Continue;
-}
-
-
-
-// =====[ COURSE REGISTER ]=====
-
-static bool startRegistered[GOKZ_MAX_COURSES];
-static bool endRegistered[GOKZ_MAX_COURSES];
-static bool courseRegistered[GOKZ_MAX_COURSES];
-
-bool GetCourseRegistered(int course)
-{
- return courseRegistered[course];
-}
-
-void RegisterCourseStart(int course)
-{
- startRegistered[course] = true;
- TryRegisterCourse(course);
-}
-
-void RegisterCourseEnd(int course)
-{
- endRegistered[course] = true;
- TryRegisterCourse(course);
-}
-
-void OnMapStart_CourseRegister()
-{
- for (int course = 0; course < GOKZ_MAX_COURSES; course++)
- {
- courseRegistered[course] = false;
- }
-}
-
-static void TryRegisterCourse(int course)
-{
- if (!courseRegistered[course] && startRegistered[course] && endRegistered[course])
- {
- courseRegistered[course] = true;
- Call_GOKZ_OnCourseRegistered(course);
- }
-}
-
-
-
-// =====[ SPAWN FIXES ]=====
-
-void OnMapStart_FixMissingSpawns()
-{
- int tSpawn = FindEntityByClassname(-1, "info_player_terrorist");
- int ctSpawn = FindEntityByClassname(-1, "info_player_counterterrorist");
-
- if (tSpawn == -1 && ctSpawn == -1)
- {
- LogMessage("Couldn't fix spawns because none exist.");
- return;
- }
-
- if (tSpawn == -1 || ctSpawn == -1)
- {
- float origin[3], angles[3];
- GetValidSpawn(origin, angles);
-
- int newSpawn = CreateEntityByName((tSpawn == -1) ? "info_player_terrorist" : "info_player_counterterrorist");
- if (DispatchSpawn(newSpawn))
- {
- TeleportEntity(newSpawn, origin, angles, NULL_VECTOR);
- }
- }
-}
-
-// =====[ BUTTONS ]=====
-
-void OnClientPreThinkPost_UseButtons(int client)
-{
- if (GOKZ_GetCoreOption(client, Option_ButtonThroughPlayers) == ButtonThroughPlayers_Enabled && GetEntProp(client, Prop_Data, "m_afButtonPressed") & IN_USE)
- {
- int entity = FindUseEntity(client);
- if (entity != -1)
- {
- AcceptEntityInput(entity, "Use", client, client, 1);
- }
- }
-}
-
-static int FindUseEntity(int client)
-{
- float fwd[3];
- float angles[3];
- GetClientEyeAngles(client, angles);
- GetAngleVectors(angles, fwd, NULL_VECTOR, NULL_VECTOR);
-
- Handle trace;
-
- float eyeOrigin[3];
- GetClientEyePosition(client, eyeOrigin);
- int useableContents = (MASK_NPCSOLID_BRUSHONLY | MASK_OPAQUE_AND_NPCS) & ~CONTENTS_OPAQUE;
-
- float endpos[3];
-
- // Check if +use trace collide with a player first, so we don't activate any button twice
- trace = TR_TraceRayFilterEx(eyeOrigin, angles, useableContents, RayType_Infinite, TRFOtherPlayersOnly, client);
- if (TR_DidHit(trace))
- {
- int ent = TR_GetEntityIndex(trace);
- if (ent < 1 || ent > MaxClients)
- {
- return -1;
- }
- // Search for a button behind it.
- trace = TR_TraceRayFilterEx(eyeOrigin, angles, useableContents, RayType_Infinite, TraceEntityFilterPlayers);
- if (TR_DidHit(trace))
- {
- char buffer[20];
- ent = TR_GetEntityIndex(trace);
- // Make sure that it is a button, and this button activates when pressed.
- // If it is not a button, check its parent to see if it is a button.
- bool isButton;
- while (ent != -1)
- {
- GetEntityClassname(ent, buffer, sizeof(buffer));
- if (StrEqual("func_button", buffer, false) && GetEntProp(ent, Prop_Data, "m_spawnflags") & SF_BUTTON_USE_ACTIVATES)
- {
- isButton = true;
- break;
- }
- else
- {
- ent = GetEntPropEnt(ent, Prop_Data, "m_hMoveParent");
- }
- }
- if (isButton)
- {
- TR_GetEndPosition(endpos, trace);
- float delta[3];
- for (int i = 0; i < 2; i++)
- {
- delta[i] = endpos[i] - eyeOrigin[i];
- }
- // Z distance is treated differently.
- float m_vecMins[3];
- float m_vecMaxs[3];
- float m_vecOrigin[3];
- GetEntPropVector(ent, Prop_Send, "m_vecOrigin", m_vecOrigin);
- GetEntPropVector(ent, Prop_Send, "m_vecMins", m_vecMins);
- GetEntPropVector(ent, Prop_Send, "m_vecMaxs", m_vecMaxs);
-
- delta[2] = IntervalDistance(endpos[2], m_vecOrigin[2] + m_vecMins[2], m_vecOrigin[2] + m_vecMaxs[2]);
- if (GetVectorLength(delta) < 80.0)
- {
- return ent;
- }
- }
- }
- }
-
- int nearestEntity;
- float nearestPoint[3];
- float nearestDist = FLOAT_MAX;
- ArrayList entities = new ArrayList();
- TR_EnumerateEntitiesSphere(eyeOrigin, 80.0, 1<<5, AddEntities, entities);
- for (int i = 0; i < entities.Length; i++)
- {
- char buffer[64];
- int ent = entities.Get(i);
- GetEntityClassname(ent, buffer, sizeof(buffer));
- // Check if the entity is a button and it is pressable.
- if (StrEqual("func_button", buffer, false) && GetEntProp(ent, Prop_Data, "m_spawnflags") & SF_BUTTON_USE_ACTIVATES)
- {
- float point[3];
- CalcNearestPoint(ent, eyeOrigin, point);
-
- float dir[3];
- for (int j = 0; j < 3; j++)
- {
- dir[j] = point[j] - eyeOrigin[2];
- }
- // Check the maximum angle the player can be away from the button.
- float minimumDot = GetEntPropFloat(ent, Prop_Send, "m_flUseLookAtAngle");
- NormalizeVector(dir, dir);
- float dot = GetVectorDotProduct(dir, fwd);
- if (dot < minimumDot)
- {
- continue;
- }
-
- float dist = CalcDistanceToLine(point, eyeOrigin, fwd);
- if (dist < nearestDist)
- {
- trace = TR_TraceRayFilterEx(eyeOrigin, point, useableContents, RayType_EndPoint, TraceEntityFilterPlayers);
- if (TR_GetFraction(trace) == 1.0 || TR_GetEntityIndex(trace) == ent)
- {
- CopyVector(point, nearestPoint);
- nearestDist = dist;
- nearestEntity = ent;
- }
- }
- }
- }
- // We found the closest button, but we still need to check if there is a player in front of it or not.
- // In the case that there isn't a player inbetween, we don't return the entity index, because that button will be pressed by the game function anyway.
- // If there is, we will press two buttons at once, the "right" button found by this function and the "wrong" button that we only happen to press because
- // there is a player in the way.
-
- trace = TR_TraceRayFilterEx(eyeOrigin, nearestPoint, useableContents, RayType_EndPoint, TRFOtherPlayersOnly);
- if (TR_DidHit(trace))
- {
- return nearestEntity;
- }
- return -1;
-}
-
-public bool AddEntities(int entity, ArrayList entities)
-{
- entities.Push(entity);
- return true;
-}
-
-static float IntervalDistance(float x, float x0, float x1)
-{
- if (x0 > x1)
- {
- float tmp = x0;
- x0 = x1;
- x1 = tmp;
- }
- if (x < x0)
- {
- return x0 - x;
- }
- else if (x > x1)
- {
- return x - x1;
- }
- return 0.0;
-}
-// TraceRay filter for other players exclusively.
-public bool TRFOtherPlayersOnly(int entity, int contentmask, int client)
-{
- return (0 < entity <= MaxClients) && (entity != client);
-}
-
-// =====[ SAFE MODE ]=====
-
-void ToggleNubSafeGuard(int client)
-{
- if (GOKZ_GetCoreOption(client, Option_Safeguard) == Safeguard_EnabledNUB)
- {
- GOKZ_SetCoreOption(client, Option_Safeguard, Safeguard_Disabled);
- }
- else
- {
- GOKZ_SetCoreOption(client, Option_Safeguard, Safeguard_EnabledNUB);
- }
-}
-
-void ToggleProSafeGuard(int client)
-{
- if (GOKZ_GetCoreOption(client, Option_Safeguard) == Safeguard_EnabledPRO)
- {
- GOKZ_SetCoreOption(client, Option_Safeguard, Safeguard_Disabled);
- }
- else
- {
- GOKZ_SetCoreOption(client, Option_Safeguard, Safeguard_EnabledPRO);
- }
-}
diff --git a/sourcemod/scripting/gokz-core/modes.sp b/sourcemod/scripting/gokz-core/modes.sp
deleted file mode 100644
index ce6f8ae..0000000
--- a/sourcemod/scripting/gokz-core/modes.sp
+++ /dev/null
@@ -1,106 +0,0 @@
-static bool modeLoaded[MODE_COUNT];
-static int modeVersion[MODE_COUNT];
-static bool GOKZHitPerf[MAXPLAYERS + 1];
-static float GOKZTakeoffSpeed[MAXPLAYERS + 1];
-
-
-
-// =====[ PUBLIC ]=====
-
-bool GetModeLoaded(int mode)
-{
- return modeLoaded[mode];
-}
-
-int GetModeVersion(int mode)
-{
- return modeLoaded[mode] ? modeVersion[mode] : -1;
-}
-
-void SetModeLoaded(int mode, bool loaded, int version = -1)
-{
- if (!modeLoaded[mode] && loaded)
- {
- modeLoaded[mode] = true;
- modeVersion[mode] = version;
- Call_GOKZ_OnModeLoaded(mode);
- }
- else if (modeLoaded[mode] && !loaded)
- {
- modeLoaded[mode] = false;
- Call_GOKZ_OnModeUnloaded(mode);
- }
-}
-
-int GetLoadedModeCount()
-{
- int count = 0;
- for (int mode = 0; mode < MODE_COUNT; mode++)
- {
- if (modeLoaded[mode])
- {
- count++;
- }
- }
- return count;
-}
-
-int GetALoadedMode()
-{
- for (int mode = 0; mode < MODE_COUNT; mode++)
- {
- if (GOKZ_GetModeLoaded(mode))
- {
- return mode;
- }
- }
- return -1; // Uh-oh
-}
-
-bool GetGOKZHitPerf(int client)
-{
- return GOKZHitPerf[client];
-}
-
-void SetGOKZHitPerf(int client, bool hitPerf)
-{
- GOKZHitPerf[client] = hitPerf;
-}
-
-float GetGOKZTakeoffSpeed(int client)
-{
- return GOKZTakeoffSpeed[client];
-}
-
-void SetGOKZTakeoffSpeed(int client, float takeoffSpeed)
-{
- GOKZTakeoffSpeed[client] = takeoffSpeed;
-}
-
-
-
-// =====[ EVENTS ]=====
-
-void OnAllPluginsLoaded_Modes()
-{
- if (GetLoadedModeCount() <= 0)
- {
- SetFailState("At least one GOKZ mode plugin is required.");
- }
-}
-
-void OnPlayerSpawn_Modes(int client)
-{
- GOKZHitPerf[client] = false;
- GOKZTakeoffSpeed[client] = 0.0;
-}
-
-void OnOptionChanged_Mode(int client, Option option)
-{
- if (option == Option_Mode)
- {
- // Remove speed when switching modes
- Movement_SetVelocityModifier(client, 1.0);
- Movement_SetVelocity(client, view_as<float>( { 0.0, 0.0, 0.0 } ));
- }
-} \ No newline at end of file
diff --git a/sourcemod/scripting/gokz-core/natives.sp b/sourcemod/scripting/gokz-core/natives.sp
deleted file mode 100644
index 319810c..0000000
--- a/sourcemod/scripting/gokz-core/natives.sp
+++ /dev/null
@@ -1,647 +0,0 @@
-void CreateNatives()
-{
- CreateNative("GOKZ_GetModeLoaded", Native_GetModeLoaded);
- CreateNative("GOKZ_GetModeVersion", Native_GetModeVersion);
- CreateNative("GOKZ_SetModeLoaded", Native_SetModeLoaded);
- CreateNative("GOKZ_GetLoadedModeCount", Native_GetLoadedModeCount);
- CreateNative("GOKZ_SetMode", Native_SetMode);
- CreateNative("GOKZ_PrintToChat", Native_PrintToChat);
- CreateNative("GOKZ_PrintToChatAndLog", Native_PrintToChatAndLog);
- CreateNative("GOKZ_GetOptionsTopMenu", Native_GetOptionsTopMenu);
- CreateNative("GOKZ_GetCourseRegistered", Native_GetCourseRegistered);
-
- CreateNative("GOKZ_StartTimer", Native_StartTimer);
- CreateNative("GOKZ_EndTimer", Native_EndTimer);
- CreateNative("GOKZ_StopTimer", Native_StopTimer);
- CreateNative("GOKZ_StopTimerAll", Native_StopTimerAll);
- CreateNative("GOKZ_TeleportToStart", Native_TeleportToStart);
- CreateNative("GOKZ_TeleportToSearchStart", Native_TeleportToSearchStart);
- CreateNative("GOKZ_GetVirtualButtonPosition", Native_GetVirtualButtonPosition);
- CreateNative("GOKZ_SetVirtualButtonPosition", Native_SetVirtualButtonPosition);
- CreateNative("GOKZ_ResetVirtualButtonPosition", Native_ResetVirtualButtonPosition);
- CreateNative("GOKZ_LockVirtualButtons", Native_LockVirtualButtons);
- CreateNative("GOKZ_GetStartPosition", Native_GetStartPosition);
- CreateNative("GOKZ_SetStartPosition", Native_SetStartPosition);
- CreateNative("GOKZ_TeleportToEnd", Native_TeleportToEnd);
- CreateNative("GOKZ_GetStartPositionType", Native_GetStartPositionType);
- CreateNative("GOKZ_SetStartPositionToMapStart", Native_SetStartPositionToMapStart);
- CreateNative("GOKZ_MakeCheckpoint", Native_MakeCheckpoint);
- CreateNative("GOKZ_GetCanMakeCheckpoint", Native_GetCanMakeCheckpoint);
- CreateNative("GOKZ_TeleportToCheckpoint", Native_TeleportToCheckpoint);
- CreateNative("GOKZ_GetCanTeleportToCheckpoint", Native_GetCanTeleportToCheckpoint);
- CreateNative("GOKZ_PrevCheckpoint", Native_PrevCheckpoint);
- CreateNative("GOKZ_GetCanPrevCheckpoint", Native_GetCanPrevCheckpoint);
- CreateNative("GOKZ_NextCheckpoint", Native_NextCheckpoint);
- CreateNative("GOKZ_GetCanNextCheckpoint", Native_GetCanNextCheckpoint);
- CreateNative("GOKZ_UndoTeleport", Native_UndoTeleport);
- CreateNative("GOKZ_GetCanUndoTeleport", Native_GetCanUndoTeleport);
- CreateNative("GOKZ_Pause", Native_Pause);
- CreateNative("GOKZ_GetCanPause", Native_GetCanPause);
- CreateNative("GOKZ_Resume", Native_Resume);
- CreateNative("GOKZ_GetCanResume", Native_GetCanResume);
- CreateNative("GOKZ_TogglePause", Native_TogglePause);
- CreateNative("GOKZ_GetCanTeleportToStart", Native_GetCanTeleportToStart);
- CreateNative("GOKZ_GetCanTeleportToEnd", Native_GetCanTeleportToEnd);
- CreateNative("GOKZ_PlayErrorSound", Native_PlayErrorSound);
- CreateNative("GOKZ_SetValidJumpOrigin", Native_SetValidJumpOrigin);
-
- CreateNative("GOKZ_GetTimerRunning", Native_GetTimerRunning);
- CreateNative("GOKZ_GetValidTimer", Native_GetValidTimer);
- CreateNative("GOKZ_GetCourse", Native_GetCourse);
- CreateNative("GOKZ_SetCourse", Native_SetCourse);
- CreateNative("GOKZ_GetPaused", Native_GetPaused);
- CreateNative("GOKZ_GetTime", Native_GetTime);
- CreateNative("GOKZ_SetTime", Native_SetTime);
- CreateNative("GOKZ_InvalidateRun", Native_InvalidateRun);
- CreateNative("GOKZ_GetCheckpointCount", Native_GetCheckpointCount);
- CreateNative("GOKZ_SetCheckpointCount", Native_SetCheckpointCount);
- CreateNative("GOKZ_GetCheckpointData", Native_GetCheckpointData);
- CreateNative("GOKZ_SetCheckpointData", Native_SetCheckpointData);
- CreateNative("GOKZ_GetUndoTeleportData", Native_GetUndoTeleportData);
- CreateNative("GOKZ_SetUndoTeleportData", Native_SetUndoTeleportData);
- CreateNative("GOKZ_GetTeleportCount", Native_GetTeleportCount);
- CreateNative("GOKZ_SetTeleportCount", Native_SetTeleportCount);
- CreateNative("GOKZ_RegisterOption", Native_RegisterOption);
- CreateNative("GOKZ_GetOptionProp", Native_GetOptionProp);
- CreateNative("GOKZ_SetOptionProp", Native_SetOptionProp);
- CreateNative("GOKZ_GetOption", Native_GetOption);
- CreateNative("GOKZ_SetOption", Native_SetOption);
- CreateNative("GOKZ_GetHitPerf", Native_GetHitPerf);
- CreateNative("GOKZ_SetHitPerf", Native_SetHitPerf);
- CreateNative("GOKZ_GetTakeoffSpeed", Native_GetTakeoffSpeed);
- CreateNative("GOKZ_SetTakeoffSpeed", Native_SetTakeoffSpeed);
- CreateNative("GOKZ_GetValidJump", Native_GetValidJump);
- CreateNative("GOKZ_JoinTeam", Native_JoinTeam);
-
- CreateNative("GOKZ_EmitSoundToClient", Native_EmitSoundToClient);
-}
-
-public int Native_GetModeLoaded(Handle plugin, int numParams)
-{
- return view_as<int>(GetModeLoaded(GetNativeCell(1)));
-}
-
-public int Native_GetModeVersion(Handle plugin, int numParams)
-{
- return view_as<int>(GetModeVersion(GetNativeCell(1)));
-}
-
-public int Native_SetModeLoaded(Handle plugin, int numParams)
-{
- SetModeLoaded(GetNativeCell(1), GetNativeCell(2), GetNativeCell(3));
- return 0;
-}
-
-public int Native_GetLoadedModeCount(Handle plugin, int numParams)
-{
- return GetLoadedModeCount();
-}
-
-public int Native_SetMode(Handle plugin, int numParams)
-{
- return view_as<bool>(SwitchToModeIfAvailable(GetNativeCell(1),GetNativeCell(2)));
-}
-
-public int Native_PrintToChatAndLog(Handle plugin, int numParams)
-{
- NativeHelper_PrintToChatOrLog(true);
- return 0;
-}
-
-public int Native_PrintToChat(Handle plugin, int numParams)
-{
- NativeHelper_PrintToChatOrLog(false);
- return 0;
-}
-
-static int NativeHelper_PrintToChatOrLog(bool alwaysLog)
-{
- int client = GetNativeCell(1);
- bool addPrefix = GetNativeCell(2);
-
- char buffer[1024];
- SetGlobalTransTarget(client);
- FormatNativeString(0, 3, 4, sizeof(buffer), _, buffer);
-
- // The console (client 0) gets a special treatment
- if (client == 0 || (!IsValidClient(client) && !IsClientSourceTV(client)) || alwaysLog)
- {
- // Strip colors
- // We can't regex-replace, so I'm quite sure that's the most efficient way.
- // It's also not perfectly safe, we will just assume you never have curly
- // braces without a color in beween.
- char colorlessBuffer[1024];
- FormatEx(colorlessBuffer, sizeof(colorlessBuffer), "%L: ", client);
- int iIn = 0, iOut = strlen(colorlessBuffer);
- do
- {
- if (buffer[iIn] == '{')
- {
- for (; buffer[iIn] != '}' && iIn < sizeof(buffer) - 2; iIn++){}
- if (iIn >= sizeof(buffer) - 2)
- {
- break;
- }
- iIn++;
- continue;
- }
-
- colorlessBuffer[iOut] = buffer[iIn];
- iIn++;
- iOut++;
- } while (buffer[iIn] != '\0' && iIn < sizeof(buffer) - 1 && iOut < sizeof(colorlessBuffer) - 1);
- colorlessBuffer[iOut] = '\0';
- LogMessage(colorlessBuffer);
- }
-
- if (client != 0)
- {
- if (addPrefix)
- {
- char prefix[64];
- gCV_gokz_chat_prefix.GetString(prefix, sizeof(prefix));
- Format(buffer, sizeof(buffer), "%s%s", prefix, buffer);
- }
-
- CPrintToChat(client, "%s", buffer);
- }
- return 0;
-}
-
-public int Native_GetOptionsTopMenu(Handle plugin, int numParams)
-{
- return view_as<int>(GetOptionsTopMenu());
-}
-
-public int Native_GetCourseRegistered(Handle plugin, int numParams)
-{
- return view_as<int>(GetCourseRegistered(GetNativeCell(1)));
-}
-
-public int Native_StartTimer(Handle plugin, int numParams)
-{
- if (BlockedExternallyCalledTimerNative(plugin, GetNativeCell(1)))
- {
- return view_as<int>(false);
- }
-
- return view_as<int>(TimerStart(GetNativeCell(1), GetNativeCell(2), GetNativeCell(3)));
-}
-
-public int Native_EndTimer(Handle plugin, int numParams)
-{
- if (BlockedExternallyCalledTimerNative(plugin, GetNativeCell(1)))
- {
- return view_as<int>(false);
- }
-
- return view_as<int>(TimerEnd(GetNativeCell(1), GetNativeCell(2)));
-}
-
-public int Native_StopTimer(Handle plugin, int numParams)
-{
- return view_as<int>(TimerStop(GetNativeCell(1), GetNativeCell(2)));
-}
-
-public int Native_StopTimerAll(Handle plugin, int numParams)
-{
- TimerStopAll(GetNativeCell(1));
- return 0;
-}
-
-public int Native_TeleportToStart(Handle plugin, int numParams)
-{
- TeleportToStart(GetNativeCell(1));
- return 0;
-}
-
-public int Native_TeleportToSearchStart(Handle plugin, int numParams)
-{
- TeleportToSearchStart(GetNativeCell(1), GetNativeCell(2));
- return 0;
-}
-
-public int Native_GetVirtualButtonPosition(Handle plugin, int numParams)
-{
- int course;
- float position[3];
-
- course = GetVirtualButtonPosition(GetNativeCell(1), position, GetNativeCell(3));
- SetNativeArray(2, position, sizeof(position));
-
- return course;
-}
-
-public int Native_SetVirtualButtonPosition(Handle plugin, int numParams)
-{
- float position[3];
-
- GetNativeArray(2, position, sizeof(position));
- SetVirtualButtonPosition(GetNativeCell(1), position, GetNativeCell(3), view_as<bool>(GetNativeCell(4)));
- return 0;
-}
-
-public int Native_ResetVirtualButtonPosition(Handle plugin, int numParams)
-{
- ResetVirtualButtonPosition(GetNativeCell(1), GetNativeCell(2));
- return 0;
-}
-
-public int Native_LockVirtualButtons(Handle plugin, int numParams)
-{
- LockVirtualButtons(GetNativeCell(1));
- return 0;
-}
-
-public int Native_GetStartPosition(Handle plugin, int numParams)
-{
- StartPositionType type;
- float position[3], angles[3];
-
- type = GetStartPosition(GetNativeCell(1), position, angles);
- SetNativeArray(2, position, sizeof(position));
- SetNativeArray(3, angles, sizeof(angles));
-
- return view_as<int>(type);
-}
-
-public int Native_SetStartPosition(Handle plugin, int numParams)
-{
- float position[3], angles[3];
-
- GetNativeArray(3, position, sizeof(position));
- GetNativeArray(4, angles, sizeof(angles));
- SetStartPosition(GetNativeCell(1), GetNativeCell(2), position, angles);
- return 0;
-}
-
-public int Native_TeleportToEnd(Handle plugin, int numParams)
-{
- TeleportToEnd(GetNativeCell(1), GetNativeCell(2));
- return 0;
-}
-
-public int Native_GetStartPositionType(Handle plugin, int numParams)
-{
- return view_as<int>(GetStartPositionType(GetNativeCell(1)));
-}
-
-public int Native_SetStartPositionToMapStart(Handle plugin, int numParams)
-{
- return SetStartPositionToMapStart(GetNativeCell(1), GetNativeCell(2));
-}
-
-public int Native_MakeCheckpoint(Handle plugin, int numParams)
-{
- MakeCheckpoint(GetNativeCell(1));
- return 0;
-}
-
-public int Native_GetCanMakeCheckpoint(Handle plugin, int numParams)
-{
- return CanMakeCheckpoint(GetNativeCell(1));
-}
-
-public int Native_TeleportToCheckpoint(Handle plugin, int numParams)
-{
- TeleportToCheckpoint(GetNativeCell(1));
- return 0;
-}
-
-public int Native_GetCanTeleportToCheckpoint(Handle plugin, int numParams)
-{
- return CanTeleportToCheckpoint(GetNativeCell(1));
-}
-
-public int Native_PrevCheckpoint(Handle plugin, int numParams)
-{
- PrevCheckpoint(GetNativeCell(1));
- return 0;
-}
-
-public int Native_GetCanPrevCheckpoint(Handle plugin, int numParams)
-{
- return CanPrevCheckpoint(GetNativeCell(1));
-}
-
-public int Native_NextCheckpoint(Handle plugin, int numParams)
-{
- NextCheckpoint(GetNativeCell(1));
- return 0;
-}
-
-public int Native_GetCanNextCheckpoint(Handle plugin, int numParams)
-{
- return CanNextCheckpoint(GetNativeCell(1));
-}
-
-public int Native_UndoTeleport(Handle plugin, int numParams)
-{
- UndoTeleport(GetNativeCell(1));
- return 0;
-}
-
-public int Native_GetCanUndoTeleport(Handle plugin, int numParams)
-{
- return CanUndoTeleport(GetNativeCell(1));
-}
-
-public int Native_Pause(Handle plugin, int numParams)
-{
- Pause(GetNativeCell(1));
- return 0;
-}
-
-public int Native_GetCanPause(Handle plugin, int numParams)
-{
- return CanPause(GetNativeCell(1));
-}
-
-public int Native_Resume(Handle plugin, int numParams)
-{
- Resume(GetNativeCell(1));
- return 0;
-}
-
-public int Native_GetCanResume(Handle plugin, int numParams)
-{
- return CanResume(GetNativeCell(1));
-}
-
-public int Native_TogglePause(Handle plugin, int numParams)
-{
- TogglePause(GetNativeCell(1));
- return 0;
-}
-
-public int Native_GetCanTeleportToStart(Handle plugin, int numParams)
-{
- return CanTeleportToStart(GetNativeCell(1));
-}
-
-public int Native_GetCanTeleportToEnd(Handle plugin, int numParams)
-{
- return CanTeleportToEnd(GetNativeCell(1));
-}
-
-public int Native_PlayErrorSound(Handle plugin, int numParams)
-{
- PlayErrorSound(GetNativeCell(1));
- return 0;
-}
-
-public int Native_SetValidJumpOrigin(Handle plugin, int numParams)
-{
- int client = GetNativeCell(1);
- float origin[3];
- GetNativeArray(2, origin, sizeof(origin));
-
- // The order is important here!
- OnValidOriginChange_ValidJump(client, origin);
-
- // Using Movement_SetOrigin instead causes considerable lag for spectators
- SetEntPropVector(client, Prop_Data, "m_vecAbsOrigin", origin);
- return 0;
-}
-
-public int Native_GetTimerRunning(Handle plugin, int numParams)
-{
- return view_as<int>(GetTimerRunning(GetNativeCell(1)));
-}
-
-public int Native_GetValidTimer(Handle plugin, int numParams)
-{
- return view_as<int>(GetValidTimer(GetNativeCell(1)));
-}
-
-public int Native_GetCourse(Handle plugin, int numParams)
-{
- return GetCurrentCourse(GetNativeCell(1));
-}
-
-public int Native_SetCourse(Handle plugin, int numParams)
-{
- if (BlockedExternallyCalledTimerNative(plugin, GetNativeCell(1)))
- {
- return view_as<int>(false);
- }
- SetCurrentCourse(GetNativeCell(1), GetNativeCell(2));
- return view_as<int>(false);
-}
-
-public int Native_GetPaused(Handle plugin, int numParams)
-{
- return view_as<int>(GetPaused(GetNativeCell(1)));
-}
-
-public int Native_GetTime(Handle plugin, int numParams)
-{
- return view_as<int>(GetCurrentTime(GetNativeCell(1)));
-}
-
-public int Native_SetTime(Handle plugin, int numParams)
-{
- if (BlockedExternallyCalledTimerNative(plugin, GetNativeCell(1)))
- {
- return view_as<int>(false);
- }
-
- SetCurrentTime(GetNativeCell(1), view_as<float>(GetNativeCell(2)));
- return view_as<int>(true);
-}
-
-public int Native_InvalidateRun(Handle plugin, int numParams)
-{
- InvalidateRun(GetNativeCell(1));
- return view_as<int>(true);
-}
-
-public int Native_GetCheckpointCount(Handle plugin, int numParams)
-{
- return GetCheckpointCount(GetNativeCell(1));
-}
-
-public int Native_SetCheckpointCount(Handle plugin, int numParams)
-{
- if (BlockedExternallyCalledTimerNative(plugin, GetNativeCell(1)))
- {
- return view_as<int>(false);
- }
- SetCheckpointCount(GetNativeCell(1), GetNativeCell(2));
- return view_as<int>(true);
-}
-
-public int Native_GetCheckpointData(Handle plugin, int numParams)
-{
- ArrayList temp = GetCheckpointData(GetNativeCell(1));
- Handle cps = CloneHandle(temp, plugin);
- delete temp;
- return view_as<int>(cps);
-}
-
-public int Native_SetCheckpointData(Handle plugin, int numParams)
-{
- if (BlockedExternallyCalledTimerNative(plugin, GetNativeCell(1)))
- {
- return view_as<int>(false);
- }
- return SetCheckpointData(GetNativeCell(1), view_as<ArrayList>(GetNativeCell(2)), GetNativeCell(3));
-}
-
-public int Native_GetUndoTeleportData(Handle plugin, int numParams)
-{
- ArrayList temp = GetUndoTeleportData(GetNativeCell(1));
- Handle utd = CloneHandle(temp, plugin);
- delete temp;
- return view_as<int>(utd);
-}
-
-public int Native_SetUndoTeleportData(Handle plugin, int numParams)
-{
- if (BlockedExternallyCalledTimerNative(plugin, GetNativeCell(1)))
- {
- return view_as<int>(false);
- }
- return SetUndoTeleportData(GetNativeCell(1), view_as<ArrayList>(GetNativeCell(2)), GetNativeCell(3));
-}
-
-public int Native_GetTeleportCount(Handle plugin, int numParams)
-{
- return GetTeleportCount(GetNativeCell(1));
-}
-
-public int Native_SetTeleportCount(Handle plugin, int numParams)
-{
- if (BlockedExternallyCalledTimerNative(plugin, GetNativeCell(1)))
- {
- return view_as<int>(false);
- }
-
- SetTeleportCount(GetNativeCell(1), GetNativeCell(2));
- return view_as<int>(true);
-}
-
-public int Native_RegisterOption(Handle plugin, int numParams)
-{
- char name[GOKZ_OPTION_MAX_NAME_LENGTH];
- GetNativeString(1, name, sizeof(name));
- char description[255];
- GetNativeString(2, description, sizeof(description));
- return view_as<int>(RegisterOption(name, description, GetNativeCell(3), GetNativeCell(4), GetNativeCell(5), GetNativeCell(6)));
-}
-
-public int Native_GetOptionProp(Handle plugin, int numParams)
-{
- char option[GOKZ_OPTION_MAX_NAME_LENGTH];
- GetNativeString(1, option, sizeof(option));
- OptionProp prop = GetNativeCell(2);
- any value = GetOptionProp(option, prop);
-
- // Return clone of Handle if called by another plugin
- if (prop == OptionProp_Cookie && plugin != gH_ThisPlugin)
- {
- value = CloneHandle(value, plugin);
- }
-
- return value;
-}
-
-public int Native_SetOptionProp(Handle plugin, int numParams)
-{
- char option[GOKZ_OPTION_MAX_NAME_LENGTH];
- GetNativeString(1, option, sizeof(option));
- OptionProp prop = GetNativeCell(2);
- return SetOptionProp(option, prop, GetNativeCell(3));
-}
-
-public int Native_GetOption(Handle plugin, int numParams)
-{
- char option[GOKZ_OPTION_MAX_NAME_LENGTH];
- GetNativeString(2, option, sizeof(option));
- return view_as<int>(GetOption(GetNativeCell(1), option));
-}
-
-public int Native_SetOption(Handle plugin, int numParams)
-{
- char option[GOKZ_OPTION_MAX_NAME_LENGTH];
- GetNativeString(2, option, sizeof(option));
- return view_as<int>(SetOption(GetNativeCell(1), option, GetNativeCell(3)));
-}
-
-public int Native_GetHitPerf(Handle plugin, int numParams)
-{
- return view_as<int>(GetGOKZHitPerf(GetNativeCell(1)));
-}
-
-public int Native_SetHitPerf(Handle plugin, int numParams)
-{
- SetGOKZHitPerf(GetNativeCell(1), view_as<bool>(GetNativeCell(2)));
- return 0;
-}
-
-public int Native_GetTakeoffSpeed(Handle plugin, int numParams)
-{
- return view_as<int>(GetGOKZTakeoffSpeed(GetNativeCell(1)));
-}
-
-public int Native_SetTakeoffSpeed(Handle plugin, int numParams)
-{
- SetGOKZTakeoffSpeed(GetNativeCell(1), view_as<float>(GetNativeCell(2)));
- return 0;
-}
-
-public int Native_GetValidJump(Handle plugin, int numParams)
-{
- return view_as<int>(GetValidJump(GetNativeCell(1)));
-}
-
-public int Native_JoinTeam(Handle plugin, int numParams)
-{
- JoinTeam(GetNativeCell(1), GetNativeCell(2), GetNativeCell(3), GetNativeCell(4));
- return 0;
-}
-
-public int Native_EmitSoundToClient(Handle plugin, int numParams)
-{
- int client = GetNativeCell(1);
-
- char sample[PLATFORM_MAX_PATH];
- GetNativeString(2, sample, sizeof(sample));
-
- float volume = GetNativeCell(3);
- float newVolume = volume;
-
- char description[64];
- GetNativeString(4, description, sizeof(description));
-
- Action result;
-
- Call_GOKZ_OnEmitSoundToClient(client, sample, newVolume, description, result);
- if (result == Plugin_Stop)
- {
- return 0;
- }
- if (result == Plugin_Changed)
- {
- EmitSoundToClient(client, sample, _, _, _, _, newVolume);
- return 0;
- }
- EmitSoundToClient(client, sample, _, _, _, _, volume);
- return 0;
-}
-
-// =====[ PRIVATE ]=====
-
-static bool BlockedExternallyCalledTimerNative(Handle plugin, int client)
-{
- if (plugin != gH_ThisPlugin)
- {
- Action result;
- Call_GOKZ_OnTimerNativeCalledExternally(plugin, client, result);
- if (result != Plugin_Continue)
- {
- return true;
- }
- }
- return false;
-}
diff --git a/sourcemod/scripting/gokz-core/options.sp b/sourcemod/scripting/gokz-core/options.sp
deleted file mode 100644
index 6daef13..0000000
--- a/sourcemod/scripting/gokz-core/options.sp
+++ /dev/null
@@ -1,438 +0,0 @@
-static StringMap optionData;
-static StringMap optionDescriptions;
-
-
-
-// =====[ PUBLIC ]=====
-
-bool RegisterOption(const char[] name, const char[] description, OptionType type, any defaultValue, any minValue, any maxValue)
-{
- if (!IsValueInRange(type, defaultValue, minValue, maxValue))
- {
- LogError("Failed to register option \"%s\" due to invalid default value and value range.", name);
- return false;
- }
-
- if (strlen(name) > GOKZ_OPTION_MAX_NAME_LENGTH - 1)
- {
- LogError("Failed to register option \"%s\" because its name is too long.", name);
- return false;
- }
-
- if (strlen(name) > GOKZ_OPTION_MAX_NAME_LENGTH - 1)
- {
- LogError("Failed to register option \"%s\" because its description is too long.", name);
- return false;
- }
-
- ArrayList data;
- Cookie cookie;
- if (IsRegisteredOption(name))
- {
- optionData.GetValue(name, data);
- cookie = GetOptionProp(name, OptionProp_Cookie);
- }
- else
- {
- data = new ArrayList(1, view_as<int>(OPTIONPROP_COUNT));
- cookie = new Cookie(name, description, CookieAccess_Private);
- }
-
- data.Set(view_as<int>(OptionProp_Cookie), cookie);
- data.Set(view_as<int>(OptionProp_Type), type);
- data.Set(view_as<int>(OptionProp_DefaultValue), defaultValue);
- data.Set(view_as<int>(OptionProp_MinValue), minValue);
- data.Set(view_as<int>(OptionProp_MaxValue), maxValue);
-
- optionData.SetValue(name, data, true);
- optionDescriptions.SetString(name, description, true);
-
- // Support late-loading/registering
- for (int client = 1; client <= MaxClients; client++)
- {
- if (AreClientCookiesCached(client))
- {
- LoadOption(client, name);
- }
- }
-
- return true;
-}
-
-any GetOptionProp(const char[] option, OptionProp prop)
-{
- ArrayList data;
- if (!optionData.GetValue(option, data))
- {
- LogError("Failed to get option property of unregistered option \"%s\".", option);
- return -1;
- }
-
- return data.Get(view_as<int>(prop));
-}
-
-bool SetOptionProp(const char[] option, OptionProp prop, any newValue)
-{
- ArrayList data;
- if (!optionData.GetValue(option, data))
- {
- LogError("Failed to set property of unregistered option \"%s\".", option);
- return false;
- }
-
- if (prop == OptionProp_Cookie)
- {
- LogError("Failed to set cookie of option \"%s\" as it is read-only.");
- return false;
- }
-
- OptionType type = GetOptionProp(option, OptionProp_Type);
- any defaultValue = GetOptionProp(option, OptionProp_DefaultValue);
- any minValue = GetOptionProp(option, OptionProp_MinValue);
- any maxValue = GetOptionProp(option, OptionProp_MaxValue);
-
- switch (prop)
- {
- case OptionProp_DefaultValue:
- {
- if (!IsValueInRange(type, newValue, minValue, maxValue))
- {
- LogError("Failed to set default value of option \"%s\" due to invalid default value and value range.", option);
- return false;
- }
- }
- case OptionProp_MinValue:
- {
- if (!IsValueInRange(type, defaultValue, newValue, maxValue))
- {
- LogError("Failed to set minimum value of option \"%s\" due to invalid default value and value range.", option);
- return false;
- }
- }
- case OptionProp_MaxValue:
- {
- if (!IsValueInRange(type, defaultValue, minValue, newValue))
- {
- LogError("Failed to set maximum value of option \"%s\" due to invalid default value and value range.", option);
- return false;
- }
- }
- }
-
- data.Set(view_as<int>(prop), newValue);
- return optionData.SetValue(option, data, true);
-}
-
-any GetOption(int client, const char[] option)
-{
- if (!IsRegisteredOption(option))
- {
- LogError("Failed to get value of unregistered option \"%s\".", option);
- return -1;
- }
-
- Cookie cookie = GetOptionProp(option, OptionProp_Cookie);
- OptionType type = GetOptionProp(option, OptionProp_Type);
- char value[100];
- cookie.Get(client, value, sizeof(value));
-
- if (type == OptionType_Float)
- {
- return StringToFloat(value);
- }
- else //if (type == OptionType_Int)
- {
- return StringToInt(value);
- }
-}
-
-bool SetOption(int client, const char[] option, any newValue)
-{
- if (!IsRegisteredOption(option))
- {
- LogError("Failed to set value of unregistered option \"%s\".", option);
- return false;
- }
-
- if (GetOption(client, option) == newValue)
- {
- return true;
- }
-
- OptionType type = GetOptionProp(option, OptionProp_Type);
- any minValue = GetOptionProp(option, OptionProp_MinValue);
- any maxValue = GetOptionProp(option, OptionProp_MaxValue);
-
- if (!IsValueInRange(type, newValue, minValue, maxValue))
- {
- LogError("Failed to set value of option \"%s\" because desired value was outside registered value range.", option);
- return false;
- }
-
- char newValueString[100];
- if (type == OptionType_Float)
- {
- FloatToString(newValue, newValueString, sizeof(newValueString));
- }
- else //if (type == OptionType_Int)
- {
- IntToString(newValue, newValueString, sizeof(newValueString));
- }
-
- Cookie cookie = GetOptionProp(option, OptionProp_Cookie);
- cookie.Set(client, newValueString);
-
- if (IsClientInGame(client))
- {
- Call_GOKZ_OnOptionChanged(client, option, newValue);
- }
-
- return true;
-}
-
-bool IsRegisteredOption(const char[] option)
-{
- int dummy;
- return optionData.GetValue(option, dummy);
-}
-
-
-
-// =====[ EVENTS ]=====
-
-void OnPluginStart_Options()
-{
- optionData = new StringMap();
- optionDescriptions = new StringMap();
- RegisterOptions();
-}
-
-void OnClientCookiesCached_Options(int client)
-{
- StringMapSnapshot optionDataSnapshot = optionData.Snapshot();
- char option[GOKZ_OPTION_MAX_NAME_LENGTH];
-
- for (int i = 0; i < optionDataSnapshot.Length; i++)
- {
- optionDataSnapshot.GetKey(i, option, sizeof(option));
- LoadOption(client, option);
- }
-
- delete optionDataSnapshot;
-
- Call_GOKZ_OnOptionsLoaded(client);
-}
-
-void OnClientPutInServer_Options(int client)
-{
- if (!GetModeLoaded(GOKZ_GetCoreOption(client, Option_Mode)))
- {
- GOKZ_SetCoreOption(client, Option_Mode, GetALoadedMode());
- }
-}
-
-void OnOptionChanged_Options(int client, Option option, int newValue)
-{
- if (option == Option_Mode && !GetModeLoaded(newValue))
- {
- GOKZ_PrintToChat(client, true, "%t", "Mode Not Available", newValue);
- GOKZ_SetCoreOption(client, Option_Mode, GetALoadedMode());
- }
- else
- {
- PrintOptionChangeMessage(client, option, newValue);
- }
-}
-
-void OnModeUnloaded_Options(int mode)
-{
- for (int client = 1; client <= MaxClients; client++)
- {
- if (IsClientInGame(client) && GOKZ_GetCoreOption(client, Option_Mode) == mode)
- {
- GOKZ_SetCoreOption(client, Option_Mode, GetALoadedMode());
- }
- }
-}
-
-void OnMapStart_Options()
-{
- LoadDefaultOptions();
-}
-
-
-
-// =====[ PRIVATE ]=====
-
-static void RegisterOptions()
-{
- for (Option option; option < OPTION_COUNT; option++)
- {
- RegisterOption(gC_CoreOptionNames[option], gC_CoreOptionDescriptions[option],
- OptionType_Int, gI_CoreOptionDefaults[option], 0, gI_CoreOptionCounts[option] - 1);
- }
-}
-
-static bool IsValueInRange(OptionType type, any value, any minValue, any maxValue)
-{
- if (type == OptionType_Float)
- {
- return FloatCompare(minValue, value) <= 0 && FloatCompare(value, maxValue) <= 0;
- }
- else //if (type == OptionType_Int)
- {
- return minValue <= value && value <= maxValue;
- }
-}
-
-static void LoadOption(int client, const char[] option)
-{
- char valueString[100];
- Cookie cookie = GetOptionProp(option, OptionProp_Cookie);
- cookie.Get(client, valueString, sizeof(valueString));
-
- // If there's no stored value for the option, set it to default
- if (valueString[0] == '\0')
- {
- SetOption(client, option, GetOptionProp(option, OptionProp_DefaultValue));
- return;
- }
-
- OptionType type = GetOptionProp(option, OptionProp_Type);
- any minValue = GetOptionProp(option, OptionProp_MinValue);
- any maxValue = GetOptionProp(option, OptionProp_MaxValue);
- any value;
-
- // If stored option isn't a valid float or integer, or is out of range, set it to default
- if (type == OptionType_Float && StringToFloatEx(valueString, value) == 0)
- {
- SetOption(client, option, GetOptionProp(option, OptionProp_DefaultValue));
- }
- else if (type == OptionType_Int && StringToIntEx(valueString, value) == 0)
- {
- SetOption(client, option, GetOptionProp(option, OptionProp_DefaultValue));
- }
- else if (!IsValueInRange(type, value, minValue, maxValue))
- {
- SetOption(client, option, GetOptionProp(option, OptionProp_DefaultValue));
- }
-}
-
-// Load default optionData from a config file, creating one and adding optionData if necessary
-static void LoadDefaultOptions()
-{
- KeyValues oldKV = new KeyValues(GOKZ_CFG_OPTIONS_ROOT);
-
- if (FileExists(GOKZ_CFG_OPTIONS) && !oldKV.ImportFromFile(GOKZ_CFG_OPTIONS))
- {
- LogError("Failed to load file: \"%s\".", GOKZ_CFG_OPTIONS);
- delete oldKV;
- return;
- }
-
- KeyValues newKV = new KeyValues(GOKZ_CFG_OPTIONS_ROOT); // This one will be sorted by option name
- StringMapSnapshot optionDataSnapshot = optionData.Snapshot();
- ArrayList optionDataSnapshotArray = new ArrayList(ByteCountToCells(GOKZ_OPTION_MAX_NAME_LENGTH), 0);
- char option[GOKZ_OPTION_MAX_NAME_LENGTH];
- char optionDescription[GOKZ_OPTION_MAX_DESC_LENGTH];
-
- // Sort the optionData by name
- for (int i = 0; i < optionDataSnapshot.Length; i++)
- {
- optionDataSnapshot.GetKey(i, option, sizeof(option));
- optionDataSnapshotArray.PushString(option);
- }
- SortADTArray(optionDataSnapshotArray, Sort_Ascending, Sort_String);
-
- // Get the values from the KeyValues, otherwise set them
- for (int i = 0; i < optionDataSnapshotArray.Length; i++)
- {
- oldKV.Rewind();
- newKV.Rewind();
- optionDataSnapshotArray.GetString(i, option, sizeof(option));
- optionDescriptions.GetString(option, optionDescription, sizeof(optionDescription));
-
- newKV.JumpToKey(option, true);
- newKV.SetString(GOKZ_CFG_OPTIONS_DESCRIPTION, optionDescription);
-
- OptionType type = GetOptionProp(option, OptionProp_Type);
- if (type == OptionType_Float)
- {
- if (oldKV.JumpToKey(option, false) && oldKV.JumpToKey(GOKZ_CFG_OPTIONS_DEFAULT, false))
- {
- oldKV.GoBack();
- newKV.SetFloat(GOKZ_CFG_OPTIONS_DEFAULT, oldKV.GetFloat(GOKZ_CFG_OPTIONS_DEFAULT));
- SetOptionProp(option, OptionProp_DefaultValue, oldKV.GetFloat(GOKZ_CFG_OPTIONS_DEFAULT));
- }
- else
- {
- newKV.SetFloat(GOKZ_CFG_OPTIONS_DEFAULT, GetOptionProp(option, OptionProp_DefaultValue));
- }
- }
- else if (type == OptionType_Int)
- {
- if (oldKV.JumpToKey(option, false) && oldKV.JumpToKey(GOKZ_CFG_OPTIONS_DEFAULT, false))
- {
- oldKV.GoBack();
- newKV.SetNum(GOKZ_CFG_OPTIONS_DEFAULT, oldKV.GetNum(GOKZ_CFG_OPTIONS_DEFAULT));
- SetOptionProp(option, OptionProp_DefaultValue, oldKV.GetNum(GOKZ_CFG_OPTIONS_DEFAULT));
- }
- else
- {
- newKV.SetNum(GOKZ_CFG_OPTIONS_DEFAULT, GetOptionProp(option, OptionProp_DefaultValue));
- }
- }
- }
-
- newKV.Rewind();
- newKV.ExportToFile(GOKZ_CFG_OPTIONS);
-
- delete oldKV;
- delete newKV;
- delete optionDataSnapshot;
- delete optionDataSnapshotArray;
-}
-
-static void PrintOptionChangeMessage(int client, Option option, int newValue)
-{
- // NOTE: Not all optionData have a message for when they are changed.
- switch (option)
- {
- case Option_Mode:
- {
- GOKZ_PrintToChat(client, true, "%t", "Switched Mode", gC_ModeNames[newValue]);
- }
- case Option_VirtualButtonIndicators:
- {
- switch (newValue)
- {
- case VirtualButtonIndicators_Disabled:
- {
- GOKZ_PrintToChat(client, true, "%t", "Option - Virtual Button Indicators - Disable");
- }
- case VirtualButtonIndicators_Enabled:
- {
- GOKZ_PrintToChat(client, true, "%t", "Option - Virtual Button Indicators - Enable");
- }
- }
- }
- case Option_Safeguard:
- {
- switch (newValue)
- {
- case Safeguard_Disabled:
- {
- GOKZ_PrintToChat(client, true, "%t", "Option - Safeguard - Disable");
- }
- case Safeguard_EnabledNUB:
- {
- GOKZ_PrintToChat(client, true, "%t", "Option - Safeguard - Enable (NUB)");
- }
- case Safeguard_EnabledPRO:
- {
- GOKZ_PrintToChat(client, true, "%t", "Option - Safeguard - Enable (PRO)");
- }
- }
- }
- }
-} \ No newline at end of file
diff --git a/sourcemod/scripting/gokz-core/teamnumfix.sp b/sourcemod/scripting/gokz-core/teamnumfix.sp
deleted file mode 100644
index 0c5d81d..0000000
--- a/sourcemod/scripting/gokz-core/teamnumfix.sp
+++ /dev/null
@@ -1,68 +0,0 @@
-static Handle H_RemovePlayer;
-static int teamEntID[4];
-static int oldTeam[MAXPLAYERS + 1];
-static int realTeam[MAXPLAYERS + 1];
-
-void OnPluginStart_TeamNumber()
-{
- GameData gamedataConf = LoadGameConfigFile("gokz-core.games");
- if (gamedataConf == null)
- {
- SetFailState("Failed to load gokz-core gamedata");
- }
-
- StartPrepSDKCall(SDKCall_Entity);
- PrepSDKCall_SetVirtual(gamedataConf.GetOffset("CCSTeam::RemovePlayer"));
- PrepSDKCall_AddParameter(SDKType_CBasePlayer, SDKPass_Pointer);
- H_RemovePlayer = EndPrepSDKCall();
- if (H_RemovePlayer == INVALID_HANDLE)
- {
- SetFailState("Unable to prepare SDKCall for CCSTeam::RemovePlayer!");
- }
-}
-
-void OnMapStart_TeamNumber()
-{
- // Fetch the entity ID of team entities and store them.
- int team = FindEntityByClassname(MaxClients + 1, "cs_team_manager");
- while (team != -1)
- {
- int teamNum = GetEntProp(team, Prop_Send, "m_iTeamNum");
- teamEntID[teamNum] = team;
- team = FindEntityByClassname(team, "cs_team_manager");
- }
-}
-
-void OnGameFrame_TeamNumber()
-{
- for (int client = 1; client <= MaxClients; client++)
- {
- if (!IsClientInGame(client) || !IsPlayerAlive(client))
- {
- continue;
- }
- int team = GetEntProp(client, Prop_Data, "m_iTeamNum");
- // If the entprop changed, remove the player from the old team, but make sure it's a valid team first
- if (team != oldTeam[client] && oldTeam[client] < 4 && oldTeam[client] > 0)
- {
- SDKCall(H_RemovePlayer, teamEntID[oldTeam[client]], client);
- }
- oldTeam[client] = team;
- }
-}
-
-void OnPlayerJoinTeam_TeamNumber(Event event, int client)
-{
- // If the old team value is invalid, fix it.
- if (event.GetInt("oldteam") > 4 || event.GetInt("oldteam") < 0)
- {
- event.SetInt("oldteam", 0);
- }
- realTeam[client] = event.GetInt("team");
-}
-
-void OnPlayerDeath_TeamNumber(int client)
-{
- // Switch the client's team to a valid team to prevent crashes.
- CS_SwitchTeam(client, realTeam[client]);
-} \ No newline at end of file
diff --git a/sourcemod/scripting/gokz-core/teleports.sp b/sourcemod/scripting/gokz-core/teleports.sp
deleted file mode 100644
index 764fc6e..0000000
--- a/sourcemod/scripting/gokz-core/teleports.sp
+++ /dev/null
@@ -1,917 +0,0 @@
-/*
- Checkpoints and teleporting, including ability to go back
- to previous checkpoint, go to next checkpoint, and undo.
-*/
-
-
-static ArrayList checkpoints[MAXPLAYERS + 1];
-static int checkpointCount[MAXPLAYERS + 1];
-static int checkpointIndex[MAXPLAYERS + 1];
-static int checkpointIndexStart[MAXPLAYERS + 1];
-static int checkpointIndexEnd[MAXPLAYERS + 1];
-static int teleportCount[MAXPLAYERS + 1];
-static StartPositionType startType[MAXPLAYERS + 1];
-static StartPositionType nonCustomStartType[MAXPLAYERS + 1];
-static float nonCustomStartOrigin[MAXPLAYERS + 1][3];
-static float nonCustomStartAngles[MAXPLAYERS + 1][3];
-static float customStartOrigin[MAXPLAYERS + 1][3];
-static float customStartAngles[MAXPLAYERS + 1][3];
-static float endOrigin[MAXPLAYERS + 1][3];
-static float endAngles[MAXPLAYERS + 1][3];
-static UndoTeleportData undoTeleportData[MAXPLAYERS + 1];
-static float lastRestartAttemptTime[MAXPLAYERS + 1];
-
-// =====[ PUBLIC ]=====
-
-int GetCheckpointCount(int client)
-{
- return checkpointCount[client];
-}
-
-void SetCheckpointCount(int client, int cpCount)
-{
- checkpointCount[client] = cpCount;
-}
-
-int GetTeleportCount(int client)
-{
- return teleportCount[client];
-}
-
-void SetTeleportCount(int client, int tpCount)
-{
- teleportCount[client] = tpCount;
-}
-
-// CHECKPOINT
-
-void OnMapStart_Checkpoints()
-{
- for (int client = 0; client < MAXPLAYERS + 1; client++)
- {
- if (checkpoints[client] != INVALID_HANDLE)
- {
- delete checkpoints[client];
- }
- checkpoints[client] = new ArrayList(sizeof(Checkpoint));
- }
-}
-
-void MakeCheckpoint(int client)
-{
- if (!CanMakeCheckpoint(client, true))
- {
- return;
- }
-
- // Call Pre Forward
- Action result;
- Call_GOKZ_OnMakeCheckpoint(client, result);
- if (result != Plugin_Continue)
- {
- return;
- }
-
- // Make Checkpoint
- checkpointCount[client]++;
- Checkpoint cp;
- cp.Create(client);
-
- if (checkpoints[client] == INVALID_HANDLE)
- {
- checkpoints[client] = new ArrayList(sizeof(Checkpoint));
- }
-
- checkpointIndex[client] = NextIndex(checkpointIndex[client], GOKZ_MAX_CHECKPOINTS);
- checkpointIndexEnd[client] = checkpointIndex[client];
- // The list has yet to be filled up, do PushArray instead of SetArray
- if (checkpoints[client].Length < GOKZ_MAX_CHECKPOINTS && checkpointIndex[client] == checkpoints[client].Length)
- {
- checkpoints[client].PushArray(cp);
- // Initialize start and end index for the first checkpoint
- if (checkpoints[client].Length == 1)
- {
- checkpointIndexStart[client] = 0;
- checkpointIndexEnd[client] = 0;
- }
- }
- else
- {
- checkpoints[client].SetArray(checkpointIndex[client], cp);
- // The new checkpoint has overridden the oldest checkpoint, move the start index by one.
- if (checkpointIndexEnd[client] == checkpointIndexStart[client])
- {
- checkpointIndexStart[client] = NextIndex(checkpointIndexStart[client], GOKZ_MAX_CHECKPOINTS);
- }
- }
-
-
- if (GOKZ_GetCoreOption(client, Option_CheckpointSounds) == CheckpointSounds_Enabled)
- {
- GOKZ_EmitSoundToClient(client, GOKZ_SOUND_CHECKPOINT, _, "Checkpoint");
- }
- if (GOKZ_GetCoreOption(client, Option_CheckpointMessages) == CheckpointMessages_Enabled)
- {
- GOKZ_PrintToChat(client, true, "%t", "Make Checkpoint", checkpointCount[client]);
- }
-
- if (!GetTimerRunning(client) && AntiCpTriggerIsTouched(client))
- {
- GOKZ_PrintToChat(client, true, "%t", "Anti Checkpoint Area Warning");
- }
-
- // Call Post Forward
- Call_GOKZ_OnMakeCheckpoint_Post(client);
-}
-
-bool CanMakeCheckpoint(int client, bool showError = false)
-{
- if (!IsPlayerAlive(client))
- {
- if (showError)
- {
- GOKZ_PrintToChat(client, true, "%t", "Must Be Alive");
- GOKZ_PlayErrorSound(client);
- }
- return false;
- }
- if (GetTimerRunning(client) && AntiCpTriggerIsTouched(client))
- {
- if (showError)
- {
- GOKZ_PrintToChat(client, true, "%t", "Can't Checkpoint (Anti Checkpoint Area)");
- GOKZ_PlayErrorSound(client);
- }
- return false;
- }
- if (!Movement_GetOnGround(client) && Movement_GetMovetype(client) != MOVETYPE_LADDER)
- {
- if (showError)
- {
- GOKZ_PrintToChat(client, true, "%t", "Can't Checkpoint (Midair)");
- GOKZ_PlayErrorSound(client);
- }
- return false;
- }
- if (BhopTriggersJustTouched(client))
- {
- if (showError)
- {
- GOKZ_PrintToChat(client, true, "%t", "Can't Checkpoint (Just Landed)");
- GOKZ_PlayErrorSound(client);
- }
- return false;
- }
- return true;
-}
-
-ArrayList GetCheckpointData(int client)
-{
- // Don't clone the entire thing, return an ordered list of checkpoints.
- // Doing this should be cleaner, saves memory and should be faster than a full Clone().
- ArrayList checkpointData = new ArrayList(sizeof(Checkpoint));
- if (checkpointIndex[client] == -1)
- {
- // No checkpoint was made, return empty ArrayList
- return checkpointData;
- }
- for (int i = checkpointIndexStart[client]; i != checkpointIndexEnd[client]; i = NextIndex(i, GOKZ_MAX_CHECKPOINTS))
- {
- Checkpoint cp;
- checkpoints[client].GetArray(i, cp);
- checkpointData.PushArray(cp);
- }
- return checkpointData;
-}
-
-bool SetCheckpointData(int client, ArrayList cps, int version)
-{
- if (version != GOKZ_CHECKPOINT_VERSION)
- {
- return false;
- }
- // cps is assumed to be ordered.
- if (cps != INVALID_HANDLE)
- {
- delete checkpoints[client];
- checkpoints[client] = cps.Clone();
- if (cps.Length == 0)
- {
- checkpointIndexStart[client] = -1;
- checkpointIndexEnd[client] = -1;
- }
- else
- {
- checkpointIndexStart[client] = 0;
- checkpointIndexEnd[client] = checkpoints[client].Length - 1;
- }
- checkpointIndex[client] = checkpointIndexEnd[client];
- return true;
- }
- return false;
-}
-
-ArrayList GetUndoTeleportData(int client)
-{
- // Enum structs cannot be sent directly over natives, we put it in an ArrayList of one instead.
- // We use another struct instead of reusing Checkpoint so normal checkpoints don't use more memory than needed.
- ArrayList undoTeleportDataArray = new ArrayList(sizeof(UndoTeleportData));
- undoTeleportDataArray.PushArray(undoTeleportData[client]);
- return undoTeleportDataArray;
-}
-
-bool SetUndoTeleportData(int client, ArrayList undoTeleportDataArray, int version)
-{
- if (version != GOKZ_CHECKPOINT_VERSION)
- {
- return false;
- }
- if (undoTeleportDataArray != INVALID_HANDLE && undoTeleportDataArray.Length == 1)
- {
- undoTeleportDataArray.GetArray(0, undoTeleportData[client], sizeof(UndoTeleportData));
- return true;
- }
- return false;
-}
-// TELEPORT
-
-void TeleportToCheckpoint(int client)
-{
- if (!CanTeleportToCheckpoint(client, true))
- {
- return;
- }
-
- // Call Pre Forward
- Action result;
- Call_GOKZ_OnTeleportToCheckpoint(client, result);
- if (result != Plugin_Continue)
- {
- return;
- }
-
- CheckpointTeleportDo(client);
-
- // Call Post Forward
- Call_GOKZ_OnTeleportToCheckpoint_Post(client);
-}
-
-bool CanTeleportToCheckpoint(int client, bool showError = false)
-{
- // Safeguard Check
- if (GOKZ_GetCoreOption(client, Option_Safeguard) == Safeguard_EnabledPRO && GOKZ_GetTimerRunning(client) && GOKZ_GetValidTimer(client) && GOKZ_GetTeleportCount(client) == 0)
- {
- if (showError)
- {
- GOKZ_PrintToChat(client, true, "%t", "Safeguard - Blocked");
- GOKZ_PlayErrorSound(client);
- }
- return false;
- }
- if (GetCurrentMapPrefix() == MapPrefix_KZPro && GetTimerRunning(client))
- {
- if (showError)
- {
- GOKZ_PrintToChat(client, true, "%t", "Can't Teleport (Map)");
- GOKZ_PlayErrorSound(client);
- }
- return false;
- }
- if (checkpoints[client] == INVALID_HANDLE || checkpoints[client].Length <= 0)
- {
- if (showError)
- {
- GOKZ_PrintToChat(client, true, "%t", "Can't Teleport (No Checkpoints)");
- GOKZ_PlayErrorSound(client);
- }
- return false;
- }
- return true;
-}
-
-
-// PREV CP
-
-void PrevCheckpoint(int client)
-{
- if (!CanPrevCheckpoint(client, true))
- {
- return;
- }
-
- // Call Pre Forward
- Action result;
- Call_GOKZ_OnPrevCheckpoint(client, result);
- if (result != Plugin_Continue)
- {
- return;
- }
-
- checkpointIndex[client] = PrevIndex(checkpointIndex[client], GOKZ_MAX_CHECKPOINTS);
- CheckpointTeleportDo(client);
-
- // Call Post Forward
- Call_GOKZ_OnPrevCheckpoint_Post(client);
-}
-
-bool CanPrevCheckpoint(int client, bool showError = false)
-{
- // Safeguard Check
- if (GOKZ_GetCoreOption(client, Option_Safeguard) == Safeguard_EnabledPRO && GOKZ_GetTimerRunning(client) && GOKZ_GetValidTimer(client))
- {
- if (showError)
- {
- GOKZ_PrintToChat(client, true, "%t", "Safeguard - Blocked");
- GOKZ_PlayErrorSound(client);
- }
- return false;
- }
- if (GetCurrentMapPrefix() == MapPrefix_KZPro && GetTimerRunning(client))
- {
- if (showError)
- {
- GOKZ_PrintToChat(client, true, "%t", "Can't Teleport (Map)");
- GOKZ_PlayErrorSound(client);
- }
- return false;
- }
- if (checkpointIndex[client] == checkpointIndexStart[client])
- {
- if (showError)
- {
- GOKZ_PrintToChat(client, true, "%t", "Can't Prev CP (No Checkpoints)");
- GOKZ_PlayErrorSound(client);
- }
- return false;
- }
- return true;
-}
-
-
-// NEXT CP
-
-void NextCheckpoint(int client)
-{
- if (!CanNextCheckpoint(client, true))
- {
- return;
- }
-
- // Call Pre Forward
- Action result;
- Call_GOKZ_OnNextCheckpoint(client, result);
- if (result != Plugin_Continue)
- {
- return;
- }
- checkpointIndex[client] = NextIndex(checkpointIndex[client], GOKZ_MAX_CHECKPOINTS);
- CheckpointTeleportDo(client);
-
- // Call Post Forward
- Call_GOKZ_OnNextCheckpoint_Post(client);
-}
-
-bool CanNextCheckpoint(int client, bool showError = false)
-{
- if (GetCurrentMapPrefix() == MapPrefix_KZPro && GetTimerRunning(client))
- {
- if (showError)
- {
- GOKZ_PrintToChat(client, true, "%t", "Can't Teleport (Map)");
- GOKZ_PlayErrorSound(client);
- }
- return false;
- }
- if (checkpointIndex[client] == checkpointIndexEnd[client])
- {
- if (showError)
- {
- GOKZ_PrintToChat(client, true, "%t", "Can't Next CP (No Checkpoints)");
- GOKZ_PlayErrorSound(client);
- }
- return false;
- }
- return true;
-}
-
-
-// RESTART & RESPAWN
-
-bool CanTeleportToStart(int client, bool showError = false)
-{
- // Safeguard Check
- if (GOKZ_GetCoreOption(client, Option_Safeguard) > Safeguard_Disabled && GOKZ_GetTimerRunning(client) && GOKZ_GetValidTimer(client))
- {
- float currentTime = GetEngineTime();
- float timeSinceLastAttempt = currentTime - lastRestartAttemptTime[client];
- float cooldown;
- // If the client restarts for the first time or the last attempt is too long ago, restart the cooldown.
- if (lastRestartAttemptTime[client] == 0.0 || timeSinceLastAttempt > GOKZ_SAFEGUARD_RESTART_MAX_DELAY)
- {
- lastRestartAttemptTime[client] = currentTime;
- cooldown = GOKZ_SAFEGUARD_RESTART_MIN_DELAY;
- }
- else
- {
- cooldown = GOKZ_SAFEGUARD_RESTART_MIN_DELAY - timeSinceLastAttempt;
- }
- if (cooldown <= 0.0)
- {
- lastRestartAttemptTime[client] = 0.0;
- return true;
- }
- if (showError)
- {
- GOKZ_PrintToChat(client, true, "%t", "Safeguard - Blocked (Temp)", cooldown);
- GOKZ_PlayErrorSound(client);
- }
- return false;
- }
- return true;
-}
-
-void TeleportToStart(int client)
-{
- if (!CanTeleportToStart(client, true))
- {
- return;
- }
-
- // Call Pre Forward
- Action result;
- Call_GOKZ_OnTeleportToStart(client, GetCurrentCourse(client), result);
- if (result != Plugin_Continue)
- {
- return;
- }
-
- // Teleport to Start
- if (startType[client] == StartPositionType_Spawn)
- {
- GOKZ_RespawnPlayer(client, .restorePos = false);
- // Respawning alone does not guarantee a valid spawn.
- float spawnOrigin[3];
- float spawnAngles[3];
- GetValidSpawn(spawnOrigin, spawnAngles);
- TeleportPlayer(client, spawnOrigin, spawnAngles);
- }
- else if (startType[client] == StartPositionType_Custom)
- {
- TeleportDo(client, customStartOrigin[client], customStartAngles[client]);
- }
- else
- {
- TeleportDo(client, nonCustomStartOrigin[client], nonCustomStartAngles[client]);
- }
-
- if (startType[client] != StartPositionType_MapButton
- && (!InRangeOfVirtualStart(client) || !CanReachVirtualStart(client)))
- {
- GOKZ_StopTimer(client, false);
- }
-
- // Call Post Forward
- Call_GOKZ_OnTeleportToStart_Post(client, GetCurrentCourse(client));
-}
-
-void TeleportToSearchStart(int client, int course)
-{
- if (!CanTeleportToStart(client, true))
- {
- return;
- }
-
- // Call Pre Forward
- Action result;
- Call_GOKZ_OnTeleportToStart(client, course, result);
- if (result != Plugin_Continue)
- {
- return;
- }
-
- float origin[3], angles[3];
- if (!GetSearchStartPosition(course, origin, angles))
- {
- if (course == 0)
- {
- GOKZ_PrintToChat(client, true, "%t", "No Start Found");
- }
- else
- {
- GOKZ_PrintToChat(client, true, "%t", "No Start Found (Bonus)", course);
- }
- return;
- }
- GOKZ_StopTimer(client, false);
-
- TeleportDo(client, origin, angles);
- // Call Post Forward
- Call_GOKZ_OnTeleportToStart_Post(client, course);
-}
-
-StartPositionType GetStartPosition(int client, float position[3], float angles[3])
-{
- if (startType[client] == StartPositionType_Custom)
- {
- position = customStartOrigin[client];
- angles = customStartAngles[client];
- }
- else if (startType[client] != StartPositionType_Spawn)
- {
- position = nonCustomStartOrigin[client];
- angles = nonCustomStartAngles[client];
- }
-
- return startType[client];
-}
-
-bool TeleportToCourseStart(int client, int course)
-{
- if (!CanTeleportToStart(client, true))
- {
- return false;
- }
-
- // Call Pre Forward
- Action result;
- Call_GOKZ_OnTeleportToStart(client, course, result);
- if (result != Plugin_Continue)
- {
- return false;
- }
- float origin[3], angles[3];
-
- if (!GetMapStartPosition(course, origin, angles))
- {
- if (!GetSearchStartPosition(course, origin, angles))
- {
- if (course == 0)
- {
- GOKZ_PrintToChat(client, true, "%t", "No Start Found");
- }
- else
- {
- GOKZ_PrintToChat(client, true, "%t", "No Start Found (Bonus)", course);
- }
- return false;
- }
- }
-
- GOKZ_StopTimer(client);
-
- TeleportDo(client, origin, angles);
-
- // Call Post Forward
- Call_GOKZ_OnTeleportToStart_Post(client, course);
- return true;
-}
-
-StartPositionType GetStartPositionType(int client)
-{
- return startType[client];
-}
-
-// Note: Use ClearStartPosition to switch off StartPositionType_Custom
-void SetStartPosition(int client, StartPositionType type, const float origin[3] = NULL_VECTOR, const float angles[3] = NULL_VECTOR)
-{
- if (type == StartPositionType_Custom)
- {
- startType[client] = StartPositionType_Custom;
-
- if (!IsNullVector(origin))
- {
- customStartOrigin[client] = origin;
- }
-
- if (!IsNullVector(angles))
- {
- customStartAngles[client] = angles;
- }
-
- // Call Post Forward
- Call_GOKZ_OnStartPositionSet_Post(client, startType[client], customStartOrigin[client], customStartAngles[client]);
- }
- else
- {
- nonCustomStartType[client] = type;
-
- if (!IsNullVector(origin))
- {
- nonCustomStartOrigin[client] = origin;
- }
-
- if (!IsNullVector(angles))
- {
- nonCustomStartAngles[client] = angles;
- }
-
- if (startType[client] != StartPositionType_Custom)
- {
- startType[client] = type;
-
- // Call Post Forward
- Call_GOKZ_OnStartPositionSet_Post(client, startType[client], nonCustomStartOrigin[client], nonCustomStartAngles[client]);
- }
- }
-}
-
-void SetStartPositionToCurrent(int client, StartPositionType type)
-{
- float origin[3], angles[3];
- Movement_GetOrigin(client, origin);
- Movement_GetEyeAngles(client, angles);
-
- SetStartPosition(client, type, origin, angles);
-}
-
-bool SetStartPositionToMapStart(int client, int course)
-{
- float origin[3], angles[3];
-
- if (!GetMapStartPosition(course, origin, angles))
- {
- return false;
- }
-
- SetStartPosition(client, StartPositionType_MapStart, origin, angles);
-
- return true;
-}
-
-bool ClearCustomStartPosition(int client)
-{
- if (GetStartPositionType(client) != StartPositionType_Custom)
- {
- return false;
- }
-
- startType[client] = nonCustomStartType[client];
-
- // Call Post Forward
- Call_GOKZ_OnStartPositionSet_Post(client, startType[client], nonCustomStartOrigin[client], nonCustomStartAngles[client]);
-
- return true;
-}
-
-
-// TELEPORT TO END
-
-bool CanTeleportToEnd(int client, bool showError = false)
-{
- // Safeguard Check
- if (GOKZ_GetCoreOption(client, Option_Safeguard) > Safeguard_Disabled && GOKZ_GetTimerRunning(client) && GOKZ_GetValidTimer(client))
- {
- if (showError)
- {
- GOKZ_PrintToChat(client, true, "%t", "Safeguard - Blocked");
- GOKZ_PlayErrorSound(client);
- }
- return false;
- }
- return true;
-}
-
-void TeleportToEnd(int client, int course)
-{
- if (!CanTeleportToEnd(client, true))
- {
- return;
- }
-
- // Call Pre Forward
- Action result;
- Call_GOKZ_OnTeleportToEnd(client, course, result);
- if (result != Plugin_Continue)
- {
- return;
- }
-
- GOKZ_StopTimer(client, false);
-
- if (!GetMapEndPosition(course, endOrigin[client], endAngles[client]))
- {
- if (course == 0)
- {
- GOKZ_PrintToChat(client, true, "%t", "No End Found");
- }
- else
- {
- GOKZ_PrintToChat(client, true, "%t", "No End Found (Bonus)", course);
- }
- return;
- }
- TeleportDo(client, endOrigin[client], endAngles[client]);
-
- // Call Post Forward
- Call_GOKZ_OnTeleportToEnd_Post(client, course);
-}
-
-void SetEndPosition(int client, const float origin[3] = NULL_VECTOR, const float angles[3] = NULL_VECTOR)
-{
- if (!IsNullVector(origin))
- {
- endOrigin[client] = origin;
- }
- if (!IsNullVector(angles))
- {
- endAngles[client] = angles;
- }
-}
-
-bool SetEndPositionToMapEnd(int client, int course)
-{
- float origin[3], angles[3];
-
- if (!GetMapEndPosition(course, origin, angles))
- {
- return false;
- }
-
- SetEndPosition(client, origin, angles);
-
- return true;
-}
-
-
-// UNDO TP
-
-void UndoTeleport(int client)
-{
- if (!CanUndoTeleport(client, true))
- {
- return;
- }
-
- // Call Pre Forward
- Action result;
- Call_GOKZ_OnUndoTeleport(client, result);
- if (result != Plugin_Continue)
- {
- return;
- }
-
- // Undo Teleport
- TeleportDo(client, undoTeleportData[client].origin, undoTeleportData[client].angles);
-
- // Call Post Forward
- Call_GOKZ_OnUndoTeleport_Post(client);
-}
-
-bool CanUndoTeleport(int client, bool showError = false)
-{
- if (teleportCount[client] <= 0)
- {
- if (showError)
- {
- GOKZ_PrintToChat(client, true, "%t", "Can't Undo (No Teleports)");
- GOKZ_PlayErrorSound(client);
- }
- return false;
- }
- if (!undoTeleportData[client].lastTeleportOnGround)
- {
- if (showError)
- {
- GOKZ_PrintToChat(client, true, "%t", "Can't Undo (TP Was Midair)");
- GOKZ_PlayErrorSound(client);
- }
- return false;
- }
- if (undoTeleportData[client].lastTeleportInBhopTrigger)
- {
- if (showError)
- {
- GOKZ_PrintToChat(client, true, "%t", "Can't Undo (Just Landed)");
- GOKZ_PlayErrorSound(client);
- }
- return false;
- }
- if (undoTeleportData[client].lastTeleportInAntiCpTrigger)
- {
- if (showError)
- {
- GOKZ_PrintToChat(client, true, "%t", "Can't Undo (AntiCp)");
- GOKZ_PlayErrorSound(client);
- }
- return false;
- }
- return true;
-}
-
-
-
-// =====[ EVENTS ]=====
-
-void OnClientPutInServer_Teleports(int client)
-{
- checkpointCount[client] = 0;
- checkpointIndex[client] = -1;
- checkpointIndexStart[client] = -1;
- checkpointIndexEnd[client] = -1;
- teleportCount[client] = 0;
- startType[client] = StartPositionType_Spawn;
- nonCustomStartType[client] = StartPositionType_Spawn;
- lastRestartAttemptTime[client] = 0.0;
- if (checkpoints[client] != INVALID_HANDLE)
- {
- checkpoints[client].Clear();
- }
- // Set start and end position to main course if we know of it
- SetStartPositionToMapStart(client, 0);
- SetEndPositionToMapEnd(client, 0);
-
-}
-
-void OnTimerStart_Teleports(int client)
-{
- checkpointCount[client] = 0;
- checkpointIndex[client] = -1;
- checkpointIndexStart[client] = -1;
- checkpointIndexEnd[client] = -1;
- teleportCount[client] = 0;
- checkpoints[client].Clear();
-}
-
-void OnStartButtonPress_Teleports(int client, int course)
-{
- SetStartPositionToCurrent(client, StartPositionType_MapButton);
- SetEndPositionToMapEnd(client, course);
-}
-
-void OnVirtualStartButtonPress_Teleports(int client)
-{
- SetStartPositionToCurrent(client, StartPositionType_MapButton);
-}
-
-void OnStartZoneStartTouch_Teleports(int client, int course)
-{
- SetStartPositionToMapStart(client, course);
- SetEndPositionToMapEnd(client, course);
-}
-
-
-
-// =====[ PRIVATE ]=====
-
-static int PrevIndex(int current, int maximum)
-{
- int prev = current - 1;
- if (prev < 0)
- {
- return maximum - 1;
- }
- return prev;
-}
-
-static void TeleportDo(int client, const float destOrigin[3], const float destAngles[3])
-{
- if (!IsPlayerAlive(client))
- {
- GOKZ_RespawnPlayer(client);
- }
-
- // Store information about where player is teleporting from
- undoTeleportData[client].Init(client, BhopTriggersJustTouched(client), Movement_GetOnGround(client), AntiCpTriggerIsTouched(client));
-
- teleportCount[client]++;
- TeleportPlayer(client, destOrigin, destAngles);
- // TeleportPlayer needs to be done before undo TP data can be fully updated.
- undoTeleportData[client].Update();
- if (GOKZ_GetCoreOption(client, Option_TeleportSounds) == TeleportSounds_Enabled)
- {
- GOKZ_EmitSoundToClient(client, GOKZ_SOUND_TELEPORT, _, "Teleport");
- }
-
- // Call Post Foward
- Call_GOKZ_OnCountedTeleport_Post(client);
-}
-
-static void CheckpointTeleportDo(int client)
-{
- Checkpoint cp;
- checkpoints[client].GetArray(checkpointIndex[client], cp);
-
- TeleportDo(client, cp.origin, cp.angles);
- if (cp.groundEnt != INVALID_ENT_REFERENCE)
- {
- SetEntPropEnt(client, Prop_Data, "m_hGroundEntity", cp.groundEnt);
- SetEntityFlags(client, GetEntityFlags(client) | FL_ONGROUND);
- }
- // Handle ladder stuff
- if (cp.onLadder)
- {
- SetEntPropVector(client, Prop_Send, "m_vecLadderNormal", cp.ladderNormal);
- if (!GOKZ_GetPaused(client))
- {
- Movement_SetMovetype(client, MOVETYPE_LADDER);
- }
- else
- {
- SetPausedOnLadder(client, true);
- }
- }
- else if (GOKZ_GetPaused(client))
- {
- SetPausedOnLadder(client, false);
- }
-}
diff --git a/sourcemod/scripting/gokz-core/timer/pause.sp b/sourcemod/scripting/gokz-core/timer/pause.sp
deleted file mode 100644
index 92ab1fb..0000000
--- a/sourcemod/scripting/gokz-core/timer/pause.sp
+++ /dev/null
@@ -1,257 +0,0 @@
-static bool paused[MAXPLAYERS + 1];
-static bool pausedOnLadder[MAXPLAYERS + 1];
-static float lastPauseTime[MAXPLAYERS + 1];
-static bool hasPausedInThisRun[MAXPLAYERS + 1];
-static float lastResumeTime[MAXPLAYERS + 1];
-static bool hasResumedInThisRun[MAXPLAYERS + 1];
-static float lastDuckValue[MAXPLAYERS + 1];
-static float lastStaminaValue[MAXPLAYERS + 1];
-
-
-
-// =====[ PUBLIC ]=====
-
-bool GetPaused(int client)
-{
- return paused[client];
-}
-
-void SetPausedOnLadder(int client, bool onLadder)
-{
- pausedOnLadder[client] = onLadder;
-}
-
-void Pause(int client)
-{
- if (!CanPause(client, true))
- {
- return;
- }
-
- // Call Pre Forward
- Action result;
- Call_GOKZ_OnPause(client, result);
- if (result != Plugin_Continue)
- {
- GOKZ_PrintToChat(client, true, "%t", "Can't Pause (Generic)");
- GOKZ_PlayErrorSound(client);
- return;
- }
-
- // Pause
- paused[client] = true;
- pausedOnLadder[client] = Movement_GetMovetype(client) == MOVETYPE_LADDER;
- lastDuckValue[client] = Movement_GetDuckSpeed(client);
- lastStaminaValue[client] = GetEntPropFloat(client, Prop_Send, "m_flStamina");
- Movement_SetVelocity(client, view_as<float>( { 0.0, 0.0, 0.0 } ));
- Movement_SetMovetype(client, MOVETYPE_NONE);
- if (GetTimerRunning(client))
- {
- hasPausedInThisRun[client] = true;
- lastPauseTime[client] = GetEngineTime();
- }
-
- // Call Post Forward
- Call_GOKZ_OnPause_Post(client);
-}
-
-bool CanPause(int client, bool showError = false)
-{
- if (paused[client])
- {
- return false;
- }
-
- if (GetTimerRunning(client))
- {
- if (hasResumedInThisRun[client]
- && GetEngineTime() - lastResumeTime[client] < GOKZ_PAUSE_COOLDOWN)
- {
- if (showError)
- {
- GOKZ_PrintToChat(client, true, "%t", "Can't Pause (Just Resumed)");
- GOKZ_PlayErrorSound(client);
- }
- return false;
- }
- else if (!Movement_GetOnGround(client)
- && !(Movement_GetSpeed(client) == 0 && Movement_GetVerticalVelocity(client) == 0))
- {
- if (showError)
- {
- GOKZ_PrintToChat(client, true, "%t", "Can't Pause (Midair)");
- GOKZ_PlayErrorSound(client);
- }
- return false;
- }
- else if (BhopTriggersJustTouched(client))
- {
- if (showError)
- {
- GOKZ_PrintToChat(client, true, "%t", "Can't Pause (Just Landed)");
- GOKZ_PlayErrorSound(client);
- }
- return false;
- }
- else if (AntiPauseTriggerIsTouched(client))
- {
- if (showError)
- {
- GOKZ_PrintToChat(client, true, "%t", "Can't Pause (Anti Pause Area)");
- GOKZ_PlayErrorSound(client);
- }
- return false;
- }
- }
-
- return true;
-}
-
-void Resume(int client, bool force = false)
-{
- if (!paused[client])
- {
- return;
- }
- if (!force && !CanResume(client, true))
- {
- return;
- }
-
- // Call Pre Forward
- Action result;
- Call_GOKZ_OnResume(client, result);
- if (result != Plugin_Continue)
- {
- GOKZ_PrintToChat(client, true, "%t", "Can't Resume (Generic)");
- GOKZ_PlayErrorSound(client);
- return;
- }
-
- // Resume
- if (pausedOnLadder[client])
- {
- Movement_SetMovetype(client, MOVETYPE_LADDER);
- }
- else
- {
- Movement_SetMovetype(client, MOVETYPE_WALK);
- }
-
- // Prevent noclip exploit
- SetEntProp(client, Prop_Send, "m_CollisionGroup", GOKZ_COLLISION_GROUP_STANDARD);
- paused[client] = false;
- if (GetTimerRunning(client))
- {
- hasResumedInThisRun[client] = true;
- lastResumeTime[client] = GetEngineTime();
- }
- Movement_SetDuckSpeed(client, lastDuckValue[client]);
- SetEntPropFloat(client, Prop_Send, "m_flStamina", lastStaminaValue[client]);
-
- // Call Post Forward
- Call_GOKZ_OnResume_Post(client);
-}
-
-bool CanResume(int client, bool showError = false)
-{
- if (GetTimerRunning(client) && hasPausedInThisRun[client]
- && GetEngineTime() - lastPauseTime[client] < GOKZ_PAUSE_COOLDOWN)
- {
- if (showError)
- {
- GOKZ_PrintToChat(client, true, "%t", "Can't Resume (Just Paused)");
- GOKZ_PlayErrorSound(client);
- }
- return false;
- }
- return true;
-}
-
-void TogglePause(int client)
-{
- if (paused[client])
- {
- Resume(client);
- }
- else
- {
- Pause(client);
- }
-}
-
-
-
-// =====[ EVENTS ]=====
-
-void OnClientPutInServer_Pause(int client)
-{
- paused[client] = false;
-}
-
-void OnTimerStart_Pause(int client)
-{
- hasPausedInThisRun[client] = false;
- hasResumedInThisRun[client] = false;
- Resume(client, true);
-}
-
-void OnChangeMovetype_Pause(int client, MoveType newMovetype)
-{
- // Check if player has escaped MOVETYPE_NONE
- if (!paused[client] || newMovetype == MOVETYPE_NONE)
- {
- return;
- }
-
- // Player has escaped MOVETYPE_NONE, so resume
- paused[client] = false;
- if (GetTimerRunning(client))
- {
- hasResumedInThisRun[client] = true;
- lastResumeTime[client] = GetEngineTime();
- }
-
- // Call Post Forward
- Call_GOKZ_OnResume_Post(client);
-}
-
-void OnPlayerSpawn_Pause(int client)
-{
- if (!paused[client])
- {
- return;
- }
-
- // Player has left paused state by spawning in, so resume
- paused[client] = false;
- if (GetTimerRunning(client))
- {
- hasResumedInThisRun[client] = true;
- lastResumeTime[client] = GetEngineTime();
- }
-
- Movement_SetDuckSpeed(client, lastDuckValue[client]);
- SetEntPropFloat(client, Prop_Send, "m_flStamina", lastStaminaValue[client]);
-
- // Call Post Forward
- Call_GOKZ_OnResume_Post(client);
-}
-
-void OnJoinTeam_Pause(int client, int team)
-{
- // Only handle joining spectators. Joining other teams is handled by OnPlayerSpawn.
- if (team == CS_TEAM_SPECTATOR)
- {
- paused[client] = true;
-
- if (GetTimerRunning(client))
- {
- hasPausedInThisRun[client] = true;
- lastPauseTime[client] = GetEngineTime();
- }
-
- // Call Post Forward
- Call_GOKZ_OnPause_Post(client);
- }
-} \ No newline at end of file
diff --git a/sourcemod/scripting/gokz-core/timer/timer.sp b/sourcemod/scripting/gokz-core/timer/timer.sp
deleted file mode 100644
index f6696ac..0000000
--- a/sourcemod/scripting/gokz-core/timer/timer.sp
+++ /dev/null
@@ -1,368 +0,0 @@
-static bool timerRunning[MAXPLAYERS + 1];
-static float currentTime[MAXPLAYERS + 1];
-static int currentCourse[MAXPLAYERS + 1];
-static float lastEndTime[MAXPLAYERS + 1];
-static float lastFalseEndTime[MAXPLAYERS + 1];
-static float lastStartSoundTime[MAXPLAYERS + 1];
-static int lastStartMode[MAXPLAYERS + 1];
-static bool validTime[MAXPLAYERS + 1];
-
-
-// =====[ PUBLIC ]=====
-
-bool GetTimerRunning(int client)
-{
- return timerRunning[client];
-}
-
-bool GetValidTimer(int client)
-{
- return validTime[client];
-}
-
-float GetCurrentTime(int client)
-{
- return currentTime[client];
-}
-
-void SetCurrentTime(int client, float time)
-{
- currentTime[client] = time;
- // The timer should be running if time is not negative.
- timerRunning[client] = time >= 0.0;
-}
-
-int GetCurrentCourse(int client)
-{
- return currentCourse[client];
-}
-
-void SetCurrentCourse(int client, int course)
-{
- currentCourse[client] = course;
-}
-
-int GetCurrentTimeType(int client)
-{
- if (GetTeleportCount(client) == 0)
- {
- return TimeType_Pro;
- }
- return TimeType_Nub;
-}
-
-bool TimerStart(int client, int course, bool allowMidair = false, bool playSound = true)
-{
- if (!IsPlayerAlive(client)
- || JustStartedTimer(client)
- || JustTeleported(client)
- || JustNoclipped(client)
- || !IsPlayerValidMoveType(client)
- || !allowMidair && (!Movement_GetOnGround(client) || JustLanded(client))
- || allowMidair && !Movement_GetOnGround(client) && (!GOKZ_GetValidJump(client) || GOKZ_GetHitPerf(client))
- || (GOKZ_GetTimerRunning(client) && GOKZ_GetCourse(client) != course))
- {
- return false;
- }
-
- // Call Pre Forward
- Action result;
- Call_GOKZ_OnTimerStart(client, course, result);
- if (result != Plugin_Continue)
- {
- return false;
- }
-
- // Prevent noclip exploit
- SetEntProp(client, Prop_Send, "m_CollisionGroup", GOKZ_COLLISION_GROUP_STANDARD);
-
- // Start Timer
- currentTime[client] = 0.0;
- timerRunning[client] = true;
- currentCourse[client] = course;
- lastStartMode[client] = GOKZ_GetCoreOption(client, Option_Mode);
- validTime[client] = true;
- if (playSound)
- {
- PlayTimerStartSound(client);
- }
-
- // Call Post Forward
- Call_GOKZ_OnTimerStart_Post(client, course);
-
- return true;
-}
-
-bool TimerEnd(int client, int course)
-{
- if (!IsPlayerAlive(client))
- {
- return false;
- }
-
- if (!timerRunning[client] || course != currentCourse[client])
- {
- PlayTimerFalseEndSound(client);
- lastFalseEndTime[client] = GetGameTime();
- return false;
- }
-
- float time = GetCurrentTime(client);
- int teleportsUsed = GetTeleportCount(client);
-
- // Call Pre Forward
- Action result;
- Call_GOKZ_OnTimerEnd(client, course, time, teleportsUsed, result);
- if (result != Plugin_Continue)
- {
- return false;
- }
-
- if (!validTime[client])
- {
- PlayTimerFalseEndSound(client);
- lastFalseEndTime[client] = GetGameTime();
- TimerStop(client, false);
- return false;
- }
- // End Timer
- timerRunning[client] = false;
- lastEndTime[client] = GetGameTime();
- PlayTimerEndSound(client);
-
- if (!IsFakeClient(client))
- {
- // Print end timer message
- Call_GOKZ_OnTimerEndMessage(client, course, time, teleportsUsed, result);
- if (result == Plugin_Continue)
- {
- PrintEndTimeString(client);
- }
- }
-
- // Call Post Forward
- Call_GOKZ_OnTimerEnd_Post(client, course, time, teleportsUsed);
-
- return true;
-}
-
-bool TimerStop(int client, bool playSound = true)
-{
- if (!timerRunning[client])
- {
- return false;
- }
-
- timerRunning[client] = false;
- if (playSound)
- {
- PlayTimerStopSound(client);
- }
-
- Call_GOKZ_OnTimerStopped(client);
-
- return true;
-}
-
-void TimerStopAll(bool playSound = true)
-{
- for (int client = 1; client <= MaxClients; client++)
- {
- if (IsValidClient(client))
- {
- TimerStop(client, playSound);
- }
- }
-}
-
-void PlayTimerStartSound(int client)
-{
- if (GetGameTime() - lastStartSoundTime[client] > GOKZ_TIMER_SOUND_COOLDOWN)
- {
- GOKZ_EmitSoundToClient(client, gC_ModeStartSounds[GOKZ_GetCoreOption(client, Option_Mode)], _, "Timer Start");
- GOKZ_EmitSoundToClientSpectators(client, gC_ModeStartSounds[GOKZ_GetCoreOption(client, Option_Mode)], _, "Timer Start");
- lastStartSoundTime[client] = GetGameTime();
- }
-}
-
-void InvalidateRun(int client)
-{
- if (validTime[client])
- {
- validTime[client] = false;
- Call_GOKZ_OnRunInvalidated(client);
- }
-}
-
-// =====[ EVENTS ]=====
-
-void OnClientPutInServer_Timer(int client)
-{
- timerRunning[client] = false;
- currentTime[client] = 0.0;
- currentCourse[client] = 0;
- lastEndTime[client] = 0.0;
- lastFalseEndTime[client] = 0.0;
- lastStartSoundTime[client] = 0.0;
- lastStartMode[client] = MODE_COUNT; // So it won't equal any mode
-}
-
-void OnPlayerRunCmdPost_Timer(int client)
-{
- if (IsPlayerAlive(client) && GetTimerRunning(client) && !GetPaused(client))
- {
- currentTime[client] += GetTickInterval();
- }
-}
-
-void OnChangeMovetype_Timer(int client, MoveType newMovetype)
-{
- if (!IsValidMovetype(newMovetype))
- {
- if (TimerStop(client))
- {
- GOKZ_PrintToChat(client, true, "%t", "Timer Stopped (Noclipped)");
- }
- }
-}
-
-void OnTeleportToStart_Timer(int client)
-{
- if (GetCurrentMapPrefix() == MapPrefix_KZPro)
- {
- TimerStop(client, false);
- }
-}
-
-void OnClientDisconnect_Timer(int client)
-{
- TimerStop(client);
-}
-
-void OnPlayerDeath_Timer(int client)
-{
- TimerStop(client);
-}
-
-void OnOptionChanged_Timer(int client, Option option)
-{
- if (option == Option_Mode)
- {
- if (TimerStop(client))
- {
- GOKZ_PrintToChat(client, true, "%t", "Timer Stopped (Changed Mode)");
- }
- }
-}
-
-void OnRoundStart_Timer()
-{
- TimerStopAll();
-}
-
-
-
-// =====[ PRIVATE ]=====
-
-static bool IsPlayerValidMoveType(int client)
-{
- return IsValidMovetype(Movement_GetMovetype(client));
-}
-
-static bool IsValidMovetype(MoveType movetype)
-{
- return movetype == MOVETYPE_WALK
- || movetype == MOVETYPE_LADDER
- || movetype == MOVETYPE_NONE
- || movetype == MOVETYPE_OBSERVER;
-}
-
-static bool JustTeleported(int client)
-{
- return gB_OriginTeleported[client] || gB_VelocityTeleported[client]
- || gI_CmdNum[client] - gI_TeleportCmdNum[client] <= GOKZ_TIMER_START_GROUND_TICKS;
-}
-
-static bool JustLanded(int client)
-{
- return !gB_OldOnGround[client]
- || gI_CmdNum[client] - Movement_GetLandingCmdNum(client) <= GOKZ_TIMER_START_NO_TELEPORT_TICKS;
-}
-
-static bool JustStartedTimer(int client)
-{
- return timerRunning[client] && GetCurrentTime(client) < EPSILON;
-}
-
-static bool JustEndedTimer(int client)
-{
- return GetGameTime() - lastEndTime[client] < 1.0;
-}
-
-static void PlayTimerEndSound(int client)
-{
- GOKZ_EmitSoundToClient(client, gC_ModeEndSounds[GOKZ_GetCoreOption(client, Option_Mode)], _, "Timer End");
- GOKZ_EmitSoundToClientSpectators(client, gC_ModeEndSounds[GOKZ_GetCoreOption(client, Option_Mode)], _, "Timer End");
-}
-
-static void PlayTimerFalseEndSound(int client)
-{
- if (!JustEndedTimer(client)
- && (GetGameTime() - lastFalseEndTime[client]) > GOKZ_TIMER_SOUND_COOLDOWN)
- {
- GOKZ_EmitSoundToClient(client, gC_ModeFalseEndSounds[GOKZ_GetCoreOption(client, Option_Mode)], _, "Timer False End");
- GOKZ_EmitSoundToClientSpectators(client, gC_ModeFalseEndSounds[GOKZ_GetCoreOption(client, Option_Mode)], _, "Timer False End");
- }
-}
-
-static void PlayTimerStopSound(int client)
-{
- GOKZ_EmitSoundToClient(client, GOKZ_SOUND_TIMER_STOP, _, "Timer Stop");
- GOKZ_EmitSoundToClientSpectators(client, GOKZ_SOUND_TIMER_STOP, _, "Timer Stop");
-}
-
-static void PrintEndTimeString(int client)
-{
- if (GetCurrentCourse(client) == 0)
- {
- switch (GetCurrentTimeType(client))
- {
- case TimeType_Nub:
- {
- GOKZ_PrintToChatAll(true, "%t", "Beat Map (NUB)",
- client,
- GOKZ_FormatTime(GetCurrentTime(client)),
- gC_ModeNamesShort[GOKZ_GetCoreOption(client, Option_Mode)]);
- }
- case TimeType_Pro:
- {
- GOKZ_PrintToChatAll(true, "%t", "Beat Map (PRO)",
- client,
- GOKZ_FormatTime(GetCurrentTime(client)),
- gC_ModeNamesShort[GOKZ_GetCoreOption(client, Option_Mode)]);
- }
- }
- }
- else
- {
- switch (GetCurrentTimeType(client))
- {
- case TimeType_Nub:
- {
- GOKZ_PrintToChatAll(true, "%t", "Beat Bonus (NUB)",
- client,
- currentCourse[client],
- GOKZ_FormatTime(GetCurrentTime(client)),
- gC_ModeNamesShort[GOKZ_GetCoreOption(client, Option_Mode)]);
- }
- case TimeType_Pro:
- {
- GOKZ_PrintToChatAll(true, "%t", "Beat Bonus (PRO)",
- client,
- currentCourse[client],
- GOKZ_FormatTime(GetCurrentTime(client)),
- gC_ModeNamesShort[GOKZ_GetCoreOption(client, Option_Mode)]);
- }
- }
- }
-} \ No newline at end of file
diff --git a/sourcemod/scripting/gokz-core/timer/virtual_buttons.sp b/sourcemod/scripting/gokz-core/timer/virtual_buttons.sp
deleted file mode 100644
index aa88a9d..0000000
--- a/sourcemod/scripting/gokz-core/timer/virtual_buttons.sp
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- Most commonly referred to in the KZ community as timer tech.
- Lets players press 'virtual' start and end buttons without looking.
-*/
-
-
-
-static int beamSprite;
-static int haloSprite;
-static float lastUsePressTime[MAXPLAYERS + 1];
-static int lastTeleportTick[MAXPLAYERS + 1];
-static bool startedTimerLastTick[MAXPLAYERS + 1];
-static bool onlyNaturalButtonPressed[MAXPLAYERS + 1];
-static int startTimerButtonPressTick[MAXPLAYERS + 1];
-static bool hasEndedTimerSincePressingUse[MAXPLAYERS + 1];
-static bool hasTeleportedSincePressingUse[MAXPLAYERS + 1];
-static bool hasVirtualStartButton[MAXPLAYERS + 1];
-static bool hasVirtualEndButton[MAXPLAYERS + 1];
-static bool wasInEndZone[MAXPLAYERS + 1];
-static float virtualStartOrigin[MAXPLAYERS + 1][3];
-static float virtualEndOrigin[MAXPLAYERS + 1][3];
-static int virtualStartCourse[MAXPLAYERS + 1];
-static int virtualEndCourse[MAXPLAYERS + 1];
-static bool virtualButtonsLocked[MAXPLAYERS + 1];
-
-
-
-// =====[ PUBLIC ]=====
-
-bool GetHasVirtualStartButton(int client)
-{
- return hasVirtualStartButton[client];
-}
-
-bool GetHasVirtualEndButton(int client)
-{
- return hasVirtualEndButton[client];
-}
-
-bool ToggleVirtualButtonsLock(int client)
-{
- virtualButtonsLocked[client] = !virtualButtonsLocked[client];
- return virtualButtonsLocked[client];
-}
-
-void LockVirtualButtons(int client)
-{
- virtualButtonsLocked[client] = true;
-}
-
-int GetVirtualButtonPosition(int client, float position[3], bool isStart)
-{
- if (isStart && hasVirtualStartButton[client])
- {
- position = virtualStartOrigin[client];
- return virtualStartCourse[client];
- }
- else if (!isStart && hasVirtualEndButton[client])
- {
- position = virtualEndOrigin[client];
- return virtualEndCourse[client];
- }
-
- return -1;
-}
-
-void SetVirtualButtonPosition(int client, float position[3], int course, bool isStart)
-{
- if (isStart)
- {
- virtualStartCourse[client] = course;
- virtualStartOrigin[client] = position;
- hasVirtualStartButton[client] = true;
- }
- else
- {
- virtualEndCourse[client] = course;
- virtualEndOrigin[client] = position;
- hasVirtualEndButton[client] = true;
- }
-}
-
-void ResetVirtualButtonPosition(int client, bool isStart)
-{
- if (isStart)
- {
- virtualStartCourse[client] = -1;
- virtualStartOrigin[client] = {0.0, 0.0, 0.0};
- hasVirtualStartButton[client] = false;
- }
- else
- {
- virtualEndCourse[client] = -1;
- virtualEndOrigin[client] = {0.0, 0.0, 0.0};
- hasVirtualEndButton[client] = false;
- }
-}
-
-// =====[ EVENTS ]=====
-
-void OnMapStart_VirtualButtons()
-{
- beamSprite = PrecacheModel("materials/sprites/laserbeam.vmt");
- haloSprite = PrecacheModel("materials/sprites/glow01.vmt");
-}
-
-void OnClientPutInServer_VirtualButtons(int client)
-{
- startedTimerLastTick[client] = false;
- hasVirtualEndButton[client] = false;
- hasVirtualStartButton[client] = false;
- virtualButtonsLocked[client] = false;
- onlyNaturalButtonPressed[client] = false;
- wasInEndZone[client] = false;
- startTimerButtonPressTick[client] = 0;
-}
-
-void OnStartButtonPress_VirtualButtons(int client, int course)
-{
- if (!virtualButtonsLocked[client] &&
- lastTeleportTick[client] + GOKZ_TIMER_START_NO_TELEPORT_TICKS < GetGameTickCount())
- {
- Movement_GetOrigin(client, virtualStartOrigin[client]);
- virtualStartCourse[client] = course;
- hasVirtualStartButton[client] = true;
- startTimerButtonPressTick[client] = GetGameTickCount();
- }
-}
-
-void OnEndButtonPress_VirtualButtons(int client, int course)
-{
- // Prevent setting end virtual button to where it would usually be unreachable
- if (IsPlayerStuck(client))
- {
- return;
- }
-
- if (!virtualButtonsLocked[client] &&
- lastTeleportTick[client] + GOKZ_TIMER_START_NO_TELEPORT_TICKS < GetGameTickCount())
- {
- Movement_GetOrigin(client, virtualEndOrigin[client]);
- virtualEndCourse[client] = course;
- hasVirtualEndButton[client] = true;
- }
-}
-
-void OnPlayerRunCmdPost_VirtualButtons(int client, int buttons, int cmdnum)
-{
- CheckForAndHandleUsage(client, buttons);
- UpdateIndicators(client, cmdnum);
-}
-
-void OnCountedTeleport_VirtualButtons(int client)
-{
- hasTeleportedSincePressingUse[client] = true;
-}
-
-void OnTeleport_DelayVirtualButtons(int client)
-{
- lastTeleportTick[client] = GetGameTickCount();
-}
-
-
-
-// =====[ PRIVATE ]=====
-
-static void CheckForAndHandleUsage(int client, int buttons)
-{
- if (buttons & IN_USE && !(gI_OldButtons[client] & IN_USE))
- {
- lastUsePressTime[client] = GetGameTime();
- hasEndedTimerSincePressingUse[client] = false;
- hasTeleportedSincePressingUse[client] = false;
- onlyNaturalButtonPressed[client] = startTimerButtonPressTick[client] == GetGameTickCount();
- }
-
- bool useCheck = PassesUseCheck(client);
-
- // Start button
- if ((useCheck || GOKZ_GetCoreOption(client, Option_TimerButtonZoneType) == TimerButtonZoneType_BothZones)
- && GetHasVirtualStartButton(client) && InRangeOfVirtualStart(client) && CanReachVirtualStart(client))
- {
- if (TimerStart(client, virtualStartCourse[client], .playSound = false))
- {
- startedTimerLastTick[client] = true;
- OnVirtualStartButtonPress_Teleports(client);
- }
- }
- else if (startedTimerLastTick[client])
- {
- // Without that check you get two sounds when pressing the natural timer button
- if (!onlyNaturalButtonPressed[client])
- {
- PlayTimerStartSound(client);
- }
- onlyNaturalButtonPressed[client] = false;
- startedTimerLastTick[client] = false;
- }
-
- // End button
- if ((useCheck || GOKZ_GetCoreOption(client, Option_TimerButtonZoneType) != TimerButtonZoneType_BothButtons)
- && GetHasVirtualEndButton(client) && InRangeOfVirtualEnd(client) && CanReachVirtualEnd(client))
- {
- if (!wasInEndZone[client])
- {
- TimerEnd(client, virtualEndCourse[client]);
- hasEndedTimerSincePressingUse[client] = true; // False end counts as well
- wasInEndZone[client] = true;
- }
- }
- else
- {
- wasInEndZone[client] = false;
- }
-}
-
-static bool PassesUseCheck(int client)
-{
- if (GetGameTime() - lastUsePressTime[client] < GOKZ_VIRTUAL_BUTTON_USE_DETECTION_TIME + EPSILON
- && !hasEndedTimerSincePressingUse[client]
- && !hasTeleportedSincePressingUse[client])
- {
- return true;
- }
-
- return false;
-}
-
-bool InRangeOfVirtualStart(int client)
-{
- return InRangeOfButton(client, virtualStartOrigin[client]);
-}
-
-static bool InRangeOfVirtualEnd(int client)
-{
- return InRangeOfButton(client, virtualEndOrigin[client]);
-}
-
-static bool InRangeOfButton(int client, const float buttonOrigin[3])
-{
- float origin[3];
- Movement_GetOrigin(client, origin);
- float distanceToButton = GetVectorDistance(origin, buttonOrigin);
- return distanceToButton <= gF_ModeVirtualButtonRanges[GOKZ_GetCoreOption(client, Option_Mode)];
-}
-
-bool CanReachVirtualStart(int client)
-{
- return CanReachButton(client, virtualStartOrigin[client]);
-}
-
-static bool CanReachVirtualEnd(int client)
-{
- return CanReachButton(client, virtualEndOrigin[client]);
-}
-
-static bool CanReachButton(int client, const float buttonOrigin[3])
-{
- float origin[3];
- Movement_GetOrigin(client, origin);
- Handle trace = TR_TraceRayFilterEx(origin, buttonOrigin, MASK_PLAYERSOLID, RayType_EndPoint, TraceEntityFilterPlayers);
- bool didHit = TR_DidHit(trace);
- delete trace;
- return !didHit;
-}
-
-
-
-// ===== [ INDICATOR ] =====
-
-static void UpdateIndicators(int client, int cmdnum)
-{
- if (cmdnum % 128 != 0 || !IsPlayerAlive(client)
- || GOKZ_GetCoreOption(client, Option_VirtualButtonIndicators) == VirtualButtonIndicators_Disabled)
- {
- return;
- }
-
- if (hasVirtualStartButton[client])
- {
- DrawIndicator(client, virtualStartOrigin[client], { 0, 255, 0, 255 } );
- }
-
- if (hasVirtualEndButton[client])
- {
- DrawIndicator(client, virtualEndOrigin[client], { 255, 0, 0, 255 } );
- }
-}
-
-static void DrawIndicator(int client, const float origin[3], const int colour[4])
-{
- float radius = gF_ModeVirtualButtonRanges[GOKZ_GetCoreOption(client, Option_Mode)];
- if (radius <= EPSILON) // Don't draw circle of radius 0
- {
- return;
- }
-
- float x, y, start[3], end[3];
-
- // Create the start position for the first part of the beam
- start[0] = origin[0] + radius;
- start[1] = origin[1];
- start[2] = origin[2];
-
- for (int i = 1; i <= 31; i++) // Circle is broken into 31 segments
- {
- float angle = 2 * PI / 31 * i;
- x = radius * Cosine(angle);
- y = radius * Sine(angle);
-
- end[0] = origin[0] + x;
- end[1] = origin[1] + y;
- end[2] = origin[2];
-
- TE_SetupBeamPoints(start, end, beamSprite, haloSprite, 0, 0, 0.97, 0.2, 0.2, 0, 0.0, colour, 0);
- TE_SendToClient(client);
-
- start[0] = end[0];
- start[1] = end[1];
- start[2] = end[2];
- }
-}
diff --git a/sourcemod/scripting/gokz-core/triggerfix.sp b/sourcemod/scripting/gokz-core/triggerfix.sp
deleted file mode 100644
index 424928d..0000000
--- a/sourcemod/scripting/gokz-core/triggerfix.sp
+++ /dev/null
@@ -1,622 +0,0 @@
-
-
-// Credits:
-// RNGFix made by rio https://github.com/jason-e/rngfix
-
-
-// Engine constants, NOT settings (do not change)
-#define LAND_HEIGHT 2.0 // Maximum height above ground at which you can "land"
-#define MIN_STANDABLE_ZNRM 0.7 // Minimum surface normal Z component of a walkable surface
-
-static int processMovementTicks[MAXPLAYERS+1];
-static float playerFrameTime[MAXPLAYERS+1];
-
-static bool touchingTrigger[MAXPLAYERS+1][2048];
-static int triggerTouchFired[MAXPLAYERS+1][2048];
-static int lastGroundEnt[MAXPLAYERS + 1];
-static bool duckedLastTick[MAXPLAYERS + 1];
-static bool mapTeleportedSequentialTicks[MAXPLAYERS+1];
-static bool jumpBugged[MAXPLAYERS + 1];
-static float jumpBugOrigin[MAXPLAYERS + 1][3];
-
-static ConVar cvGravity;
-
-static Handle acceptInputHookPre;
-static Handle processMovementHookPre;
-static Address serverGameEnts;
-static Handle markEntitiesAsTouching;
-static Handle passesTriggerFilters;
-
-public void OnPluginStart_Triggerfix()
-{
- HookEvent("player_jump", Event_PlayerJump);
-
- cvGravity = FindConVar("sv_gravity");
- if (cvGravity == null)
- {
- SetFailState("Could not find sv_gravity");
- }
-
- GameData gamedataConf = LoadGameConfigFile("gokz-core.games");
- if (gamedataConf == null)
- {
- SetFailState("Failed to load gokz-core gamedata");
- }
-
- // PassesTriggerFilters
- StartPrepSDKCall(SDKCall_Entity);
- if (!PrepSDKCall_SetFromConf(gamedataConf, SDKConf_Virtual, "CBaseTrigger::PassesTriggerFilters"))
- {
- SetFailState("Failed to get CBaseTrigger::PassesTriggerFilters offset");
- }
- PrepSDKCall_SetReturnInfo(SDKType_Bool, SDKPass_Plain);
- PrepSDKCall_AddParameter(SDKType_CBaseEntity, SDKPass_Pointer);
- passesTriggerFilters = EndPrepSDKCall();
-
- if (passesTriggerFilters == null) SetFailState("Unable to prepare SDKCall for CBaseTrigger::PassesTriggerFilters");
-
- // CreateInterface
- // Thanks SlidyBat and ici
- StartPrepSDKCall(SDKCall_Static);
- if (!PrepSDKCall_SetFromConf(gamedataConf, SDKConf_Signature, "CreateInterface"))
- {
- SetFailState("Failed to get CreateInterface");
- }
- PrepSDKCall_AddParameter(SDKType_String, SDKPass_Pointer);
- PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Pointer, VDECODE_FLAG_ALLOWNULL);
- PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain);
- Handle CreateInterface = EndPrepSDKCall();
-
- if (CreateInterface == null)
- {
- SetFailState("Unable to prepare SDKCall for CreateInterface");
- }
-
- char interfaceName[64];
-
- // ProcessMovement
- if (!GameConfGetKeyValue(gamedataConf, "IGameMovement", interfaceName, sizeof(interfaceName)))
- {
- SetFailState("Failed to get IGameMovement interface name");
- }
- Address IGameMovement = SDKCall(CreateInterface, interfaceName, 0);
- if (!IGameMovement)
- {
- SetFailState("Failed to get IGameMovement pointer");
- }
-
- int offset = GameConfGetOffset(gamedataConf, "ProcessMovement");
- if (offset == -1)
- {
- SetFailState("Failed to get ProcessMovement offset");
- }
-
- processMovementHookPre = DHookCreate(offset, HookType_Raw, ReturnType_Void, ThisPointer_Ignore, DHook_ProcessMovementPre);
- DHookAddParam(processMovementHookPre, HookParamType_CBaseEntity);
- DHookAddParam(processMovementHookPre, HookParamType_ObjectPtr);
- DHookRaw(processMovementHookPre, false, IGameMovement);
-
- // MarkEntitiesAsTouching
- if (!GameConfGetKeyValue(gamedataConf, "IServerGameEnts", interfaceName, sizeof(interfaceName)))
- {
- SetFailState("Failed to get IServerGameEnts interface name");
- }
- serverGameEnts = SDKCall(CreateInterface, interfaceName, 0);
- if (!serverGameEnts)
- {
- SetFailState("Failed to get IServerGameEnts pointer");
- }
-
- StartPrepSDKCall(SDKCall_Raw);
- if (!PrepSDKCall_SetFromConf(gamedataConf, SDKConf_Virtual, "IServerGameEnts::MarkEntitiesAsTouching"))
- {
- SetFailState("Failed to get IServerGameEnts::MarkEntitiesAsTouching offset");
- }
- PrepSDKCall_AddParameter(SDKType_Edict, SDKPass_Pointer);
- PrepSDKCall_AddParameter(SDKType_Edict, SDKPass_Pointer);
- markEntitiesAsTouching = EndPrepSDKCall();
-
- if (markEntitiesAsTouching == null)
- {
- SetFailState("Unable to prepare SDKCall for IServerGameEnts::MarkEntitiesAsTouching");
- }
-
- gamedataConf = LoadGameConfigFile("sdktools.games/engine.csgo");
- offset = gamedataConf.GetOffset("AcceptInput");
- if (offset == -1)
- {
- SetFailState("Failed to get AcceptInput offset");
- }
-
- acceptInputHookPre = DHookCreate(offset, HookType_Entity, ReturnType_Bool, ThisPointer_CBaseEntity, DHooks_AcceptInput);
- DHookAddParam(acceptInputHookPre, HookParamType_CharPtr);
- DHookAddParam(acceptInputHookPre, HookParamType_CBaseEntity);
- DHookAddParam(acceptInputHookPre, HookParamType_CBaseEntity);
- //varaint_t is a union of 12 (float[3]) plus two int type params 12 + 8 = 20
- DHookAddParam(acceptInputHookPre, HookParamType_Object, 20, DHookPass_ByVal|DHookPass_ODTOR|DHookPass_OCTOR|DHookPass_OASSIGNOP);
- DHookAddParam(acceptInputHookPre, HookParamType_Int);
-
- delete CreateInterface;
- delete gamedataConf;
-
- if (gB_LateLoad)
- {
- for (int client = 1; client <= MaxClients; client++)
- {
- if (IsClientInGame(client)) OnClientPutInServer(client);
- }
-
- char classname[64];
- for (int entity = MaxClients+1; entity < sizeof(touchingTrigger[]); entity++)
- {
- if (!IsValidEntity(entity)) continue;
- GetEntPropString(entity, Prop_Data, "m_iClassname", classname, sizeof(classname));
- HookTrigger(entity, classname);
- }
- }
-}
-
-public void OnEntityCreated_Triggerfix(int entity, const char[] classname)
-{
- if (entity >= sizeof(touchingTrigger[]))
- {
- return;
- }
- HookTrigger(entity, classname);
-}
-
-public void OnClientConnected_Triggerfix(int client)
-{
- processMovementTicks[client] = 0;
- for (int i = 0; i < sizeof(touchingTrigger[]); i++)
- {
- touchingTrigger[client][i] = false;
- triggerTouchFired[client][i] = 0;
- }
-}
-
-public void OnClientPutInServer_Triggerfix(int client)
-{
- SDKHook(client, SDKHook_PostThink, Hook_PlayerPostThink);
- DHookEntity(acceptInputHookPre, false, client);
-}
-
-public void OnGameFrame_Triggerfix()
-{
- // Loop through all the players and make sure that triggers that are supposed to be fired but weren't now
- // get fired properly.
- // This must be run OUTSIDE of usercmd, because sometimes usercmd gets delayed heavily.
- for (int client = 1; client <= MaxClients; client++)
- {
- if (IsValidClient(client) && IsPlayerAlive(client) && !CheckWater(client) &&
- (GetEntityMoveType(client) == MOVETYPE_WALK || GetEntityMoveType(client) == MOVETYPE_LADDER))
- {
- DoTriggerFix(client);
-
- // Reset the Touch tracking.
- // We save a bit of performance by putting this inside the loop
- // Even if triggerTouchFired is not correct, touchingTrigger still is.
- // That should prevent DoTriggerFix from activating the wrong triggers.
- // Plus, players respawn where they previously are as well with a timer on,
- // so this should not be a big problem.
- for (int trigger = 0; trigger < sizeof(triggerTouchFired[]); trigger++)
- {
- triggerTouchFired[client][trigger] = 0;
- }
- }
- }
-}
-
-void OnPlayerRunCmd_Triggerfix(int client)
-{
- // Reset the Touch tracking.
- // While this is mostly unnecessary, it can also happen that the server runs multiple ticks of player movement at once,
- // therefore the triggers need to be checked again.
- for (int trigger = 0; trigger < sizeof(triggerTouchFired[]); trigger++)
- {
- triggerTouchFired[client][trigger] = 0;
- }
-}
-
-static void Event_PlayerJump(Event event, const char[] name, bool dontBroadcast)
-{
- int client = GetClientOfUserId(event.GetInt("userid"));
-
- jumpBugged[client] = !!lastGroundEnt[client];
- if (jumpBugged[client])
- {
- GetClientAbsOrigin(client, jumpBugOrigin[client]);
- // if player's origin is still in the ducking position then adjust for that.
- if (duckedLastTick[client] && !Movement_GetDucking(client))
- {
- jumpBugOrigin[client][2] -= 9.0;
- }
- }
-}
-
-static Action Hook_TriggerStartTouch(int entity, int other)
-{
- if (1 <= other <= MaxClients)
- {
- touchingTrigger[other][entity] = true;
- }
-
- return Plugin_Continue;
-}
-
-static Action Hook_TriggerEndTouch(int entity, int other)
-{
- if (1 <= other <= MaxClients)
- {
- touchingTrigger[other][entity] = false;
- }
- return Plugin_Continue;
-}
-
-static Action Hook_TriggerTouch(int entity, int other)
-{
- if (1 <= other <= MaxClients)
- {
- triggerTouchFired[other][entity]++;
- }
- return Plugin_Continue;
-}
-
-static MRESReturn DHook_ProcessMovementPre(Handle hParams)
-{
- int client = DHookGetParam(hParams, 1);
-
- processMovementTicks[client]++;
- playerFrameTime[client] = GetTickInterval() * GetEntPropFloat(client, Prop_Data, "m_flLaggedMovementValue");
- mapTeleportedSequentialTicks[client] = false;
-
- if (IsPlayerAlive(client))
- {
- if (GetEntityMoveType(client) == MOVETYPE_WALK
- && !CheckWater(client))
- {
- lastGroundEnt[client] = GetEntPropEnt(client, Prop_Data, "m_hGroundEntity");
- }
- duckedLastTick[client] = Movement_GetDucking(client);
- }
-
- return MRES_Ignored;
-}
-
-static MRESReturn DHooks_AcceptInput(int client, DHookReturn hReturn, DHookParam hParams)
-{
- if (!IsValidClient(client) || !IsPlayerAlive(client) || CheckWater(client) ||
- (GetEntityMoveType(client) != MOVETYPE_WALK && GetEntityMoveType(client) != MOVETYPE_LADDER))
- {
- return MRES_Ignored;
- }
-
- // Get args
- static char param[64];
- static char command[64];
- DHookGetParamString(hParams, 1, command, sizeof(command));
- if (StrEqual(command, "AddOutput"))
- {
- DHookGetParamObjectPtrString(hParams, 4, 0, ObjectValueType_String, param, sizeof(param));
- char kv[16];
- SplitString(param, " ", kv, sizeof(kv));
- // KVs are case insensitive.
- // Any of these inputs can change the filter behavior.
- if (StrEqual(kv[0], "targetname", false) || StrEqual(kv[0], "teamnumber", false) || StrEqual(kv[0], "classname", false) || StrEqual(command, "ResponseContext", false))
- {
- DoTriggerFix(client, true);
- }
- }
- else if (StrEqual(command, "AddContext") || StrEqual(command, "RemoveContext") || StrEqual(command, "ClearContext"))
- {
- DoTriggerFix(client, true);
- }
- return MRES_Ignored;
-}
-
-static bool DoTriggerFix(int client, bool filterFix = false)
-{
- // Adapted from DoTriggerjumpFix right below.
- float landingMins[3], landingMaxs[3];
- float origin[3];
-
- GetEntPropVector(client, Prop_Data, "m_vecAbsOrigin", origin);
- GetEntPropVector(client, Prop_Data, "m_vecMins", landingMins);
- GetEntPropVector(client, Prop_Data, "m_vecMaxs", landingMaxs);
-
- ArrayList triggers = new ArrayList();
- // Get a list of triggers that we are touching now.
-
- TR_EnumerateEntitiesHull(origin, origin, landingMins, landingMaxs, true, AddTrigger, triggers);
-
- bool didSomething = false;
-
- for (int i = 0; i < triggers.Length; i++)
- {
- int trigger = triggers.Get(i);
- if (!touchingTrigger[client][trigger])
- {
- // Normally this wouldn't happen, because the trigger should be colliding with the player's hull if it gets here.
- continue;
- }
- char className[64];
- GetEntityClassname(trigger, className, sizeof(className));
- if (StrEqual(className, "trigger_push"))
- {
- // Completely ignore push triggers.
- continue;
- }
- if (filterFix && SDKCall(passesTriggerFilters, trigger, client) && triggerTouchFired[client][trigger] < GOKZ_MAX_RETOUCH_TRIGGER_COUNT)
- {
- // MarkEntitiesAsTouching always fires the Touch function even if it was already fired this tick.
- SDKCall(markEntitiesAsTouching, serverGameEnts, client, trigger);
-
- // Player properties might be changed right after this so it will need to be triggered again.
- // Triggers changing this filter will loop onto itself infintely so we need to avoid that.
- triggerTouchFired[client][trigger]++;
- didSomething = true;
- }
- else if (!triggerTouchFired[client][trigger])
- {
- // If the player is still touching the trigger on this tick, and Touch was not called for whatever reason
- // in the last tick, we make sure that it is called now.
- SDKCall(markEntitiesAsTouching, serverGameEnts, client, trigger);
- triggerTouchFired[client][trigger]++;
- didSomething = true;
- }
- }
-
- delete triggers;
-
- return didSomething;
-}
-
-static bool DoTriggerjumpFix(int client, const float landingPoint[3], const float landingMins[3], const float landingMaxs[3])
-{
- // It's possible to land above a trigger but also in another trigger_teleport, have the teleport move you to
- // another location, and then the trigger jumping fix wouldn't fire the other trigger you technically landed above,
- // but I can't imagine a mapper would ever actually stack triggers like that.
-
- float origin[3];
- GetEntPropVector(client, Prop_Data, "m_vecAbsOrigin", origin);
-
- float landingMaxsBelow[3];
- landingMaxsBelow[0] = landingMaxs[0];
- landingMaxsBelow[1] = landingMaxs[1];
- landingMaxsBelow[2] = origin[2] - landingPoint[2];
-
- ArrayList triggers = new ArrayList();
-
- // Find triggers that are between us and the ground (using the bounding box quadrant we landed with if applicable).
- // This will fail on triggers thinner than 0.03125 unit thick, but it's highly unlikely that a mapper would put a trigger that thin.
- TR_EnumerateEntitiesHull(landingPoint, landingPoint, landingMins, landingMaxsBelow, true, AddTrigger, triggers);
-
- bool didSomething = false;
-
- for (int i = 0; i < triggers.Length; i++)
- {
- int trigger = triggers.Get(i);
-
- // MarkEntitiesAsTouching always fires the Touch function even if it was already fired this tick.
- // In case that could cause side-effects, manually keep track of triggers we are actually touching
- // and don't re-touch them.
- if (touchingTrigger[client][trigger])
- {
- continue;
- }
-
- SDKCall(markEntitiesAsTouching, serverGameEnts, client, trigger);
- didSomething = true;
- }
-
- delete triggers;
-
- return didSomething;
-}
-
-// PostThink works a little better than a ProcessMovement post hook because we need to wait for ProcessImpacts (trigger activation)
-static void Hook_PlayerPostThink(int client)
-{
- if (!IsPlayerAlive(client)
- || GetEntityMoveType(client) != MOVETYPE_WALK
- || CheckWater(client))
- {
- return;
- }
-
- bool landed = (GetEntPropEnt(client, Prop_Data, "m_hGroundEntity") != -1
- && lastGroundEnt[client] == -1)
- || jumpBugged[client];
-
- float landingMins[3], landingMaxs[3], landingPoint[3];
-
- // Get info about the ground we landed on (if we need to do landing fixes).
- if (landed)
- {
- float origin[3], nrm[3], velocity[3];
- GetEntPropVector(client, Prop_Data, "m_vecAbsOrigin", origin);
- GetEntPropVector(client, Prop_Data, "m_vecVelocity", velocity);
-
- if (jumpBugged[client])
- {
- origin = jumpBugOrigin[client];
- }
-
- GetEntPropVector(client, Prop_Data, "m_vecMins", landingMins);
- GetEntPropVector(client, Prop_Data, "m_vecMaxs", landingMaxs);
-
- float originBelow[3];
- originBelow[0] = origin[0];
- originBelow[1] = origin[1];
- originBelow[2] = origin[2] - LAND_HEIGHT;
-
- TR_TraceHullFilter(origin, originBelow, landingMins, landingMaxs, MASK_PLAYERSOLID, PlayerFilter);
-
- if (!TR_DidHit())
- {
- // This should never happen, since we know we are on the ground.
- landed = false;
- }
- else
- {
- TR_GetPlaneNormal(null, nrm);
-
- if (nrm[2] < MIN_STANDABLE_ZNRM)
- {
- // This is rare, and how the incline fix should behave isn't entirely clear because maybe we should
- // collide with multiple faces at once in this case, but let's just get the ground we officially
- // landed on and use that for our ground normal.
-
- // landingMins and landingMaxs will contain the final values used to find the ground after returning.
- if (TracePlayerBBoxForGround(origin, originBelow, landingMins, landingMaxs))
- {
- TR_GetPlaneNormal(null, nrm);
- }
- else
- {
- // This should also never happen.
- landed = false;
- }
- }
-
- TR_GetEndPosition(landingPoint);
- }
- }
-
- // reset it here because we don't need it again
- jumpBugged[client] = false;
-
- // Must use TR_DidHit because if the unduck origin is closer than 0.03125 units from the ground,
- // the trace fraction would return 0.0.
- if (landed && TR_DidHit())
- {
- DoTriggerjumpFix(client, landingPoint, landingMins, landingMaxs);
- // Check if a trigger we just touched put us in the air (probably due to a teleport).
- if (GetEntityFlags(client) & FL_ONGROUND == 0)
- {
- landed = false;
- }
- }
-}
-
-static bool PlayerFilter(int entity, int mask)
-{
- return !(1 <= entity <= MaxClients);
-}
-
-static void HookTrigger(int entity, const char[] classname)
-{
- if (StrContains(classname, "trigger_") != -1)
- {
- SDKHook(entity, SDKHook_StartTouchPost, Hook_TriggerStartTouch);
- SDKHook(entity, SDKHook_EndTouchPost, Hook_TriggerEndTouch);
- SDKHook(entity, SDKHook_TouchPost, Hook_TriggerTouch);
- }
-}
-
-static bool CheckWater(int client)
-{
- // The cached water level is updated multiple times per tick, including after movement happens,
- // so we can just check the cached value here.
- return GetEntProp(client, Prop_Data, "m_nWaterLevel") > 1;
-}
-
-public bool AddTrigger(int entity, ArrayList triggers)
-{
- TR_ClipCurrentRayToEntity(MASK_ALL, entity);
- if (TR_DidHit())
- {
- triggers.Push(entity);
- }
-
- return true;
-}
-
-static bool TracePlayerBBoxForGround(const float origin[3], const float originBelow[3], float mins[3], float maxs[3])
-{
- // See CGameMovement::TracePlayerBBoxForGround()
-
- float origMins[3], origMaxs[3];
- origMins = mins;
- origMaxs = maxs;
-
- float nrm[3];
-
- mins = origMins;
-
- // -x -y
- maxs[0] = origMaxs[0] > 0.0 ? 0.0 : origMaxs[0];
- maxs[1] = origMaxs[1] > 0.0 ? 0.0 : origMaxs[1];
- maxs[2] = origMaxs[2];
-
- TR_TraceHullFilter(origin, originBelow, mins, maxs, MASK_PLAYERSOLID, PlayerFilter);
-
- if (TR_DidHit())
- {
- TR_GetPlaneNormal(null, nrm);
- if (nrm[2] >= MIN_STANDABLE_ZNRM)
- {
- return true;
- }
- }
-
- // +x +y
- mins[0] = origMins[0] < 0.0 ? 0.0 : origMins[0];
- mins[1] = origMins[1] < 0.0 ? 0.0 : origMins[1];
- mins[2] = origMins[2];
-
- maxs = origMaxs;
-
- TR_TraceHullFilter(origin, originBelow, mins, maxs, MASK_PLAYERSOLID, PlayerFilter);
-
- if (TR_DidHit())
- {
- TR_GetPlaneNormal(null, nrm);
- if (nrm[2] >= MIN_STANDABLE_ZNRM)
- {
- return true;
- }
- }
-
- // -x +y
- mins[0] = origMins[0];
- mins[1] = origMins[1] < 0.0 ? 0.0 : origMins[1];
- mins[2] = origMins[2];
-
- maxs[0] = origMaxs[0] > 0.0 ? 0.0 : origMaxs[0];
- maxs[1] = origMaxs[1];
- maxs[2] = origMaxs[2];
-
- TR_TraceHullFilter(origin, originBelow, mins, maxs, MASK_PLAYERSOLID, PlayerFilter);
-
- if (TR_DidHit())
- {
- TR_GetPlaneNormal(null, nrm);
- if (nrm[2] >= MIN_STANDABLE_ZNRM)
- {
- return true;
- }
- }
-
- // +x -y
- mins[0] = origMins[0] < 0.0 ? 0.0 : origMins[0];
- mins[1] = origMins[1];
- mins[2] = origMins[2];
-
- maxs[0] = origMaxs[0];
- maxs[1] = origMaxs[1] > 0.0 ? 0.0 : origMaxs[1];
- maxs[2] = origMaxs[2];
-
- TR_TraceHullFilter(origin, originBelow, mins, maxs, MASK_PLAYERSOLID, PlayerFilter);
-
- if (TR_DidHit())
- {
- TR_GetPlaneNormal(null, nrm);
- if (nrm[2] >= MIN_STANDABLE_ZNRM)
- {
- return true;
- }
- }
-
- return false;
-}