1 
2 //**************************************************************************
3 //**
4 //** g_game.c : Heretic 2 : Raven Software, Corp.
5 //**
6 //** $RCSfile: g_game.c,v $
7 //** $Revision: 1.68 $
8 //** $Date: 96/01/12 13:18:07 $
9 //** $Author: bgokey $
10 //**
11 //**************************************************************************
12 
13 #include <string.h>
14 #include "h2def.h"
15 #include "p_local.h"
16 #include "soundst.h"
17 
18 #define AM_STARTKEY	9
19 
20 // External functions
21 
22 extern void R_InitSky(int map);
23 extern void P_PlayerNextArtifact(player_t *player);
24 
25 // Functions
26 
27 boolean G_CheckDemoStatus (void);
28 void G_ReadDemoTiccmd (ticcmd_t *cmd);
29 void G_WriteDemoTiccmd (ticcmd_t *cmd);
30 void G_InitNew (skill_t skill, int episode, int map);
31 
32 void G_DoReborn (int playernum);
33 
34 void G_DoLoadLevel(void);
35 void G_DoInitNew(void);
36 void G_DoNewGame(void);
37 void G_DoLoadGame(void);
38 void G_DoPlayDemo(void);
39 void G_DoTeleportNewMap(void);
40 void G_DoCompleted(void);
41 void G_DoVictory(void);
42 void G_DoWorldDone(void);
43 void G_DoSaveGame(void);
44 void G_DoSingleReborn(void);
45 
46 void H2_PageTicker(void);
47 void H2_AdvanceDemo(void);
48 
49 extern boolean mn_SuicideConsole;
50 
51 gameaction_t    gameaction;
52 gamestate_t     gamestate;
53 skill_t         gameskill;
54 //boolean         respawnmonsters;
55 int             gameepisode;
56 int             gamemap;
57 int				 prevmap;
58 
59 boolean         paused;
60 boolean         sendpause;              // send a pause event next tic
61 boolean         sendsave;               // send a save event next tic
62 boolean         usergame;               // ok to save / end game
63 
64 boolean         timingdemo;             // if true, exit with report on completion
65 int             starttime;              // for comparative timing purposes
66 
67 boolean         viewactive;
68 
69 boolean         deathmatch;             // only if started as net death
70 boolean         netgame;                // only true if packets are broadcast
71 boolean         playeringame[MAXPLAYERS];
72 player_t        players[MAXPLAYERS];
73 pclass_t		PlayerClass[MAXPLAYERS];
74 
75 // Position indicator for cooperative net-play reborn
76 int RebornPosition;
77 
78 int             consoleplayer;          // player taking events and displaying
79 int             displayplayer;          // view being displayed
80 int             gametic;
81 int             levelstarttic;          // gametic at level start
82 
83 char            demoname[32];
84 boolean         demorecording;
85 boolean         demoplayback;
86 byte            *demobuffer, *demo_p;
87 boolean         singledemo;             // quit after playing a demo from cmdline
88 
89 boolean         precache = true;        // if true, load all graphics at start
90 
91 short            consistancy[MAXPLAYERS][BACKUPTICS];
92 
93 //
94 // controls (have defaults)
95 //
96 int key_right, key_left, key_up, key_down;
97 int key_strafeleft, key_straferight, key_jump;
98 int key_fire, key_use, key_strafe, key_speed, speed_lock;
99 int	key_flyup, key_flydown, key_flycenter;
100 int	key_lookup, key_lookdown, key_lookcenter;
101 int	key_invleft, key_invright, key_useartifact;
102 
103 int mousebfire;
104 int mousebstrafe;
105 int mousebforward;
106 int mousebjump;
107 
108 int joybfire;
109 int joybstrafe;
110 int joybuse;
111 int joybspeed;
112 int joybjump;
113 
114 int LeaveMap;
115 static int LeavePosition;
116 
117 //#define MAXPLMOVE       0x32 // Old Heretic Max move
118 
119 fixed_t MaxPlayerMove[NUMCLASSES] = { 0x3C, 0x32, 0x2D, 0x31 };
120 fixed_t forwardmove[NUMCLASSES][2] =
121 {
122 	{ 0x1D, 0x3C },
123 	{ 0x19, 0x32 },
124 	{ 0x16, 0x2E },
125 	{ 0x18, 0x31 }
126 };
127 
128 fixed_t sidemove[NUMCLASSES][2] =
129 {
130 	{ 0x1B, 0x3B },
131 	{ 0x18, 0x28 },
132 	{ 0x15, 0x25 },
133 	{ 0x17, 0x27 }
134 };
135 
136 fixed_t angleturn[3] = {640, 1280, 320};     // + slow turn
137 #define SLOWTURNTICS    6
138 
139 #define NUMKEYS 256
140 boolean         gamekeydown[NUMKEYS];
141 int             turnheld;                   // for accelerative turning
142 int				 lookheld;
143 
144 
145 boolean         mousearray[4];
146 boolean         *mousebuttons = &mousearray[1];
147 	// allow [-1]
148 int             mousex, mousey;             // mouse values are used once
149 int             dclicktime, dclickstate, dclicks;
150 int             dclicktime2, dclickstate2, dclicks2;
151 
152 int             joyxmove, joyymove;         // joystick values are repeated
153 boolean         joyarray[5];
154 boolean         *joybuttons = &joyarray[1];     // allow [-1]
155 
156 int     savegameslot;
157 char    savedescription[32];
158 
159 int inventoryTics;
160 
161 #ifdef __WATCOMC__
162 extern externdata_t *i_ExternData;
163 #endif
164 
165 static skill_t TempSkill;
166 static int TempEpisode;
167 static int TempMap;
168 
169 //=============================================================================
170 /*
171 ====================
172 =
173 = G_BuildTiccmd
174 =
175 = Builds a ticcmd from all of the available inputs or reads it from the
176 = demo buffer.
177 = If recording a demo, write it out
178 ====================
179 */
180 
181 extern boolean inventory;
182 extern int curpos;
183 extern int inv_ptr;
184 
185 extern  int             isCyberPresent;     // is CyberMan present?
186 boolean usearti = true;
187 void I_ReadCyberCmd (ticcmd_t *cmd);
188 
G_BuildTiccmd(ticcmd_t * cmd)189 void G_BuildTiccmd (ticcmd_t *cmd)
190 {
191 	int             i;
192 	boolean         strafe, bstrafe;
193 	int             speed, tspeed, lspeed;
194 	int             forward, side;
195 	int look, arti;
196 	int flyheight;
197 	int pClass;
198 
199 	extern boolean artiskip;
200 
201 #ifdef __WATCOMC__
202 	int angleDelta;
203 	static int oldAngle;
204 	extern int newViewAngleOff;
205 	static int externInvKey;
206 	extern boolean automapactive;
207 	event_t ev;
208 #endif
209 
210 	pClass = players[consoleplayer].class;
211 	memset (cmd,0,sizeof(*cmd));
212 
213 //	cmd->consistancy =
214 //		consistancy[consoleplayer][(maketic*ticdup)%BACKUPTICS];
215 
216 	cmd->consistancy =
217 		consistancy[consoleplayer][maketic%BACKUPTICS];
218 	if (isCyberPresent)
219 		I_ReadCyberCmd (cmd);
220 
221 //printf ("cons: %i\n",cmd->consistancy);
222 
223 	strafe = gamekeydown[key_strafe] || mousebuttons[mousebstrafe]
224 		|| joybuttons[joybstrafe];
225 	speed = gamekeydown[key_speed] || speed_lock || joybuttons[joybspeed];
226 #ifdef __WATCOMC__
227 	if(useexterndriver)
228 	{
229 		speed |= (i_ExternData->buttons&EBT_SPEED);
230 		strafe |= (i_ExternData->buttons&EBT_STRAFE);
231 	}
232 #endif
233 
234 	forward = side = look = arti = flyheight = 0;
235 
236 //
237 // use two stage accelerative turning on the keyboard and joystick
238 //
239 	if (joyxmove < 0 || joyxmove > 0
240 	|| gamekeydown[key_right] || gamekeydown[key_left])
241 		turnheld += ticdup;
242 	else
243 		turnheld = 0;
244 	if (turnheld < SLOWTURNTICS)
245 		tspeed = 2;             // slow turn
246 	else
247 		tspeed = speed;
248 
249 	if(gamekeydown[key_lookdown] || gamekeydown[key_lookup])
250 	{
251 		lookheld += ticdup;
252 	}
253 	else
254 	{
255 		lookheld = 0;
256 	}
257 	if(lookheld < SLOWTURNTICS)
258 	{
259 		lspeed = 1; // 3;
260 	}
261 	else
262 	{
263 		lspeed = 2; // 5;
264 	}
265 
266 //
267 // let movement keys cancel each other out
268 //
269 	if(strafe)
270 	{
271 		if (gamekeydown[key_right])
272 		{
273 			side += sidemove[pClass][speed];
274 		}
275 		if (gamekeydown[key_left])
276 		{
277 			side -= sidemove[pClass][speed];
278 		}
279 		if (joyxmove > 0)
280 		{
281 			side += sidemove[pClass][speed];
282 		}
283 		if (joyxmove < 0)
284 		{
285 			side -= sidemove[pClass][speed];
286 		}
287 	}
288 	else
289 	{
290 		if (gamekeydown[key_right])
291 			cmd->angleturn -= angleturn[tspeed];
292 		if (gamekeydown[key_left])
293 			cmd->angleturn += angleturn[tspeed];
294 		if (joyxmove > 0)
295 			cmd->angleturn -= angleturn[tspeed];
296 		if (joyxmove < 0)
297 			cmd->angleturn += angleturn[tspeed];
298 	}
299 
300 	if (gamekeydown[key_up])
301 	{
302 		forward += forwardmove[pClass][speed];
303 	}
304 	if (gamekeydown[key_down])
305 	{
306 		forward -= forwardmove[pClass][speed];
307 	}
308 	if (joyymove < 0)
309 	{
310 		forward += forwardmove[pClass][speed];
311 	}
312 	if (joyymove > 0)
313 	{
314 		forward -= forwardmove[pClass][speed];
315 	}
316 	if (gamekeydown[key_straferight])
317 	{
318 		side += sidemove[pClass][speed];
319 	}
320 	if (gamekeydown[key_strafeleft])
321 	{
322 		side -= sidemove[pClass][speed];
323 	}
324 
325 	// Look up/down/center keys
326 	if(gamekeydown[key_lookup])
327 	{
328 		look = lspeed;
329 	}
330 	if(gamekeydown[key_lookdown])
331 	{
332 		look = -lspeed;
333 	}
334 #ifdef __WATCOMC__
335 	if(gamekeydown[key_lookcenter] && !useexterndriver)
336 	{
337 		look = TOCENTER;
338 	}
339 #else
340 	if(gamekeydown[key_lookcenter])
341 	{
342 		look = TOCENTER;
343 	}
344 #endif
345 
346 #ifdef __WATCOMC__
347 	if(useexterndriver && look != TOCENTER && (gamestate == GS_LEVEL ||
348 		gamestate == GS_INTERMISSION))
349 	{
350 		if(i_ExternData->moveForward)
351 		{
352 			forward += i_ExternData->moveForward;
353 			if(speed)
354 			{
355 				forward <<= 1;
356 			}
357 		}
358 		if(i_ExternData->angleTurn)
359 		{
360 			if(strafe)
361 			{
362 				side += i_ExternData->angleTurn;
363 			}
364 			else
365 			{
366 				cmd->angleturn += i_ExternData->angleTurn;
367 			}
368 		}
369 		if(i_ExternData->moveSideways)
370 		{
371 			side += i_ExternData->moveSideways;
372 			if(speed)
373 			{
374 				side <<= 1;
375 			}
376 		}
377 		if(i_ExternData->buttons&EBT_CENTERVIEW)
378 		{
379 			look = TOCENTER;
380 			oldAngle = 0;
381 		}
382 		else if(i_ExternData->pitch)
383 		{
384 			angleDelta = i_ExternData->pitch-oldAngle;
385 			if(abs(angleDelta) < 35)
386 			{
387 				look = angleDelta/5;
388 			}
389 			else
390 			{
391 				look = 7*(angleDelta > 0 ? 1 : -1);
392 			}
393 			if(look == TOCENTER)
394 			{
395 				look++;
396 			}
397 			oldAngle += look*5;
398 		}
399 		if(i_ExternData->flyDirection)
400 		{
401 			if(i_ExternData->flyDirection > 0)
402 			{
403 				flyheight = 5;
404 			}
405 			else
406 			{
407 				flyheight = -5;
408 			}
409 		}
410 		if(abs(newViewAngleOff-i_ExternData->angleHead) < 3000)
411 		{
412 			newViewAngleOff = i_ExternData->angleHead;
413 		}
414 		if(i_ExternData->buttons&EBT_FIRE)
415 		{
416 			cmd->buttons |= BT_ATTACK;
417 		}
418 		if(i_ExternData->buttons&EBT_OPENDOOR)
419 		{
420 			cmd->buttons |= BT_USE;
421 		}
422 		if(i_ExternData->buttons&EBT_PAUSE)
423 		{
424 			cmd->buttons = BT_SPECIAL|BTS_PAUSE;
425 			i_ExternData->buttons &= ~EBT_PAUSE;
426 		}
427 		if(externInvKey&EBT_USEARTIFACT)
428 		{
429 			ev.type = ev_keyup;
430 			ev.data1 = key_useartifact;
431 			H2_PostEvent(&ev);
432 			externInvKey &= ~EBT_USEARTIFACT;
433 		}
434 		else if(i_ExternData->buttons&EBT_USEARTIFACT)
435 		{
436 			externInvKey |= EBT_USEARTIFACT;
437 			ev.type = ev_keydown;
438 			ev.data1 = key_useartifact;
439 			H2_PostEvent(&ev);
440 		}
441 		if(externInvKey&EBT_INVENTORYRIGHT)
442 		{
443 			ev.type = ev_keyup;
444 			ev.data1 = key_invright;
445 			H2_PostEvent(&ev);
446 			externInvKey &= ~EBT_INVENTORYRIGHT;
447 		}
448 		else if(i_ExternData->buttons&EBT_INVENTORYRIGHT)
449 		{
450 			externInvKey |= EBT_INVENTORYRIGHT;
451 			ev.type = ev_keydown;
452 			ev.data1 = key_invright;
453 			H2_PostEvent(&ev);
454 		}
455 		if(externInvKey&EBT_INVENTORYLEFT)
456 		{
457 			ev.type = ev_keyup;
458 			ev.data1 = key_invleft;
459 			H2_PostEvent(&ev);
460 			externInvKey &= ~EBT_INVENTORYLEFT;
461 		}
462 		else if(i_ExternData->buttons&EBT_INVENTORYLEFT)
463 		{
464 			externInvKey |= EBT_INVENTORYLEFT;
465 			ev.type = ev_keydown;
466 			ev.data1 = key_invleft;
467 			H2_PostEvent(&ev);
468 		}
469 		if(i_ExternData->buttons&EBT_FLYDROP)
470 		{
471 			flyheight = TOCENTER;
472 		}
473 		if(gamestate == GS_LEVEL)
474 		{
475 			if(externInvKey&EBT_MAP)
476 			{ // automap
477 				ev.type = ev_keyup;
478 				ev.data1 = AM_STARTKEY;
479 				H2_PostEvent(&ev);
480 				externInvKey &= ~EBT_MAP;
481 			}
482 			else if(i_ExternData->buttons&EBT_MAP)
483 			{
484 				externInvKey |= EBT_MAP;
485 				ev.type = ev_keydown;
486 				ev.data1 = AM_STARTKEY;
487 				H2_PostEvent(&ev);
488 			}
489 		}
490 		if(i_ExternData->buttons&EBT_WEAPONCYCLE)
491 		{
492 			int curWeapon;
493 			player_t *pl;
494 
495 			pl = &players[consoleplayer];
496 			curWeapon = pl->readyweapon;
497 			for(curWeapon = (curWeapon+1)&3; curWeapon != pl->readyweapon;
498 				curWeapon = (curWeapon+1)&3)
499 			{
500 				if(pl->weaponowned[curWeapon])
501 				{
502 					cmd->buttons |= BT_CHANGE;
503 					cmd->buttons |= curWeapon<<BT_WEAPONSHIFT;
504 					break;
505 				}
506 			}
507 		}
508 		if(i_ExternData->buttons&EBT_JUMP)
509 		{
510 			cmd->arti |= AFLAG_JUMP;
511 		}
512 	}
513 #endif
514 
515 	// Fly up/down/drop keys
516 	if(gamekeydown[key_flyup])
517 	{
518 		flyheight = 5; // note that the actual flyheight will be twice this
519 	}
520 	if(gamekeydown[key_flydown])
521 	{
522 		flyheight = -5;
523 	}
524 	if(gamekeydown[key_flycenter])
525 	{
526 		flyheight = TOCENTER;
527 #ifdef __WATCOMC__
528 		if(!useexterndriver)
529 		{
530 			look = TOCENTER;
531 		}
532 #else
533 		look = TOCENTER;
534 #endif
535 	}
536 	// Use artifact key
537 	if(gamekeydown[key_useartifact])
538 	{
539 		if(gamekeydown[key_speed] && artiskip)
540 		{
541 			if(players[consoleplayer].inventory[inv_ptr].type != arti_none)
542 			{ // Skip an artifact
543 				gamekeydown[key_useartifact] = false;
544 				P_PlayerNextArtifact(&players[consoleplayer]);
545 			}
546 		}
547 		else
548 		{
549 			if(inventory)
550 			{
551 				players[consoleplayer].readyArtifact =
552 					players[consoleplayer].inventory[inv_ptr].type;
553 				inventory = false;
554 				cmd->arti = 0;
555 				usearti = false;
556 			}
557 			else if(usearti)
558 			{
559 				cmd->arti |=
560 					players[consoleplayer].inventory[inv_ptr].type&AFLAG_MASK;
561 				usearti = false;
562 			}
563 		}
564 	}
565 	if(gamekeydown[key_jump] || mousebuttons[mousebjump]
566 		|| joybuttons[joybjump])
567 	{
568 		cmd->arti |= AFLAG_JUMP;
569 	}
570 	if(mn_SuicideConsole)
571 	{
572 		cmd->arti |= AFLAG_SUICIDE;
573 		mn_SuicideConsole = false;
574 	}
575 
576 	// Artifact hot keys
577 	if(gamekeydown[KEY_BACKSPACE] && !cmd->arti)
578 	{
579 		gamekeydown[KEY_BACKSPACE] = false; 	// Use one of each artifact
580 		cmd->arti = NUMARTIFACTS;
581 	}
582 	else if(gamekeydown[KEY_BACKSLASH] && !cmd->arti
583 	&& (players[consoleplayer].mo->health < MAXHEALTH))
584 	{
585 		gamekeydown[KEY_BACKSLASH] = false;
586 		cmd->arti = arti_health;
587 	}
588 	else if(gamekeydown[KEY_ZERO] && !cmd->arti)
589 	{
590 		gamekeydown[KEY_ZERO] = false;
591 		cmd->arti = arti_poisonbag;
592 	}
593 	else if(gamekeydown[KEY_NINE] && !cmd->arti)
594 	{
595 		gamekeydown[KEY_NINE] = false;
596 		cmd->arti = arti_blastradius;
597 	}
598 	else if(gamekeydown[KEY_EIGHT] && !cmd->arti)
599 	{
600 		gamekeydown[KEY_EIGHT] = false;
601 		cmd->arti = arti_teleport;
602 	}
603 	else if(gamekeydown[KEY_SEVEN] && !cmd->arti)
604 	{
605 		gamekeydown[KEY_SEVEN] = false;
606 		cmd->arti = arti_teleportother;
607 	}
608 	else if(gamekeydown[KEY_SIX] && !cmd->arti)
609 	{
610 		gamekeydown[KEY_SIX] = false;
611 		cmd->arti = arti_egg;
612 	}
613 	else if(gamekeydown[KEY_FIVE] && !cmd->arti
614 	&& !players[consoleplayer].powers[pw_invulnerability])
615 	{
616 		gamekeydown[KEY_FIVE] = false;
617 		cmd->arti = arti_invulnerability;
618 	}
619 
620 //
621 // buttons
622 //
623 	cmd->chatchar = CT_dequeueChatChar();
624 
625 	if (gamekeydown[key_fire] || mousebuttons[mousebfire]
626 		|| joybuttons[joybfire])
627 		cmd->buttons |= BT_ATTACK;
628 
629 	if (gamekeydown[key_use] || joybuttons[joybuse] )
630 	{
631 		cmd->buttons |= BT_USE;
632 		dclicks = 0;                    // clear double clicks if hit use button
633 	}
634 
635 	for(i = 0; i < NUMWEAPONS; i++)
636 	{
637 		if(gamekeydown['1'+i])
638 		{
639 			cmd->buttons |= BT_CHANGE;
640 			cmd->buttons |= i<<BT_WEAPONSHIFT;
641 			break;
642 		}
643 	}
644 
645 //
646 // mouse
647 //
648 	if (mousebuttons[mousebforward])
649 	{
650 		forward += forwardmove[pClass][speed];
651 	}
652 
653 //
654 // forward double click
655 //
656 	if (mousebuttons[mousebforward] != dclickstate && dclicktime > 1 )
657 	{
658 		dclickstate = mousebuttons[mousebforward];
659 		if (dclickstate)
660 			dclicks++;
661 		if (dclicks == 2)
662 		{
663 			cmd->buttons |= BT_USE;
664 			dclicks = 0;
665 		}
666 		else
667 			dclicktime = 0;
668 	}
669 	else
670 	{
671 		dclicktime += ticdup;
672 		if (dclicktime > 20)
673 		{
674 			dclicks = 0;
675 			dclickstate = 0;
676 		}
677 	}
678 
679 //
680 // strafe double click
681 //
682 	bstrafe = mousebuttons[mousebstrafe]
683 || joybuttons[joybstrafe];
684 	if (bstrafe != dclickstate2 && dclicktime2 > 1 )
685 	{
686 		dclickstate2 = bstrafe;
687 		if (dclickstate2)
688 			dclicks2++;
689 		if (dclicks2 == 2)
690 		{
691 			cmd->buttons |= BT_USE;
692 			dclicks2 = 0;
693 		}
694 		else
695 			dclicktime2 = 0;
696 	}
697 	else
698 	{
699 		dclicktime2 += ticdup;
700 		if (dclicktime2 > 20)
701 		{
702 			dclicks2 = 0;
703 			dclickstate2 = 0;
704 		}
705 	}
706 
707 	if (strafe)
708 	{
709 		side += mousex*2;
710 	}
711 	else
712 	{
713 		cmd->angleturn -= mousex*0x8;
714 	}
715 	forward += mousey;
716 	mousex = mousey = 0;
717 
718 	if (forward > MaxPlayerMove[pClass])
719 	{
720 		forward = MaxPlayerMove[pClass];
721 	}
722 	else if (forward < -MaxPlayerMove[pClass])
723 	{
724 		forward = -MaxPlayerMove[pClass];
725 	}
726 	if (side > MaxPlayerMove[pClass])
727 	{
728 		side = MaxPlayerMove[pClass];
729 	}
730 	else if (side < -MaxPlayerMove[pClass])
731 	{
732 		side = -MaxPlayerMove[pClass];
733 	}
734 	if(players[consoleplayer].powers[pw_speed]
735 		&& !players[consoleplayer].morphTics)
736 	{ // Adjust for a player with a speed artifact
737 		forward = (3*forward)>>1;
738 		side = (3*side)>>1;
739 	}
740 	cmd->forwardmove += forward;
741 	cmd->sidemove += side;
742 	if(players[consoleplayer].playerstate == PST_LIVE)
743 	{
744 		if(look < 0)
745 		{
746 			look += 16;
747 		}
748 		cmd->lookfly = look;
749 	}
750 	if(flyheight < 0)
751 	{
752 		flyheight += 16;
753 	}
754 	cmd->lookfly |= flyheight<<4;
755 
756 //
757 // special buttons
758 //
759 	if (sendpause)
760 	{
761 		sendpause = false;
762 		cmd->buttons = BT_SPECIAL | BTS_PAUSE;
763 	}
764 
765 	if (sendsave)
766 	{
767 		sendsave = false;
768 		cmd->buttons = BT_SPECIAL | BTS_SAVEGAME | (savegameslot<<BTS_SAVESHIFT);
769 	}
770 }
771 
772 
773 /*
774 ==============
775 =
776 = G_DoLoadLevel
777 =
778 ==============
779 */
780 
G_DoLoadLevel(void)781 void G_DoLoadLevel (void)
782 {
783 	int             i;
784 
785 	levelstarttic = gametic;        // for time calculation
786 	gamestate = GS_LEVEL;
787 	for (i=0 ; i<MAXPLAYERS ; i++)
788 	{
789 		if (playeringame[i] && players[i].playerstate == PST_DEAD)
790 			players[i].playerstate = PST_REBORN;
791 		memset (players[i].frags,0,sizeof(players[i].frags));
792 	}
793 
794 	SN_StopAllSequences();
795 	P_SetupLevel (gameepisode, gamemap, 0, gameskill);
796 	displayplayer = consoleplayer;      // view the guy you are playing
797 	starttime = I_GetTime ();
798 	gameaction = ga_nothing;
799 	Z_CheckHeap ();
800 
801 //
802 // clear cmd building stuff
803 //
804 
805 	memset (gamekeydown, 0, sizeof(gamekeydown));
806 	joyxmove = joyymove = 0;
807 	mousex = mousey = 0;
808 	sendpause = sendsave = paused = false;
809 	memset (mousebuttons, 0, sizeof(mousebuttons));
810 	memset (joybuttons, 0, sizeof(joybuttons));
811 }
812 
813 
814 /*
815 ===============================================================================
816 =
817 = G_Responder
818 =
819 = get info needed to make ticcmd_ts for the players
820 =
821 ===============================================================================
822 */
823 
G_Responder(event_t * ev)824 boolean G_Responder(event_t *ev)
825 {
826 	player_t *plr;
827 	extern boolean MenuActive;
828 
829 	plr = &players[consoleplayer];
830 	if(ev->type == ev_keyup && ev->data1 == key_useartifact)
831 	{ // flag to denote that it's okay to use an artifact
832 		if(!inventory)
833 		{
834 			plr->readyArtifact = plr->inventory[inv_ptr].type;
835 		}
836 		usearti = true;
837 	}
838 
839 	// Check for spy mode player cycle
840 	if(gamestate == GS_LEVEL && ev->type == ev_keydown
841 		&& ev->data1 == KEY_F12 && !deathmatch)
842 	{ // Cycle the display player
843 		do
844 		{
845 			displayplayer++;
846 			if(displayplayer == MAXPLAYERS)
847 			{
848 				displayplayer = 0;
849 			}
850 		} while(!playeringame[displayplayer]
851 			&& displayplayer != consoleplayer);
852 		return(true);
853 	}
854 
855 	if(CT_Responder(ev))
856 	{ // Chat ate the event
857 		return(true);
858 	}
859 	if(gamestate == GS_LEVEL)
860 	{
861 		if(SB_Responder(ev))
862 		{ // Status bar ate the event
863 			return(true);
864 		}
865 		if(AM_Responder(ev))
866 		{ // Automap ate the event
867 			return(true);
868 		}
869 	}
870 
871 	switch(ev->type)
872 	{
873 		case ev_keydown:
874 			if(ev->data1 == key_invleft)
875 			{
876 				inventoryTics = 5*35;
877 				if(!inventory)
878 				{
879 					inventory = true;
880 					break;
881 				}
882 				inv_ptr--;
883 				if(inv_ptr < 0)
884 				{
885 					inv_ptr = 0;
886 				}
887 				else
888 				{
889 					curpos--;
890 					if(curpos < 0)
891 					{
892 						curpos = 0;
893 					}
894 				}
895 				return(true);
896 			}
897 			if(ev->data1 == key_invright)
898 			{
899 				inventoryTics = 5*35;
900 				if(!inventory)
901 				{
902 					inventory = true;
903 					break;
904 				}
905 				inv_ptr++;
906 				if(inv_ptr >= plr->inventorySlotNum)
907 				{
908 					inv_ptr--;
909 					if(inv_ptr < 0)
910 						inv_ptr = 0;
911 				}
912 				else
913 				{
914 					curpos++;
915 					if(curpos > 6)
916 					{
917 						curpos = 6;
918 					}
919 				}
920 				return(true);
921 			}
922 			if(ev->data1 == KEY_PAUSE && !MenuActive)
923 			{
924 				sendpause = true;
925 				return(true);
926 			}
927 			if(ev->data1 < NUMKEYS)
928 			{
929 				gamekeydown[ev->data1] = true;
930 			}
931 			return(true); // eat key down events
932 
933 		case ev_keyup:
934 			if(ev->data1 < NUMKEYS)
935 			{
936 				gamekeydown[ev->data1] = false;
937 			}
938 			return(false); // always let key up events filter down
939 
940 		case ev_mouse:
941 			mousebuttons[0] = ev->data1&1;
942 			mousebuttons[1] = ev->data1&2;
943 			mousebuttons[2] = ev->data1&4;
944 			mousex = ev->data2*(mouseSensitivity+5)/10;
945 			mousey = ev->data3*(mouseSensitivity+5)/10;
946 			return(true); // eat events
947 
948 		case ev_joystick:
949 			joybuttons[0] = ev->data1&1;
950 			joybuttons[1] = ev->data1&2;
951 			joybuttons[2] = ev->data1&4;
952 			joybuttons[3] = ev->data1&8;
953 			joyxmove = ev->data2;
954 			joyymove = ev->data3;
955 			return(true); // eat events
956 
957 		default:
958 			break;
959 	}
960 	return(false);
961 }
962 
963 
964 //==========================================================================
965 //
966 // G_Ticker
967 //
968 //==========================================================================
969 
G_Ticker(void)970 void G_Ticker(void)
971 {
972 	int i, buf;
973 	ticcmd_t *cmd=NULL;
974 
975 //
976 // do player reborns if needed
977 //
978 	for (i=0 ; i<MAXPLAYERS ; i++)
979 		if (playeringame[i] && players[i].playerstate == PST_REBORN)
980 			G_DoReborn (i);
981 
982 //
983 // do things to change the game state
984 //
985 	while (gameaction != ga_nothing)
986 	{
987 		switch (gameaction)
988 		{
989 			case ga_loadlevel:
990 				G_DoLoadLevel();
991 				break;
992 			case ga_initnew:
993 				G_DoInitNew();
994 				break;
995 			case ga_newgame:
996 				G_DoNewGame();
997 				break;
998 			case ga_loadgame:
999 				Draw_LoadIcon();
1000 				G_DoLoadGame();
1001 				break;
1002 			case ga_savegame:
1003 				Draw_SaveIcon();
1004 				G_DoSaveGame();
1005 				break;
1006 			case ga_singlereborn:
1007 				G_DoSingleReborn();
1008 				break;
1009 			case ga_playdemo:
1010 				G_DoPlayDemo();
1011 				break;
1012 			case ga_screenshot:
1013 				M_ScreenShot();
1014 				gameaction = ga_nothing;
1015 				break;
1016 			case ga_leavemap:
1017 				Draw_TeleportIcon();
1018 				G_DoTeleportNewMap();
1019 				break;
1020 			case ga_completed:
1021 				G_DoCompleted();
1022 				break;
1023 			case ga_worlddone:
1024 				G_DoWorldDone();
1025 				break;
1026 			case ga_victory:
1027 				F_StartFinale();
1028 				break;
1029 			default:
1030 				break;
1031 		}
1032 	}
1033 
1034 
1035 //
1036 // get commands, check consistancy, and build new consistancy check
1037 //
1038 	//buf = gametic%BACKUPTICS;
1039 	buf = (gametic/ticdup)%BACKUPTICS;
1040 
1041 	for (i=0 ; i<MAXPLAYERS ; i++)
1042 		if (playeringame[i])
1043 		{
1044 			cmd = &players[i].cmd;
1045 
1046 			memcpy (cmd, &netcmds[i][buf], sizeof(ticcmd_t));
1047 
1048 			if (demoplayback)
1049 				G_ReadDemoTiccmd (cmd);
1050 			if (demorecording)
1051 				G_WriteDemoTiccmd (cmd);
1052 
1053 			if (netgame && !(gametic%ticdup) )
1054 			{
1055 				if (gametic > BACKUPTICS
1056 				&& consistancy[i][buf] != cmd->consistancy)
1057 				{
1058 					I_Error ("consistency failure (%i should be %i)",cmd->consistancy, consistancy[i][buf]);
1059 				}
1060 				if (players[i].mo)
1061 					consistancy[i][buf] = players[i].mo->x;
1062 				else
1063 					consistancy[i][buf] = rndindex;
1064 			}
1065 		}
1066 
1067 //
1068 // check for special buttons
1069 //
1070 	for (i=0 ; i<MAXPLAYERS ; i++)
1071 		if (playeringame[i])
1072 		{
1073 			if (players[i].cmd.buttons & BT_SPECIAL)
1074 			{
1075 				switch (players[i].cmd.buttons & BT_SPECIALMASK)
1076 				{
1077 				case BTS_PAUSE:
1078 					paused ^= 1;
1079 					if(paused)
1080 					{
1081 						S_PauseSound();
1082 					}
1083 					else
1084 					{
1085 						S_ResumeSound();
1086 					}
1087 					break;
1088 
1089 				case BTS_SAVEGAME:
1090 					if (!savedescription[0])
1091 					{
1092 						if(netgame)
1093 						{
1094 							strcpy (savedescription, "NET GAME");
1095 						}
1096 						else
1097 						{
1098 							strcpy(savedescription, "SAVE GAME");
1099 						}
1100 					}
1101 					savegameslot =
1102 						(players[i].cmd.buttons & BTS_SAVEMASK)>>BTS_SAVESHIFT;
1103 					gameaction = ga_savegame;
1104 					break;
1105 				}
1106 			}
1107 		}
1108 	// turn inventory off after a certain amount of time
1109 	if(inventory && !(--inventoryTics))
1110 	{
1111 		players[consoleplayer].readyArtifact =
1112 			players[consoleplayer].inventory[inv_ptr].type;
1113 		inventory = false;
1114 		cmd->arti = 0;
1115 	}
1116 //
1117 // do main actions
1118 //
1119 //
1120 // do main actions
1121 //
1122 	switch (gamestate)
1123 	{
1124 		case GS_LEVEL:
1125 			P_Ticker ();
1126 			SB_Ticker ();
1127 			AM_Ticker ();
1128 			CT_Ticker();
1129 			break;
1130 		case GS_INTERMISSION:
1131 			IN_Ticker ();
1132 			break;
1133 		case GS_FINALE:
1134 			F_Ticker();
1135 			break;
1136 		case GS_DEMOSCREEN:
1137 			H2_PageTicker ();
1138 			break;
1139 	}
1140 }
1141 
1142 
1143 /*
1144 ==============================================================================
1145 
1146 						PLAYER STRUCTURE FUNCTIONS
1147 
1148 also see P_SpawnPlayer in P_Things
1149 ==============================================================================
1150 */
1151 
1152 //==========================================================================
1153 //
1154 // G_PlayerExitMap
1155 //
1156 // Called when the player leaves a map.
1157 //
1158 //==========================================================================
1159 
G_PlayerExitMap(int playerNumber)1160 void G_PlayerExitMap(int playerNumber)
1161 {
1162 	int i;
1163 	player_t *player;
1164 	int flightPower;
1165 
1166 	player = &players[playerNumber];
1167 
1168 //	if(deathmatch)
1169 //	{
1170 //		// Strip all but one of each type of artifact
1171 //		for(i = 0; i < player->inventorySlotNum; i++)
1172 //		{
1173 //			player->inventory[i].count = 1;
1174 //		}
1175 //		player->artifactCount = player->inventorySlotNum;
1176 //	}
1177 //	else
1178 
1179 	// Strip all current powers (retain flight)
1180 	flightPower = player->powers[pw_flight];
1181 	memset(player->powers, 0, sizeof(player->powers));
1182 	player->powers[pw_flight] = flightPower;
1183 
1184 	if(deathmatch)
1185 	{
1186 		player->powers[pw_flight] = 0;
1187 	}
1188 	else
1189 	{
1190 		if(P_GetMapCluster(gamemap) != P_GetMapCluster(LeaveMap))
1191 		{ // Entering new cluster
1192 			// Strip all keys
1193 			player->keys = 0;
1194 
1195 			// Strip flight artifact
1196 			for(i = 0; i < 25; i++)
1197 			{
1198 				player->powers[pw_flight] = 0;
1199 				P_PlayerUseArtifact(player, arti_fly);
1200 			}
1201 			player->powers[pw_flight] = 0;
1202 		}
1203 	}
1204 
1205 	if(player->morphTics)
1206 	{
1207 		player->readyweapon = player->mo->special1; // Restore weapon
1208 		player->morphTics = 0;
1209 	}
1210 	player->messageTics = 0;
1211 	player->lookdir = 0;
1212 	player->mo->flags &= ~MF_SHADOW; // Remove invisibility
1213 	player->extralight = 0; // Remove weapon flashes
1214 	player->fixedcolormap = 0; // Remove torch
1215 	player->damagecount = 0; // No palette changes
1216 	player->bonuscount = 0;
1217 	player->poisoncount = 0;
1218 	if(player == &players[consoleplayer])
1219 	{
1220 		SB_state = -1; // refresh the status bar
1221 		viewangleoffset = 0;
1222 	}
1223 }
1224 
1225 //==========================================================================
1226 //
1227 // G_PlayerReborn
1228 //
1229 // Called after a player dies.  Almost everything is cleared and
1230 // initialized.
1231 //
1232 //==========================================================================
1233 
G_PlayerReborn(int player)1234 void G_PlayerReborn(int player)
1235 {
1236 	player_t *p;
1237 	int frags[MAXPLAYERS];
1238 	int killcount, itemcount, secretcount;
1239 	uint worldTimer;
1240 
1241 	memcpy(frags, players[player].frags, sizeof(frags));
1242 	killcount = players[player].killcount;
1243 	itemcount = players[player].itemcount;
1244 	secretcount = players[player].secretcount;
1245 	worldTimer = players[player].worldTimer;
1246 
1247 	p = &players[player];
1248 	memset(p, 0, sizeof(*p));
1249 
1250 	memcpy(players[player].frags, frags, sizeof(players[player].frags));
1251 	players[player].killcount = killcount;
1252 	players[player].itemcount = itemcount;
1253 	players[player].secretcount = secretcount;
1254 	players[player].worldTimer = worldTimer;
1255 	players[player].class = PlayerClass[player];
1256 
1257 	p->usedown = p->attackdown = true; // don't do anything immediately
1258 	p->playerstate = PST_LIVE;
1259 	p->health = MAXHEALTH;
1260 	p->readyweapon = p->pendingweapon = WP_FIRST;
1261 	p->weaponowned[WP_FIRST] = true;
1262 	p->messageTics = 0;
1263 	p->lookdir = 0;
1264 	localQuakeHappening[player] = false;
1265 	if(p == &players[consoleplayer])
1266 	{
1267 		SB_state = -1; // refresh the status bar
1268 		inv_ptr = 0; // reset the inventory pointer
1269 		curpos = 0;
1270 		viewangleoffset = 0;
1271 	}
1272 }
1273 
1274 /*
1275 ====================
1276 =
1277 = G_CheckSpot
1278 =
1279 = Returns false if the player cannot be respawned at the given mapthing_t spot
1280 = because something is occupying it
1281 ====================
1282 */
1283 
1284 void P_SpawnPlayer (mapthing_t *mthing);
1285 
G_CheckSpot(int playernum,mapthing_t * mthing)1286 boolean G_CheckSpot (int playernum, mapthing_t *mthing)
1287 {
1288 	fixed_t         x,y;
1289 	subsector_t *ss;
1290 	unsigned        an;
1291 	mobj_t      *mo;
1292 
1293 	x = mthing->x << FRACBITS;
1294 	y = mthing->y << FRACBITS;
1295 
1296 	players[playernum].mo->flags2 &= ~MF2_PASSMOBJ;
1297 	if (!P_CheckPosition (players[playernum].mo, x, y) )
1298 	{
1299 		players[playernum].mo->flags2 |= MF2_PASSMOBJ;
1300 		return false;
1301 	}
1302 	players[playernum].mo->flags2 |= MF2_PASSMOBJ;
1303 
1304 // spawn a teleport fog
1305 	ss = R_PointInSubsector (x,y);
1306 	an = ( ANG45 * (mthing->angle/45) ) >> ANGLETOFINESHIFT;
1307 
1308 	mo = P_SpawnMobj (x+20*finecosine[an], y+20*finesine[an],
1309 		ss->sector->floorheight+TELEFOGHEIGHT, MT_TFOG);
1310 	if (players[consoleplayer].viewz != 1)
1311 		S_StartSound (mo, SFX_TELEPORT);  // don't start sound on first frame
1312 
1313 	return true;
1314 }
1315 
1316 /*
1317 ====================
1318 =
1319 = G_DeathMatchSpawnPlayer
1320 =
1321 = Spawns a player at one of the random death match spots
1322 = called at level load and each death
1323 ====================
1324 */
1325 
G_DeathMatchSpawnPlayer(int playernum)1326 void G_DeathMatchSpawnPlayer (int playernum)
1327 {
1328 	int             i,j;
1329 	int             selections;
1330 
1331 	selections = deathmatch_p - deathmatchstarts;
1332 
1333 	// This check has been moved to p_setup.c:P_LoadThings()
1334 	//if (selections < 8)
1335 	//	I_Error ("Only %i deathmatch spots, 8 required", selections);
1336 
1337 	for (j=0 ; j<20 ; j++)
1338 	{
1339 		i = P_Random() % selections;
1340 		if (G_CheckSpot (playernum, &deathmatchstarts[i]) )
1341 		{
1342 			deathmatchstarts[i].type = playernum+1;
1343 			P_SpawnPlayer (&deathmatchstarts[i]);
1344 			return;
1345 		}
1346 	}
1347 
1348 // no good spot, so the player will probably get stuck
1349 	P_SpawnPlayer (&playerstarts[0][playernum]);
1350 }
1351 
1352 //==========================================================================
1353 //
1354 // G_DoReborn
1355 //
1356 //==========================================================================
1357 
G_DoReborn(int playernum)1358 void G_DoReborn(int playernum)
1359 {
1360 	int i;
1361 	boolean oldWeaponowned[NUMWEAPONS];
1362 	int oldKeys;
1363 	int oldPieces;
1364 	boolean foundSpot;
1365 	int bestWeapon;
1366 
1367 	if(G_CheckDemoStatus())
1368 	{
1369 		return;
1370 	}
1371 	if(!netgame)
1372 	{
1373 		if(SV_RebornSlotAvailable())
1374 		{ // Use the reborn code if the slot is available
1375 			gameaction = ga_singlereborn;
1376 		}
1377 		else
1378 		{ // Start a new game if there's no reborn info
1379 			gameaction = ga_newgame;
1380 		}
1381 	}
1382 	else
1383 	{ // Net-game
1384 		players[playernum].mo->player = NULL; // Dissassociate the corpse
1385 
1386 		if(deathmatch)
1387 		{ // Spawn at random spot if in death match
1388 			G_DeathMatchSpawnPlayer(playernum);
1389 			return;
1390 		}
1391 
1392 		// Cooperative net-play, retain keys and weapons
1393 		oldKeys = players[playernum].keys;
1394 		oldPieces = players[playernum].pieces;
1395 		for(i = 0; i < NUMWEAPONS; i++)
1396 		{
1397 			oldWeaponowned[i] = players[playernum].weaponowned[i];
1398 		}
1399 
1400 		foundSpot = false;
1401 		if(G_CheckSpot(playernum,
1402 			&playerstarts[RebornPosition][playernum]))
1403 		{ // Appropriate player start spot is open
1404 			P_SpawnPlayer(&playerstarts[RebornPosition][playernum]);
1405 			foundSpot = true;
1406 		}
1407 		else
1408 		{
1409 			// Try to spawn at one of the other player start spots
1410 			for(i = 0; i < MAXPLAYERS; i++)
1411 			{
1412 				if(G_CheckSpot(playernum, &playerstarts[RebornPosition][i]))
1413 				{ // Found an open start spot
1414 
1415 					// Fake as other player
1416 					playerstarts[RebornPosition][i].type = playernum+1;
1417 					P_SpawnPlayer(&playerstarts[RebornPosition][i]);
1418 
1419 					// Restore proper player type
1420 					playerstarts[RebornPosition][i].type = i+1;
1421 
1422 					foundSpot = true;
1423 					break;
1424 				}
1425 			}
1426 		}
1427 
1428 		if(foundSpot == false)
1429 		{ // Player's going to be inside something
1430 			P_SpawnPlayer(&playerstarts[RebornPosition][playernum]);
1431 		}
1432 
1433 		// Restore keys and weapons
1434 		players[playernum].keys = oldKeys;
1435 		players[playernum].pieces = oldPieces;
1436 		for(bestWeapon = 0, i = 0; i < NUMWEAPONS; i++)
1437 		{
1438 			if(oldWeaponowned[i])
1439 			{
1440 				bestWeapon = i;
1441 				players[playernum].weaponowned[i] = true;
1442 			}
1443 		}
1444 		players[playernum].mana[MANA_1] = 25;
1445 		players[playernum].mana[MANA_2] = 25;
1446 		if(bestWeapon)
1447 		{ // Bring up the best weapon
1448 			players[playernum].pendingweapon = bestWeapon;
1449 		}
1450 	}
1451 }
1452 
G_ScreenShot(void)1453 void G_ScreenShot (void)
1454 {
1455 	gameaction = ga_screenshot;
1456 }
1457 
1458 //==========================================================================
1459 //
1460 // G_StartNewInit
1461 //
1462 //==========================================================================
1463 
G_StartNewInit(void)1464 void G_StartNewInit(void)
1465 {
1466 	SV_InitBaseSlot();
1467 	SV_ClearRebornSlot();
1468 	P_ACSInitNewGame();
1469 	// Default the player start spot group to 0
1470 	RebornPosition = 0;
1471 }
1472 
1473 //==========================================================================
1474 //
1475 // G_StartNewGame
1476 //
1477 //==========================================================================
1478 
G_StartNewGame(skill_t skill)1479 void G_StartNewGame(skill_t skill)
1480 {
1481 	int realMap;
1482 
1483 	G_StartNewInit();
1484 	realMap = P_TranslateMap(1);
1485 	if(realMap == -1)
1486 	{
1487 		realMap = 1;
1488 	}
1489 	G_InitNew(TempSkill, 1, realMap);
1490 }
1491 
1492 //==========================================================================
1493 //
1494 // G_TeleportNewMap
1495 //
1496 // Only called by the warp cheat code.  Works just like normal map to map
1497 // teleporting, but doesn't do any interlude stuff.
1498 //
1499 //==========================================================================
1500 
G_TeleportNewMap(int map,int position)1501 void G_TeleportNewMap(int map, int position)
1502 {
1503 	gameaction = ga_leavemap;
1504 	LeaveMap = map;
1505 	LeavePosition = position;
1506 }
1507 
1508 //==========================================================================
1509 //
1510 // G_DoTeleportNewMap
1511 //
1512 //==========================================================================
1513 
G_DoTeleportNewMap(void)1514 void G_DoTeleportNewMap(void)
1515 {
1516 	SV_MapTeleport(LeaveMap, LeavePosition);
1517 	gamestate = GS_LEVEL;
1518 	gameaction = ga_nothing;
1519 	RebornPosition = LeavePosition;
1520 }
1521 
1522 /*
1523 boolean secretexit;
1524 void G_ExitLevel (void)
1525 {
1526 	secretexit = false;
1527 	gameaction = ga_completed;
1528 }
1529 void G_SecretExitLevel (void)
1530 {
1531 	secretexit = true;
1532 	gameaction = ga_completed;
1533 }
1534 */
1535 
1536 //==========================================================================
1537 //
1538 // G_Completed
1539 //
1540 // Starts intermission routine, which is used only during hub exits,
1541 // and DeathMatch games.
1542 //==========================================================================
1543 
G_Completed(int map,int position)1544 void G_Completed(int map, int position)
1545 {
1546 	gameaction = ga_completed;
1547 	LeaveMap = map;
1548 	LeavePosition = position;
1549 }
1550 
G_DoCompleted(void)1551 void G_DoCompleted(void)
1552 {
1553 	int i;
1554 
1555 	gameaction = ga_nothing;
1556 	if(G_CheckDemoStatus())
1557 	{
1558 		return;
1559 	}
1560 	for(i = 0; i < MAXPLAYERS; i++)
1561 	{
1562 		if(playeringame[i])
1563 		{
1564 			G_PlayerExitMap(i);
1565 		}
1566 	}
1567 	if(LeaveMap == -1 && LeavePosition == -1)
1568 	{
1569 		gameaction = ga_victory;
1570 		return;
1571 	}
1572 	else
1573 	{
1574 		gamestate = GS_INTERMISSION;
1575 		IN_Start();
1576 	}
1577 
1578 /*
1579 	int i;
1580 	static int afterSecret[3] = { 7, 5, 5 };
1581 
1582 	gameaction = ga_nothing;
1583 	if(G_CheckDemoStatus())
1584 	{
1585 		return;
1586 	}
1587 	for(i = 0; i < MAXPLAYERS; i++)
1588 	{
1589 		if(playeringame[i])
1590 		{
1591 			G_PlayerFinishLevel(i);
1592 		}
1593 	}
1594 	prevmap = gamemap;
1595 	if(secretexit == true)
1596 	{
1597 		gamemap = 9;
1598 	}
1599 	else if(gamemap == 9)
1600 	{ // Finished secret level
1601 		gamemap = afterSecret[gameepisode-1];
1602 	}
1603 	else if(gamemap == 8)
1604 	{
1605 		gameaction = ga_victory;
1606 		return;
1607 	}
1608 	else
1609 	{
1610 		gamemap++;
1611 	}
1612 	gamestate = GS_INTERMISSION;
1613 	IN_Start();
1614 */
1615 }
1616 
1617 //============================================================================
1618 //
1619 // G_WorldDone
1620 //
1621 //============================================================================
1622 
G_WorldDone(void)1623 void G_WorldDone(void)
1624 {
1625 	gameaction = ga_worlddone;
1626 }
1627 
1628 //============================================================================
1629 //
1630 // G_DoWorldDone
1631 //
1632 //============================================================================
1633 
G_DoWorldDone(void)1634 void G_DoWorldDone(void)
1635 {
1636 	gamestate = GS_LEVEL;
1637 	G_DoLoadLevel();
1638 	gameaction = ga_nothing;
1639 	viewactive = true;
1640 }
1641 
1642 //==========================================================================
1643 //
1644 // G_DoSingleReborn
1645 //
1646 // Called by G_Ticker based on gameaction.  Loads a game from the reborn
1647 // save slot.
1648 //
1649 //==========================================================================
1650 
G_DoSingleReborn(void)1651 void G_DoSingleReborn(void)
1652 {
1653 	gameaction = ga_nothing;
1654 	SV_LoadGame(SV_GetRebornSlot());
1655 	SB_SetClassData();
1656 }
1657 
1658 //==========================================================================
1659 //
1660 // G_LoadGame
1661 //
1662 // Can be called by the startup code or the menu task.
1663 //
1664 //==========================================================================
1665 
1666 static int GameLoadSlot;
1667 
G_LoadGame(int slot)1668 void G_LoadGame(int slot)
1669 {
1670 	GameLoadSlot = slot;
1671 	gameaction = ga_loadgame;
1672 }
1673 
1674 //==========================================================================
1675 //
1676 // G_DoLoadGame
1677 //
1678 // Called by G_Ticker based on gameaction.
1679 //
1680 //==========================================================================
1681 
G_DoLoadGame(void)1682 void G_DoLoadGame(void)
1683 {
1684 	gameaction = ga_nothing;
1685 	SV_LoadGame(GameLoadSlot);
1686 	if(!netgame)
1687 	{ // Copy the base slot to the reborn slot
1688 		SV_UpdateRebornSlot();
1689 	}
1690 	SB_SetClassData();
1691 }
1692 
1693 //==========================================================================
1694 //
1695 // G_SaveGame
1696 //
1697 // Called by the menu task.  <description> is a 24 byte text string.
1698 //
1699 //==========================================================================
1700 
G_SaveGame(int slot,char * description)1701 void G_SaveGame(int slot, char *description)
1702 {
1703 	savegameslot = slot;
1704 	strcpy(savedescription, description);
1705 	sendsave = true;
1706 }
1707 
1708 //==========================================================================
1709 //
1710 // G_DoSaveGame
1711 //
1712 // Called by G_Ticker based on gameaction.
1713 //
1714 //==========================================================================
1715 
G_DoSaveGame(void)1716 void G_DoSaveGame(void)
1717 {
1718 	SV_SaveGame(savegameslot, savedescription);
1719 	gameaction = ga_nothing;
1720 	savedescription[0] = 0;
1721 	P_SetMessage(&players[consoleplayer], TXT_GAMESAVED, true);
1722 }
1723 
1724 //==========================================================================
1725 //
1726 // G_DeferredNewGame
1727 //
1728 //==========================================================================
1729 
G_DeferredNewGame(skill_t skill)1730 void G_DeferredNewGame(skill_t skill)
1731 {
1732 	TempSkill = skill;
1733 	gameaction = ga_newgame;
1734 }
1735 
1736 //==========================================================================
1737 //
1738 // G_DoNewGame
1739 //
1740 //==========================================================================
1741 
G_DoNewGame(void)1742 void G_DoNewGame(void)
1743 {
1744 	G_StartNewGame(TempSkill);
1745 	gameaction = ga_nothing;
1746 }
1747 
1748 /*
1749 ====================
1750 =
1751 = G_InitNew
1752 =
1753 = Can be called by the startup code or the menu task
1754 = consoleplayer, displayplayer, playeringame[] should be set
1755 ====================
1756 */
1757 
G_DeferedInitNew(skill_t skill,int episode,int map)1758 void G_DeferedInitNew(skill_t skill, int episode, int map)
1759 {
1760 	TempSkill = skill;
1761 	TempEpisode = episode;
1762 	TempMap = map;
1763 	gameaction = ga_initnew;
1764 }
1765 
G_DoInitNew(void)1766 void G_DoInitNew(void)
1767 {
1768 	SV_InitBaseSlot();
1769 	G_InitNew(TempSkill, TempEpisode, TempMap);
1770 	gameaction = ga_nothing;
1771 }
1772 
G_InitNew(skill_t skill,int episode,int map)1773 void G_InitNew(skill_t skill, int episode, int map)
1774 {
1775 	int i;
1776 
1777 	if(paused)
1778 	{
1779 		paused = false;
1780 		S_ResumeSound();
1781 	}
1782 	if(skill < sk_baby)
1783 	{
1784 		skill = sk_baby;
1785 	}
1786 	if(skill > sk_nightmare)
1787 	{
1788 		skill = sk_nightmare;
1789 	}
1790 	if(map < 1)
1791 	{
1792 		map = 1;
1793 	}
1794 	if(map > 99)
1795 	{
1796 		map = 99;
1797 	}
1798 	M_ClearRandom();
1799 	// Force players to be initialized upon first level load
1800 	for(i = 0; i < MAXPLAYERS; i++)
1801 	{
1802 		players[i].playerstate = PST_REBORN;
1803 		players[i].worldTimer = 0;
1804 	}
1805 
1806 	// Set up a bunch of globals
1807 	usergame = true; // will be set false if a demo
1808 	paused = false;
1809 	demorecording = false;
1810 	demoplayback = false;
1811 	viewactive = true;
1812 	gameepisode = episode;
1813 	gamemap = map;
1814 	gameskill = skill;
1815 	BorderNeedRefresh = true;
1816 
1817 	// Initialize the sky
1818 	R_InitSky(map);
1819 
1820 	// Give one null ticcmd_t
1821 	//gametic = 0;
1822 	//maketic = 1;
1823 	//for (i=0 ; i<MAXPLAYERS ; i++)
1824 	//	nettics[i] = 1; // one null event for this gametic
1825 	//memset (localcmds,0,sizeof(localcmds));
1826 	//memset (netcmds,0,sizeof(netcmds));
1827 
1828 	G_DoLoadLevel();
1829 }
1830 
1831 /*
1832 ===============================================================================
1833 
1834 							DEMO RECORDING
1835 
1836 ===============================================================================
1837 */
1838 
1839 #define DEMOMARKER      0x80
1840 
G_ReadDemoTiccmd(ticcmd_t * cmd)1841 void G_ReadDemoTiccmd (ticcmd_t *cmd)
1842 {
1843 	if (*demo_p == DEMOMARKER)
1844 	{       // end of demo data stream
1845 		G_CheckDemoStatus ();
1846 		return;
1847 	}
1848 	cmd->forwardmove = ((signed char)*demo_p++);
1849 	cmd->sidemove = ((signed char)*demo_p++);
1850 	cmd->angleturn = ((unsigned char)*demo_p++)<<8;
1851 	cmd->buttons = (unsigned char)*demo_p++;
1852 	cmd->lookfly = (unsigned char)*demo_p++;
1853 	cmd->arti = (unsigned char)*demo_p++;
1854 }
1855 
G_WriteDemoTiccmd(ticcmd_t * cmd)1856 void G_WriteDemoTiccmd (ticcmd_t *cmd)
1857 {
1858 	if (gamekeydown['q'])           // press q to end demo recording
1859 		G_CheckDemoStatus ();
1860 	*demo_p++ = cmd->forwardmove;
1861 	*demo_p++ = cmd->sidemove;
1862 	*demo_p++ = cmd->angleturn>>8;
1863 	*demo_p++ = cmd->buttons;
1864 	*demo_p++ = cmd->lookfly;
1865 	*demo_p++ = cmd->arti;
1866 	demo_p -= 6;
1867 	G_ReadDemoTiccmd (cmd);         // make SURE it is exactly the same
1868 }
1869 
1870 
1871 
1872 /*
1873 ===================
1874 =
1875 = G_RecordDemo
1876 =
1877 ===================
1878 */
1879 
G_RecordDemo(skill_t skill,int numplayers,int episode,int map,char * name)1880 void G_RecordDemo (skill_t skill, int numplayers, int episode, int map, char *name)
1881 {
1882 	int             i;
1883 
1884 	G_InitNew (skill, episode, map);
1885 	usergame = false;
1886 	strcpy (demoname, name);
1887 	strcat (demoname, ".lmp");
1888 	demobuffer = demo_p = Z_Malloc (0x20000,PU_STATIC,NULL);
1889 	*demo_p++ = skill;
1890 	*demo_p++ = episode;
1891 	*demo_p++ = map;
1892 
1893 	for (i=0 ; i<MAXPLAYERS ; i++)
1894 	{
1895 		*demo_p++ = playeringame[i];
1896 		*demo_p++ = PlayerClass[i];
1897 	}
1898 	demorecording = true;
1899 }
1900 
1901 
1902 /*
1903 ===================
1904 =
1905 = G_PlayDemo
1906 =
1907 ===================
1908 */
1909 
1910 char    *defdemoname;
1911 
G_DeferedPlayDemo(char * name)1912 void G_DeferedPlayDemo (char *name)
1913 {
1914 	defdemoname = name;
1915 	gameaction = ga_playdemo;
1916 }
1917 
G_DoPlayDemo(void)1918 void G_DoPlayDemo (void)
1919 {
1920 	skill_t skill;
1921 	int             i, episode, map;
1922 
1923 	gameaction = ga_nothing;
1924 	demobuffer = demo_p = W_CacheLumpName (defdemoname, PU_STATIC);
1925 	skill = *demo_p++;
1926 	episode = *demo_p++;
1927 	map = *demo_p++;
1928 
1929 	for (i=0 ; i<MAXPLAYERS ; i++)
1930 	{
1931 		playeringame[i] = *demo_p++;
1932 		PlayerClass[i] = *demo_p++;
1933 	}
1934 
1935 	// Initialize world info, etc.
1936 	G_StartNewInit();
1937 
1938 	precache = false;               // don't spend a lot of time in loadlevel
1939 	G_InitNew (skill, episode, map);
1940 	precache = true;
1941 	usergame = false;
1942 	demoplayback = true;
1943 }
1944 
1945 
1946 /*
1947 ===================
1948 =
1949 = G_TimeDemo
1950 =
1951 ===================
1952 */
1953 
G_TimeDemo(char * name)1954 void G_TimeDemo (char *name)
1955 {
1956 	skill_t skill;
1957 	int             episode, map;
1958 
1959 	demobuffer = demo_p = W_CacheLumpName (name, PU_STATIC);
1960 	skill = *demo_p++;
1961 	episode = *demo_p++;
1962 	map = *demo_p++;
1963 	G_InitNew (skill, episode, map);
1964 	usergame = false;
1965 	demoplayback = true;
1966 	timingdemo = true;
1967 	singletics = true;
1968 }
1969 
1970 
1971 /*
1972 ===================
1973 =
1974 = G_CheckDemoStatus
1975 =
1976 = Called after a death or level completion to allow demos to be cleaned up
1977 = Returns true if a new demo loop action will take place
1978 ===================
1979 */
1980 
G_CheckDemoStatus(void)1981 boolean G_CheckDemoStatus (void)
1982 {
1983 	int             endtime;
1984 
1985 	if (timingdemo)
1986 	{
1987 		endtime = I_GetTime ();
1988 		I_Error ("timed %i gametics in %i realtics",gametic
1989 		, endtime-starttime);
1990 	}
1991 
1992 	if (demoplayback)
1993 	{
1994 		if (singledemo)
1995 			I_Quit ();
1996 
1997 		Z_ChangeTag (demobuffer, PU_CACHE);
1998 		demoplayback = false;
1999 		H2_AdvanceDemo();
2000 		return true;
2001 	}
2002 
2003 	if (demorecording)
2004 	{
2005 		*demo_p++ = DEMOMARKER;
2006 		M_WriteFile (demoname, demobuffer, demo_p - demobuffer);
2007 		Z_Free (demobuffer);
2008 		demorecording = false;
2009 		I_Error ("Demo %s recorded",demoname);
2010 	}
2011 
2012 	return false;
2013 }
2014