From 4e09f9ee39e003b852471e3016411cc3a3169802 Mon Sep 17 00:00:00 2001 From: Nikolay Korolev Date: Sun, 30 Jun 2019 23:29:53 +0300 Subject: [PATCH] Added camera funcs to Replay --- src/control/Replay.cpp | 242 +++++++++++++++++++++++++++++++++++++++-- src/control/Replay.h | 8 ++ 2 files changed, 239 insertions(+), 11 deletions(-) diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp index 09cbf2d2..8d59f3ce 100644 --- a/src/control/Replay.cpp +++ b/src/control/Replay.cpp @@ -8,7 +8,9 @@ #include "Clock.h" #include "DMAudio.h" #include "Draw.h" +#include "FileMgr.h" #include "Heli.h" +#include "main.h" #include "math/Matrix.h" #include "ModelIndices.h" #include "ModelInfo.h" @@ -91,6 +93,9 @@ float &CReplay::CameraFocusX = *(float*)0x942F5C; float &CReplay::CameraFocusY = *(float*)0x942F74; float &CReplay::CameraFocusZ = *(float*)0x942F58; bool &CReplay::bPlayerInRCBuggy = *(bool*)0x95CDC3; +float &CReplay::fDistanceLookAroundCam = *(float*)0x885B44; +float &CReplay::fBetaAngleLookAroundCam = *(float*)0x94072C; +float &CReplay::fAlphaAngleLookAroundCam = *(float*)0x8F2A0C; static void(*(&CBArray)[30])(CAnimBlendAssociation*, void*) = *(void(*(*)[30])(CAnimBlendAssociation*, void*))*(uintptr*)0x61052C; static void(*CBArray_RE3[])(CAnimBlendAssociation*, void*) = @@ -810,7 +815,11 @@ bool CReplay::PlayBackThisFrameInterpolation(CAddressInReplayBuffer *buffer, flo TheCamera.GetMatrix() = TheCamera.GetMatrix() * CMatrix(split); *TheCamera.GetMatrix().GetPosition() *= split; TheCamera.GetMatrix() += CMatrix(interpolation) * pg->camera_pos; - *RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera)) = TheCamera.GetMatrix().m_matrix; + RwMatrix* pm = RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera)); + 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; @@ -935,13 +944,20 @@ void CReplay::ProcessReplayCamera(void) { switch (CameraMode) { case REPLAYCAMMODE_TOPDOWN: + { *TheCamera.GetMatrix().GetPosition() = CVector(CameraFocusX, CameraFocusY, CameraFocusZ + 15.0f); *TheCamera.GetMatrix().GetForward() = CVector(0.0f, 0.0f, -1.0f); *TheCamera.GetMatrix().GetUp() = CVector(0.0f, 1.0f, 0.0f); *TheCamera.GetMatrix().GetRight() = CVector(1.0f, 0.0f, 0.0f); - *RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera)) = TheCamera.GetMatrix().m_matrix; + RwMatrix* pm = RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera)); + pm->pos = *(RwV3d*)TheCamera.GetMatrix().GetPosition(); + pm->at = *(RwV3d*)TheCamera.GetMatrix().GetForward(); + pm->up = *(RwV3d*)TheCamera.GetMatrix().GetUp(); + pm->right = *(RwV3d*)TheCamera.GetMatrix().GetRight(); break; + } case REPLAYCAMMODE_FIXED: + { *TheCamera.GetMatrix().GetPosition() = CVector(CameraFixedX, CameraFixedY, CameraFixedZ); CVector forward(CameraFocusX - CameraFixedX, CameraFocusY - CameraFixedY, CameraFocusZ - CameraFixedZ); forward.Normalise(); @@ -952,8 +968,13 @@ void CReplay::ProcessReplayCamera(void) *TheCamera.GetMatrix().GetForward() = forward; *TheCamera.GetMatrix().GetUp() = up; *TheCamera.GetMatrix().GetRight() = right; - *RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera)) = TheCamera.GetMatrix().m_matrix; + RwMatrix* pm = RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera)); + pm->pos = *(RwV3d*)TheCamera.GetMatrix().GetPosition(); + pm->at = *(RwV3d*)TheCamera.GetMatrix().GetForward(); + pm->up = *(RwV3d*)TheCamera.GetMatrix().GetUp(); + pm->right = *(RwV3d*)TheCamera.GetMatrix().GetRight(); break; + } default: break; } @@ -1302,13 +1323,210 @@ void CReplay::MarkEverythingAsNew(void) } } #endif + +#if 0 WRAPPER void CReplay::SaveReplayToHD(void) { EAXJMP(0x597330); } +#else +void CReplay::SaveReplayToHD(void) +{ + CFileMgr::SetDirMyDocuments(); + int fw = CFileMgr::OpenFileForWriting("replay.rep"); + if (fw < 0){ + debug("Couldn't open replay.rep for writing"); + CFileMgr::SetDir(""); + return; + } + CFileMgr::Write(fw, "gta3_7f", sizeof("gta3_7f")); + 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; + for(int i = first;; i = (i + 1) % 8 ){ + CFileMgr::Write(fw, (char*)Buffers[first], sizeof(Buffers[first])); + if (BufferStatus[i] == REPLAYBUFFER_RECORD) + break; + } + CFileMgr::CloseFile(fw); + CFileMgr::SetDir(""); +} +#endif + +#if 0 WRAPPER void PlayReplayFromHD(void) { EAXJMP(0x597420); } +#else +void PlayReplayFromHD(void) +{ + CFileMgr::SetDirMyDocuments(); + int fr = CFileMgr::OpenFile("replay.rep", "rb"); + if (fr < 0) { + debug("Couldn't open replay.rep for reading"); + /* Forgot to SetDir? */ + return; + } + CFileMgr::Read(fr, gString, 8); + if (strncmp(gString, "gta3_7f", sizeof("gta3_7f"))){ + CFileMgr::CloseFile(fr); + debug("Wrong file type for replay"); + CFileMgr::SetDir(""); + return; + } + int slot; + for (slot = 0; CFileMgr::Read(fr, (char*)CReplay::Buffers[slot], sizeof(CReplay::Buffers[slot])); slot++) + CReplay::BufferStatus[slot] = CReplay::REPLAYBUFFER_PLAYBACK; + CReplay::BufferStatus[slot - 1] = CReplay::REPLAYBUFFER_RECORD; + while (slot < 8) + CReplay::BufferStatus[slot++] = CReplay::REPLAYBUFFER_UNUSED; + CFileMgr::CloseFile(fr); + CFileMgr::SetDir(""); + CReplay::TriggerPlayback(CReplay::REPLAYCAMMODE_ASSTORED, 0.0f, 0.0f, 0.0f, false); + CReplay::bPlayingBackFromFile = true; + CReplay::bAllowLookAroundCam = true; + CReplay::StreamAllNecessaryCarsAndPeds(); +} +#endif + +#if 0 WRAPPER void CReplay::StreamAllNecessaryCarsAndPeds(void) { EAXJMP(0x597560); } +#else +void CReplay::StreamAllNecessaryCarsAndPeds(void) +{ + for (int slot = 0; slot < 8; slot++) { + if (BufferStatus[slot] == REPLAYBUFFER_UNUSED) + continue; + for (int offset = 0; Buffers[slot][offset] != REPLAYPACKET_END; offset += FindSizeOfPacket(Buffers[slot][offset])) { + switch (Buffers[slot][offset]) { + case REPLAYPACKET_VEHICLE: + CStreaming::RequestModel(((tVehicleUpdatePacket*)&Buffers[slot][offset])->mi, 0); + break; + case REPLAYPACKET_PED_HEADER: + CStreaming::RequestModel(((tPedHeaderPacket*)&Buffers[slot][offset])->mi, 0); + break; + default: + break; + } + } + } + CStreaming::LoadAllRequestedModels(false); +} +#endif + +#if 0 WRAPPER void CReplay::FindFirstFocusCoordinate(CVector *coord) { EAXJMP(0x5975E0); } +#else +void CReplay::FindFirstFocusCoordinate(CVector *coord) +{ + *coord = CVector(0.0f, 0.0f, 0.0f); + for (int slot = 0; slot < 8; slot++) { + if (BufferStatus[slot] == REPLAYBUFFER_UNUSED) + continue; + for (int offset = 0; Buffers[slot][offset] != REPLAYPACKET_END; offset += FindSizeOfPacket(Buffers[slot][offset])) { + if (Buffers[slot][offset] == REPLAYPACKET_GENERAL) { + *coord = ((tGeneralPacket*)&Buffers[slot][offset])->player_pos; + return; + } + } + } +} +#endif + +#if 0 WRAPPER bool CReplay::ShouldStandardCameraBeProcessed(void) { EAXJMP(0x597680); } +#else +bool CReplay::ShouldStandardCameraBeProcessed(void) +{ + if (Mode != MODE_PLAYBACK) + return true; + if (FramesActiveLookAroundCam || bPlayerInRCBuggy) + return false; + return FindPlayerVehicle() != nil; +} +#endif + +#if 0 WRAPPER void CReplay::ProcessLookAroundCam(void) { EAXJMP(0x5976C0); } +#else +void CReplay::ProcessLookAroundCam(void) +{ + if (!bAllowLookAroundCam) + return; + float x_moved = CPad::NewMouseControllerState.x / 200.0f; + float y_moved = CPad::NewMouseControllerState.y / 200.0f; + if (x_moved > 0.01f || y_moved > 0.01f) { + if (FramesActiveLookAroundCam == 0) + fDistanceLookAroundCam = 9.0f; + FramesActiveLookAroundCam = 60; + } + if (bPlayerInRCBuggy) + FramesActiveLookAroundCam = 0; + if (!FramesActiveLookAroundCam) + return; + --FramesActiveLookAroundCam; + fBetaAngleLookAroundCam += x_moved; + if (CPad::NewMouseControllerState.LMB && CPad::NewMouseControllerState.RMB) + fDistanceLookAroundCam = max(3.0f, min(15.0f, fDistanceLookAroundCam + 2.0f * y_moved)); + else + fAlphaAngleLookAroundCam = max(0.1f, min(1.5f, fAlphaAngleLookAroundCam + y_moved)); + CVector camera_pt( + fDistanceLookAroundCam * sin(fBetaAngleLookAroundCam) * cos(fAlphaAngleLookAroundCam), + fDistanceLookAroundCam * cos(fBetaAngleLookAroundCam) * cos(fAlphaAngleLookAroundCam), + fDistanceLookAroundCam * sin(fAlphaAngleLookAroundCam) + ); + CVector focus = CVector(CameraFocusX, CameraFocusY, CameraFocusZ); + camera_pt += focus; + CColPoint cp; + CEntity* pe = nil; + if (CWorld::ProcessLineOfSight(focus, camera_pt, cp, pe, true, false, false, false, false, true, true)){ + camera_pt = cp.point; + CVector direction = focus - cp.point; + direction.Normalise(); + camera_pt += direction / 4.0f; + } + CVector forward = focus - camera_pt; + forward.Normalise(); + CVector right = CrossProduct(CVector(0.0f, 0.0f, 1.0f), forward); + right.Normalise(); + CVector up = CrossProduct(forward, right); + up.Normalise(); + *TheCamera.GetMatrix().GetForward() = forward; + *TheCamera.GetMatrix().GetUp() = up; + *TheCamera.GetMatrix().GetRight() = right; + *TheCamera.GetMatrix().GetPosition() = camera_pt; + RwMatrix* pm = RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera)); + pm->pos = *(RwV3d*)TheCamera.GetMatrix().GetPosition(); + pm->at = *(RwV3d*)TheCamera.GetMatrix().GetForward(); + pm->up = *(RwV3d*)TheCamera.GetMatrix().GetUp(); + pm->right = *(RwV3d*)TheCamera.GetMatrix().GetRight(); + TheCamera.CalculateDerivedValues(); + RwMatrixUpdate(RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera))); + RwFrameUpdateObjects(RwCameraGetFrame(TheCamera.m_pRwCamera)); +} +#endif + +#if 0 WRAPPER size_t CReplay::FindSizeOfPacket(uint8 type) { EAXJMP(0x597CC0); } +#else +size_t CReplay::FindSizeOfPacket(uint8 type) +{ + switch (type) { + case REPLAYPACKET_END: return 4; + case REPLAYPACKET_VEHICLE: return sizeof(tVehicleUpdatePacket); + case REPLAYPACKET_PED_HEADER: return sizeof(tPedHeaderPacket); + case REPLAYPACKET_PED_UPDATE: return sizeof(tPedUpdatePacket); + case REPLAYPACKET_GENERAL: return sizeof(tGeneralPacket); + case REPLAYPACKET_CLOCK: return sizeof(tClockPacket); + case REPLAYPACKET_WEATHER: return sizeof(tWeatherPacket); + case REPLAYPACKET_ENDOFFRAME: return 4; + case REPLAYPACKET_TIMER: return sizeof(tTimerPacket); + case REPLAYPACKET_BULLET_TRACES:return sizeof(tBulletTracePacket); + default: break; + } + return 0; +} +#endif #if 0 WRAPPER void CReplay::Display(void) { EAXJMP(0x595EE0); } @@ -1328,12 +1546,14 @@ void CReplay::Display() #endif STARTPATCHES -InjectHook(0x592FC0, PrintElementsInPtrList, PATCH_JUMP); -InjectHook(0x592FE0, CReplay::Init, PATCH_JUMP); -InjectHook(0x593150, CReplay::DisableReplays, PATCH_JUMP); -InjectHook(0x593160, CReplay::EnableReplays, PATCH_JUMP); -InjectHook(0x593170, CReplay::Update, PATCH_JUMP); -InjectHook(0x595B20, CReplay::FinishPlayback, PATCH_JUMP); -InjectHook(0x595BD0, CReplay::EmptyReplayBuffer, PATCH_JUMP); -InjectHook(0x596030, CReplay::TriggerPlayback, PATCH_JUMP); +InjectHook(0x592FE0, &CReplay::Init, PATCH_JUMP); +InjectHook(0x593150, &CReplay::DisableReplays, PATCH_JUMP); +InjectHook(0x593160, &CReplay::EnableReplays, PATCH_JUMP); +InjectHook(0x593170, &CReplay::Update, PATCH_JUMP); +InjectHook(0x595B20, &CReplay::FinishPlayback, PATCH_JUMP); +InjectHook(0x595BD0, &CReplay::EmptyReplayBuffer, PATCH_JUMP); +InjectHook(0x595EE0, &CReplay::Display, PATCH_JUMP); +InjectHook(0x596030, &CReplay::TriggerPlayback, PATCH_JUMP); +InjectHook(0x597560, &CReplay::StreamAllNecessaryCarsAndPeds, PATCH_JUMP); +InjectHook(0x597680, &CReplay::ShouldStandardCameraBeProcessed, PATCH_JUMP); ENDPATCHES diff --git a/src/control/Replay.h b/src/control/Replay.h index 3a2ecc7f..d622ce9c 100644 --- a/src/control/Replay.h +++ b/src/control/Replay.h @@ -49,6 +49,8 @@ struct CStoredDetailedAnimationState uint16 aFlags2[6]; }; +void PlayReplayFromHD(void); + class CReplay { enum { @@ -245,6 +247,9 @@ private: static float &CameraFocusY; static float &CameraFocusZ; static bool &bPlayerInRCBuggy; + static float &fDistanceLookAroundCam; + static float &fAlphaAngleLookAroundCam; + static float &fBetaAngleLookAroundCam; public: static void Init(void); @@ -283,4 +288,7 @@ private: static void FindFirstFocusCoordinate(CVector *coord); static void ProcessLookAroundCam(void); static size_t FindSizeOfPacket(uint8); + + /* Absolute nonsense, but how could this function end up being outside of class? */ + friend void PlayReplayFromHD(void); };