summaryrefslogtreecommitdiff
path: root/src/control/Replay.h
blob: 56de52a3be6f2687f75c77b51f2fb909ea3cfc5d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
#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); 
};