diff options
60 files changed, 844 insertions, 53 deletions
diff --git a/src/BulletTraces.cpp b/src/BulletTraces.cpp index a873875c..e7348a7b 100644 --- a/src/BulletTraces.cpp +++ b/src/BulletTraces.cpp @@ -1,3 +1,7 @@ +#include "common.h" +#include "patcher.h" #include "BulletTraces.h" CBulletTrace (&CBulletTraces::aTraces)[16] = *(CBulletTrace(*)[16])*(uintptr*)0x72B1B8; + +WRAPPER void CBulletTraces::Init(void) { EAXJMP(0x518DE0); } diff --git a/src/BulletTraces.h b/src/BulletTraces.h index 34d2bcc6..5a37c53c 100644 --- a/src/BulletTraces.h +++ b/src/BulletTraces.h @@ -6,4 +6,6 @@ class CBulletTraces { public: static CBulletTrace(&aTraces)[16]; + + static void Init(void); }; diff --git a/src/Camera.cpp b/src/Camera.cpp index 999792dd..e2dd12ff 100644 --- a/src/Camera.cpp +++ b/src/Camera.cpp @@ -1282,4 +1282,6 @@ STARTPATCHES InjectHook(0x45E3A0, &CCam::Process_FollowPed, PATCH_JUMP); InjectHook(0x45BE60, &CCam::Process_BehindCar, PATCH_JUMP); InjectHook(0x45C090, &CCam::Process_Cam_On_A_String, PATCH_JUMP); + + InjectHook(0x473250, &CCamera::dtor, PATCH_JUMP); ENDPATCHES diff --git a/src/Camera.h b/src/Camera.h index 9154b614..2316fd5d 100644 --- a/src/Camera.h +++ b/src/Camera.h @@ -458,6 +458,8 @@ int m_iModeObbeCamIsInForCar; void RenderMotionBlur(void); void DrawBordersForWideScreen(void); + + void dtor(void) { this->CCamera::~CCamera(); } }; static_assert(offsetof(CCamera, m_WideScreenOn) == 0x70, "CCamera: error"); static_assert(offsetof(CCamera, WorldViewerBeingUsed) == 0x75, "CCamera: error"); diff --git a/src/DamageManager.cpp b/src/DamageManager.cpp index d4c8f16e..a065e187 100644 --- a/src/DamageManager.cpp +++ b/src/DamageManager.cpp @@ -1 +1,21 @@ -#include "DamageManager.h"
\ No newline at end of file +#include "common.h" +#include "patcher.h" +#include "DamageManager.h" + +#if 0 +WRAPPER void CDamageManager::SetDoorStatus(int door, unsigned int status) { EAXJMP(0x545920); } +#else +void CDamageManager::SetDoorStatus(int door, unsigned int status) +{ + m_bDoorStatus[door] = status; +} +#endif + +#if 0 +WRAPPER unsigned int CDamageManager::GetDoorStatus(int door) { EAXJMP(0x545930); } +#else +unsigned int CDamageManager::GetDoorStatus(int door) +{ + return m_bDoorStatus[door]; +} +#endif
\ No newline at end of file diff --git a/src/DamageManager.h b/src/DamageManager.h index 4f1fa640..01269a42 100644 --- a/src/DamageManager.h +++ b/src/DamageManager.h @@ -5,6 +5,16 @@ class CDamageManager { public: + + enum { + CAR_DOOR_BONNET = 0, + CAR_DOOR_BUMPER, + CAR_DOOR_LF, + CAR_DOOR_RF, + CAR_DOOR_LR, + CAR_DOOR_RR + }; + float field_0; char m_bEngineStatus; char m_bWheelStatus[4]; @@ -15,4 +25,7 @@ public: char field_25; char field_26; char field_27; + + void SetDoorStatus(int, unsigned int); + unsigned int GetDoorStatus(int); };
\ No newline at end of file diff --git a/src/EmergencyPed.cpp b/src/EmergencyPed.cpp new file mode 100644 index 00000000..7b847896 --- /dev/null +++ b/src/EmergencyPed.cpp @@ -0,0 +1,7 @@ +#include "common.h" +#include "patcher.h" +#include "EmergencyPed.h" + +STARTPATCHES +InjectHook(0x4C2EF0, &CEmergencyPed::dtor, PATCH_JUMP); +ENDPATCHES
\ No newline at end of file diff --git a/src/Fire.cpp b/src/Fire.cpp new file mode 100644 index 00000000..05d72199 --- /dev/null +++ b/src/Fire.cpp @@ -0,0 +1,5 @@ +#include "common.h" +#include "patcher.h" +#include "Fire.h" + +WRAPPER void CFire::Extinguish(void) { EAXJMP(0x479D40); }
\ No newline at end of file diff --git a/src/Fire.h b/src/Fire.h new file mode 100644 index 00000000..c7f83fd8 --- /dev/null +++ b/src/Fire.h @@ -0,0 +1,23 @@ +#pragma once +#include "common.h" +#include "Entity.h" + +class CFire +{ + char m_bIsOngoing; + char m_bExists; + char m_bPropogationFlag; + char m_bAudioSet; + CVector m_vecPos; + CEntity *m_pEntity; + CEntity *m_pSource; + int m_nExtinguishTime; + int m_nStartTime; + int field_20; + int field_24; + int field_28; + float field_2C; + +public: + void Extinguish(void); +};
\ No newline at end of file diff --git a/src/MloInstance.cpp b/src/MloInstance.cpp new file mode 100644 index 00000000..dbd83727 --- /dev/null +++ b/src/MloInstance.cpp @@ -0,0 +1,7 @@ +#include "common.h" +#include "patcher.h" +#include "MloInstance.h" + +STARTPATCHES +InjectHook(0x50BE90, &CMloInstance::dtor, PATCH_JUMP); +ENDPATCHES
\ No newline at end of file diff --git a/src/MloInstance.h b/src/MloInstance.h new file mode 100644 index 00000000..00afc379 --- /dev/null +++ b/src/MloInstance.h @@ -0,0 +1,9 @@ +#pragma once + +#include "Placeable.h" + +class CMloInstance : CPlaceable +{ +public: + void dtor() { this->CMloInstance::~CMloInstance(); } +};
\ No newline at end of file diff --git a/src/ParticleObject.cpp b/src/ParticleObject.cpp index bd5e6b0a..58f2cfcb 100644 --- a/src/ParticleObject.cpp +++ b/src/ParticleObject.cpp @@ -4,7 +4,6 @@ WRAPPER void CParticleObject::AddObject(uint16, const CVector &pos, bool remove) { EAXJMP(0x4BC4D0); } - // Converted from static void __cdecl CParticleObject::Initialise() 0x42C760 void CParticleObject::Initialise() { @@ -15,4 +14,8 @@ void CParticleObject::Initialise() void CParticleObject::UpdateAll() { ((void (__cdecl *)())0x4BCA30)(); -}
\ No newline at end of file +} + +STARTPATCHES + InjectHook(0x4BC420, &CParticleObject::dtor, PATCH_JUMP); +ENDPATCHES
\ No newline at end of file diff --git a/src/ParticleObject.h b/src/ParticleObject.h index d6b48810..34debbfd 100644 --- a/src/ParticleObject.h +++ b/src/ParticleObject.h @@ -1,5 +1,7 @@ #pragma once +#include "Placeable.h" + enum eParticleObjectType { POBJECT_PAVEMENT_STEAM, @@ -24,10 +26,12 @@ enum eParticleObjectType POBJECT_CATALINAS_SHOTGUNFLASH, }; -class CParticleObject +class CParticleObject : CPlaceable { public: static void AddObject(uint16, const CVector &pos, bool remove); static void Initialise(); static void UpdateAll(); + + void dtor() { this->CParticleObject::~CParticleObject(); } }; diff --git a/src/audio/DMAudio.cpp b/src/audio/DMAudio.cpp index 63f23c4a..b3887c70 100644 --- a/src/audio/DMAudio.cpp +++ b/src/audio/DMAudio.cpp @@ -27,3 +27,4 @@ WRAPPER void cDMAudio::SetMusicFadeVol(uint8) { EAXJMP(0x57C920); } WRAPPER int32 cDMAudio::CreateEntity(int, void*) { EAXJMP(0x57C7C0); } WRAPPER void cDMAudio::SetEntityStatus(int32 id, uint8 enable) { EAXJMP(0x57C810); } WRAPPER void cDMAudio::SetRadioInCar(int32) { EAXJMP(0x57CE60); } +WRAPPER void cDMAudio::DestroyEntity(int32) { EAXJMP(0x57C7F0); } diff --git a/src/audio/DMAudio.h b/src/audio/DMAudio.h index ea5aeeb2..46b40e37 100644 --- a/src/audio/DMAudio.h +++ b/src/audio/DMAudio.h @@ -196,6 +196,6 @@ public: void SetEntityStatus(int32 id, uint8 enable); void SetRadioInCar(int32); uint8 IsMP3RadioChannelAvailable(); - + void DestroyEntity(int32); }; extern cDMAudio &DMAudio; diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index 145c643c..1b389631 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -3,6 +3,8 @@ #include "CarCtrl.h" int &CCarCtrl::NumLawEnforcerCars = *(int*)0x8F1B38; +int &CCarCtrl::NumAmbulancesOnDuty = *(int*)0x885BB0; +int &CCarCtrl::NumFiretrucksOnDuty = *(int*)0x9411F0; bool &CCarCtrl::bCarsGeneratedAroundCamera = *(bool*)0x95CD8A; WRAPPER void CCarCtrl::SwitchVehicleToRealPhysics(CVehicle*) { EAXJMP(0x41F7F0); } diff --git a/src/control/CarCtrl.h b/src/control/CarCtrl.h index 3469dcf1..0195219e 100644 --- a/src/control/CarCtrl.h +++ b/src/control/CarCtrl.h @@ -11,5 +11,7 @@ public: static int32 ChooseCarModel(int32 vehclass); static int32 &NumLawEnforcerCars; + static int32 &NumAmbulancesOnDuty; + static int32 &NumFiretrucksOnDuty; static bool &bCarsGeneratedAroundCamera; }; diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp index e80d8746..4733f6f2 100644 --- a/src/control/Replay.cpp +++ b/src/control/Replay.cpp @@ -1,11 +1,14 @@ #include "common.h" #include "patcher.h" #include "AnimBlendAssociation.h" +#include "Boat.h" #include "BulletTraces.h" #include "CarCtrl.h" +#include "CivilianPed.h" #include "Clock.h" #include "DMAudio.h" #include "Draw.h" +#include "Heli.h" #include "math/Matrix.h" #include "ModelIndices.h" #include "ModelInfo.h" @@ -13,6 +16,7 @@ #include "Pad.h" #include "PhoneInfo.h" #include "Pickups.h" +#include "Plane.h" #include "Pools.h" #include "Population.h" #include "Replay.h" @@ -22,6 +26,7 @@ #include "render/Skidmarks.h" #include "Streaming.h" #include "Timer.h" +#include "Train.h" #include "Weather.h" #include "Zones.h" #include "Font.h" @@ -82,11 +87,13 @@ bool &CReplay::bAllowLookAroundCam = *(bool*)0x95CDCD; float &CReplay::LoadSceneX = *(float*)0x880F9C; float &CReplay::LoadSceneY = *(float*)0x880F98; float &CReplay::LoadSceneZ = *(float*)0x880F94; +float &CReplay::CameraFocusX = *(float*)0x942F5C; +float &CReplay::CameraFocusY = *(float*)0x942F74; +float &CReplay::CameraFocusZ = *(float*)0x942F58; +bool &CReplay::bPlayerInRCBuggy = *(bool*)0x95CDC3; -#if 1 static void(*(&CBArray)[30])(CAnimBlendAssociation*, void*) = *(void(*(*)[30])(CAnimBlendAssociation*, void*))*(uintptr*)0x61052C; -#else -static void(*CBArray[])(CAnimBlendAssociation*, void*) = +static void(*CBArray_RE3[])(CAnimBlendAssociation*, void*) = { nil, &CPed::PedGetupCB, &CPed::PedStaggerCB, &CPed::PedEvadeCB, &CPed::FinishDieAnimCB, &CPed::FinishedWaitCB, &CPed::FinishLaunchCB, &CPed::FinishHitHeadCB, &CPed::PedAnimGetInCB, &CPed::PedAnimDoorOpenCB, @@ -95,7 +102,6 @@ static void(*CBArray[])(CAnimBlendAssociation*, void*) = &CPed::FinishFightMoveCB, &PhonePutDownCB, &PhonePickUpCB, &CPed::PedAnimDoorCloseRollingCB, &CPed::FinishJumpCB, &CPed::PedLandCB, &FinishFuckUCB, &CPed::RestoreHeadingRateCB, &CPed::PedSetQuickDraggedOutCarPositionCB, &CPed::PedSetDraggedOutCarPositionCB }; -#endif #if 0 WRAPPER uint8 FindCBFunctionID(void(*f)(CAnimBlendAssociation*, void*)) { EAXJMP(0x584E70); } @@ -106,13 +112,17 @@ static uint8 FindCBFunctionID(void(*f)(CAnimBlendAssociation*, void*)) if (CBArray[i] == f) return i; } + for (int i = 0; i < sizeof(CBArray_RE3) / sizeof(*CBArray_RE3); i++) { + if (CBArray_RE3[i] == f) + return i; + } return 0; } #endif static void(*FindCBFunction(uint8 id))(CAnimBlendAssociation*, void*) { - return CBArray[id]; + return CBArray_RE3[id]; } WRAPPER static void ApplyPanelDamageToCar(uint32, CAutomobile*, bool) { EAXJMP(0x584EA0); } @@ -410,36 +420,37 @@ WRAPPER void CReplay::ProcessPedUpdate(CPed *ped, float interpolation, CAddressI void CReplay::ProcessPedUpdate(CPed *ped, float interpolation, CAddressInReplayBuffer *buffer) { tPedUpdatePacket *pp = (tPedUpdatePacket*)&buffer->m_pBase[buffer->m_nOffset]; - if (ped){ - ped->m_fRotationCur = pp->heading * M_PI / 128.0f; - ped->m_fRotationDest = pp->heading * M_PI / 128.0f; - CMatrix ped_matrix; - pp->matrix.DecompressIntoFullMatrix(ped_matrix); - ped->GetMatrix() = ped->GetMatrix() * CMatrix(1.0f - interpolation); - *ped->GetMatrix().GetPosition() *= (1.0f - interpolation); - ped->GetMatrix() += CMatrix(interpolation) * ped_matrix; - if (pp->vehicle_index) { - ped->m_pMyVehicle = CPools::GetVehiclePool()->GetSlot(pp->vehicle_index - 1); - ped->bInVehicle = pp->vehicle_index; - } - else { - ped->m_pMyVehicle = nil; - ped->bInVehicle = false; - } - if (pp->assoc_group_id != ped->m_animGroup) { - ped->m_animGroup = (AssocGroupId)pp->assoc_group_id; - if (ped == FindPlayerPed()) - ((CPlayerPed*)ped)->ReApplyMoveAnims(); - } - RetrievePedAnimation(ped, &pp->anim_state); - ped->RemoveWeaponModel(-1); - if (pp->weapon_model != (uint8)-1) - ped->AddWeaponModel(pp->weapon_model); - CWorld::Remove(ped); - CWorld::Add(ped); - }else{ + if (!ped){ debug("Replay:Ped wasn't there\n"); + buffer->m_nOffset += sizeof(tPedUpdatePacket); + return; + } + ped->m_fRotationCur = pp->heading * M_PI / 128.0f; + ped->m_fRotationDest = pp->heading * M_PI / 128.0f; + CMatrix ped_matrix; + pp->matrix.DecompressIntoFullMatrix(ped_matrix); + ped->GetMatrix() = ped->GetMatrix() * CMatrix(1.0f - interpolation); + *ped->GetMatrix().GetPosition() *= (1.0f - interpolation); + ped->GetMatrix() += CMatrix(interpolation) * ped_matrix; + if (pp->vehicle_index) { + ped->m_pMyVehicle = CPools::GetVehiclePool()->GetSlot(pp->vehicle_index - 1); + ped->bInVehicle = pp->vehicle_index; } + else { + ped->m_pMyVehicle = nil; + ped->bInVehicle = false; + } + if (pp->assoc_group_id != ped->m_animGroup) { + ped->m_animGroup = (AssocGroupId)pp->assoc_group_id; + if (ped == FindPlayerPed()) + ((CPlayerPed*)ped)->ReApplyMoveAnims(); + } + RetrievePedAnimation(ped, &pp->anim_state); + ped->RemoveWeaponModel(-1); + if (pp->weapon_model != (uint8)-1) + ped->AddWeaponModel(pp->weapon_model); + CWorld::Remove(ped); + CWorld::Add(ped); buffer->m_nOffset += sizeof(tPedUpdatePacket); } #endif @@ -533,7 +544,35 @@ void CReplay::RetrieveDetailedPedAnimation(CPed *ped, CStoredDetailedAnimationSt } } #endif + +#if 0 WRAPPER void CReplay::PlaybackThisFrame(void) { EAXJMP(0x5946B0); } +#else +void CReplay::PlaybackThisFrame(void) +{ + static int SlowMotionCounter = 0; + CAddressInReplayBuffer buf = Playback; + if (PlayBackThisFrameInterpolation(&buf, 1.0f, nil)){ + DMAudio.SetEffectsFadeVol(127); + DMAudio.SetMusicFadeVol(127); + return; + } + if (SlowMotionCounter){ + CAddressInReplayBuffer buf_sm = buf; + if (PlayBackThisFrameInterpolation(&buf_sm, SlowMotionCounter * 1.0f / SlowMotion, nil)){ + DMAudio.SetEffectsFadeVol(127); + DMAudio.SetMusicFadeVol(127); + return; + } + } + SlowMotionCounter = (SlowMotionCounter + 1) % SlowMotion; + if (SlowMotionCounter == 0) + Playback = buf; + ProcessLookAroundCam(); + DMAudio.SetEffectsFadeVol(0); + DMAudio.SetMusicFadeVol(0); +} +#endif #if 0 WRAPPER void CReplay::StoreCarUpdate(CVehicle *vehicle, int id) { EAXJMP(0x5947F0); } @@ -574,10 +613,325 @@ void CReplay::StoreCarUpdate(CVehicle *vehicle, int id) Record.m_nOffset += sizeof(tVehicleUpdatePacket); } #endif + +#if 0 WRAPPER void CReplay::ProcessCarUpdate(CVehicle *vehicle, float interpolation, CAddressInReplayBuffer *buffer) { EAXJMP(0x594D10); } +#else +void CReplay::ProcessCarUpdate(CVehicle *vehicle, float interpolation, CAddressInReplayBuffer *buffer) +{ + tVehicleUpdatePacket* vp = (tVehicleUpdatePacket*)&buffer->m_pBase[buffer->m_nOffset]; + if (!vehicle){ + debug("Replay:Car wasn't there"); + return; + } + CMatrix vehicle_matrix; + vp->matrix.DecompressIntoFullMatrix(vehicle_matrix); + vehicle->GetMatrix() = vehicle->GetMatrix() * CMatrix(1.0f - interpolation); + *vehicle->GetMatrix().GetPosition() *= (1.0f - interpolation); + vehicle->GetMatrix() += CMatrix(interpolation) * vehicle_matrix; + vehicle->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f); + vehicle->m_fHealth = 4 * vp->health; + vehicle->m_fGasPedal = vp->acceleration / 100.0f; + if (vehicle->IsCar()) + ApplyPanelDamageToCar(vp->panels, (CAutomobile*)vehicle, true); + vehicle->m_vecMoveSpeed = CVector(vp->velocityX / 8000.0f, vp->velocityY / 8000.0f, vp->velocityZ / 8000.0f); + if (vehicle->GetModelIndex() == MI_RHINO) { + ((CAutomobile*)vehicle)->m_fCarGunLR = vp->car_gun * M_PI / 128.0f; + vehicle->m_fSteerAngle = 0.0f; + }else{ + vehicle->m_fSteerAngle = vp->wheel_state / 50.0f; + } + if (vehicle->IsCar()) { + CAutomobile* car = (CAutomobile*)vehicle; + for (int i = 0; i < 4; i++) { + car->m_afWheelSuspDist[i] = vp->wheel_susp_dist[i] / 50.0f; + car->m_afWheelRotation[i] = vp->wheel_rotation[i] * M_PI / 128.0f; + } + car->m_aDoors[2].m_fAngle = car->m_aDoors[2].m_fPreviousAngle = vp->door_angles[0] * M_PI / 127.0f; + car->m_aDoors[3].m_fAngle = car->m_aDoors[3].m_fPreviousAngle = vp->door_angles[1] * M_PI / 127.0f; + if (vp->door_angles[0]) + car->m_DamageManager.m_bDoorStatus[2] = 2; + if (vp->door_angles[1]) + car->m_DamageManager.m_bDoorStatus[3] = 2; + if (vp->door_status & 1 && car->m_DamageManager.GetDoorStatus(CDamageManager::CAR_DOOR_BONNET) != 3){ + car->m_DamageManager.SetDoorStatus(CDamageManager::CAR_DOOR_BONNET, 3); + car->SetDoorDamage(17, CDamageManager::CAR_DOOR_BONNET, true); + } + if (vp->door_status & 2 && car->m_DamageManager.GetDoorStatus(CDamageManager::CAR_DOOR_BUMPER) != 3) { + car->m_DamageManager.SetDoorStatus(CDamageManager::CAR_DOOR_BUMPER, 3); + car->SetDoorDamage(18, CDamageManager::CAR_DOOR_BUMPER, true); + } + if (vp->door_status & 4 && car->m_DamageManager.GetDoorStatus(CDamageManager::CAR_DOOR_LF) != 3) { + car->m_DamageManager.SetDoorStatus(CDamageManager::CAR_DOOR_LF, 3); + car->SetDoorDamage(15, CDamageManager::CAR_DOOR_LF, true); + } + if (vp->door_status & 8 && car->m_DamageManager.GetDoorStatus(CDamageManager::CAR_DOOR_RF) != 3) { + car->m_DamageManager.SetDoorStatus(CDamageManager::CAR_DOOR_RF, 3); + car->SetDoorDamage(11, CDamageManager::CAR_DOOR_RF, true); + } + if (vp->door_status & 0x10 && car->m_DamageManager.GetDoorStatus(CDamageManager::CAR_DOOR_LR) != 3) { + car->m_DamageManager.SetDoorStatus(CDamageManager::CAR_DOOR_LR, 3); + car->SetDoorDamage(16, CDamageManager::CAR_DOOR_LR, true); + } + if (vp->door_status & 0x20 && car->m_DamageManager.GetDoorStatus(CDamageManager::CAR_DOOR_RR) != 3) { + car->m_DamageManager.SetDoorStatus(CDamageManager::CAR_DOOR_RR, 3); + car->SetDoorDamage(12, CDamageManager::CAR_DOOR_RR, true); + } + vehicle->m_veh_flagA10 = true; + if (vehicle->IsCar()) + ((CAutomobile*)vehicle)->m_nDriveWheelsOnGround = 4; + CWorld::Remove(vehicle); + CWorld::Add(vehicle); + if (vehicle->IsBoat()) + ((CBoat*)vehicle)->m_bIsAnchored = false; + } +} +#endif + +#if 0 WRAPPER bool CReplay::PlayBackThisFrameInterpolation(CAddressInReplayBuffer *buffer, float interpolation, uint32 *pTimer) { EAXJMP(0x595240); } +#else +bool CReplay::PlayBackThisFrameInterpolation(CAddressInReplayBuffer *buffer, float interpolation, uint32 *pTimer){ + /* Mistake. Not even sure what this is even doing here... + * PlayerWanted is a backup to restore at the end of replay. + * Setting current wanted pointer to it makes it useless. + * Causes picking up bribes in replays reducing wanted level bug. + * Obviously fact of picking them up is a bug on its own, + * but it doesn't cancel this one. + */ + FindPlayerPed()->m_pWanted = &PlayerWanted; + + CBulletTraces::Init(); + float split = 1.0f - interpolation; + int ped_min_index = 0; /* Optimization due to peds and vehicles placed in buffer sequentially. */ + int vehicle_min_index = 0; /* So next ped can't have pool index less than current. */ + for(;;){ + uint8* ptr = buffer->m_pBase; + uint32 offset = buffer->m_nOffset; + uint8 type = ptr[offset]; + if (type == REPLAYPACKET_ENDOFFRAME) + break; + switch (type) { + case REPLAYPACKET_END: + { + int slot = buffer->m_bSlot; + if (BufferStatus[slot] == REPLAYBUFFER_RECORD) { + FinishPlayback(); + return true; + } + buffer->m_bSlot = (slot + 1) % 8; + buffer->m_nOffset = 0; + buffer->m_pBase = Buffers[buffer->m_bSlot]; + ped_min_index = 0; + vehicle_min_index = 0; + break; + } + case REPLAYPACKET_VEHICLE: + { + tVehicleUpdatePacket* vp = (tVehicleUpdatePacket*)&ptr[offset]; + for (int i = vehicle_min_index; i < vp->index; i++) { + CVehicle* v = CPools::GetVehiclePool()->GetSlot(i); + if (!v) + continue; + /* Removing vehicles not present in this frame. */ + CWorld::Remove(v); + delete v; + } + vehicle_min_index = vp->index + 1; + CVehicle* v = CPools::GetVehiclePool()->GetSlot(vp->index); + CVehicle* new_v; + if (!v) { + int mi = vp->mi; + if (CStreaming::ms_aInfoForModel[mi].m_loadState != 1) { + CStreaming::RequestModel(mi, 0); + } + else { + if (mi == MI_DEADDODO || mi == MI_AIRTRAIN) { + new_v = new(vp->index << 8) CPlane(mi, 2); + } + else if (mi == MI_TRAIN) { + new_v = new(vp->index << 8) CTrain(mi, 2); + } + else if (mi == MI_CHOPPER || mi == MI_ESCAPE) { + new_v = new(vp->index << 8) CHeli(mi, 2); + } + else if (CModelInfo::IsBoatModel(mi)){ + new_v = new(vp->index << 8) CBoat(mi, 2); + } + else{ + new_v = new(vp->index << 8) CAutomobile(mi, 2); + } + new_v->m_status = STATUS_PLAYER_PLAYBACKFROMBUFFER; + vp->matrix.DecompressIntoFullMatrix(new_v->GetMatrix()); + new_v->m_currentColour1 = vp->primary_color; + new_v->m_currentColour2 = vp->secondary_color; + CWorld::Add(new_v); + } + } + ProcessCarUpdate(CPools::GetVehiclePool()->GetSlot(vp->index), interpolation, buffer); + buffer->m_nOffset += sizeof(tVehicleUpdatePacket); + break; + } + case REPLAYPACKET_PED_HEADER: + { + tPedHeaderPacket* ph = (tPedHeaderPacket*)&ptr[offset]; + if (!CPools::GetPedPool()->GetSlot(ph->index)) { + if (CStreaming::ms_aInfoForModel[ph->mi].m_loadState != 1) { + CStreaming::RequestModel(ph->mi, 0); + } + else { + CPed* new_p = new(ph->index << 8) CCivilianPed(ph->pedtype, ph->mi); + new_p->m_status = STATUS_PLAYER_PLAYBACKFROMBUFFER; + new_p->GetMatrix().SetUnity(); + CWorld::Add(new_p); + } + } + buffer->m_nOffset += sizeof(tPedHeaderPacket); + break; + } + case REPLAYPACKET_PED_UPDATE: + { + tPedUpdatePacket* pu = (tPedUpdatePacket*)&ptr[offset]; + for (int i = ped_min_index; i < pu->index; i++) { + CPed* p = CPools::GetPedPool()->GetSlot(i); + if (!p) + continue; + /* Removing peds not present in this frame. */ + CWorld::Remove(p); + delete p; + } + ped_min_index = pu->index + 1; + ProcessPedUpdate(CPools::GetPedPool()->GetSlot(pu->index), interpolation, buffer); + break; + } + case REPLAYPACKET_GENERAL: + { + tGeneralPacket* pg = (tGeneralPacket*)&ptr[offset]; + TheCamera.GetMatrix() = TheCamera.GetMatrix() * CMatrix(split); + *TheCamera.GetMatrix().GetPosition() *= split; + TheCamera.GetMatrix() += CMatrix(interpolation) * pg->camera_pos; + RwMatrix* pm = &RpAtomicGetFrame(&TheCamera.m_pRwCamera->object.object)->modelling; + pm->pos = *(RwV3d*)TheCamera.GetMatrix().GetPosition(); + pm->at = *(RwV3d*)TheCamera.GetMatrix().GetForward(); + pm->up = *(RwV3d*)TheCamera.GetMatrix().GetUp(); + pm->right = *(RwV3d*)TheCamera.GetMatrix().GetRight(); + CameraFocusX = split * CameraFocusX + interpolation * pg->player_pos.x; + CameraFocusY = split * CameraFocusY + interpolation * pg->player_pos.y; + CameraFocusZ = split * CameraFocusZ + interpolation * pg->player_pos.z; + bPlayerInRCBuggy = pg->in_rcvehicle; + buffer->m_nOffset += sizeof(tGeneralPacket); + break; + } + case REPLAYPACKET_CLOCK: + { + tClockPacket* pc = (tClockPacket*)&ptr[offset]; + CClock::SetGameClock(pc->hours, pc->minutes); + buffer->m_nOffset += sizeof(tClockPacket); + break; + } + case REPLAYPACKET_WEATHER: + { + tWeatherPacket* pw = (tWeatherPacket*)&ptr[offset]; + CWeather::OldWeatherType = pw->old_weather; + CWeather::NewWeatherType = pw->new_weather; + CWeather::InterpolationValue = pw->interpolation; + buffer->m_nOffset += sizeof(tWeatherPacket); + break; + } + case REPLAYPACKET_ENDOFFRAME: + { + /* Not supposed to be here. */ + buffer->m_nOffset++; + break; + } + case REPLAYPACKET_TIMER: + { + tTimerPacket* pt = (tTimerPacket*)&ptr[offset]; + if (pTimer) + *pTimer = pt->timer; + CTimer::SetTimeInMilliseconds(pt->timer); + buffer->m_nOffset += sizeof(tTimerPacket); + break; + } + case REPLAYPACKET_BULLET_TRACES: + { + tBulletTracePacket* pb = (tBulletTracePacket*)&ptr[offset]; + CBulletTraces::aTraces[pb->index].m_bInUse = true; + CBulletTraces::aTraces[pb->index].m_bFramesInUse = pb->frames; + CBulletTraces::aTraces[pb->index].m_bLifeTime = pb->lifetime; + CBulletTraces::aTraces[pb->index].m_vecInf = pb->inf; + CBulletTraces::aTraces[pb->index].m_vecSup = pb->sup; + buffer->m_nOffset += sizeof(tBulletTracePacket); + } + default: + break; + } + } + buffer->m_nOffset += 4; + for (int i = vehicle_min_index; i < CPools::GetVehiclePool()->GetSize(); i++) { + CVehicle* v = CPools::GetVehiclePool()->GetSlot(i); + if (!v) + continue; + /* Removing vehicles not present in this frame. */ + CWorld::Remove(v); + delete v; + } + for (int i = ped_min_index; i < CPools::GetPedPool()->GetSize(); i++) { + CPed* p = CPools::GetPedPool()->GetSlot(i); + if (!p) + continue; + /* Removing peds not present in this frame. */ + CWorld::Remove(p); + delete p; + } + ProcessReplayCamera(); + return false; +} +#endif +#if 0 WRAPPER void CReplay::FinishPlayback(void) { EAXJMP(0x595B20); } +#else +void CReplay::FinishPlayback(void) +{ + if (Mode != MODE_PLAYBACK) + return; + EmptyAllPools(); + RestoreStuffFromMem(); + Mode = MODE_RECORD; + if (bDoLoadSceneWhenDone){ + CVector v_ls(LoadSceneX, LoadSceneY, LoadSceneZ); + CGame::currLevel = CTheZones::GetLevelFromPosition(v_ls); + CCollision::SortOutCollisionAfterLoad(); + CStreaming::LoadScene(v_ls); + } + bDoLoadSceneWhenDone = false; + if (bPlayingBackFromFile){ + Init(); + MarkEverythingAsNew(); + } + DMAudio.SetEffectsFadeVol(127); + DMAudio.SetMusicFadeVol(127); +} +#endif + +#if 0 WRAPPER void CReplay::EmptyReplayBuffer(void) { EAXJMP(0x595BD0); } +#else +void CReplay::EmptyReplayBuffer(void) +{ + if (Mode == MODE_PLAYBACK) + return; + for (int i = 0; i < 8; i++){ + BufferStatus[i] = REPLAYBUFFER_UNUSED; + } + Record.m_bSlot = 0; + Record.m_pBase = Buffers[0]; + BufferStatus[0] = REPLAYBUFFER_RECORD; + Record.m_pBase[Record.m_nOffset] = 0; + MarkEverythingAsNew(); +} +#endif + WRAPPER void CReplay::ProcessReplayCamera(void) { EAXJMP(0x595C40); } #if 0 @@ -883,6 +1237,8 @@ InjectHook(0x593150, CReplay::DisableReplays, PATCH_JUMP); InjectHook(0x593160, CReplay::EnableReplays, PATCH_JUMP); InjectHook(0x593170, CReplay::Update, PATCH_JUMP); InjectHook(0x594050, CReplay::ProcessPedUpdate, PATCH_JUMP); +InjectHook(0x594D10, CReplay::ProcessCarUpdate, PATCH_JUMP); +InjectHook(0x593BB0, CReplay::StoreDetailedPedAnimation, PATCH_JUMP); InjectHook(0x5944B0, CReplay::RetrieveDetailedPedAnimation, PATCH_JUMP); //InjectHook(0x5966E0, CReplay::RestoreStuffFromMem, PATCH_JUMP); ENDPATCHES diff --git a/src/control/Replay.h b/src/control/Replay.h index 125dfef4..f44e4c41 100644 --- a/src/control/Replay.h +++ b/src/control/Replay.h @@ -241,6 +241,10 @@ private: static float &LoadSceneX; static float &LoadSceneY; static float &LoadSceneZ; + static float &CameraFocusX; + static float &CameraFocusY; + static float &CameraFocusZ; + static bool &bPlayerInRCBuggy; public: static void Init(void); @@ -257,25 +261,21 @@ public: inline static bool IsPlayingBack() { return Mode == MODE_PLAYBACK; } inline static bool IsPlayingBackFromFile() { return bPlayingBackFromFile; } -private: +//private: static void RecordThisFrame(void); static void StorePedUpdate(CPed *ped, int id); static void StorePedAnimation(CPed *ped, CStoredAnimationState *state); static void StoreDetailedPedAnimation(CPed *ped, CStoredDetailedAnimationState *state); -public: static void ProcessPedUpdate(CPed *ped, float interpolation, CAddressInReplayBuffer *buffer); static void RetrievePedAnimation(CPed *ped, CStoredAnimationState *state); static void RetrieveDetailedPedAnimation(CPed *ped, CStoredDetailedAnimationState *state); -private: static void PlaybackThisFrame(void); static void StoreCarUpdate(CVehicle *vehicle, int id); static void ProcessCarUpdate(CVehicle *vehicle, float interpolation, CAddressInReplayBuffer *buffer); static bool PlayBackThisFrameInterpolation(CAddressInReplayBuffer *buffer, float interpolation, uint32 *pTimer); static void ProcessReplayCamera(void); static void StoreStuffInMem(void); -public: /* temp */ static void RestoreStuffFromMem(void); -private: static void EmptyPedsAndVehiclePools(void); static void EmptyAllPools(void); static void MarkEverythingAsNew(void); diff --git a/src/entities/Automobile.cpp b/src/entities/Automobile.cpp index 89fac33e..e74013be 100644 --- a/src/entities/Automobile.cpp +++ b/src/entities/Automobile.cpp @@ -2,4 +2,15 @@ #include "patcher.h" #include "Automobile.h" -WRAPPER void CAutomobile::SetDoorDamage(int32, uint32, bool) { EAXJMP(0x530200); }
\ No newline at end of file +CAutomobile::CAutomobile(int mi, uint8 owner) +{ + ctor(mi, owner); +} + +WRAPPER CAutomobile* CAutomobile::ctor(int, uint8) { EAXJMP(0x52C6B0); } + +WRAPPER void CAutomobile::SetDoorDamage(int32, uint32, bool) { EAXJMP(0x530200); } + +STARTPATCHES +InjectHook(0x52D170, &CAutomobile::dtor, PATCH_JUMP); +ENDPATCHES
\ No newline at end of file diff --git a/src/entities/Automobile.h b/src/entities/Automobile.h index 7422112b..246943a7 100644 --- a/src/entities/Automobile.h +++ b/src/entities/Automobile.h @@ -18,9 +18,14 @@ public: float m_afWheelRotation[4]; uint8 stuff3[200]; float m_fCarGunLR; - uint8 stuff4[36]; + uint8 stuff4[13]; + uint8 m_nDriveWheelsOnGround; + uint8 stuff5[22]; + CAutomobile(int, uint8); + CAutomobile* ctor(int, uint8); void SetDoorDamage(int32, uint32, bool); /* TODO: eDoors */ + void dtor() { this->CAutomobile::~CAutomobile(); } }; static_assert(sizeof(CAutomobile) == 0x5A8, "CAutomobile: error"); static_assert(offsetof(CAutomobile, m_afWheelSuspDist) == 0x46C, "CAutomobile: error"); diff --git a/src/entities/Boat.cpp b/src/entities/Boat.cpp new file mode 100644 index 00000000..076a910e --- /dev/null +++ b/src/entities/Boat.cpp @@ -0,0 +1,14 @@ +#include "common.h" +#include "patcher.h" +#include "Boat.h" + +CBoat::CBoat(int mi, uint8 owner) +{ + ctor(mi, owner); +} + +WRAPPER CBoat* CBoat::ctor(int, uint8) { EAXJMP(0x53E3E0); } + +STARTPATCHES +InjectHook(0x53E790, &CBoat::dtor, PATCH_JUMP); +ENDPATCHES
\ No newline at end of file diff --git a/src/entities/Boat.h b/src/entities/Boat.h index b66ab107..6d6482a4 100644 --- a/src/entities/Boat.h +++ b/src/entities/Boat.h @@ -6,6 +6,12 @@ class CBoat : public CVehicle { public: // 0x288 - uint8 stuff[508]; + uint8 stuff1[57]; + bool m_bIsAnchored; + uint8 stuff[450]; + + CBoat(int, uint8); + CBoat* ctor(int, uint8); + void dtor() { this->CBoat::~CBoat(); }; }; static_assert(sizeof(CBoat) == 0x484, "CBoat: error"); diff --git a/src/entities/Building.cpp b/src/entities/Building.cpp index d69a65fe..b9fca96f 100644 --- a/src/entities/Building.cpp +++ b/src/entities/Building.cpp @@ -23,5 +23,6 @@ CBuilding::ReplaceWithNewModel(int32 id) STARTPATCHES InjectHook(0x4057D0, &CBuilding::ctor, PATCH_JUMP); + InjectHook(0x405800, &CBuilding::dtor, PATCH_JUMP); InjectHook(0x405850, &CBuilding::ReplaceWithNewModel, PATCH_JUMP); ENDPATCHES diff --git a/src/entities/Building.h b/src/entities/Building.h index b1f96bae..89d0a460 100644 --- a/src/entities/Building.h +++ b/src/entities/Building.h @@ -17,5 +17,6 @@ public: virtual bool GetIsATreadable(void) { return false; } CBuilding *ctor(void) { return ::new (this) CBuilding(); } + void dtor(void) { this->CBuilding::~CBuilding(); } }; static_assert(sizeof(CBuilding) == 0x64, "CBuilding: error"); diff --git a/src/entities/CivilianPed.cpp b/src/entities/CivilianPed.cpp new file mode 100644 index 00000000..cf589211 --- /dev/null +++ b/src/entities/CivilianPed.cpp @@ -0,0 +1,14 @@ +#include "common.h" +#include "patcher.h" +#include "CivilianPed.h" + +CCivilianPed::CCivilianPed(int pedtype, int mi) +{ + ctor(pedtype, mi); +} + +WRAPPER CCivilianPed* CCivilianPed::ctor(int pedtype, int mi) { EAXJMP(0x4BFF30); } + +STARTPATCHES + InjectHook(0x4BFFC0, &CCivilianPed::dtor, PATCH_JUMP); +ENDPATCHES
\ No newline at end of file diff --git a/src/entities/CivilianPed.h b/src/entities/CivilianPed.h index 7a592279..4d3346d3 100644 --- a/src/entities/CivilianPed.h +++ b/src/entities/CivilianPed.h @@ -5,5 +5,8 @@ class CCivilianPed : public CPed { public: + CCivilianPed(int, int); + CCivilianPed* ctor(int, int); + void dtor(void) { this->CCivilianPed::~CCivilianPed(); } }; static_assert(sizeof(CCivilianPed) == 0x53C, "CCivilianPed: error"); diff --git a/src/entities/CopPed.cpp b/src/entities/CopPed.cpp new file mode 100644 index 00000000..041185ee --- /dev/null +++ b/src/entities/CopPed.cpp @@ -0,0 +1,14 @@ +#include "common.h" +#include "patcher.h" +#include "CopPed.h" + +CCopPed::~CCopPed() +{ + ClearPursuit(); +} + +WRAPPER void CCopPed::ClearPursuit(void) { EAXJMP(0x4C28C0); } + +STARTPATCHES + InjectHook(0x4C13E0, &CCopPed::dtor, PATCH_JUMP); +ENDPATCHES
\ No newline at end of file diff --git a/src/entities/CopPed.h b/src/entities/CopPed.h index 23d52ad0..b938dfc2 100644 --- a/src/entities/CopPed.h +++ b/src/entities/CopPed.h @@ -63,6 +63,11 @@ public: int8 field_1365; int8 field_1366; int8 field_1367; + + ~CCopPed(); + void dtor(void) { this->CCopPed::~CCopPed(); } + + void ClearPursuit(void); }; static_assert(sizeof(CCopPed) == 0x558, "CCopPed: error"); diff --git a/src/entities/CutsceneObject.cpp b/src/entities/CutsceneObject.cpp index 9089f600..ede5be5b 100644 --- a/src/entities/CutsceneObject.cpp +++ b/src/entities/CutsceneObject.cpp @@ -90,6 +90,7 @@ CCutsceneObject::RemoveLighting(bool reset) } STARTPATCHES + InjectHook(0x4BA960, &CCutsceneObject::dtor, PATCH_JUMP); InjectHook(0x4BA980, &CCutsceneObject::SetModelIndex_, PATCH_JUMP); InjectHook(0x4BA9C0, &CCutsceneObject::ProcessControl_, PATCH_JUMP); InjectHook(0x4BAA40, &CCutsceneObject::PreRender_, PATCH_JUMP); diff --git a/src/entities/CutsceneObject.h b/src/entities/CutsceneObject.h index 182d8612..b4325f4b 100644 --- a/src/entities/CutsceneObject.h +++ b/src/entities/CutsceneObject.h @@ -14,7 +14,7 @@ public: bool SetupLighting(void); void RemoveLighting(bool reset); - + void dtor(void) { this->CCutsceneObject::~CCutsceneObject(); } void SetModelIndex_(uint32 id) { CCutsceneObject::SetModelIndex(id); } void ProcessControl_(void) { CCutsceneObject::ProcessControl(); } void PreRender_(void) { CCutsceneObject::PreRender(); } diff --git a/src/entities/Dummy.cpp b/src/entities/Dummy.cpp index 493bdbc7..5401c1fa 100644 --- a/src/entities/Dummy.cpp +++ b/src/entities/Dummy.cpp @@ -52,6 +52,7 @@ CDummy::Remove(void) } STARTPATCHES + InjectHook(0x473810, &CDummy::dtor, PATCH_JUMP); InjectHook(0x473860, &CDummy::Add_, PATCH_JUMP); InjectHook(0x473AD0, &CDummy::Remove_, PATCH_JUMP); ENDPATCHES diff --git a/src/entities/Dummy.h b/src/entities/Dummy.h index 4cfef2e2..59359bb5 100644 --- a/src/entities/Dummy.h +++ b/src/entities/Dummy.h @@ -18,5 +18,6 @@ public: // to make patching virtual functions possible void Add_(void) { CDummy::Add(); } void Remove_(void) { CDummy::Remove(); } + void dtor(void) { this->CDummy::~CDummy(); } }; static_assert(sizeof(CDummy) == 0x68, "CDummy: error"); diff --git a/src/entities/DummyObject.cpp b/src/entities/DummyObject.cpp index 083ad6c6..1e4b2ae0 100644 --- a/src/entities/DummyObject.cpp +++ b/src/entities/DummyObject.cpp @@ -11,3 +11,7 @@ CDummyObject::CDummyObject(CObject *obj) obj->DetachFromRwObject(); m_level = obj->m_level; } + +STARTPATCHES + InjectHook(0x4BAB70, &CDummyObject::dtor, PATCH_JUMP); +ENDPATCHES
\ No newline at end of file diff --git a/src/entities/DummyObject.h b/src/entities/DummyObject.h index d4dce609..10554bdd 100644 --- a/src/entities/DummyObject.h +++ b/src/entities/DummyObject.h @@ -9,5 +9,6 @@ class CDummyObject : public CDummy public: CDummyObject(void) {} CDummyObject(CObject *obj); + void dtor(void) { this->CDummyObject::~CDummyObject(); } }; static_assert(sizeof(CDummyObject) == 0x68, "CDummyObject: error"); diff --git a/src/entities/EmergencyPed.h b/src/entities/EmergencyPed.h index f21996e8..fa07f3ee 100644 --- a/src/entities/EmergencyPed.h +++ b/src/entities/EmergencyPed.h @@ -7,5 +7,7 @@ class CEmergencyPed : public CPed public: // 0x53C uint8 stuff[24]; + + void dtor(void) { this->CEmergencyPed::~CEmergencyPed(); } }; static_assert(sizeof(CEmergencyPed) == 0x554, "CEmergencyPed: error"); diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp index e9b35cd5..a5fbe92d 100644 --- a/src/entities/Entity.cpp +++ b/src/entities/Entity.cpp @@ -449,6 +449,8 @@ CEntity::PruneReferences(void) STARTPATCHES InjectHook(0x473C30, &CEntity::ctor, PATCH_JUMP); + InjectHook(0x473E40, &CEntity::dtor, PATCH_JUMP); + InjectHook(0x473E70, &CEntity::SetModelIndex_, PATCH_JUMP); InjectHook(0x4742C0, (void (CEntity::*)(CVector&))&CEntity::GetBoundCentre, PATCH_JUMP); InjectHook(0x474310, &CEntity::GetBoundRadius, PATCH_JUMP); InjectHook(0x474C10, &CEntity::GetIsTouching, PATCH_JUMP); diff --git a/src/entities/Entity.h b/src/entities/Entity.h index 27dd8c14..26a6e46b 100644 --- a/src/entities/Entity.h +++ b/src/entities/Entity.h @@ -156,8 +156,10 @@ public: // to make patching virtual functions possible CEntity *ctor(void) { return ::new (this) CEntity(); } + void dtor(void) { this->CEntity::~CEntity(); } void Add_(void) { CEntity::Add(); } void Remove_(void) { CEntity::Remove(); } + void SetModelIndex_(uint32 i) { CEntity::SetModelIndex(i); } void CreateRwObject_(void) { CEntity::CreateRwObject(); } void DeleteRwObject_(void) { CEntity::DeleteRwObject(); } CRect GetBoundRect_(void) { return CEntity::GetBoundRect(); } diff --git a/src/entities/Heli.cpp b/src/entities/Heli.cpp index 21731fed..01ee5375 100644 --- a/src/entities/Heli.cpp +++ b/src/entities/Heli.cpp @@ -2,4 +2,14 @@ #include "patcher.h" #include "Heli.h" +CHeli::CHeli(int mi, uint8 owner) +{ + ctor(mi, owner); +} + +WRAPPER CHeli* CHeli::ctor(int, uint8) { EAXJMP(0x547220); } WRAPPER void CHeli::SpecialHeliPreRender(void) { EAXJMP(0x54AE10); } + +STARTPATCHES +InjectHook(0x5474A0, &CHeli::dtor, PATCH_JUMP); +ENDPATCHES diff --git a/src/entities/Heli.h b/src/entities/Heli.h index 57c3db0f..da7bb171 100644 --- a/src/entities/Heli.h +++ b/src/entities/Heli.h @@ -8,6 +8,10 @@ public: // 0x288 uint8 stuff[180]; + CHeli(int, uint8); + CHeli* ctor(int, uint8); + void dtor(void) { this->CHeli::~CHeli(); } + static void SpecialHeliPreRender(void); }; static_assert(sizeof(CHeli) == 0x33C, "CHeli: error"); diff --git a/src/entities/Object.cpp b/src/entities/Object.cpp index 8c7cc4c9..1feecbdf 100644 --- a/src/entities/Object.cpp +++ b/src/entities/Object.cpp @@ -66,5 +66,6 @@ CObject::Render(void) WRAPPER void CObject::DeleteAllTempObjectInArea(CVector, float) { EAXJMP(0x4BBED0); } STARTPATCHES + InjectHook(0x4BAE00, &CObject::dtor, PATCH_JUMP); InjectHook(0x4BB1E0, &CObject::Render_, PATCH_JUMP); ENDPATCHES diff --git a/src/entities/Object.h b/src/entities/Object.h index a156609c..0cb951e2 100644 --- a/src/entities/Object.h +++ b/src/entities/Object.h @@ -73,6 +73,7 @@ public: static void DeleteAllTempObjectInArea(CVector, float); + void dtor(void) { this->CObject::~CObject(); } void Render_(void) { CObject::Render(); } }; static_assert(sizeof(CObject) == 0x198, "CObject: error"); diff --git a/src/entities/Ped.cpp b/src/entities/Ped.cpp index 828e9c19..bc1a5203 100644 --- a/src/entities/Ped.cpp +++ b/src/entities/Ped.cpp @@ -17,6 +17,7 @@ #include "Shadows.h" #include "Weather.h" #include "CullZones.h" +#include "Population.h" bool &CPed::bNastyLimbsCheat = *(bool*)0x95CD44; bool &CPed::bPedCheat2 = *(bool*)0x95CD5A; @@ -27,8 +28,65 @@ CVector &CPed::offsetToOpenLowCarDoor = *(CVector*)0x62E03C; CVector &CPed::offsetToOpenVanDoor = *(CVector*)0x62E048; void *CPed::operator new(size_t sz) { return CPools::GetPedPool()->New(); } +void *CPed::operator new(size_t sz, int handle) { return CPools::GetPedPool()->New(handle); } void CPed::operator delete(void *p, size_t sz) { CPools::GetPedPool()->Delete((CPed*)p); } +CPed::~CPed(void) +{ + CWorld::Remove(this); + CRadar::ClearBlipForEntity(BLIP_CHAR, CPools::GetPedPool()->GetIndex(this)); + if (bInVehicle && m_pMyVehicle){ + uint8 door_flag = 0; + switch (m_vehEnterType) { + case VEHICLE_ENTER_FRONT_LEFT: door_flag = 1; break; + case VEHICLE_ENTER_REAR_LEFT: door_flag = 2; break; + case VEHICLE_ENTER_FRONT_RIGHT: door_flag = 4; break; + case VEHICLE_ENTER_REAR_RIGHT: door_flag = 8; break; + default: break; + } + if (m_pMyVehicle->pDriver == this) + m_pMyVehicle->pDriver = nil; + else { + for (int i = 0; i < m_pMyVehicle->m_nNumMaxPassengers; i++) { + if (m_pMyVehicle->pPassengers[i] == this) + m_pMyVehicle->pPassengers[i] = nil; + } + } + if (m_nPedState == PED_EXIT_CAR || m_nPedState == PED_DRAG_FROM_CAR) + m_pMyVehicle->m_nGettingOutFlags &= ~door_flag; + bInVehicle = false; + m_pMyVehicle = nil; + }else if (m_nPedState == PED_ENTER_CAR || m_nPedState == PED_CARJACK){ + QuitEnteringCar(); + } + if (m_pFire) + m_pFire->Extinguish(); + CPopulation::UpdatePedCount(m_nPedType, true); + DMAudio.DestroyEntity(m_audioEntityId); +} + +void CPed::FlagToDestroyWhenNextProcessed(void) +{ + bRemoveFromWorld = true; + if (!bInVehicle || !m_pMyVehicle) + return; + if (m_pMyVehicle->pDriver == this){ + m_pMyVehicle->pDriver = nil; + if (IsPlayer() && m_pMyVehicle->m_status != STATUS_WRECKED) + m_pMyVehicle->m_status = STATUS_ABANDONED; + }else{ + m_pMyVehicle->RemovePassenger(this); + } + bInVehicle = false; + m_pMyVehicle = nil; + if (m_nCreatedBy == 2) /* TODO: enum (MISSION) */ + m_nPedState = PED_DEAD; + else + m_nPedState = PED_NONE; + m_pVehicleAnim = nil; +} + +WRAPPER void CPed::QuitEnteringCar() { EAXJMP(0x4E0E00); } WRAPPER void CPed::KillPedWithCar(CVehicle *veh, float impulse) { EAXJMP(0x4EC430); } WRAPPER void CPed::Say(uint16 audio) { EAXJMP(0x4E5A10); } WRAPPER void CPed::SetDie(AnimationId anim, float arg1, float arg2) { EAXJMP(0x4D37D0); } @@ -1621,10 +1679,11 @@ WRAPPER void CPed::FinishFightMoveCB(CAnimBlendAssociation *assoc, void *arg) { WRAPPER void CPed::PedAnimDoorCloseRollingCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4E4B90); } WRAPPER void CPed::FinishJumpCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4D7A50); } WRAPPER void CPed::PedLandCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4CE8A0); } -WRAPPER void FinishFuckUCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4C6620); } +WRAPPER void FinishFuckUCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4C6580); } WRAPPER void CPed::RestoreHeadingRateCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4D6550); } STARTPATCHES + InjectHook(0x4C50D0, &CPed::dtor, PATCH_JUMP); InjectHook(0x4CF8F0, &CPed::AddWeaponModel, PATCH_JUMP); InjectHook(0x4C6AA0, &CPed::AimGun, PATCH_JUMP); InjectHook(0x4EB470, &CPed::ApplyHeadShot, PATCH_JUMP); diff --git a/src/entities/Ped.h b/src/entities/Ped.h index f83594aa..2edbd9e2 100644 --- a/src/entities/Ped.h +++ b/src/entities/Ped.h @@ -9,6 +9,7 @@ #include "AnimBlendClumpData.h" #include "AnimBlendAssociation.h" #include "WeaponInfo.h" +#include "Fire.h" struct CPathNode; @@ -184,7 +185,9 @@ public: uint8 m_ped_flagI20 : 1; uint8 m_ped_flagI40 : 1; uint8 m_ped_flagI80 : 1; - uint8 stuff10[15]; + uint8 stuff10[3]; + uint8 m_nCreatedBy; + uint8 stuff14[11]; CPed *m_field_16C; uint8 stuff12[44]; int32 m_pEventEntity; @@ -243,7 +246,8 @@ public: uint8 stuff[2]; int32 m_pPointGunAt; CVector m_vecHitLastPos; - uint8 stuff8[12]; + uint8 stuff8[8]; + CFire* m_pFire; CEntity *m_pLookTarget; float m_fLookDirection; int32 m_wepModelID; @@ -266,8 +270,14 @@ public: uint8 stuff11[30]; static void *operator new(size_t); + static void *operator new(size_t, int); static void operator delete(void*, size_t); + ~CPed(void); + void FlagToDestroyWhenNextProcessed(void); + + void dtor(void) { this->CPed::~CPed(); } + bool IsPlayer(void); bool UseGroundColModel(void); bool CanSetPedState(void); @@ -301,6 +311,7 @@ public: void LineUpPedWithCar(PedLineUpPhase phase); void SetPedPositionInCar(void); void PlayFootSteps(void); + void QuitEnteringCar(void); static void GetLocalPositionToOpenCarDoor(CVector *output, CVehicle *veh, uint32 enterType, float offset); static void GetPositionToOpenCarDoor(CVector *output, CVehicle *veh, uint32 enterType, float seatPosMult); static void GetPositionToOpenCarDoor(CVector* output, CVehicle* veh, uint32 enterType); diff --git a/src/entities/Physical.cpp b/src/entities/Physical.cpp index 64e0fb8b..b570efd9 100644 --- a/src/entities/Physical.cpp +++ b/src/entities/Physical.cpp @@ -1895,6 +1895,7 @@ CPhysical::ProcessCollision(void) STARTPATCHES + InjectHook(0x495130, &CPhysical::dtor, PATCH_JUMP); InjectHook(0x4951F0, &CPhysical::Add_, PATCH_JUMP); InjectHook(0x4954B0, &CPhysical::Remove_, PATCH_JUMP); InjectHook(0x495540, &CPhysical::RemoveAndAdd, PATCH_JUMP); diff --git a/src/entities/Physical.h b/src/entities/Physical.h index 749e2dd8..25bc1185 100644 --- a/src/entities/Physical.h +++ b/src/entities/Physical.h @@ -134,6 +134,7 @@ public: void ProcessCollision(void); // to make patching virtual functions possible + void dtor(void) { this->CPhysical::~CPhysical(); } void Add_(void) { CPhysical::Add(); } void Remove_(void) { CPhysical::Remove(); } CRect GetBoundRect_(void) { return CPhysical::GetBoundRect(); } diff --git a/src/entities/Plane.cpp b/src/entities/Plane.cpp new file mode 100644 index 00000000..6e30bced --- /dev/null +++ b/src/entities/Plane.cpp @@ -0,0 +1,19 @@ +#include "common.h" +#include "patcher.h" +#include "Plane.h" + +CPlane::CPlane(int mi, uint8 owner) +{ + ctor(mi, owner); +} + +WRAPPER CPlane* CPlane::ctor(int, uint8) { EAXJMP(0x54B170); } + +CPlane::~CPlane() +{ + DeleteRwObject(); +} + +STARTPATCHES +InjectHook(0x54B270, &CPlane::dtor, PATCH_JUMP); +ENDPATCHES
\ No newline at end of file diff --git a/src/entities/Plane.h b/src/entities/Plane.h index 9acc24ec..e26008f6 100644 --- a/src/entities/Plane.h +++ b/src/entities/Plane.h @@ -1,5 +1,6 @@ #pragma once +#include "common.h" #include "Vehicle.h" class CPlane : public CVehicle @@ -7,5 +8,11 @@ class CPlane : public CVehicle public: // 0x288 uint8 stuff[20]; + + CPlane(int, uint8); + ~CPlane(void); + CPlane* ctor(int, uint8); + void dtor(void) { this->CPlane::~CPlane(); } + void FlagToDestroyWhenNextProcessed() { bRemoveFromWorld = true; } }; static_assert(sizeof(CPlane) == 0x29C, "CPlane: error"); diff --git a/src/entities/PlayerPed.cpp b/src/entities/PlayerPed.cpp index 86312996..2d67d5b2 100644 --- a/src/entities/PlayerPed.cpp +++ b/src/entities/PlayerPed.cpp @@ -2,4 +2,13 @@ #include "patcher.h" #include "PlayerPed.h" +CPlayerPed::~CPlayerPed() +{ + delete m_pWanted; +} + WRAPPER void CPlayerPed::ReApplyMoveAnims(void) { EAXJMP(0x4F07C0); } + +STARTPATCHES + InjectHook(0x4EFB30, &CPlayerPed::dtor, PATCH_JUMP); +ENDPATCHES
\ No newline at end of file diff --git a/src/entities/PlayerPed.h b/src/entities/PlayerPed.h index d268f61b..d09deb49 100644 --- a/src/entities/PlayerPed.h +++ b/src/entities/PlayerPed.h @@ -39,6 +39,9 @@ public: float field_1512; float m_fFPSMoveHeading; + ~CPlayerPed(); + + void dtor(void) { this->CPlayerPed::~CPlayerPed(); } void ReApplyMoveAnims(void); }; diff --git a/src/entities/Projectile.cpp b/src/entities/Projectile.cpp new file mode 100644 index 00000000..e21323de --- /dev/null +++ b/src/entities/Projectile.cpp @@ -0,0 +1,7 @@ +#include "common.h" +#include "patcher.h" +#include "Projectile.h" + +STARTPATCHES + InjectHook(0x4BFED0, &CProjectile::dtor, PATCH_JUMP); +ENDPATCHES
\ No newline at end of file diff --git a/src/entities/Projectile.h b/src/entities/Projectile.h new file mode 100644 index 00000000..a8e826b6 --- /dev/null +++ b/src/entities/Projectile.h @@ -0,0 +1,11 @@ +#pragma once + +#pragma once + +#include "Object.h" + +class CProjectile : public CObject +{ +public: + void dtor(void) { this->CProjectile::~CProjectile(); } +}; diff --git a/src/entities/Train.cpp b/src/entities/Train.cpp new file mode 100644 index 00000000..62fd53ec --- /dev/null +++ b/src/entities/Train.cpp @@ -0,0 +1,14 @@ +#include "common.h" +#include "patcher.h" +#include "Train.h" + +CTrain::CTrain(int mi, uint8 owner) +{ + ctor(mi, owner); +} + +WRAPPER CTrain* CTrain::ctor(int, uint8) { EAXJMP(0x54E2A0); } + +STARTPATCHES +InjectHook(0x54E450, &CTrain::dtor, PATCH_JUMP); +ENDPATCHES
\ No newline at end of file diff --git a/src/entities/Train.h b/src/entities/Train.h index f3fb9a40..84b6faf5 100644 --- a/src/entities/Train.h +++ b/src/entities/Train.h @@ -1,5 +1,7 @@ #pragma once +#include "common.h" +#include "patcher.h" #include "Vehicle.h" enum @@ -16,5 +18,9 @@ public: uint8 stuff2[7]; int16 m_doorState; uint8 stuff3[62]; + + CTrain(int, uint8); + CTrain* ctor(int, uint8); + void dtor(void) { this->CTrain::~CTrain(); } }; static_assert(sizeof(CTrain) == 0x2E4, "CTrain: error"); diff --git a/src/entities/Treadable.cpp b/src/entities/Treadable.cpp index e2eca36a..230d1633 100644 --- a/src/entities/Treadable.cpp +++ b/src/entities/Treadable.cpp @@ -1,7 +1,12 @@ #include "common.h" +#include "patcher.h" #include "rpworld.h" #include "Treadable.h" #include "Pools.h" void *CTreadable::operator new(size_t sz) { return CPools::GetTreadablePool()->New(); } void CTreadable::operator delete(void *p, size_t sz) { CPools::GetTreadablePool()->Delete((CTreadable*)p); } + +STARTPATCHES + InjectHook(0x405A10, &CTreadable::dtor, PATCH_JUMP); +ENDPATCHES
\ No newline at end of file diff --git a/src/entities/Treadable.h b/src/entities/Treadable.h index df5c9ee0..2194638d 100644 --- a/src/entities/Treadable.h +++ b/src/entities/Treadable.h @@ -12,5 +12,6 @@ public: int16 m_nodeIndicesPeds[12]; virtual bool GetIsATreadable(void) { return true; } + void dtor(void) { this->CTreadable::~CTreadable(); } }; static_assert(sizeof(CTreadable) == 0x94, "CTreadable: error"); diff --git a/src/entities/Vehicle.cpp b/src/entities/Vehicle.cpp index ced504a3..bcbaee32 100644 --- a/src/entities/Vehicle.cpp +++ b/src/entities/Vehicle.cpp @@ -4,6 +4,8 @@ #include "Pools.h" #include "CarCtrl.h" #include "ModelIndices.h" +#include "DMAudio.h" +#include "Radar.h" bool &CVehicle::bWheelsOnlyCheat = *(bool *)0x95CD78; bool &CVehicle::bAllDodosCheat = *(bool *)0x95CD75; @@ -12,8 +14,34 @@ bool &CVehicle::bCheat4 = *(bool *)0x95CD65; bool &CVehicle::bCheat5 = *(bool *)0x95CD64; void *CVehicle::operator new(size_t sz) { return CPools::GetVehiclePool()->New(); } +void *CVehicle::operator new(size_t sz, int handle) { return CPools::GetVehiclePool()->New(handle); } void CVehicle::operator delete(void *p, size_t sz) { CPools::GetVehiclePool()->Delete((CVehicle*)p); } +CVehicle::~CVehicle() +{ + m_nAlarmState = 0; + if (m_audioEntityId >= 0){ + DMAudio.DestroyEntity(m_audioEntityId); + m_audioEntityId = -5; + } + CRadar::ClearBlipForEntity(BLIP_CAR, CPools::GetVehiclePool()->GetIndex(this)); + for (int i = 0; i < m_nNumMaxPassengers; i++){ + if (pPassengers[i]) + pPassengers[i]->FlagToDestroyWhenNextProcessed(); + } + if (m_pCarFire) + m_pCarFire->Extinguish(); + CCarCtrl::UpdateCarCount(this, true); + if (bIsAmbulanceOnDuty){ + CCarCtrl::NumAmbulancesOnDuty--; + bIsAmbulanceOnDuty = false; + } + if (bIsFiretruckOnDuty){ + CCarCtrl::NumFiretrucksOnDuty--; + bIsFiretruckOnDuty = false; + } +} + bool CVehicle::IsLawEnforcementVehicle(void) { @@ -47,6 +75,28 @@ CVehicle::ChangeLawEnforcerState(bool enable) } void +CVehicle::RemovePassenger(CPed *p) +{ + if (IsTrain()){ + for (int i = 0; i < 8; i++){ + if (pPassengers[i] == p) { + pPassengers[i] = nil; + m_nNumPassengers--; + return; + } + } + return; + } + for (int i = 0; i < m_nNumMaxPassengers; i++){ + if (pPassengers[i] == p){ + pPassengers[i] = nil; + m_nNumPassengers--; + return; + } + } +} + +void CVehicle::RemoveDriver(void) { m_status = STATUS_ABANDONED; diff --git a/src/entities/Vehicle.h b/src/entities/Vehicle.h index f11e9e97..eed8f7a8 100644 --- a/src/entities/Vehicle.h +++ b/src/entities/Vehicle.h @@ -50,8 +50,8 @@ public: float m_fBreakPedal; uint8 m_nCreatedBy; // eVehicleCreatedBy uint8 bIsLawEnforcer : 1; - uint8 m_veh_flagA2 : 1; - uint8 m_veh_flagA4 : 1; + uint8 bIsAmbulanceOnDuty : 1; + uint8 bIsFiretruckOnDuty : 1; uint8 m_veh_flagA8 : 1; uint8 m_veh_flagA10 : 1; uint8 m_veh_flagA20 : 1; @@ -111,8 +111,13 @@ public: eVehicleType m_vehType; static void *operator new(size_t); + static void *operator new(size_t sz, int slot); static void operator delete(void*, size_t); + ~CVehicle(void); + + void dtor(void) { this->CVehicle::~CVehicle(); } + bool IsCar(void) { return m_vehType == VEHICLE_TYPE_CAR; } bool IsBoat(void) { return m_vehType == VEHICLE_TYPE_BOAT; } bool IsTrain(void) { return m_vehType == VEHICLE_TYPE_TRAIN; } @@ -120,6 +125,7 @@ public: bool IsPlane(void) { return m_vehType == VEHICLE_TYPE_PLANE; } bool IsLawEnforcementVehicle(void); void ChangeLawEnforcerState(bool enable); + void RemovePassenger(CPed *); void RemoveDriver(void); bool IsUpsideDown(void); diff --git a/src/math/Matrix.h b/src/math/Matrix.h index 63cb2753..6e1001cb 100644 --- a/src/math/Matrix.h +++ b/src/math/Matrix.h @@ -202,6 +202,21 @@ public: void CopyOnlyMatrix(CMatrix *other){ m_matrix = other->m_matrix; } + void SetUnity(void) { + m_matrix.right.x = 1.0f; + m_matrix.right.y = 0.0f; + m_matrix.right.z = 0.0f; + m_matrix.up.x = 0.0f; + m_matrix.up.y = 1.0f; + m_matrix.up.z = 0.0f; + m_matrix.at.x = 0.0f; + m_matrix.at.y = 0.0f; + m_matrix.at.z = 1.0f; + m_matrix.pos.x = 0.0f; + m_matrix.pos.x = 0.0f; + m_matrix.pos.y = 0.0f; + m_matrix.pos.z = 0.0f; + } }; inline CMatrix& diff --git a/src/templates.h b/src/templates.h index 7ed7043e..ef2db33a 100644 --- a/src/templates.h +++ b/src/templates.h @@ -60,7 +60,7 @@ public: return (T*)&m_entries[m_allocPtr]; } T *New(int handle){ - T *entry = (T*)m_entries[handle>>8]; + T *entry = (T*)&m_entries[handle>>8]; SetNotFreeAt(handle); return entry; } |