From 98cc8a434c0a484d2d56e1cb34dc88d7d98a0853 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sun, 23 Jun 2019 01:34:11 +0300 Subject: StorePedUpdate --- src/control/Replay.cpp | 24 ++++++++++++++++++++++-- src/control/Replay.h | 17 +++++++++++++++-- 2 files changed, 37 insertions(+), 4 deletions(-) (limited to 'src/control') diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp index a8d87302..d9cd2a80 100644 --- a/src/control/Replay.cpp +++ b/src/control/Replay.cpp @@ -132,7 +132,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]; @@ -182,7 +181,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; @@ -210,7 +209,28 @@ 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 WRAPPER void CReplay::StorePedAnimation(CPed *ped, CStoredAnimationState *state) { EAXJMP(0x593670); } WRAPPER void CReplay::StoreDetailedPedAnimation(CPed *ped, CStoredDetailedAnimationState *state) { EAXJMP(0x593BB0); } WRAPPER void CReplay::ProcessPedUpdate(CPed *ped, float interpolation, CAddressInReplayBuffer *buffer) { EAXJMP(0x594050); } diff --git a/src/control/Replay.h b/src/control/Replay.h index b37bd29f..b73b249c 100644 --- a/src/control/Replay.h +++ b/src/control/Replay.h @@ -65,13 +65,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 +146,19 @@ 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"); + private: static uint8 &Mode; static CAddressInReplayBuffer &Record; -- cgit v1.2.3 From a87f3188e9832c442b66fa67fd312359a77a32c0 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sun, 23 Jun 2019 13:58:14 +0300 Subject: CReplay::StorePedAnimation --- src/control/Replay.cpp | 46 +++++++++++++++++++++++++++++++++++++++++++++- src/control/Replay.h | 46 +++++++++++++++++++++++----------------------- 2 files changed, 68 insertions(+), 24 deletions(-) (limited to 'src/control') diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp index d9cd2a80..ab253cde 100644 --- a/src/control/Replay.cpp +++ b/src/control/Replay.cpp @@ -1,11 +1,13 @@ #include "common.h" #include "patcher.h" +#include "AnimBlendAssociation.h" #include "BulletTraces.h" #include "Clock.h" #include "Draw.h" #include "math/Matrix.h" #include "ModelIndices.h" #include "Replay.h" +#include "RpAnimBlend.h" #include "Pad.h" #include "Pools.h" #include "CutsceneMgr.h" @@ -45,7 +47,7 @@ bool &CReplay::bDoLoadSceneWhenDone = *(bool*)0x95CD76; 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 */ } } @@ -231,7 +233,49 @@ void CReplay::StorePedUpdate(CPed *ped, int id) 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 WRAPPER void CReplay::StoreDetailedPedAnimation(CPed *ped, CStoredDetailedAnimationState *state) { EAXJMP(0x593BB0); } WRAPPER void CReplay::ProcessPedUpdate(CPed *ped, float interpolation, CAddressInReplayBuffer *buffer) { EAXJMP(0x594050); } WRAPPER void CReplay::RetrievePedAnimation(CPed *ped, CStoredAnimationState *state) { EAXJMP(0x5942A0); } diff --git a/src/control/Replay.h b/src/control/Replay.h index b73b249c..8d1f1c38 100644 --- a/src/control/Replay.h +++ b/src/control/Replay.h @@ -19,33 +19,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]; + int8 aAnimId[3]; + int8 aCurTime[3]; + int8 aSpeed[3]; + int8 aBlendAmount[3]; + int8 aFunctionCallbackID[3]; + int16 aFlags[3]; + int8 aAnimId2[6]; + int8 aCurTime2[6]; + int8 aSpeed2[6]; + int8 aBlendAmount2[6]; + int8 aFunctionCallbackID2[6]; + int16 aFlags2[6]; }; class CReplay -- cgit v1.2.3 From cc731f47324cf58c899b242e34d661b651d3acef Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Tue, 25 Jun 2019 01:42:23 +0300 Subject: More replay stuff --- src/control/CarCtrl.cpp | 1 + src/control/CarCtrl.h | 1 + src/control/PhoneInfo.cpp | 6 + src/control/PhoneInfo.h | 6 + src/control/Pickups.cpp | 2 + src/control/Pickups.h | 5 + src/control/Population.cpp | 5 +- src/control/Population.h | 4 + src/control/Replay.cpp | 437 ++++++++++++++++++++++++++++++++++++++++++++- src/control/Replay.h | 78 ++++++-- 10 files changed, 529 insertions(+), 16 deletions(-) create mode 100644 src/control/PhoneInfo.cpp create mode 100644 src/control/PhoneInfo.h (limited to 'src/control') diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index d59ae2d0..730ccd16 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -4,3 +4,4 @@ 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 1f468475..a6537e34 100644 --- a/src/control/CarCtrl.h +++ b/src/control/CarCtrl.h @@ -7,4 +7,5 @@ class CCarCtrl public: static void SwitchVehicleToRealPhysics(CVehicle*); static void AddToCarArray(int id, int vehclass); + static void UpdateCarCount(CVehicle*, bool); }; 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 ab253cde..dfc988c3 100644 --- a/src/control/Replay.cpp +++ b/src/control/Replay.cpp @@ -2,17 +2,28 @@ #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 "RpAnimBlend.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" uint8 &CReplay::Mode = *(uint8*)0x95CD5B; CAddressInReplayBuffer &CReplay::Record = *(CAddressInReplayBuffer*)0x942F7C; @@ -43,6 +54,66 @@ 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) { @@ -276,28 +347,387 @@ void CReplay::StorePedAnimation(CPed *ped, CStoredAnimationState *state) } } #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); } WRAPPER void CReplay::Display(void) { EAXJMP(0x595EE0); } + +#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); } @@ -308,4 +738,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 8d1f1c38..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" @@ -34,18 +35,18 @@ struct CStoredAnimationState struct CStoredDetailedAnimationState { - int8 aAnimId[3]; - int8 aCurTime[3]; - int8 aSpeed[3]; - int8 aBlendAmount[3]; - int8 aFunctionCallbackID[3]; - int16 aFlags[3]; - int8 aAnimId2[6]; - int8 aCurTime2[6]; - int8 aSpeed2[6]; - int8 aBlendAmount2[6]; - int8 aFunctionCallbackID2[6]; - int16 aFlags2[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 @@ -159,6 +160,31 @@ class CReplay }; 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; @@ -189,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); @@ -219,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); -- cgit v1.2.3 From fa132bb773394764feb453b08c4785364f19adf5 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Wed, 26 Jun 2019 23:47:23 +0300 Subject: Fixed merge errors --- src/control/Replay.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/control') diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp index 1c71f25f..9ac1280e 100644 --- a/src/control/Replay.cpp +++ b/src/control/Replay.cpp @@ -419,7 +419,7 @@ void CReplay::StoreCarUpdate(CVehicle *vehicle, int id) 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->acceleration = vehicle->m_fGasPedal * 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)); @@ -430,7 +430,7 @@ void CReplay::StoreCarUpdate(CVehicle *vehicle, int id) 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; + vp->wheel_state = 50.0f * vehicle->m_fSteerAngle; if (vehicle->IsCar()){ CAutomobile* car = (CAutomobile*)vehicle; for (int i = 0; i < 4; i++){ -- cgit v1.2.3 From a45675d4db0fb006d35791a3d9c693797ec0fe13 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Wed, 26 Jun 2019 23:50:22 +0300 Subject: fixed autobuild --- src/control/Replay.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/control') diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp index 9ac1280e..3ccf1f39 100644 --- a/src/control/Replay.cpp +++ b/src/control/Replay.cpp @@ -84,7 +84,7 @@ float &CReplay::LoadSceneY = *(float*)0x880F98; float &CReplay::LoadSceneZ = *(float*)0x880F94; #if 1 -static void(*(&CBArray)[30])(CAnimBlendAssociation*, void*) = *(void(*(*)[30])(CAnimBlendAssociation*, void*))0x61052C; +static void(*(&CBArray)[30])(CAnimBlendAssociation*, void*) = *(void(*(*)[30])(CAnimBlendAssociation*, void*))*(uintptr*)0x61052C; #else static void(*CBArray[])(CAnimBlendAssociation*, void*) = { -- cgit v1.2.3