summaryrefslogtreecommitdiff
path: root/sourcemod/scripting/gokz-mode-simplekz.sp
diff options
context:
space:
mode:
authoraura <nw@moneybot.cc>2026-02-17 23:42:09 +0100
committeraura <nw@moneybot.cc>2026-02-17 23:42:09 +0100
commit5e2eb7d67ae933b7566f1944d0bb7744da03d586 (patch)
tree054acff1113270a9cd07933df760f3768c1b6853 /sourcemod/scripting/gokz-mode-simplekz.sp
parent341db13a008dc12bb22ceb50452d93d01476308c (diff)
move source stuff to its own folder
Diffstat (limited to 'sourcemod/scripting/gokz-mode-simplekz.sp')
-rw-r--r--sourcemod/scripting/gokz-mode-simplekz.sp846
1 files changed, 0 insertions, 846 deletions
diff --git a/sourcemod/scripting/gokz-mode-simplekz.sp b/sourcemod/scripting/gokz-mode-simplekz.sp
deleted file mode 100644
index 99d76ac..0000000
--- a/sourcemod/scripting/gokz-mode-simplekz.sp
+++ /dev/null
@@ -1,846 +0,0 @@
-#include <sourcemod>
-
-#include <sdkhooks>
-#include <sdktools>
-#include <dhooks>
-
-#include <movementapi>
-
-#undef REQUIRE_EXTENSIONS
-#undef REQUIRE_PLUGIN
-#include <gokz/core>
-#include <updater>
-
-#include <gokz/kzplayer>
-
-#pragma newdecls required
-#pragma semicolon 1
-
-
-
-public Plugin myinfo =
-{
- name = "GOKZ Mode - SimpleKZ",
- author = "DanZay",
- description = "SimpleKZ mode for GOKZ",
- version = GOKZ_VERSION,
- url = GOKZ_SOURCE_URL
-};
-
-#define UPDATER_URL GOKZ_UPDATER_BASE_URL..."gokz-mode-simplekz.txt"
-
-#define MODE_VERSION 21
-#define PS_MAX_REWARD_TURN_RATE 0.703125 // Degrees per tick (90 degrees per second)
-#define PS_MAX_TURN_RATE_DECREMENT 0.015625 // Degrees per tick (2 degrees per second)
-#define PS_SPEED_MAX 26.54321 // Units
-#define PS_SPEED_INCREMENT 0.35 // Units per tick
-#define PS_SPEED_DECREMENT_MIDAIR 0.2824 // Units per tick (lose PS_SPEED_MAX in 0 offset jump i.e. 94 ticks)
-#define PS_GRACE_TICKS 3 // No. of ticks allowed to fail prestrafe checks when prestrafing - helps players with low fps
-#define DUCK_SPEED_NORMAL 8.0
-#define DUCK_SPEED_MINIMUM 6.0234375 // Equal to if you just ducked/unducked for the first time in a while
-
-float gF_ModeCVarValues[MODECVAR_COUNT] =
-{
- 6.5, // sv_accelerate
- 0.0, // sv_accelerate_use_weapon_speed
- 100.0, // sv_airaccelerate
- 30.0, // sv_air_max_wishspeed
- 1.0, // sv_enablebunnyhopping
- 5.2, // sv_friction
- 800.0, // sv_gravity
- 301.993377, // sv_jump_impulse
- 1.0, // sv_ladder_scale_speed
- 0.0, // sv_ledge_mantle_helper
- 320.0, // sv_maxspeed
- 3500.0, // sv_maxvelocity
- 0.0, // sv_staminajumpcost
- 0.0, // sv_staminalandcost
- 0.0, // sv_staminamax
- 0.0, // sv_staminarecoveryrate
- 0.7, // sv_standable_normal
- 0.0, // sv_timebetweenducks
- 0.7, // sv_walkable_normal
- 10.0, // sv_wateraccelerate
- 0.8, // sv_water_movespeed_multiplier
- 0.0, // sv_water_swim_mode
- 0.0, // sv_weapon_encumbrance_per_item
- 0.0 // sv_weapon_encumbrance_scale
-};
-
-bool gB_GOKZCore;
-ConVar gCV_ModeCVar[MODECVAR_COUNT];
-bool gB_HitTweakedPerf[MAXPLAYERS + 1];
-int gI_Cmdnum[MAXPLAYERS + 1];
-float gF_PSBonusSpeed[MAXPLAYERS + 1];
-float gF_PSVelMod[MAXPLAYERS + 1];
-float gF_PSVelModLanding[MAXPLAYERS + 1];
-bool gB_PSTurningLeft[MAXPLAYERS + 1];
-float gF_PSTurnRate[MAXPLAYERS + 1];
-int gI_PSTicksSinceIncrement[MAXPLAYERS + 1];
-Handle gH_GetPlayerMaxSpeed;
-DynamicDetour gH_CanUnduck;
-int gI_TickCount[MAXPLAYERS + 1];
-DynamicDetour gH_AirAccelerate;
-int gI_OldButtons[MAXPLAYERS + 1];
-int gI_OldFlags[MAXPLAYERS + 1];
-bool gB_OldOnGround[MAXPLAYERS + 1];
-float gF_OldOrigin[MAXPLAYERS + 1][3];
-float gF_OldAngles[MAXPLAYERS + 1][3];
-float gF_OldVelocity[MAXPLAYERS + 1][3];
-int gI_LastJumpButtonCmdnum[MAXPLAYERS + 1];
-int gI_OffsetCGameMovement_player;
-
-
-
-// =====[ PLUGIN EVENTS ]=====
-
-public void OnPluginStart()
-{
- if (FloatAbs(1.0 / GetTickInterval() - 128.0) > EPSILON)
- {
- SetFailState("gokz-mode-simplekz only supports 128 tickrate servers.");
- }
- HookEvents();
- CreateConVars();
-}
-
-public void OnAllPluginsLoaded()
-{
- if (LibraryExists("updater"))
- {
- Updater_AddPlugin(UPDATER_URL);
- }
- if (LibraryExists("gokz-core"))
- {
- gB_GOKZCore = true;
- GOKZ_SetModeLoaded(Mode_SimpleKZ, true, MODE_VERSION);
- }
-
- for (int client = 1; client <= MaxClients; client++)
- {
- if (IsClientInGame(client))
- {
- OnClientPutInServer(client);
- }
- }
-}
-
-public void OnPluginEnd()
-{
- if (gB_GOKZCore)
- {
- GOKZ_SetModeLoaded(Mode_SimpleKZ, false);
- }
-}
-
-public void OnLibraryAdded(const char[] name)
-{
- if (StrEqual(name, "updater"))
- {
- Updater_AddPlugin(UPDATER_URL);
- }
- else if (StrEqual(name, "gokz-core"))
- {
- gB_GOKZCore = true;
- GOKZ_SetModeLoaded(Mode_SimpleKZ, true, MODE_VERSION);
- }
-}
-
-public void OnLibraryRemoved(const char[] name)
-{
- gB_GOKZCore = gB_GOKZCore && !StrEqual(name, "gokz-core");
-}
-
-
-
-// =====[ CLIENT EVENTS ]=====
-
-public void OnClientPutInServer(int client)
-{
- ResetClient(client);
- if (IsValidClient(client))
- {
- HookClientEvents(client);
- }
- if (IsUsingMode(client))
- {
- ReplicateConVars(client);
- }
-}
-
-public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3], float angles[3], int &weapon, int &subtype, int &cmdnum, int &tickcount, int &seed, int mouse[2])
-{
- if (!IsPlayerAlive(client) || !IsUsingMode(client))
- {
- return Plugin_Continue;
- }
-
- KZPlayer player = KZPlayer(client);
- RemoveCrouchJumpBind(player, buttons);
- ReduceDuckSlowdown(player);
- CalcPrestrafeVelMod(player, angles);
- FixWaterBoost(player, buttons);
- FixDisplacementStuck(player);
-
- gB_HitTweakedPerf[player.ID] = false;
- gI_Cmdnum[player.ID] = cmdnum;
- gI_OldButtons[player.ID] = buttons;
- gI_OldFlags[player.ID] = GetEntityFlags(player.ID);
- gB_OldOnGround[player.ID] = player.OnGround;
- gI_TickCount[player.ID] = tickcount;
- player.GetOrigin(gF_OldOrigin[player.ID]);
- player.GetEyeAngles(gF_OldAngles[player.ID]);
- player.GetVelocity(gF_OldVelocity[player.ID]);
-
- return Plugin_Continue;
-}
-
-public MRESReturn DHooks_OnGetPlayerMaxSpeed(int client, Handle hReturn)
-{
- if (!IsUsingMode(client))
- {
- return MRES_Ignored;
- }
- DHookSetReturn(hReturn, SPEED_NORMAL * gF_PSVelMod[client]);
- return MRES_Supercede;
-}
-
-public MRESReturn DHooks_OnAirAccelerate_Pre(Address pThis, DHookParam hParams)
-{
- int client = GOKZGetClientFromGameMovementAddress(pThis, gI_OffsetCGameMovement_player);
- if (!IsPlayerAlive(client) || !IsUsingMode(client))
- {
- return MRES_Ignored;
- }
-
- // NOTE: Prestrafing changes GetPlayerMaxSpeed, which changes
- // air acceleration, so remove gF_PreVelMod[client] from wishspeed/maxspeed.
- // This also applies to when the player is ducked: their wishspeed is
- // 85 and with prestrafing can be ~93.
- float wishspeed = DHookGetParam(hParams, 2);
- if (gF_PSVelMod[client] > 1.0)
- {
- DHookSetParam(hParams, 2, wishspeed / gF_PSVelMod[client]);
- return MRES_ChangedHandled;
- }
-
- return MRES_Ignored;
-}
-
-public MRESReturn DHooks_OnCanUnduck_Pre(Address pThis, DHookReturn hReturn)
-{
- int client = GOKZGetClientFromGameMovementAddress(pThis, gI_OffsetCGameMovement_player);
- if (!IsPlayerAlive(client) || !IsUsingMode(client))
- {
- return MRES_Ignored;
- }
- // Just landed fully ducked, you can't unduck.
- if (Movement_GetLandingTick(client) == (gI_TickCount[client] - 1) && GetEntPropFloat(client, Prop_Send, "m_flDuckAmount") >= 1.0 && GetEntProp(client, Prop_Send, "m_bDucked"))
- {
- hReturn.Value = false;
- return MRES_Supercede;
- }
- return MRES_Ignored;
-}
-
-public void OnPlayerRunCmdPost(int client, int buttons, int impulse, const float vel[3], const float angles[3], int weapon, int subtype, int cmdnum, int tickcount, int seed, const int mouse[2])
-{
- if (!IsValidClient(client) || !IsPlayerAlive(client) || !IsUsingMode(client))
- {
- return;
- }
-
- if (buttons & IN_JUMP)
- {
- gI_LastJumpButtonCmdnum[client] = cmdnum;
- }
-}
-
-public void SDKHook_OnClientPreThink_Post(int client)
-{
- if (!IsPlayerAlive(client) || !IsUsingMode(client))
- {
- return;
- }
-
- // Don't tweak convars if GOKZ isn't running
- if (gB_GOKZCore)
- {
- TweakConVars();
- }
-}
-
-public void Movement_OnStartTouchGround(int client)
-{
- if (!IsUsingMode(client))
- {
- return;
- }
-
- KZPlayer player = KZPlayer(client);
- gF_PSVelModLanding[player.ID] = gF_PSVelMod[player.ID];
-}
-
-public Action Movement_OnJumpPre(int client, float origin[3], float velocity[3])
-{
- if (!IsPlayerAlive(client) || !IsUsingMode(client))
- {
- return Plugin_Continue;
- }
-
- KZPlayer player = KZPlayer(client);
- return TweakJump(player, origin, velocity);
-}
-
-public Action Movement_OnCategorizePositionPost(int client, float origin[3], float velocity[3])
-{
- if (!IsPlayerAlive(client) || !IsUsingMode(client))
- {
- return Plugin_Continue;
- }
- return SlopeFix(client, origin, velocity);
-}
-
-public void Movement_OnChangeMovetype(int client, MoveType oldMovetype, MoveType newMovetype)
-{
- if (!IsUsingMode(client))
- {
- return;
- }
-
- KZPlayer player = KZPlayer(client);
- if (gB_GOKZCore && newMovetype == MOVETYPE_WALK)
- {
- player.GOKZHitPerf = false;
- player.GOKZTakeoffSpeed = player.TakeoffSpeed;
- }
-}
-
-public void GOKZ_OnOptionChanged(int client, const char[] option, any newValue)
-{
- if (StrEqual(option, gC_CoreOptionNames[Option_Mode]) && newValue == Mode_SimpleKZ)
- {
- ReplicateConVars(client);
- }
-}
-
-public void GOKZ_OnCountedTeleport_Post(int client)
-{
- ResetClient(client);
-}
-
-
-
-// =====[ GENERAL ]=====
-
-bool IsUsingMode(int client)
-{
- // If GOKZ core isn't loaded, then apply mode at all times
- return !gB_GOKZCore || GOKZ_GetCoreOption(client, Option_Mode) == Mode_SimpleKZ;
-}
-
-void ResetClient(int client)
-{
- KZPlayer player = KZPlayer(client);
- ResetVelMod(player);
-}
-
-void HookEvents()
-{
- GameData gameData = LoadGameConfigFile("movementapi.games");
- if (gameData == INVALID_HANDLE)
- {
- SetFailState("Failed to find movementapi.games config");
- }
-
- int offset = gameData.GetOffset("GetPlayerMaxSpeed");
- if (offset == -1)
- {
- SetFailState("Failed to get GetPlayerMaxSpeed offset");
- }
- gH_GetPlayerMaxSpeed = DHookCreate(offset, HookType_Entity, ReturnType_Float, ThisPointer_CBaseEntity, DHooks_OnGetPlayerMaxSpeed);
-
- gH_AirAccelerate = DynamicDetour.FromConf(gameData, "CGameMovement::AirAccelerate");
- if (gH_AirAccelerate == INVALID_HANDLE)
- {
- SetFailState("Failed to find CGameMovement::AirAccelerate function signature");
- }
-
- if (!gH_AirAccelerate.Enable(Hook_Pre, DHooks_OnAirAccelerate_Pre))
- {
- SetFailState("Failed to enable detour on CGameMovement::AirAccelerate");
- }
-
- char buffer[16];
- if (!gameData.GetKeyValue("CGameMovement::player", buffer, sizeof(buffer)))
- {
- SetFailState("Failed to get CGameMovement::player offset.");
- }
- gI_OffsetCGameMovement_player = StringToInt(buffer);
-
- gameData = LoadGameConfigFile("gokz-core.games");
- gH_CanUnduck = DynamicDetour.FromConf(gameData, "CCSGameMovement::CanUnduck");
- if (gH_CanUnduck == INVALID_HANDLE)
- {
- SetFailState("Failed to find CCSGameMovement::CanUnduck function signature");
- }
-
- if (!gH_CanUnduck.Enable(Hook_Pre, DHooks_OnCanUnduck_Pre))
- {
- SetFailState("Failed to enable detour on CCSGameMovement::CanUnduck");
- }
- delete gameData;
-}
-
-// =====[ CONVARS ]=====
-
-void CreateConVars()
-{
- for (int i = 0; i < MODECVAR_COUNT; i++)
- {
- gCV_ModeCVar[i] = FindConVar(gC_ModeCVars[i]);
- }
-}
-
-void TweakConVars()
-{
- for (int i = 0; i < MODECVAR_COUNT; i++)
- {
- gCV_ModeCVar[i].FloatValue = gF_ModeCVarValues[i];
- }
-}
-
-void ReplicateConVars(int client)
-{
- /*
- Replicate convars only when player changes mode in GOKZ
- so that lagg isn't caused by other players using other
- modes, and also as an optimisation.
- */
-
- if (IsFakeClient(client))
- {
- return;
- }
-
- for (int i = 0; i < MODECVAR_COUNT; i++)
- {
- gCV_ModeCVar[i].ReplicateToClient(client, FloatToStringEx(gF_ModeCVarValues[i]));
- }
-}
-
-
-
-// =====[ VELOCITY MODIFIER ]=====
-
-void HookClientEvents(int client)
-{
- DHookEntity(gH_GetPlayerMaxSpeed, true, client);
- SDKHook(client, SDKHook_PreThinkPost, SDKHook_OnClientPreThink_Post);
-}
-
-void ResetVelMod(KZPlayer player)
-{
- gF_PSBonusSpeed[player.ID] = 0.0;
- gF_PSVelMod[player.ID] = 1.0;
- gF_PSTurnRate[player.ID] = 0.0;
-}
-
-void CalcPrestrafeVelMod(KZPlayer player, const float angles[3])
-{
- gI_PSTicksSinceIncrement[player.ID]++;
-
- // Short circuit if speed is 0 (also avoids divide by 0 errors)
- if (player.Speed < EPSILON)
- {
- ResetVelMod(player);
- return;
- }
-
- // Current speed without bonus
- float baseSpeed = FloatMin(SPEED_NORMAL, player.Speed / gF_PSVelMod[player.ID]);
-
- float newBonusSpeed = gF_PSBonusSpeed[player.ID];
-
- // If player is in mid air, decrement their velocity modifier
- if (!player.OnGround)
- {
- newBonusSpeed -= PS_SPEED_DECREMENT_MIDAIR;
- }
- // If player is turning at the required speed, and has the correct button inputs, reward it
- else if (player.Turning && ValidPrestrafeButtons(player))
- {
- // If player changes their prestrafe direction, reset it
- if (player.TurningLeft && !gB_PSTurningLeft[player.ID]
- || player.TurningRight && gB_PSTurningLeft[player.ID])
- {
- ResetVelMod(player);
- newBonusSpeed = 0.0;
- }
-
- // Keep track of the direction of the turn
- gB_PSTurningLeft[player.ID] = player.TurningLeft;
-
- // Step one of calculating new turn rate
- float newTurningRate = FloatAbs(CalcDeltaAngle(gF_OldAngles[player.ID][1], angles[1]));
-
- // If no turning for just a few ticks, then forgive and calculate reward based on that no. of ticks
- if (gI_PSTicksSinceIncrement[player.ID] <= PS_GRACE_TICKS)
- {
- // This turn occurred over multiple ticks, so scale appropriately
- // Also cap turn rate at maximum reward turn rate
- newTurningRate = FloatMin(PS_MAX_REWARD_TURN_RATE,
- newTurningRate / gI_PSTicksSinceIncrement[player.ID]);
-
- // Limit how fast turn rate can decrease (also scaled appropriately)
- gF_PSTurnRate[player.ID] = FloatMax(newTurningRate,
- gF_PSTurnRate[player.ID] - PS_MAX_TURN_RATE_DECREMENT * gI_PSTicksSinceIncrement[player.ID]);
-
- newBonusSpeed += CalcPreRewardSpeed(gF_PSTurnRate[player.ID], baseSpeed) * gI_PSTicksSinceIncrement[player.ID];
- }
- else
- {
- // Cap turn rate at maximum reward turn rate
- newTurningRate = FloatMin(PS_MAX_REWARD_TURN_RATE, newTurningRate);
-
- // Limit how fast turn rate can decrease
- gF_PSTurnRate[player.ID] = FloatMax(newTurningRate,
- gF_PSTurnRate[player.ID] - PS_MAX_TURN_RATE_DECREMENT);
-
- // This is normal turning behaviour
- newBonusSpeed += CalcPreRewardSpeed(gF_PSTurnRate[player.ID], baseSpeed);
- }
-
- gI_PSTicksSinceIncrement[player.ID] = 0;
- }
- else if (gI_PSTicksSinceIncrement[player.ID] > PS_GRACE_TICKS)
- {
- // They definitely aren't turning, but limit how fast turn rate can decrease
- gF_PSTurnRate[player.ID] = FloatMax(0.0,
- gF_PSTurnRate[player.ID] - PS_MAX_TURN_RATE_DECREMENT);
- }
-
- if (newBonusSpeed < 0.0)
- {
- // Keep velocity modifier positive
- newBonusSpeed = 0.0;
- }
- else
- {
- // Scale the bonus speed based on current base speed and turn rate
- float baseSpeedScaleFactor = baseSpeed / SPEED_NORMAL; // Max 1.0
- float turnRateScaleFactor = FloatMin(1.0, gF_PSTurnRate[player.ID] / PS_MAX_REWARD_TURN_RATE);
- float scaledMaxBonusSpeed = PS_SPEED_MAX * baseSpeedScaleFactor * turnRateScaleFactor;
- newBonusSpeed = FloatMin(newBonusSpeed, scaledMaxBonusSpeed);
- }
-
- gF_PSBonusSpeed[player.ID] = newBonusSpeed;
- gF_PSVelMod[player.ID] = 1.0 + (newBonusSpeed / baseSpeed);
-}
-
-bool ValidPrestrafeButtons(KZPlayer player)
-{
- bool forwardOrBack = player.Buttons & (IN_FORWARD | IN_BACK) && !(player.Buttons & IN_FORWARD && player.Buttons & IN_BACK);
- bool leftOrRight = player.Buttons & (IN_MOVELEFT | IN_MOVERIGHT) && !(player.Buttons & IN_MOVELEFT && player.Buttons & IN_MOVERIGHT);
- return forwardOrBack || leftOrRight;
-}
-
-float CalcPreRewardSpeed(float yawDiff, float baseSpeed)
-{
- // Formula
- float reward;
- if (yawDiff >= PS_MAX_REWARD_TURN_RATE)
- {
- reward = PS_SPEED_INCREMENT;
- }
- else
- {
- reward = PS_SPEED_INCREMENT * (yawDiff / PS_MAX_REWARD_TURN_RATE);
- }
-
- return reward * baseSpeed / SPEED_NORMAL;
-}
-
-
-
-
-// =====[ JUMPING ]=====
-
-Action TweakJump(KZPlayer player, float origin[3], float velocity[3])
-{
- // TakeoffCmdnum and TakeoffSpeed is not defined here because the player technically hasn't taken off yet.
- int cmdsSinceLanding = gI_Cmdnum[player.ID] - player.LandingCmdNum;
- gB_HitTweakedPerf[player.ID] = cmdsSinceLanding <= 1
- || cmdsSinceLanding <= 3 && gI_Cmdnum[player.ID] - gI_LastJumpButtonCmdnum[player.ID] <= 3;
-
- if (gB_HitTweakedPerf[player.ID])
- {
- if (cmdsSinceLanding <= 1)
- {
- NerfRealPerf(player, origin);
- }
-
- ApplyTweakedTakeoffSpeed(player, velocity);
-
- if (cmdsSinceLanding > 1 || player.TakeoffSpeed > SPEED_NORMAL)
- {
- // Restore prestrafe lost due to briefly being on the ground
- gF_PSVelMod[player.ID] = gF_PSVelModLanding[player.ID];
- }
- return Plugin_Changed;
- }
- return Plugin_Continue;
-}
-
-public Action Movement_OnJumpPost(int client)
-{
- if (!IsUsingMode(client))
- {
- return Plugin_Continue;
- }
- KZPlayer player = KZPlayer(client);
- player.GOKZHitPerf = gB_HitTweakedPerf[player.ID];
- player.GOKZTakeoffSpeed = player.TakeoffSpeed;
- return Plugin_Continue;
-}
-
-public void Movement_OnStopTouchGround(int client)
-{
- if (!IsUsingMode(client))
- {
- return;
- }
- KZPlayer player = KZPlayer(client);
- player.GOKZHitPerf = gB_HitTweakedPerf[player.ID];
- player.GOKZTakeoffSpeed = player.TakeoffSpeed;
-}
-
-void NerfRealPerf(KZPlayer player, float origin[3])
-{
- // Not worth worrying about if player is already falling
- // player.VerticalVelocity is not updated yet! Use processing velocity.
- float velocity[3];
- Movement_GetProcessingVelocity(player.ID, velocity);
- if (velocity[2] < EPSILON)
- {
- return;
- }
-
- // Work out where the ground was when they bunnyhopped
- float startPosition[3], endPosition[3], mins[3], maxs[3], groundOrigin[3];
-
- startPosition = origin;
-
- endPosition = startPosition;
- endPosition[2] = endPosition[2] - 2.0; // Should be less than 2.0 units away
-
- GetEntPropVector(player.ID, Prop_Send, "m_vecMins", mins);
- GetEntPropVector(player.ID, Prop_Send, "m_vecMaxs", maxs);
-
- Handle trace = TR_TraceHullFilterEx(
- startPosition,
- endPosition,
- mins,
- maxs,
- MASK_PLAYERSOLID,
- TraceEntityFilterPlayers,
- player.ID);
-
- // This is expected to always hit, previously this can fail upon jumpbugs.
- if (TR_DidHit(trace))
- {
- TR_GetEndPosition(groundOrigin, trace);
- origin[2] = groundOrigin[2];
- }
-
- delete trace;
-}
-
-void ApplyTweakedTakeoffSpeed(KZPlayer player, float velocity[3])
-{
- // Note that resulting velocity has same direction as landing velocity, not current velocity
- // because current velocity direction can change drastically in just one tick (eg. walls)
- // and it doesnt make sense for the new velocity to push you in that direction.
-
- float newVelocity[3], baseVelocity[3];
- player.GetLandingVelocity(newVelocity);
- player.GetBaseVelocity(baseVelocity);
- SetVectorHorizontalLength(newVelocity, CalcTweakedTakeoffSpeed(player));
- AddVectors(newVelocity, baseVelocity, newVelocity); // For backwards compatibility
- velocity[0] = newVelocity[0];
- velocity[1] = newVelocity[1];
-}
-
-// Takeoff speed assuming player has met the conditions to need tweaking
-float CalcTweakedTakeoffSpeed(KZPlayer player)
-{
- // Formula
- if (player.LandingSpeed > SPEED_NORMAL)
- {
- return FloatMin(player.LandingSpeed, (0.2 * player.LandingSpeed + 200) * gF_PSVelModLanding[player.ID]);
- }
- return player.LandingSpeed;
-}
-
-
-
-// =====[ SLOPEFIX ]=====
-
-// ORIGINAL AUTHORS : Mev & Blacky
-// URL : https://forums.alliedmods.net/showthread.php?p=2322788
-// NOTE : Modified by DanZay for this plugin
-
-Action SlopeFix(int client, float origin[3], float velocity[3])
-{
- KZPlayer player = KZPlayer(client);
- // Check if player landed on the ground
- if (Movement_GetOnGround(client) && !gB_OldOnGround[client])
- {
- float vMins[] = {-16.0, -16.0, 0.0};
- // Always use ducked hull as the real hull size isn't updated yet.
- // Might cause slight issues in extremely rare scenarios.
- float vMaxs[] = {16.0, 16.0, 54.0};
-
- float vEndPos[3];
- vEndPos[0] = origin[0];
- vEndPos[1] = origin[1];
- vEndPos[2] = origin[2] - gF_ModeCVarValues[ModeCVar_MaxVelocity];
-
- // Set up and do tracehull to find out if the player landed on a slope
- TR_TraceHullFilter(origin, vEndPos, vMins, vMaxs, MASK_PLAYERSOLID_BRUSHONLY, TraceRayDontHitSelf, client);
-
- if (TR_DidHit())
- {
- // Gets the normal vector of the surface under the player
- float vPlane[3], vLast[3];
- player.GetLandingVelocity(vLast);
- TR_GetPlaneNormal(null, vPlane);
-
- // Make sure it's not flat ground and not a surf ramp (1.0 = flat ground, < 0.7 = surf ramp)
- if (0.7 <= vPlane[2] < 1.0)
- {
- /*
- Copy the ClipVelocity function from sdk2013
- (https://mxr.alliedmods.net/hl2sdk-sdk2013/source/game/shared/gamemovement.cpp#3145)
- With some minor changes to make it actually work
- */
-
- float fBackOff = GetVectorDotProduct(vLast, vPlane);
-
- float change, vVel[3];
- for (int i; i < 2; i++)
- {
- change = vPlane[i] * fBackOff;
- vVel[i] = vLast[i] - change;
- }
-
- float fAdjust = GetVectorDotProduct(vVel, vPlane);
- if (fAdjust < 0.0)
- {
- for (int i; i < 2; i++)
- {
- vVel[i] -= (vPlane[i] * fAdjust);
- }
- }
-
- vVel[2] = 0.0;
- vLast[2] = 0.0;
-
- // Make sure the player is going down a ramp by checking if they actually will gain speed from the boost
- if (GetVectorLength(vVel) > GetVectorLength(vLast))
- {
- CopyVector(vVel, velocity);
- player.SetLandingVelocity(velocity);
- return Plugin_Changed;
- }
- }
- }
- }
- return Plugin_Continue;
-}
-
-public bool TraceRayDontHitSelf(int entity, int mask, any data)
-{
- return entity != data && !(0 < entity <= MaxClients);
-}
-
-
-
-// =====[ OTHER ]=====
-
-void FixWaterBoost(KZPlayer player, int buttons)
-{
- if (GetEntProp(player.ID, Prop_Send, "m_nWaterLevel") >= 2) // WL_Waist = 2
- {
- // If duck is being pressed and we're not already ducking or on ground
- if (GetEntityFlags(player.ID) & (FL_DUCKING | FL_ONGROUND) == 0
- && buttons & IN_DUCK && ~gI_OldButtons[player.ID] & IN_DUCK)
- {
- float newOrigin[3];
- Movement_GetOrigin(player.ID, newOrigin);
- newOrigin[2] += 9.0;
-
- TR_TraceHullFilter(newOrigin, newOrigin, view_as<float>( { -16.0, -16.0, 0.0 } ), view_as<float>( { 16.0, 16.0, 54.0 } ), MASK_PLAYERSOLID, TraceEntityFilterPlayers);
- if (!TR_DidHit())
- {
- TeleportEntity(player.ID, newOrigin, NULL_VECTOR, NULL_VECTOR);
- }
- }
- }
-}
-
-void FixDisplacementStuck(KZPlayer player)
-{
- int flags = GetEntityFlags(player.ID);
- bool unducked = ~flags & FL_DUCKING && gI_OldFlags[player.ID] & FL_DUCKING;
-
- float standingMins[] = {-16.0, -16.0, 0.0};
- float standingMaxs[] = {16.0, 16.0, 72.0};
-
- if (unducked)
- {
- // check if we're stuck after unducking and if we're stuck then force duck
- float origin[3];
- Movement_GetOrigin(player.ID, origin);
- TR_TraceHullFilter(origin, origin, standingMins, standingMaxs, MASK_PLAYERSOLID, TraceEntityFilterPlayers);
-
- if (TR_DidHit())
- {
- player.SetVelocity(gF_OldVelocity[player.ID]);
- SetEntProp(player.ID, Prop_Send, "m_bDucking", true);
- }
- }
-}
-
-void RemoveCrouchJumpBind(KZPlayer player, int &buttons)
-{
- if (player.OnGround && buttons & IN_JUMP && !(gI_OldButtons[player.ID] & IN_JUMP) && !(gI_OldButtons[player.ID] & IN_DUCK))
- {
- buttons &= ~IN_DUCK;
- }
-}
-
-void ReduceDuckSlowdown(KZPlayer player)
-{
- /*
- Duck speed is reduced by the game upon ducking or unducking.
- The goal here is to accept that duck speed is reduced, but
- stop it from being reduced further when spamming duck.
-
- This is done by enforcing a minimum duck speed equivalent to
- the value as if the player only ducked once. When not in not
- in the middle of ducking, duck speed is reset to its normal
- value in effort to reduce the number of times the minimum
- duck speed is enforced. This should reduce noticeable lagg.
- */
-
- if (!GetEntProp(player.ID, Prop_Send, "m_bDucking")
- && player.DuckSpeed < DUCK_SPEED_NORMAL - EPSILON)
- {
- player.DuckSpeed = DUCK_SPEED_NORMAL;
- }
- else if (player.DuckSpeed < DUCK_SPEED_MINIMUM - EPSILON)
- {
- player.DuckSpeed = DUCK_SPEED_MINIMUM;
- }
-}