From c735f2f7505315f14ef86158503e60273d2fdefc Mon Sep 17 00:00:00 2001 From: ricardoofnl Date: Sat, 5 Sep 2026 09:50:08 +0700 Subject: [PATCH] [saco] Implement/match `ScrUnkAE`, `ScrUnkAF`, `ScrUnkB2`, `ScrUnkA0`, `ScrUnk39`, `ScrUnk7E` and `ScrUnk7F`; the actor lookup lands in `ecx` because it is the `this` of a thiscall, not an allocator choice --- saco/game/actorped.h | 4 ++ saco/game/vehicle.h | 2 + saco/net/localplayer.h | 2 +- saco/net/scriptrpc.cpp | 151 +++++++++++++++++++++++++++++++++++++++-- 4 files changed, 151 insertions(+), 8 deletions(-) diff --git a/saco/game/actorped.h b/saco/game/actorped.h index 2322471..ad2353c 100644 --- a/saco/game/actorped.h +++ b/saco/game/actorped.h @@ -31,6 +31,10 @@ public: void ToggleImmunity(BYTE byteEnable); + void FUNC_1009C550(); // .text:1009C550 + void FUNC_1009C570(float a1); // .text:1009C570 + void FUNC_1009C5D0(int a1); // .text:1009C5D0 + PED_TYPE *m_pPed; DWORD m_dwMarkerID; DWORD m_dwArrow; diff --git a/saco/game/vehicle.h b/saco/game/vehicle.h index e893dab..2cef674 100644 --- a/saco/game/vehicle.h +++ b/saco/game/vehicle.h @@ -59,6 +59,8 @@ public: void sub_100B7AC0(int iPanelDamage, int iDoorDamage, BYTE byteLightDamage); // .text:100B7AC0 void sub_100B7940(BYTE byteTyreDamage); // .text:100B7940 void FUNC_100B72C0(int a1); // .text:100B72C0 + void FUNC_100B8170(float a1); // .text:100B8170 + void FUNC_100B80B0(short a1); // .text:100B80B0 void SetHydraThrusters(DWORD dwDirection); DWORD GetHydraThrusters(); diff --git a/saco/net/localplayer.h b/saco/net/localplayer.h index 761e4ca..9ba447f 100644 --- a/saco/net/localplayer.h +++ b/saco/net/localplayer.h @@ -90,7 +90,7 @@ public: DWORD field_306; DWORD field_30A; - BYTE _pad30E; + BYTE field_30E; BYTE field_30F; DWORD field_310; diff --git a/saco/net/scriptrpc.cpp b/saco/net/scriptrpc.cpp index 402fa98..98e0f79 100644 --- a/saco/net/scriptrpc.cpp +++ b/saco/net/scriptrpc.cpp @@ -329,9 +329,74 @@ void ScrUnk7D(RPCParameters *rpcParams) // nothing } -void ScrUnk7E(RPCParameters *rpcParams) {} -void ScrUnk7F(RPCParameters *rpcParams) {} -void ScrUnk39(RPCParameters *rpcParams) {} +void ScrUnk7E(RPCParameters *rpcParams) +{ + PCHAR Data = reinterpret_cast(rpcParams->input); + int iBitLength = rpcParams->numberOfBitsOfData; + PlayerID sender = rpcParams->sender; + + PLAYERID playerId; + BYTE byteMode; + + RakNet::BitStream bsData(Data,(iBitLength/8)+1,false); + + bsData.Read(playerId); + bsData.Read(byteMode); + + switch(byteMode) { + case 2: byteMode = 15; break; + case 3: byteMode = 14; break; + default: byteMode = 4; break; + } + + CLocalPlayer *pLocalPlayer = pNetGame->GetPlayerPool()->GetLocalPlayer(); + pLocalPlayer->field_30E = byteMode; + pLocalPlayer->FUNC_10004280(playerId); +} +void ScrUnk7F(RPCParameters *rpcParams) +{ + PCHAR Data = reinterpret_cast(rpcParams->input); + int iBitLength = rpcParams->numberOfBitsOfData; + PlayerID sender = rpcParams->sender; + + PLAYERID playerId; + BYTE byteMode; + + RakNet::BitStream bsData(Data,(iBitLength/8)+1,false); + + bsData.Read(playerId); + bsData.Read(byteMode); + + switch(byteMode) { + case 2: byteMode = 15; break; + case 3: byteMode = 14; break; + default: byteMode = 3; break; + } + + CLocalPlayer *pLocalPlayer = pNetGame->GetPlayerPool()->GetLocalPlayer(); + pLocalPlayer->field_30E = byteMode; + pLocalPlayer->FUNC_10004230(playerId); +} +void ScrUnk39(RPCParameters *rpcParams) +{ + PCHAR Data = reinterpret_cast(rpcParams->input); + int iBitLength = rpcParams->numberOfBitsOfData; + PlayerID sender = rpcParams->sender; + + VEHICLEID vehicleId; + short sUnk; + + RakNet::BitStream bsData(Data,(iBitLength/8)+1,false); + + CVehiclePool *pVehiclePool = pNetGame->GetVehiclePool(); + if(!pVehiclePool) return; + + bsData.Read(vehicleId); + bsData.Read(sUnk); + + if(pVehiclePool->GetSlotState(vehicleId)) + ((CVehicle *)pVehiclePool->GetAt(vehicleId))->FUNC_100B80B0(sUnk); +} void ScrUnk4B(RPCParameters *rpcParams) { PCHAR Data = reinterpret_cast(rpcParams->input); @@ -939,7 +1004,24 @@ void ScrUnk9F(RPCParameters *rpcParams) ((CEntity *)pNetGame->GetVehiclePool()->GetAt(vehicleId))->TeleportTo(fX, fY, fZ); } } -void ScrUnkA0(RPCParameters *rpcParams) {} +void ScrUnkA0(RPCParameters *rpcParams) +{ + PCHAR Data = reinterpret_cast(rpcParams->input); + int iBitLength = rpcParams->numberOfBitsOfData; + PlayerID sender = rpcParams->sender; + + VEHICLEID vehicleId; + float fUnk; + + RakNet::BitStream bsData(Data,(iBitLength/8)+1,false); + + bsData.Read(vehicleId); + bsData.Read(fUnk); + + CVehiclePool *pVehiclePool = pNetGame->GetVehiclePool(); + if(pVehiclePool && pVehiclePool->GetSlotState(vehicleId)) + ((CVehicle *)pVehiclePool->GetAt(vehicleId))->FUNC_100B8170(fUnk); +} void ScrUnkA1(RPCParameters *rpcParams) { PCHAR Data = reinterpret_cast(rpcParams->input); @@ -1299,8 +1381,44 @@ void ScrUnkA9(RPCParameters *rpcParams) } } void ScrUnkAD(RPCParameters *rpcParams) {} -void ScrUnkAE(RPCParameters *rpcParams) {} -void ScrUnkAF(RPCParameters *rpcParams) {} +void ScrUnkAE(RPCParameters *rpcParams) +{ + PCHAR Data = reinterpret_cast(rpcParams->input); + int iBitLength = rpcParams->numberOfBitsOfData; + PlayerID sender = rpcParams->sender; + + ACTORID actorId; + + RakNet::BitStream bsData(Data,(iBitLength/8)+1,false); + + bsData.Read(actorId); + + CActorPool *pActorPool = pNetGame->GetActorPool(); + if(pActorPool) { + CActorPed *pActor = (CActorPed *)pActorPool->GetAt(actorId); + if(pActor) pActor->FUNC_1009C550(); + } +} +void ScrUnkAF(RPCParameters *rpcParams) +{ + PCHAR Data = reinterpret_cast(rpcParams->input); + int iBitLength = rpcParams->numberOfBitsOfData; + PlayerID sender = rpcParams->sender; + + ACTORID actorId; + float fUnk; + + RakNet::BitStream bsData(Data,(iBitLength/8)+1,false); + + bsData.Read(actorId); + bsData.Read(fUnk); + + CActorPool *pActorPool = pNetGame->GetActorPool(); + if(pActorPool) { + CActorPed *pActor = (CActorPed *)pActorPool->GetAt(actorId); + if(pActor) pActor->FUNC_1009C570(fUnk); + } +} void ScrUnkB0(RPCParameters *rpcParams) { PCHAR Data = reinterpret_cast(rpcParams->input); @@ -1327,7 +1445,26 @@ void ScrUnkB0(RPCParameters *rpcParams) } } } -void ScrUnkB2(RPCParameters *rpcParams) {} +void ScrUnkB2(RPCParameters *rpcParams) +{ + PCHAR Data = reinterpret_cast(rpcParams->input); + int iBitLength = rpcParams->numberOfBitsOfData; + PlayerID sender = rpcParams->sender; + + ACTORID actorId; + int iUnk; + + RakNet::BitStream bsData(Data,(iBitLength/8)+1,false); + + bsData.Read(actorId); + bsData.Read(iUnk); + + CActorPool *pActorPool = pNetGame->GetActorPool(); + if(pActorPool) { + CActorPed *pActor = (CActorPed *)pActorPool->GetAt(actorId); + if(pActor) pActor->FUNC_1009C5D0(iUnk); + } +} void ScrUnk30(RPCParameters *rpcParams) { PCHAR Data = reinterpret_cast(rpcParams->input);