mirror of
https://github.com/dashr9230/SA-MP.git
synced 2026-10-10 19:53:04 +08:00
3456 lines
82 KiB
C++
3456 lines
82 KiB
C++
|
|
#include "../main.h"
|
|
#include "game.h"
|
|
#include "util.h"
|
|
#include "keystuff.h"
|
|
#include "aimstuff.h"
|
|
|
|
extern int iGtaVersion;
|
|
extern CNetGame* pNetGame;
|
|
extern CGame* pGame;
|
|
extern CChatWindow *pChatWindow;
|
|
extern CObjectPool *unnamed_1014FFAC; // 0x1014FFAC, lives in another translation unit
|
|
|
|
extern DWORD dwGraphicsLoop; // Used for the external dll game loop.
|
|
|
|
int WINAPI exc_filter(unsigned int code, struct _EXCEPTION_POINTERS *ep, char *what);
|
|
|
|
#define NUDE void _declspec(naked)
|
|
|
|
//-----------------------------------------------------------
|
|
// Globals which are used to avoid stack frame alteration
|
|
// inside the following hook procedures.
|
|
|
|
DWORD dwFarClipHookAddr=0;
|
|
DWORD dwFarClipReturnAddr=0;
|
|
|
|
// used generically
|
|
PED_TYPE *_pPlayer;
|
|
|
|
BOOL bIgnoreNextEntry=FALSE;
|
|
BOOL bIgnoreNextExit=FALSE;
|
|
|
|
BYTE byteSavedCameraMode;
|
|
DWORD dwCurPlayerActor=0;
|
|
BYTE *pbyteCameraMode = (BYTE *)0xB6F1A8;
|
|
BYTE *pbyteCurrentPlayer = (BYTE *)0xB7CD74;
|
|
WORD *wCameraMode2 = (WORD *)0xB6F858;
|
|
|
|
PED_TYPE pedCrimeReportTemp; // pay attention! used in 0x100A1790 ; void __thiscall CGame::PlayCrimeReport as pedCrimeReportTemp 0x10150D00
|
|
|
|
int iRadarColor1=0;
|
|
DWORD dwSavedCheatFn=0;
|
|
|
|
BOOL bAllowVehicleCreation=FALSE;
|
|
|
|
float fFarClip=1400.0f;
|
|
|
|
DWORD dwParam1;
|
|
DWORD dwParam2;
|
|
DWORD dwParamThis;
|
|
|
|
DWORD unnamed_10113AD8 = 1;
|
|
DWORD unnamed_10113ADC = 0x7FB270; // RwRasterCreate
|
|
WORD unnamed_10113B2C;
|
|
BYTE unnamed_10113AE8[3] = {0xFF,0x52,0x20}; // original `call dword ptr [edx+20h]` at 0x4096AA
|
|
|
|
PCHAR unnamed_10150734;
|
|
DWORD unnamed_10150960;
|
|
PCHAR unnamed_10151628; // gxt key, also reused as the ped a use-gun task runs on
|
|
DWORD unnamed_101516C8;
|
|
DWORD unnamed_101516D0;
|
|
DWORD unnamed_101516D4;
|
|
DWORD unnamed_101516D8; // vehicle being rendered
|
|
DWORD unnamed_10151710;
|
|
DWORD unnamed_1015172C;
|
|
DWORD unnamed_10151804;
|
|
bool unnamed_10151808;
|
|
DWORD unnamed_1015180C;
|
|
DWORD unnamed_10151810;
|
|
DWORD unnamed_10151814;
|
|
DWORD unnamed_10151818;
|
|
DWORD unnamed_10151824;
|
|
|
|
CObjectPool *unnamed_1015177C;
|
|
|
|
WORD wLastRendObj=0;
|
|
|
|
BYTE Unk1_JmpCode[] = {0xFF,0x19,0xD1,0xBE,0x35,0x00};
|
|
BYTE TaskEnterVehicleDriver_HookJmpCode[] = {0xFF,0x25,0xBB,0x19,0x69,0x00,0x90};
|
|
BYTE TaskExitVehicle_HookJmpCode[] = {0xFF,0x25,0xBA,0xB8,0x63,0x00,0x90};
|
|
BYTE RadarTranslateColor_HookJmpCode[] = {0xFF,0x25,0x79,0x4A,0x58,0x00,0x90};
|
|
BYTE CheatProcessHook_JmpCode[] = {0xFF,0x25,0xAA,0x85,0x43,0x00,0x90};
|
|
BYTE Unk2_JmpCode[] = {0xFF,0x25,0x33,0x14,0x42,0x00};
|
|
BYTE Unk3_JmpCode[] = {0xFF,0x25,0x61,0x36,0x53,0x00,0x90,0x90,0x90};
|
|
BYTE CGameShutdown_HookJmpCode[] = {0xFF,0x25,0xF1,0xC8,0x53,0x00,0x90};
|
|
BYTE PedDamage_HookJmpCode[] = {0xFF,0x25,0xBC,0x5A,0x4B,0x00};
|
|
BYTE Unk4_JmpCode[] = {0xFF,0x25,0x74,0x22,0x50,0x00,0x90,0x90,0x90,0x90};
|
|
BYTE Unk5_JmpCode[] = {0xFF,0x25,0x61,0x38,0x4C,0x00};
|
|
BYTE GetText_HookJmpCode[] = {0xFF,0x25,0x43,0x00,0x6A,0x00,0x90,0x90,0x90};
|
|
BYTE Unk6_JmpCode[] = {0xFF,0x25,0xD8,0xFF,0x5E,0x00,0x90};
|
|
BYTE CProjectileInfo_Update_HookJmpCode[] = {0xFF,0x25,0x1B,0x8B,0x73,0x00};
|
|
BYTE CWeapon__Satchel__Activate_HookJmpCode[] = {0xFF,0x25,0x5B,0x88,0x73,0x00};
|
|
BYTE Unk7_JmpCode[] = {0xFF,0x25,0x36,0xA0,0x63,0x00,0x90};
|
|
BYTE Unk8_JmpCode[] = {0xFF,0x25,0x77,0xAB,0x5E,0x00,0x90};
|
|
BYTE Unk9_JmpCode[] = {0xFF,0x25,0x39,0x88,0x4C,0x00,0x90,0x90};
|
|
BYTE CAnimManager__AddAnimation_Hook_HookJmpCode[] = {0xFF,0x25,0x34,0x39,0x4D,0x00,0x90,0x90,0x90,0x90};
|
|
BYTE CAnimManager__BlendAnimation_HookJmpCode[] = {0xFF,0x25,0x09,0x46,0x4D,0x00,0x90};
|
|
BYTE Unk10_JmpCode[] = {0xFF,0x25,0xE5,0x42,0x4D,0x00,0x90};
|
|
BYTE Unk11_JmpCode[] = {0xFF,0x25,0x29,0x3B,0x4D,0x00};
|
|
BYTE RwRasterDestroy_HookJmpCode[] = {0xFF,0x25,0x21,0xC7,0x59,0x00};
|
|
BYTE CFileLoader__LoadObjectInstance_HookJmpCode[] = {0xFF,0x25,0x84,0x80,0x53,0x00,0x90};
|
|
BYTE CRenderer__AddEntityToRenderList_HookJmpCode[] = {0xFF,0x25,0xA6,0x34,0x55,0x00,0x90,0x90,0x90};
|
|
BYTE CEventDamage__AffectsPed_HookJmpCode[] = {0xFF,0x25,0x33,0x34,0x4B,0x00};
|
|
BYTE Unk12_JmpCode[] = {0xFF,0x25,0xC6,0x84,0x6D,0x00,0x90,0x90};
|
|
BYTE CStreaming__RequestModel_HookJmpCode[] = {0xFF,0x25,0xD7,0x87,0x40,0x00};
|
|
BYTE CWorld__ProcessVerticalLine_HookJmpCode[] = {0xFF,0x25,0xDB,0x74,0x56,0x00};
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
|
|
// TODO: implement functions
|
|
|
|
// radar scale/shape fix
|
|
|
|
|
|
bool bHudScaleFix = true;
|
|
DWORD dwHudScaleX = 0;
|
|
DWORD dwHudScaleY = 0;
|
|
float fMaximumWidth;
|
|
float fMaximumHeight;
|
|
bool bSomeHudScaleFixFlag = false;
|
|
float* CRadar__radarHeight = (float*)0x866B74;
|
|
float* CRadar__radarWidth = (float*)0x866B78;
|
|
|
|
void ProcessHudScaleFix()
|
|
{
|
|
if ( bHudScaleFix )
|
|
{
|
|
dwHudScaleX = *(DWORD*)0x859520;
|
|
dwHudScaleY = *(DWORD*)0x859524;
|
|
|
|
fMaximumWidth = (float)pGame->GetScreenWidth();
|
|
fMaximumHeight = (float)pGame->GetScreenHeight();
|
|
|
|
if ( pGame->GetScreenWidth() > 0 && pGame->GetScreenHeight() > 0 )
|
|
{
|
|
if ( fMaximumWidth / fMaximumHeight >= 1.6f )
|
|
{
|
|
*CRadar__radarHeight = 82.0f;
|
|
*CRadar__radarWidth = 96.0f;
|
|
*(float*)0x859524 = 0.00242f;
|
|
*(float*)0x859520 = 0.00222f / (fMaximumWidth / fMaximumHeight);
|
|
bSomeHudScaleFixFlag = true;
|
|
}
|
|
else
|
|
{
|
|
*CRadar__radarHeight = 76.0f;
|
|
*CRadar__radarWidth = 94.0f;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
inline void FUNC_100A24C0()
|
|
{
|
|
if(bSomeHudScaleFixFlag == true)
|
|
{
|
|
*(DWORD*)0x859520 = dwHudScaleX;
|
|
*(DWORD*)0x859524 = dwHudScaleY;
|
|
*CRadar__radarHeight = 76.0f;
|
|
*CRadar__radarWidth = 94.0f;
|
|
bSomeHudScaleFixFlag = false;
|
|
}
|
|
}
|
|
|
|
NUDE CHud__DrawRadar_Hook()
|
|
{
|
|
__asm pushad
|
|
ProcessHudScaleFix();
|
|
|
|
__asm
|
|
{
|
|
popad
|
|
|
|
// call original CHud::DrawRadar
|
|
mov edx, 0x58A330
|
|
call edx
|
|
|
|
pushad
|
|
}
|
|
|
|
FUNC_100A24C0();
|
|
|
|
__asm
|
|
{
|
|
popad
|
|
retn
|
|
}
|
|
}
|
|
|
|
bool bSomeFlag = false;
|
|
NUDE CHud__DrawCrossHairs_Hook()
|
|
{
|
|
__asm pushad
|
|
|
|
bSomeFlag = false;
|
|
if ( pGame && pGame->FindPlayerPed() )
|
|
{
|
|
if ( pGame->FindPlayerPed()->GetCameraMode() == 53 )
|
|
{
|
|
ProcessHudScaleFix();
|
|
bSomeFlag = true;
|
|
}
|
|
}
|
|
|
|
__asm
|
|
{
|
|
popad
|
|
|
|
// call original CHud::DrawCrossHairs
|
|
mov edx, 0x58E020
|
|
call edx
|
|
|
|
pushad
|
|
}
|
|
|
|
if (bSomeFlag)
|
|
{
|
|
FUNC_100A24C0();
|
|
bSomeFlag = false;
|
|
}
|
|
|
|
__asm
|
|
{
|
|
popad
|
|
retn
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE CCamera__Process_Hook()
|
|
{
|
|
_asm pushad
|
|
|
|
if(pGame) {
|
|
pGame->GetCamera()->FUNC_1009D6B0();
|
|
}
|
|
|
|
_asm popad
|
|
_asm mov eax, 0x52B730
|
|
_asm jmp eax
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
void CGame__Process_Hook()
|
|
{
|
|
if(pGame) pGame->sub_100A1C10();
|
|
|
|
// every pool update gets its own seh block, tagged so exc_filter can name it
|
|
if(pNetGame && pNetGame->GetObjectPool())
|
|
{
|
|
__try
|
|
{
|
|
pNetGame->GetObjectPool()->FUNC_10012A50();
|
|
}
|
|
__except(exc_filter(GetExceptionCode(), GetExceptionInformation(), "s003")) { }
|
|
}
|
|
|
|
if(unnamed_1014FFAC)
|
|
{
|
|
__try
|
|
{
|
|
unnamed_1014FFAC->FUNC_10012A50();
|
|
}
|
|
__except(exc_filter(GetExceptionCode(), GetExceptionInformation(), "s003d")) { }
|
|
}
|
|
|
|
if(pNetGame && pNetGame->GetVehiclePool()) pNetGame->GetVehiclePool()->FUNC_1001ED70();
|
|
if(pNetGame && pNetGame->GetObjectPool()) pNetGame->GetObjectPool()->FUNC_10012B10();
|
|
if(pChatWindow) pChatWindow->FUNC_10067ED0();
|
|
|
|
__try
|
|
{
|
|
_asm mov edx, 0x53BEE0
|
|
_asm call edx
|
|
}
|
|
__except(exc_filter(GetExceptionCode(), GetExceptionInformation(), "s007")) { }
|
|
|
|
if(pNetGame && pNetGame->GetTextDrawPool()) pNetGame->GetTextDrawPool()->FUNC_1001E870();
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
void FUNC_100C3D30(BOOL bFogEnable); // todo: implement `FUNC_100C3D30`, lives in another file
|
|
extern DWORD GLOBAL_1026EBDC; // todo: define, lives in another file
|
|
|
|
NUDE CPed_Render_Hook()
|
|
{
|
|
__asm pushad
|
|
|
|
FUNC_100C3D30(FALSE);
|
|
|
|
__asm
|
|
{
|
|
popad
|
|
|
|
// call original CPed::Render
|
|
mov edx, 0x5E7680
|
|
call edx
|
|
|
|
pushad
|
|
}
|
|
|
|
if (GLOBAL_1026EBDC) FUNC_100C3D30(TRUE);
|
|
else FUNC_100C3D30(FALSE);
|
|
|
|
__asm
|
|
{
|
|
popad
|
|
retn
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
// saved return address, shared by the task and anim hooks below
|
|
DWORD dwHookRetnAddr;
|
|
|
|
// animation the local player got told to play, picked up for sync
|
|
DWORD dwAnimClump;
|
|
DWORD dwAnimGroup;
|
|
DWORD dwAnimID;
|
|
DWORD dwAnimBlend;
|
|
DWORD dwLocalPlayerClump;
|
|
|
|
DWORD dwSyncAnimType;
|
|
DWORD dwSyncAnimGroup;
|
|
DWORD dwSyncAnimID;
|
|
DWORD dwSyncAnimBlend;
|
|
|
|
DWORD dwAddAnimationRetAddr = 0x4D3AAA;
|
|
DWORD dwBlendAnimationRetAddr = 0x4D4617;
|
|
|
|
NUDE CAnimManager__AddAnimation_Hook()
|
|
{
|
|
_asm mov edx, [esp]
|
|
_asm mov dwHookRetnAddr, edx
|
|
_asm mov edx, [esp+4]
|
|
_asm mov dwAnimClump, edx
|
|
_asm mov edx, [esp+8]
|
|
_asm mov dwAnimGroup, edx
|
|
_asm mov edx, [esp+12]
|
|
_asm mov dwAnimID, edx
|
|
_asm pushad
|
|
|
|
_pPlayer = GamePool_FindPlayerPed();
|
|
if(_pPlayer) dwLocalPlayerClump = (DWORD)_pPlayer->entity.pdwRenderWare;
|
|
else dwLocalPlayerClump = 0;
|
|
|
|
if(dwAnimClump == dwLocalPlayerClump && (dwAnimGroup || dwAnimID != 0xA0))
|
|
{
|
|
dwSyncAnimType = 1;
|
|
dwSyncAnimGroup = dwAnimGroup;
|
|
dwSyncAnimID = dwAnimID;
|
|
}
|
|
|
|
_asm popad
|
|
_asm mov eax, [esp+12]
|
|
_asm mov edx, ds:0xB4EA34
|
|
_asm jmp dwAddAnimationRetAddr
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE CAnimManager__BlendAnimation_Hook()
|
|
{
|
|
_asm mov edx, [esp]
|
|
_asm mov dwHookRetnAddr, edx
|
|
_asm mov edx, [esp+4]
|
|
_asm mov dwAnimClump, edx
|
|
_asm mov edx, [esp+8]
|
|
_asm mov dwAnimGroup, edx
|
|
_asm mov edx, [esp+12]
|
|
_asm mov dwAnimID, edx
|
|
_asm mov edx, [esp+16]
|
|
_asm mov dwAnimBlend, edx
|
|
_asm pushad
|
|
|
|
_pPlayer = GamePool_FindPlayerPed();
|
|
if(_pPlayer) dwLocalPlayerClump = (DWORD)_pPlayer->entity.pdwRenderWare;
|
|
else dwLocalPlayerClump = 0;
|
|
|
|
if(dwAnimClump == dwLocalPlayerClump && (dwAnimGroup || dwAnimID != 0xA0))
|
|
{
|
|
dwSyncAnimType = 2;
|
|
dwSyncAnimGroup = dwAnimGroup;
|
|
dwSyncAnimID = dwAnimID;
|
|
dwSyncAnimBlend = dwAnimBlend;
|
|
}
|
|
|
|
_asm popad
|
|
_asm sub esp, 0x14
|
|
_asm mov ecx, [esp+0x18]
|
|
_asm jmp dwBlendAnimationRetAddr
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
DWORD dwProcessControlPed;
|
|
PED_TYPE *_pProcessControlPed;
|
|
BYTE byteSavedCurrentPlayer;
|
|
BYTE byteProcessControlPlayerID;
|
|
WORD wSavedCameraMode2;
|
|
DWORD dwSavedPedHealth;
|
|
GTA_CONTROLSET *pProcessControlKeys;
|
|
|
|
// `fst [esi+0x55C]` heading writes at 0x6884C4 and 0x688200, only enabled for the local player
|
|
BYTE PedHeadingCode1[] = {0xD9,0x96,0x5C,0x05,0x00,0x00};
|
|
BYTE PedHeadingCode2[] = {0xD9,0x96,0x5C,0x05,0x00,0x00};
|
|
// `call 0x5E1B10` at 0x5E92F4, nopped out while a remote ped processes
|
|
BYTE RemotePedProcessCode[] = {0xE8,0x17,0x88,0xFF,0xFF};
|
|
|
|
CPlayerPool *pRemotePedPlayerPool;
|
|
PLAYERID remotePedPlayerId;
|
|
CRemotePlayer *pRemotePedPlayer;
|
|
|
|
// runs the original CPlayerPed::ProcessControl for a remote ped under SEH; a fault
|
|
// there kicks the player rather than taking the whole client down
|
|
void ProcessControlRemotePed()
|
|
{
|
|
__try
|
|
{
|
|
_asm mov ecx, dwProcessControlPed
|
|
_asm mov edx, 0x60EA90
|
|
_asm call edx
|
|
}
|
|
__except(exc_filter(GetExceptionCode(), GetExceptionInformation(), "playerped"))
|
|
{
|
|
if(*pbyteCurrentPlayer)
|
|
{
|
|
if(pNetGame)
|
|
{
|
|
pRemotePedPlayerPool = pNetGame->GetPlayerPool();
|
|
|
|
if(pRemotePedPlayerPool)
|
|
{
|
|
remotePedPlayerId = pRemotePedPlayerPool->FUNC_100138C0(dwProcessControlPed);
|
|
|
|
if(remotePedPlayerId != 0xFFFF)
|
|
{
|
|
pRemotePedPlayer = pRemotePedPlayerPool->GetAt(remotePedPlayerId);
|
|
|
|
if(pRemotePedPlayer) pRemotePedPlayer->FUNC_10017530();
|
|
|
|
if(pChatWindow)
|
|
pChatWindow->AddDebugMessage("Removed player %u due to error.", remotePedPlayerId);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// .text:100A28C0 : nop the two ped heading writes back out
|
|
void FUNC_100A28C0()
|
|
{
|
|
memset((void *)0x6884C4, 0x90, 6);
|
|
memset((void *)0x688200, 0x90, 6);
|
|
}
|
|
|
|
// .text:100A28E0 : put the two ped heading writes back
|
|
void FUNC_100A28E0()
|
|
{
|
|
memcpy((void *)0x6884C4, PedHeadingCode1, 6);
|
|
memcpy((void *)0x688200, PedHeadingCode2, 6);
|
|
}
|
|
|
|
// .text:100A2920 : nop the remote ped process call out
|
|
void FUNC_100A2920()
|
|
{
|
|
UnFuck(0x5E92F4, 5);
|
|
memset((void *)0x5E92F4, 0x90, 5);
|
|
}
|
|
|
|
// .text:100A2940 : put the remote ped process call back
|
|
void FUNC_100A2940()
|
|
{
|
|
memcpy((void *)0x5E92F4, RemotePedProcessCode, 5);
|
|
}
|
|
|
|
NUDE CPlayerPed_ProcessControl_Hook()
|
|
{
|
|
_asm mov dwProcessControlPed, ecx
|
|
_asm pushad
|
|
|
|
_pProcessControlPed = (PED_TYPE *)dwProcessControlPed;
|
|
byteSavedCurrentPlayer = *pbyteCurrentPlayer;
|
|
byteProcessControlPlayerID = FindPlayerNumFromPedPtr(dwProcessControlPed);
|
|
|
|
if(dwProcessControlPed && byteProcessControlPlayerID && !byteSavedCurrentPlayer)
|
|
{
|
|
GameStoreLocalPlayerKeys();
|
|
GameSetRemotePlayerKeys(byteProcessControlPlayerID);
|
|
|
|
byteSavedCameraMode = *pbyteCameraMode;
|
|
*pbyteCameraMode = GameGetPlayerCameraMode(byteProcessControlPlayerID);
|
|
wSavedCameraMode2 = *wCameraMode2;
|
|
*wCameraMode2 = GameGetPlayerCameraMode(byteProcessControlPlayerID);
|
|
if(*wCameraMode2 == 4) *wCameraMode2 = 0;
|
|
|
|
GameStoreLocalPlayerCameraExtZoom();
|
|
GameSetRemotePlayerCameraExtZoom(byteProcessControlPlayerID);
|
|
GameStoreLocalPlayerAim();
|
|
GameSetRemotePlayerAim(byteProcessControlPlayerID);
|
|
GameStoreLocalPlayerWeaponSkills();
|
|
GameSetRemotePlayerWeaponSkills(byteProcessControlPlayerID);
|
|
|
|
*pbyteCurrentPlayer = byteProcessControlPlayerID;
|
|
dwSavedPedHealth = *(DWORD *)&_pProcessControlPed->fHealth;
|
|
|
|
UnFuck(0x5E92F4, 5);
|
|
memset((void *)0x5E92F4, 0x90, 5);
|
|
ProcessControlRemotePed();
|
|
memcpy((void *)0x5E92F4, RemotePedProcessCode, 5);
|
|
|
|
GameSetLocalPlayerWeaponSkills();
|
|
*pbyteCameraMode = byteSavedCameraMode;
|
|
*wCameraMode2 = wSavedCameraMode2;
|
|
GameSetLocalPlayerCameraExtZoom();
|
|
*pbyteCurrentPlayer = 0;
|
|
GameSetLocalPlayerKeys();
|
|
GameSetLocalPlayerAim();
|
|
}
|
|
else
|
|
{
|
|
if(pNetGame && pNetGame->GetPlayerPool()->GetLocalPlayer()->GetField_F0())
|
|
{
|
|
struc_41 *pSettings = pNetGame->GetSettings();
|
|
|
|
if(pGame->FindPlayerPed()->HasExceededWorldBoundries(pSettings->fWorldBoundryPX,
|
|
pSettings->fWorldBoundryZX, pSettings->fWorldBoundryPY, pSettings->fWorldBoundryNY))
|
|
{
|
|
if(!pGame->GetActiveInterior())
|
|
{
|
|
DWORD dwStateFlags = _pProcessControlPed->dwStateFlags;
|
|
|
|
if(!(dwStateFlags & 0x100) && (dwStateFlags & 3))
|
|
{
|
|
pProcessControlKeys = GameGetInternalKeys();
|
|
pProcessControlKeys->wKeys1[14] = 255;
|
|
pProcessControlKeys->wKeys2[14] = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(pGame->FindPlayerPed())
|
|
{
|
|
if(pGame->FindPlayerPed()->field_2F7)
|
|
{
|
|
pProcessControlKeys = GameGetInternalKeys();
|
|
pProcessControlKeys->wKeys1[18] = 0;
|
|
pProcessControlKeys->wKeys2[18] = 0;
|
|
}
|
|
|
|
if(pGame->FindPlayerPed()->field_2F6)
|
|
{
|
|
pProcessControlKeys = GameGetInternalKeys();
|
|
pProcessControlKeys->wKeys1[14] = 0;
|
|
pProcessControlKeys->wKeys2[14] = 0;
|
|
}
|
|
|
|
if(pGame->FindPlayerPed()->field_2F8)
|
|
{
|
|
pProcessControlKeys = GameGetInternalKeys();
|
|
pProcessControlKeys->wKeys1[16] = 0;
|
|
pProcessControlKeys->wKeys2[16] = 0;
|
|
}
|
|
}
|
|
|
|
memcpy((void *)0x6884C4, PedHeadingCode1, 6);
|
|
memcpy((void *)0x688200, PedHeadingCode2, 6);
|
|
|
|
_asm mov ecx, dwProcessControlPed
|
|
_asm mov edx, 0x60EA90
|
|
_asm call edx
|
|
|
|
memset((void *)0x6884C4, 0x90, 6);
|
|
memset((void *)0x688200, 0x90, 6);
|
|
}
|
|
|
|
_asm popad
|
|
_asm retn
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
MATRIX4X4 unnamed_10150A48; // ped matrix saved across ProcessControl
|
|
float unnamed_10150C1C;
|
|
float unnamed_10150C20;
|
|
float unnamed_10150C24;
|
|
|
|
NUDE CCivillianPed__ProcessControl_Hook()
|
|
{
|
|
_asm mov dwProcessControlPed, ecx
|
|
_asm pushad
|
|
|
|
_pProcessControlPed = (PED_TYPE *)dwProcessControlPed;
|
|
|
|
// hold attached/frozen peds still while the game processes them
|
|
if((_pProcessControlPed->entity.dwPhysFlags & 0x40000) &&
|
|
(_pProcessControlPed->entity.dwPhysFlags & 0x800000) &&
|
|
(_pProcessControlPed->entity.dwPhysFlags & 0x200000))
|
|
{
|
|
_pProcessControlPed->entity.vecMoveSpeed.X = 0.0f;
|
|
_pProcessControlPed->entity.vecMoveSpeed.Y = 0.0f;
|
|
}
|
|
|
|
if(_pProcessControlPed->entity.mat)
|
|
{
|
|
unnamed_10150A48 = *_pProcessControlPed->entity.mat;
|
|
unnamed_10150C1C = _pProcessControlPed->entity.vecMoveSpeed.X;
|
|
unnamed_10150C20 = _pProcessControlPed->entity.vecMoveSpeed.Y;
|
|
unnamed_10150C24 = _pProcessControlPed->entity.vecMoveSpeed.Z;
|
|
}
|
|
|
|
_asm mov ecx, dwProcessControlPed
|
|
_asm mov edx, 0x5DDBF0 ;// CCivilianPed::ProcessControl
|
|
_asm call edx
|
|
|
|
if((_pProcessControlPed->entity.dwPhysFlags & 0x40000) &&
|
|
(_pProcessControlPed->entity.dwPhysFlags & 0x800000) &&
|
|
(_pProcessControlPed->entity.dwPhysFlags & 0x200000))
|
|
{
|
|
if(_pProcessControlPed->entity.mat)
|
|
{
|
|
_pProcessControlPed->entity.mat->pos.X = unnamed_10150A48.pos.X;
|
|
_pProcessControlPed->entity.mat->pos.Y = unnamed_10150A48.pos.Y;
|
|
_pProcessControlPed->entity.mat->pos.Z = unnamed_10150A48.pos.Z;
|
|
}
|
|
|
|
_pProcessControlPed->entity.vecMoveSpeed.X = 0.0f;
|
|
_pProcessControlPed->entity.vecMoveSpeed.Y = 0.0f;
|
|
}
|
|
|
|
_asm popad
|
|
_asm retn
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
WORD unnamed_10150730;
|
|
BYTE unnamed_10150BC0;
|
|
DWORD unnamed_1015168C;
|
|
|
|
NUDE TaskUseGun_Hook()
|
|
{
|
|
_asm mov unnamed_10151628, ecx
|
|
_asm mov eax, [esp+4]
|
|
_asm mov dwProcessControlPed, eax
|
|
|
|
byteSavedCurrentPlayer = *pbyteCurrentPlayer;
|
|
byteProcessControlPlayerID = FindPlayerNumFromPedPtr(dwProcessControlPed);
|
|
|
|
if(dwProcessControlPed && byteProcessControlPlayerID && !byteSavedCurrentPlayer)
|
|
{
|
|
// run the task with the remote player's keys, camera and skills in place
|
|
GameStoreLocalPlayerKeys();
|
|
GameSetRemotePlayerKeys(byteProcessControlPlayerID);
|
|
|
|
unnamed_10150BC0 = *pbyteCameraMode;
|
|
*pbyteCameraMode = GameGetPlayerCameraMode(byteProcessControlPlayerID);
|
|
|
|
unnamed_10150730 = *wCameraMode2;
|
|
*wCameraMode2 = GameGetPlayerCameraMode(byteProcessControlPlayerID);
|
|
if(*wCameraMode2 == 4) *wCameraMode2 = 0;
|
|
|
|
GameStoreLocalPlayerCameraExtZoom();
|
|
GameSetRemotePlayerCameraExtZoom(byteProcessControlPlayerID);
|
|
|
|
GameStoreLocalPlayerAim();
|
|
GameSetRemotePlayerAim(byteProcessControlPlayerID);
|
|
|
|
GameStoreLocalPlayerWeaponSkills();
|
|
GameSetRemotePlayerWeaponSkills(byteProcessControlPlayerID);
|
|
|
|
*pbyteCurrentPlayer = byteProcessControlPlayerID;
|
|
|
|
_asm mov ecx, unnamed_10151628
|
|
_asm push dwProcessControlPed
|
|
_asm mov eax, 0x624ED0 ;// CTaskSimpleUseGun::ProcessPed
|
|
_asm call eax
|
|
|
|
*pbyteCameraMode = unnamed_10150BC0;
|
|
*wCameraMode2 = unnamed_10150730;
|
|
|
|
GameSetLocalPlayerWeaponSkills();
|
|
GameSetLocalPlayerCameraExtZoom();
|
|
*pbyteCurrentPlayer = 0;
|
|
GameSetLocalPlayerAim();
|
|
GameSetLocalPlayerKeys();
|
|
}
|
|
else
|
|
{
|
|
unnamed_1015168C = 1;
|
|
|
|
_asm mov ecx, unnamed_10151628
|
|
_asm push dwProcessControlPed
|
|
_asm mov eax, 0x624ED0
|
|
_asm call eax
|
|
|
|
unnamed_1015168C = 0;
|
|
}
|
|
|
|
_asm retn 4
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
DWORD unnamed_10151684;
|
|
DWORD unnamed_10151688;
|
|
|
|
NUDE WeaponRender__GetWeaponSkill_Hook()
|
|
{
|
|
_asm mov dwProcessControlPed, ecx
|
|
|
|
_pProcessControlPed = (PED_TYPE *)dwProcessControlPed;
|
|
byteSavedCurrentPlayer = *pbyteCurrentPlayer;
|
|
byteProcessControlPlayerID = FindPlayerNumFromPedPtr(dwProcessControlPed);
|
|
|
|
if(dwProcessControlPed && byteProcessControlPlayerID && !byteSavedCurrentPlayer)
|
|
{
|
|
// render a remote player with his own skill level
|
|
GameStoreLocalPlayerWeaponSkills();
|
|
GameSetRemotePlayerWeaponSkills(byteProcessControlPlayerID);
|
|
unnamed_10151688 = 1;
|
|
}
|
|
|
|
_asm mov ecx, dwProcessControlPed
|
|
_asm movsx eax, byte ptr [ecx+0x718]
|
|
_asm imul eax, 0x1C
|
|
_asm mov eax, [eax+ecx+0x5A0]
|
|
_asm push eax
|
|
_asm mov edx, 0x5E3B60 ;// CPed::GetWeaponSkill
|
|
_asm call edx
|
|
_asm mov unnamed_10151684, eax
|
|
|
|
if(unnamed_10151688)
|
|
{
|
|
GameSetLocalPlayerWeaponSkills();
|
|
unnamed_10151688 = 0;
|
|
}
|
|
|
|
_asm mov eax, unnamed_10151684
|
|
_asm retn
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
DWORD dwAttachedEntitiesPlayer;
|
|
CRemotePlayer *pAttachedEntitiesRemotePlayer;
|
|
|
|
void FUNC_10014650(); // .text:10014650
|
|
|
|
NUDE CWorld__ProcessAttachedEntities_Hook()
|
|
{
|
|
__asm
|
|
{
|
|
// call original CWorld::ProcessAttachedEntities
|
|
mov edx, 0x5647F0
|
|
call edx
|
|
|
|
pushad
|
|
}
|
|
|
|
if(pNetGame)
|
|
{
|
|
if(pNetGame->GetPlayerPool())
|
|
pNetGame->GetPlayerPool()->m_pLocalPlayer->FUNC_10003570();
|
|
|
|
if(pNetGame && pNetGame->GetPlayerPool())
|
|
{
|
|
for(dwAttachedEntitiesPlayer = 0; dwAttachedEntitiesPlayer != MAX_PLAYERS; dwAttachedEntitiesPlayer++)
|
|
{
|
|
// GetAt's bound check and body, written out; the PLAYERID cast is what truncates to a word
|
|
PLAYERID playerId = (PLAYERID)dwAttachedEntitiesPlayer;
|
|
if(playerId < MAX_PLAYERS)
|
|
{
|
|
if(pNetGame->GetPlayerPool()->field_2A[playerId])
|
|
{
|
|
CNetPlayer *pNetPlayer = pNetGame->GetPlayerPool()->m_pPlayers[playerId];
|
|
CRemotePlayer *pRemotePlayer;
|
|
|
|
if(pNetPlayer) pRemotePlayer = pNetPlayer->m_pRemotePlayer;
|
|
else pRemotePlayer = NULL;
|
|
|
|
pAttachedEntitiesRemotePlayer = pRemotePlayer;
|
|
|
|
if(pRemotePlayer && pRemotePlayer->m_pPlayerPed && pRemotePlayer->field_10A)
|
|
{
|
|
FUNC_10014650();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
__asm
|
|
{
|
|
popad
|
|
retn
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE CWorld__ProcessPedsAfterPreRender_Hook()
|
|
{
|
|
__asm
|
|
{
|
|
// call original CWorld::ProcessPedsAfterPreRender
|
|
mov edx, 0x563430
|
|
call edx
|
|
|
|
pushad
|
|
}
|
|
|
|
if (pNetGame && pNetGame->GetPlayerPool())
|
|
pNetGame->GetPlayerPool()->FUNC_10013960();
|
|
|
|
__asm
|
|
{
|
|
popad
|
|
retn
|
|
}}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
DWORD unnamed_10150978; // original ProcessControl of the vehicle class
|
|
float unnamed_10150A34;
|
|
VEHICLE_TYPE *unnamed_10150A38;
|
|
BYTE unnamed_10150AA0;
|
|
DWORD unnamed_10150BBC; // vtable of the vehicle being processed
|
|
DWORD unnamed_10150C88;
|
|
DWORD unnamed_10151690;
|
|
|
|
NUDE AllVehicles_ProcessControl_Hook()
|
|
{
|
|
_asm mov unnamed_10150A38, ecx
|
|
_asm mov eax, [ecx]
|
|
_asm mov unnamed_10150BBC, eax
|
|
_asm pushad
|
|
|
|
if(unnamed_10150BBC == 0x871120) unnamed_10150978 = 0x6B1880; // CAutomobile
|
|
else if(unnamed_10150BBC == 0x8721A0) unnamed_10150978 = 0x6F1770; // CBoat
|
|
else if(unnamed_10150BBC == 0x871360) unnamed_10150978 = 0x6B9250; // CBike
|
|
else if(unnamed_10150BBC == 0x871948) unnamed_10150978 = 0x6C9260; // CPlane
|
|
else if(unnamed_10150BBC == 0x871680) unnamed_10150978 = 0x6C7050; // CHeli
|
|
else if(unnamed_10150BBC == 0x871528) unnamed_10150978 = 0x6BFA30; // CBmx
|
|
else if(unnamed_10150BBC == 0x8717D8) unnamed_10150978 = 0x6C8250; // CMonsterTruck
|
|
else if(unnamed_10150BBC == 0x871AE8) unnamed_10150978 = 0x6CDCC0; // CQuadBike
|
|
else if(unnamed_10150BBC == 0x872370) unnamed_10150978 = 0x6F86A0; // CTrain
|
|
else if(unnamed_10150BBC == 0x871C28) unnamed_10150978 = 0x6CED20; // CTrailer
|
|
|
|
byteSavedCurrentPlayer = *(BYTE *)0xB7CD74;
|
|
|
|
PED_TYPE *pDriver;
|
|
pDriver = unnamed_10150A38->pDriver;
|
|
|
|
// a remote player drives it, run the class ProcessControl with his keys and aim
|
|
if(unnamed_10150A38->pDriver && pDriver->dwPedType == 0 &&
|
|
pDriver != GamePool_FindPlayerPed() && byteSavedCurrentPlayer == 0)
|
|
{
|
|
byteProcessControlPlayerID = FindPlayerNumFromPedPtr((DWORD)pDriver);
|
|
|
|
GameStoreLocalPlayerKeys();
|
|
GameSetRemotePlayerKeys(byteProcessControlPlayerID);
|
|
|
|
unnamed_10150BC0 = *pbyteCameraMode;
|
|
*pbyteCameraMode = GameGetPlayerCameraMode(byteProcessControlPlayerID);
|
|
unnamed_10150730 = *wCameraMode2;
|
|
*wCameraMode2 = GameGetPlayerCameraMode(byteProcessControlPlayerID);
|
|
if(*wCameraMode2 == 4) *wCameraMode2 = 0;
|
|
|
|
GameStoreLocalPlayerAim();
|
|
GameSetRemotePlayerAim(byteProcessControlPlayerID);
|
|
|
|
if((unnamed_10150A38->byteFlags & 0x10) == 0)
|
|
{
|
|
if(unnamed_10150BBC == 0x871680) unnamed_10150A38->entity.nControlFlags |= 0x20;
|
|
|
|
pProcessControlKeys = GameGetInternalKeys();
|
|
pProcessControlKeys->wKeys1[14] = 0;
|
|
pProcessControlKeys->wKeys2[14] = 0;
|
|
pProcessControlKeys->wKeys1[16] = 0;
|
|
pProcessControlKeys->wKeys2[16] = 0;
|
|
} else {
|
|
unnamed_10150A38->entity.nControlFlags &= 0xDF;
|
|
}
|
|
|
|
unnamed_10150C88 = *(DWORD *)((BYTE *)unnamed_10150A38 + 0x648);
|
|
*(DWORD *)&unnamed_10150A34 = *(DWORD *)((BYTE *)unnamed_10150A38 + 0x64C);
|
|
|
|
// let the game process it as a civillian driven vehicle
|
|
*pbyteCurrentPlayer = 0;
|
|
unnamed_10150A38->pDriver->dwPedType = 4;
|
|
unnamed_10150AA0 = unnamed_10150A38->entity.nControlFlags;
|
|
unnamed_10150A38->entity.nControlFlags = 0x1A;
|
|
|
|
_asm mov edx, unnamed_10150A38
|
|
_asm lea ecx, [edx+0x138]
|
|
_asm mov edx, 0x502280
|
|
_asm call edx
|
|
|
|
unnamed_10150A38->entity.nControlFlags = unnamed_10150AA0;
|
|
unnamed_10150A38->pDriver->dwPedType = 0;
|
|
*pbyteCurrentPlayer = byteProcessControlPlayerID;
|
|
|
|
MATRIX4X4 *pMatrix = unnamed_10150A38->entity.mat;
|
|
if(pMatrix)
|
|
{
|
|
unnamed_10150A48 = *pMatrix;
|
|
*(DWORD *)&unnamed_10150C1C = *(DWORD *)&unnamed_10150A38->entity.vecMoveSpeed.X;
|
|
*(DWORD *)&unnamed_10150C20 = *(DWORD *)&unnamed_10150A38->entity.vecMoveSpeed.Y;
|
|
*(DWORD *)&unnamed_10150C24 = *(DWORD *)&unnamed_10150A38->entity.vecMoveSpeed.Z;
|
|
}
|
|
|
|
_asm mov ecx, unnamed_10150A38
|
|
_asm mov eax, unnamed_10150978
|
|
_asm call eax
|
|
|
|
if(unnamed_10150A38->entity.mat && !FUNC_100B6950(unnamed_10150A38) &&
|
|
!IsATrainPart(&unnamed_10150A38->entity))
|
|
{
|
|
// keep the height and vertical speed the server gave us
|
|
*(DWORD *)&unnamed_10150A38->entity.mat->pos.Z = *(DWORD *)&unnamed_10150A48.pos.Z;
|
|
unnamed_10150A38->entity.vecMoveSpeed.Z = unnamed_10150C24;
|
|
}
|
|
else if(unnamed_10150A38->entity.mat && (unnamed_10150978 == 0x6F1770 ||
|
|
unnamed_10150978 == 0x6C9260 || unnamed_10150978 == 0x6C7050))
|
|
{
|
|
*(DWORD *)&unnamed_10150A38->entity.mat->pos.Z = *(DWORD *)&unnamed_10150A48.pos.Z;
|
|
unnamed_10150A38->entity.vecMoveSpeed.Z = unnamed_10150C24;
|
|
}
|
|
|
|
if(unnamed_10150978 == 0x6BFA30 || unnamed_10150978 == 0x6B9250)
|
|
{
|
|
// bikes, ease the lean angle half way back to the synced one
|
|
*(DWORD *)((BYTE *)unnamed_10150A38 + 0x648) = unnamed_10150C88;
|
|
*(float *)((BYTE *)unnamed_10150A38 + 0x64C) = unnamed_10150A34;
|
|
|
|
if(*(float *)((BYTE *)unnamed_10150A38 + 0x64C) > *(float *)((BYTE *)unnamed_10150A38 + 0x648))
|
|
{
|
|
*(float *)((BYTE *)unnamed_10150A38 + 0x648) = (*(float *)((BYTE *)unnamed_10150A38 + 0x64C) -
|
|
*(float *)((BYTE *)unnamed_10150A38 + 0x648)) * 0.5f + *(float *)((BYTE *)unnamed_10150A38 + 0x648);
|
|
}
|
|
else if(*(float *)((BYTE *)unnamed_10150A38 + 0x64C) < *(float *)((BYTE *)unnamed_10150A38 + 0x648))
|
|
{
|
|
*(float *)((BYTE *)unnamed_10150A38 + 0x648) = *(float *)((BYTE *)unnamed_10150A38 + 0x648) -
|
|
(*(float *)((BYTE *)unnamed_10150A38 + 0x648) - *(float *)((BYTE *)unnamed_10150A38 + 0x64C)) * 0.5f;
|
|
}
|
|
}
|
|
|
|
*pbyteCurrentPlayer = 0;
|
|
GameSetLocalPlayerKeys();
|
|
*pbyteCameraMode = unnamed_10150BC0;
|
|
*wCameraMode2 = unnamed_10150730;
|
|
GameSetLocalPlayerAim();
|
|
|
|
_asm popad
|
|
_asm retn
|
|
}
|
|
else if(pDriver && pDriver->dwPedType == 0 &&
|
|
unnamed_10150A38->pDriver == GamePool_FindPlayerPed())
|
|
{
|
|
if((unnamed_10150A38->byteFlags & 0x10) == 0)
|
|
{
|
|
if(unnamed_10150BBC == 0x871680) unnamed_10150A38->entity.nControlFlags |= 0x20;
|
|
|
|
unnamed_10151690 = 1;
|
|
GameStoreLocalPlayerKeys();
|
|
|
|
pProcessControlKeys = GameGetInternalKeys();
|
|
pProcessControlKeys->wKeys1[14] = 0;
|
|
pProcessControlKeys->wKeys2[14] = 0;
|
|
pProcessControlKeys->wKeys1[16] = 0;
|
|
pProcessControlKeys->wKeys2[16] = 0;
|
|
} else {
|
|
unnamed_10150A38->entity.nControlFlags &= 0xDF;
|
|
}
|
|
|
|
_asm mov edx, unnamed_10150A38
|
|
_asm lea ecx, [edx+0x138]
|
|
_asm mov edx, 0x502280
|
|
_asm call edx
|
|
|
|
_asm mov ecx, unnamed_10150A38
|
|
_asm mov eax, unnamed_10150978
|
|
_asm call eax
|
|
|
|
if(unnamed_10151690)
|
|
{
|
|
unnamed_10151690 = 0;
|
|
GameSetLocalPlayerKeys();
|
|
}
|
|
|
|
_asm popad
|
|
_asm retn
|
|
}
|
|
else
|
|
{
|
|
if(FUNC_100B4860(unnamed_10150A38) || IsATrainPart(&unnamed_10150A38->entity) ||
|
|
FUNC_100B6950(unnamed_10150A38))
|
|
{
|
|
MATRIX4X4 *pMatrix = unnamed_10150A38->entity.mat;
|
|
if(pMatrix)
|
|
{
|
|
unnamed_10150A48 = *pMatrix;
|
|
*(DWORD *)&unnamed_10150C1C = *(DWORD *)&unnamed_10150A38->entity.vecMoveSpeed.X;
|
|
*(DWORD *)&unnamed_10150C20 = *(DWORD *)&unnamed_10150A38->entity.vecMoveSpeed.Y;
|
|
*(DWORD *)&unnamed_10150C24 = *(DWORD *)&unnamed_10150A38->entity.vecMoveSpeed.Z;
|
|
}
|
|
|
|
_asm mov edx, unnamed_10150A38
|
|
_asm lea ecx, [edx+0x138]
|
|
_asm mov edx, 0x502280
|
|
_asm call edx
|
|
|
|
_asm mov ecx, unnamed_10150A38
|
|
_asm mov eax, unnamed_10150978
|
|
_asm call eax
|
|
}
|
|
|
|
_asm popad
|
|
_asm retn
|
|
}
|
|
|
|
_asm popad
|
|
_asm retn
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
// fix horn processing
|
|
|
|
VEHICLE_TYPE *_pHornVehicle;
|
|
int _iHasSetHornHookFix = 0;
|
|
BYTE _byteSavedControlFlags = 0;
|
|
DWORD _dwVehicleParams = 0;
|
|
DWORD _dwAudioClass = 0;
|
|
|
|
NUDE VehicleHorn_Hook()
|
|
{
|
|
_asm mov _dwAudioClass, ecx
|
|
|
|
_asm mov edx, [esp+4]
|
|
_asm mov _dwVehicleParams, edx
|
|
|
|
_asm mov eax, [edx+16]
|
|
_asm mov _pHornVehicle, eax
|
|
|
|
_byteSavedControlFlags = _pHornVehicle->entity.nControlFlags;
|
|
|
|
if( _pHornVehicle->pDriver &&
|
|
IN_VEHICLE(_pHornVehicle->pDriver) )
|
|
{
|
|
_pHornVehicle->entity.nControlFlags = 0x02;
|
|
//_iHasSetHornHookFix = 1;
|
|
} else {
|
|
_pHornVehicle->entity.nControlFlags = 0x22;
|
|
//_iHasSetHornHookFix = 0;
|
|
}
|
|
|
|
_asm push _dwVehicleParams
|
|
_asm mov ecx, _dwAudioClass
|
|
_asm mov edx, 0x5002C0
|
|
_asm call edx
|
|
|
|
_pHornVehicle->entity.nControlFlags = _byteSavedControlFlags;
|
|
|
|
_asm retn 4
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
DWORD dwSayParam1;
|
|
DWORD dwSayParam2;
|
|
float fSayParam3;
|
|
DWORD dwSayParam4;
|
|
DWORD dwSayParam5;
|
|
DWORD dwSayParam6;
|
|
|
|
NUDE CPed_Say_Hook()
|
|
{
|
|
_asm mov eax, [esp+4]
|
|
_asm mov dwSayParam1, eax
|
|
_asm mov eax, [esp+8]
|
|
_asm mov dwSayParam2, eax
|
|
_asm mov eax, [esp+12]
|
|
_asm mov fSayParam3, eax
|
|
_asm mov eax, [esp+16]
|
|
_asm mov dwSayParam4, eax
|
|
_asm mov eax, [esp+20]
|
|
_asm mov dwSayParam5, eax
|
|
_asm mov eax, [esp+24]
|
|
_asm mov dwSayParam6, eax
|
|
|
|
_asm pushad
|
|
|
|
if(dwSayParam1 != 45) {
|
|
if(pChatWindow) pChatWindow->AddDebugMessage("CPed::Say(%u,%u,%f,%u,%u,%u)",
|
|
dwSayParam1,dwSayParam2,fSayParam3,dwSayParam4,dwSayParam5,dwSayParam6);
|
|
}
|
|
|
|
_asm popad
|
|
|
|
_asm mov eax, [esp+4]
|
|
_asm test ax, ax
|
|
_asm mov edx, 0x5EFFE7
|
|
_asm jmp edx
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE ZoneOverlay_Hook()
|
|
{
|
|
_asm pushad
|
|
if (pNetGame && pNetGame->GetGangZonePool()) pNetGame->GetGangZonePool()->Draw();
|
|
_asm popad
|
|
_asm ret
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE PlayerWalk_Hook()
|
|
{
|
|
_asm pushad
|
|
|
|
if (pNetGame && pNetGame->GetWalkStyle())
|
|
{
|
|
_asm popad
|
|
_asm mov [esi + 0x4D4], eax
|
|
}
|
|
else
|
|
{
|
|
_asm popad
|
|
}
|
|
_asm ret
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE PickUpPickup_Hook()
|
|
{
|
|
_asm mov unnamed_10150960, esi
|
|
_asm pushad
|
|
|
|
if (pNetGame && pNetGame->GetPickupPool())
|
|
pNetGame->GetPickupPool()->sub_10013440((unnamed_10150960 - 0x9788C0) >> 5);
|
|
|
|
_asm popad
|
|
_asm mov al, [esi+0x1C]
|
|
_asm cmp al, 6
|
|
_asm push 0x4579CB
|
|
_asm ret
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE CWeapon_FireCamera_Hook()
|
|
{
|
|
_asm mov ebx, [esp+8]
|
|
_asm mov dwCurPlayerActor, ebx
|
|
_asm pushad
|
|
|
|
if (dwCurPlayerActor == (DWORD)GamePool_FindPlayerPed()) {
|
|
*(BYTE*)0xC8A7C0 = 1;
|
|
*(BYTE*)0xC8A7C1 = 1;
|
|
}
|
|
|
|
_asm popad
|
|
_asm mov ebx, 0x73C260
|
|
_asm jmp ebx
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE CCameraCamShake_Sniper_Hook()
|
|
{
|
|
_asm ret
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE CTrain_ProcessControl_Derailment()
|
|
{
|
|
_asm {
|
|
mov eax, [esi+1444]; // get the speed
|
|
and eax, 0x80000000; // get the upper bit
|
|
or eax, 0x3F800000; // or it with 1.0f (it'll be -ve if bit is set)
|
|
mov [esi+1444], eax; // set the new speed
|
|
ret;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
int FUNC_100A36C0(); // todo: implement `FUNC_100A36C0`
|
|
|
|
DWORD dwEnterExitVehicle;
|
|
|
|
NUDE TaskEnterVehicleDriver_Hook()
|
|
{
|
|
_asm mov eax, [esp]
|
|
_asm mov dwHookRetnAddr, eax
|
|
_asm mov eax, [esp+4]
|
|
_asm mov dwEnterExitVehicle, eax
|
|
_asm pushad
|
|
|
|
if((dwHookRetnAddr == 0x570A20 || dwHookRetnAddr == 0x570A99) && !FUNC_100A36C0())
|
|
{
|
|
_asm
|
|
{
|
|
popad
|
|
|
|
// kill the task, we're not letting them in
|
|
mov ebx, [ecx]
|
|
test ebx, ebx
|
|
jz noTaskDelete
|
|
push 1
|
|
call dword ptr [ebx]
|
|
noTaskDelete:
|
|
pop eax
|
|
pop eax
|
|
mov eax, 0x570A9E
|
|
jmp eax
|
|
}
|
|
}
|
|
|
|
_asm popad
|
|
_asm mov eax, [esp+4]
|
|
_asm push esi
|
|
_asm push 0
|
|
_asm mov ebx, 0x6402F7
|
|
_asm jmp ebx
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
DWORD dwExitTaskThis;
|
|
DWORD dwPutOutOfVehicle = 0xFFFFFFFF;
|
|
CVehiclePool *pExitVehiclePool;
|
|
WORD wExitVehicleID;
|
|
CVehicle *pExitVehicle;
|
|
CLocalPlayer *pExitLocalPlayer;
|
|
MATRIX4X4 matExitVehicle;
|
|
|
|
NUDE TaskExitVehicle()
|
|
{
|
|
_asm mov ebp, esp
|
|
_asm mov dwExitTaskThis, ecx
|
|
_asm mov eax, [ebp]
|
|
_asm mov dwHookRetnAddr, eax
|
|
_asm mov eax, [ebp+4]
|
|
_asm mov dwEnterExitVehicle, eax
|
|
|
|
dwPutOutOfVehicle = 0xFFFFFFFF;
|
|
|
|
if(!bIgnoreNextExit &&
|
|
(dwHookRetnAddr == 0x5704A1 || dwHookRetnAddr == 0x5703FC))
|
|
{
|
|
if(pNetGame)
|
|
{
|
|
if(GamePool_FindPlayerPed()->pVehicle == dwEnterExitVehicle)
|
|
{
|
|
pExitVehiclePool = pNetGame->GetVehiclePool();
|
|
wExitVehicleID = pExitVehiclePool->FUNC_1001EB90((int)GamePool_FindPlayerPed()->pVehicle);
|
|
|
|
if(wExitVehicleID != 0xFFFF)
|
|
{
|
|
pExitVehicle = (CVehicle *)pExitVehiclePool->FUNC_10001120(wExitVehicleID);
|
|
pExitLocalPlayer = pNetGame->GetPlayerPool()->GetLocalPlayer();
|
|
|
|
if(pExitVehicle && pExitLocalPlayer)
|
|
{
|
|
if(pExitVehicle->IsATrainPart())
|
|
{
|
|
// exiting a train part normally doesn't work, dump them next to it
|
|
dwPutOutOfVehicle = 1;
|
|
pExitVehicle->GetMatrix(&matExitVehicle);
|
|
pExitLocalPlayer->GetPlayerPed()->RemoveFromVehicleAndPutAt(
|
|
matExitVehicle.pos.X + 2.5f,
|
|
matExitVehicle.pos.Y + 2.5f,
|
|
matExitVehicle.pos.Z);
|
|
}
|
|
else
|
|
{
|
|
pExitLocalPlayer->FUNC_10005BF0(wExitVehicleID);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bIgnoreNextExit = FALSE;
|
|
}
|
|
|
|
_asm push dwPutOutOfVehicle
|
|
_asm push 0x841618
|
|
_asm mov ecx, dwExitTaskThis
|
|
_asm mov edx, 0x63B8C0
|
|
_asm add edx, 7
|
|
_asm jmp edx
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE AddVehicleHook()
|
|
{
|
|
_asm pushad
|
|
|
|
if(!bAllowVehicleCreation) {
|
|
_asm popad
|
|
_asm xor eax, eax
|
|
_asm ret
|
|
}
|
|
|
|
_asm popad
|
|
_asm mov eax, 0x421446
|
|
_asm jmp eax
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
// disable cheat code processing
|
|
NUDE CheatProcessorHook()
|
|
{
|
|
__asm
|
|
{
|
|
mov dwSavedCheatFn, eax
|
|
pushad
|
|
|
|
// CCheat::m_bHasPlayerCheated = true
|
|
mov edx, 0x96918C
|
|
mov byte ptr [edx], 1
|
|
|
|
popad
|
|
|
|
// dont process cheat
|
|
mov edx, 0x438581
|
|
cmp eax, 0
|
|
jmp edx
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE RadarTranslateColor()
|
|
{
|
|
_asm mov eax, [esp+4]
|
|
_asm mov iRadarColor1, eax
|
|
TranslateColorCodeToRGBA(iRadarColor1); // return will still be in eax.
|
|
_asm ret
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE SetFarClipHook()
|
|
{
|
|
_asm fld fFarClip
|
|
_asm push esi
|
|
_asm mov esi, [esp+8]
|
|
_asm mov edx, dwFarClipReturnAddr
|
|
_asm jmp edx
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
// We use this to trap and exit the game
|
|
|
|
DWORD dwShutDownTick;
|
|
void QuitGame(); // todo: implement `QuitGame`
|
|
|
|
NUDE CGameShutdownHook()
|
|
{
|
|
dwShutDownTick = GetTickCount() + 2000;
|
|
QuitGame();
|
|
|
|
while(GetTickCount() < dwShutDownTick) {
|
|
Sleep(100);
|
|
}
|
|
|
|
ExitProcess(0);
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
DWORD unnamed_101516A0; // CEventDamage *
|
|
DWORD unnamed_101516A4; // CPed * taking the damage
|
|
|
|
int __stdcall FUNC_100A3BB0(DWORD *pEventDamage, PED_TYPE *pPed); // todo: implement `FUNC_100A3BB0`
|
|
|
|
// maps a ped pointer to a player id, falling back to the driver of the vehicle it is in
|
|
PLAYERID FUNC_100A3AE0(DWORD dwPed)
|
|
{
|
|
if(!dwPed) return 0xFFFF;
|
|
|
|
PLAYERID playerId;
|
|
CPlayerPool *pPlayerPool = pNetGame->GetPlayerPool();
|
|
|
|
playerId = pPlayerPool->FUNC_100138C0(dwPed);
|
|
|
|
if(playerId == 0xFFFF)
|
|
{
|
|
VEHICLEID vehicleId = pNetGame->GetVehiclePool()->FUNC_1001EB90(dwPed);
|
|
|
|
if(vehicleId != 0xFFFF)
|
|
{
|
|
int iHighestId = pPlayerPool->field_2F3A;
|
|
|
|
for(int i = 0; i <= iHighestId; i++)
|
|
{
|
|
PLAYERID id = (PLAYERID)i;
|
|
|
|
if(id < MAX_PLAYERS && pPlayerPool->field_2A[id])
|
|
{
|
|
CNetPlayer *pNetPlayer = pPlayerPool->m_pPlayers[id];
|
|
CRemotePlayer *pRemotePlayer;
|
|
|
|
if(pNetPlayer) pRemotePlayer = pNetPlayer->m_pRemotePlayer;
|
|
else pRemotePlayer = NULL;
|
|
|
|
// no null check, same as retail
|
|
if(pRemotePlayer->field_1E7 == vehicleId)
|
|
{
|
|
playerId = id;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return playerId;
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
// maps a ped pointer to the actor that owns it
|
|
ACTORID FUNC_100A3B80(DWORD dwPed)
|
|
{
|
|
if(!dwPed) return 0xFFFF;
|
|
return pNetGame->GetActorPool()->FUNC_100018B0(dwPed);
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
// 0x100A3BB0 : decides whether a ped damage event gets reported to the server
|
|
BOOL __stdcall FUNC_100A3BB0(DWORD *pEvent, PED_TYPE *pPed)
|
|
{
|
|
PED_TYPE *pPlayerPed = GamePool_FindPlayerPed();
|
|
bool bLocalTarget = false;
|
|
|
|
if(!pNetGame) return FALSE;
|
|
|
|
if((PED_TYPE *)pEvent[0] != pPlayerPed && pPed && *(DWORD *)pPed == 0x86C0A8) return TRUE;
|
|
|
|
if(pPed != pPlayerPed)
|
|
{
|
|
if((PED_TYPE *)pEvent[0] != pPlayerPed) return FALSE;
|
|
}
|
|
else bLocalTarget = true;
|
|
|
|
CPlayerPool *pPlayerPool = pNetGame->GetPlayerPool();
|
|
PLAYERID playerId;
|
|
|
|
if(bLocalTarget)
|
|
{
|
|
DWORD dwTask = pPlayerPool->m_pLocalPlayer->field_2DA;
|
|
|
|
if(dwTask)
|
|
{
|
|
if(*(DWORD *)(dwTask + 0x40) == pEvent[0]) return TRUE;
|
|
if(pEvent[3] == 0x36) return TRUE;
|
|
}
|
|
|
|
playerId = FUNC_100A3AE0(pEvent[0]);
|
|
pPlayerPool->m_pLocalPlayer->FUNC_100068A0(playerId, *(float *)&pEvent[1], pEvent[3], pEvent[2]);
|
|
}
|
|
else
|
|
{
|
|
playerId = FUNC_100A3AE0((DWORD)pPed);
|
|
|
|
if(playerId != 0xFFFF)
|
|
{
|
|
pPlayerPool->m_pLocalPlayer->FUNC_100069B0(playerId, *(float *)&pEvent[1], pEvent[3], pEvent[2]);
|
|
|
|
if(pPlayerPool->GetAt(playerId)->field_10C) return TRUE;
|
|
}
|
|
else
|
|
{
|
|
ACTORID actorId = FUNC_100A3B80((DWORD)pPed);
|
|
|
|
if(actorId != 0xFFFF)
|
|
{
|
|
pPlayerPool->m_pLocalPlayer->FUNC_10006AC0(actorId, *(float *)&pEvent[1], pEvent[3], pEvent[2]);
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(pNetGame->GetSettings()->field_22)
|
|
{
|
|
BYTE byteTeam = pPlayerPool->m_pLocalPlayer->m_byteTeam;
|
|
|
|
if(byteTeam == 0xFF) return FALSE;
|
|
if(playerId == 0xFFFF) return FALSE;
|
|
|
|
if((BYTE)pNetGame->GetPlayerPool()->GetAt(playerId)->field_109 == byteTeam) return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE PedDamage_Hook()
|
|
{
|
|
__asm
|
|
{
|
|
mov eax, fs:0
|
|
test ecx, ecx
|
|
jz computeResponse
|
|
mov unnamed_101516A0, ecx
|
|
mov ebx, [esp+4]
|
|
test ebx, ebx
|
|
jz computeResponse
|
|
mov unnamed_101516A4, ebx
|
|
pushad
|
|
|
|
mov eax, unnamed_101516A4
|
|
push eax
|
|
mov ecx, unnamed_101516A0
|
|
push ecx
|
|
call FUNC_100A3BB0
|
|
test eax, eax
|
|
jz computeResponseAfterSync
|
|
|
|
// the netcode dealt with it, don't let the game apply the damage
|
|
popad
|
|
retn 0Ch
|
|
computeResponseAfterSync:
|
|
popad
|
|
computeResponse:
|
|
mov edx, 0x4B5AC6 ;// CEventDamage::ComputeDamageResponse + 6
|
|
jmp edx
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE AnimCrashFixHook()
|
|
{
|
|
__asm
|
|
{
|
|
push edi
|
|
mov edi, [esp+8] ;// arg0
|
|
test edi, edi
|
|
jz exitFn
|
|
mov eax, 0x4D41C5 ;// CAnimManager::UncompressAnimation
|
|
jmp eax
|
|
exitFn:
|
|
pop edi
|
|
ret
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE SetForegroundWindowCrashFixHook()
|
|
{
|
|
__asm
|
|
{
|
|
mov eax, ds:0xC17054;
|
|
test eax, eax;
|
|
jz exitFn;
|
|
push 0x746929; // return address;
|
|
ret;
|
|
exitFn:
|
|
xor eax, eax;
|
|
ret;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE GenTaskAlloc_Hook()
|
|
{
|
|
_asm mov edi, [esp+4]
|
|
_asm mov dwParam1, edi
|
|
//_asm mov edx, [esp+8]
|
|
//_asm mov dwParam2, edx
|
|
_asm mov dwParamThis, ecx
|
|
|
|
_asm pushad
|
|
_asm mov edx, [edi]
|
|
_asm mov ecx, edi
|
|
_asm call dword ptr [edx+4]
|
|
_asm mov dwParam2, eax
|
|
|
|
//pChatWindow->AddDebugMessage("TaskAlloc: 0x%X, 0x%X, 0x%X",dwParamThis,dwParam1,dwParam2);
|
|
_asm popad
|
|
|
|
_asm mov eax, fs:0
|
|
_asm mov edx, 0x4C3876
|
|
_asm jmp edx
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
// used for correct report message using 100A1790 ; void __thiscall CGame::PlayCrimeReport
|
|
|
|
NUDE PoliceScannerAudio_FindPlayerPed_Hook()
|
|
{
|
|
__asm
|
|
{
|
|
mov eax, offset pedCrimeReportTemp
|
|
retn
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
// delete satchel projectile if the owner is dead (not sure if this code will work properly)
|
|
|
|
DWORD dwProjectileObject = 0;
|
|
DWORD dwProjectileInfo = 0;
|
|
NUDE CProjectile_Update_Hook()
|
|
{
|
|
__asm
|
|
{
|
|
mov dwProjectileObject, esi
|
|
mov dwProjectileInfo, ebx
|
|
|
|
pushad
|
|
|
|
mov eax, dwProjectileInfo
|
|
mov ecx, [eax+4] ;// dwProjectileInfo->pOwner
|
|
test ecx, ecx //
|
|
jnz dont_delete // if the owner == nullptr, delete the projectile
|
|
|
|
// delete projectile CProjectileInfo::RemoveIfThisIsAProjectile
|
|
push dwProjectileObject
|
|
mov eax, 0x739A40
|
|
call eax
|
|
|
|
// correct stack
|
|
add esp, 4
|
|
|
|
popad
|
|
|
|
mov dl, 0x0FF
|
|
jmp end_hook
|
|
|
|
dont_delete:
|
|
popad
|
|
|
|
// original code
|
|
mov ecx, [ebx+4]
|
|
mov dl, [ecx+36h]
|
|
|
|
end_hook:
|
|
push 0x738F40
|
|
retn
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE CWeapon__Satchel__Activate_Hook()
|
|
{
|
|
__asm
|
|
{
|
|
CMP DWORD PTR DS:[ESI-0x20], 0x27
|
|
MOV EDI, DWORD PTR SS:[EBP]
|
|
JNZ skip
|
|
MOV EAX, [ESP]
|
|
CMP DWORD PTR DS:[ESI-0x1C], EAX
|
|
JNZ skip
|
|
MOV EAX, 0x738880
|
|
JMP EAX
|
|
|
|
skip:
|
|
MOV EAX, 0x7388DB
|
|
JMP EAX
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE PathProcessingCrashFixHook()
|
|
{
|
|
__asm
|
|
{
|
|
push esi
|
|
test ecx, ecx;
|
|
jz exitFn
|
|
mov esi,dword ptr ss:[esp+8]
|
|
mov eax,dword ptr ds:[esi]
|
|
mov edx, 0x63A047;
|
|
jmp edx;
|
|
|
|
exitFn:
|
|
mov esi, 0x63a04d;
|
|
jmp esi;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE SetCarColorCrashFix()
|
|
{
|
|
__asm
|
|
{
|
|
test eax, eax;
|
|
jz exitFn; // CPool_CVehicle_GetAt(scmParam1) == NULL
|
|
mov ecx, 0x47eab8;
|
|
mov cl,byte ptr ds:[0xA43C7C]; // get color1 (was replaced by jmpcode)
|
|
jmp ecx; // continue function
|
|
|
|
exitFn:
|
|
mov esi, 0x47eaca;
|
|
jmp esi;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE GetText_Hook()
|
|
{
|
|
__asm
|
|
{
|
|
// stolen prologue from CText::Get
|
|
sub esp, 0x20
|
|
push esi
|
|
push edi
|
|
mov edi, [esp+0x2C]
|
|
pushad
|
|
mov unnamed_10151628, edi
|
|
}
|
|
|
|
unnamed_10150734 = 0;
|
|
|
|
// SAMP prefixed keys are server menu text, not gxt entries
|
|
if(pNetGame && unnamed_10151628[0] == 'S' && unnamed_10151628[1] == 'A' &&
|
|
unnamed_10151628[2] == 'M' && unnamed_10151628[3] == 'P' && pNetGame->GetMenuPool())
|
|
{
|
|
unnamed_10150734 = pNetGame->GetMenuPool()->GetTextPointer(unnamed_10151628 + 4);
|
|
}
|
|
|
|
__asm
|
|
{
|
|
popad
|
|
cmp unnamed_10150734, 0
|
|
jz callOriginal
|
|
mov eax, unnamed_10150734
|
|
pop edi
|
|
pop esi
|
|
add esp, 0x20
|
|
retn 4
|
|
|
|
callOriginal:
|
|
mov eax, 0x6A0059
|
|
jmp eax
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE CCustomCarPlateMgr__CreatePlateTexture__RwRasterCreate_Hook()
|
|
{
|
|
__asm
|
|
{
|
|
// only ever create the plate raster once
|
|
mov eax, unnamed_101516C8
|
|
test eax, eax
|
|
jnz exitFn
|
|
|
|
cmp iGtaVersion, GTASA_VERSION_USA10
|
|
jnz createRaster
|
|
mov unnamed_10113ADC, 0x7FB230
|
|
|
|
createRaster:
|
|
push 0x604
|
|
push 0x20
|
|
push 0x10
|
|
push 0x40
|
|
mov ebx, unnamed_10113ADC
|
|
call ebx
|
|
mov unnamed_101516C8, eax
|
|
pop ebx
|
|
pop ebx
|
|
pop ebx
|
|
pop ebx
|
|
|
|
exitFn:
|
|
mov eax, unnamed_101516C8
|
|
retn
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE RwRasterDestroy_Hook()
|
|
{
|
|
__asm
|
|
{
|
|
mov eax, [esp+4] ;// arg0 (RwRaster *)
|
|
mov unnamed_101516D0, eax
|
|
pushad
|
|
|
|
// never let the game destroy our cached plate raster
|
|
cmp unnamed_10113AD8, 0
|
|
jz destroyRaster
|
|
cmp unnamed_101516C8, 0
|
|
jz destroyRaster
|
|
mov eax, unnamed_101516D0
|
|
cmp eax, unnamed_101516C8
|
|
jnz destroyRaster
|
|
|
|
popad
|
|
mov eax, 1
|
|
retn
|
|
|
|
destroyRaster:
|
|
popad
|
|
push esi
|
|
mov esi, [esp+8]
|
|
push esi
|
|
mov edx, unnamed_101516D4
|
|
jmp edx
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE CVehicle__Render_Hook()
|
|
{
|
|
_asm mov unnamed_101516D8, esi
|
|
_asm ret
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
DWORD dwRenderObjectRet = 0;
|
|
ENTITY_TYPE *_pRenderEntity;
|
|
CObject *_pRenderNetObject;
|
|
CPlayerPool *_pRenderPlayerPool;
|
|
|
|
NUDE CObject__Render_Hook()
|
|
{
|
|
_asm mov eax, [esp]
|
|
_asm mov dwRenderObjectRet, eax
|
|
_asm mov _pRenderEntity, ecx
|
|
|
|
_asm pushad
|
|
|
|
if (_pRenderEntity) wLastRendObj = _pRenderEntity->nModelIndex;
|
|
|
|
_pRenderNetObject = NULL;
|
|
|
|
if (pNetGame && _pRenderEntity && (_pRenderEntity->dwProcessingFlags & 0x80000000))
|
|
{
|
|
if ((_pRenderNetObject = pNetGame->GetObjectPool()->FUNC_100129D0(_pRenderEntity)) != NULL ||
|
|
((_pRenderPlayerPool = pNetGame->GetPlayerPool()) != NULL &&
|
|
(_pRenderNetObject = _pRenderPlayerPool->FUNC_10013B70(_pRenderEntity)) != NULL))
|
|
{
|
|
_pRenderNetObject->FUNC_100A9E30();
|
|
}
|
|
}
|
|
|
|
if (unnamed_1014FFAC && _pRenderEntity && (_pRenderEntity->dwProcessingFlags & 0x80000000))
|
|
{
|
|
_pRenderNetObject = unnamed_1014FFAC->FUNC_100129D0(_pRenderEntity);
|
|
if (_pRenderNetObject) _pRenderNetObject->FUNC_100A9E30();
|
|
}
|
|
|
|
_asm
|
|
{
|
|
popad
|
|
|
|
// call original CObject::Render
|
|
mov eax, 0x59F180
|
|
call eax
|
|
|
|
pushad
|
|
}
|
|
|
|
if (pNetGame && _pRenderNetObject) _pRenderNetObject->FUNC_100A9E70();
|
|
if (unnamed_1014FFAC && _pRenderNetObject) _pRenderNetObject->FUNC_100A9E70();
|
|
|
|
_asm popad
|
|
_asm retn
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE CRadar__DrawMap__FindPlayerSpeed_Hook()
|
|
{
|
|
// keep the map still while the local player is a vehicle passenger
|
|
if(pGame && pGame->FindPlayerPed() && pGame->FindPlayerPed()->IsInVehicle() &&
|
|
pGame->FindPlayerPed()->IsAPassenger())
|
|
{
|
|
_asm lea eax, unnamed_10151710
|
|
_asm ret
|
|
}
|
|
|
|
_asm mov edx, 0x56E090 ;// FindPlayerSpeed
|
|
_asm jmp edx
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
DWORD dwObjectInstance = 0;
|
|
DWORD dwObjectInstanceUnused = 0;
|
|
BOOL bReplaceAllObjects = FALSE;
|
|
|
|
int FUNC_1009D050(int iModelID, float fX, float fY, float fZ); // todo: implement `IsObjectRemoved`
|
|
|
|
NUDE CFileLoader__LoadObjectInstance_Hook()
|
|
{
|
|
_asm mov eax, [esp+4]
|
|
_asm mov dwObjectInstance, eax
|
|
_asm mov eax, [esp+8]
|
|
_asm mov dwObjectInstanceUnused, eax
|
|
|
|
_asm pushad
|
|
|
|
// replace removed objects with an invisible model
|
|
if (dwObjectInstance && FUNC_1009D050(*(int *)(dwObjectInstance + 0x1C), *(float *)dwObjectInstance,
|
|
*(float *)(dwObjectInstance + 4), *(float *)(dwObjectInstance + 8)))
|
|
{
|
|
*(int *)(dwObjectInstance + 0x1C) = 19300;
|
|
}
|
|
|
|
if (bReplaceAllObjects) *(int *)(dwObjectInstance + 0x1C) = 19300;
|
|
|
|
_asm
|
|
{
|
|
popad
|
|
|
|
push -1
|
|
push 0x83C931
|
|
mov eax, 0x538097
|
|
jmp eax
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
float fEscalatorCheck1;
|
|
float fEscalatorCheck2;
|
|
|
|
NUDE CEscalator__Update_Hook()
|
|
{
|
|
__asm pushad
|
|
|
|
UnFuck(0x858BA4, 4);
|
|
UnFuck(0x858F84, 4);
|
|
|
|
fEscalatorCheck1 = *(float*)0x858BA4;
|
|
fEscalatorCheck2 = *(float*)0x858F84;
|
|
|
|
*(float*)0x858BA4 = 40.0f;
|
|
*(float*)0x858F84 = 50.0f;
|
|
|
|
__asm
|
|
{
|
|
popad
|
|
|
|
mov eax, 0x717D30 // CEscalator::Update
|
|
call eax
|
|
|
|
pushad
|
|
}
|
|
|
|
*(float*)0x858BA4 = fEscalatorCheck1;
|
|
*(float*)0x858F84 = fEscalatorCheck2;
|
|
|
|
__asm popad
|
|
__asm ret
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE CObject__CreateRwObject_Hook()
|
|
{
|
|
_asm mov eax, [esp]
|
|
_asm mov unnamed_1015172C, eax
|
|
_asm pushad
|
|
|
|
// stop the original from calling the roadsign/plate atomic setup
|
|
UnFuck(0x4096AA, 3);
|
|
memset((void *)0x4096AA, 0x90, 3);
|
|
|
|
__asm
|
|
{
|
|
popad
|
|
|
|
mov eax, 0x533D30 // CObject::CreateRwObject
|
|
call eax
|
|
|
|
pushad
|
|
}
|
|
|
|
memcpy((void *)0x4096AA, unnamed_10113AE8, 3);
|
|
|
|
__asm popad
|
|
__asm ret
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
DWORD dwDeleteRwObjectRet = 0;
|
|
ENTITY_TYPE *_pDeleteRwObjectEntity;
|
|
BYTE byteSavedRoadsignCode[5] = {0xE8,0x3C,0xFF,0xFF,0xFF};
|
|
|
|
NUDE CEntity__DeleteRwObject_Hook()
|
|
{
|
|
_asm mov eax, [esp]
|
|
_asm mov dwDeleteRwObjectRet, eax
|
|
_asm mov _pDeleteRwObjectEntity, ecx
|
|
|
|
_asm pushad
|
|
|
|
if (_pDeleteRwObjectEntity->nModelIndex == 3586 || _pDeleteRwObjectEntity->nModelIndex == 3743 ||
|
|
_pDeleteRwObjectEntity->nModelIndex == 8980 || _pDeleteRwObjectEntity->nModelIndex == 8979)
|
|
{
|
|
// nop the CCustomRoadsignMgr call these models crash in
|
|
UnFuck(0x71791F, 5);
|
|
memset((void *)0x71791F, 0x90, 5);
|
|
|
|
_asm
|
|
{
|
|
popad
|
|
|
|
// call original CEntity::DeleteRwObject
|
|
mov eax, 0x534030
|
|
call eax
|
|
|
|
pushad
|
|
}
|
|
|
|
memcpy((void *)0x71791F, byteSavedRoadsignCode, 5);
|
|
|
|
_asm popad
|
|
_asm retn
|
|
}
|
|
|
|
_asm popad
|
|
_asm mov eax, 0x534030
|
|
_asm jmp eax
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
VEHICLE_TYPE *_pBreakTowLinkVehicle;
|
|
VEHICLEID _BreakTowLinkTractorId;
|
|
CVehiclePool *_pBreakTowLinkPool;
|
|
// set while samp detaches a trailer itself, so gta gets to break the link
|
|
BOOL bIgnoreBreakTowLinkHook;
|
|
CVehicle *_pBreakTowLinkTractor;
|
|
|
|
NUDE CAutomobile__BreakTowLink_Hook()
|
|
{
|
|
__asm
|
|
{
|
|
mov _pBreakTowLinkVehicle, ecx
|
|
|
|
pushad
|
|
}
|
|
|
|
if (pNetGame && !bIgnoreBreakTowLinkHook && _pBreakTowLinkVehicle &&
|
|
_pBreakTowLinkVehicle->fHealth > 0.0f)
|
|
{
|
|
_pBreakTowLinkPool = pNetGame->FUNC_10001180();
|
|
_BreakTowLinkTractorId = _pBreakTowLinkPool->FUNC_1001EB90(_pBreakTowLinkVehicle->dwTractor);
|
|
|
|
if (_BreakTowLinkTractorId != 0xFFFF)
|
|
{
|
|
_pBreakTowLinkTractor = (CVehicle *)_pBreakTowLinkPool->FUNC_10001120(_BreakTowLinkTractorId);
|
|
|
|
if (_pBreakTowLinkTractor && !_pBreakTowLinkTractor->IsDriverLocalPlayer() &&
|
|
*(DWORD *)_pBreakTowLinkTractor->_gap48)
|
|
{
|
|
__asm
|
|
{
|
|
popad
|
|
retn
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
__asm
|
|
{
|
|
popad
|
|
|
|
// call original CAutomobile::BreakTowLink
|
|
mov eax, 0x6A4400
|
|
jmp eax
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
ENTITY_TYPE *_pAttachedEntity;
|
|
CObject *_pAttachedObject;
|
|
DWORD _dwAttachedEntityEsp;
|
|
DWORD _dwAttachedEntityResult;
|
|
|
|
NUDE CWorld__ProcessAttachedEntities__PositionAttachedEntity_Hook()
|
|
{
|
|
__asm
|
|
{
|
|
mov _dwAttachedEntityEsp, esp
|
|
mov _pAttachedEntity, ecx
|
|
|
|
pushad
|
|
|
|
// call original CEntity::PositionAttachedEntity
|
|
mov ecx, _pAttachedEntity
|
|
mov ebx, 0x546FF0
|
|
call ebx
|
|
|
|
mov _dwAttachedEntityResult, eax
|
|
}
|
|
|
|
if (pNetGame && pNetGame->GetObjectPool())
|
|
{
|
|
_pAttachedObject = pNetGame->GetObjectPool()->FUNC_100129D0(_pAttachedEntity);
|
|
if (_pAttachedObject) _pAttachedObject->FUNC_100A7E20();
|
|
}
|
|
|
|
__asm
|
|
{
|
|
popad
|
|
mov eax, _dwAttachedEntityResult
|
|
retn
|
|
}}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE CRenderer__RenderEverythingBarRoads_Hook()
|
|
{
|
|
_asm mov eax, 0x553AA0 ;// CRenderer::RenderEverythingBarRoads
|
|
_asm call eax
|
|
|
|
if(pNetGame) {
|
|
unnamed_1015177C = pNetGame->GetObjectPool();
|
|
if(unnamed_1015177C) {
|
|
unnamed_1015177C->FUNC_10012B90();
|
|
}
|
|
}
|
|
|
|
if(unnamed_1014FFAC) {
|
|
unnamed_1014FFAC->FUNC_10012B90();
|
|
}
|
|
|
|
_asm ret
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE CRenderer__RenderFadingInEntities_Hook()
|
|
{
|
|
_asm mov eax, 0x5531E0 ;// CRenderer::RenderFadingInEntities
|
|
_asm call eax
|
|
|
|
if(pNetGame) {
|
|
unnamed_1015177C = pNetGame->GetObjectPool();
|
|
if(unnamed_1015177C) {
|
|
unnamed_1015177C->FUNC_10012BD0();
|
|
}
|
|
}
|
|
|
|
if(unnamed_1014FFAC) {
|
|
unnamed_1014FFAC->FUNC_10012BD0();
|
|
}
|
|
|
|
_asm ret
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
ENTITY_TYPE *_pRenderListEntity;
|
|
|
|
NUDE CRenderer__AddEntityToRenderList_Hook()
|
|
{
|
|
_asm push esi
|
|
_asm mov esi, [esp+8]
|
|
_asm mov _pRenderListEntity, esi
|
|
|
|
_asm pushad
|
|
|
|
// keep objects out of the render list once they are past their draw distance
|
|
if (pNetGame && _pRenderListEntity && _pRenderListEntity->vtable == 0x866F60 &&
|
|
(_pRenderListEntity->dwProcessingFlags & 0x80000000))
|
|
{
|
|
_pRenderNetObject = pNetGame->FUNC_10002E10()->FUNC_100129D0(_pRenderListEntity);
|
|
|
|
if (_pRenderNetObject && (_pRenderNetObject->field_118B != 0 ||
|
|
_pRenderNetObject->field_54 > 300.0f || _pRenderNetObject->field_1199 != 0))
|
|
{
|
|
_asm popad
|
|
_asm pop esi
|
|
_asm retn
|
|
}
|
|
}
|
|
|
|
if (unnamed_1014FFAC && _pRenderListEntity && _pRenderListEntity->vtable == 0x866F60 &&
|
|
(_pRenderListEntity->dwProcessingFlags & 0x80000000))
|
|
{
|
|
_pRenderNetObject = unnamed_1014FFAC->FUNC_100129D0(_pRenderListEntity);
|
|
|
|
if (_pRenderNetObject && (_pRenderNetObject->field_118B != 0 ||
|
|
_pRenderNetObject->field_54 > 300.0f))
|
|
{
|
|
_asm popad
|
|
_asm pop esi
|
|
_asm retn
|
|
}
|
|
}
|
|
|
|
_asm
|
|
{
|
|
popad
|
|
|
|
// original code
|
|
mov esi, _pRenderListEntity
|
|
movsx eax, word ptr [esi+22h]
|
|
mov edx, 0x5534B9
|
|
jmp edx
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE CEntity__RenderEffects__RenderRoadsignAtomic_Hook()
|
|
{
|
|
__asm
|
|
{
|
|
mov eax, [esp+4] ;// arg0 (RpAtomic *)
|
|
test eax, eax
|
|
jz exitFn
|
|
mov eax, 0x6FF350 ;// CCustomRoadsignMgr::RenderRoadsignAtomic
|
|
jmp eax
|
|
exitFn:
|
|
ret
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
DWORD dwEventDamageThis;
|
|
DWORD dwEventDamagePed;
|
|
|
|
NUDE CEventDamage__AffectsPed_Hook()
|
|
{
|
|
__asm
|
|
{
|
|
mov dwEventDamageThis, ecx
|
|
mov eax, [esp+4]
|
|
mov dwEventDamagePed, eax
|
|
pushad
|
|
cmp pNetGame, 0
|
|
jz do_affects_ped
|
|
call GamePool_FindPlayerPed
|
|
cmp dwEventDamagePed, eax
|
|
jnz do_affects_ped
|
|
mov eax, pbyteCurrentPlayer
|
|
movzx ecx, byte ptr [eax]
|
|
test ecx, ecx
|
|
jz do_affects_ped
|
|
popad
|
|
|
|
// inside a remote player context: always report the event as affecting the ped
|
|
xor eax, eax
|
|
mov al, 1
|
|
retn 4
|
|
do_affects_ped:
|
|
popad
|
|
sub esp, 0xC
|
|
push esi
|
|
mov esi, ecx
|
|
mov eax, 0x4B35A6 // CEventDamage::AffectsPed + 6
|
|
jmp eax
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
// the game hands two 20 byte blocks (a position plus two more floats) to
|
|
// CCollision::BuildCacheOfCameraCollision
|
|
typedef struct _CAMCOL_POINT
|
|
{
|
|
VECTOR vecPos;
|
|
float field_C;
|
|
float field_10;
|
|
} CAMCOL_POINT;
|
|
|
|
CAMCOL_POINT _camColStart;
|
|
CAMCOL_POINT _camColEnd;
|
|
BYTE _byteCamColResult;
|
|
|
|
BYTE CCollision__BuildCacheOfCameraCollision_Hook(CAMCOL_POINT *pStart, CAMCOL_POINT *pEnd)
|
|
{
|
|
_camColStart = *pStart;
|
|
_camColEnd = *pEnd;
|
|
|
|
_byteCamColResult = 0;
|
|
|
|
__asm
|
|
{
|
|
push pEnd
|
|
push pStart
|
|
|
|
// call original CCollision::BuildCacheOfCameraCollision
|
|
mov edx, 0x41AC40
|
|
call edx
|
|
|
|
mov _byteCamColResult, al
|
|
|
|
pop edx
|
|
pop edx
|
|
}
|
|
|
|
// gta only caches collision inside the map bounds, so samp entities placed
|
|
// outside of them have to be checked by hand
|
|
if (pEnd->vecPos.X > 3000.0f || pEnd->vecPos.X < -3000.0f ||
|
|
pEnd->vecPos.Y > 3000.0f || pEnd->vecPos.Y < -3000.0f)
|
|
{
|
|
if (pNetGame && !_byteCamColResult &&
|
|
pNetGame->GetObjectPool()->FUNC_10012DE0(&_camColStart.vecPos, &_camColEnd.vecPos))
|
|
_byteCamColResult = 1;
|
|
|
|
if (unnamed_1014FFAC && !_byteCamColResult &&
|
|
unnamed_1014FFAC->FUNC_10012DE0(&_camColStart.vecPos, &_camColEnd.vecPos))
|
|
_byteCamColResult = 1;
|
|
|
|
if (pNetGame && !pNetGame->GetField232() && !_byteCamColResult &&
|
|
pNetGame->GetVehiclePool()->FUNC_1001EE20(&_camColStart.vecPos, &_camColEnd.vecPos))
|
|
_byteCamColResult = 1;
|
|
}
|
|
|
|
return _byteCamColResult;
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE CCollision__CheckCameraCollisionVehicles_Hook()
|
|
{
|
|
__asm
|
|
{
|
|
pushad
|
|
cmp pNetGame, 0
|
|
jz do_check
|
|
mov eax, pNetGame
|
|
movzx ecx, byte ptr [eax+0x232] // pNetGame->field_232
|
|
test ecx, ecx
|
|
jz do_check
|
|
popad
|
|
xor eax, eax
|
|
retn
|
|
do_check:
|
|
popad
|
|
mov eax, 0x41A990 // CCollision::CheckCameraCollisionVehicles
|
|
jmp eax
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE CWorld__CameraToIgnoreThisObject_Hook()
|
|
{
|
|
__asm
|
|
{
|
|
mov eax, [esp+4] // pEntity
|
|
test eax, eax
|
|
jz ignore_this_object
|
|
mov ecx, [eax+0xFC]
|
|
cmp ecx, 0
|
|
jnz ignore_this_object
|
|
mov edx, 0x563F40 // CWorld::CameraToIgnoreThisObject
|
|
jmp edx
|
|
ignore_this_object:
|
|
mov eax, 1
|
|
retn
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
// shared by the four ProcessEntityCollision hooks below
|
|
DWORD dwCollisionThis;
|
|
DWORD dwCollisionEntity;
|
|
DWORD dwCollisionRetAddr;
|
|
|
|
NUDE CAutomobile__ProcessEntityCollision_Hook()
|
|
{
|
|
__asm
|
|
{
|
|
mov dwCollisionThis, ecx
|
|
mov edx, [esp]
|
|
mov dwCollisionRetAddr, edx
|
|
mov edx, [esp+4]
|
|
mov dwCollisionEntity, edx
|
|
pushad
|
|
cmp pNetGame, 0
|
|
jz process_collision
|
|
mov eax, pNetGame
|
|
movzx ecx, byte ptr [eax+0x232] // pNetGame->field_232
|
|
test ecx, ecx
|
|
jz process_collision
|
|
cmp dwCollisionThis, 0
|
|
jz process_collision
|
|
cmp dwCollisionEntity, 0
|
|
jz process_collision
|
|
mov edx, dwCollisionEntity
|
|
movzx eax, word ptr [edx+0x22] // entity.nModelIndex
|
|
cmp eax, 400
|
|
jl process_collision
|
|
mov ecx, dwCollisionEntity
|
|
movzx edx, word ptr [ecx+0x22]
|
|
cmp edx, 611 // only vehicle models pass
|
|
jg process_collision
|
|
mov eax, dwCollisionThis
|
|
cmp dword ptr [eax+0x460], 0 // pVehicle->pDriver
|
|
jz process_collision
|
|
mov ecx, dwCollisionEntity
|
|
cmp dword ptr [ecx+0x460], 0
|
|
jz process_collision
|
|
popad
|
|
|
|
// both vehicles are being driven, so don't collide them
|
|
mov eax, 0
|
|
retn 8
|
|
process_collision:
|
|
popad
|
|
mov edx, 0x6ACE70 // CAutomobile::ProcessEntityCollision
|
|
jmp edx
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE CBike__ProcessEntityCollision_Hook()
|
|
{
|
|
__asm
|
|
{
|
|
mov dwCollisionThis, ecx
|
|
mov edx, [esp]
|
|
mov dwCollisionRetAddr, edx
|
|
mov edx, [esp+4]
|
|
mov dwCollisionEntity, edx
|
|
pushad
|
|
cmp pNetGame, 0
|
|
jz process_collision
|
|
mov eax, pNetGame
|
|
movzx ecx, byte ptr [eax+0x232] // pNetGame->field_232
|
|
test ecx, ecx
|
|
jz process_collision
|
|
cmp dwCollisionThis, 0
|
|
jz process_collision
|
|
cmp dwCollisionEntity, 0
|
|
jz process_collision
|
|
mov edx, dwCollisionEntity
|
|
movzx eax, word ptr [edx+0x22] // entity.nModelIndex
|
|
cmp eax, 400
|
|
jl process_collision
|
|
mov ecx, dwCollisionEntity
|
|
movzx edx, word ptr [ecx+0x22]
|
|
cmp edx, 611 // only vehicle models pass
|
|
jg process_collision
|
|
mov eax, dwCollisionThis
|
|
cmp dword ptr [eax+0x460], 0 // pVehicle->pDriver
|
|
jz process_collision
|
|
mov ecx, dwCollisionEntity
|
|
cmp dword ptr [ecx+0x460], 0
|
|
jz process_collision
|
|
popad
|
|
|
|
// both vehicles are being driven, so don't collide them
|
|
mov eax, 0
|
|
retn 8
|
|
process_collision:
|
|
popad
|
|
mov edx, 0x6BDEA0 // CBike::ProcessEntityCollision
|
|
jmp edx
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE CMonsterTruck__ProcessEntityCollision_Hook()
|
|
{
|
|
__asm
|
|
{
|
|
mov dwCollisionThis, ecx
|
|
mov edx, [esp]
|
|
mov dwCollisionRetAddr, edx
|
|
mov edx, [esp+4]
|
|
mov dwCollisionEntity, edx
|
|
pushad
|
|
cmp pNetGame, 0
|
|
jz process_collision
|
|
mov eax, pNetGame
|
|
movzx ecx, byte ptr [eax+0x232] // pNetGame->field_232
|
|
test ecx, ecx
|
|
jz process_collision
|
|
cmp dwCollisionThis, 0
|
|
jz process_collision
|
|
cmp dwCollisionEntity, 0
|
|
jz process_collision
|
|
mov edx, dwCollisionEntity
|
|
movzx eax, word ptr [edx+0x22] // entity.nModelIndex
|
|
cmp eax, 400
|
|
jl process_collision
|
|
mov ecx, dwCollisionEntity
|
|
movzx edx, word ptr [ecx+0x22]
|
|
cmp edx, 611 // only vehicle models pass
|
|
jg process_collision
|
|
mov eax, dwCollisionThis
|
|
cmp dword ptr [eax+0x460], 0 // pVehicle->pDriver
|
|
jz process_collision
|
|
mov ecx, dwCollisionEntity
|
|
cmp dword ptr [ecx+0x460], 0
|
|
jz process_collision
|
|
popad
|
|
|
|
// both vehicles are being driven, so don't collide them
|
|
mov eax, 0
|
|
retn 8
|
|
process_collision:
|
|
popad
|
|
mov edx, 0x6C8AE0 // CMonsterTruck::ProcessEntityCollision
|
|
jmp edx
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE CPhysical__ProcessEntityCollision_Hook()
|
|
{
|
|
__asm
|
|
{
|
|
mov dwCollisionThis, ecx
|
|
mov edx, [esp]
|
|
mov dwCollisionRetAddr, edx
|
|
mov edx, [esp+4]
|
|
mov dwCollisionEntity, edx
|
|
pushad
|
|
cmp pNetGame, 0
|
|
jz process_collision
|
|
mov eax, pNetGame
|
|
movzx ecx, byte ptr [eax+0x232] // pNetGame->field_232
|
|
test ecx, ecx
|
|
jz process_collision
|
|
cmp dwCollisionThis, 0
|
|
jz process_collision
|
|
cmp dwCollisionEntity, 0
|
|
jz process_collision
|
|
mov edx, dwCollisionEntity
|
|
movzx eax, word ptr [edx+0x22] // entity.nModelIndex
|
|
cmp eax, 400
|
|
jl process_collision
|
|
mov ecx, dwCollisionEntity
|
|
movzx edx, word ptr [ecx+0x22]
|
|
cmp edx, 611 // only vehicle models pass
|
|
jg process_collision
|
|
mov eax, dwCollisionThis
|
|
cmp dword ptr [eax+0x460], 0 // pVehicle->pDriver
|
|
jz process_collision
|
|
mov ecx, dwCollisionEntity
|
|
cmp dword ptr [ecx+0x460], 0
|
|
jz process_collision
|
|
popad
|
|
|
|
// both vehicles are being driven, so don't collide them
|
|
mov eax, 0
|
|
retn 8
|
|
process_collision:
|
|
popad
|
|
mov edx, 0x546D00 // CPhysical::ProcessEntityCollision
|
|
jmp edx
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE CVehicle__UsesSiren_Hook()
|
|
{
|
|
__asm
|
|
{
|
|
// the streamed in check below already answered for this vehicle
|
|
mov eax, unnamed_1015180C
|
|
test eax, eax
|
|
jz usesSiren
|
|
mov unnamed_1015180C, 0
|
|
mov al, 1
|
|
retn
|
|
|
|
usesSiren:
|
|
mov unnamed_10151804, ecx
|
|
mov edx, 0x6D8470 // CVehicle::UsesSiren
|
|
call edx
|
|
mov unnamed_10151808, al
|
|
}
|
|
|
|
if(!unnamed_10151808)
|
|
{
|
|
_asm pushad
|
|
|
|
// the game doesn't know about server sided sirens, ask our own vehicle
|
|
if(pNetGame)
|
|
{
|
|
CVehiclePool *pVehiclePool = pNetGame->GetVehiclePool();
|
|
if(pVehiclePool)
|
|
{
|
|
unnamed_10113B2C = pVehiclePool->FUNC_1001EB90(unnamed_10151804);
|
|
if(unnamed_10113B2C != 0xFFFF)
|
|
{
|
|
CVehicle *pVehicle = (CVehicle *)pNetGame->GetVehiclePool()->FUNC_10001120(unnamed_10113B2C);
|
|
if(pVehicle->FUNC_100B8330()) unnamed_10151808 = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
_asm popad
|
|
}
|
|
|
|
_asm mov al, unnamed_10151808
|
|
_asm retn
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE CAEWeatherAudioEntity__UpdateParameters_Hook()
|
|
{
|
|
_asm mov edx, [esp+4]
|
|
_asm mov unnamed_10151814, edx
|
|
_asm mov edx, [esp+8]
|
|
_asm mov unnamed_10151818, edx
|
|
unnamed_10151810 = *(DWORD *)0xB72914;
|
|
|
|
// mute the rain/wind audio while the outdoor ambience track is disabled
|
|
if(pGame)
|
|
{
|
|
CAudio *pAudio = pGame->m_pGameAudio;
|
|
if(pAudio->field_4) *(DWORD *)0xB72914 = 1;
|
|
}
|
|
|
|
_asm push unnamed_10151818
|
|
_asm push unnamed_10151814
|
|
_asm mov edx, 0x505A00
|
|
_asm call edx
|
|
|
|
*(DWORD *)0xB72914 = unnamed_10151810;
|
|
_asm ret 8
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE CWorld__ProcessVerticalLine_Hook()
|
|
{
|
|
__asm
|
|
{
|
|
mov eax, [esp] ;// caller
|
|
mov unnamed_10151824, eax
|
|
cmp eax, 0x59E8F9
|
|
jz callFn
|
|
mov eax, [esp+0x14]
|
|
test eax, eax
|
|
jz callFn
|
|
mov byte ptr [esp+0x20], 1
|
|
callFn:
|
|
sub esp, 0x2C
|
|
mov eax, 0x407C37 ;// CWorld::ProcessVerticalLine
|
|
jmp eax
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE CStreaming__RequestModel_Hook()
|
|
{
|
|
__asm
|
|
{
|
|
cmp ebp, 0 ;// model id
|
|
jl exitFn
|
|
push esi
|
|
push edi
|
|
lea edi, [ebp+ebp*4]
|
|
mov eax, 0x4087F0 ;// CStreaming::RequestModel
|
|
jmp eax
|
|
exitFn:
|
|
pop ebp
|
|
pop ebx
|
|
ret
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
// arguments of the shot being fired, shared with CWeapon__FireSniper_Hook
|
|
ENTITY_TYPE* pFiringEntity = 0;
|
|
VECTOR* pPosn = 0;
|
|
VECTOR* pEffectPosn = 0;
|
|
ENTITY_TYPE* pTargetEntity = 0;
|
|
VECTOR* pTarget = 0;
|
|
VECTOR* pPosnForDriveBy = 0;
|
|
DWORD dwUnknown8 = 0;
|
|
DWORD dwAdditionalEffects = 0;
|
|
|
|
NUDE CWeapon__FireInstantHit_Hook()
|
|
{
|
|
__asm
|
|
{
|
|
mov eax, [esp+0x4]
|
|
mov pFiringEntity, eax
|
|
mov eax, [esp+0x8]
|
|
mov pPosn, eax
|
|
mov eax, [esp+0xC]
|
|
mov pEffectPosn, eax
|
|
mov eax, [esp+0x10]
|
|
mov pTargetEntity, eax
|
|
mov eax, [esp+0x14]
|
|
mov pTarget, eax
|
|
mov eax, [esp+0x18]
|
|
mov pPosnForDriveBy, eax
|
|
mov eax, [esp+0x1C]
|
|
mov dwUnknown8, eax
|
|
mov eax, [esp+0x20]
|
|
mov dwAdditionalEffects, eax
|
|
|
|
pushad
|
|
}
|
|
|
|
if(pFiringEntity != (ENTITY_TYPE*)GamePool_FindPlayerPed())
|
|
{
|
|
__asm
|
|
{
|
|
popad
|
|
retn 0x20
|
|
}
|
|
}
|
|
|
|
if(pNetGame && pNetGame->GetPlayerPool())
|
|
pNetGame->GetPlayerPool()->sub_10013C90();
|
|
|
|
if(pGame && pGame->FindPlayerPed())
|
|
pGame->FindPlayerPed()->FUNC_100AFA70();
|
|
|
|
if(pNetGame && pNetGame->GetPlayerPool())
|
|
pNetGame->GetPlayerPool()->sub_10013D10();
|
|
|
|
_asm popad
|
|
_asm ret 0x20
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
extern DWORD unnamed_10118990; // 0x10118990, lives in another translation unit
|
|
|
|
// where a synced shot came from, snapshotted by CPlayerPed::FUNC_100AFA70
|
|
struct SHOT_SYNC_DATA
|
|
{
|
|
char _gap0[0x1C];
|
|
VECTOR vecOffset;
|
|
ENTITY_TYPE *pAttachedTo;
|
|
};
|
|
|
|
// todo: implement sub_100A5410
|
|
void __stdcall sub_100A5410(VECTOR *vecOrigin, VECTOR *vecLine, VECTOR *colPoint, DWORD *pHitEntity);
|
|
|
|
VECTOR vecShotOrigin; // 0x10150CE4
|
|
BOOL bLineOfSightResult = 0; // 0x101517B0
|
|
CPlayerPed *pShotSyncPlayer = 0; // 0x101517CC
|
|
SHOT_SYNC_DATA *pShotSyncData = 0; // 0x101517D0
|
|
|
|
BOOL CWorld__ProcessLineOfSight_Hook(VECTOR *vecOrigin, VECTOR *vecLine, VECTOR *colPoint,
|
|
DWORD *pHitEntity, int bCheckBuildings, int bCheckVehicles, int bCheckPeds,
|
|
int bCheckObjects, int bCheckDummies, int bSeeThroughStuff,
|
|
int bIgnoreSomeObjectsForCamera, int bUnk1)
|
|
{
|
|
// aim the ray at where the remote player actually shot from
|
|
if(unnamed_10118990 != 2 && pShotSyncPlayer && pShotSyncPlayer != pGame->FindPlayerPed() &&
|
|
pShotSyncData && pShotSyncData->pAttachedTo &&
|
|
pShotSyncData->pAttachedTo->vtable != 0x863C40 &&
|
|
pShotSyncData->pAttachedTo->mat)
|
|
{
|
|
if(unnamed_10118990 == 0)
|
|
{
|
|
FUNC_100B4D10(&vecShotOrigin, pShotSyncData->pAttachedTo->mat, &pShotSyncData->vecOffset);
|
|
}
|
|
else
|
|
{
|
|
vecShotOrigin.X = pShotSyncData->pAttachedTo->mat->pos.X + pShotSyncData->vecOffset.X;
|
|
vecShotOrigin.Y = pShotSyncData->pAttachedTo->mat->pos.Y + pShotSyncData->vecOffset.Y;
|
|
vecShotOrigin.Z = pShotSyncData->pAttachedTo->mat->pos.Z + pShotSyncData->vecOffset.Z;
|
|
}
|
|
|
|
vecLine->X = vecShotOrigin.X - vecOrigin->X + vecShotOrigin.X;
|
|
vecLine->Y = vecShotOrigin.Y - vecOrigin->Y + vecShotOrigin.Y;
|
|
vecLine->Z = vecShotOrigin.Z - vecOrigin->Z + vecShotOrigin.Z;
|
|
}
|
|
|
|
bLineOfSightResult = ProcessLineOfSight(vecOrigin, vecLine, colPoint, pHitEntity,
|
|
bCheckBuildings, bCheckVehicles, bCheckPeds, bCheckObjects, bCheckDummies,
|
|
bSeeThroughStuff, bIgnoreSomeObjectsForCamera, bUnk1);
|
|
|
|
// a remote player's shot must not collide with the local player
|
|
if(unnamed_10118990 != 2 && pShotSyncPlayer && pShotSyncPlayer != pGame->FindPlayerPed() &&
|
|
pShotSyncData && !pShotSyncData->pAttachedTo)
|
|
{
|
|
if(*pHitEntity == (DWORD)GamePool_FindPlayerPed() ||
|
|
(IN_VEHICLE(GamePool_FindPlayerPed()) &&
|
|
*pHitEntity == GamePool_FindPlayerPed()->pVehicle))
|
|
{
|
|
*pHitEntity = 0;
|
|
colPoint->X = 0.0f;
|
|
colPoint->Y = 0.0f;
|
|
colPoint->Z = 0.0f;
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
if(pShotSyncPlayer && pShotSyncPlayer == pGame->FindPlayerPed())
|
|
sub_100A5410(vecOrigin, vecLine, colPoint, pHitEntity);
|
|
|
|
return bLineOfSightResult;
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE CWeapon__FireSniper_Hook()
|
|
{
|
|
_asm mov eax, [esp+0x4]
|
|
_asm mov pFiringEntity, eax
|
|
_asm pushad
|
|
|
|
if(pFiringEntity != (ENTITY_TYPE*)GamePool_FindPlayerPed())
|
|
{
|
|
__asm
|
|
{
|
|
popad
|
|
retn 0xC
|
|
}
|
|
}
|
|
|
|
if(pGame && pGame->FindPlayerPed())
|
|
pGame->FindPlayerPed()->FUNC_100AFA70();
|
|
|
|
_asm popad
|
|
_asm ret 0xC
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
// bullets get a 50x velocity so the shot lands on the frame it was fired
|
|
const float fBulletVelocityScale = 50.0f;
|
|
|
|
NUDE CBulletInfo__AddBullet_Hook()
|
|
{
|
|
__asm
|
|
{
|
|
push ebp
|
|
mov ebp, esp
|
|
|
|
fld dword ptr [ebp+0x1C]
|
|
fmul fBulletVelocityScale
|
|
fstp dword ptr [ebp+0x1C]
|
|
fld dword ptr [ebp+0x20]
|
|
fmul fBulletVelocityScale
|
|
fstp dword ptr [ebp+0x20]
|
|
fld dword ptr [ebp+0x24]
|
|
fmul fBulletVelocityScale
|
|
fstp dword ptr [ebp+0x24]
|
|
|
|
push dword ptr [ebp+0x24]
|
|
push dword ptr [ebp+0x20]
|
|
push dword ptr [ebp+0x1C]
|
|
push dword ptr [ebp+0x18]
|
|
push dword ptr [ebp+0x14]
|
|
push dword ptr [ebp+0x10]
|
|
push dword ptr [ebp+0xC]
|
|
push dword ptr [ebp+0x8]
|
|
mov edx, 0x736010 ;// CBulletInfo::AddBullet
|
|
call edx
|
|
add esp, 0x20
|
|
|
|
mov edx, 0x7360D0 ;// CBulletInfo::Update
|
|
call edx
|
|
|
|
pop ebp
|
|
retn
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
// todo: implement sub_100A5240, it tells whether the damage came from a team mate
|
|
BOOL sub_100A5240(DWORD dwVehicle, DWORD dwInflictor, DWORD dwWeapon);
|
|
|
|
DWORD dwDamageInflictor = 0;
|
|
DWORD dwDamagedVehicle = 0;
|
|
DWORD dwDamageWeapon = 0;
|
|
BOOL bIgnoreVehicleDamage = 0;
|
|
DWORD dwInflictDamageRetAddr = 0;
|
|
|
|
PLAYERID wInflictDamageDriver;
|
|
CPlayerPool *pInflictDamagePool;
|
|
|
|
// true when the local player drives dwVehicle and dwPed belongs to a team mate
|
|
BOOL FUNC_100A5240(DWORD dwVehicle, DWORD dwPed)
|
|
{
|
|
if(!pNetGame || !pGame || !pGame->FindPlayerPed()
|
|
|| !pGame->FindPlayerPed()->IsInVehicle()
|
|
|| pGame->FindPlayerPed()->IsAPassenger()
|
|
|| (int)pGame->FindPlayerPed()->GetGtaVehicle() != (int)dwVehicle)
|
|
return FALSE;
|
|
|
|
wInflictDamageDriver = FUNC_100A3AE0(dwPed);
|
|
if(wInflictDamageDriver == 0xFFFF) return FALSE;
|
|
|
|
pInflictDamagePool = pNetGame->GetPlayerPool();
|
|
if(!pInflictDamagePool) return FALSE;
|
|
|
|
if(pNetGame->GetSettings()->field_22)
|
|
{
|
|
BYTE byteTeam = pInflictDamagePool->m_pLocalPlayer->m_byteTeam;
|
|
|
|
if(byteTeam == 0xFF) return FALSE;
|
|
|
|
if((BYTE)pNetGame->GetPlayerPool()->GetAt(wInflictDamageDriver)->field_109 == byteTeam)
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE CVehicle__InflictDamage_Hook()
|
|
{
|
|
_asm mov dwDamagedVehicle, ecx
|
|
_asm mov eax, [esp]
|
|
_asm mov dwInflictDamageRetAddr, eax
|
|
_asm mov eax, [esp+0x4]
|
|
_asm mov dwDamageInflictor, eax
|
|
_asm mov eax, [esp+0x8]
|
|
_asm mov dwDamageWeapon, eax
|
|
_asm pushad
|
|
|
|
bIgnoreVehicleDamage = sub_100A5240(dwDamagedVehicle, dwDamageInflictor, dwDamageWeapon);
|
|
|
|
_asm popad
|
|
|
|
if(bIgnoreVehicleDamage)
|
|
{
|
|
_asm xor eax, eax
|
|
_asm retn 0x18
|
|
}
|
|
|
|
if(iGtaVersion == 1)
|
|
{
|
|
_asm push 0xFFFFFFFF
|
|
_asm mov eax, 0x404CDC
|
|
_asm jmp eax
|
|
}
|
|
else
|
|
{
|
|
_asm push 0xFFFFFFFF
|
|
_asm mov eax, 0x404CE3
|
|
_asm jmp eax
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
// fps-related hook
|
|
NUDE CTimer__GetCurrentTimeInCycles_Hook()
|
|
{
|
|
Sleep(1);
|
|
|
|
_asm mov edx, 0x561A80
|
|
_asm jmp edx
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
// .text:100A23F0 : drops a 0x190 byte game frame and returns
|
|
NUDE FUNC_100A23F0()
|
|
{
|
|
_asm add esp, 0x190
|
|
_asm retn
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
DWORD dwRandCaller;
|
|
|
|
NUDE Rand_Hook()
|
|
{
|
|
_asm mov eax, [esp+0]
|
|
_asm mov dwRandCaller, eax
|
|
|
|
/*
|
|
if(dwRandCaller > 0x73FB10 && dwRandCaller < 0x74132E) {
|
|
_asm mov eax, iSyncedRandomNumber
|
|
_asm ret
|
|
}*/
|
|
|
|
rand();
|
|
_asm ret
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
// We use a special bit (32) on dwProcFlags (+28) to indicate
|
|
// whether we should process gravity/collisions on this PlayerPed.
|
|
|
|
NUDE CPlayerPed_ProcessCollision_Hook()
|
|
{
|
|
_asm test ecx, ecx
|
|
_asm jnz ptr_is_ok
|
|
_asm ret
|
|
ptr_is_ok:
|
|
_asm mov eax, [ecx+28]
|
|
_asm shr eax, 31
|
|
_asm cmp eax, 1
|
|
_asm jne do_process_cols
|
|
_asm ret // we set top bit so don't process this
|
|
do_process_cols:
|
|
_asm mov edx, 0x54DFB0
|
|
_asm jmp edx
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
DWORD dwMat;
|
|
DWORD dwMatEffects;
|
|
DWORD dwDataParam;
|
|
|
|
NUDE VehicleModel_SetEnvironmentMapHook()
|
|
{
|
|
_asm mov eax, [esp+4]
|
|
_asm mov dwMat, eax
|
|
_asm mov eax, [esp+8]
|
|
_asm mov dwDataParam, eax
|
|
|
|
UnFuck(0x6D64F0,1);
|
|
*(PBYTE)0x6D64F0 = 0xC3;
|
|
|
|
/*
|
|
_asm push dwMat
|
|
_asm mov edx, 0x812140 // _RpMatFXMaterialGetEffects
|
|
_asm call edx
|
|
_asm pop edx
|
|
_asm mov dwMatEffects, eax*/
|
|
|
|
_asm push 0
|
|
_asm push dwMat
|
|
_asm mov edx, 0x811C80 // _RpMatFXMaterialSetEffects
|
|
_asm call edx
|
|
_asm pop edx
|
|
_asm pop edx
|
|
|
|
//pChatWindow->AddDebugMessage("SetEnvironmentMapCB(0x%X,0x%X,%d)",dwMat,dwDataParam,dwMatEffects);
|
|
|
|
_asm mov edx, 0x4C8848
|
|
_asm cmp [esp+8], 0FFFFh
|
|
_asm jmp edx
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
NUDE FUNC_100A5FF0()
|
|
{
|
|
_asm mov edx, 0x550F10
|
|
_asm call edx
|
|
|
|
_asm ret
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
// trampolines that only snapshot the caller's arguments before handing the
|
|
// call on to GTA
|
|
|
|
DWORD unnamed_10150A20;
|
|
DWORD unnamed_10151730;
|
|
DWORD unnamed_10150C14;
|
|
DWORD unnamed_101515F8;
|
|
DWORD unnamed_101514AC;
|
|
|
|
// .text:100A4410
|
|
NUDE FUNC_100A4410()
|
|
{
|
|
_asm mov eax, [esp]
|
|
_asm mov unnamed_10150A20, eax
|
|
_asm pushad
|
|
_asm popad
|
|
_asm mov eax, 0x4C95C0
|
|
_asm jmp eax
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
// .text:100A4B40
|
|
NUDE FUNC_100A4B40()
|
|
{
|
|
_asm mov eax, [esp]
|
|
_asm mov unnamed_1015172C, eax
|
|
_asm mov unnamed_10151730, ecx
|
|
_asm pushad
|
|
_asm popad
|
|
_asm mov eax, 0x5A2BD0
|
|
_asm jmp eax
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
// .text:100A4920
|
|
NUDE FUNC_100A4920()
|
|
{
|
|
_asm mov eax, [esp+4]
|
|
_asm mov unnamed_10150C14, eax
|
|
_asm mov eax, [esp+8]
|
|
_asm mov unnamed_101515F8, eax
|
|
_asm mov eax, [esp+12]
|
|
_asm mov unnamed_101514AC, eax
|
|
_asm pushad
|
|
_asm popad
|
|
_asm mov eax, 0x40C6B0
|
|
_asm jmp eax
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
// .text:100A4F50
|
|
NUDE FUNC_100A4F50()
|
|
{
|
|
_asm pushad
|
|
_asm popad
|
|
_asm mov eax, 0x61E3F0
|
|
_asm jmp eax
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
// .text:100A4F30 : only let the game run its own handler while we are not connected
|
|
NUDE FUNC_100A4F30()
|
|
{
|
|
if(pGame->sub_100A0920())
|
|
{
|
|
_asm retn
|
|
}
|
|
|
|
_asm mov edx, 0x69EFC0
|
|
_asm jmp edx
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
// .text:100A4EB0
|
|
NUDE FUNC_100A4EB0()
|
|
{
|
|
_asm
|
|
{
|
|
mov eax, [esp+4]
|
|
push eax
|
|
mov eax, 0x5618D0
|
|
call eax
|
|
pop edx
|
|
pushad
|
|
}
|
|
|
|
if(pGame) pGame->sub_100A1C10();
|
|
|
|
_asm
|
|
{
|
|
popad
|
|
retn
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
// .text:100A5E20
|
|
NUDE FUNC_100A5E20()
|
|
{
|
|
_asm mov edx, 0x72B850
|
|
_asm call edx
|
|
_asm retn
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
inline void InstallMethodHook( DWORD dwInstallAddress,
|
|
DWORD dwHookFunction )
|
|
{
|
|
DWORD oldProt, oldProt2;
|
|
VirtualProtect((LPVOID)dwInstallAddress,4,PAGE_EXECUTE_READWRITE,&oldProt);
|
|
*(PDWORD)dwInstallAddress = (DWORD)dwHookFunction;
|
|
VirtualProtect((LPVOID)dwInstallAddress,4,oldProt,&oldProt2);
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
void InstallHook( DWORD dwInstallAddress,
|
|
DWORD dwHookFunction,
|
|
DWORD dwHookStorage,
|
|
BYTE * pbyteJmpCode,
|
|
int iJmpCodeSize )
|
|
{
|
|
DWORD oldProt, oldProt2;
|
|
|
|
// Install the pointer to procaddr.
|
|
VirtualProtect((PVOID)dwHookStorage,4,PAGE_EXECUTE_READWRITE,&oldProt);
|
|
*(PDWORD)dwHookStorage = (DWORD)dwHookFunction;
|
|
VirtualProtect((PVOID)dwHookStorage,4,oldProt,&oldProt2);
|
|
|
|
// Install the Jmp code.
|
|
VirtualProtect((PVOID)dwInstallAddress,iJmpCodeSize,PAGE_EXECUTE_READWRITE,&oldProt);
|
|
memcpy((PVOID)dwInstallAddress,pbyteJmpCode,iJmpCodeSize);
|
|
VirtualProtect((PVOID)dwInstallAddress,iJmpCodeSize,oldProt,&oldProt2);
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
inline void InstallCallHook(DWORD dwInstallAddress, DWORD dwHookFunction, BYTE byteJumpCode = 0xE8)
|
|
{
|
|
DWORD oldProt, oldProt2;
|
|
DWORD disp = dwHookFunction - (dwInstallAddress + 5);
|
|
|
|
VirtualProtect((LPVOID)dwInstallAddress,5,PAGE_EXECUTE_READWRITE,&oldProt);
|
|
*(PBYTE)(dwInstallAddress) = byteJumpCode;
|
|
*(PDWORD)(dwInstallAddress+1) = (DWORD)disp;
|
|
VirtualProtect((LPVOID)dwInstallAddress,5,oldProt,&oldProt2);
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
void InstallGameAndGraphicsLoopHooks()
|
|
{
|
|
UnFuck(0x53EB13,4);
|
|
*(int *)0x53EB13 = dwGraphicsLoop - 0x53EB12 - 5; // relative addr
|
|
|
|
InstallCallHook(0x58FC53,(DWORD)CHud__DrawRadar_Hook);
|
|
|
|
InstallCallHook(0x58FBBF,(DWORD)CHud__DrawCrossHairs_Hook);
|
|
|
|
InstallCallHook(0x53C104,(DWORD)CCamera__Process_Hook);
|
|
|
|
InstallCallHook(0x53E981,(DWORD)CGame__Process_Hook);
|
|
|
|
// For fixing fogging issues (needed for both debug and net)
|
|
InstallMethodHook(0x86D1B0,(DWORD)CPed_Render_Hook); // This is PlayerPed
|
|
InstallMethodHook(0x86C0F0,(DWORD)CPed_Render_Hook);
|
|
InstallMethodHook(0x86C168,(DWORD)CPed_Render_Hook);
|
|
InstallMethodHook(0x86C248,(DWORD)CPed_Render_Hook);
|
|
InstallMethodHook(0x86C3A0,(DWORD)CPed_Render_Hook);
|
|
|
|
InstallCallHook(0x53E930,(DWORD)CTimer__GetCurrentTimeInCycles_Hook);
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
void GameInstallHooks()
|
|
{
|
|
InstallGameAndGraphicsLoopHooks();
|
|
|
|
InstallHook(0x4D3AA0,(DWORD)CAnimManager__AddAnimation_Hook,0x4D3934,CAnimManager__AddAnimation_Hook_HookJmpCode,sizeof(CAnimManager__AddAnimation_Hook_HookJmpCode));
|
|
|
|
InstallHook(0x4D4610,(DWORD)CAnimManager__BlendAnimation_Hook,0x4D4609,CAnimManager__BlendAnimation_HookJmpCode,sizeof(CAnimManager__BlendAnimation_HookJmpCode));
|
|
|
|
InstallMethodHook(0x86D190,(DWORD)CPlayerPed_ProcessControl_Hook);
|
|
|
|
InstallMethodHook(0x86C0D0,(DWORD)CCivillianPed__ProcessControl_Hook);
|
|
|
|
InstallMethodHook(0x86D744,(DWORD)TaskUseGun_Hook);
|
|
|
|
InstallCallHook(0x7330A2,(DWORD)WeaponRender__GetWeaponSkill_Hook);
|
|
|
|
InstallMethodHook(0x86D194,(DWORD)CPlayerPed_ProcessCollision_Hook);
|
|
|
|
InstallCallHook(0x5689FD,(DWORD)CWorld__ProcessAttachedEntities_Hook);
|
|
|
|
InstallCallHook(0x53EA03,(DWORD)CWorld__ProcessPedsAfterPreRender_Hook);
|
|
|
|
InstallMethodHook(0x871148,(DWORD)AllVehicles_ProcessControl_Hook); // Automobile
|
|
InstallMethodHook(0x8721C8,(DWORD)AllVehicles_ProcessControl_Hook); // boat
|
|
InstallMethodHook(0x871388,(DWORD)AllVehicles_ProcessControl_Hook); // motorbike1
|
|
InstallMethodHook(0x871970,(DWORD)AllVehicles_ProcessControl_Hook); // plane
|
|
InstallMethodHook(0x8716A8,(DWORD)AllVehicles_ProcessControl_Hook); // heli
|
|
InstallMethodHook(0x871550,(DWORD)AllVehicles_ProcessControl_Hook); // pushbike
|
|
InstallMethodHook(0x871800,(DWORD)AllVehicles_ProcessControl_Hook); // truck
|
|
InstallMethodHook(0x871B10,(DWORD)AllVehicles_ProcessControl_Hook); // quad
|
|
InstallMethodHook(0x872398,(DWORD)AllVehicles_ProcessControl_Hook); // train
|
|
InstallMethodHook(0x871C50,(DWORD)AllVehicles_ProcessControl_Hook);
|
|
|
|
InstallCallHook(0x501B1D,(DWORD)VehicleHorn_Hook);
|
|
InstallCallHook(0x501B42,(DWORD)VehicleHorn_Hook);
|
|
InstallCallHook(0x501FC2,(DWORD)VehicleHorn_Hook);
|
|
InstallCallHook(0x502067,(DWORD)VehicleHorn_Hook);
|
|
InstallCallHook(0x5021AE,(DWORD)VehicleHorn_Hook);
|
|
|
|
// Radar and map hooks for gang zones
|
|
InstallCallHook(0x5869BF,(DWORD)ZoneOverlay_Hook);
|
|
InstallCallHook(0x5759E4,(DWORD)ZoneOverlay_Hook);
|
|
|
|
InstallCallHook(0x609A4E,(DWORD)PlayerWalk_Hook);
|
|
InstallCallHook(0x4579C6,(DWORD)PickUpPickup_Hook, 0xE9);
|
|
InstallCallHook(0x73C252,(DWORD)CWeapon_FireCamera_Hook, 0xE9);
|
|
|
|
// Hook the call to CCamera::CamShake when called for sniper fire
|
|
InstallCallHook(0x73ACE2,(DWORD)CCameraCamShake_Sniper_Hook);
|
|
|
|
// Hook the train derailment code
|
|
InstallCallHook(0x6F8CF8,(DWORD)CTrain_ProcessControl_Derailment);
|
|
|
|
InstallHook(0x6402F0,(DWORD)TaskEnterVehicleDriver_Hook,
|
|
0x6919BB,TaskEnterVehicleDriver_HookJmpCode,sizeof(TaskEnterVehicleDriver_HookJmpCode));
|
|
|
|
InstallHook(0x63B8C0,(DWORD)TaskExitVehicle,
|
|
0x63B8BA,TaskExitVehicle_HookJmpCode,sizeof(TaskExitVehicle_HookJmpCode));
|
|
|
|
InstallHook(0x438576,(DWORD)CheatProcessorHook,
|
|
0x4385AA,CheatProcessHook_JmpCode,sizeof(CheatProcessHook_JmpCode));
|
|
|
|
InstallHook(0x584770,(DWORD)RadarTranslateColor,0x584A79,
|
|
RadarTranslateColor_HookJmpCode,sizeof(RadarTranslateColor_HookJmpCode));
|
|
|
|
InstallHook(0x53C900,(DWORD)CGameShutdownHook,0x53C8F1,
|
|
CGameShutdown_HookJmpCode,sizeof(CGameShutdown_HookJmpCode));
|
|
|
|
InstallHook(0x4B5AC0,(DWORD)PedDamage_Hook,0x4B5ABC,
|
|
PedDamage_HookJmpCode,sizeof(PedDamage_HookJmpCode));
|
|
|
|
// Fix for 0x004D41C5 crash
|
|
InstallCallHook(0x4D41C0, (DWORD)AnimCrashFixHook, 0xE9);
|
|
|
|
InstallCallHook(0x4E7427,(DWORD)PoliceScannerAudio_FindPlayerPed_Hook);
|
|
|
|
// Fix for crash when the player who threw the satchel died
|
|
InstallHook(0x738F3A, (DWORD)CProjectile_Update_Hook, 0x738B1B, CProjectileInfo_Update_HookJmpCode, sizeof(CProjectileInfo_Update_HookJmpCode));
|
|
// Fix for all satchels blowing up when someone activated their satchel
|
|
InstallHook(0x738877, (DWORD)CWeapon__Satchel__Activate_Hook, 0x73885B, CWeapon__Satchel__Activate_HookJmpCode, sizeof(CWeapon__Satchel__Activate_HookJmpCode));
|
|
|
|
InstallHook(0x6A0050, (DWORD)GetText_Hook, 0x6A0043, GetText_HookJmpCode, sizeof (GetText_HookJmpCode));
|
|
|
|
InstallCallHook(0x6FDED6,(DWORD)CCustomCarPlateMgr__CreatePlateTexture__RwRasterCreate_Hook);
|
|
|
|
if(iGtaVersion == GTASA_VERSION_USA10)
|
|
{
|
|
InstallHook(0x7FB020,(DWORD)RwRasterDestroy_Hook,0x59C721,RwRasterDestroy_HookJmpCode,sizeof(RwRasterDestroy_HookJmpCode));
|
|
unnamed_101516D4 = 0x7FB026;
|
|
}
|
|
else
|
|
{
|
|
InstallHook(0x7FB060,(DWORD)RwRasterDestroy_Hook,0x59C721,RwRasterDestroy_HookJmpCode,sizeof(RwRasterDestroy_HookJmpCode));
|
|
unnamed_101516D4 = 0x7FB066;
|
|
}
|
|
|
|
InstallCallHook(0x6D0E7E,(DWORD)CVehicle__Render_Hook);
|
|
|
|
InstallMethodHook(0x866FA8,(DWORD)CObject__Render_Hook);
|
|
|
|
InstallCallHook(0x586C0A,(DWORD)CRadar__DrawMap__FindPlayerSpeed_Hook);
|
|
|
|
InstallHook(0x538090,(DWORD)CFileLoader__LoadObjectInstance_Hook,0x538084,CFileLoader__LoadObjectInstance_HookJmpCode,sizeof(CFileLoader__LoadObjectInstance_HookJmpCode));
|
|
|
|
InstallCallHook(0x718599,(DWORD)CEscalator__Update_Hook);
|
|
|
|
InstallMethodHook(0x866F7C,(DWORD)CObject__CreateRwObject_Hook);
|
|
|
|
InstallMethodHook(0x866F80,(DWORD)CEntity__DeleteRwObject_Hook);
|
|
InstallMethodHook(0x8585E8,(DWORD)CEntity__DeleteRwObject_Hook);
|
|
|
|
InstallMethodHook(0x871218,(DWORD)CAutomobile__BreakTowLink_Hook);
|
|
InstallMethodHook(0x871778,(DWORD)CAutomobile__BreakTowLink_Hook);
|
|
InstallMethodHook(0x8718D0,(DWORD)CAutomobile__BreakTowLink_Hook);
|
|
InstallMethodHook(0x871A40,(DWORD)CAutomobile__BreakTowLink_Hook);
|
|
InstallMethodHook(0x871BE0,(DWORD)CAutomobile__BreakTowLink_Hook);
|
|
|
|
InstallCallHook(0x5648D3,(DWORD)CWorld__ProcessAttachedEntities__PositionAttachedEntity_Hook);
|
|
|
|
InstallCallHook(0x53DFDD,(DWORD)CRenderer__RenderEverythingBarRoads_Hook);
|
|
|
|
InstallCallHook(0x53E019,(DWORD)CRenderer__RenderFadingInEntities_Hook);
|
|
|
|
InstallHook(0x5534B0,(DWORD)CRenderer__AddEntityToRenderList_Hook,0x5534A6,CRenderer__AddEntityToRenderList_HookJmpCode,sizeof(CRenderer__AddEntityToRenderList_HookJmpCode));
|
|
|
|
InstallCallHook(0x5342F9,(DWORD)CEntity__RenderEffects__RenderRoadsignAtomic_Hook);
|
|
|
|
InstallHook(0x4B35A0,(DWORD)CEventDamage__AffectsPed_Hook,0x4B3433,CEventDamage__AffectsPed_HookJmpCode,sizeof(CEventDamage__AffectsPed_HookJmpCode));
|
|
|
|
InstallCallHook(0x41B02E,(DWORD)CCollision__BuildCacheOfCameraCollision_Hook);
|
|
|
|
InstallCallHook(0x41AF80,(DWORD)CCollision__CheckCameraCollisionVehicles_Hook);
|
|
|
|
InstallCallHook(0x41AB78,(DWORD)CWorld__CameraToIgnoreThisObject_Hook);
|
|
|
|
InstallMethodHook(0x871178,(DWORD)CAutomobile__ProcessEntityCollision_Hook);
|
|
InstallMethodHook(0x8716D8,(DWORD)CAutomobile__ProcessEntityCollision_Hook);
|
|
InstallMethodHook(0x8719A0,(DWORD)CAutomobile__ProcessEntityCollision_Hook);
|
|
InstallMethodHook(0x871B40,(DWORD)CAutomobile__ProcessEntityCollision_Hook);
|
|
|
|
InstallMethodHook(0x8713B8,(DWORD)CBike__ProcessEntityCollision_Hook);
|
|
InstallMethodHook(0x871580,(DWORD)CBike__ProcessEntityCollision_Hook);
|
|
|
|
InstallMethodHook(0x871830,(DWORD)CMonsterTruck__ProcessEntityCollision_Hook);
|
|
|
|
InstallMethodHook(0x8721F8,(DWORD)CPhysical__ProcessEntityCollision_Hook);
|
|
|
|
InstallCallHook(0x6E0954,(DWORD)CVehicle__UsesSiren_Hook);
|
|
InstallCallHook(0x6B2BCB,(DWORD)CVehicle__UsesSiren_Hook);
|
|
InstallCallHook(0x4F77DA,(DWORD)CVehicle__UsesSiren_Hook);
|
|
|
|
InstallMethodHook(0x872A74,(DWORD)CAEWeatherAudioEntity__UpdateParameters_Hook);
|
|
|
|
InstallHook(0x5674E0,(DWORD)CWorld__ProcessVerticalLine_Hook,0x5674DB,CWorld__ProcessVerticalLine_HookJmpCode,sizeof(CWorld__ProcessVerticalLine_HookJmpCode));
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
void InstallModelInfoHackHooks()
|
|
{
|
|
InstallHook(0x4087EA,(DWORD)CStreaming__RequestModel_Hook,0x4087D7,CStreaming__RequestModel_HookJmpCode,sizeof(CStreaming__RequestModel_HookJmpCode));
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
void InstallShotSyncHooks()
|
|
{
|
|
InstallCallHook(0x742495,(DWORD)CWeapon__FireInstantHit_Hook);
|
|
InstallCallHook(0x7424EC,(DWORD)CWeapon__FireInstantHit_Hook);
|
|
InstallCallHook(0x742548,(DWORD)CWeapon__FireInstantHit_Hook);
|
|
|
|
InstallCallHook(0x740721,(DWORD)CWorld__ProcessLineOfSight_Hook);
|
|
InstallCallHook(0x740B69,(DWORD)CWorld__ProcessLineOfSight_Hook);
|
|
InstallCallHook(0x736247,(DWORD)CWorld__ProcessLineOfSight_Hook);
|
|
|
|
InstallCallHook(0x7424CB,(DWORD)CWeapon__FireSniper_Hook);
|
|
|
|
InstallCallHook(0x73AC4B,(DWORD)CBulletInfo__AddBullet_Hook);
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
|
|
void InstallVehicleFriendyFireHooks()
|
|
{
|
|
InstallCallHook(0x6D7C90,(DWORD)CVehicle__InflictDamage_Hook,0xE9);
|
|
}
|
|
|
|
//-----------------------------------------------------------
|