From b145cc82f5ca62e446b9a967afff619f599f29e4 Mon Sep 17 00:00:00 2001 From: ricardoofnl Date: Sat, 5 Sep 2026 09:31:26 +0700 Subject: [PATCH] [saco] Implement/match `FUNC_10015C90`, the trailer sync handler; the 0.5 gate is a `<=` chain and the 6.0/3.0 snap gate a `>` chain --- saco/game/vehicle.h | 3 ++ saco/net/remoteplayer.cpp | 61 +++++++++++++++++++++++++++++++++++++++ saco/net/remoteplayer.h | 10 +++++++ 3 files changed, 74 insertions(+) diff --git a/saco/game/vehicle.h b/saco/game/vehicle.h index 2cef674..7df50a2 100644 --- a/saco/game/vehicle.h +++ b/saco/game/vehicle.h @@ -94,6 +94,9 @@ public: void FUNC_100B8150(char *szText); // .text:100B8150 void FUNC_100B7C10(); // .text:100B7C10 void FUNC_100B7C80(int a1); // .text:100B7C80 + CVehicle *FUNC_100B7C90(); // .text:100B7C90 + BOOL FUNC_100B7D70(); // .text:100B7D70 + BOOL FUNC_100B7DD0(); // .text:100B7DD0 BOOL FUNC_100B7460(); // .text:100B7460 BOOL FUNC_100B7E00(); // .text:100B7E00 diff --git a/saco/net/remoteplayer.cpp b/saco/net/remoteplayer.cpp index c595f9d..2cc60a8 100644 --- a/saco/net/remoteplayer.cpp +++ b/saco/net/remoteplayer.cpp @@ -41,6 +41,8 @@ typedef char CRemotePlayer_offsets[( typedef char CNetPlayer_offsets[(offsetof(CNetPlayer, m_PlayerName) == 0x14) ? 1 : -1]; typedef char BULLET_SYNC_offsets[(offsetof(BULLET_SYNC_DATA, byteWeaponID) == 0x27 && sizeof(BULLET_SYNC_DATA) == 0x28) ? 1 : -1]; +typedef char TRAILER_SYNC_offsets[(offsetof(TRAILER_SYNC_DATA, vecTurnSpeed) == 0x2A && + sizeof(TRAILER_SYNC_DATA) == 0x36) ? 1 : -1]; typedef char struc_41_offsets[(offsetof(struc_41, field_30) == 0x30) ? 1 : -1]; typedef char WEAPON_SLOT_offsets[(offsetof(WEAPON_SLOT_TYPE, field_8) == 8 && sizeof(WEAPON_SLOT_TYPE) == 28) ? 1 : -1]; @@ -475,6 +477,65 @@ void CRemotePlayer::FUNC_10016370(BULLET_SYNC_DATA *pSync) //---------------------------------------------------- +void CRemotePlayer::FUNC_10015C90(TRAILER_SYNC_DATA *pTrailer) +{ + if(!pTrailer->TrailerID) return; + if(pTrailer->TrailerID == INVALID_VEHICLE_ID) return; + + MATRIX4X4 mat; + VECTOR vecMove; + + CVehicle *pTrailerVeh = (CVehicle *)pNetGame->GetVehiclePool()->GetAt(pTrailer->TrailerID); + CVehicle *pVehicle = field_1E1; + if(!pVehicle) return; + if(!pTrailerVeh) return; + + if(!pTrailerVeh->FUNC_100B7D70() && !pVehicle->FUNC_100B7DD0()) return; + + if(pVehicle->FUNC_100B7C90() != pTrailerVeh) { + pVehicle->FUNC_100B7C80((int)pTrailerVeh); + pVehicle->FUNC_100B7C10(); + } + + pTrailerVeh->GetMatrix(&mat); + FUNC_100B6A80(pTrailer->quat, &mat); + + if(FloatOffset(pTrailer->vecPos.X, mat.pos.X) <= 0.5f && + FloatOffset(pTrailer->vecPos.Y, mat.pos.Y) <= 0.5f && + FloatOffset(pTrailer->vecPos.Z, mat.pos.Z) <= 0.5f) return; + + if(FloatOffset(pTrailer->vecPos.X, mat.pos.X) > 6.0f || + FloatOffset(pTrailer->vecPos.Y, mat.pos.Y) > 6.0f || + FloatOffset(pTrailer->vecPos.Z, mat.pos.Z) > 3.0f) { + mat.pos.X = pTrailer->vecPos.X; + mat.pos.Y = pTrailer->vecPos.Y; + mat.pos.Z = pTrailer->vecPos.Z; + pTrailerVeh->SetMatrix(mat); + pTrailerVeh->SetMoveSpeedVector(pTrailer->vecMoveSpeed); + pTrailerVeh->SetTurnSpeedVector(pTrailer->vecTurnSpeed); + return; + } + + pTrailerVeh->SetMatrix(mat); + pTrailerVeh->SetTurnSpeedVector(pTrailer->vecTurnSpeed); + + vecMove.X = 0.0f; + vecMove.Y = 0.0f; + vecMove.Z = 0.0f; + pTrailerVeh->GetMoveSpeedVector(&vecMove); + + if(FloatOffset(pTrailer->vecPos.X, mat.pos.X) > 0.05f) + vecMove.X = (pTrailer->vecPos.X - mat.pos.X) * 0.025f + vecMove.X; + if(FloatOffset(pTrailer->vecPos.Y, mat.pos.Y) > 0.05f) + vecMove.Y = (pTrailer->vecPos.Y - mat.pos.Y) * 0.025f + vecMove.Y; + if(FloatOffset(pTrailer->vecPos.Z, mat.pos.Z) > 0.05f) + vecMove.Z = (pTrailer->vecPos.Z - mat.pos.Z) * 0.025f + vecMove.Z; + + pTrailerVeh->SetMoveSpeedVector(vecMove); +} + +//---------------------------------------------------- + void CRemotePlayer::FUNC_10014950() { if(!m_pPlayerPed) return; diff --git a/saco/net/remoteplayer.h b/saco/net/remoteplayer.h index f283163..b2352d4 100644 --- a/saco/net/remoteplayer.h +++ b/saco/net/remoteplayer.h @@ -3,6 +3,15 @@ //---------------------------------------------------- +struct TRAILER_SYNC_DATA +{ + VEHICLEID TrailerID; + VECTOR vecPos; + float quat[4]; + VECTOR vecMoveSpeed; + VECTOR vecTurnSpeed; +}; + // the bullet sync payload, 0x28 bytes on the wire struct BULLET_SYNC_DATA { @@ -108,6 +117,7 @@ public: void FUNC_10014C40(); // .text:10014C40 void FUNC_10016370(BULLET_SYNC_DATA *pSync); // .text:10016370 void FUNC_10014950(); // .text:10014950 + void FUNC_10015C90(TRAILER_SYNC_DATA *pTrailer); // .text:10015C90 void FUNC_10014E60(); // .text:10014E60 void FUNC_10015460(); // .text:10015460 void FUNC_10015760(BYTE *pAim); // .text:10015760