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