From 743fe59be177d38e8109371c73092b68f2aa8a28 Mon Sep 17 00:00:00 2001 From: Dots Date: Tue, 15 Sep 2026 22:23:42 +0300 Subject: [PATCH] Add Movement_GetTakeoffLadderNormal, clean up ladderjump logic --- .../scripting/include/movementapi.inc | 14 ++++++ addons/sourcemod/scripting/movementapi.sp | 3 ++ .../sourcemod/scripting/movementapi/hooks.sp | 45 ++++++++++++------- .../scripting/movementapi/natives.sp | 10 +++++ 4 files changed, 55 insertions(+), 17 deletions(-) diff --git a/addons/sourcemod/scripting/include/movementapi.inc b/addons/sourcemod/scripting/include/movementapi.inc index 0bd6a83..cf6ba7c 100644 --- a/addons/sourcemod/scripting/include/movementapi.inc +++ b/addons/sourcemod/scripting/include/movementapi.inc @@ -379,6 +379,15 @@ native int Movement_GetTakeoffTick(int client); */ native int Movement_GetTakeoffCmdNum(int client); +/** + * Gets the plane normal of the ladder the player last took off from. + * + * @param client Client index. + * @param result Ladder normal, zero vector if the last takeoff was not from a ladder. + * @return True if the last takeoff was from a ladder. + */ +native bool Movement_GetTakeoffLadderNormal(int client, float result[3]); + /** * Gets a player's origin at the time of their last landing with the distbug fixed. * @@ -618,6 +627,10 @@ methodmap MovementAPIPlayer < MovementPlayer { return Movement_GetTakeoffCmdNum(this.ID); } } + + public bool GetTakeoffLadderNormal(float buffer[3]) { + return Movement_GetTakeoffLadderNormal(this.ID, buffer); + } public void GetLandingOrigin(float buffer[3]) { Movement_GetLandingOrigin(this.ID, buffer); @@ -735,6 +748,7 @@ public void __pl_movementapi_SetNTVOptional() MarkNativeAsOptional("Movement_GetTakeoffSpeed"); MarkNativeAsOptional("Movement_GetTakeoffTick"); MarkNativeAsOptional("Movement_GetTakeoffCmdNum"); + MarkNativeAsOptional("Movement_GetTakeoffLadderNormal"); MarkNativeAsOptional("Movement_GetLandingOrigin"); MarkNativeAsOptional("Movement_GetLandingVelocity"); MarkNativeAsOptional("Movement_GetLandingSpeed"); diff --git a/addons/sourcemod/scripting/movementapi.sp b/addons/sourcemod/scripting/movementapi.sp index 4a207f0..88cb874 100644 --- a/addons/sourcemod/scripting/movementapi.sp +++ b/addons/sourcemod/scripting/movementapi.sp @@ -167,6 +167,7 @@ static void ResetClientData(int client) gB_ProcessingLadderMove[client] = false; gF_PreLadderMoveVelocity[client] = view_as( { 0.0, 0.0, 0.0 } ); gB_TakeoffFromLadder[client] = false; + gF_TakeoffLadderNormal[client] = view_as( { 0.0, 0.0, 0.0 } ); gF_PostLadderMoveOrigin[client] = view_as( { 0.0, 0.0, 0.0 } ); gF_PostLadderMoveVelocity[client] = view_as( { 0.0, 0.0, 0.0 } ); gB_ProcessingDuck[client] = false; @@ -217,6 +218,7 @@ static void CheckNoclip(int client) gI_TakeoffCmdNum[client] = gI_Cmdnum[client]; gB_HitPerf[client] = false; gB_Jumped[client] = false; + gF_TakeoffLadderNormal[client] = view_as( { 0.0, 0.0, 0.0 } ); } Call_OnChangeMovetype(client, gMT_OldMovetype[client], movetype); } @@ -234,6 +236,7 @@ static void CheckGround(int client) gI_TakeoffCmdNum[client] = gI_Cmdnum[client]; gB_HitPerf[client] = false; gB_Jumped[client] = false; + gF_TakeoffLadderNormal[client] = view_as( { 0.0, 0.0, 0.0 } ); Call_OnStopTouchGround(client, false, false, false); } } diff --git a/addons/sourcemod/scripting/movementapi/hooks.sp b/addons/sourcemod/scripting/movementapi/hooks.sp index 8bd0f7e..7ed49f5 100644 --- a/addons/sourcemod/scripting/movementapi/hooks.sp +++ b/addons/sourcemod/scripting/movementapi/hooks.sp @@ -16,6 +16,7 @@ float gF_Velocity[MAXPLAYERS + 1][3]; bool gB_ProcessingLadderMove[MAXPLAYERS + 1]; float gF_PreLadderMoveVelocity[MAXPLAYERS + 1][3]; bool gB_TakeoffFromLadder[MAXPLAYERS + 1]; +float gF_TakeoffLadderNormal[MAXPLAYERS + 1][3]; float gF_PostLadderMoveOrigin[MAXPLAYERS + 1][3]; float gF_PostLadderMoveVelocity[MAXPLAYERS + 1][3]; @@ -176,6 +177,7 @@ public MRESReturn DHooks_OnLadderMove_Post(Address pThis, DHookReturn hReturn) gI_TakeoffCmdNum[client] = gI_Cmdnum[client]; gB_Jumped[client] = false; gB_HitPerf[client] = false; + GetEntPropVector(client, Prop_Send, "m_vecLadderNormal", gF_TakeoffLadderNormal[client]); Call_OnChangeMovetype(client, MOVETYPE_LADDER, MOVETYPE_WALK); } else if (returnValue && gMT_OldMovetype[client] != MOVETYPE_LADDER) @@ -191,23 +193,19 @@ public MRESReturn DHooks_OnLadderMove_Post(Address pThis, DHookReturn hReturn) Call_OnChangeMovetype(client, MOVETYPE_WALK, MOVETYPE_LADDER); } } - else if (returnValue && gMT_OldMovetype[client] == MOVETYPE_LADDER) + else if (returnValue && gMT_OldMovetype[client] == MOVETYPE_LADDER + && Movement_GetMovetype(client) == MOVETYPE_WALK) { - // Player is on the ladder and in the air, pressing jump pushes them away from the ladder. - float curtime = GetGameTime(); - int buttons = GetClientButtons(client); - float ignoreLadderJumpTime = GetEntPropFloat(client, Prop_Data, "m_ignoreLadderJumpTime"); - if (buttons & IN_JUMP && ignoreLadderJumpTime <= curtime) - { - gF_TakeoffVelocity[client] = gF_PostLadderMoveVelocity[client]; - gF_TakeoffOrigin[client] = gF_PostLadderMoveOrigin[client]; - gI_TakeoffTick[client] = gI_TickCount[client]; - gI_TakeoffCmdNum[client] = gI_Cmdnum[client]; - gB_Jumped[client] = false; - gB_HitPerf[client] = false; - gB_TakeoffFromLadder[client] = true; - Call_OnChangeMovetype(client, MOVETYPE_LADDER, MOVETYPE_WALK); - } + // Jumping away from the ladder. + gF_TakeoffVelocity[client] = gF_PostLadderMoveVelocity[client]; + gF_TakeoffOrigin[client] = gF_PostLadderMoveOrigin[client]; + gI_TakeoffTick[client] = gI_TickCount[client]; + gI_TakeoffCmdNum[client] = gI_Cmdnum[client]; + gB_Jumped[client] = false; + gB_HitPerf[client] = false; + gB_TakeoffFromLadder[client] = true; + GetEntPropVector(client, Prop_Send, "m_vecLadderNormal", gF_TakeoffLadderNormal[client]); + Call_OnChangeMovetype(client, MOVETYPE_LADDER, MOVETYPE_WALK); } Action result = UpdateMoveData(pThis, client, Call_OnLadderMovePost); if (result != Plugin_Continue) @@ -293,6 +291,10 @@ public MRESReturn DHooks_OnJump_Post(Address pThis, DHookParam hParams) gF_TakeoffVelocity[client] = gF_Velocity[client]; gI_TakeoffCmdNum[client] = gI_Cmdnum[client]; gI_TakeoffTick[client] = gI_TickCount[client]; + if (!gB_TakeoffFromLadder[client]) + { + gF_TakeoffLadderNormal[client] = view_as( { 0.0, 0.0, 0.0 } ); + } // OnJump will only be called if the client previously touched some sort of ground, so Call_OnStopTouchGround should always be called. Call_OnStopTouchGround(client, true, gB_TakeoffFromLadder[client], gB_Jumpbugged[client]); @@ -514,7 +516,16 @@ public MRESReturn DHooks_OnCategorizePosition_Post(Address pThis) gB_Jumped[client] = false; gB_HitPerf[client] = false; bool hadLadderMoveType = Movement_GetMovetype(client) == MOVETYPE_LADDER || gMT_OldMovetype[client] == MOVETYPE_LADDER; - Call_OnStopTouchGround(client, false, hadLadderMoveType && !gB_WalkMoved[client], false); + bool ladderJump = hadLadderMoveType && !gB_WalkMoved[client]; + if (ladderJump) + { + GetEntPropVector(client, Prop_Send, "m_vecLadderNormal", gF_TakeoffLadderNormal[client]); + } + else + { + gF_TakeoffLadderNormal[client] = view_as( { 0.0, 0.0, 0.0 } ); + } + Call_OnStopTouchGround(client, false, ladderJump, false); } } diff --git a/addons/sourcemod/scripting/movementapi/natives.sp b/addons/sourcemod/scripting/movementapi/natives.sp index 0e5d45a..d5bb955 100644 --- a/addons/sourcemod/scripting/movementapi/natives.sp +++ b/addons/sourcemod/scripting/movementapi/natives.sp @@ -7,6 +7,7 @@ void CreateNatives() CreateNative("Movement_GetTakeoffSpeed", Native_GetTakeoffSpeed); CreateNative("Movement_GetTakeoffTick", Native_GetTakeoffTick); CreateNative("Movement_GetTakeoffCmdNum", Native_GetTakeoffCmdNum); + CreateNative("Movement_GetTakeoffLadderNormal", Native_GetTakeoffLadderNormal); CreateNative("Movement_GetNobugLandingOrigin", Native_GetNobugLandingOrigin); CreateNative("Movement_GetLandingOrigin", Native_GetLandingOrigin); CreateNative("Movement_GetLandingVelocity", Native_GetLandingVelocity); @@ -67,6 +68,15 @@ public int Native_GetTakeoffCmdNum(Handle plugin, int numParams) return gI_TakeoffCmdNum[GetNativeCell(1)]; } +public int Native_GetTakeoffLadderNormal(Handle plugin, int numParams) +{ + int client = GetNativeCell(1); + SetNativeArray(2, gF_TakeoffLadderNormal[client], 3); + return gF_TakeoffLadderNormal[client][0] != 0.0 + || gF_TakeoffLadderNormal[client][1] != 0.0 + || gF_TakeoffLadderNormal[client][2] != 0.0; +} + public int Native_GetNobugLandingOrigin(Handle plugin, int numParams) { return SetNativeArray(2, gF_NobugLandingOrigin[GetNativeCell(1)], 3);