2 //**************************************************************************
4 //** g_game.c : Heretic 2 : Raven Software, Corp.
11 //**************************************************************************
22 extern void R_InitSky(int map);
23 extern void P_PlayerNextArtifact(player_t *player);
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);
32 void G_DoReborn (int playernum);
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);
46 void H2_PageTicker(void);
47 void H2_AdvanceDemo(void);
49 extern boolean mn_SuicideConsole;
51 gameaction_t gameaction;
52 gamestate_t gamestate;
54 //boolean respawnmonsters;
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
64 boolean timingdemo; // if true, exit with report on completion
65 int starttime; // for comparative timing purposes
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];
75 // Position indicator for cooperative net-play reborn
78 int consoleplayer; // player taking events and displaying
79 int displayplayer; // view being displayed
81 int levelstarttic; // gametic at level start
84 boolean demorecording;
86 byte *demobuffer, *demo_p;
87 boolean singledemo; // quit after playing a demo from cmdline
89 boolean precache = true; // if true, load all graphics at start
91 short consistancy[MAXPLAYERS][BACKUPTICS];
94 // controls (have defaults)
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;
99 int key_flyup, key_flydown, key_flycenter;
100 int key_lookup, key_lookdown, key_lookcenter;
101 int key_invleft, key_invright, key_useartifact;
118 static int LeavePosition;
120 //#define MAXPLMOVE 0x32 // Old Heretic Max move
122 fixed_t MaxPlayerMove[NUMCLASSES] = { 0x3C, 0x32, 0x2D,
127 fixed_t forwardmove[NUMCLASSES][2] =
138 fixed_t sidemove[NUMCLASSES][2] =
149 fixed_t angleturn[3] = {640, 1280, 320}; // + slow turn
150 #define SLOWTURNTICS 6
153 boolean gamekeydown[NUMKEYS];
154 int turnheld; // for accelerative turning
158 boolean mousearray[4];
159 boolean *mousebuttons = &mousearray[1];
162 int mousex, mousey; // mouse values are used once
163 int dclicktime, dclickstate, dclicks;
164 int dclicktime2, dclickstate2, dclicks2;
166 int joyxmove, joyymove; // joystick values are repeated
168 boolean *joybuttons = &joyarray[1]; // allow [-1]
171 char savedescription[32];
176 static skill_t TempSkill;
177 static int TempEpisode;
180 //=============================================================================
186 = Builds a ticcmd from all of the available inputs or reads it from the
188 = If recording a demo, write it out
192 extern boolean inventory;
196 extern int isCyberPresent; // is CyberMan present?
197 boolean usearti = true;
198 void I_ReadCyberCmd (ticcmd_t *cmd);
200 void G_BuildTiccmd (ticcmd_t *cmd)
203 boolean strafe, bstrafe;
204 int speed, tspeed, lspeed;
210 extern boolean artiskip;
213 pClass = players[consoleplayer].class;
214 memset (cmd,0,sizeof(*cmd));
216 // cmd->consistancy =
217 // consistancy[consoleplayer][(maketic*ticdup)%BACKUPTICS];
220 consistancy[consoleplayer][maketic%BACKUPTICS];
222 //printf ("cons: %i\n",cmd->consistancy);
223 strafe = gamekeydown[key_strafe] || mousebuttons[mousebstrafe]
224 || joybuttons[joybstrafe];
226 speed = gamekeydown[key_speed] || joybuttons[joybspeed]
227 || joybuttons[joybspeed];
228 if(alwaysrun && !demoplayback && !demorecording)
230 forward = side = look = arti = flyheight = 0;
233 // use two stage accelerative turning on the keyboard and joystick
235 if (joyxmove < 0 || joyxmove > 0
236 || gamekeydown[key_right] || gamekeydown[key_left])
240 if (turnheld < SLOWTURNTICS)
241 tspeed = 2; // slow turn
245 if(gamekeydown[key_lookdown] || gamekeydown[key_lookup])
253 if(lookheld < SLOWTURNTICS)
263 // let movement keys cancel each other out
267 if (gamekeydown[key_right])
269 side += sidemove[pClass][speed];
271 if (gamekeydown[key_left])
273 side -= sidemove[pClass][speed];
277 side += sidemove[pClass][speed];
281 side -= sidemove[pClass][speed];
286 if (gamekeydown[key_right])
287 cmd->angleturn -= angleturn[tspeed];
288 if (gamekeydown[key_left])
289 cmd->angleturn += angleturn[tspeed];
291 cmd->angleturn -= angleturn[tspeed];
293 cmd->angleturn += angleturn[tspeed];
296 if (gamekeydown[key_up])
298 forward += forwardmove[pClass][speed];
300 if (gamekeydown[key_down])
302 forward -= forwardmove[pClass][speed];
306 forward += forwardmove[pClass][speed];
310 forward -= forwardmove[pClass][speed];
312 if (gamekeydown[key_straferight])
314 side += sidemove[pClass][speed];
316 if (gamekeydown[key_strafeleft])
318 side -= sidemove[pClass][speed];
321 // Look up/down/center keys
322 if(gamekeydown[key_lookup])
326 if(gamekeydown[key_lookdown])
330 if(gamekeydown[key_lookcenter])
335 // Fly up/down/drop keys
336 if(gamekeydown[key_flyup])
338 flyheight = 5; // note that the actual flyheight will be twice this
340 if(gamekeydown[key_flydown])
344 if(gamekeydown[key_flycenter])
346 flyheight = TOCENTER;
350 if(gamekeydown[key_useartifact])
352 if(gamekeydown[key_speed] && artiskip)
354 if(players[consoleplayer].inventory[inv_ptr].type != arti_none)
355 { // Skip an artifact
356 gamekeydown[key_useartifact] = false;
357 P_PlayerNextArtifact(&players[consoleplayer]);
364 players[consoleplayer].readyArtifact =
365 players[consoleplayer].inventory[inv_ptr].type;
373 players[consoleplayer].inventory[inv_ptr].type&AFLAG_MASK;
378 if(gamekeydown[key_jump] || mousebuttons[mousebjump]
379 || joybuttons[joybjump])
381 cmd->arti |= AFLAG_JUMP;
383 if(mn_SuicideConsole)
385 cmd->arti |= AFLAG_SUICIDE;
386 mn_SuicideConsole = false;
390 if(gamekeydown[KEY_BACKSPACE] && !cmd->arti)
392 gamekeydown[KEY_BACKSPACE] = false; // Use one of each artifact
393 cmd->arti = NUMARTIFACTS;
395 else if(gamekeydown[KEY_BACKSLASH] && !cmd->arti
396 && (players[consoleplayer].mo->health < MAXHEALTH))
398 gamekeydown[KEY_BACKSLASH] = false;
399 cmd->arti = arti_health;
401 else if(gamekeydown[KEY_ZERO] && !cmd->arti)
403 gamekeydown[KEY_ZERO] = false;
404 cmd->arti = arti_poisonbag;
406 else if(gamekeydown[KEY_NINE] && !cmd->arti)
408 gamekeydown[KEY_NINE] = false;
409 cmd->arti = arti_blastradius;
411 else if(gamekeydown[KEY_EIGHT] && !cmd->arti)
413 gamekeydown[KEY_EIGHT] = false;
414 cmd->arti = arti_teleport;
416 else if(gamekeydown[KEY_SEVEN] && !cmd->arti)
418 gamekeydown[KEY_SEVEN] = false;
419 cmd->arti = arti_teleportother;
421 else if(gamekeydown[KEY_SIX] && !cmd->arti)
423 gamekeydown[KEY_SIX] = false;
424 cmd->arti = arti_egg;
426 else if(gamekeydown[KEY_FIVE] && !cmd->arti
427 && !players[consoleplayer].powers[pw_invulnerability])
429 gamekeydown[KEY_FIVE] = false;
430 cmd->arti = arti_invulnerability;
436 cmd->chatchar = CT_dequeueChatChar();
437 if (gamekeydown[key_fire] || mousebuttons[mousebfire]
438 || joybuttons[joybfire])
439 cmd->buttons |= BT_ATTACK;
441 if (gamekeydown[key_use] || joybuttons[joybuse] )
443 cmd->buttons |= BT_USE;
444 dclicks = 0; // clear double clicks if hit use button
447 for(i = 0; i < NUMWEAPONS; i++)
449 if(gamekeydown['1'+i])
451 cmd->buttons |= BT_CHANGE;
452 cmd->buttons |= i<<BT_WEAPONSHIFT;
461 printf( "%d %d %d %d <%d %d>\n",
462 mousebuttons[mousebfire], mousebuttons[mousebforward],
463 mousebuttons[mousebjump], mousebuttons[mousebstrafe],
466 if (mousebuttons[mousebforward])
468 forward += forwardmove[pClass][speed];
472 // forward double click
474 if (mousebuttons[mousebforward] != dclickstate && dclicktime > 1 )
476 dclickstate = mousebuttons[mousebforward];
481 cmd->buttons |= BT_USE;
489 dclicktime += ticdup;
498 // strafe double click
500 bstrafe = mousebuttons[mousebstrafe]
501 || joybuttons[joybstrafe];
502 if (bstrafe != dclickstate2 && dclicktime2 > 1 )
504 dclickstate2 = bstrafe;
509 cmd->buttons |= BT_USE;
517 dclicktime2 += ticdup;
518 if (dclicktime2 > 20)
530 cmd->angleturn -= mousex*0x8;
533 if( demorecording || demoplayback || (mouselook == 0) )
539 // We'll directly change the viewing pitch of the console player.
540 float adj = ((mousey*0x4)<<16) / (float) ANGLE_180*180*110.0/85.0;
541 float newlookdir = 0; /* jim initialiser added to prevent warning */
543 adj *= 2; //Speed up the X11 mlook a little.
546 newlookdir = players[consoleplayer].lookdir + adj;
547 else if(mouselook == 2)
548 newlookdir = players[consoleplayer].lookdir - adj;
550 // vertical view angle taken from p_user.c line 249.
551 if( newlookdir > 90 )
553 if( newlookdir < -110 )
556 players[consoleplayer].lookdir = newlookdir;
561 if (forward > MaxPlayerMove[pClass])
563 forward = MaxPlayerMove[pClass];
565 else if (forward < -MaxPlayerMove[pClass])
567 forward = -MaxPlayerMove[pClass];
569 if (side > MaxPlayerMove[pClass])
571 side = MaxPlayerMove[pClass];
573 else if (side < -MaxPlayerMove[pClass])
575 side = -MaxPlayerMove[pClass];
577 if(players[consoleplayer].powers[pw_speed]
578 && !players[consoleplayer].morphTics)
579 { // Adjust for a player with a speed artifact
580 forward = (3*forward)>>1;
583 cmd->forwardmove += forward;
584 cmd->sidemove += side;
585 if(players[consoleplayer].playerstate == PST_LIVE)
597 cmd->lookfly |= flyheight<<4;
605 cmd->buttons = BT_SPECIAL | BTS_PAUSE;
611 cmd->buttons = BT_SPECIAL | BTS_SAVEGAME | (savegameslot<<BTS_SAVESHIFT);
624 void G_DoLoadLevel (void)
628 levelstarttic = gametic; // for time calculation
629 gamestate = GS_LEVEL;
630 for (i=0 ; i<MAXPLAYERS ; i++)
632 if (playeringame[i] && players[i].playerstate == PST_DEAD)
633 players[i].playerstate = PST_REBORN;
634 memset (players[i].frags,0,sizeof(players[i].frags));
637 SN_StopAllSequences();
638 P_SetupLevel (gameepisode, gamemap, 0, gameskill);
639 displayplayer = consoleplayer; // view the guy you are playing
640 starttime = I_GetTime ();
641 gameaction = ga_nothing;
645 // clear cmd building stuff
648 memset (gamekeydown, 0, sizeof(gamekeydown));
649 joyxmove = joyymove = 0;
651 sendpause = sendsave = paused = false;
652 memset (mousebuttons, 0, sizeof(mousebuttons));
653 memset (joybuttons, 0, sizeof(joybuttons));
658 ===============================================================================
662 = get info needed to make ticcmd_ts for the players
664 ===============================================================================
667 boolean G_Responder(event_t *ev)
670 extern boolean MenuActive;
672 plr = &players[consoleplayer];
673 if(ev->type == ev_keyup && ev->data1 == key_useartifact)
674 { // flag to denote that it's okay to use an artifact
677 plr->readyArtifact = plr->inventory[inv_ptr].type;
682 // Check for spy mode player cycle
683 if(gamestate == GS_LEVEL && ev->type == ev_keydown
684 && ev->data1 == KEY_F12 && !deathmatch)
685 { // Cycle the display player
689 if(displayplayer == MAXPLAYERS)
693 } while(!playeringame[displayplayer]
694 && displayplayer != consoleplayer);
699 { // Chat ate the event
702 if(gamestate == GS_LEVEL)
705 { // Status bar ate the event
709 { // Automap ate the event
717 if(ev->data1 == key_invleft)
719 inventoryTics = 5*35;
740 if(ev->data1 == key_invright)
742 inventoryTics = 5*35;
749 if(inv_ptr >= plr->inventorySlotNum)
765 if(ev->data1 == KEY_PAUSE && !MenuActive)
770 if(ev->data1 < NUMKEYS)
772 gamekeydown[ev->data1] = true;
774 return(true); // eat key down events
777 if(ev->data1 < NUMKEYS)
779 gamekeydown[ev->data1] = false;
781 return(false); // always let key up events filter down
785 mousebuttons[0] = ev->data1&1;
786 mousebuttons[1] = ev->data1&2;
787 mousebuttons[2] = ev->data1&4;
788 mousex = ev->data2*(mouseSensitivity+5)/10;
789 mousey = ev->data3*(mouseSensitivity+5)/10;
790 return(true); // eat events
793 joybuttons[0] = ev->data1&1;
794 joybuttons[1] = ev->data1&2;
795 joybuttons[2] = ev->data1&4;
796 joybuttons[3] = ev->data1&8;
797 joyxmove = ev->data2;
798 joyymove = ev->data3;
799 return(true); // eat events
808 //==========================================================================
812 //==========================================================================
820 // do player reborns if needed
822 for (i=0 ; i<MAXPLAYERS ; i++)
823 if (playeringame[i] && players[i].playerstate == PST_REBORN)
827 // do things to change the game state
829 while (gameaction != ga_nothing)
850 case ga_singlereborn:
858 gameaction = ga_nothing;
862 G_DoTeleportNewMap();
880 // get commands, check consistancy, and build new consistancy check
882 //buf = gametic%BACKUPTICS;
885 buf = (gametic/ticdup)%BACKUPTICS;
887 for (i=0 ; i<MAXPLAYERS ; i++)
890 cmd = &players[i].cmd;
892 memcpy (cmd, &netcmds[i][buf], sizeof(ticcmd_t));
895 G_ReadDemoTiccmd (cmd);
897 G_WriteDemoTiccmd (cmd);
899 if (netgame && !(gametic%ticdup) )
901 if (gametic > BACKUPTICS
902 && consistancy[i][buf] != cmd->consistancy)
904 I_Error ("consistency failure (%i should be %i)",cmd->consistancy, consistancy[i][buf]);
907 consistancy[i][buf] = players[i].mo->x;
909 consistancy[i][buf] = rndindex;
914 // check for special buttons
916 for (i=0 ; i<MAXPLAYERS ; i++)
919 if (players[i].cmd.buttons & BT_SPECIAL)
921 switch (players[i].cmd.buttons & BT_SPECIALMASK)
936 if (!savedescription[0])
940 strcpy (savedescription, "NET GAME");
944 strcpy(savedescription, "SAVE GAME");
948 (players[i].cmd.buttons & BTS_SAVEMASK)>>BTS_SAVESHIFT;
949 gameaction = ga_savegame;
955 // turn inventory off after a certain amount of time
956 if(inventory && !(--inventoryTics))
958 players[consoleplayer].readyArtifact =
959 players[consoleplayer].inventory[inv_ptr].type;
977 case GS_INTERMISSION:
991 ==============================================================================
993 PLAYER STRUCTURE FUNCTIONS
995 also see P_SpawnPlayer in P_Things
996 ==============================================================================
999 //==========================================================================
1003 // Called when the player leaves a map.
1005 //==========================================================================
1007 void G_PlayerExitMap(int playerNumber)
1013 player = &players[playerNumber];
1017 // // Strip all but one of each type of artifact
1018 // for(i = 0; i < player->inventorySlotNum; i++)
1020 // player->inventory[i].count = 1;
1022 // player->artifactCount = player->inventorySlotNum;
1026 // Strip all current powers (retain flight)
1027 flightPower = player->powers[pw_flight];
1028 memset(player->powers, 0, sizeof(player->powers));
1029 player->powers[pw_flight] = flightPower;
1033 player->powers[pw_flight] = 0;
1037 if(P_GetMapCluster(gamemap) != P_GetMapCluster(LeaveMap))
1038 { // Entering new cluster
1042 // Strip flight artifact
1043 for(i = 0; i < 25; i++)
1045 player->powers[pw_flight] = 0;
1046 P_PlayerUseArtifact(player, arti_fly);
1048 player->powers[pw_flight] = 0;
1052 if(player->morphTics)
1054 player->readyweapon = player->mo->special1; // Restore weapon
1055 player->morphTics = 0;
1057 player->messageTics = 0;
1058 player->lookdir = 0;
1059 player->mo->flags &= ~MF_SHADOW; // Remove invisibility
1060 player->extralight = 0; // Remove weapon flashes
1061 player->fixedcolormap = 0; // Remove torch
1062 player->damagecount = 0; // No palette changes
1063 player->bonuscount = 0;
1064 player->poisoncount = 0;
1065 if(player == &players[consoleplayer])
1067 SB_state = -1; // refresh the status bar
1068 viewangleoffset = 0;
1072 //==========================================================================
1076 // Called after a player dies. Almost everything is cleared and
1079 //==========================================================================
1081 void G_PlayerReborn(int player)
1084 int frags[MAXPLAYERS];
1085 int killcount, itemcount, secretcount;
1088 memcpy(frags, players[player].frags, sizeof(frags));
1089 killcount = players[player].killcount;
1090 itemcount = players[player].itemcount;
1091 secretcount = players[player].secretcount;
1092 worldTimer = players[player].worldTimer;
1094 p = &players[player];
1095 memset(p, 0, sizeof(*p));
1097 memcpy(players[player].frags, frags, sizeof(players[player].frags));
1098 players[player].killcount = killcount;
1099 players[player].itemcount = itemcount;
1100 players[player].secretcount = secretcount;
1101 players[player].worldTimer = worldTimer;
1102 players[player].class = PlayerClass[player];
1104 p->usedown = p->attackdown = true; // don't do anything immediately
1105 p->playerstate = PST_LIVE;
1106 p->health = MAXHEALTH;
1107 p->readyweapon = p->pendingweapon = WP_FIRST;
1108 p->weaponowned[WP_FIRST] = true;
1111 localQuakeHappening[player] = false;
1112 if(p == &players[consoleplayer])
1114 SB_state = -1; // refresh the status bar
1115 inv_ptr = 0; // reset the inventory pointer
1117 viewangleoffset = 0;
1122 ====================
1126 = Returns false if the player cannot be respawned at the given mapthing_t spot
1127 = because something is occupying it
1128 ====================
1131 void P_SpawnPlayer (mapthing_t *mthing);
1133 boolean G_CheckSpot (int playernum, mapthing_t *mthing)
1140 x = mthing->x << FRACBITS;
1141 y = mthing->y << FRACBITS;
1143 players[playernum].mo->flags2 &= ~MF2_PASSMOBJ;
1144 if (!P_CheckPosition (players[playernum].mo, x, y) )
1146 players[playernum].mo->flags2 |= MF2_PASSMOBJ;
1149 players[playernum].mo->flags2 |= MF2_PASSMOBJ;
1151 // spawn a teleport fog
1152 ss = R_PointInSubsector (x,y);
1153 an = ( ANG45 * (mthing->angle/45) ) >> ANGLETOFINESHIFT;
1155 mo = P_SpawnMobj (x+20*finecosine[an], y+20*finesine[an],
1156 ss->sector->floorheight+TELEFOGHEIGHT, MT_TFOG);
1158 if (players[consoleplayer].viewz != 1)
1159 S_StartSound (mo, SFX_TELEPORT); // don't start sound on first frame
1165 ====================
1167 = G_DeathMatchSpawnPlayer
1169 = Spawns a player at one of the random death match spots
1170 = called at level load and each death
1171 ====================
1174 void G_DeathMatchSpawnPlayer (int playernum)
1179 selections = deathmatch_p - deathmatchstarts;
1181 // This check has been moved to p_setup.c:P_LoadThings()
1182 //if (selections < 8)
1183 // I_Error ("Only %i deathmatch spots, 8 required", selections);
1185 for (j=0 ; j<20 ; j++)
1187 i = P_Random() % selections;
1188 if (G_CheckSpot (playernum, &deathmatchstarts[i]) )
1190 deathmatchstarts[i].type = playernum+1;
1191 P_SpawnPlayer (&deathmatchstarts[i]);
1196 // no good spot, so the player will probably get stuck
1197 P_SpawnPlayer (&playerstarts[0][playernum]);
1200 //==========================================================================
1204 //==========================================================================
1206 void G_DoReborn(int playernum)
1209 boolean oldWeaponowned[NUMWEAPONS];
1215 if(G_CheckDemoStatus())
1221 if(SV_RebornSlotAvailable())
1222 { // Use the reborn code if the slot is available
1223 gameaction = ga_singlereborn;
1226 { // Start a new game if there's no reborn info
1227 gameaction = ga_newgame;
1232 players[playernum].mo->player = NULL; // Dissassociate the corpse
1235 { // Spawn at random spot if in death match
1236 G_DeathMatchSpawnPlayer(playernum);
1240 // Cooperative net-play, retain keys and weapons
1241 oldKeys = players[playernum].keys;
1242 oldPieces = players[playernum].pieces;
1243 for(i = 0; i < NUMWEAPONS; i++)
1245 oldWeaponowned[i] = players[playernum].weaponowned[i];
1249 if(G_CheckSpot(playernum,
1250 &playerstarts[RebornPosition][playernum]))
1251 { // Appropriate player start spot is open
1252 P_SpawnPlayer(&playerstarts[RebornPosition][playernum]);
1257 // Try to spawn at one of the other player start spots
1258 for(i = 0; i < MAXPLAYERS; i++)
1260 if(G_CheckSpot(playernum, &playerstarts[RebornPosition][i]))
1261 { // Found an open start spot
1263 // Fake as other player
1264 playerstarts[RebornPosition][i].type = playernum+1;
1265 P_SpawnPlayer(&playerstarts[RebornPosition][i]);
1267 // Restore proper player type
1268 playerstarts[RebornPosition][i].type = i+1;
1276 if(foundSpot == false)
1277 { // Player's going to be inside something
1278 P_SpawnPlayer(&playerstarts[RebornPosition][playernum]);
1281 // Restore keys and weapons
1282 players[playernum].keys = oldKeys;
1283 players[playernum].pieces = oldPieces;
1284 for(bestWeapon = 0, i = 0; i < NUMWEAPONS; i++)
1286 if(oldWeaponowned[i])
1289 players[playernum].weaponowned[i] = true;
1292 players[playernum].mana[MANA_1] = 25;
1293 players[playernum].mana[MANA_2] = 25;
1295 { // Bring up the best weapon
1296 players[playernum].pendingweapon = bestWeapon;
1301 void G_ScreenShot (void)
1303 gameaction = ga_screenshot;
1306 //==========================================================================
1310 //==========================================================================
1312 void G_StartNewInit(void)
1315 SV_ClearRebornSlot();
1317 // Default the player start spot group to 0
1321 //==========================================================================
1325 //==========================================================================
1327 void G_StartNewGame(skill_t skill)
1332 realMap = P_TranslateMap(1);
1337 G_InitNew(TempSkill, 1, realMap);
1340 //==========================================================================
1344 // Only called by the warp cheat code. Works just like normal map to map
1345 // teleporting, but doesn't do any interlude stuff.
1347 //==========================================================================
1349 void G_TeleportNewMap(int map, int position)
1351 gameaction = ga_leavemap;
1353 LeavePosition = position;
1356 //==========================================================================
1358 // G_DoTeleportNewMap
1360 //==========================================================================
1362 void G_DoTeleportNewMap(void)
1364 SV_MapTeleport(LeaveMap, LeavePosition);
1365 gamestate = GS_LEVEL;
1366 gameaction = ga_nothing;
1367 RebornPosition = LeavePosition;
1372 void G_ExitLevel (void)
1375 gameaction = ga_completed;
1377 void G_SecretExitLevel (void)
1380 gameaction = ga_completed;
1384 //==========================================================================
1388 // Starts intermission routine, which is used only during hub exits,
1389 // and DeathMatch games.
1390 //==========================================================================
1392 void G_Completed(int map, int position)
1394 gameaction = ga_completed;
1396 LeavePosition = position;
1399 void G_DoCompleted(void)
1403 gameaction = ga_nothing;
1404 if(G_CheckDemoStatus())
1408 for(i = 0; i < MAXPLAYERS; i++)
1415 if(LeaveMap == -1 && LeavePosition == -1)
1417 gameaction = ga_victory;
1422 gamestate = GS_INTERMISSION;
1428 static int afterSecret[3] = { 7, 5, 5 };
1430 gameaction = ga_nothing;
1431 if(G_CheckDemoStatus())
1435 for(i = 0; i < MAXPLAYERS; i++)
1439 G_PlayerFinishLevel(i);
1443 if(secretexit == true)
1447 else if(gamemap == 9)
1448 { // Finished secret level
1449 gamemap = afterSecret[gameepisode-1];
1451 else if(gamemap == 8)
1453 gameaction = ga_victory;
1460 gamestate = GS_INTERMISSION;
1465 //============================================================================
1469 //============================================================================
1471 void G_WorldDone(void)
1473 gameaction = ga_worlddone;
1476 //============================================================================
1480 //============================================================================
1482 void G_DoWorldDone(void)
1484 gamestate = GS_LEVEL;
1486 gameaction = ga_nothing;
1490 //==========================================================================
1494 // Called by G_Ticker based on gameaction. Loads a game from the reborn
1497 //==========================================================================
1499 void G_DoSingleReborn(void)
1501 gameaction = ga_nothing;
1502 SV_LoadGame(SV_GetRebornSlot());
1506 //==========================================================================
1510 // Can be called by the startup code or the menu task.
1512 //==========================================================================
1514 static int GameLoadSlot;
1516 void G_LoadGame(int slot)
1518 GameLoadSlot = slot;
1519 gameaction = ga_loadgame;
1522 //==========================================================================
1526 // Called by G_Ticker based on gameaction.
1528 //==========================================================================
1530 void G_DoLoadGame(void)
1532 gameaction = ga_nothing;
1533 SV_LoadGame(GameLoadSlot);
1535 { // Copy the base slot to the reborn slot
1536 SV_UpdateRebornSlot();
1541 //==========================================================================
1545 // Called by the menu task. <description> is a 24 byte text string.
1547 //==========================================================================
1549 void G_SaveGame(int slot, char *description)
1551 savegameslot = slot;
1552 strcpy(savedescription, description);
1556 //==========================================================================
1560 // Called by G_Ticker based on gameaction.
1562 //==========================================================================
1564 void G_DoSaveGame(void)
1566 SV_SaveGame(savegameslot, savedescription);
1567 gameaction = ga_nothing;
1568 savedescription[0] = 0;
1569 P_SetMessage(&players[consoleplayer], TXT_GAMESAVED, true);
1572 //==========================================================================
1574 // G_DeferredNewGame
1576 //==========================================================================
1578 void G_DeferredNewGame(skill_t skill)
1581 gameaction = ga_newgame;
1584 //==========================================================================
1588 //==========================================================================
1590 void G_DoNewGame(void)
1592 G_StartNewGame(TempSkill);
1593 gameaction = ga_nothing;
1597 ====================
1601 = Can be called by the startup code or the menu task
1602 = consoleplayer, displayplayer, playeringame[] should be set
1603 ====================
1606 void G_DeferedInitNew(skill_t skill, int episode, int map)
1609 TempEpisode = episode;
1611 gameaction = ga_initnew;
1614 void G_DoInitNew(void)
1617 G_InitNew(TempSkill, TempEpisode, TempMap);
1618 gameaction = ga_nothing;
1621 void G_InitNew(skill_t skill, int episode, int map)
1634 if(skill > sk_nightmare)
1636 skill = sk_nightmare;
1647 // Force players to be initialized upon first level load
1648 for(i = 0; i < MAXPLAYERS; i++)
1650 players[i].playerstate = PST_REBORN;
1651 players[i].worldTimer = 0;
1654 // Set up a bunch of globals
1655 usergame = true; // will be set false if a demo
1657 demorecording = false;
1658 demoplayback = false;
1660 gameepisode = episode;
1663 BorderNeedRefresh = true;
1665 // Initialize the sky
1668 // Give one null ticcmd_t
1671 //for (i=0 ; i<MAXPLAYERS ; i++)
1672 // nettics[i] = 1; // one null event for this gametic
1673 //memset (localcmds,0,sizeof(localcmds));
1674 //memset (netcmds,0,sizeof(netcmds));
1680 ===============================================================================
1684 ===============================================================================
1687 #define DEMOMARKER 0x80
1689 void G_ReadDemoTiccmd (ticcmd_t *cmd)
1691 if (*demo_p == DEMOMARKER)
1692 { // end of demo data stream
1693 G_CheckDemoStatus ();
1696 cmd->forwardmove = ((signed char)*demo_p++);
1697 cmd->sidemove = ((signed char)*demo_p++);
1698 cmd->angleturn = ((unsigned char)*demo_p++)<<8;
1699 cmd->buttons = (unsigned char)*demo_p++;
1700 cmd->lookfly = (unsigned char)*demo_p++;
1701 cmd->arti = (unsigned char)*demo_p++;
1704 void G_WriteDemoTiccmd (ticcmd_t *cmd)
1706 if (gamekeydown['q']) // press q to end demo recording
1707 G_CheckDemoStatus ();
1708 *demo_p++ = cmd->forwardmove;
1709 *demo_p++ = cmd->sidemove;
1710 *demo_p++ = cmd->angleturn>>8;
1711 *demo_p++ = cmd->buttons;
1712 *demo_p++ = cmd->lookfly;
1713 *demo_p++ = cmd->arti;
1715 G_ReadDemoTiccmd (cmd); // make SURE it is exactly the same
1728 void G_RecordDemo (skill_t skill, int numplayers, int episode, int map, char *name)
1732 G_InitNew (skill, episode, map);
1734 strcpy (demoname, name);
1735 strcat (demoname, ".lmp");
1736 demobuffer = demo_p = Z_Malloc (0x20000,PU_STATIC,NULL);
1738 *demo_p++ = episode;
1741 for (i=0 ; i<MAXPLAYERS ; i++)
1743 *demo_p++ = playeringame[i];
1744 *demo_p++ = PlayerClass[i];
1746 demorecording = true;
1760 void G_DeferedPlayDemo (char *name)
1763 gameaction = ga_playdemo;
1766 void G_DoPlayDemo (void)
1769 int i, episode, map;
1771 gameaction = ga_nothing;
1772 demobuffer = demo_p = W_CacheLumpName (defdemoname, PU_STATIC);
1774 episode = *demo_p++;
1777 for (i=0 ; i<MAXPLAYERS ; i++)
1779 playeringame[i] = *demo_p++;
1780 PlayerClass[i] = *demo_p++;
1783 // Initialize world info, etc.
1786 precache = false; // don't spend a lot of time in loadlevel
1787 G_InitNew (skill, episode, map);
1790 demoplayback = true;
1802 void G_TimeDemo (char *name)
1807 demobuffer = demo_p = W_CacheLumpName (name, PU_STATIC);
1809 episode = *demo_p++;
1811 G_InitNew (skill, episode, map);
1813 demoplayback = true;
1824 = Called after a death or level completion to allow demos to be cleaned up
1825 = Returns true if a new demo loop action will take place
1829 boolean G_CheckDemoStatus (void)
1835 endtime = I_GetTime ();
1836 I_Error ("timed %i gametics in %i realtics",gametic
1837 , endtime-starttime);
1845 Z_ChangeTag (demobuffer, PU_CACHE);
1846 demoplayback = false;
1853 *demo_p++ = DEMOMARKER;
1854 M_WriteFile (demoname, demobuffer, demo_p - demobuffer);
1855 Z_Free (demobuffer);
1856 demorecording = false;
1857 I_Error ("Demo %s recorded",demoname);