Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
298 serge 1
// Emacs style mode select   -*- C++ -*-
2
//-----------------------------------------------------------------------------
3
//
4
// $Id:$
5
//
6
// Copyright (C) 1993-1996 by id Software, Inc.
7
//
8
// This source is available for distribution and/or modification
9
// only under the terms of the DOOM Source Code License as
10
// published by id Software. All rights reserved.
11
//
12
// The source is distributed in the hope that it will be useful,
13
// but WITHOUT ANY WARRANTY; without even the implied warranty of
14
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
15
// for more details.
16
//
17
// $Log:$
18
//
19
// DESCRIPTION:  none
20
//
21
//-----------------------------------------------------------------------------
22
 
23
 
24
static const char
25
rcsid[] = "$Id: g_game.c,v 1.8 1997/02/03 22:45:09 b1 Exp $";
26
 
27
#include 
28
#include 
29
 
30
#include "doomdef.h"
31
#include "doomstat.h"
32
 
33
#include "z_zone.h"
34
#include "f_finale.h"
35
#include "m_argv.h"
36
#include "m_misc.h"
37
#include "m_menu.h"
38
#include "m_random.h"
39
#include "i_system.h"
40
 
41
#include "p_setup.h"
42
#include "p_saveg.h"
43
#include "p_tick.h"
44
 
45
#include "d_main.h"
46
 
47
#include "wi_stuff.h"
48
#include "hu_stuff.h"
49
#include "st_stuff.h"
50
#include "am_map.h"
51
 
52
// Needs access to LFB.
53
#include "v_video.h"
54
 
55
#include "w_wad.h"
56
 
57
#include "p_local.h"
58
 
59
#include "s_sound.h"
60
 
61
// Data.
62
#include "dstrings.h"
63
#include "sounds.h"
64
 
65
// SKY handling - still the wrong place.
66
#include "r_data.h"
67
#include "r_sky.h"
68
 
69
 
70
 
71
#include "g_game.h"
72
 
73
 
74
#define SAVEGAMESIZE	0x2c000
75
#define SAVESTRINGSIZE	24
76
 
77
 
78
 
79
boolean	G_CheckDemoStatus (void);
80
void	G_ReadDemoTiccmd (ticcmd_t* cmd);
81
void	G_WriteDemoTiccmd (ticcmd_t* cmd);
82
void	G_PlayerReborn (int player);
83
void	G_InitNew (skill_t skill, int episode, int map);
84
 
85
void	G_DoReborn (int playernum);
86
 
87
void	G_DoLoadLevel (void);
88
void	G_DoNewGame (void);
89
void	G_DoLoadGame (void);
90
void	G_DoPlayDemo (void);
91
void	G_DoCompleted (void);
92
void	G_DoVictory (void);
93
void	G_DoWorldDone (void);
94
void	G_DoSaveGame (void);
95
 
96
 
97
gameaction_t    gameaction;
98
gamestate_t     gamestate;
99
skill_t         gameskill;
100
boolean		respawnmonsters;
101
int             gameepisode;
102
int             gamemap;
103
 
104
boolean         paused;
105
boolean         sendpause;             	// send a pause event next tic
106
boolean         sendsave;             	// send a save event next tic
107
boolean         usergame;               // ok to save / end game
108
 
109
boolean         timingdemo;             // if true, exit with report on completion
110
boolean         nodrawers;              // for comparative timing purposes
111
boolean         noblit;                 // for comparative timing purposes
112
int             starttime;          	// for comparative timing purposes
113
 
114
boolean         viewactive;
115
 
116
boolean         deathmatch;           	// only if started as net death
117
boolean         netgame;                // only true if packets are broadcast
118
boolean         playeringame[MAXPLAYERS];
119
player_t        players[MAXPLAYERS];
120
 
121
int             consoleplayer;          // player taking events and displaying
122
int             displayplayer;          // view being displayed
123
int             gametic;
124
int             levelstarttic;          // gametic at level start
125
int             totalkills, totalitems, totalsecret;    // for intermission
126
 
127
char            demoname[32];
128
boolean         demorecording;
129
boolean         demoplayback;
130
boolean		netdemo;
131
byte*		demobuffer;
132
byte*		demo_p;
133
byte*		demoend;
134
boolean         singledemo;            	// quit after playing a demo from cmdline
135
 
136
boolean         precache = true;        // if true, load all graphics at start
137
 
138
wbstartstruct_t wminfo;               	// parms for world map / intermission
139
 
140
short		consistancy[MAXPLAYERS][BACKUPTICS];
141
 
142
byte*		savebuffer;
143
 
144
 
145
//
146
// controls (have defaults)
147
//
148
int             key_right;
149
int		key_left;
150
 
151
int		key_up;
152
int		key_down;
153
int             key_strafeleft;
154
int		key_straferight;
155
int             key_fire;
156
int		key_use;
157
int		key_strafe;
158
int		key_speed;
159
 
160
int             mousebfire;
161
int             mousebstrafe;
162
int             mousebforward;
163
 
164
int             joybfire;
165
int             joybstrafe;
166
int             joybuse;
167
int             joybspeed;
168
 
169
 
170
 
171
#define MAXPLMOVE		(forwardmove[1])
172
 
173
#define TURBOTHRESHOLD	0x32
174
 
175
fixed_t		forwardmove[2] = {0x19, 0x32};
176
fixed_t		sidemove[2] = {0x18, 0x28};
177
fixed_t		angleturn[3] = {640, 1280, 320};	// + slow turn
178
 
179
#define SLOWTURNTICS	6
180
 
181
#define NUMKEYS		256
182
 
183
boolean         gamekeydown[NUMKEYS];
184
int             turnheld;				// for accelerative turning
185
 
186
boolean		mousearray[4];
187
boolean*	mousebuttons = &mousearray[1];		// allow [-1]
188
 
189
// mouse values are used once
190
int             mousex;
191
int		mousey;
192
 
193
int             dclicktime;
194
int		dclickstate;
195
int		dclicks;
196
int             dclicktime2;
197
int		dclickstate2;
198
int		dclicks2;
199
 
200
// joystick values are repeated
201
int             joyxmove;
202
int		joyymove;
203
boolean         joyarray[5];
204
boolean*	joybuttons = &joyarray[1];		// allow [-1]
205
 
206
int		savegameslot;
207
char		savedescription[32];
208
 
209
 
210
#define	BODYQUESIZE	32
211
 
212
mobj_t*		bodyque[BODYQUESIZE];
213
int		bodyqueslot;
214
 
215
void*		statcopy;				// for statistics driver
216
 
217
 
218
 
