Skip to content

Commit 336c351

Browse files
authored
Use TryPlayerMove's m_tracelist for true landing origin in bugged jumps (#44)
1 parent 089d398 commit 336c351

6 files changed

Lines changed: 391 additions & 2 deletions

File tree

addons/sourcemod/gamedata/movementapi.games.txt

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,24 @@
22
{
33
"csgo"
44
{
5+
"Addresses"
6+
{
7+
"sm_pSingleton"
8+
{
9+
"windows"
10+
{
11+
"signature" "CGameMovement::TryPlayerMove"
12+
"read" "718"
13+
}
14+
"linux"
15+
{
16+
"signature" "CGameMovement::TryPlayerMove"
17+
"read" "483"
18+
}
19+
20+
"read" "0"
21+
}
22+
}
523
"Keys"
624
{
725
"CGameMovement::player" "4"
@@ -90,6 +108,24 @@
90108
"this" "address"
91109
"return" "void"
92110
}
111+
"CGameMovement::TryPlayerMove"
112+
{
113+
"signature" "CGameMovement::TryPlayerMove"
114+
"callconv" "thiscall"
115+
"this" "address"
116+
"return" "int"
117+
"arguments"
118+
{
119+
"pFirstDest"
120+
{
121+
"type" "vectorptr"
122+
}
123+
"pFirstTrace"
124+
{
125+
"type" "objectptr"
126+
}
127+
}
128+
}
93129
}
94130
"Offsets"
95131
{
@@ -150,6 +186,12 @@
150186
"windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\xF9\xC7\x45\x2A\x00\x00\x00\x00\x8B\x47\x2A\xC7\x80"
151187
"linux" "\x55\x89\xE5\x57\x56\x53\x81\xEC\xA8\x00\x00\x00\x8B\x7D\x08"
152188
}
189+
"CGameMovement::TryPlayerMove"
190+
{
191+
"library" "server"
192+
"windows" "\x55\x8B\xEC\x83\xE4\xF8\x81\xEC\x38\x01\x00\x00\xF3\x0F\x10\x35\x2A\x2A\x2A\x2A"
193+
"linux" "\x55\x66\x0F\xEF\xDB\x89\xE5\x57\x56\x53\x81\xEC\x2A\x2A\x2A\x2A\x8B\x7D\x08"
194+
}
153195
}
154196
}
155197
}

addons/sourcemod/scripting/include/movementapi.inc

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,28 @@ forward Action Movement_OnCategorizePositionPre(int client, float origin[3], flo
283283
*/
284284
forward Action Movement_OnCategorizePositionPost(int client, float origin[3], float velocity[3]);
285285

286+
/**
287+
* Called before TryPlayerMove movement function is called.
288+
* Modifying origin or velocity parameters will change player's origin and velocity accordingly.
289+
*
290+
* @param client Client index.
291+
* @param origin Player origin.
292+
* @param velocity Player velocity.
293+
* @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise.
294+
*/
295+
forward Action Movement_OnTryPlayerMovePre(int client, float origin[3], float velocity[3]);
296+
297+
/**
298+
* Called after TryPlayerMove movement function is called.
299+
* Modifying origin or velocity parameters will change player's origin and velocity accordingly.
300+
*
301+
* @param client Client index.
302+
* @param origin Player origin.
303+
* @param velocity Player velocity.
304+
* @return Plugin_Changed if origin or velocity is changed, Plugin_Continue otherwise.
305+
*/
306+
forward Action Movement_OnTryPlayerMovePost(int client, float origin[3], float velocity[3]);
307+
286308
// =====[ NATIVES ]=====
287309

288310
/**
@@ -484,13 +506,42 @@ native void Movement_SetTakeoffVelocity(int client, float velocity[3]);
484506
*/
485507
native void Movement_SetLandingOrigin(int client, float origin[3]);
486508

509+
/**
510+
* Get the player's number of collisions during movement processing.
511+
* This function should ideally be called after inside Movement_OnTryPlayerMovePost.
512+
*
513+
* @param client Client index.
514+
* @param origin Desired velocity.
515+
*/
516+
native int Movement_GetCollisionCount(int client);
517+
518+
/**
519+
* Set the player's landing velocity.
520+
* This function should ideally be called after inside Movement_OnTryPlayerMovePost.
521+
*
522+
* @param client Client index.
523+
* @param num Collision number, must not exceed Movement_GetCollisionCount's value.
524+
* @param result Resultant vector.
525+
*/
526+
native void Movement_GetCollisionStartOrigin(int client, int num, float result[3]);
527+
528+
/**
529+
* Set the player's landing velocity.
530+
* This function should ideally be called after inside Movement_OnTryPlayerMovePost.
531+
*
532+
* @param client Client index.
533+
* @param origin Desired velocity.
534+
*/
535+
native void Movement_GetCollisionEndOrigin(int client, int num, float result[3]);
536+
487537
/**
488538
* Set the player's landing velocity.
539+
* This function should ideally be called after inside Movement_OnTryPlayerMovePost.
489540
*
490541
* @param client Client index.
491542
* @param origin Desired velocity.
492543
*/
493-
native void Movement_SetLandingVelocity(int client, float velocity[3]);
544+
native void Movement_GetCollisionNormal(int client, int num, float result[3]);
494545

495546
// =====[ METHODMAP ]=====
496547

@@ -608,6 +659,26 @@ methodmap MovementAPIPlayer < MovementPlayer {
608659
}
609660
}
610661

