#pragma once #include "Pools.h" #include "World.h" #ifdef FIX_BUGS #ifndef DONT_FIX_REPLAY_BUGS #define FIX_REPLAY_BUGS #endif #endif class CVehicle; struct CReference; struct CAddressInReplayBuffer { uint32 m_nOffset; uint8 *m_pBase; uint8 m_bSlot; }; struct CStoredAnimationState { uint8 animId; uint8 time; uint8 speed; uint8 secAnimId; uint8 secTime; uint8 secSpeed; uint8 blendAmount; uint8 partAnimId; uint8 partAnimTime; uint8 partAnimSpeed; uint8 partBlendAmount; }; enum { NUM_MAIN_ANIMS_IN_REPLAY = 3, NUM_PARTIAL_ANIMS_IN_REPLAY = 6 }; struct CStoredDetailedAnimationState { uint8 aAnimId[NUM_MAIN_ANIMS_IN_REPLAY]; uint8 aCurTime[NUM_MAIN_ANIMS_IN_REPLAY]; uint8 aSpeed[NUM_MAIN_ANIMS_IN_REPLAY]; uint8 aBlendAmount[NUM_MAIN_ANIMS_IN_REPLAY]; #ifdef FIX_REPLAY_BUGS int8 aBlendDelta[NUM_MAIN_ANIMS_IN_REPLAY]; #endif uint8 aFunctionCallbackID[NUM_MAIN_ANIMS_IN_REPLAY]; uint16 aFlags[NUM_MAIN_ANIMS_IN_REPLAY]; uint8 aAnimId2[NUM_PARTIAL_ANIMS_IN_REPLAY]; uint8 aCurTime2[NUM_PARTIAL_ANIMS_IN_REPLAY]; uint8 aSpeed2[NUM_PARTIAL_ANIMS_IN_REPLAY]; uint8 aBlendAmount2[NUM_PARTIAL_ANIMS_IN_REPLAY]; #ifdef FIX_REPLAY_BUGS int8 aBlendDelta2[NUM_PARTIAL_ANIMS_IN_REPLAY]; #endif uint8 aFunctionCallbackID2[NUM_PARTIAL_ANIMS_IN_REPLAY]; uint16 aFlags2[NUM_PARTIAL_ANIMS_IN_REPLAY]; }; void PlayReplayFromHD(void); class CReplay { enum { 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_UPDATE = 3, REPLAYPACKET_GENERAL = 4, REPLAYPACKET_CLOCK = 5, REPLAYPACKET_WEATHER = 6, REPLAYPACKET_ENDOFFRAME = 7, REPLAYPACKET_TIMER = 8, REPLAYPACKET_BULLET_TRACES = 9 }; enum { REPLAYBUFFER_UNUSED = 0, REPLAYBUFFER_PLAYBACK = 1, REPLAYBUFFER_RECORD = 2 }; enum { NUM_REPLAYBUFFERS = 8, REPLAYBUFFERSIZE = 100000 }; 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"); struct tPedUpdatePacket { uint8 type; uint8 index; int8 heading; int8 vehicle_index; CStoredAnimationState anim_state; CCompressedMatrixNotAligned matrix; int8 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; int8 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; 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 uint8 *pRadarBlips; static uint8 *pStoredCam; static uint8 *pWorld1; static CReference *pEmptyReferences; static CStoredDetailedAnimationState *pPedAnims; static uint8 *pPickups; static uint8 *pReferences; static uint8 BufferStatus[NUM_REPLAYBUFFERS]; static uint8 Buffers[NUM_REPLAYBUFFERS][REPLAYBUFFERSIZE]; static bool bPlayingBackFromFile; static bool bReplayEnabled; 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; static float CameraFocusX; static float CameraFocusY; static float CameraFocusZ; static bool bPlayerInRCBuggy; static float fDistanceLookAroundCam; static float fAlphaAngleLookAroundCam; static float fBetaAngleLookAroundCam; public: static void Init(void); static void DisableReplays(void); static void EnableReplays(void); static void Update(void); static void FinishPlayback(void); static void EmptyReplayBuffer(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); static bool IsPlayingBack() { return Mode == MODE_PLAYBACK; } 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 TriggerPlaybackLastCoupleOfSeconds(uint32, uint8, float, float, float, uint32); static bool FastForwardToTime(uint32); 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); /* Absolute nonsense, but how could this function end up being outside of class? */ friend void PlayReplayFromHD(void); };