diff options
36 files changed, 826 insertions, 69 deletions
diff --git a/src/Collision.cpp b/src/Collision.cpp index e6a81954..774caf9d 100644 --- a/src/Collision.cpp +++ b/src/Collision.cpp @@ -93,6 +93,8 @@ CCollision::LoadCollisionWhenINeedIt(bool changeLevel) #endif +WRAPPER void CCollision::SortOutCollisionAfterLoad(void) { EAXJMP(0x40B900); } + // // Test // @@ -1583,6 +1585,8 @@ CColModel::GetTrianglePoint(CVector &v, int i) const v = vertices[i]; } +WRAPPER CColModel& CColModel::operator=(const CColModel& other) { EAXJMP(0x411710); } + STARTPATCHES InjectHook(0x4B9C30, (CMatrix& (*)(const CMatrix &src, CMatrix &dst))Invert, PATCH_JUMP); diff --git a/src/Collision.h b/src/Collision.h index 1bd4ca4a..aa125334 100644 --- a/src/Collision.h +++ b/src/Collision.h @@ -108,6 +108,7 @@ struct CColModel CColModel *ctor(void) { return ::new (this) CColModel(); } void dtor(void) { this->CColModel::~CColModel(); } + CColModel& operator=(const CColModel& other); }; class CCollision @@ -119,6 +120,7 @@ public: static void Init(void); static void Update(void); static void LoadCollisionWhenINeedIt(bool changeLevel); + static void SortOutCollisionAfterLoad(void); static void DrawColModel(const CMatrix &mat, const CColModel &colModel); static void DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel, int32 id); diff --git a/src/DamageManager.cpp b/src/DamageManager.cpp new file mode 100644 index 00000000..d4c8f16e --- /dev/null +++ b/src/DamageManager.cpp @@ -0,0 +1 @@ +#include "DamageManager.h"
\ No newline at end of file diff --git a/src/DamageManager.h b/src/DamageManager.h new file mode 100644 index 00000000..4f1fa640 --- /dev/null +++ b/src/DamageManager.h @@ -0,0 +1,18 @@ +#pragma once + +#include "common.h" + +class CDamageManager +{ +public: + float field_0; + char m_bEngineStatus; + char m_bWheelStatus[4]; + char m_bDoorStatus[7]; + uint32 m_abLightStatus; + uint32 m_abPanelsStatus; + char field_24; + char field_25; + char field_26; + char field_27; +};
\ No newline at end of file diff --git a/src/Door.h b/src/Door.h new file mode 100644 index 00000000..99fae5f1 --- /dev/null +++ b/src/Door.h @@ -0,0 +1,17 @@ +#pragma once + +#include "common.h" + +struct CDoor +{ + float m_fAngleWhenOpened; + float m_fAngleWhenClosed; + char field_8; + char field_9; + char field_10; + char field_11; + float m_fAngle; + float m_fPreviousAngle; + float m_fAngularVelocity; + CVector m_vecVelocity; +};
\ No newline at end of file diff --git a/src/Radar.cpp b/src/Radar.cpp index 3c2f24d3..1b6ca527 100644 --- a/src/Radar.cpp +++ b/src/Radar.cpp @@ -1,3 +1,4 @@ +#include "config.h" #include "common.h" #include "patcher.h" #include "RwHelper.h" diff --git a/src/References.h b/src/References.h index 5ee20d38..c8017c0d 100644 --- a/src/References.h +++ b/src/References.h @@ -10,8 +10,8 @@ struct CReference class CReferences { - static CReference *aRefs; //[NUMREFERENCES]; public: + static CReference *aRefs; //[NUMREFERENCES]; static CReference *&pEmptyList; static void Init(void); }; diff --git a/src/Skidmarks.cpp b/src/Skidmarks.cpp new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/src/Skidmarks.cpp diff --git a/src/Streaming.cpp b/src/Streaming.cpp index 0dc64d62..149de7c3 100644 --- a/src/Streaming.cpp +++ b/src/Streaming.cpp @@ -1584,6 +1584,8 @@ CStreaming::UpdateMemoryUsed(void) // empty } +WRAPPER void CStreaming::LoadScene(CVector *pos) { EAXJMP(0x40A6D0); } +WRAPPER void CStreaming::LoadAllRequestedModels(bool) { EAXJMP(0x40A440); } bool CStreamingInfo::GetCdPosnAndSize(uint32 &posn, uint32 &size) diff --git a/src/Streaming.h b/src/Streaming.h index 75d53dcd..e92819e1 100644 --- a/src/Streaming.h +++ b/src/Streaming.h @@ -159,4 +159,7 @@ public: static void LoadInitialPeds(void); static void LoadInitialVehicles(void); + + static void LoadScene(CVector *pos); + static void LoadAllRequestedModels(bool); }; diff --git a/src/Timer.h b/src/Timer.h index ff532050..75d4048c 100644 --- a/src/Timer.h +++ b/src/Timer.h @@ -14,15 +14,24 @@ class CTimer static bool &m_CodePause; public: static float GetTimeStep(void) { return ms_fTimeStep; } + static inline void SetTimeStep(float ts) { ms_fTimeStep = ts; } static float GetTimeStepNonClipped(void) { return ms_fTimeStepNonClipped; } - static void SetTimeStep(float ts) { ms_fTimeStep = ts; } + static inline void SetTimeStepNonClipped(float ts) { ms_fTimeStepNonClipped = ts; } static uint32 GetFrameCounter(void) { return m_FrameCounter; } + static inline void SetFrameCounter(uint32 fc) { m_FrameCounter = fc; } static uint32 GetTimeInMilliseconds(void) { return m_snTimeInMilliseconds; } + static inline void SetTimeInMilliseconds(uint32 t) { m_snTimeInMilliseconds = t; } + static uint32 GetTimeInMillisecondsNonClipped(void) { return m_snTimeInMillisecondsNonClipped; } + static inline void SetTimeInMillisecondsNonClipped(uint32 t) { m_snTimeInMillisecondsNonClipped = t; } static uint32 GetTimeInMillisecondsPauseMode(void) { return m_snTimeInMillisecondsPauseMode; } + static inline void SetTimeInMillisecondsPauseMode(uint32 t) { m_snTimeInMillisecondsPauseMode = t; } + static uint32 GetPreviousTimeInMilliseconds(void) { return m_snPreviousTimeInMilliseconds; } + static inline void SetPreviousTimeInMilliseconds(uint32 t) { m_snPreviousTimeInMilliseconds = t; } + static float GetTimeScale(void) { return ms_fTimeScale; } + static inline void SetTimeScale(float ts) { ms_fTimeScale = ts; } static bool GetIsPaused() { return m_UserPause || m_CodePause; } static bool GetIsUserPaused() { return m_UserPause; } - static void SetTimeScale(float ts) { ms_fTimeScale = ts; } static void SetCodePause(bool pause) { m_CodePause = pause; } static void Initialise(void); diff --git a/src/World.cpp b/src/World.cpp index e99668ec..0a83c595 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -588,7 +588,7 @@ STARTPATCHES InjectHook(0x4B3B50, CWorld::FindRoofZFor3DCoord, PATCH_JUMP); ENDPATCHES -WRAPPER CPed *FindPlayerPed(void) { EAXJMP(0x4A1150); } +WRAPPER CPlayerPed *FindPlayerPed(void) { EAXJMP(0x4A1150); } WRAPPER CVector &FindPlayerCoors(CVector &v) { EAXJMP(0x4A1030); } WRAPPER CVehicle *FindPlayerVehicle(void) { EAXJMP(0x4A10C0); } WRAPPER CVehicle *FindPlayerTrain(void) { EAXJMP(0x4A1120); } diff --git a/src/World.h b/src/World.h index c8fe827d..e3a6a8f2 100644 --- a/src/World.h +++ b/src/World.h @@ -105,9 +105,9 @@ public: static float GetWorldY(int y) { return y*SECTOR_SIZE_Y + WORLD_MIN_Y; } }; -class CPed; +class CPlayerPed; class CVehicle; -CPed *FindPlayerPed(void); +CPlayerPed *FindPlayerPed(void); CVector &FindPlayerCoors(CVector &v); CVehicle *FindPlayerVehicle(void); CVehicle *FindPlayerTrain(void); diff --git a/src/audio/DMAudio.cpp b/src/audio/DMAudio.cpp index bfa24ab0..1a1e47ed 100644 --- a/src/audio/DMAudio.cpp +++ b/src/audio/DMAudio.cpp @@ -18,9 +18,10 @@ WRAPPER void cDMAudio::ChangeMusicMode(uint8 mode) { EAXJMP(0x57CCF0); } WRAPPER void cDMAudio::PlayFrontEndSound(uint32, uint32) { EAXJMP(0x57CC20); } WRAPPER void cDMAudio::PlayOneShot(int, uint16, float) { EAXJMP(0x57C840); } -WRAPPER int cDMAudio::GetRadioInCar() { EAXJMP(0x57CE40); } -WRAPPER uint8 cDMAudio::IsMP3RadioChannelAvailable() { EAXJMP(0x57C9F0); } - -WRAPPER void cDMAudio::SetEffectsFadeVol(int16) { EAXJMP(0x57C8F0); } -WRAPPER void cDMAudio::SetMusicFadeVol(int16) { EAXJMP(0x57C920); } +WRAPPER int32 cDMAudio::GetRadioInCar() { EAXJMP(0x57CE40); } +WRAPPER void cDMAudio::SetEffectsFadeVol(uint8) { EAXJMP(0x57C8F0); } +WRAPPER void cDMAudio::SetMusicFadeVol(uint8) { EAXJMP(0x57C920); } +WRAPPER int32 cDMAudio::CreateEntity(int, void*) { EAXJMP(0x57C7C0); } +WRAPPER void cDMAudio::SetEntityStatus(int32, int8) { EAXJMP(0x57C810); } +WRAPPER void cDMAudio::SetRadioInCar(int32) { EAXJMP(0x57CE60); }
\ No newline at end of file diff --git a/src/audio/DMAudio.h b/src/audio/DMAudio.h index bf9b65b9..6df2ceea 100644 --- a/src/audio/DMAudio.h +++ b/src/audio/DMAudio.h @@ -189,10 +189,13 @@ public: void ChangeMusicMode(uint8 mode); void PlayFrontEndSound(uint32, uint32); void PlayOneShot(int, uint16, float); - int GetRadioInCar(); + int32 GetRadioInCar(void); + void SetEffectsFadeVol(uint8); + void SetMusicFadeVol(uint8); + int32 CreateEntity(int, void*); + void SetEntityStatus(int32, int8); + void SetRadioInCar(int32); uint8 IsMP3RadioChannelAvailable(); - void SetEffectsFadeVol(int16); - void SetMusicFadeVol(int16); }; extern cDMAudio &DMAudio; diff --git a/src/config.h b/src/config.h index 1cd532ee..83aa7b8f 100644 --- a/src/config.h +++ b/src/config.h @@ -59,6 +59,7 @@ enum Config { NUMONSCREENTIMERENTRIES = 1, NUMRADARBLIPS = 32, + NUMPICKUPS = 336, }; #define GTA3_1_1_PATCH diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index ff73e405..4ce856f7 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -6,3 +6,4 @@ int &CCarCtrl::NumLawEnforcerCars = *(int*)0x8F1B38; WRAPPER void CCarCtrl::SwitchVehicleToRealPhysics(CVehicle*) { EAXJMP(0x41F7F0); } WRAPPER void CCarCtrl::AddToCarArray(int id, int vehclass) { EAXJMP(0x4182F0); } +WRAPPER void CCarCtrl::UpdateCarCount(CVehicle*, bool) { EAXJMP(0x4202E0); }
\ No newline at end of file diff --git a/src/control/CarCtrl.h b/src/control/CarCtrl.h index 06204ddd..cc9327ee 100644 --- a/src/control/CarCtrl.h +++ b/src/control/CarCtrl.h @@ -7,6 +7,7 @@ class CCarCtrl public: static void SwitchVehicleToRealPhysics(CVehicle*); static void AddToCarArray(int id, int vehclass); + static void UpdateCarCount(CVehicle*, bool); static int32 &NumLawEnforcerCars; }; diff --git a/src/control/PhoneInfo.cpp b/src/control/PhoneInfo.cpp new file mode 100644 index 00000000..dbb7acc5 --- /dev/null +++ b/src/control/PhoneInfo.cpp @@ -0,0 +1,6 @@ +#include "common.h" +#include "patcher.h" +#include "PhoneInfo.h" + +WRAPPER void PhonePutDownCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x42F570); } +WRAPPER void PhonePickUpCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x42F470); }
\ No newline at end of file diff --git a/src/control/PhoneInfo.h b/src/control/PhoneInfo.h new file mode 100644 index 00000000..a29043ed --- /dev/null +++ b/src/control/PhoneInfo.h @@ -0,0 +1,6 @@ +#pragma once + +#include "AnimBlendAssociation.h" + +void PhonePutDownCB(CAnimBlendAssociation *assoc, void *arg); +void PhonePickUpCB(CAnimBlendAssociation *assoc, void *arg);
\ No newline at end of file diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp index 63aaa08e..cec13c8a 100644 --- a/src/control/Pickups.cpp +++ b/src/control/Pickups.cpp @@ -2,6 +2,8 @@ #include "patcher.h" #include "Pickups.h" +CPickup(&CPickups::aPickUps)[NUMPICKUPS] = *(CPickup(*)[NUMPICKUPS])*(uintptr*)0x878C98; + WRAPPER void CPickups::RenderPickUpText(void) { EAXJMP(0x432440); } WRAPPER void CPacManPickups::Render(void) { EAXJMP(0x432F60); } diff --git a/src/control/Pickups.h b/src/control/Pickups.h index d2c3628c..3ae2764c 100644 --- a/src/control/Pickups.h +++ b/src/control/Pickups.h @@ -1,9 +1,14 @@ #pragma once +#include "config.h" +#include "Pickup.h" + class CPickups { public: static void RenderPickUpText(void); + + static CPickup(&aPickUps)[NUMPICKUPS]; }; class CPacManPickups diff --git a/src/control/Population.cpp b/src/control/Population.cpp index 9327452b..ebb48a93 100644 --- a/src/control/Population.cpp +++ b/src/control/Population.cpp @@ -1,4 +1,7 @@ #include "common.h" +#include "patcher.h" #include "Population.h" -bool &CPopulation::ms_bGivePedsWeapons = *(bool*)0x95CCF6;
\ No newline at end of file +bool &CPopulation::ms_bGivePedsWeapons = *(bool*)0x95CCF6; + +WRAPPER void CPopulation::UpdatePedCount(uint32, bool) { EAXJMP(0x4F5A60); }
\ No newline at end of file diff --git a/src/control/Population.h b/src/control/Population.h index ce27657a..a5572cdb 100644 --- a/src/control/Population.h +++ b/src/control/Population.h @@ -1,7 +1,11 @@ #pragma once +#include "PedType.h" + class CPopulation { public: static bool &ms_bGivePedsWeapons; + + static void UpdatePedCount(uint32, bool); };
\ No newline at end of file diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp index a3d8ff1b..1c71f25f 100644 --- a/src/control/Replay.cpp +++ b/src/control/Replay.cpp @@ -1,16 +1,29 @@ #include "common.h" #include "patcher.h" +#include "AnimBlendAssociation.h" #include "BulletTraces.h" +#include "CarCtrl.h" #include "Clock.h" +#include "DMAudio.h" #include "Draw.h" #include "math/Matrix.h" #include "ModelIndices.h" -#include "Replay.h" +#include "ModelInfo.h" +#include "Object.h" #include "Pad.h" +#include "PhoneInfo.h" +#include "Pickups.h" #include "Pools.h" +#include "Population.h" +#include "Replay.h" +#include "RpAnimBlend.h" +#include "RwHelper.h" #include "CutsceneMgr.h" +#include "render/Skidmarks.h" +#include "Streaming.h" #include "Timer.h" #include "Weather.h" +#include "Zones.h" #include "Font.h" #include "Text.h" @@ -43,11 +56,71 @@ bool &CReplay::bReplayEnabled = *(bool*)0x617CAC; uint32 &CReplay::SlowMotion = *(uint32*)0x9414D4; uint32 &CReplay::FramesActiveLookAroundCam = *(uint32*)0x880F84; bool &CReplay::bDoLoadSceneWhenDone = *(bool*)0x95CD76; +CPtrList &CReplay::WorldPtrList = *(CPtrList*)0x880F90; +CPtrList &CReplay::BigBuildingPtrList = *(CPtrList*)0x941284; +CWanted &CReplay::PlayerWanted = *(CWanted*)0x8F6278; +CPlayerInfo &CReplay::PlayerInfo = *(CPlayerInfo*)0x8F5840; +uint32 &CReplay::Time1 = *(uint32*)0x8F29DC; +uint32 &CReplay::Time2 = *(uint32*)0x8F29D0; +uint32 &CReplay::Time3 = *(uint32*)0x8F29D4; +uint32 &CReplay::Time4 = *(uint32*)0x8F29C8; +uint32 &CReplay::Frame = *(uint32*)0x8F2554; +uint8 &CReplay::ClockHours = *(uint8*)0x95CDC5; +uint8 &CReplay::ClockMinutes = *(uint8*)0x95CDA2; +uint16 &CReplay::OldWeatherType = *(uint16*)0x95CCEA; +uint16 &CReplay::NewWeatherType = *(uint16*)0x95CC6E; +float &CReplay::WeatherInterpolationValue = *(float*)0x8F1A28; +float &CReplay::TimeStepNonClipped = *(float*)0x8F5FF4; +float &CReplay::TimeStep = *(float*)0x8F2C24; +float &CReplay::TimeScale = *(float*)0x880E20; +float &CReplay::CameraFixedX = *(float*)0x943054; +float &CReplay::CameraFixedY = *(float*)0x943058; +float &CReplay::CameraFixedZ = *(float*)0x94305C; +int32 &CReplay::OldRadioStation = *(int32*)0x94151C; +int8 &CReplay::CameraMode = *(int8*)0x95CD5F; +bool &CReplay::bAllowLookAroundCam = *(bool*)0x95CDCD; +float &CReplay::LoadSceneX = *(float*)0x880F9C; +float &CReplay::LoadSceneY = *(float*)0x880F98; +float &CReplay::LoadSceneZ = *(float*)0x880F94; + +#if 1 +static void(*(&CBArray)[30])(CAnimBlendAssociation*, void*) = *(void(*(*)[30])(CAnimBlendAssociation*, void*))0x61052C; +#else +static void(*CBArray[])(CAnimBlendAssociation*, void*) = +{ + nil, &CPed::PedGetupCB, &CPed::PedStaggerCB, &CPed::PedEvadeCB, &CPed::FinishDieAnimCB, + &CPed::FinishedWaitCB, &CPed::FinishLaunchCB, &CPed::FinishHitHeadCB, &CPed::PedAnimGetInCB, &CPed::PedAnimDoorOpenCB, + &CPed::PedAnimPullPedOutCB, &CPed::PedAnimDoorCloseCB, &CPed::SetInCarCB, &CPed::PedSetOutCarCB, &CPed::PedAnimAlignCB, + &CPed::PedSetDraggedOutCarCB, &CPed::PedAnimStepOutCarCB, &CPed::PedSetInTrainCB, &CPed::PedSetOutTrainCB, &CPed::FinishedAttackCB, + &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); } +#else +static uint8 FindCBFunctionID(void(*f)(CAnimBlendAssociation*, void*)) +{ + for (int i = 0; i < sizeof(CBArray) / sizeof(*CBArray); i++){ + if (CBArray[i] == f) + return i; + } + return 0; +} +#endif + +static void(*FindCBFunction(uint8 id))(CAnimBlendAssociation*, void*) +{ + return CBArray[id]; +} + +WRAPPER static void ApplyPanelDamageToCar(uint32, CAutomobile*, bool) { EAXJMP(0x584EA0); } void PrintElementsInPtrList(void) { for (CPtrNode* node = CWorld::GetBigBuildingList(LEVEL_NONE).first; node; node = node->next) { - // Most likely debug print was present here + /* Most likely debug print was present here */ } } @@ -134,7 +207,6 @@ void CReplay::Update(void) #if 0 WRAPPER void CReplay::RecordThisFrame(void) { EAXJMP(0x5932B0); } #else - void CReplay::RecordThisFrame(void) { tGeneralPacket* general = (tGeneralPacket*)&Record.m_pBase[Record.m_nOffset]; @@ -184,7 +256,7 @@ void CReplay::RecordThisFrame(void) if (!CBulletTraces::aTraces[i].m_bInUse) continue; tBulletTracePacket* bt = (tBulletTracePacket*)&Record.m_pBase[Record.m_nOffset]; - bt->type = REPLAYPACKET_BULLETTRACES; + bt->type = REPLAYPACKET_BULLET_TRACES; bt->index = i; bt->frames = CBulletTraces::aTraces[i].m_bFramesInUse; bt->lifetime = CBulletTraces::aTraces[i].m_bLifeTime; @@ -212,29 +284,451 @@ void CReplay::RecordThisFrame(void) MarkEverythingAsNew(); } #endif + +#if 0 WRAPPER void CReplay::StorePedUpdate(CPed *ped, int id) { EAXJMP(0x5935B0); } +#else +void CReplay::StorePedUpdate(CPed *ped, int id) +{ + tPedUpdatePacket* pp = (tPedUpdatePacket*)&Record.m_pBase[Record.m_nOffset]; + pp->type = REPLAYPACKET_PED_UPDATE; + pp->index = id; + pp->heading = 128.0f / M_PI * ped->m_fRotationCur; + pp->matrix.CompressFromFullMatrix(ped->GetMatrix()); + pp->assoc_group_id = ped->m_animGroup; + /* Would be more sane to use GetJustIndex(ped->m_pMyVehicle) in following assignment */ + if (ped->bInVehicle && ped->m_pMyVehicle) + pp->vehicle_index = (CPools::GetVehiclePool()->GetIndex(ped->m_pMyVehicle) >> 8) + 1; + else + pp->vehicle_index = 0; + pp->weapon_model = ped->m_wepModelID; + StorePedAnimation(ped, &pp->anim_state); + Record.m_nOffset += sizeof(tPedUpdatePacket); +} +#endif + +#if 0 WRAPPER void CReplay::StorePedAnimation(CPed *ped, CStoredAnimationState *state) { EAXJMP(0x593670); } +#else +void CReplay::StorePedAnimation(CPed *ped, CStoredAnimationState *state) +{ + CAnimBlendAssociation* second; + float blend_amount; + CAnimBlendAssociation* main = RpAnimBlendClumpGetMainAssociation((RpClump*)ped->m_rwObject, &second, &blend_amount); + if (main){ + state->animId = main->animId; + state->time = 255.0f / 4.0f * max(0.0f, min(4.0f, main->currentTime)); + state->speed = 255.0f / 3.0f * max(0.0f, min(3.0f, main->speed)); + }else{ + state->animId = 3; + state->time = 0; + state->speed = 85; + } + if (second) { + state->secAnimId = second->animId; + state->secTime = 255.0f / 4.0f * max(0.0f, min(4.0f, second->currentTime)); + state->secSpeed = 255.0f / 3.0f * max(0.0f, min(3.0f, second->speed)); + state->blendAmount = 255.0f / 2.0f * max(0.0f, min(2.0f, blend_amount)); + }else{ + state->secAnimId = 0; + state->secTime = 0; + state->secSpeed = 0; + state->blendAmount = 0; + } + CAnimBlendAssociation* partial = RpAnimBlendClumpGetMainPartialAssociation((RpClump*)ped->m_rwObject); + if (partial) { + state->partAnimId = partial->animId; + state->partAnimTime = 255.0f / 4.0f * max(0.0f, min(4.0f, partial->currentTime)); + state->partAnimSpeed = 255.0f / 3.0f * max(0.0f, min(3.0f, partial->speed)); + state->partBlendAmount = 255.0f / 2.0f * max(0.0f, min(2.0f, partial->blendAmount)); + }else{ + state->partAnimId = 0; + state->partAnimTime = 0; + state->partAnimSpeed = 0; + state->partBlendAmount = 0; + } +} +#endif + +#if 0 WRAPPER void CReplay::StoreDetailedPedAnimation(CPed *ped, CStoredDetailedAnimationState *state) { EAXJMP(0x593BB0); } +#else +void CReplay::StoreDetailedPedAnimation(CPed *ped, CStoredDetailedAnimationState *state) +{ + for (int i = 0; i < 3; i++){ + CAnimBlendAssociation* assoc = RpAnimBlendClumpGetMainAssociation_N((RpClump*)ped->m_rwObject, i); + if (assoc){ + state->aAnimId[i] = assoc->animId; + state->aCurTime[i] = 255.0f / 4.0f * max(0.0f, min(4.0f, assoc->currentTime)); + state->aSpeed[i] = 255.0f / 3.0f * max(0.0f, min(3.0f, assoc->speed)); + state->aBlendAmount[i] = 255.0f / 2.0f * max(0.0f, min(2.0f, assoc->blendAmount)); + state->aFlags[i] = assoc->flags; + if (assoc->callbackType == CAnimBlendAssociation::CB_FINISH || assoc->callbackType == CAnimBlendAssociation::CB_DELETE) { + state->aFunctionCallbackID[i] = FindCBFunctionID(assoc->callback); + if (assoc->callbackType == CAnimBlendAssociation::CB_FINISH) + state->aFunctionCallbackID[i] |= 0x80; + }else{ + state->aFunctionCallbackID[i] = 0; + } + }else{ + state->aAnimId[i] = 173; /* TODO: enum */ + state->aCurTime[i] = 0; + state->aSpeed[i] = 85; + state->aFunctionCallbackID[i] = 0; + state->aFlags[i] = 0; + } + } + for (int i = 0; i < 6; i++) { + CAnimBlendAssociation* assoc = RpAnimBlendClumpGetMainPartialAssociation_N((RpClump*)ped->m_rwObject, i); + if (assoc) { + state->aAnimId2[i] = assoc->animId; + state->aCurTime2[i] = 255.0f / 4.0f * max(0.0f, min(4.0f, assoc->currentTime)); + state->aSpeed2[i] = 255.0f / 3.0f * max(0.0f, min(3.0f, assoc->speed)); + state->aBlendAmount2[i] = 255.0f / 2.0f * max(0.0f, min(2.0f, assoc->blendAmount)); + state->aFlags2[i] = assoc->flags; + if (assoc->callbackType == CAnimBlendAssociation::CB_FINISH || assoc->callbackType == CAnimBlendAssociation::CB_DELETE) { + state->aFunctionCallbackID2[i] = FindCBFunctionID(assoc->callback); + if (assoc->callbackType == CAnimBlendAssociation::CB_FINISH) + state->aFunctionCallbackID2[i] |= 0x80; + }else{ + state->aFunctionCallbackID2[i] = 0; + } + } + else { + state->aAnimId2[i] = 173; /* TODO: enum */ + state->aCurTime2[i] = 0; + state->aSpeed2[i] = 85; + state->aFunctionCallbackID2[i] = 0; + state->aFlags2[i] = 0; + } + } +} +#endif WRAPPER void CReplay::ProcessPedUpdate(CPed *ped, float interpolation, CAddressInReplayBuffer *buffer) { EAXJMP(0x594050); } WRAPPER void CReplay::RetrievePedAnimation(CPed *ped, CStoredAnimationState *state) { EAXJMP(0x5942A0); } WRAPPER void CReplay::RetrieveDetailedPedAnimation(CPed *ped, CStoredDetailedAnimationState *state) { EAXJMP(0x5944B0); } WRAPPER void CReplay::PlaybackThisFrame(void) { EAXJMP(0x5946B0); } + +#if 0 WRAPPER void CReplay::StoreCarUpdate(CVehicle *vehicle, int id) { EAXJMP(0x5947F0); } +#else +void CReplay::StoreCarUpdate(CVehicle *vehicle, int id) +{ + tVehicleUpdatePacket* vp = (tVehicleUpdatePacket*)&Record.m_pBase[Record.m_nOffset]; + vp->type = REPLAYPACKET_VEHICLE; + vp->index = id; + vp->matrix.CompressFromFullMatrix(vehicle->GetMatrix()); + vp->health = vehicle->m_fHealth / 4.0f; /* Not anticipated that health can be > 1000. */ + vp->acceleration = vehicle->m_fAcceleration * 100.0f; + vp->panels = vehicle->IsCar() ? ((CAutomobile*)vehicle)->m_DamageManager.m_abPanelsStatus : 0; + vp->velocityX = 8000.0f * max(-4.0f, min(4.0f, vehicle->GetSpeed().x)); /* 8000!? */ + vp->velocityY = 8000.0f * max(-4.0f, min(4.0f, vehicle->GetSpeed().y)); + vp->velocityZ = 8000.0f * max(-4.0f, min(4.0f, vehicle->GetSpeed().z)); + vp->mi = vehicle->GetModelIndex(); + vp->primary_color = vehicle->m_currentColour1; + vp->secondary_color = vehicle->m_currentColour2; + if (vehicle->GetModelIndex() == MI_RHINO) + vp->car_gun = 128.0f / M_PI * ((CAutomobile*)vehicle)->m_fCarGunLR; + else + vp->wheel_state = 50.0f * vehicle->m_fWheelState; + if (vehicle->IsCar()){ + CAutomobile* car = (CAutomobile*)vehicle; + for (int i = 0; i < 4; i++){ + vp->wheel_susp_dist[i] = 50.0f * car->m_afWheelSuspDist[i]; + vp->wheel_rotation[i] = 128.0f / M_PI * car->m_afWheelRotation[i]; + } + vp->door_angles[0] = 127.0f / M_PI * car->m_aDoors[2].m_fAngle; + vp->door_angles[1] = 127.0f / M_PI * car->m_aDoors[3].m_fAngle; + vp->door_status = 0; + for (int i = 0; i < 6; i++){ + if (car->m_DamageManager.m_bDoorStatus[i] == 3) + vp->door_status |= BIT(i); + } + } + Record.m_nOffset += sizeof(tVehicleUpdatePacket); +} +#endif WRAPPER void CReplay::ProcessCarUpdate(CVehicle *vehicle, float interpolation, CAddressInReplayBuffer *buffer) { EAXJMP(0x594D10); } WRAPPER bool CReplay::PlayBackThisFrameInterpolation(CAddressInReplayBuffer *buffer, float interpolation, uint32 *pTimer) { EAXJMP(0x595240); } WRAPPER void CReplay::FinishPlayback(void) { EAXJMP(0x595B20); } WRAPPER void CReplay::Shutdown(void) { EAXJMP(0x595BD0); } WRAPPER void CReplay::ProcessReplayCamera(void) { EAXJMP(0x595C40); } + +#if 0 WRAPPER void CReplay::TriggerPlayback(uint8 cam_mode, float cam_x, float cam_y, float cam_z, bool load_scene) { EAXJMP(0x596030); } +#else +void CReplay::TriggerPlayback(uint8 cam_mode, float cam_x, float cam_y, float cam_z, bool load_scene) +{ + if (Mode != MODE_RECORD) + return; + CameraFixedX = cam_x; + CameraFixedY = cam_y; + CameraFixedZ = cam_z; + Mode = MODE_PLAYBACK; + FramesActiveLookAroundCam = 0; + CameraMode = cam_mode; + bAllowLookAroundCam = true; + bPlayingBackFromFile = false; + OldRadioStation = DMAudio.GetRadioInCar(); + DMAudio.ChangeMusicMode(0); + DMAudio.SetEffectsFadeVol(0); + DMAudio.SetMusicFadeVol(0); + int current; + for (current = 0; current < 8; current++) + if (BufferStatus[current] == REPLAYBUFFER_RECORD) + break; + int first; + for (first = (current + 1) % 8; ; first = (first + 1) % 8) + if (BufferStatus[first] == REPLAYBUFFER_RECORD || BufferStatus[first] == REPLAYBUFFER_PLAYBACK) + break; + Playback.m_bSlot = first; + Playback.m_nOffset = 0; + Playback.m_pBase = Buffers[first]; + CObject::DeleteAllTempObjectInArea(CVector(0.0f, 0.0f, 0.0f), 1000000.0f); + StoreStuffInMem(); + EmptyPedsAndVehiclePools(); + SlowMotion = 1; + CSkidmarks::Clear(); + StreamAllNecessaryCarsAndPeds(); + if (load_scene) + bDoLoadSceneWhenDone = false; + else{ + bDoLoadSceneWhenDone = true; + LoadSceneX = TheCamera.GetPosition().x; + LoadSceneY = TheCamera.GetPosition().y; + LoadSceneZ = TheCamera.GetPosition().z; + CVector ff_coord; + FindFirstFocusCoordinate(&ff_coord); + CGame::currLevel = CTheZones::GetLevelFromPosition(ff_coord); + CCollision::SortOutCollisionAfterLoad(); + CStreaming::LoadScene(&ff_coord); + } + if (cam_mode == REPLAYCAMMODE_ASSTORED) + TheCamera.CarZoomIndicator = 5.0f; +} +#endif + +#if 1 WRAPPER void CReplay::StoreStuffInMem(void) { EAXJMP(0x5961F0); } +#else +void CReplay::StoreStuffInMem(void) +{ + CPools::GetVehiclePool()->Store(pBuf0, pBuf1); + CPools::GetPedPool()->Store(pBuf2, pBuf3); + CPools::GetObjectPool()->Store(pBuf4, pBuf5); + CPools::GetPtrNodePool()->Store(pBuf6, pBuf7); + CPools::GetEntryInfoNodePool()->Store(pBuf8, pBuf9); + CPools::GetDummyPool()->Store(pBuf10, pBuf11); + pWorld1 = (CSector*)malloc(sizeof(CSector) * NUMSECTORS_X * NUMSECTORS_Y); + memcpy(pWorld1, CWorld::GetSector(0, 0), NUMSECTORS_X * NUMSECTORS_Y * sizeof(CSector)); + WorldPtrList = CWorld::GetMovingEntityList(); /* Interesting way to copy a list... */ + BigBuildingPtrList = CWorld::GetBigBuildingList(LEVEL_NONE); + pPickups = (CPickup*)malloc(sizeof(CPickup) * NUMPICKUPS); + memcpy(pPickups, CPickups::aPickUps, NUMPICKUPS * sizeof(CPickup)); + pReferences = (CReference*)malloc(sizeof(CReference) * NUMREFERENCES); + memcpy(pReferences, CReferences::aRefs, NUMREFERENCES * sizeof(CReference)); + pEmptyReferences = CReferences::pEmptyList; + pStoredCam = (CCamera*)malloc(sizeof(CCamera)); + memcpy(pStoredCam, &TheCamera, sizeof(CCamera)); + pRadarBlips = (CBlip*)malloc(sizeof(CBlip) * NUMBLIPS); + memcpy(pRadarBlips, CRadar::ms_RadarTrace, NUMBLIPS * sizeof(CBlip)); + PlayerWanted = *FindPlayerPed()->m_pWanted; + PlayerInfo = CWorld::Players[0]; + Time1 = CTimer::GetTimeInMilliseconds(); + Time2 = CTimer::GetTimeInMillisecondsNonClipped(); + Time3 = CTimer::GetPreviousTimeInMilliseconds(); + Time4 = CTimer::GetTimeInMillisecondsPauseMode(); + Frame = CTimer::GetFrameCounter(); + ClockHours = CClock::GetHours(); + ClockMinutes = CClock::GetMinutes(); + OldWeatherType = CWeather::OldWeatherType; + NewWeatherType = CWeather::NewWeatherType; + WeatherInterpolationValue = CWeather::InterpolationValue; + TimeStepNonClipped = CTimer::GetTimeStepNonClipped(); + TimeStep = CTimer::GetTimeStep(); + TimeScale = CTimer::GetTimeScale(); + int size = CPools::GetPedPool()->GetSize(); + pPedAnims = (CStoredDetailedAnimationState*)malloc(size * sizeof(CStoredDetailedAnimationState)); + for (int i = 0; i < size; i++) { + CPed* ped = CPools::GetPedPool()->GetSlot(i); + if (ped) + StoreDetailedPedAnimation(ped, &pPedAnims[i]); + } +} +#endif + +#if 1 WRAPPER void CReplay::RestoreStuffFromMem(void) { EAXJMP(0x5966E0); } +#else +void CReplay::RestoreStuffFromMem(void) +{ + CPools::GetVehiclePool()->CopyBack(pBuf0, pBuf1); + CPools::GetPedPool()->CopyBack(pBuf2, pBuf3); + CPools::GetObjectPool()->CopyBack(pBuf4, pBuf5); + CPools::GetPtrNodePool()->CopyBack(pBuf6, pBuf7); + CPools::GetEntryInfoNodePool()->CopyBack(pBuf8, pBuf9); + CPools::GetDummyPool()->CopyBack(pBuf10, pBuf11); + memcpy(CWorld::GetSector(0, 0), pWorld1, sizeof(CSector) * NUMSECTORS_X * NUMSECTORS_Y); + free(pWorld1); + pWorld1 = nil; + CWorld::GetMovingEntityList() = WorldPtrList; + CWorld::GetBigBuildingList(LEVEL_NONE) = BigBuildingPtrList; + memcpy(CPickups::aPickUps, pPickups, sizeof(CPickup) * NUMPICKUPS); + free(pPickups); + pPickups = nil; + memcpy(CReferences::aRefs, pReferences, sizeof(CReference) * NUMREFERENCES); + free(pReferences); + pReferences = nil; + CReferences::pEmptyList = pEmptyReferences; + pEmptyReferences = nil; + memcpy(&TheCamera, pStoredCam, sizeof(CCamera)); + free(pStoredCam); + pStoredCam = nil; + memcpy(CRadar::ms_RadarTrace, pRadarBlips, sizeof(CBlip) * NUMBLIPS); + free(pRadarBlips); + pRadarBlips = nil; + FindPlayerPed()->m_pWanted = new CWanted(PlayerWanted); /* Nice memory leak */ + CWorld::Players[0] = PlayerInfo; + int size = CPools::GetPedPool()->GetSize(); + for (int i = size - 1; i >= 0; i--){ + CPed* ped = CPools::GetPedPool()->GetSlot(i); + if (!ped) + continue; + int mi = ped->GetModelIndex(); + CStreaming::RequestModel(mi, 0); + CStreaming::LoadAllRequestedModels(false); + ped->m_rwObject = nil; + ped->m_modelIndex = -1; + ped->SetModelIndex(mi); + ped->m_pVehicleAnim = 0; + ped->uAudioEntityId = DMAudio.CreateEntity(0, ped); + DMAudio.SetEntityStatus(ped->uAudioEntityId, 1); + CPopulation::UpdatePedCount(ped->m_nPedType, false); + if (ped->m_wepModelID >= 0) + ped->AddWeaponModel(ped->m_wepModelID); + } + size = CPools::GetVehiclePool()->GetSize(); + for (int i = size - 1; i >= 0; i--) { + CVehicle* vehicle = CPools::GetVehiclePool()->GetSlot(i); + if (!vehicle) + continue; + int mi = vehicle->GetModelIndex(); + CStreaming::RequestModel(mi, 0); + CStreaming::LoadAllRequestedModels(false); + vehicle->m_rwObject = nil; + vehicle->m_modelIndex = -1; + vehicle->SetModelIndex(mi); + if (mi == MI_DODO){ + CAutomobile* dodo = (CAutomobile*)vehicle; + GetFirstObject(dodo->m_apModelNodes[4])->flags = 0; /* TODO: 4 to enum */ + CMatrix tmp1; + tmp1.Attach(&dodo->m_apModelNodes[1]->modelling, false); + CMatrix tmp2(&dodo->m_apModelNodes[4]->modelling, false); + *tmp1.GetPosition() += CVector(tmp2.GetPosition()->x + 0.1f, 0.0f, tmp2.GetPosition()->z); + tmp1.UpdateRW(); + } + if (vehicle->IsCar()){ + CAutomobile* car = (CAutomobile*)vehicle; + int32 panels = car->m_DamageManager.m_abPanelsStatus; + car->m_DamageManager.m_abPanelsStatus = 0; + ApplyPanelDamageToCar(panels, car, true); + car->SetDoorDamage(17, 0, true); /* BONNET */ + car->SetDoorDamage(18, 1, true); /* BUMPER */ + car->SetDoorDamage(15, 2, true); /* DOOR_FRONT_LEFT */ + car->SetDoorDamage(11, 3, true); /* DOOR_FRONT_RIGHT */ + car->SetDoorDamage(16, 4, true); /* DOOR_BACK_LEFT */ + car->SetDoorDamage(12, 5, true); /* DOOR_BACK_RIGHT */ + } + vehicle->uAudioEntityId = DMAudio.CreateEntity(0, vehicle); + DMAudio.SetEntityStatus(vehicle->uAudioEntityId, 1); + CCarCtrl::UpdateCarCount(vehicle, false); + if ((mi == MI_AIRTRAIN || mi == MI_DEADDODO) && vehicle->m_rwObject){ + CVehicleModelInfo* info = (CVehicleModelInfo*)CModelInfo::GetModelInfo(mi); + if (RwObjectGetType(vehicle->m_rwObject) == rpATOMIC){ + vehicle->GetMatrix().Detach(); + if (vehicle->m_rwObject){ + if (RwObjectGetType(vehicle->m_rwObject) == rpATOMIC){ + RwFrame* frame = RpAtomicGetFrame(vehicle->m_rwObject); + RpAtomicDestroy((RpAtomic*)vehicle->m_rwObject); + RwFrameDestroy(frame); + } + vehicle->m_rwObject = nil; + } + }else{ + vehicle->DeleteRwObject(); + int model_id = info->m_wheelId; + if (model_id != -1){ + if ((vehicle->m_rwObject = CModelInfo::GetModelInfo(model_id)->CreateInstance())){ + vehicle->GetMatrix().AttachRW(&((RwFrame*)vehicle->m_rwObject->parent)->modelling, false); + } + } + } + } + } + PrintElementsInPtrList(); + size = CPools::GetObjectPool()->GetSize(); + for (int i = size - 1; i >= 0; i--) { + CObject* object = CPools::GetObjectPool()->GetSlot(i); + if (!object) + continue; + int mi = object->GetModelIndex(); + CStreaming::RequestModel(mi, 0); + CStreaming::LoadAllRequestedModels(false); + object->m_rwObject = nil; + object->m_modelIndex = -1; + object->SetModelIndex(mi); + object->GetMatrix().m_attachment = nil; + if (RwObjectGetType(object->m_rwObject) == rpATOMIC) + object->GetMatrix().AttachRW(RwFrameGetMatrix(RpAtomicGetFrame(object->m_rwObject)), false); + } + size = CPools::GetDummyPool()->GetSize(); + for (int i = size - 1; i >= 0; i--) { + CDummy* dummy = CPools::GetDummyPool()->GetSlot(i); + if (!dummy) + continue; + int mi = dummy->GetModelIndex(); + CStreaming::RequestModel(mi, 0); + CStreaming::LoadAllRequestedModels(false); + dummy->m_rwObject = nil; + dummy->m_modelIndex = -1; + dummy->SetModelIndex(mi); + dummy->GetMatrix().m_attachment = nil; + if (RwObjectGetType(dummy->m_rwObject) == rpATOMIC) + dummy->GetMatrix().AttachRW(RwFrameGetMatrix(RpAtomicGetFrame(dummy->m_rwObject)), false); + } + CTimer::SetTimeInMilliseconds(Time1); + CTimer::SetTimeInMillisecondsNonClipped(Time2); + CTimer::SetPreviousTimeInMilliseconds(Time3); + CTimer::SetTimeInMillisecondsPauseMode(Time4); + CTimer::SetTimeScale(TimeScale); + CTimer::SetFrameCounter(Frame); + CTimer::SetTimeStep(TimeStep); + CTimer::SetTimeStepNonClipped(TimeStepNonClipped); + CClock::SetGameClock(ClockHours, ClockMinutes); + CWeather::OldWeatherType = OldWeatherType; + CWeather::NewWeatherType = NewWeatherType; + CWeather::InterpolationValue = WeatherInterpolationValue; + size = CPools::GetPedPool()->GetSize(); + for (int i = 0; i < size; i++) { + CPed* ped = CPools::GetPedPool()->GetSlot(i); + if (!ped) + continue; + RetrieveDetailedPedAnimation(ped, &pPedAnims[i]); + } + free(pPedAnims); + pPedAnims = nil; + DMAudio.ChangeMusicMode(0); + DMAudio.SetRadioInCar(OldRadioStation); + DMAudio.ChangeMusicMode(1); +} +#endif WRAPPER void CReplay::EmptyPedsAndVehiclePools(void) { EAXJMP(0x5970E0); } WRAPPER void CReplay::EmptyAllPools(void) { EAXJMP(0x5971B0); } WRAPPER void CReplay::MarkEverythingAsNew(void) { EAXJMP(0x597280); } WRAPPER void CReplay::SaveReplayToHD(void) { EAXJMP(0x597330); } WRAPPER void PlayReplayFromHD(void) { EAXJMP(0x597420); } WRAPPER void CReplay::StreamAllNecessaryCarsAndPeds(void) { EAXJMP(0x597560); } -WRAPPER void CReplay::FindFirstFocusCoordinate(CVector *coord) { EAXJMP(0x5975E00); } +WRAPPER void CReplay::FindFirstFocusCoordinate(CVector *coord) { EAXJMP(0x5975E0); } WRAPPER bool CReplay::ShouldStandardCameraBeProcessed(void) { EAXJMP(0x597680); } WRAPPER void CReplay::ProcessLookAroundCam(void) { EAXJMP(0x5976C0); } WRAPPER size_t CReplay::FindSizeOfPacket(uint8 type) { EAXJMP(0x597CC0); } @@ -262,4 +756,5 @@ InjectHook(0x592FE0, CReplay::Init, PATCH_JUMP); InjectHook(0x593150, CReplay::DisableReplays, PATCH_JUMP); InjectHook(0x593150, CReplay::EnableReplays, PATCH_JUMP); InjectHook(0x593170, CReplay::Update, PATCH_JUMP); +//InjectHook(0x5966E0, CReplay::RestoreStuffFromMem, PATCH_JUMP); ENDPATCHES diff --git a/src/control/Replay.h b/src/control/Replay.h index b37bd29f..b622788f 100644 --- a/src/control/Replay.h +++ b/src/control/Replay.h @@ -7,6 +7,7 @@ #include "Radar.h" #include "References.h" #include "Vehicle.h" +#include "Wanted.h" #include "World.h" #include "common.h" @@ -19,33 +20,33 @@ struct CAddressInReplayBuffer struct CStoredAnimationState { - int8 animId; - int8 time; - int8 speed; - int8 secAnimId; - int8 secTime; - int8 secSpeed; - int8 blendAmount; - int8 partAnimId; - int8 partAnimTime; - int8 partAnimSpeed; - int8 partBlendAmount; + uint8 animId; + uint8 time; + uint8 speed; + uint8 secAnimId; + uint8 secTime; + uint8 secSpeed; + uint8 blendAmount; + uint8 partAnimId; + uint8 partAnimTime; + uint8 partAnimSpeed; + uint8 partBlendAmount; }; struct CStoredDetailedAnimationState { - int8 m_abAnimId[3]; - int8 m_abCurTime[3]; - int8 m_abSpeed[3]; - int8 m_abBlendAmount[3]; - int8 m_abFunctionCallbackID[3]; - int16 m_awFlags[3]; - int8 m_abAnimId2[6]; - int8 m_abCurTime2[6]; - int8 m_abSpeed2[6]; - int8 m_abBlendAmount2[6]; - int8 m_abFunctionCallbackID2[6]; - int16 m_awFlags2[6]; + uint8 aAnimId[3]; + uint8 aCurTime[3]; + uint8 aSpeed[3]; + uint8 aBlendAmount[3]; + uint8 aFunctionCallbackID[3]; + uint16 aFlags[3]; + uint8 aAnimId2[6]; + uint8 aCurTime2[6]; + uint8 aSpeed2[6]; + uint8 aBlendAmount2[6]; + uint8 aFunctionCallbackID2[6]; + uint16 aFlags2[6]; }; class CReplay @@ -65,13 +66,13 @@ class CReplay REPLAYPACKET_END = 0, REPLAYPACKET_VEHICLE = 1, REPLAYPACKET_PED_HEADER = 2, - REPLAYPACKET_PED = 3, + REPLAYPACKET_PED_UPDATE = 3, REPLAYPACKET_GENERAL = 4, REPLAYPACKET_CLOCK = 5, REPLAYPACKET_WEATHER = 6, REPLAYPACKET_ENDOFFRAME = 7, REPLAYPACKET_TIMER = 8, - REPLAYPACKET_BULLETTRACES = 9 + REPLAYPACKET_BULLET_TRACES = 9 }; enum { @@ -146,6 +147,44 @@ class CReplay }; static_assert(sizeof(tEndOfFramePacket) == 4, "tEndOfFramePacket: error"); + struct tPedUpdatePacket + { + uint8 type; + uint8 index; + int8 heading; + int8 vehicle_index; + CStoredAnimationState anim_state; + CCompressedMatrixNotAligned matrix; + uint8 assoc_group_id; + uint8 weapon_model; + }; + static_assert(sizeof(tPedUpdatePacket) == 40, "tPedUpdatePacket: error"); + + struct tVehicleUpdatePacket + { + uint8 type; + uint8 index; + uint8 health; + uint8 acceleration; + CCompressedMatrixNotAligned matrix; + int8 door_angles[2]; + uint16 mi; + uint32 panels; + int8 velocityX; + int8 velocityY; + int8 velocityZ; + union{ + int8 car_gun; + uint8 wheel_state; + }; + uint8 wheel_susp_dist[4]; + uint8 wheel_rotation[4]; + uint8 door_status; + uint8 primary_color; + uint8 secondary_color; + }; + static_assert(sizeof(tVehicleUpdatePacket) == 48, "tVehicleUpdatePacket: error"); + private: static uint8 &Mode; static CAddressInReplayBuffer &Record; @@ -176,6 +215,32 @@ private: static uint32 &SlowMotion; static uint32 &FramesActiveLookAroundCam; static bool &bDoLoadSceneWhenDone; + static CPtrList &WorldPtrList; + static CPtrList &BigBuildingPtrList; + static CWanted &PlayerWanted; + static CPlayerInfo &PlayerInfo; + static uint32 &Time1; + static uint32 &Time2; + static uint32 &Time3; + static uint32 &Time4; + static uint32 &Frame; + static uint8 &ClockHours; + static uint8 &ClockMinutes; + static uint16 &OldWeatherType; + static uint16 &NewWeatherType; + static float &WeatherInterpolationValue; + static float &TimeStepNonClipped; + static float &TimeStep; + static float &TimeScale; + static float &CameraFixedX; + static float &CameraFixedY; + static float &CameraFixedZ; + static int32 &OldRadioStation; + static int8 &CameraMode; + static bool &bAllowLookAroundCam; + static float &LoadSceneX; + static float &LoadSceneY; + static float &LoadSceneZ; public: static void Init(void); @@ -206,7 +271,9 @@ private: 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 new file mode 100644 index 00000000..89fac33e --- /dev/null +++ b/src/entities/Automobile.cpp @@ -0,0 +1,5 @@ +#include "common.h" +#include "patcher.h" +#include "Automobile.h" + +WRAPPER void CAutomobile::SetDoorDamage(int32, uint32, bool) { EAXJMP(0x530200); }
\ No newline at end of file diff --git a/src/entities/Automobile.h b/src/entities/Automobile.h index 379124e6..7422112b 100644 --- a/src/entities/Automobile.h +++ b/src/entities/Automobile.h @@ -1,14 +1,26 @@ #pragma once +#include "DamageManager.h" +#include "Door.h" +#include "RwHelper.h" #include "Vehicle.h" class CAutomobile : public CVehicle { public: // 0x288 - uint8 stuff1[484]; + CDamageManager m_DamageManager; + CDoor m_aDoors[6]; + RwFrame *m_apModelNodes[20]; + uint8 stuff1[160]; float m_afWheelSuspDist[4]; - uint8 stuff2[300]; + uint8 stuff2[44]; + float m_afWheelRotation[4]; + uint8 stuff3[200]; + float m_fCarGunLR; + uint8 stuff4[36]; + + void SetDoorDamage(int32, uint32, bool); /* TODO: eDoors */ }; static_assert(sizeof(CAutomobile) == 0x5A8, "CAutomobile: error"); static_assert(offsetof(CAutomobile, m_afWheelSuspDist) == 0x46C, "CAutomobile: error"); diff --git a/src/entities/Object.cpp b/src/entities/Object.cpp index 35a64604..8c7cc4c9 100644 --- a/src/entities/Object.cpp +++ b/src/entities/Object.cpp @@ -63,6 +63,8 @@ CObject::Render(void) CEntity::Render(); } +WRAPPER void CObject::DeleteAllTempObjectInArea(CVector, float) { EAXJMP(0x4BBED0); } + STARTPATCHES InjectHook(0x4BB1E0, &CObject::Render_, PATCH_JUMP); ENDPATCHES diff --git a/src/entities/Object.h b/src/entities/Object.h index 2079ff0e..a156609c 100644 --- a/src/entities/Object.h +++ b/src/entities/Object.h @@ -71,6 +71,7 @@ public: void ObjectDamage(float amount); + static void DeleteAllTempObjectInArea(CVector, float); void Render_(void) { CObject::Render(); } }; diff --git a/src/entities/Ped.cpp b/src/entities/Ped.cpp index 5a4c736e..c4109312 100644 --- a/src/entities/Ped.cpp +++ b/src/entities/Ped.cpp @@ -1463,6 +1463,30 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase) } +WRAPPER void CPed::PedGetupCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4CE810); } +WRAPPER void CPed::PedStaggerCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4CE8D0); } +WRAPPER void CPed::PedEvadeCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4D36E0); } +WRAPPER void CPed::FinishDieAnimCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4D3950); } +WRAPPER void CPed::FinishedWaitCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4D6520); } +WRAPPER void CPed::FinishLaunchCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4D7490); } +WRAPPER void CPed::FinishHitHeadCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4D7A80); } +WRAPPER void CPed::PedAnimGetInCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4DEC80); } +WRAPPER void CPed::PedAnimDoorOpenCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4DE500); } +WRAPPER void CPed::PedAnimPullPedOutCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4DEAF0); } +WRAPPER void CPed::PedAnimDoorCloseCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4DF1B0); } +WRAPPER void CPed::SetInCarCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4CF220); } +WRAPPER void CPed::PedSetOutCarCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4CE8F0); } +WRAPPER void CPed::PedAnimAlignCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4DE130); } +WRAPPER void CPed::PedAnimStepOutCarCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4DF5C0); } +WRAPPER void CPed::PedSetInTrainCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4E3290); } +WRAPPER void CPed::PedSetOutTrainCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4E36E0); } +WRAPPER void CPed::FinishFightMoveCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4E9830); } +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 CPed::RestoreHeadingRateCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4D6550); } + STARTPATCHES InjectHook(0x4CF8F0, &CPed::AddWeaponModel, PATCH_JUMP); InjectHook(0x4C6AA0, &CPed::AimGun, PATCH_JUMP); diff --git a/src/entities/Ped.h b/src/entities/Ped.h index 187bd08c..34c7a485 100644 --- a/src/entities/Ped.h +++ b/src/entities/Ped.h @@ -303,10 +303,32 @@ public: static void GetPositionToOpenCarDoor(CVector* output, CVehicle* veh, uint32 enterType); static RwObject *SetPedAtomicVisibilityCB(RwObject *object, void *data); static RwFrame *RecurseFrameChildrenVisibilityCB(RwFrame *frame, void *data); - static void FinishedAttackCB(CAnimBlendAssociation *attackAssoc, void *arg); - static void PedSetDraggedOutCarCB(CAnimBlendAssociation *dragAssoc, void *arg); - static void PedSetQuickDraggedOutCarPositionCB(CAnimBlendAssociation *dragAssoc, void *arg); - static void PedSetDraggedOutCarPositionCB(CAnimBlendAssociation *dragAssoc, void *arg); + static void PedGetupCB(CAnimBlendAssociation *assoc, void *arg); + static void PedStaggerCB(CAnimBlendAssociation *assoc, void *arg); + static void PedEvadeCB(CAnimBlendAssociation *assoc, void *arg); + static void FinishDieAnimCB(CAnimBlendAssociation *assoc, void *arg); + static void FinishedWaitCB(CAnimBlendAssociation *assoc, void *arg); + static void FinishLaunchCB(CAnimBlendAssociation *assoc, void *arg); + static void FinishHitHeadCB(CAnimBlendAssociation *assoc, void *arg); + static void PedAnimGetInCB(CAnimBlendAssociation *assoc, void *arg); + static void PedAnimDoorOpenCB(CAnimBlendAssociation *assoc, void *arg); + static void PedAnimPullPedOutCB(CAnimBlendAssociation *assoc, void *arg); + static void PedAnimDoorCloseCB(CAnimBlendAssociation *assoc, void *arg); + static void SetInCarCB(CAnimBlendAssociation *assoc, void *arg); + static void PedSetOutCarCB(CAnimBlendAssociation *assoc, void *arg); + static void PedAnimAlignCB(CAnimBlendAssociation *assoc, void *arg); + static void PedSetDraggedOutCarCB(CAnimBlendAssociation *assoc, void *arg); + static void PedAnimStepOutCarCB(CAnimBlendAssociation *assoc, void *arg); + static void PedSetInTrainCB(CAnimBlendAssociation *assoc, void *arg); + static void PedSetOutTrainCB(CAnimBlendAssociation *assoc, void *arg); + static void FinishedAttackCB(CAnimBlendAssociation *assoc, void *arg); + static void FinishFightMoveCB(CAnimBlendAssociation *assoc, void *arg); + static void PedAnimDoorCloseRollingCB(CAnimBlendAssociation *assoc, void *arg); + static void FinishJumpCB(CAnimBlendAssociation *assoc, void *arg); + static void PedLandCB(CAnimBlendAssociation *assoc, void *arg); + static void RestoreHeadingRateCB(CAnimBlendAssociation *assoc, void *arg); + static void PedSetQuickDraggedOutCarPositionCB(CAnimBlendAssociation *assoc, void *arg); + static void PedSetDraggedOutCarPositionCB(CAnimBlendAssociation *assoc, void *arg); bool HasWeapon(eWeaponType weaponType) { return m_weapons[weaponType].m_eWeaponType == weaponType; } CWeapon *GetWeapon(void) { return &m_weapons[m_currentWeapon]; } @@ -320,6 +342,8 @@ public: static bool &bPedCheat3; }; +void FinishFuckUCB(CAnimBlendAssociation *assoc, void *arg); + static_assert(offsetof(CPed, m_nPedState) == 0x224, "CPed: error"); static_assert(offsetof(CPed, m_pCurSurface) == 0x2FC, "CPed: error"); static_assert(offsetof(CPed, m_pMyVehicle) == 0x310, "CPed: error"); diff --git a/src/math/Matrix.h b/src/math/Matrix.h index 74e3d70d..e2e5394e 100644 --- a/src/math/Matrix.h +++ b/src/math/Matrix.h @@ -270,3 +270,37 @@ Multiply3x3(const CMatrix &mat, const CVector &vec) mat.m_matrix.right.y * vec.x + mat.m_matrix.up.y * vec.y + mat.m_matrix.at.y * vec.z, mat.m_matrix.right.z * vec.x + mat.m_matrix.up.z * vec.y + mat.m_matrix.at.z * vec.z); } + +class CCompressedMatrixNotAligned +{ + CVector m_vecPos; + int8 m_rightX; + int8 m_rightY; + int8 m_rightZ; + int8 m_upX; + int8 m_upY; + int8 m_upZ; +public: + void CompressFromFullMatrix(CMatrix &other) + { + m_rightX = 127.0f * other.GetRight()->x; + m_rightY = 127.0f * other.GetRight()->y; + m_rightZ = 127.0f * other.GetRight()->z; + m_upX = 127.0f * other.GetForward()->x; + m_upY = 127.0f * other.GetForward()->y; + m_upZ = 127.0f * other.GetForward()->z; + m_vecPos = *other.GetPosition(); + } + void DecompressIntoFullMatrix(CMatrix &other) + { + other.GetRight()->x = m_rightX / 127.0f; + other.GetRight()->y = m_rightY / 127.0f; + other.GetRight()->z = m_rightZ / 127.0f; + other.GetForward()->x = m_upX / 127.0f; + other.GetForward()->y = m_upY / 127.0f; + other.GetForward()->z = m_upZ / 127.0f; + *other.GetUp() = CrossProduct(*other.GetRight(), *other.GetForward()); + *other.GetPosition() = m_vecPos; + other.Reorthogonalise(); + } +};
\ No newline at end of file diff --git a/src/render/Skidmarks.cpp b/src/render/Skidmarks.cpp index 678e1cdc..fd5e7d2b 100644 --- a/src/render/Skidmarks.cpp +++ b/src/render/Skidmarks.cpp @@ -2,4 +2,6 @@ #include "patcher.h" #include "Skidmarks.h" +WRAPPER void CSkidmarks::Clear(void) { EAXJMP(0x518130); } + WRAPPER void CSkidmarks::Render(void) { EAXJMP(0x5182E0); } diff --git a/src/render/Skidmarks.h b/src/render/Skidmarks.h index dcd61652..d1e1d996 100644 --- a/src/render/Skidmarks.h +++ b/src/render/Skidmarks.h @@ -3,5 +3,6 @@ class CSkidmarks { public: + static void Clear(void); static void Render(void); }; diff --git a/src/templates.h b/src/templates.h index d1ef99f0..7ed7043e 100644 --- a/src/templates.h +++ b/src/templates.h @@ -101,26 +101,26 @@ public: n++; return n; } - void ClearStorage(uint8 **flags, U **entries){ - delete[] flags; - delete[] entries; - *flags = nil; - *entries = nil; - } - void CopyBack(uint8 **flags, U **entries){ - memcpy(m_flags, *flags, sizeof(Flags)*m_size); - memcpy(m_entries, *entries, sizeof(U)*m_size); - debug("Size copied:%d (%d)", sizeof(U)*m_size, sizeof(Flags)*m_size); + void ClearStorage(uint8 *&flags, U *&entries){ + free(flags); + free(entries); + flags = nil; + entries = nil; + } + void CopyBack(uint8 *&flags, U *&entries){ + memcpy(m_flags, flags, sizeof(uint8)*m_size); + memcpy(m_entries, entries, sizeof(U)*m_size); + debug("Size copied:%d (%d)\n", sizeof(U)*m_size, sizeof(Flags)*m_size); m_allocPtr = 0; ClearStorage(flags, entries); - debug("CopyBack:%d (/%d)", GetNoOfUsedSpaces(), m_size); /* Assumed inlining */ - } - void Store(uint8 **flags, U** entries){ - *flags = (Flags*)malloc(sizeof(Flags)*m_size); - *entries = (U*)malloc(sizeof(U)*m_size); - memcpy(*flags, m_flags, sizeof(Flags)*m_size); - memcpy(*entries, m_entries, sizeof(U)*m_size); - debug("Stored:%d (/%d)", GetNoOfUsedSpaces(), m_size); /* Assumed inlining */ + debug("CopyBack:%d (/%d)\n", GetNoOfUsedSpaces(), m_size); /* Assumed inlining */ + } + void Store(uint8 *&flags, U *&entries){ + flags = (uint8*)malloc(sizeof(uint8)*m_size); + entries = (U*)malloc(sizeof(U)*m_size); + memcpy(flags, m_flags, sizeof(uint8)*m_size); + memcpy(entries, m_entries, sizeof(U)*m_size); + debug("Stored:%d (/%d)\n", GetNoOfUsedSpaces(), m_size); /* Assumed inlining */ } }; |