662+
property int CollisionCount {
663+
public get() {
664+
return Movement_GetCollisionCount(this.ID);
665+
}
666+
}
667+
public void GetCollisionStartOrigin(int num, float buffer[3])
668+
{
669+
Movement_GetCollisionStartOrigin(this.ID, num, buffer);
670+
}
671+
672+
public void GetCollisionEndOrigin(int num, float buffer[3])
673+
{
674+
Movement_GetCollisionEndOrigin(this.ID, num, buffer);
675+
}
676+
677+
public void GetCollisionNormal(int num, float buffer[3])
678+
{
679+
Movement_GetCollisionNormal(this.ID, num, buffer);
680+
}
681+
611682
public void GetProcessingVelocity(float buffer[3])
612683
{
613684
Movement_GetProcessingVelocity(this.ID, buffer);
@@ -659,5 +730,9 @@ public void __pl_movementapi_SetNTVOptional()
659730
MarkNativeAsOptional("Movement_SetTakeoffVelocity");
660731
MarkNativeAsOptional("Movement_SetLandingOrigin");
661732
MarkNativeAsOptional("Movement_SetLandingVelocity");
733+
MarkNativeAsOptional("Movement_GetCollisionCount");
734+
MarkNativeAsOptional("Movement_GetCollisionStartOrigin");
735+
MarkNativeAsOptional("Movement_GetCollisionEndOrigin");
736+
MarkNativeAsOptional("Movement_GetCollisionNormal");
662737
}
663738
#endif

addons/sourcemod/scripting/movementapi/forwards.sp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ static Handle H_OnWalkMovePre;
2121
static Handle H_OnWalkMovePost;
2222
static Handle H_OnCategorizePositionPre;
2323
static Handle H_OnCategorizePositionPost;
24+
static Handle H_OnTryPlayerMovePre;
25+
static Handle H_OnTryPlayerMovePost;
2426

2527
void CreateGlobalForwards()
2628
{
@@ -54,6 +56,9 @@ void CreateGlobalForwards()
5456

5557
H_OnCategorizePositionPre = CreateGlobalForward("Movement_OnCategorizePositionPre", ET_Event, Param_Cell, Param_Array, Param_Array);
5658
H_OnCategorizePositionPost = CreateGlobalForward("Movement_OnCategorizePositionPost", ET_Event, Param_Cell, Param_Array, Param_Array);
59+
60+
H_OnTryPlayerMovePre = CreateGlobalForward("Movement_OnTryPlayerMovePre", ET_Event, Param_Cell, Param_Array, Param_Array);
61+
H_OnTryPlayerMovePost = CreateGlobalForward("Movement_OnTryPlayerMovePost", ET_Event, Param_Cell, Param_Array, Param_Array);
5762
}
5863

5964
void Call_OnStartDucking(int client)
@@ -265,4 +270,24 @@ Action Call_OnCategorizePositionPost(int client, float origin[3], float velocity
265270
Call_PushArrayEx(velocity, 3, SM_PARAM_COPYBACK);
266271
Call_Finish(result);
267272
return result;
273+
}
274+
275+
Action Call_OnTryPlayerMovePre(int client, float origin[3], float velocity[3], Action &result)
276+
{
277+
Call_StartForward(H_OnTryPlayerMovePre);
278+
Call_PushCell(client);
279+
Call_PushArrayEx(origin, 3, SM_PARAM_COPYBACK);
280+
Call_PushArrayEx(velocity, 3, SM_PARAM_COPYBACK);
281+
Call_Finish(result);
282+
return result;
283+
}
284+
285+
Action Call_OnTryPlayerMovePost(int client, float origin[3], float velocity[3], Action &result)
286+
{
287+
Call_StartForward(H_OnTryPlayerMovePost);
288+
Call_PushCell(client);
289+
Call_PushArrayEx(origin, 3, SM_PARAM_COPYBACK);
290+
Call_PushArrayEx(velocity, 3, SM_PARAM_COPYBACK);
291+
Call_Finish(result);
292+
return result;
268293
}

