From 309aa7a189c6a3c695985c91f633a462a327c337 Mon Sep 17 00:00:00 2001 From: rtldg Date: Wed, 21 Jun 2023 01:41:07 +0000 Subject: [PATCH] get the shavit_misc_prespeed 1&&>=3 working again with the on-ground timer --- .../scripting/include/shavit/core.inc | 15 ++- addons/sourcemod/scripting/shavit-core.sp | 116 ++++++++++++------ addons/sourcemod/scripting/shavit-misc.sp | 65 +++++++++- addons/sourcemod/scripting/shavit-zones.sp | 5 +- 4 files changed, 158 insertions(+), 43 deletions(-) diff --git a/addons/sourcemod/scripting/include/shavit/core.inc b/addons/sourcemod/scripting/include/shavit/core.inc index 91046cf3..e880e9d6 100644 --- a/addons/sourcemod/scripting/include/shavit/core.inc +++ b/addons/sourcemod/scripting/include/shavit/core.inc @@ -551,6 +551,15 @@ stock void TrimDisplayString(const char[] str, char[] outstr, int outstrlen, int Format(outstr, outstrlen, "%s...", outstr); } +// TODO: surfacefriction +stock float MaxPrestrafe(float runspeed, float accelerate, float friction, float tickinterval) +{ + return runspeed * SquareRoot( + (accelerate / friction) * + ((2.0 - accelerate * tickinterval) / (2.0 - friction * tickinterval)) + ); +} + /** * Called before shavit-core processes the client's usercmd. * Before this is called, safety checks (fake/dead clients) happen. @@ -599,9 +608,10 @@ forward void Shavit_OnTimeIncrementPost(int client, float time); * * @param client Client index. * @param track Timer track. + * @param skipGroundTimer Whether shavit-core can skip the on-ground-for-half-a-second check. shavit-misc uses this for some prespeed settings... * @return Plugin_Continue to do nothing or anything else to not start the timer. */ -forward Action Shavit_OnStartPre(int client, int track); +forward Action Shavit_OnStartPre(int client, int track, bool& skipGroundTimer); /** * Called when a player's timer starts. @@ -862,9 +872,10 @@ native Database Shavit_GetDatabase(int& outdriver=0); * * @param client Client index. * @param track Timer track. + * @param skipGroundCheck Whether to skip checking if the player is on the ground. This is used in shavit-zones for when teleporting/!restarting players to a floating zone... * @noreturn */ -native void Shavit_StartTimer(int client, int track); +native void Shavit_StartTimer(int client, int track, bool skipGroundCheck=false); /** * Restarts the timer for a player. diff --git a/addons/sourcemod/scripting/shavit-core.sp b/addons/sourcemod/scripting/shavit-core.sp index 5cc869bd..48ebcc1a 100644 --- a/addons/sourcemod/scripting/shavit-core.sp +++ b/addons/sourcemod/scripting/shavit-core.sp @@ -256,7 +256,7 @@ public void OnPluginStart() { // forwards gH_Forwards_Start = CreateGlobalForward("Shavit_OnStart", ET_Ignore, Param_Cell, Param_Cell); - gH_Forwards_StartPre = CreateGlobalForward("Shavit_OnStartPre", ET_Event, Param_Cell, Param_Cell); + gH_Forwards_StartPre = CreateGlobalForward("Shavit_OnStartPre", ET_Event, Param_Cell, Param_Cell, Param_CellByRef); gH_Forwards_Stop = CreateGlobalForward("Shavit_OnStop", ET_Event, Param_Cell, Param_Cell); gH_Forwards_StopPre = CreateGlobalForward("Shavit_OnStopPre", ET_Event, Param_Cell, Param_Cell); gH_Forwards_FinishPre = CreateGlobalForward("Shavit_OnFinishPre", ET_Hook, Param_Cell, Param_Array); @@ -1777,7 +1777,7 @@ public int Native_IsKZMap(Handle handler, int numParams) public int Native_StartTimer(Handle handler, int numParams) { - StartTimer(GetNativeCell(1), GetNativeCell(2)); + StartTimer(GetNativeCell(1), GetNativeCell(2), numParams >= 3 ? GetNativeCell(3) : false); return 0; } @@ -2440,58 +2440,88 @@ TimerStatus GetTimerStatus(int client) return Timer_Running; } -// TODO: surfacefriction -float MaxPrestrafe(float runspeed, float accelerate, float friction, float tickinterval) +float StyleMaxPrestrafe(int style) { - return runspeed * SquareRoot( - (accelerate / friction) * - ((2.0 - accelerate * tickinterval) / (2.0 - friction * tickinterval)) - ); -} - -float ClientMaxPrestrafe(int client) -{ - float runspeed = GetStyleSettingFloat(gA_Timers[client].bsStyle, "runspeed"); + float runspeed = GetStyleSettingFloat(style, "runspeed"); return MaxPrestrafe(runspeed, sv_accelerate.FloatValue, sv_friction.FloatValue, GetTickInterval()); } -void StartTimer(int client, int track) +bool CanStartTimer(int client, int track, bool skipGroundCheck) { if(!IsValidClient(client, true) || GetClientTeam(client) < 2 || IsFakeClient(client) || !gB_CookiesRetrieved[client]) { - return; + return false; } + int style = gA_Timers[client].bsStyle; + + int prespeed = GetStyleSettingInt(style, "prespeed"); + if (prespeed == 1) + return true; + float fSpeed[3]; GetEntPropVector(client, Prop_Data, "m_vecVelocity", fSpeed); + + int nozaxisspeed = GetStyleSettingInt(style, "nozaxisspeed"); + if (nozaxisspeed < 0) nozaxisspeed = gCV_NoZAxisSpeed.IntValue; + + if (nozaxisspeed && fSpeed[2] != 0.0) + return false; + + if (prespeed == 2) + return true; + + bool skipGroundTimer = false; + Action result = Plugin_Continue; + Call_StartForward(gH_Forwards_StartPre); + Call_PushCell(client); + Call_PushCell(track); + Call_PushCellRef(skipGroundTimer); + Call_Finish(result); + + if (result != Plugin_Continue) + return false; + + // re-grab velocity in case shavit-misc capped it + GetEntPropVector(client, Prop_Data, "m_vecVelocity", fSpeed); float curVel = SquareRoot(Pow(fSpeed[0], 2.0) + Pow(fSpeed[1], 2.0)); - int nozaxisspeed = GetStyleSettingInt(gA_Timers[client].bsStyle, "nozaxisspeed"); + // This helps with zones that are floating in the air (commonly for bonuses). + // Since you teleport into the air with 0-velocity... + if (curVel <= 50.0) + return true; - if (nozaxisspeed < 0) + float prestrafe = StyleMaxPrestrafe(style); + if (curVel > prestrafe) + return false; + + if (skipGroundCheck || GetStyleSettingBool(style, "startinair")) + return true; + +#if 0 + MoveType mtMoveType = GetEntityMoveType(client); + bool bInWater = (GetEntProp(client, Prop_Send, "m_nWaterLevel") >= 2); + int iGroundEntity = GetEntPropEnt(client, Prop_Send, "m_hGroundEntity"); + // gA_Timers[client].bOnGround isn't updated/correct when zones->touchpost->starttimer happens... frustrating... + bool bOnGround = (!bInWater && mtMoveType == MOVETYPE_WALK && iGroundEntity != -1); + + if (!bOnGround) return false; +#endif + + if (skipGroundTimer) return true; + + int halfSecOfTicks = RoundFloat(0.5 / GetTickInterval()); + int onGroundTicks = gI_LastTickcount[client] - gI_FirstTouchedGround[client]; + + return onGroundTicks >= halfSecOfTicks; +} + +void StartTimer(int client, int track, bool skipGroundCheck) +{ + if (CanStartTimer(client, track, skipGroundCheck)) { - nozaxisspeed = gCV_NoZAxisSpeed.BoolValue; - } - - if (!nozaxisspeed || - GetStyleSettingInt(gA_Timers[client].bsStyle, "prespeed") == 1 || - (fSpeed[2] == 0.0 && (GetStyleSettingInt(gA_Timers[client].bsStyle, "prespeed") == 2 || curVel <= 50.0 || - ((curVel <= ClientMaxPrestrafe(client) && gA_Timers[client].bOnGround && - (gI_LastTickcount[client]-gI_FirstTouchedGround[client] > RoundFloat(0.5/GetTickInterval()))))))) // beautiful - { - Action result = Plugin_Continue; - Call_StartForward(gH_Forwards_StartPre); - Call_PushCell(client); - Call_PushCell(track); - Call_Finish(result); - - if(result == Plugin_Continue) + if (true) // fucking shit { - Call_StartForward(gH_Forwards_Start); - Call_PushCell(client); - Call_PushCell(track); - Call_Finish(result); - if (gA_Timers[client].bClientPaused) { //SetEntityMoveType(client, MOVETYPE_WALK); @@ -2523,6 +2553,11 @@ void StartTimer(int client, int track) gA_Timers[client].fZoneOffset[Zone_End] = 0.0; gA_Timers[client].fDistanceOffset[Zone_Start] = 0.0; gA_Timers[client].fDistanceOffset[Zone_End] = 0.0; + + float fSpeed[3]; + GetEntPropVector(client, Prop_Data, "m_vecVelocity", fSpeed); + float curVel = SquareRoot(Pow(fSpeed[0], 2.0) + Pow(fSpeed[1], 2.0)); + gA_Timers[client].fAvgVelocity = curVel; gA_Timers[client].fMaxVelocity = curVel; @@ -2533,6 +2568,11 @@ void StartTimer(int client, int track) UpdateLaggedMovement(client, true); SetEntityGravity(client, GetStyleSettingFloat(gA_Timers[client].bsStyle, "gravity")); + + Call_StartForward(gH_Forwards_Start); + Call_PushCell(client); + Call_PushCell(track); + Call_Finish(); } #if 0 else if(result == Plugin_Handled || result == Plugin_Stop) diff --git a/addons/sourcemod/scripting/shavit-misc.sp b/addons/sourcemod/scripting/shavit-misc.sp index beb05f2d..638ba8c1 100644 --- a/addons/sourcemod/scripting/shavit-misc.sp +++ b/addons/sourcemod/scripting/shavit-misc.sp @@ -117,6 +117,8 @@ ConVar gCV_PauseMovement = null; Convar gCV_RestartWithFullHP = null; // external cvars +ConVar sv_accelerate = null; +ConVar sv_friction = null; ConVar sv_cheats = null; ConVar sv_disable_immunity_alpha = null; ConVar mp_humanteam = null; @@ -312,6 +314,9 @@ public void OnPluginStart() sv_disable_radar = FindConVar("sv_disable_radar"); tf_dropped_weapon_lifetime = FindConVar("tf_dropped_weapon_lifetime"); + sv_accelerate = FindConVar("sv_accelerate"); + sv_friction = FindConVar("sv_friction"); + // crons CreateTimer(10.0, Timer_Cron, 0, TIMER_REPEAT); @@ -2253,13 +2258,69 @@ public Action Command_Specs(int client, int args) return Plugin_Handled; } -public Action Shavit_OnStartPre(int client) +float StyleMaxPrestrafe(int style) { - if (Shavit_GetStyleSettingInt(gI_Style[client], "prespeed") == 0 && GetEntityMoveType(client) == MOVETYPE_NOCLIP) + float runspeed = Shavit_GetStyleSettingFloat(style, "runspeed"); + return MaxPrestrafe(runspeed, sv_accelerate.FloatValue, sv_friction.FloatValue, GetTickInterval()); +} + +public Action Shavit_OnStartPre(int client, int track, bool& skipGroundTimer) +{ + if (GetEntityMoveType(client) == MOVETYPE_NOCLIP) { return Plugin_Stop; } + if (Shavit_GetStyleSettingInt(gI_Style[client], "prespeed") == 0) + { + int prespeed_type = Shavit_GetStyleSettingInt(gI_Style[client], "prespeed_type"); + + if (prespeed_type == -1) + { + prespeed_type = gCV_PreSpeed.IntValue; + } + + if (prespeed_type == 1 || prespeed_type >= 3) + { + float fSpeed[3]; + GetEntPropVector(client, Prop_Data, "m_vecAbsVelocity", fSpeed); + + float fLimit = (Shavit_GetStyleSettingFloat(gI_Style[client], "runspeed") + gCV_PrestrafeLimit.FloatValue); + float maxPrestrafe = StyleMaxPrestrafe(gI_Style[client]); + if (fLimit > maxPrestrafe) fLimit = maxPrestrafe; + + // if trying to jump, add a very low limit to stop prespeeding in an elegant way + // otherwise, make sure nothing weird is happening (such as sliding at ridiculous speeds, at zone enter) + if (prespeed_type < 4 && fSpeed[2] > 0.0) + { + fLimit /= 3.0; + } + + float fSpeedXY = (SquareRoot(Pow(fSpeed[0], 2.0) + Pow(fSpeed[1], 2.0))); + float fScale = (fLimit / fSpeedXY); + + if(fScale < 1.0) + { + if (prespeed_type == 5) + { + float zSpeed = fSpeed[2]; + fSpeed[2] = 0.0; + + ScaleVector(fSpeed, fScale); + fSpeed[2] = zSpeed; + } + else + { + ScaleVector(fSpeed, fScale); + } + + DumbSetVelocity(client, fSpeed); + } + + skipGroundTimer = true; + } + } + return Plugin_Continue; } diff --git a/addons/sourcemod/scripting/shavit-zones.sp b/addons/sourcemod/scripting/shavit-zones.sp index b8624f10..2ec80ef1 100644 --- a/addons/sourcemod/scripting/shavit-zones.sp +++ b/addons/sourcemod/scripting/shavit-zones.sp @@ -4991,7 +4991,8 @@ public void Shavit_OnRestart(int client, int track) { ResetClientTargetNameAndClassName(client, track); // normally StartTimer will happen on zone-touch BUT we have this here for zones that are in the air - Shavit_StartTimer(client, track); + bool skipGroundCheck = true; + Shavit_StartTimer(client, track, skipGroundCheck); } } // kz buttons @@ -5416,10 +5417,12 @@ public void TouchPost(int entity, int other) } } +#if 0 if (GetEntPropEnt(other, Prop_Send, "m_hGroundEntity") == -1 && !Shavit_GetStyleSettingBool(Shavit_GetBhopStyle(other), "startinair")) { return; } +#endif // start timer instantly for main track, but require bonuses to have the current timer stopped // so you don't accidentally step on those while running