219
int G_CmdChecksum (ticcmd_t* cmd)
220
{
221
    int		i;
222
    int		sum = 0;
223
 
224
    for (i=0 ; i< sizeof(*cmd)/4 - 1 ; i++)
225
	sum += ((int *)cmd)[i];
226
 
227
    return sum;
228
}
229
 
230
 
231
//
232
// G_BuildTiccmd
233
// Builds a ticcmd from all of the available inputs
234
// or reads it from the demo buffer.
235
// If recording a demo, write it out
236
//
237
void G_BuildTiccmd (ticcmd_t* cmd)
238
{
239
    int		i;
240
    boolean	strafe;
241
    boolean	bstrafe;
242
    int		speed;
243
    int		tspeed;
244
    int		forward;
245
    int		side;
246
 
247
    ticcmd_t*	base;
248
 
249
    base = I_BaseTiccmd ();		// empty, or external driver
250
    memcpy (cmd,base,sizeof(*cmd));
251
 
252
    cmd->consistancy =
253
	consistancy[consoleplayer][maketic%BACKUPTICS];
254
 
255
 
256
    strafe = gamekeydown[key_strafe] || mousebuttons[mousebstrafe]
257
	|| joybuttons[joybstrafe];
258
    speed = gamekeydown[key_speed] || joybuttons[joybspeed];
259
 
260
    forward = side = 0;
261
 
262
    // use two stage accelerative turning
263
    // on the keyboard and joystick
264
    if (joyxmove < 0
265
	|| joyxmove > 0
266
	|| gamekeydown[key_right]
267
	|| gamekeydown[key_left])
268
	turnheld += ticdup;
269
    else
270
	turnheld = 0;
271
 
272
    if (turnheld < SLOWTURNTICS)
273
	tspeed = 2;             // slow turn
274
    else
275
	tspeed = speed;
276
 
277
    // let movement keys cancel each other out
278
    if (strafe)
279
    {
280
	if (gamekeydown[key_right])
281
	{
282
	    // fprintf(stderr, "strafe right\n");
283
	    side += sidemove[speed];
284
	}
285
	if (gamekeydown[key_left])
286
	{
287
	    //	fprintf(stderr, "strafe left\n");
288
	    side -= sidemove[speed];
289
	}
290
	if (joyxmove > 0)
291
	    side += sidemove[speed];
292
	if (joyxmove < 0)
293
	    side -= sidemove[speed];
294
 
295
    }
296
    else
297
    {
298
	if (gamekeydown[key_right])
299
	    cmd->angleturn -= angleturn[tspeed];
300
	if (gamekeydown[key_left])
301
	    cmd->angleturn += angleturn[tspeed];
302
	if (joyxmove > 0)
303
	    cmd->angleturn -= angleturn[tspeed];
304
	if (joyxmove < 0)
305
	    cmd->angleturn += angleturn[tspeed];
306
    }
307
 
308
    if (gamekeydown[key_up])
309
    {
310
	// fprintf(stderr, "up\n");
311
	forward += forwardmove[speed];
312
    }
313
    if (gamekeydown[key_down])
314
    {
315
	// fprintf(stderr, "down\n");
316
	forward -= forwardmove[speed];
317
    }
318
    if (joyymove < 0)
319
	forward += forwardmove[speed];
320
    if (joyymove > 0)
321
	forward -= forwardmove[speed];
322
    if (gamekeydown[key_straferight])
323
	side += sidemove[speed];
324
    if (gamekeydown[key_strafeleft])
325
	side -= sidemove[speed];
326
 
327
    // buttons
328
    cmd->chatchar = HU_dequeueChatChar();
329
 
330
    if (gamekeydown[key_fire] || mousebuttons[mousebfire]
331
	|| joybuttons[joybfire])
332
	cmd->buttons |= BT_ATTACK;
333
 
334
    if (gamekeydown[key_use] || joybuttons[joybuse] )
335
    {
336
	cmd->buttons |= BT_USE;
337
	// clear double clicks if hit use button
338
	dclicks = 0;
339
    }
340
 
341
    // chainsaw overrides
342
    for (i=0 ; i
343
	if (gamekeydown['1'+i])
344
	{
345
	    cmd->buttons |= BT_CHANGE;
346
	    cmd->buttons |= i<
347
	    break;
348
	}
349
 
350
    // mouse
351
    if (mousebuttons[mousebforward])
352
	forward += forwardmove[speed];
353
 
354
    // forward double click
355
    if (mousebuttons[mousebforward] != dclickstate && dclicktime > 1 )
356
    {
357
	dclickstate = mousebuttons[mousebforward];
358
	if (dclickstate)
359
	    dclicks++;
360
	if (dclicks == 2)
361
	{
362
	    cmd->buttons |= BT_USE;
363
	    dclicks = 0;
364
	}
365
	else
366
	    dclicktime = 0;
367
    }
368
    else
369
    {
370
	dclicktime += ticdup;
371
	if (dclicktime > 20)
372
	{
373
	    dclicks = 0;
374
	    dclickstate = 0;
375
	}
376
    }
377
 
378
    // strafe double click
379
    bstrafe =
380
	mousebuttons[mousebstrafe]
381
	|| joybuttons[joybstrafe];
382
    if (bstrafe != dclickstate2 && dclicktime2 > 1 )
383
    {
384
	dclickstate2 = bstrafe;
385
	if (dclickstate2)
386
	    dclicks2++;
387
	if (dclicks2 == 2)
388
	{
389
	    cmd->buttons |= BT_USE;
390
	    dclicks2 = 0;
391
	}
392
	else
393
	    dclicktime2 = 0;
394
    }
395
    else
396
    {
397
	dclicktime2 += ticdup;
398
	if (dclicktime2 > 20)
399
	{
400
	    dclicks2 = 0;
401
	    dclickstate2 = 0;
402
	}
403
    }
404
 
405
    forward += mousey;
406
    if (strafe)
407
	side += mousex*2;
408
    else
409
	cmd->angleturn -= mousex*0x8;
410
 
411
    mousex = mousey = 0;
412
 
413
    if (forward > MAXPLMOVE)
414
	forward = MAXPLMOVE;
415
    else if (forward < -MAXPLMOVE)
416
	forward = -MAXPLMOVE;
417
    if (side > MAXPLMOVE)
418
	side = MAXPLMOVE;
419
    else if (side < -MAXPLMOVE)
420
	side = -MAXPLMOVE;
421
 
422
    cmd->forwardmove += forward;
423
    cmd->sidemove += side;
424
 
425
    // special buttons
426
    if (sendpause)
427
    {
428
	sendpause = false;
429
	cmd->buttons = BT_SPECIAL | BTS_PAUSE;
430
    }
431
 
432
    if (sendsave)
433
    {
434
	sendsave = false;
435
	cmd->buttons = BT_SPECIAL | BTS_SAVEGAME | (savegameslot<
436
    }
437
}
438
 
439
 
440
//
441
// G_DoLoadLevel
442
//
443
extern  gamestate_t     wipegamestate;
444
 
445
void G_DoLoadLevel (void)
446
{
447
    int             i;
448
 
449
    // Set the sky map.
450
    // First thing, we have a dummy sky texture name,
451
    //  a flat. The data is in the WAD only because
452
    //  we look for an actual index, instead of simply
453
    //  setting one.
454
    skyflatnum = R_FlatNumForName ( SKYFLATNAME );
455
 
456
    // DOOM determines the sky texture to be used
457
    // depending on the current episode, and the game version.
458
    if ( (gamemode == commercial)
459
	 || ( gamemode == pack_tnt )
460
	 || ( gamemode == pack_plut ) )
461
    {
462
	skytexture = R_TextureNumForName ("SKY3");
463
	if (gamemap < 12)
464
	    skytexture = R_TextureNumForName ("SKY1");
465
	else
466
	    if (gamemap < 21)
467
		skytexture = R_TextureNumForName ("SKY2");
468
    }
469
 
470
    levelstarttic = gametic;        // for time calculation
471
 
472
    if (wipegamestate == GS_LEVEL)
473
	wipegamestate = -1;             // force a wipe
474
 
475
    gamestate = GS_LEVEL;
476
 
477
    for (i=0 ; i
478
    {
479
	if (playeringame[i] && players[i].playerstate == PST_DEAD)
480
	    players[i].playerstate = PST_REBORN;
481
	memset (players[i].frags,0,sizeof(players[i].frags));
482
    }
483
 
484
    P_SetupLevel (gameepisode, gamemap, 0, gameskill);
485
    displayplayer = consoleplayer;		// view the guy you are playing
486
    starttime = I_GetTime ();
487
    gameaction = ga_nothing;
488
    Z_CheckHeap ();
489
 
490
    // clear cmd building stuff
491
    memset (gamekeydown, 0, sizeof(gamekeydown));
492
    joyxmove = joyymove = 0;
493
    mousex = mousey = 0;
494
    sendpause = sendsave = paused = false;
495
    memset (mousebuttons, 0, sizeof(mousebuttons));
496
    memset (joybuttons, 0, sizeof(joybuttons));
497
}
498
 
499
 
500
//
501
// G_Responder
502
// Get info needed to make ticcmd_ts for the players.
503
//
504
boolean G_Responder (event_t* ev)
505
{
506
    // allow spy mode changes even during the demo
507
    if (gamestate == GS_LEVEL && ev->type == ev_keydown
508
	&& ev->data1 == KEY_F12 && (singledemo || !deathmatch) )
509
    {
510
	// spy mode
511
	do
512
	{
513
	    displayplayer++;
514
	    if (displayplayer == MAXPLAYERS)
515
		displayplayer = 0;
516
	} while (!playeringame[displayplayer] && displayplayer != consoleplayer);
517
	return true;
518
    }
519
 
520
    // any other key pops up menu if in demos
521
    if (gameaction == ga_nothing && !singledemo &&
522
	(demoplayback || gamestate == GS_DEMOSCREEN)
523
	)
524
    {
525
	if (ev->type == ev_keydown ||
526
	    (ev->type == ev_mouse && ev->data1) ||
527
	    (ev->type == ev_joystick && ev->data1) )
528
	{
529
	    M_StartControlPanel ();
530
	    return true;
531
	}
532
	return false;
533
    }
534
 
535
    if (gamestate == GS_LEVEL)
536
    {
537
#if 0
538
	if (devparm && ev->type == ev_keydown && ev->data1 == ';')
539
	{
540
	    G_DeathMatchSpawnPlayer (0);
541
	    return true;
542
	}
543
#endif
544
	if (HU_Responder (ev))
545
	    return true;	// chat ate the event
546
	if (ST_Responder (ev))
547
	    return true;	// status window ate it
548
	if (AM_Responder (ev))
549
	    return true;	// automap ate it
550
    }
551
 
552
    if (gamestate == GS_FINALE)
553
    {
554
	if (F_Responder (ev))
555
	    return true;	// finale ate the event
556
    }
557
 
558
    switch (ev->type)
559
    {
560
      case ev_keydown:
561
	if (ev->data1 == KEY_PAUSE)
562
	{
563
	    sendpause = true;
564
	    return true;
565
	}
566
	if (ev->data1 
567
	    gamekeydown[ev->data1] = true;
568
	return true;    // eat key down events
569
 
570
      case ev_keyup:
571
	if (ev->data1 
572
	    gamekeydown[ev->data1] = false;
573
	return false;   // always let key up events filter down
574
 
575
      case ev_mouse:
576
	mousebuttons[0] = ev->data1 & 1;
577
	mousebuttons[1] = ev->data1 & 2;
578
	mousebuttons[2] = ev->data1 & 4;
579
	mousex = ev->data2*(mouseSensitivity+5)/10;
580
	mousey = ev->data3*(mouseSensitivity+5)/10;
581
	return true;    // eat events
582
 
583
      case ev_joystick:
584
	joybuttons[0] = ev->data1 & 1;
585
	joybuttons[1] = ev->data1 & 2;
586
	joybuttons[2] = ev->data1 & 4;
587
	joybuttons[3] = ev->data1 & 8;
588
	joyxmove = ev->data2;
589
	joyymove = ev->data3;
590
	return true;    // eat events
591
 
592
      default:
593
	break;
594
    }
595
 
596
    return false;
597
}
598
 
599
 
600
 
601
//
602
// G_Ticker
603
// Make ticcmd_ts for the players.
604
//
605
void G_Ticker (void)
606
{
607
    int		i;
608
    int		buf;
609
    ticcmd_t*	cmd;
610
 
611
    // do player reborns if needed
612
    for (i=0 ; i
613
	if (playeringame[i] && players[i].playerstate == PST_REBORN)
614
	    G_DoReborn (i);
615
 
616
    // do things to change the game state
617
    while (gameaction != ga_nothing)
618
    {
619
	switch (gameaction)
620
	{
621
	  case ga_loadlevel:
622
	    G_DoLoadLevel ();
623
	    break;
624
	  case ga_newgame:
625
	    G_DoNewGame ();
626
	    break;
627
	  case ga_loadgame:
628
	    G_DoLoadGame ();
629
	    break;
630
	  case ga_savegame:
631
	    G_DoSaveGame ();
632
	    break;
633
	  case ga_playdemo:
634
	    G_DoPlayDemo ();
635
	    break;
636
	  case ga_completed:
637
	    G_DoCompleted ();
638
	    break;
639
	  case ga_victory:
640
	    F_StartFinale ();
641
	    break;
642
	  case ga_worlddone:
643
	    G_DoWorldDone ();
644
	    break;
645
	  case ga_screenshot:
646
	    M_ScreenShot ();
647
	    gameaction = ga_nothing;
648
	    break;
649
	  case ga_nothing:
650
	    break;
651
	}
652
    }
653
 
654
    // get commands, check consistancy,
655
    // and build new consistancy check
656
    buf = (gametic/ticdup)%BACKUPTICS;
657
 
658
    for (i=0 ; i
659
    {
660
	if (playeringame[i])
661
	{
662
	    cmd = &players[i].cmd;
663
 
664
	    memcpy (cmd, &netcmds[i][buf], sizeof(ticcmd_t));
665
 
666
	    if (demoplayback)
667
		G_ReadDemoTiccmd (cmd);
668
	    if (demorecording)
669
		G_WriteDemoTiccmd (cmd);
670
 
671
	    // check for turbo cheats
672
	    if (cmd->forwardmove > TURBOTHRESHOLD
673
		&& !(gametic&31) && ((gametic>>5)&3) == i )
674
	    {
675
		static char turbomessage[80];
676
		extern char *player_names[4];
677
		sprintf (turbomessage, "%s is turbo!",player_names[i]);
678
		players[consoleplayer].message = turbomessage;
679
	    }
680
 
681
	    if (netgame && !netdemo && !(gametic%ticdup) )
682
	    {
683
		if (gametic > BACKUPTICS
684
		    && consistancy[i][buf] != cmd->consistancy)
685
		{
686
		    I_Error ("consistency failure (%i should be %i)",
687
			     cmd->consistancy, consistancy[i][buf]);
688
		}
689
		if (players[i].mo)
690
		    consistancy[i][buf] = players[i].mo->x;
691
		else
692
		    consistancy[i][buf] = rndindex;
693
	    }
694
	}
695
    }
696
 
697
    // check for special buttons
698
    for (i=0 ; i
699
    {
700
	if (playeringame[i])
701
	{
702
	    if (players[i].cmd.buttons & BT_SPECIAL)
703
	    {
704
		switch (players[i].cmd.buttons & BT_SPECIALMASK)
705
		{
706
		  case BTS_PAUSE:
707
		    paused ^= 1;
708
		    if (paused)
709
			S_PauseSound ();
710
		    else
711
			S_ResumeSound ();
712
		    break;
713
 
714
		  case BTS_SAVEGAME:
715
		    if (!savedescription[0])
716
			strcpy (savedescription, "NET GAME");
717
		    savegameslot =
718
			(players[i].cmd.buttons & BTS_SAVEMASK)>>BTS_SAVESHIFT;
719
		    gameaction = ga_savegame;
720
		    break;
721
		}
722
	    }
723
	}
724
    }
725
 
726
    // do main actions
727
    switch (gamestate)
728
    {
729
      case GS_LEVEL:
730
	P_Ticker ();
731
	ST_Ticker ();
732
	AM_Ticker ();
733
	HU_Ticker ();
734
	break;
735
 
736
      case GS_INTERMISSION:
737
	WI_Ticker ();
738
	break;
739
 
740
      case GS_FINALE:
741
	F_Ticker ();
742
	break;
743
 
744
      case GS_DEMOSCREEN:
745
	D_PageTicker ();
746
	break;
747
    }
748
}
749
 
750
 
751
//
752
// PLAYER STRUCTURE FUNCTIONS
753
// also see P_SpawnPlayer in P_Things
754
//
755
 
756
//
757
// G_InitPlayer
758
// Called at the start.
759
// Called by the game initialization functions.
760
//
761
void G_InitPlayer (int player)
762
{
763
    player_t*	p;
764
 
765
    // set up the saved info
766
    p = &players[player];
767
 
768
    // clear everything else to defaults
769
    G_PlayerReborn (player);
770
 
771
}
772
 
773
 
774
 
775
//
776
// G_PlayerFinishLevel
777
// Can when a player completes a level.
778
//
779
void G_PlayerFinishLevel (int player)
780
{
781
    player_t*	p;
782
 
783
    p = &players[player];
784
 
785
    memset (p->powers, 0, sizeof (p->powers));
786
    memset (p->cards, 0, sizeof (p->cards));
787
    p->mo->flags &= ~MF_SHADOW;		// cancel invisibility
788
    p->extralight = 0;			// cancel gun flashes
789
    p->fixedcolormap = 0;		// cancel ir gogles
790
    p->damagecount = 0;			// no palette changes
791
    p->bonuscount = 0;
792
}
793
 
794
 
795
//
796
// G_PlayerReborn
797
// Called after a player dies
798
// almost everything is cleared and initialized
799
//
800
void G_PlayerReborn (int player)
801
{
802
    player_t*	p;
803
    int		i;
804
    int		frags[MAXPLAYERS];
805
    int		killcount;
806
    int		itemcount;
807
    int		secretcount;
808
 
809
    memcpy (frags,players[player].frags,sizeof(frags));
810
    killcount = players[player].killcount;
811
    itemcount = players[player].itemcount;
812
    secretcount = players[player].secretcount;
813
 
814
    p = &players[player];
815
    memset (p, 0, sizeof(*p));
816
 
817
    memcpy (players[player].frags, frags, sizeof(players[player].frags));
818
    players[player].killcount = killcount;
819
    players[player].itemcount = itemcount;
820
    players[player].secretcount = secretcount;
821
 
822
    p->usedown = p->attackdown = true;	// don't do anything immediately
823
    p->playerstate = PST_LIVE;
824
    p->health = MAXHEALTH;
825
    p->readyweapon = p->pendingweapon = wp_pistol;
826
    p->weaponowned[wp_fist] = true;
827
    p->weaponowned[wp_pistol] = true;
828
    p->ammo[am_clip] = 50;
829
 
830
    for (i=0 ; i
831
	p->maxammo[i] = maxammo[i];
832
 
833
}
834
 
835
//
836
// G_CheckSpot
837
// Returns false if the player cannot be respawned
838
// at the given mapthing_t spot
839
// because something is occupying it
840
//
841
void P_SpawnPlayer (mapthing_t* mthing);
842
 
843
boolean
844
G_CheckSpot
845
( int		playernum,
846
  mapthing_t*	mthing )
847
{
848
    fixed_t		x;
849
    fixed_t		y;
850
    subsector_t*	ss;
851
    unsigned		an;
852
    mobj_t*		mo;
853
    int			i;
854
 
855
    if (!players[playernum].mo)
856
    {
857
	// first spawn of level, before corpses
858
	for (i=0 ; i
859
	    if (players[i].mo->x == mthing->x << FRACBITS
860
		&& players[i].mo->y == mthing->y << FRACBITS)
861
		return false;
862
	return true;
863
    }
864
 
865
    x = mthing->x << FRACBITS;
866
    y = mthing->y << FRACBITS;
867
 
868
    if (!P_CheckPosition (players[playernum].mo, x, y) )
869
	return false;
870
 
871
    // flush an old corpse if needed
872
    if (bodyqueslot >= BODYQUESIZE)
873
	P_RemoveMobj (bodyque[bodyqueslot%BODYQUESIZE]);
874
    bodyque[bodyqueslot%BODYQUESIZE] = players[playernum].mo;
875
    bodyqueslot++;
876
 
877
    // spawn a teleport fog
878
    ss = R_PointInSubsector (x,y);
879
    an = ( ANG45 * (mthing->angle/45) ) >> ANGLETOFINESHIFT;
880
 
881
    mo = P_SpawnMobj (x+20*finecosine[an], y+20*finesine[an]
882
		      , ss->sector->floorheight
883
		      , MT_TFOG);
884
 
885
    if (players[consoleplayer].viewz != 1)
886
	S_StartSound (mo, sfx_telept);	// don't start sound on first frame
887
 
888
    return true;
889
}
890
 
891
 
892
//
893
// G_DeathMatchSpawnPlayer
894
// Spawns a player at one of the random death match spots
895
// called at level load and each death
896
//
897
void G_DeathMatchSpawnPlayer (int playernum)
898
{
899
    int             i,j;
900
    int				selections;
901
 
902
    selections = deathmatch_p - deathmatchstarts;
903
    if (selections < 4)
904
	I_Error ("Only %i deathmatch spots, 4 required", selections);
905
 
906
    for (j=0 ; j<20 ; j++)
907
    {
908
	i = P_Random() % selections;
909
	if (G_CheckSpot (playernum, &deathmatchstarts[i]) )
910
	{
911
	    deathmatchstarts[i].type = playernum+1;
912
	    P_SpawnPlayer (&deathmatchstarts[i]);
913
	    return;
914
	}
915
    }
916
 
917
    // no good spot, so the player will probably get stuck
918
    P_SpawnPlayer (&playerstarts[playernum]);
919
}
920
 
921
//
922
// G_DoReborn
923
//
924
void G_DoReborn (int playernum)
925
{
926
    int                             i;
927
 
928
    if (!netgame)
929
    {
930
	// reload the level from scratch
931
	gameaction = ga_loadlevel;
932
    }
933
    else
934
    {
935
	// respawn at the start
936
 
937
	// first dissasociate the corpse
938
	players[playernum].mo->player = NULL;
939
 
940
	// spawn at random spot if in death match
941
	if (deathmatch)
942
	{
943
	    G_DeathMatchSpawnPlayer (playernum);
944
	    return;
945
	}
946
 
947
	if (G_CheckSpot (playernum, &playerstarts[playernum]) )
948
	{
949
	    P_SpawnPlayer (&playerstarts[playernum]);
950
	    return;
951
	}
952
 
953
	// try to spawn at one of the other players spots
954
	for (i=0 ; i
955
	{
956
	    if (G_CheckSpot (playernum, &playerstarts[i]) )
957
	    {
958
		playerstarts[i].type = playernum+1;	// fake as other player
959
		P_SpawnPlayer (&playerstarts[i]);
960
		playerstarts[i].type = i+1;		// restore
961
		return;
962
	    }
963
	    // he's going to be inside something.  Too bad.
964
	}
965
	P_SpawnPlayer (&playerstarts[playernum]);
966
    }
967
}
968
 
969
 
970
void G_ScreenShot (void)
971
{
972
    gameaction = ga_screenshot;
973
}
974
 
975
 
976
 
977
// DOOM Par Times
978
int pars[4][10] =
979
{
980
    {0},
981
    {0,30,75,120,90,165,180,180,30,165},
982
    {0,90,90,90,120,90,360,240,30,170},
983
    {0,90,45,90,150,90,90,165,30,135}
984
};
985
 
986
// DOOM II Par Times
987
int cpars[32] =
988
{
989
    30,90,120,120,90,150,120,120,270,90,	//  1-10
990
    210,150,150,150,210,150,420,150,210,150,	// 11-20
991
    240,150,180,150,150,300,330,420,300,180,	// 21-30
992
    120,30					// 31-32
993
};
994
 
995
 
996
//
997
// G_DoCompleted
998
//
999
boolean		secretexit;
1000
extern char*	pagename;
1001
 
1002
void G_ExitLevel (void)
1003
{
1004
    secretexit = false;
1005
    gameaction = ga_completed;
1006
}
1007
 
1008
// Here's for the german edition.
1009
void G_SecretExitLevel (void)
1010
{
1011
    // IF NO WOLF3D LEVELS, NO SECRET EXIT!
1012
    if ( (gamemode == commercial)
1013
      && (W_CheckNumForName("map31")<0))
1014
	secretexit = false;
1015
    else
1016
	secretexit = true;
1017
    gameaction = ga_completed;
1018
}
1019
 
1020
void G_DoCompleted (void)
1021
{
1022
    int             i;
1023
 
1024
    gameaction = ga_nothing;
1025
 
1026
    for (i=0 ; i
1027
	if (playeringame[i])
1028
	    G_PlayerFinishLevel (i);        // take away cards and stuff
1029
 
1030
    if (automapactive)
1031
	AM_Stop ();
1032
 
1033
    if ( gamemode != commercial)
1034
	switch(gamemap)
1035
	{
1036
	  case 8:
1037
	    gameaction = ga_victory;
1038
	    return;
1039
	  case 9:
1040
	    for (i=0 ; i
1041
		players[i].didsecret = true;
1042
	    break;
1043
	}
1044
 
1045
//#if 0  Hmmm - why?
1046
    if ( (gamemap == 8)
1047
	 && (gamemode != commercial) )
1048
    {
1049
	// victory
1050
	gameaction = ga_victory;
1051
	return;
1052
    }
1053
 
1054
    if ( (gamemap == 9)
1055
	 && (gamemode != commercial) )
1056
    {
1057
	// exit secret level
1058
	for (i=0 ; i
1059
	    players[i].didsecret = true;
1060
    }
1061
//#endif
1062
 
1063
 
1064
    wminfo.didsecret = players[consoleplayer].didsecret;
1065
    wminfo.epsd = gameepisode -1;
1066
    wminfo.last = gamemap -1;
1067
 
1068
    // wminfo.next is 0 biased, unlike gamemap
1069
    if ( gamemode == commercial)
1070
    {
1071
	if (secretexit)
1072
	    switch(gamemap)
1073
	    {
1074
	      case 15: wminfo.next = 30; break;
1075
	      case 31: wminfo.next = 31; break;
1076
	    }
1077
	else
1078
	    switch(gamemap)
1079
	    {
1080
	      case 31:
1081
	      case 32: wminfo.next = 15; break;
1082
	      default: wminfo.next = gamemap;
1083
	    }
1084
    }
1085
    else
1086
    {
1087
	if (secretexit)
1088
	    wminfo.next = 8; 	// go to secret level
1089
	else if (gamemap == 9)
1090
	{
1091
	    // returning from secret level
1092
	    switch (gameepisode)
1093
	    {
1094
	      case 1:
1095
		wminfo.next = 3;
1096
		break;
1097
	      case 2:
1098
		wminfo.next = 5;
1099
		break;
1100
	      case 3:
1101
		wminfo.next = 6;
1102
		break;
1103
	      case 4:
1104
		wminfo.next = 2;
1105
		break;
1106
	    }
1107
	}
1108
	else
1109
	    wminfo.next = gamemap;          // go to next level
1110
    }
1111
 
1112
    wminfo.maxkills = totalkills;
1113
    wminfo.maxitems = totalitems;
1114
    wminfo.maxsecret = totalsecret;
1115
    wminfo.maxfrags = 0;
1116
    if ( gamemode == commercial )
1117
	wminfo.partime = 35*cpars[gamemap-1];
1118
    else
1119
	wminfo.partime = 35*pars[gameepisode][gamemap];
1120
    wminfo.pnum = consoleplayer;
1121
 
1122
    for (i=0 ; i
1123
    {
1124
	wminfo.plyr[i].in = playeringame[i];
1125
	wminfo.plyr[i].skills = players[i].killcount;
1126
	wminfo.plyr[i].sitems = players[i].itemcount;
1127
	wminfo.plyr[i].ssecret = players[i].secretcount;
1128
	wminfo.plyr[i].stime = leveltime;
1129
	memcpy (wminfo.plyr[i].frags, players[i].frags
1130
		, sizeof(wminfo.plyr[i].frags));
1131
    }
1132
 
1133
    gamestate = GS_INTERMISSION;
1134
    viewactive = false;
1135
    automapactive = false;
1136
 
1137
    if (statcopy)
1138
	memcpy (statcopy, &wminfo, sizeof(wminfo));
1139
 
1140
    WI_Start (&wminfo);
1141
}
1142
 
1143
 
1144
//
1145
// G_WorldDone
1146
//
1147
void G_WorldDone (void)
1148
{
1149
    gameaction = ga_worlddone;
1150
 
1151
    if (secretexit)
1152
	players[consoleplayer].didsecret = true;
1153
 
1154
    if ( gamemode == commercial )
1155
    {
1156
	switch (gamemap)
1157
	{
1158
	  case 15:
1159
	  case 31:
1160
	    if (!secretexit)
1161
		break;
1162
	  case 6:
1163
	  case 11:
1164
	  case 20:
1165
	  case 30:
1166
	    F_StartFinale ();
1167
	    break;
1168
	}
1169
    }
1170
}
1171
 
1172
void G_DoWorldDone (void)
1173
{
1174
    gamestate = GS_LEVEL;
1175
    gamemap = wminfo.next+1;
1176
    G_DoLoadLevel ();
1177
    gameaction = ga_nothing;
1178
    viewactive = true;
1179
}
1180
 
1181
 
1182
 
1183
//
1184
// G_InitFromSavegame
1185
// Can be called by the startup code or the menu task.
1186
//
1187
extern boolean setsizeneeded;
1188
void R_ExecuteSetViewSize (void);
1189
 
1190
char	savename[256];
1191
 
1192
void G_LoadGame (char* name)
1193
{
1194
    strcpy (savename, name);
1195
    gameaction = ga_loadgame;
1196
}
1197
 
1198
#define VERSIONSIZE		16
1199
 
1200
 
1201
void G_DoLoadGame (void)
1202
{
1203
    int		length;
1204
    int		i;
1205
    int		a,b,c;
1206
    char	vcheck[VERSIONSIZE];
1207
 
1208
    gameaction = ga_nothing;
1209
 
1210
    length = M_ReadFile (savename, &savebuffer);
1211
    save_p = savebuffer + SAVESTRINGSIZE;
1212
 
1213
    // skip the description field
1214
    memset (vcheck,0,sizeof(vcheck));
1215
    sprintf (vcheck,"version %i",VERSION_NUM);
1216
    if (strcmp ((char *)save_p, vcheck))
1217
	return;				// bad version
1218
    save_p += VERSIONSIZE;
1219
 
1220
    gameskill = *save_p++;
1221
    gameepisode = *save_p++;
1222
    gamemap = *save_p++;
1223
    for (i=0 ; i
1224
	playeringame[i] = *save_p++;
1225
 
1226
    // load a base level
1227
    G_InitNew (gameskill, gameepisode, gamemap);
1228
 
1229
    // get the times
1230
    a = *save_p++;
1231
    b = *save_p++;
1232
    c = *save_p++;
1233
    leveltime = (a<<16) + (b<<8) + c;
1234
 
1235
    // dearchive all the modifications
1236
    P_UnArchivePlayers ();
1237
    P_UnArchiveWorld ();
1238
    P_UnArchiveThinkers ();
1239
    P_UnArchiveSpecials ();
1240
 
1241
    if (*save_p != 0x1d)
1242
	I_Error ("Bad savegame");
1243
 
1244
    // done
1245
    Z_Free (savebuffer);
1246
 
1247
    if (setsizeneeded)
1248
	R_ExecuteSetViewSize ();
1249
 
1250
    // draw the pattern into the back screen
1251
    R_FillBackScreen ();
1252
}
1253
 
1254
 
1255
//
1256
// G_SaveGame
1257
// Called by the menu task.
1258
// Description is a 24 byte text string
1259
//
1260
void
1261
G_SaveGame
1262
( int	slot,
1263
  char*	description )
1264
{
1265
    savegameslot = slot;
1266
    strcpy (savedescription, description);
1267
    sendsave = true;
1268
}
1269
 
1270
void G_DoSaveGame (void)
1271
{
1272
    char	name[100];
1273
    char	name2[VERSIONSIZE];
1274
    char*	description;
1275
    int		length;
1276
    int		i;
1277
 
1278
    sprintf (name,"%d.dsg",savegameslot);
1279
    description = savedescription;
1280
 
1281
    save_p = savebuffer = screens[1]+0x4000;
1282
 
1283
    memcpy (save_p, description, SAVESTRINGSIZE);
1284
    save_p += SAVESTRINGSIZE;
1285
    memset (name2,0,sizeof(name2));
1286
    sprintf (name2,"version %i",VERSION_NUM);
1287
    memcpy (save_p, name2, VERSIONSIZE);
1288
    save_p += VERSIONSIZE;
1289
 
1290
    *save_p++ = gameskill;
1291
    *save_p++ = gameepisode;
1292
    *save_p++ = gamemap;
1293
    for (i=0 ; i
1294
	*save_p++ = playeringame[i];
1295
    *save_p++ = leveltime>>16;
1296
    *save_p++ = leveltime>>8;
1297
    *save_p++ = leveltime;
1298
 
1299
    P_ArchivePlayers ();
1300
    P_ArchiveWorld ();
1301
    P_ArchiveThinkers ();
1302
    P_ArchiveSpecials ();
1303
 
1304
    *save_p++ = 0x1d;		// consistancy marker
1305
 
1306
    length = save_p - savebuffer;
1307
    if (length > SAVEGAMESIZE)
1308
	I_Error ("Savegame buffer overrun");
1309
    M_WriteFile (name, savebuffer, length);
1310
    gameaction = ga_nothing;
1311
    savedescription[0] = 0;
1312
 
1313
    players[consoleplayer].message = GGSAVED;
1314
 
1315
    // draw the pattern into the back screen
1316
    R_FillBackScreen ();
1317
}
1318
 
1319
 
1320
//
1321
// G_InitNew
1322
// Can be called by the startup code or the menu task,
1323
// consoleplayer, displayplayer, playeringame[] should be set.
1324
//
1325
skill_t	d_skill;
1326
int     d_episode;
1327
int     d_map;
1328
 
1329
void
1330
G_DeferedInitNew
1331
( skill_t	skill,
1332
  int		episode,
1333
  int		map)
1334
{
1335
    d_skill = skill;
1336
    d_episode = episode;
1337
    d_map = map;
1338
    gameaction = ga_newgame;
1339
}
1340
 
1341
 
1342
void G_DoNewGame (void)
1343
{
1344
    demoplayback = false;
1345
    netdemo = false;
1346
    netgame = false;
1347
    deathmatch = false;
1348
    playeringame[1] = playeringame[2] = playeringame[3] = 0;
1349
    respawnparm = false;
1350
    fastparm = false;
1351
    nomonsters = false;
1352
    consoleplayer = 0;
1353
    G_InitNew (d_skill, d_episode, d_map);
1354
    gameaction = ga_nothing;
1355
}
1356
 
1357
// The sky texture to be used instead of the F_SKY1 dummy.
1358
extern  int	skytexture;
1359
 
1360
 
1361
void
1362
G_InitNew
1363
( skill_t	skill,
1364
  int		episode,
1365
  int		map )
1366
{
1367
    int             i;
1368
 
1369
    if (paused)
1370
    {
1371
	paused = false;
1372
	S_ResumeSound ();
1373
    }
1374
 
1375
 
1376
    if (skill > sk_nightmare)
1377
	skill = sk_nightmare;
1378
 
1379
 
1380
    // This was quite messy with SPECIAL and commented parts.
1381
    // Supposedly hacks to make the latest edition work.
1382
    // It might not work properly.
1383
    if (episode < 1)
1384
      episode = 1;
1385
 
1386
    if ( gamemode == retail )
1387
    {
1388
      if (episode > 4)
1389
	episode = 4;
1390
    }
1391
    else if ( gamemode == shareware )
1392
    {
1393
      if (episode > 1)
1394
	   episode = 1;	// only start episode 1 on shareware
1395
    }
1396
    else
1397
    {
1398
      if (episode > 3)
1399
	episode = 3;
1400
    }
1401
 
1402
 
1403
 
1404
    if (map < 1)
1405
	map = 1;
1406
 
1407
    if ( (map > 9)
1408
	 && ( gamemode != commercial) )
1409
      map = 9;
1410
 
1411
    M_ClearRandom ();
1412
 
1413
    if (skill == sk_nightmare || respawnparm )
1414
	respawnmonsters = true;
1415
    else
1416
	respawnmonsters = false;
1417
 
1418
    if (fastparm || (skill == sk_nightmare && gameskill != sk_nightmare) )
1419
    {
1420
	for (i=S_SARG_RUN1 ; i<=S_SARG_PAIN2 ; i++)
1421
	    states[i].tics >>= 1;
1422
	mobjinfo[MT_BRUISERSHOT].speed = 20*FRACUNIT;
1423
	mobjinfo[MT_HEADSHOT].speed = 20*FRACUNIT;
1424
	mobjinfo[MT_TROOPSHOT].speed = 20*FRACUNIT;
1425
    }
1426
    else if (skill != sk_nightmare && gameskill == sk_nightmare)
1427
    {
1428
	for (i=S_SARG_RUN1 ; i<=S_SARG_PAIN2 ; i++)
1429
	    states[i].tics <<= 1;
1430
	mobjinfo[MT_BRUISERSHOT].speed = 15*FRACUNIT;
1431
	mobjinfo[MT_HEADSHOT].speed = 10*FRACUNIT;
1432
	mobjinfo[MT_TROOPSHOT].speed = 10*FRACUNIT;
1433
    }
1434
 
1435
 
1436
    // force players to be initialized upon first level load
1437
    for (i=0 ; i
1438
	players[i].playerstate = PST_REBORN;
1439
 
1440
    usergame = true;                // will be set false if a demo
1441
    paused = false;
1442
    demoplayback = false;
1443
    automapactive = false;
1444
    viewactive = true;
1445
    gameepisode = episode;
1446
    gamemap = map;
1447
    gameskill = skill;
1448
 
1449
    viewactive = true;
1450
 
1451
    // set the sky map for the episode
1452
    if ( gamemode == commercial)
1453
    {
1454
	skytexture = R_TextureNumForName ("SKY3");
1455
	if (gamemap < 12)
1456
	    skytexture = R_TextureNumForName ("SKY1");
1457
	else
1458
	    if (gamemap < 21)
1459
		skytexture = R_TextureNumForName ("SKY2");
1460
    }
1461
    else
1462
	switch (episode)
1463
	{
1464
	  case 1:
1465
	    skytexture = R_TextureNumForName ("SKY1");
1466
	    break;
1467
	  case 2:
1468
	    skytexture = R_TextureNumForName ("SKY2");
1469
	    break;
1470
	  case 3:
1471
	    skytexture = R_TextureNumForName ("SKY3");
1472
	    break;
1473
	  case 4:	// Special Edition sky
1474
	    skytexture = R_TextureNumForName ("SKY4");
1475
	    break;
1476
	}
1477
 
1478
    G_DoLoadLevel ();
1479
}
1480
 
1481
 
1482
//
1483
// DEMO RECORDING
1484
//
1485
#define DEMOMARKER		0x80
1486
 
1487
 
1488
void G_ReadDemoTiccmd (ticcmd_t* cmd)
1489
{
1490
    if (*demo_p == DEMOMARKER)
1491
    {
1492
	// end of demo data stream
1493
	G_CheckDemoStatus ();
1494
	return;
1495
    }
1496
    cmd->forwardmove = ((signed char)*demo_p++);
1497
    cmd->sidemove = ((signed char)*demo_p++);
1498
    cmd->angleturn = ((unsigned char)*demo_p++)<<8;
1499
    cmd->buttons = (unsigned char)*demo_p++;
1500
}
1501
 
1502
 
1503
void G_WriteDemoTiccmd (ticcmd_t* cmd)
1504
{
1505
    if (gamekeydown['q'])           // press q to end demo recording
1506
	G_CheckDemoStatus ();
1507
    *demo_p++ = cmd->forwardmove;
1508
    *demo_p++ = cmd->sidemove;
1509
    *demo_p++ = (cmd->angleturn+128)>>8;
1510
    *demo_p++ = cmd->buttons;
1511
    demo_p -= 4;
1512
    if (demo_p > demoend - 16)
1513
    {
1514
	// no more space
1515
	G_CheckDemoStatus ();
1516
	return;
1517
    }
1518
 
1519
    G_ReadDemoTiccmd (cmd);         // make SURE it is exactly the same
1520
}
1521
 
1522
 
1523
 
1524
//
1525
// G_RecordDemo
1526
//
1527
void G_RecordDemo (char* name)
1528
{
1529
    int             i;
1530
    int				maxsize;
1531
 
1532
    usergame = false;
1533
    strcpy (demoname, name);
1534
    strcat (demoname, ".lmp");
1535
    maxsize = 0x20000;
1536
    i = M_CheckParm ("-maxdemo");
1537
    if (i && i
1538
	maxsize = atoi(myargv[i+1])*1024;
1539
    demobuffer = Z_Malloc (maxsize,PU_STATIC,NULL);
1540
    demoend = demobuffer + maxsize;
1541
 
1542
    demorecording = true;
1543
}
1544
 
1545
 
1546
void G_BeginRecording (void)
1547
{
1548
    int             i;
1549
 
1550
    demo_p = demobuffer;
1551
 
1552
    *demo_p++ = VERSION_NUM;
1553
    *demo_p++ = gameskill;
1554
    *demo_p++ = gameepisode;
1555
    *demo_p++ = gamemap;
1556
    *demo_p++ = deathmatch;
1557
    *demo_p++ = respawnparm;
1558
    *demo_p++ = fastparm;
1559
    *demo_p++ = nomonsters;
1560
    *demo_p++ = consoleplayer;
1561
 
1562
    for (i=0 ; i
1563
	*demo_p++ = playeringame[i];
1564
}
1565
 
1566
 
1567
//
1568
// G_PlayDemo
1569
//
1570
 
1571
char*	defdemoname;
1572
 
1573
void G_DeferedPlayDemo (char* name)
1574
{
1575
    defdemoname = name;
1576
    gameaction = ga_playdemo;
1577
}
1578
 
1579
void G_DoPlayDemo (void)
1580
{
1581
    skill_t skill;
1582
    int             i, episode, map;
1583
 
1584
    gameaction = ga_nothing;
1585
    demobuffer = demo_p = W_CacheLumpName (defdemoname, PU_STATIC);
1586
    if ( *demo_p++ != VERSION_NUM)
1587
    {
1588
      gameaction = ga_nothing;
1589
      return;
1590
    }
1591
 
1592
    skill = *demo_p++;
1593
    episode = *demo_p++;
1594
    map = *demo_p++;
1595
    deathmatch = *demo_p++;
1596
    respawnparm = *demo_p++;
1597
    fastparm = *demo_p++;
1598
    nomonsters = *demo_p++;
1599
    consoleplayer = *demo_p++;
1600
 
1601
    for (i=0 ; i
1602
	playeringame[i] = *demo_p++;
1603
    if (playeringame[1])
1604
    {
1605
	netgame = true;
1606
	netdemo = true;
1607
    }
1608
 
1609
    // don't spend a lot of time in loadlevel
1610
    precache = false;
1611
    G_InitNew (skill, episode, map);
1612
    precache = true;
1613
 
1614
    usergame = false;
1615
    demoplayback = true;
1616
}
1617
 
1618
//
1619
// G_TimeDemo
1620
//
1621
void G_TimeDemo (char* name)
1622
{
1623
    nodrawers = M_CheckParm ("-nodraw");
1624
    noblit = M_CheckParm ("-noblit");
1625
    timingdemo = true;
1626
    singletics = true;
1627
 
1628
    defdemoname = name;
1629
    gameaction = ga_playdemo;
1630
}
1631
 
1632
 
1633
/*
1634
===================
1635
=
1636
= G_CheckDemoStatus
1637
=
1638
= Called after a death or level completion to allow demos to be cleaned up
1639
= Returns true if a new demo loop action will take place
1640
===================
1641
*/
1642
 
1643
boolean G_CheckDemoStatus (void)
1644
{
1645
    int             endtime;
1646
 
1647
    if (timingdemo)
1648
    {
1649
	endtime = I_GetTime ();
1650
	I_Error ("timed %i gametics in %i realtics",gametic
1651
		 , endtime-starttime);
1652
    }
1653
 
1654
    if (demoplayback)
1655
    {
1656
/*	if (singledemo)
1657
	    I_Quit ();  */
1658
 
1659
	Z_ChangeTag (demobuffer, PU_CACHE);
1660
	demoplayback = false;
1661
	netdemo = false;
1662
	netgame = false;
1663
	deathmatch = false;
1664
	playeringame[1] = playeringame[2] = playeringame[3] = 0;
1665
	respawnparm = false;
1666
	fastparm = false;
1667
	nomonsters = false;
1668
	consoleplayer = 0;
1669
	D_AdvanceDemo ();
1670
	return true;
1671
    }
1672
 
1673
    if (demorecording)
1674
    {
1675
	*demo_p++ = DEMOMARKER;
1676
	M_WriteFile (demoname, demobuffer, demo_p - demobuffer);
1677
	Z_Free (demobuffer);
1678
	demorecording = false;
1679
	I_Error ("Demo %s recorded",demoname);
1680
    }
1681
 
1682
    return false;
1683
}
1684
 
1685
 
1686