addons/sourcemod/scripting/movementapi/hooks.sp

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ static DynamicDetour H_OnJump;
66
static DynamicDetour H_OnAirAccelerate;
77
static DynamicDetour H_OnWalkMove;
88
static DynamicDetour H_OnCategorizePosition;
9+
static DynamicDetour H_OnTryPlayerMove;
10+
static Address moveHelperAddr;
11+
static bool tryPlayerMoveThisTick;
912

1013
float gF_Origin[MAXPLAYERS + 1][3];
1114
float gF_Velocity[MAXPLAYERS + 1][3];
@@ -31,6 +34,12 @@ float gF_PostAAVelocity[MAXPLAYERS + 1][3];
3134

3235
bool gB_OldWalkMoved[MAXPLAYERS + 1];
3336

37+
int gI_CollisionCount[MAXPLAYERS + 1];
38+
39+
float gF_TraceStartOrigin[MAXPLAYERS + 1][MAX_BUMPS][3];
40+
float gF_TraceEndOrigin[MAXPLAYERS + 1][MAX_BUMPS][3];
41+
float gF_TraceNormal[MAXPLAYERS + 1][MAX_BUMPS][3];
42+
3443
void HookGameMovementFunctions()
3544
{
3645
HookGameMovementFunction(H_OnDuck, "CCSGameMovement::Duck", DHooks_OnDuck_Pre, DHooks_OnDuck_Post);
@@ -41,6 +50,13 @@ void HookGameMovementFunctions()
4150
HookGameMovementFunction(H_OnJump, "CCSGameMovement::OnJump", DHooks_OnJump_Pre, DHooks_OnJump_Post);
4251
HookGameMovementFunction(H_OnPlayerMove, "CCSGameMovement::PlayerMove", DHooks_OnPlayerMove_Pre, DHooks_OnPlayerMove_Post);
4352
HookGameMovementFunction(H_OnCategorizePosition, "CGameMovement::CategorizePosition", DHooks_OnCategorizePosition_Pre, DHooks_OnCategorizePosition_Post);
53+
HookGameMovementFunction(H_OnTryPlayerMove, "CGameMovement::TryPlayerMove", DHooks_OnTryPlayerMove_Pre, DHooks_OnTryPlayerMove_Post);
54+
55+
moveHelperAddr = GameConfGetAddress(gH_GameData, "sm_pSingleton");
56+
if (!moveHelperAddr)
57+
{
58+
SetFailState("Failed to find IMoveHelper::sm_pSingleton.");
59+
}
4460
}
4561

4662
Action UpdateMoveData(Address pThis, int client, Function func)
@@ -429,7 +445,7 @@ public MRESReturn DHooks_OnPlayerMove_Post(Address pThis)
429445
return MRES_Ignored;
430446
}
431447
Action result = UpdateMoveData(pThis, client, Call_OnPlayerMovePost);
432-
448+
tryPlayerMoveThisTick = false;
433449
if (result != Plugin_Continue)
434450
{
435451
return MRES_Handled;
@@ -513,8 +529,74 @@ public MRESReturn DHooks_OnCategorizePosition_Post(Address pThis)
513529
}
514530
}
515531

