diff --git a/addons/sourcemod/scripting/include/movementapi.inc b/addons/sourcemod/scripting/include/movementapi.inc index 7848165..0782d6d 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. * @@ -624,6 +633,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); @@ -741,6 +754,7 @@ public void __pl_movementapi_SetNTVOptional() MarkNativeAsOptional("Movement_GetTakeoffSpeed"); MarkNativeAsOptional("Movement_GetTakeoffTick"); MarkNativeAsOptional("Movement_GetTakeoffCmdNum"); + MarkNativeAsOptional("Movement_GetTakeoffLadderNormal"); MarkNativeAsOptional("Movement_GetNobugLandingOrigin"); MarkNativeAsOptional("Movement_GetLandingOrigin"); MarkNativeAsOptional("Movement_GetLandingVelocity"); diff --git a/addons/sourcemod/scripting/movementapi.sp b/addons/sourcemod/scripting/movementapi.sp index 1745d7c..7929127 100644 --- a/addons/sourcemod/scripting/movementapi.sp +++ b/addons/sourcemod/scripting/movementapi.sp @@ -174,6 +174,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; @@ -230,6 +231,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); } @@ -247,6 +249,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 8684e53..9adf941 100644 --- a/addons/sourcemod/scripting/movementapi/hooks.sp +++ b/addons/sourcemod/scripting/movementapi/hooks.sp @@ -33,6 +33,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]; @@ -200,6 +201,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) @@ -215,23 +217,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) @@ -317,6 +315,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]); @@ -540,7 +542,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 e1ad0e3..53b1022 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);