From 16b657842ed3c615b163b0b63d3d25739ff06b6d Mon Sep 17 00:00:00 2001 From: ricardoofnl Date: Thu, 3 Sep 2026 03:37:09 +0700 Subject: [PATCH] [saco] Match `CRemotePlayer::FUNC_10014650`; vehicle ids 2000-3000 index the object pool, offsets clamped to +/-100 --- saco/net/objectpool.h | 2 +- saco/net/remoteplayer.cpp | 48 +++++++++++++++++++++++++++++++++++++++ saco/net/remoteplayer.h | 4 +++- 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/saco/net/objectpool.h b/saco/net/objectpool.h index 69b17e2..5df7454 100644 --- a/saco/net/objectpool.h +++ b/saco/net/objectpool.h @@ -3,7 +3,7 @@ class CObjectPool { -private: +public: int field_0; int field_4[MAX_OBJECTS]; int field_FA4[MAX_OBJECTS]; diff --git a/saco/net/remoteplayer.cpp b/saco/net/remoteplayer.cpp index 40e8e06..3f4e5db 100644 --- a/saco/net/remoteplayer.cpp +++ b/saco/net/remoteplayer.cpp @@ -251,6 +251,54 @@ void CRemotePlayer::FUNC_10014540(short a1, short a2, short a3) //---------------------------------------------------- +void CRemotePlayer::FUNC_10014650() +{ + if(field_10A != 17) return; + if(!field_C5.wVehicleID) return; + if(field_C5.wVehicleID == INVALID_VEHICLE_ID) return; + if(field_C5.wVehicleID >= (MAX_VEHICLES + 1000)) return; + + CVehiclePool *pVehiclePool = pNetGame->GetVehiclePool(); + CObjectPool *pObjectPool = pNetGame->GetObjectPool(); + CEntity *pEntity; + + if(field_C5.wVehicleID < MAX_VEHICLES) { + if(!pVehiclePool->field_3074[field_C5.wVehicleID]) return; + pEntity = (CEntity *)pVehiclePool->field_1134[field_C5.wVehicleID]; + } else { + WORD wObjectID = field_C5.wVehicleID - MAX_VEHICLES; + if(wObjectID > MAX_OBJECTS) return; + if(!pObjectPool->field_4[wObjectID]) return; + pEntity = (CEntity *)pObjectPool->field_FA4[wObjectID]; + } + + if(!pEntity) return; + + if(field_C5.vecOffset.X > 100.0f) return; + if(field_C5.vecOffset.X < -100.0f) return; + if(field_C5.vecOffset.Y > 100.0f) return; + if(field_C5.vecOffset.Y < -100.0f) return; + if(field_C5.vecOffset.Z > 100.0f) return; + if(field_C5.vecOffset.Z < -100.0f) return; + + MATRIX4X4 matEntity; + MATRIX4X4 matPed; + VECTOR vecMove; + VECTOR vecTurn; + VECTOR vecOut; + + pEntity->GetMatrix(&matEntity); + pEntity->GetMoveSpeedVector(&vecMove); + pEntity->GetTurnSpeedVector(&vecTurn); + m_pPlayerPed->GetMatrix(&matPed); + + FUNC_100B4D10(&vecOut, &matEntity, &field_C5.vecOffset); + matPed.pos = vecOut; + m_pPlayerPed->SetMatrix(matPed); +} + +//---------------------------------------------------- + void CRemotePlayer::FUNC_10014500(int a1) { if(!a1) { diff --git a/saco/net/remoteplayer.h b/saco/net/remoteplayer.h index 081b36c..68b0f84 100644 --- a/saco/net/remoteplayer.h +++ b/saco/net/remoteplayer.h @@ -23,7 +23,8 @@ public: char field_AD[24]; // one 68-byte block: ResetAllSyncAttributes memsets it whole struct { - char _pad0[62]; + char _pad0[50]; + VECTOR vecOffset; // 0xF7 WORD wVehicleID; // 0x103 char _pad1[4]; } field_C5; @@ -79,6 +80,7 @@ public: void FUNC_100143A0(); // .text:100143A0 void FUNC_10014500(int a1); // .text:10014500 void FUNC_10014540(short a1, short a2, short a3); // .text:10014540 + void FUNC_10014650(); // .text:10014650 void FUNC_10017610(char *szText); // .text:10017610 void FUNC_100150D0(VECTOR *pPos, VECTOR *pMoveSpeed); // .text:100150D0 void FUNC_100155E0(int a1, VECTOR *pPos, VECTOR *pMoveSpeed); // .text:100155E0