2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 void CL_FinishTimeDemo (void);
26 ==============================================================================
30 When a demo is playing back, all outgoing network messages are skipped, and
31 incoming messages are read from the demo file.
33 Whenever cl.time gets past the last received message, another message is
34 read from the demo file.
35 ==============================================================================
42 Called to play the next demo in the demo loop
45 void CL_NextDemo (void)
49 if (cls.demonum == -1)
50 return; // don't play demos
52 if (!cls.demos[cls.demonum][0] || cls.demonum == MAX_DEMOS)
55 if (!cls.demos[cls.demonum][0])
57 Con_Printf ("No demos listed with startdemos\n");
63 sprintf (str,"playdemo %s\n", cls.demos[cls.demonum]);
64 Cbuf_InsertText (str);
72 Called when a demo file runs out, or the user starts a game
75 // LordHavoc: now called only by CL_Disconnect
76 void CL_StopPlayback (void)
78 if (!cls.demoplayback)
81 FS_Close (cls.demofile);
82 cls.demoplayback = false;
93 Dumps the current net message, prefixed by the length and view angles
96 void CL_WriteDemoMessage (void)
102 if (cls.demopaused) // LordHavoc: pausedemo
105 len = LittleLong (net_message.cursize);
106 FS_Write (cls.demofile, &len, 4);
107 for (i=0 ; i<3 ; i++)
109 f = LittleFloat (cl.viewangles[i]);
110 FS_Write (cls.demofile, &f, 4);
112 FS_Write (cls.demofile, net_message.data, net_message.cursize);
113 FS_Flush (cls.demofile);
120 Handles playback of demos
123 void CL_ReadDemoMessage(void)
128 if (!cls.demoplayback)
131 // LordHavoc: pausedemo
135 // decide if it is time to grab the next message
136 // always grab until fully connected
137 if (cls.signon == SIGNONS)
141 if (host_framecount == cls.td_lastframe)
143 // already read this frame's message
146 cls.td_lastframe = host_framecount;
147 // if this is the second frame, grab the real td_starttime
148 // so the bogus time on the first frame doesn't count
149 if (host_framecount == cls.td_startframe + 1)
150 cls.td_starttime = realtime;
152 else if (cl.time <= cl.mtime[0])
154 // don't need another message yet
159 // get the next message
160 FS_Read(cls.demofile, &net_message.cursize, 4);
161 net_message.cursize = LittleLong(net_message.cursize);
162 VectorCopy(cl.mviewangles[0], cl.mviewangles[1]);
163 for (i = 0;i < 3;i++)
165 r = FS_Read(cls.demofile, &f, 4);
166 cl.mviewangles[0][i] = LittleFloat(f);
169 if (net_message.cursize > NET_MAXMESSAGE)
170 Host_Error("Demo message > NET_MAXMESSAGE");
171 if (FS_Read(cls.demofile, net_message.data, net_message.cursize) == (size_t)net_message.cursize)
174 CL_ParseServerMessage();
185 stop recording a demo
188 void CL_Stop_f (void)
190 if (cmd_source != src_command)
193 if (!cls.demorecording)
195 Con_Printf ("Not recording a demo.\n");
199 // write a disconnect message to the demo file
200 SZ_Clear (&net_message);
201 MSG_WriteByte (&net_message, svc_disconnect);
202 CL_WriteDemoMessage ();
205 FS_Close (cls.demofile);
207 cls.demorecording = false;
208 Con_Printf ("Completed demo\n");
215 record <demoname> <map> [cd track]
218 void CL_Record_f (void)
221 char name[MAX_OSPATH];
223 if (cmd_source != src_command)
227 if (c != 2 && c != 3 && c != 4)
229 Con_Printf ("record <demoname> [<map> [cd track]]\n");
233 if (strstr(Cmd_Argv(1), ".."))
235 Con_Printf ("Relative pathnames are not allowed.\n");
239 if (c == 2 && cls.state == ca_connected)
241 Con_Printf("Can not record - already connected to server\nClient demo recording must be started before connecting\n");
245 // write the forced cd track number, or -1
248 track = atoi(Cmd_Argv(3));
249 Con_Printf ("Forcing CD track to %i\n", cls.forcetrack);
255 strncpy (name, Cmd_Argv(1), sizeof (name) - 1);
256 name[sizeof (name) - 1] = '\0';
257 FS_DefaultExtension (name, ".dem");
261 Cmd_ExecuteString ( va("map %s", Cmd_Argv(2)), src_command);
263 // open the demo file
264 Con_Printf ("recording to %s.\n", name);
265 cls.demofile = FS_Open (name, "wb", false);
268 Con_Printf ("ERROR: couldn't open.\n");
272 cls.forcetrack = track;
273 FS_Printf (cls.demofile, "%i\n", cls.forcetrack);
275 cls.demorecording = true;
286 void CL_PlayDemo_f (void)
290 qboolean neg = false;
292 if (cmd_source != src_command)
297 Con_Printf ("play <demoname> : plays a demo\n");
301 // disconnect from server
304 // open the demo file
305 strcpy (name, Cmd_Argv(1));
306 FS_DefaultExtension (name, ".dem");
308 Con_Printf ("Playing demo from %s.\n", name);
309 cls.demofile = FS_Open (name, "rb", false);
312 Con_Printf ("ERROR: couldn't open.\n");
313 cls.demonum = -1; // stop demo loop
317 SCR_BeginLoadingPlaque ();
319 cls.demoplayback = true;
320 cls.state = ca_connected;
323 while ((c = FS_Getc (cls.demofile)) != '\n')
327 cls.forcetrack = cls.forcetrack * 10 + (c - '0');
330 cls.forcetrack = -cls.forcetrack;
339 void CL_FinishTimeDemo (void)
342 double time; // LordHavoc: changed timedemo accuracy to double
344 cls.timedemo = false;
346 // the first frame didn't count
347 frames = (host_framecount - cls.td_startframe) - 1;
348 time = realtime - cls.td_starttime;
351 // LordHavoc: timedemo now prints out 7 digits of fraction
352 Con_Printf ("%i frames %5.7f seconds %5.7f fps\n", frames, time, frames/time);
362 void CL_TimeDemo_f (void)
364 if (cmd_source != src_command)
369 Con_Printf ("timedemo <demoname> : gets demo speeds\n");
375 // cls.td_starttime will be grabbed at the second frame of the demo, so
376 // all the loading time doesn't get counted
378 // instantly hide console and deactivate it
380 key_consoleactive = 0;
385 cls.td_startframe = host_framecount;
386 cls.td_lastframe = -1; // get a new message this frame