First commit of replay system
This commit is contained in:
parent
75ede35342
commit
8b47a5b9f4
3
.gitignore
vendored
3
.gitignore
vendored
@ -3,3 +3,6 @@
|
|||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
/.vs
|
/.vs
|
||||||
|
/bin/Debug
|
||||||
|
/build
|
||||||
|
/src/skel/win
|
||||||
|
12
src/BulletTrace.h
Normal file
12
src/BulletTrace.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
struct CBulletTrace
|
||||||
|
{
|
||||||
|
CVector m_vecInf;
|
||||||
|
CVector m_vecSup;
|
||||||
|
char m_bInUse;
|
||||||
|
char m_bFramesInUse;
|
||||||
|
char m_bLifeTime;
|
||||||
|
};
|
3
src/BulletTraces.cpp
Normal file
3
src/BulletTraces.cpp
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#include "BulletTraces.h"
|
||||||
|
|
||||||
|
CBulletTrace (&CBulletTraces::aTraces)[16] = *(CBulletTrace(*)[16])0x72B1B8;
|
9
src/BulletTraces.h
Normal file
9
src/BulletTraces.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "BulletTrace.h"
|
||||||
|
|
||||||
|
class CBulletTraces
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static CBulletTrace(&aTraces)[16];
|
||||||
|
};
|
@ -525,7 +525,7 @@ void CPad::UpdatePads(void)
|
|||||||
ControlsManager.AffectPadFromKeyBoard();
|
ControlsManager.AffectPadFromKeyBoard();
|
||||||
ControlsManager.AffectPadFromMouse();
|
ControlsManager.AffectPadFromMouse();
|
||||||
|
|
||||||
if ( CReplay::bPlayingBackFromFile )
|
if ( CReplay::IsPlayingBackFromFile() )
|
||||||
bUpdate = false;
|
bUpdate = false;
|
||||||
|
|
||||||
if ( bUpdate )
|
if ( bUpdate )
|
||||||
|
33
src/Pickup.h
Normal file
33
src/Pickup.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "common.h"
|
||||||
|
#include "Object.h"
|
||||||
|
|
||||||
|
enum ePickupType
|
||||||
|
{
|
||||||
|
PICKUP_NONE = 0,
|
||||||
|
PICKUP_IN_SHOP = 1,
|
||||||
|
PICKUP_ON_STREET = 2,
|
||||||
|
PICKUP_ONCE = 3,
|
||||||
|
PICKUP_ONCE_TIMEOUT = 4,
|
||||||
|
PICKUP_COLLECTABLE1 = 5,
|
||||||
|
PICKUP_IN_SHOP_OUT_OF_STOCK = 6,
|
||||||
|
PICKUP_MONEY = 7,
|
||||||
|
PICKUP_MINE_INACTIVE = 8,
|
||||||
|
PICKUP_MINE_ARMED = 9,
|
||||||
|
PICKUP_NAUTICAL_MINE_INACTIVE = 10,
|
||||||
|
PICKUP_NAUTICAL_MINE_ARMED = 11,
|
||||||
|
PICKUP_FLOATINGPACKAGE = 12,
|
||||||
|
PICKUP_FLOATINGPACKAGE_FLOATING = 13,
|
||||||
|
PICKUP_ON_STREET_SLOW = 14,
|
||||||
|
};
|
||||||
|
|
||||||
|
class CPickup
|
||||||
|
{
|
||||||
|
ePickupType m_eType;
|
||||||
|
unsigned __int16 m_wQuantity;
|
||||||
|
CObject *m_pObject;
|
||||||
|
int m_nTimer;
|
||||||
|
__int16 m_eModelIndex;
|
||||||
|
__int16 m_wIndex;
|
||||||
|
CVector m_vecPos;
|
||||||
|
};
|
@ -31,7 +31,7 @@ void COnscreenTimer::Init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void COnscreenTimer::Process() {
|
void COnscreenTimer::Process() {
|
||||||
if(CReplay::Mode != CReplay::MODE_1 && !m_bDisabled) {
|
if(!CReplay::IsPlayingBack() && !m_bDisabled) {
|
||||||
for(uint32 i = 0; i < NUMONSCREENTIMERENTRIES; i++) {
|
for(uint32 i = 0; i < NUMONSCREENTIMERENTRIES; i++) {
|
||||||
m_sEntries[i].Process();
|
m_sEntries[i].Process();
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ void cMusicManager::DisplayRadioStationName()
|
|||||||
int8 gStreamedSound;
|
int8 gStreamedSound;
|
||||||
int8 gRetuneCounter;
|
int8 gRetuneCounter;
|
||||||
|
|
||||||
if (!CTimer::GetIsPaused() && !TheCamera.m_WideScreenOn && cMusicManager::PlayerInCar() && CReplay::Mode != 1) {
|
if (!CTimer::GetIsPaused() && !TheCamera.m_WideScreenOn && cMusicManager::PlayerInCar() && !CReplay::IsPlayingBack()) {
|
||||||
if (MusicManager.m_bPlayerInCar && !MusicManager.m_bPreviousPlayerInCar)
|
if (MusicManager.m_bPlayerInCar && !MusicManager.m_bPreviousPlayerInCar)
|
||||||
pCurrentStation = nullptr;
|
pCurrentStation = nullptr;
|
||||||
|
|
||||||
|
@ -1,8 +1,255 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "patcher.h"
|
#include "patcher.h"
|
||||||
|
#include "BulletTraces.h"
|
||||||
|
#include "Clock.h"
|
||||||
|
#include "Draw.h"
|
||||||
|
#include "math/Matrix.h"
|
||||||
|
#include "ModelIndices.h"
|
||||||
#include "Replay.h"
|
#include "Replay.h"
|
||||||
|
#include "Pad.h"
|
||||||
|
#include "Pools.h"
|
||||||
|
#include "CutsceneMgr.h"
|
||||||
|
#include "Timer.h"
|
||||||
|
#include "Weather.h"
|
||||||
|
|
||||||
uint8 &CReplay::Mode = *(uint8*)0x95CD5B;
|
uint8 &CReplay::Mode = *(uint8*)0x95CD5B;
|
||||||
|
CAddressInReplayBuffer &CReplay::Record = *(CAddressInReplayBuffer*)0x942F7C;
|
||||||
|
CAddressInReplayBuffer &CReplay::Playback = *(CAddressInReplayBuffer*)0x8F5F48;
|
||||||
|
uint8 *&CReplay::pBuf0 = *(uint8**)0x8E2C64;
|
||||||
|
CAutomobile *&CReplay::pBuf1 = *(CAutomobile**)0x8E2C68;
|
||||||
|
uint8 *&CReplay::pBuf2 = *(uint8**)0x8E2C6C;
|
||||||
|
CPlayerPed *&CReplay::pBuf3 = *(CPlayerPed**)0x8E2C70;
|
||||||
|
uint8 *&CReplay::pBuf4 = *(uint8**)0x8E2C74;
|
||||||
|
CCutsceneHead *&CReplay::pBuf5 = *(CCutsceneHead**)0x8E2C78;
|
||||||
|
uint8 *&CReplay::pBuf6 = *(uint8**)0x8E2C80;
|
||||||
|
CPtrNode *&CReplay::pBuf7 = *(CPtrNode**)0x8E2C84;
|
||||||
|
uint8 *&CReplay::pBuf8 = *(uint8**)0x8E2C54;
|
||||||
|
CEntryInfoNode *&CReplay::pBuf9 = *(CEntryInfoNode**)0x8E2C58;
|
||||||
|
uint8 *&CReplay::pBuf10 = *(uint8**)0x8F2C28;
|
||||||
|
CDummyPed *&CReplay::pBuf11 = *(CDummyPed**)0x8F2C2C;
|
||||||
|
CBlip *&CReplay::pRadarBlips = *(CBlip**)0x8F29F8;
|
||||||
|
CCamera *&CReplay::pStoredCam = *(CCamera**)0x8F2C34;
|
||||||
|
CSector *&CReplay::pWorld1 = *(CSector**)0x8E29C4;
|
||||||
|
CReference *&CReplay::pEmptyReferences = *(CReference**)0x8F256C;
|
||||||
|
CStoredDetailedAnimationState *&CReplay::pPedAnims = *(CStoredDetailedAnimationState**)0x8F6260;
|
||||||
|
CPickup *&CReplay::pPickups = *(CPickup**)0x8F1A48;
|
||||||
|
CReference *&CReplay::pReferences = *(CReference**)0x880FAC;
|
||||||
|
uint8(&CReplay::BufferStatus)[8] = *(uint8(*)[8])0x8804D8;
|
||||||
|
uint8(&CReplay::Buffers)[8][100000] = *(uint8(*)[8][100000])0x779958;
|
||||||
bool &CReplay::bPlayingBackFromFile = *(bool*)0x95CD58;
|
bool &CReplay::bPlayingBackFromFile = *(bool*)0x95CD58;
|
||||||
|
bool &CReplay::bReplayEnabled = *(bool*)0x617CAC;
|
||||||
|
uint32 &CReplay::SlowMotion = *(uint32*)0x9414D4;
|
||||||
|
uint32 &CReplay::FramesActiveLookAroundCam = *(uint32*)0x880F84;
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
WRAPPER void CReplay::Init(void) { EAXJMP(0x592FE0); }
|
||||||
|
#else
|
||||||
|
void CReplay::Init(void)
|
||||||
|
{
|
||||||
|
pBuf0 = nil;
|
||||||
|
pBuf1 = nil;
|
||||||
|
pBuf2 = nil;
|
||||||
|
pBuf3 = nil;
|
||||||
|
pBuf4 = nil;
|
||||||
|
pBuf5 = nil;
|
||||||
|
pBuf6 = nil;
|
||||||
|
pBuf7 = nil;
|
||||||
|
pBuf8 = nil;
|
||||||
|
pBuf9 = nil;
|
||||||
|
pBuf10 = nil;
|
||||||
|
pBuf11 = nil;
|
||||||
|
pRadarBlips = nil;
|
||||||
|
pStoredCam = nil;
|
||||||
|
pWorld1 = nil;
|
||||||
|
pEmptyReferences = nil;
|
||||||
|
pPedAnims = nil;
|
||||||
|
pPickups = nil;
|
||||||
|
pReferences = nil;
|
||||||
|
Mode = MODE_RECORD;
|
||||||
|
Playback.m_nOffset = 0;
|
||||||
|
Playback.m_pBase = nil;
|
||||||
|
Playback.m_bSlot = 0;
|
||||||
|
Record.m_nOffset = 0;
|
||||||
|
Record.m_pBase = nil;
|
||||||
|
Record.m_bSlot = 0;
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
BufferStatus[i] = REPLAYBUFFER_UNUSED;
|
||||||
|
Record.m_bSlot = 0;
|
||||||
|
Record.m_pBase = Buffers[0];
|
||||||
|
BufferStatus[0] = REPLAYBUFFER_RECORD;
|
||||||
|
Buffers[0][Record.m_nOffset] = REPLAYPACKET_END;
|
||||||
|
bPlayingBackFromFile = false;
|
||||||
|
bReplayEnabled = true;
|
||||||
|
SlowMotion = 1;
|
||||||
|
FramesActiveLookAroundCam = 0;
|
||||||
|
bDoLoadSceneWhenDone = false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void CReplay::DisableReplays(void)
|
||||||
|
{
|
||||||
|
bReplayEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CReplay::EnableReplays(void)
|
||||||
|
{
|
||||||
|
bReplayEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
WRAPPER void CReplay::Update(void) { EAXJMP(0x593170); }
|
||||||
|
#else
|
||||||
|
void PlayReplayFromHD(void);
|
||||||
|
void CReplay::Update(void)
|
||||||
|
{
|
||||||
|
if (CCutsceneMgr::IsCutsceneProcessing() || CTimer::GetIsPaused())
|
||||||
|
return;
|
||||||
|
switch (Mode){
|
||||||
|
case MODE_RECORD:
|
||||||
|
RecordThisFrame();
|
||||||
|
break;
|
||||||
|
case MODE_PLAYBACK:
|
||||||
|
PlaybackThisFrame();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (CDraw::FadeValue || !bReplayEnabled)
|
||||||
|
return;
|
||||||
|
if (Mode == MODE_PLAYBACK){
|
||||||
|
if (CPad::NewKeyState.F[0] && !CPad::OldKeyState.F[0])
|
||||||
|
FinishPlayback();
|
||||||
|
}
|
||||||
|
else if (Mode == MODE_RECORD){
|
||||||
|
if (CPad::NewKeyState.F[0] && !CPad::OldKeyState.F[0])
|
||||||
|
TriggerPlayback(REPLAYCAMMODE_ASSTORED, 0.0f, 0.0f, 0.0f, false);
|
||||||
|
if (CPad::NewKeyState.F[1] && !CPad::OldKeyState.F[1])
|
||||||
|
SaveReplayToHD();
|
||||||
|
if (CPad::NewKeyState.F[2] && !CPad::OldKeyState.F[2])
|
||||||
|
PlayReplayFromHD();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
WRAPPER void CReplay::RecordThisFrame(void) { EAXJMP(0x5932B0); }
|
||||||
|
#else
|
||||||
|
|
||||||
|
void CReplay::RecordThisFrame(void)
|
||||||
|
{
|
||||||
|
tGeneralPacket* general = (tGeneralPacket*)&Record.m_pBase[Record.m_nOffset];
|
||||||
|
general->type = REPLAYPACKET_GENERAL;
|
||||||
|
general->camera_pos.CopyOnlyMatrix(&TheCamera.GetMatrix());
|
||||||
|
FindPlayerCoors(general->player_pos);
|
||||||
|
general->in_rcvehicle = CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle ? true : false;
|
||||||
|
Record.m_nOffset += sizeof(*general);
|
||||||
|
tClockPacket* clock = (tClockPacket*)&Record.m_pBase[Record.m_nOffset];
|
||||||
|
clock->type = REPLAYPACKET_CLOCK;
|
||||||
|
clock->hours = CClock::GetHours();
|
||||||
|
clock->minutes = CClock::GetMinutes();
|
||||||
|
Record.m_nOffset += sizeof(*clock);
|
||||||
|
tWeatherPacket* weather = (tWeatherPacket*)&Record.m_pBase[Record.m_nOffset];
|
||||||
|
weather->type = REPLAYPACKET_WEATHER;
|
||||||
|
weather->old_weather = CWeather::OldWeatherType;
|
||||||
|
weather->new_weather = CWeather::NewWeatherType;
|
||||||
|
weather->interpolation = CWeather::InterpolationValue;
|
||||||
|
Record.m_nOffset += sizeof(*weather);
|
||||||
|
tTimerPacket* timer = (tTimerPacket*)&Record.m_pBase[Record.m_nOffset];
|
||||||
|
timer->type = REPLAYPACKET_TIMER;
|
||||||
|
timer->timer = CTimer::GetTimeInMilliseconds();
|
||||||
|
Record.m_nOffset += sizeof(*timer);
|
||||||
|
CVehiclePool* vehicles = CPools::GetVehiclePool();
|
||||||
|
for (int i = 0; i < vehicles->GetSize(); i++){
|
||||||
|
CVehicle* v = vehicles->GetSlot(i);
|
||||||
|
if (v && v->m_rwObject && v->GetModelIndex() != MI_AIRTRAIN && v->GetModelIndex() != MI_TRAIN)
|
||||||
|
StoreCarUpdate(v, i);
|
||||||
|
}
|
||||||
|
CPedPool* peds = CPools::GetPedPool();
|
||||||
|
for (int i = 0; i < peds->GetSize(); i++) {
|
||||||
|
CPed* p = peds->GetSlot(i);
|
||||||
|
if (!p || !p->m_rwObject)
|
||||||
|
continue;
|
||||||
|
if (!p->bRecordedForReplay){
|
||||||
|
tPedHeaderPacket* ph = (tPedHeaderPacket*)&Record.m_pBase[Record.m_nOffset];
|
||||||
|
ph->type = REPLAYPACKET_PED_HEADER;
|
||||||
|
ph->index = i;
|
||||||
|
ph->mi = p->GetModelIndex();
|
||||||
|
ph->pedtype = p->m_nPedType;
|
||||||
|
Record.m_nOffset += sizeof(*ph);
|
||||||
|
p->bRecordedForReplay = true;
|
||||||
|
}
|
||||||
|
StorePedUpdate(p, i);
|
||||||
|
}
|
||||||
|
for (uint8 i = 0; i < 16; i++){
|
||||||
|
if (!CBulletTraces::aTraces[i].m_bInUse)
|
||||||
|
continue;
|
||||||
|
tBulletTracePacket* bt = (tBulletTracePacket*)&Record.m_pBase[Record.m_nOffset];
|
||||||
|
bt->type = REPLAYPACKET_BULLETTRACES;
|
||||||
|
bt->index = i;
|
||||||
|
bt->frames = CBulletTraces::aTraces[i].m_bFramesInUse;
|
||||||
|
bt->lifetime = CBulletTraces::aTraces[i].m_bLifeTime;
|
||||||
|
bt->inf = CBulletTraces::aTraces[i].m_vecInf;
|
||||||
|
bt->sup = CBulletTraces::aTraces[i].m_vecSup;
|
||||||
|
Record.m_nOffset += sizeof(*bt);
|
||||||
|
}
|
||||||
|
tEndOfFramePacket* eof = (tEndOfFramePacket*)&Record.m_pBase[Record.m_nOffset];
|
||||||
|
eof->type = REPLAYPACKET_ENDOFFRAME;
|
||||||
|
Record.m_nOffset += sizeof(*eof);
|
||||||
|
if (Record.m_nOffset <= 97000){
|
||||||
|
/* Unsafe assumption which can cause buffer overflow
|
||||||
|
* if size of next frame exceeds 3000 bytes.
|
||||||
|
* Most notably it causes various timecyc errors. */
|
||||||
|
Record.m_pBase[Record.m_nOffset] = REPLAYPACKET_END;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Record.m_pBase[Record.m_nOffset] = REPLAYPACKET_END;
|
||||||
|
BufferStatus[Record.m_bSlot] = REPLAYBUFFER_PLAYBACK;
|
||||||
|
Record.m_bSlot = (Record.m_bSlot + 1) % 8;
|
||||||
|
BufferStatus[Record.m_bSlot] = REPLAYBUFFER_RECORD;
|
||||||
|
Record.m_pBase = Buffers[Record.m_bSlot];
|
||||||
|
Record.m_nOffset = 0;
|
||||||
|
*Record.m_pBase = REPLAYPACKET_END;
|
||||||
|
MarkEverythingAsNew();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
WRAPPER void CReplay::StorePedUpdate(CPed *ped, int id) { EAXJMP(0x5935B0); }
|
||||||
|
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); }
|
||||||
|
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); }
|
||||||
|
WRAPPER void CReplay::StoreCarUpdate(CVehicle *vehicle, int id) { EAXJMP(0x5947F0); }
|
||||||
|
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); }
|
WRAPPER void CReplay::Display(void) { EAXJMP(0x595EE0); }
|
||||||
|
WRAPPER void CReplay::TriggerPlayback(uint8 cam_mode, float cam_x, float cam_y, float cam_z, bool load_scene) { EAXJMP(0x596030); }
|
||||||
|
WRAPPER void CReplay::StoreStuffInMem(void) { EAXJMP(0x5961F0); }
|
||||||
|
WRAPPER void CReplay::RestoreStuffFromMem(void) { EAXJMP(0x5966E0); }
|
||||||
|
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 bool CReplay::ShouldStandardCameraBeProcessed(void) { EAXJMP(0x597680); }
|
||||||
|
WRAPPER void CReplay::ProcessLookAroundCam(void) { EAXJMP(0x5976C0); }
|
||||||
|
WRAPPER size_t CReplay::FindSizeOfPacket(uint8 type) { EAXJMP(0x597CC0); }
|
||||||
|
|
||||||
|
STARTPATCHES
|
||||||
|
InjectHook(0x592FC0, PrintElementsInPtrList, PATCH_JUMP);
|
||||||
|
InjectHook(0x592FE0, CReplay::Init, PATCH_JUMP);
|
||||||
|
InjectHook(0x593150, CReplay::DisableReplays, PATCH_JUMP);
|
||||||
|
InjectHook(0x593150, CReplay::EnableReplays, PATCH_JUMP);
|
||||||
|
InjectHook(0x593170, CReplay::Update, PATCH_JUMP);
|
||||||
|
ENDPATCHES
|
@ -1,14 +1,217 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "Camera.h"
|
||||||
|
#include "Ped.h"
|
||||||
|
#include "Pools.h"
|
||||||
|
#include "Pickup.h"
|
||||||
|
#include "Radar.h"
|
||||||
|
#include "References.h"
|
||||||
|
#include "Vehicle.h"
|
||||||
|
#include "World.h"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
struct CAddressInReplayBuffer
|
||||||
|
{
|
||||||
|
unsigned int m_nOffset;
|
||||||
|
uint8 *m_pBase;
|
||||||
|
uint8 m_bSlot;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CStoredAnimationState
|
||||||
|
{
|
||||||
|
char animId;
|
||||||
|
char time;
|
||||||
|
char speed;
|
||||||
|
char secAnimId;
|
||||||
|
char secTime;
|
||||||
|
char secSpeed;
|
||||||
|
char blendAmount;
|
||||||
|
char partAnimId;
|
||||||
|
char partAnimTime;
|
||||||
|
char partAnimSpeed;
|
||||||
|
char partBlendAmount;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CStoredDetailedAnimationState
|
||||||
|
{
|
||||||
|
char m_abAnimId[3];
|
||||||
|
char m_abCurTime[3];
|
||||||
|
char m_abSpeed[3];
|
||||||
|
char m_abBlendAmount[3];
|
||||||
|
char m_abFunctionCallbackID[3];
|
||||||
|
int16 m_awFlags[3];
|
||||||
|
char m_abAnimId2[6];
|
||||||
|
char m_abCurTime2[6];
|
||||||
|
char m_abSpeed2[6];
|
||||||
|
char m_abBlendAmount2[6];
|
||||||
|
char m_abFunctionCallbackID2[6];
|
||||||
|
int16 m_awFlags2[6];
|
||||||
|
};
|
||||||
|
|
||||||
class CReplay
|
class CReplay
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
enum {
|
enum {
|
||||||
MODE_1 = 1
|
MODE_RECORD = 0,
|
||||||
|
MODE_PLAYBACK = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
REPLAYCAMMODE_ASSTORED = 0,
|
||||||
|
REPLAYCAMMODE_TOPDOWN = 1,
|
||||||
|
REPLAYCAMMODE_FIXED = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
REPLAYPACKET_END = 0,
|
||||||
|
REPLAYPACKET_VEHICLE = 1,
|
||||||
|
REPLAYPACKET_PED_HEADER = 2,
|
||||||
|
REPLAYPACKET_PED = 3,
|
||||||
|
REPLAYPACKET_GENERAL = 4,
|
||||||
|
REPLAYPACKET_CLOCK = 5,
|
||||||
|
REPLAYPACKET_WEATHER = 6,
|
||||||
|
REPLAYPACKET_ENDOFFRAME = 7,
|
||||||
|
REPLAYPACKET_TIMER = 8,
|
||||||
|
REPLAYPACKET_BULLETTRACES = 9
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
REPLAYBUFFER_UNUSED = 0,
|
||||||
|
REPLAYBUFFER_PLAYBACK = 1,
|
||||||
|
REPLAYBUFFER_RECORD = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct tGeneralPacket
|
||||||
|
{
|
||||||
|
uint8 type;
|
||||||
|
bool in_rcvehicle;
|
||||||
|
CMatrix camera_pos;
|
||||||
|
CVector player_pos;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(tGeneralPacket) == 88, "tGeneralPacket: error");
|
||||||
|
|
||||||
|
struct tClockPacket
|
||||||
|
{
|
||||||
|
uint8 type;
|
||||||
|
uint8 hours;
|
||||||
|
uint8 minutes;
|
||||||
|
private:
|
||||||
|
uint8 __align;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(tClockPacket) == 4, "tClockPacket: error");
|
||||||
|
|
||||||
|
struct tWeatherPacket
|
||||||
|
{
|
||||||
|
uint8 type;
|
||||||
|
uint8 old_weather;
|
||||||
|
uint8 new_weather;
|
||||||
|
float interpolation;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(tWeatherPacket) == 8, "tWeatherPacket: error");
|
||||||
|
|
||||||
|
struct tTimerPacket
|
||||||
|
{
|
||||||
|
uint8 type;
|
||||||
|
uint32 timer;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(tTimerPacket) == 8, "tTimerPacket: error");
|
||||||
|
|
||||||
|
struct tPedHeaderPacket
|
||||||
|
{
|
||||||
|
uint8 type;
|
||||||
|
uint8 index;
|
||||||
|
uint16 mi;
|
||||||
|
uint8 pedtype;
|
||||||
|
private:
|
||||||
|
uint8 __align[3];
|
||||||
|
};
|
||||||
|
static_assert(sizeof(tPedHeaderPacket) == 8, "tPedHeaderPacket: error");
|
||||||
|
|
||||||
|
struct tBulletTracePacket
|
||||||
|
{
|
||||||
|
uint8 type;
|
||||||
|
uint8 frames;
|
||||||
|
uint8 lifetime;
|
||||||
|
uint8 index;
|
||||||
|
CVector inf;
|
||||||
|
CVector sup;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(tBulletTracePacket) == 28, "tBulletTracePacket: error");
|
||||||
|
|
||||||
|
struct tEndOfFramePacket
|
||||||
|
{
|
||||||
|
uint8 type;
|
||||||
|
private:
|
||||||
|
uint8 __align[3];
|
||||||
|
};
|
||||||
|
static_assert(sizeof(tEndOfFramePacket) == 4, "tEndOfFramePacket: error");
|
||||||
|
|
||||||
|
private:
|
||||||
static uint8 &Mode;
|
static uint8 &Mode;
|
||||||
|
static CAddressInReplayBuffer &Record;
|
||||||
|
static CAddressInReplayBuffer &Playback;
|
||||||
|
static uint8 *&pBuf0;
|
||||||
|
static CAutomobile *&pBuf1;
|
||||||
|
static uint8 *&pBuf2;
|
||||||
|
static CPlayerPed *&pBuf3;
|
||||||
|
static uint8 *&pBuf4;
|
||||||
|
static CCutsceneHead *&pBuf5;
|
||||||
|
static uint8 *&pBuf6;
|
||||||
|
static CPtrNode *&pBuf7;
|
||||||
|
static uint8 *&pBuf8;
|
||||||
|
static CEntryInfoNode *&pBuf9;
|
||||||
|
static uint8 *&pBuf10;
|
||||||
|
static CDummyPed *&pBuf11;
|
||||||
|
static CBlip *&pRadarBlips;
|
||||||
|
static CCamera *&pStoredCam;
|
||||||
|
static CSector *&pWorld1;
|
||||||
|
static CReference *&pEmptyReferences;
|
||||||
|
static CStoredDetailedAnimationState *&pPedAnims;
|
||||||
|
static CPickup *&pPickups;
|
||||||
|
static CReference *&pReferences;
|
||||||
|
static uint8 (&BufferStatus)[8];
|
||||||
|
static uint8 (&Buffers)[8][100000];
|
||||||
static bool &bPlayingBackFromFile;
|
static bool &bPlayingBackFromFile;
|
||||||
|
static bool &bReplayEnabled;
|
||||||
|
static uint32 &SlowMotion;
|
||||||
|
static uint32 &FramesActiveLookAroundCam;
|
||||||
|
static bool &bDoLoadSceneWhenDone;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void Init(void);
|
||||||
|
static void DisableReplays(void);
|
||||||
|
static void EnableReplays(void);
|
||||||
|
static void Update(void);
|
||||||
|
static void FinishPlayback(void);
|
||||||
|
static void Shutdown(void);
|
||||||
static void Display(void);
|
static void Display(void);
|
||||||
|
static void TriggerPlayback(uint8 cam_mode, float cam_x, float cam_y, float cam_z, bool load_scene);
|
||||||
|
static void StreamAllNecessaryCarsAndPeds(void);
|
||||||
|
static bool ShouldStandardCameraBeProcessed(void);
|
||||||
|
|
||||||
|
inline static bool IsPlayingBack() { return Mode == MODE_PLAYBACK; }
|
||||||
|
inline static bool IsPlayingBackFromFile() { return bPlayingBackFromFile; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void RecordThisFrame(void);
|
||||||
|
static void StorePedUpdate(CPed *ped, int id);
|
||||||
|
static void StorePedAnimation(CPed *ped, CStoredAnimationState *state);
|
||||||
|
static void StoreDetailedPedAnimation(CPed *ped, CStoredDetailedAnimationState *state);
|
||||||
|
static void ProcessPedUpdate(CPed *ped, float interpolation, CAddressInReplayBuffer *buffer);
|
||||||
|
static void RetrievePedAnimation(CPed *ped, CStoredAnimationState *state);
|
||||||
|
static void RetrieveDetailedPedAnimation(CPed *ped, CStoredDetailedAnimationState *state);
|
||||||
|
static void PlaybackThisFrame(void);
|
||||||
|
static void StoreCarUpdate(CVehicle *vehicle, int id);
|
||||||
|
static void ProcessCarUpdate(CVehicle *vehicle, float interpolation, CAddressInReplayBuffer *buffer);
|
||||||
|
static bool PlayBackThisFrameInterpolation(CAddressInReplayBuffer *buffer, float interpolation, uint32 *pTimer);
|
||||||
|
static void ProcessReplayCamera(void);
|
||||||
|
static void StoreStuffInMem(void);
|
||||||
|
static void RestoreStuffFromMem(void);
|
||||||
|
static void EmptyPedsAndVehiclePools(void);
|
||||||
|
static void EmptyAllPools(void);
|
||||||
|
static void MarkEverythingAsNew(void);
|
||||||
|
static void SaveReplayToHD(void);
|
||||||
|
static void FindFirstFocusCoordinate(CVector *coord);
|
||||||
|
static void ProcessLookAroundCam(void);
|
||||||
|
static size_t FindSizeOfPacket(uint8);
|
||||||
};
|
};
|
||||||
|
@ -160,7 +160,7 @@ public:
|
|||||||
uint8 m_ped_flagI1 : 1;
|
uint8 m_ped_flagI1 : 1;
|
||||||
uint8 m_ped_flagI2 : 1;
|
uint8 m_ped_flagI2 : 1;
|
||||||
uint8 m_ped_flagI4 : 1;
|
uint8 m_ped_flagI4 : 1;
|
||||||
uint8 m_ped_flagI8 : 1;
|
uint8 bRecordedForReplay : 1;
|
||||||
uint8 m_ped_flagI10 : 1;
|
uint8 m_ped_flagI10 : 1;
|
||||||
uint8 m_ped_flagI20 : 1;
|
uint8 m_ped_flagI20 : 1;
|
||||||
uint8 m_ped_flagI40 : 1;
|
uint8 m_ped_flagI40 : 1;
|
||||||
|
@ -155,6 +155,9 @@ public:
|
|||||||
r.Normalise();
|
r.Normalise();
|
||||||
f = CrossProduct(u, r);
|
f = CrossProduct(u, r);
|
||||||
}
|
}
|
||||||
|
void CopyOnlyMatrix(CMatrix *other){
|
||||||
|
m_matrix = other->m_matrix;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline CMatrix&
|
inline CMatrix&
|
||||||
|
@ -189,7 +189,7 @@ void CHud::Draw()
|
|||||||
RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT);
|
RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT);
|
||||||
RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);
|
RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);
|
||||||
|
|
||||||
if (CReplay::Mode != 1) {
|
if (!CReplay::IsPlayingBack()) {
|
||||||
if (m_Wants_To_Draw_Hud && !TheCamera.m_WideScreenOn) {
|
if (m_Wants_To_Draw_Hud && !TheCamera.m_WideScreenOn) {
|
||||||
bool Mode_RunAround = 0;
|
bool Mode_RunAround = 0;
|
||||||
bool Mode_FirstPerson = 0;
|
bool Mode_FirstPerson = 0;
|
||||||
@ -1063,7 +1063,7 @@ WRAPPER void CHud::DrawAfterFade(void) { EAXJMP(0x509030); }
|
|||||||
#else
|
#else
|
||||||
void CHud::DrawAfterFade()
|
void CHud::DrawAfterFade()
|
||||||
{
|
{
|
||||||
if (CTimer::GetIsUserPaused() || CReplay::Mode == 1)
|
if (CTimer::GetIsUserPaused() || CReplay::IsPlayingBack())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (m_HelpMessage[0]) {
|
if (m_HelpMessage[0]) {
|
||||||
|
@ -101,6 +101,27 @@ public:
|
|||||||
n++;
|
n++;
|
||||||
return 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);
|
||||||
|
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)*size);
|
||||||
|
*entries = (U*)malloc(sizeof(U)*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 */
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
Loading…
Reference in New Issue
Block a user