532+
public MRESReturn DHooks_OnTryPlayerMove_Pre(Address pThis, DHookReturn hReturn, DHookParam hParams)
533+
{
534+
int client = GetClientFromGameMovementAddress(pThis);
535+
if (!IsPlayerAlive(client) || IsFakeClient(client))
536+
{
537+
return MRES_Ignored;
538+
}
539+
Action result = UpdateMoveData(pThis, client, Call_OnTryPlayerMovePre);
540+
541+
for (int i = 0; i < MAX_BUMPS; i++)
542+
{
543+
gF_TraceStartOrigin[client][i] = NULL_VECTOR;
544+
gF_TraceEndOrigin[client][i] = NULL_VECTOR;
545+
gF_TraceNormal[client][i] = NULL_VECTOR;
546+
}
547+
548+
if (result != Plugin_Continue)
549+
{
550+
return MRES_Handled;
551+
}
552+
else
553+
{
554+
return MRES_Ignored;
555+
}
556+
}
557+
558+
public MRESReturn DHooks_OnTryPlayerMove_Post(Address pThis, DHookReturn hReturn, DHookParam hParams)
559+
{
560+
int client = GetClientFromGameMovementAddress(pThis);
561+
if (!IsPlayerAlive(client) || IsFakeClient(client))
562+
{
563+
return MRES_Ignored;
564+
}
565+
566+
tryPlayerMoveThisTick = true;
567+
gI_CollisionCount[client] = LoadFromAddress(moveHelperAddr + view_as<Address>(8) + view_as<Address>(12), NumberType_Int32);
568+
569+
Address m_TouchList_m_pElements = LoadFromAddress(moveHelperAddr + view_as<Address>(8) + view_as<Address>(16), NumberType_Int32);
570+
571+
for (int i = 0; i < gI_CollisionCount[client]; i++)
572+
{
573+
Trace trace = Trace(m_TouchList_m_pElements + view_as<Address>(i*96) + view_as<Address>(12));
574+
trace.startpos.ToArray(gF_TraceStartOrigin[client][i]);
575+
trace.endpos.ToArray(gF_TraceEndOrigin[client][i]);
576+
trace.plane.normal.ToArray(gF_TraceNormal[client][i]);
577+
}
578+
579+
Action result = UpdateMoveData(pThis, client, Call_OnTryPlayerMovePost);
580+
if (result != Plugin_Continue)
581+
{
582+
return MRES_Handled;
583+
}
584+
else
585+
{
586+
return MRES_Ignored;
587+
}
588+
}
589+
516590
static void NobugLandingOrigin(int client, float landingOrigin[3])
517591
{
592+
// Jump is bugged, try to use the trace result of TryPlayerMove if possible.
593+
if (tryPlayerMoveThisTick && gI_CollisionCount[client] > 0)
594+
{
595+
landingOrigin = gF_TraceEndOrigin[client][0];
596+
return;
597+
}
598+
// Fallback when no collision happened during TryPlayerMove, or that function was not called.
599+
518600
// NOTE: Get ground position and distance to ground.
519601
float groundEndPoint[3];
520602
groundEndPoint = gF_Origin[client];

addons/sourcemod/scripting/movementapi/natives.sp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ void CreateNatives()
2525
CreateNative("Movement_SetTakeoffVelocity", Native_SetTakeoffVelocity);
2626
CreateNative("Movement_SetLandingOrigin", Native_SetLandingOrigin);
2727
CreateNative("Movement_SetLandingVelocity", Native_SetLandingVelocity);
28+
29+
CreateNative("Movement_GetCollisionCount", Native_GetCollisionCount);
30+
CreateNative("Movement_GetCollisionStartOrigin", Native_GetCollisionStartOrigin);
31+
CreateNative("Movement_GetCollisionEndOrigin", Native_GetCollisionEndOrigin);
32+
CreateNative("Movement_GetCollisionNormal", Native_GetCollisionNormal);
2833
}
2934

3035
public int Native_GetJumped(Handle plugin, int numParams)
@@ -180,4 +185,27 @@ public int Native_SetLandingVelocity(Handle plugin, int numParams)
180185
}
181186

182187
return 0;
188+
}
189+
190+
public int Native_GetCollisionCount(Handle plugin, int numParams)
191+
{
192+
return gI_CollisionCount[GetNativeCell(1)];
193+
}
194+
195+
public int Native_GetCollisionStartOrigin(Handle plugin, int numParams)
196+
{
197+
SetNativeArray(3, gF_TraceStartOrigin[GetNativeCell(1)][GetNativeCell(2)], sizeof(gF_TraceStartOrigin[][]));
198+
return 0;
199+
}
200+
201+
public int Native_GetCollisionEndOrigin(Handle plugin, int numParams)
202+
{
203+
SetNativeArray(3, gF_TraceEndOrigin[GetNativeCell(1)][GetNativeCell(2)], sizeof(gF_TraceEndOrigin[][]));
204+
return 0;
205+
}
206+
207+
public int Native_GetCollisionNormal(Handle plugin, int numParams)
208+
{
209+
SetNativeArray(3, gF_TraceNormal[GetNativeCell(1)][GetNativeCell(2)], sizeof(gF_TraceNormal[][]));
210+
return 0;
183211
}

0 commit comments

Comments
 (0)