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,
125 fixed_t forwardmove[NUMCLASSES][2] =
134 fixed_t sidemove[NUMCLASSES][2] =
143 fixed_t angleturn[3] = {640, 1280, 320}; // + slow turn
144 #define SLOWTURNTICS 6
147 boolean gamekeydown[NUMKEYS];
148 int turnheld; // for accelerative turning
152 boolean mousearray[4];
153 boolean *mousebuttons = &mousearray[1];
156 int mousex, mousey; // mouse values are used once
157 int dclicktime, dclickstate, dclicks;
158 int dclicktime2, dclickstate2, dclicks2;
160 int joyxmove, joyymove; // joystick values are repeated
162 boolean *joybuttons = &joyarray[1]; // allow [-1]
165 char savedescription[32];
170 static skill_t TempSkill;
171 static int TempEpisode;
174 //=============================================================================
180 = Builds a ticcmd from all of the available inputs or reads it from the
182 = If recording a demo, write it out
186 extern boolean inventory;
190 extern int isCyberPresent; // is CyberMan present?
191 boolean usearti = true;
192 void I_ReadCyberCmd (ticcmd_t *cmd);
194 void G_BuildTiccmd (ticcmd_t *cmd)
197 boolean strafe, bstrafe;
198 int speed, tspeed, lspeed;
204 extern boolean artiskip;
207 pClass = players[consoleplayer].class;
208 memset (cmd,0,sizeof(*cmd));
210 // cmd->consistancy =
211 // consistancy[consoleplayer][(maketic*ticdup)%BACKUPTICS];
214 consistancy[consoleplayer][maketic%BACKUPTICS];
216 //printf ("cons: %i\n",cmd->consistancy);
217 strafe = gamekeydown[key_strafe] || mousebuttons[mousebstrafe]
218 || joybuttons[joybstrafe];
220 speed = gamekeydown[key_speed] || joybuttons[joybspeed]
221 || joybuttons[joybspeed];
222 if(alwaysrun && !demoplayback && !demorecording)
224 forward = side = look = arti = flyheight = 0;
227 // use two stage accelerative turning on the keyboard and joystick
229 if (joyxmove < 0 || joyxmove > 0
230 || gamekeydown[key_right] || gamekeydown[key_left])
234 if (turnheld < SLOWTURNTICS)
235 tspeed = 2; // slow turn
239 if(gamekeydown[key_lookdown] || gamekeydown[key_lookup])
247 if(lookheld < SLOWTURNTICS)
257 // let movement keys cancel each other out
261 if (gamekeydown[key_right])
263 side += sidemove[pClass][speed];
265 if (gamekeydown[key_left])
267 side -= sidemove[pClass][speed];
271 side += sidemove[pClass][speed];
275 side -= sidemove[pClass][speed];
280 if (gamekeydown[key_right])
281 cmd->angleturn -= angleturn[tspeed];
282 if (gamekeydown[key_left])
283 cmd->angleturn += angleturn[tspeed];
285 cmd->angleturn -= angleturn[tspeed];
287 cmd->angleturn += angleturn[tspeed];
290 if (gamekeydown[key_up])
292 forward += forwardmove[pClass][speed];
294 if (gamekeydown[key_down])
296 forward -= forwardmove[pClass][speed];
300 forward += forwardmove[pClass][speed];
304 forward -= forwardmove[pClass][speed];
306 if (gamekeydown[key_straferight])
308 side += sidemove[pClass][speed];
310 if (gamekeydown[key_strafeleft])
312 side -= sidemove[pClass][speed];
315 // Look up/down/center keys
316 if(gamekeydown[key_lookup])
320 if(gamekeydown[key_lookdown])
324 if(gamekeydown[key_lookcenter])
329 // Fly up/down/drop keys
330 if(gamekeydown[key_flyup])
332 flyheight = 5; // note that the actual flyheight will be twice this
334 if(gamekeydown[key_flydown])
338 if(gamekeydown[key_flycenter])
340 flyheight = TOCENTER;
344 if(gamekeydown[key_useartifact])
346 if(gamekeydown[key_speed] && artiskip)
348 if(players[consoleplayer].inventory[inv_ptr].type != arti_none)
349 { // Skip an artifact
350 gamekeydown[key_useartifact] = false;
351 P_PlayerNextArtifact(&players[consoleplayer]);
358 players[consoleplayer].readyArtifact =
359 players[consoleplayer].inventory[inv_ptr].type;
367 players[consoleplayer].inventory[inv_ptr].type&AFLAG_MASK;
372 if(gamekeydown[key_jump] || mousebuttons[mousebjump]
373 || joybuttons[joybjump])
375 cmd->arti |= AFLAG_JUMP;
377 if(mn_SuicideConsole)
379 cmd->arti |= AFLAG_SUICIDE;
380 mn_SuicideConsole = false;
384 if(gamekeydown[KEY_BACKSPACE] && !cmd->arti)
386 gamekeydown[KEY_BACKSPACE] = false; // Use one of each artifact
387 cmd->arti = NUMARTIFACTS;
389 else if(gamekeydown[KEY_BACKSLASH] && !cmd->arti
390 && (players[consoleplayer].mo->health < MAXHEALTH))
392 gamekeydown[KEY_BACKSLASH] = false;
393 cmd->arti = arti_health;
395 else if(gamekeydown[KEY_ZERO] && !cmd->arti)
397 gamekeydown[KEY_ZERO] = false;
398 cmd->arti = arti_poisonbag;
400 else if(gamekeydown[KEY_NINE] && !cmd->arti)
402 gamekeydown[KEY_NINE] = false;
403 cmd->arti = arti_blastradius;
405 else if(gamekeydown[KEY_EIGHT] && !cmd->arti)
407 gamekeydown[KEY_EIGHT] = false;
408 cmd->arti = arti_teleport;
410 else if(gamekeydown[KEY_SEVEN] && !cmd->arti)
412 gamekeydown[KEY_SEVEN] = false;
413 cmd->arti = arti_teleportother;
415 else if(gamekeydown[KEY_SIX] && !cmd->arti)
417 gamekeydown[KEY_SIX] = false;
418 cmd->arti = arti_egg;
420 else if(gamekeydown[KEY_FIVE] && !cmd->arti
421 && !players[consoleplayer].powers[pw_invulnerability])
423 gamekeydown[KEY_FIVE] = false;
424 cmd->arti = arti_invulnerability;
430 cmd->chatchar = CT_dequeueChatChar();
431 if (gamekeydown[key_fire] || mousebuttons[mousebfire]
432 || joybuttons[joybfire])
433 cmd->buttons |= BT_ATTACK;
435 if (gamekeydown[key_use] || joybuttons[joybuse] )
437 cmd->buttons |= BT_USE;
438 dclicks = 0; // clear double clicks if hit use button
441 for(i = 0; i < NUMWEAPONS; i++)
443 if(gamekeydown['1'+i])
445 cmd->buttons |= BT_CHANGE;
446 cmd->buttons |= i<<BT_WEAPONSHIFT;
455 printf( "%d %d %d %d <%d %d>\n",
456 mousebuttons[mousebfire], mousebuttons[mousebforward],
457 mousebuttons[mousebjump], mousebuttons[mousebstrafe],
460 if (mousebuttons[mousebforward])
462 forward += forwardmove[pClass][speed];
466 // forward double click
468 if (mousebuttons[mousebforward] != dclickstate && dclicktime > 1 )
470 dclickstate = mousebuttons[mousebforward];
475 cmd->buttons |= BT_USE;
483 dclicktime += ticdup;
492 // strafe double click
494 bstrafe = mousebuttons[mousebstrafe]
495 || joybuttons[joybstrafe];
496 if (bstrafe != dclickstate2 && dclicktime2 > 1 )
498 dclickstate2 = bstrafe;
503 cmd->buttons |= BT_USE;
511 dclicktime2 += ticdup;
512 if (dclicktime2 > 20)
524 cmd->angleturn -= mousex*0x8;
527 if( demorecording || demoplayback || (mouselook == 0) )
533 // We'll directly change the viewing pitch of the console player.
534 float adj = ((mousey*0x4)<<16) / (float) ANGLE_180*180*110.0/85.0;
535 float newlookdir = 0; /* jim initialiser added to prevent warning */
537 adj *= 2; //Speed up the X11 mlook a little.
540 newlookdir = players[consoleplayer].lookdir + adj;
541 else if(mouselook == 2)
542 newlookdir = players[consoleplayer].lookdir - adj;
544 // vertical view angle taken from p_user.c line 249.
545 if( newlookdir > 90 )
547 if( newlookdir < -110 )
550 players[consoleplayer].lookdir = newlookdir;
555 if (forward > MaxPlayerMove[pClass])
557 forward = MaxPlayerMove[pClass];
559 else if (forward < -MaxPlayerMove[pClass])
561 forward = -MaxPlayerMove[pClass];
563 if (side > MaxPlayerMove[pClass])
565 side = MaxPlayerMove[pClass];
567 else if (side < -MaxPlayerMove[pClass])
569 side = -MaxPlayerMove[pClass];
571 if(players[consoleplayer].powers[pw_speed]
572 && !players[consoleplayer].morphTics)
573 { // Adjust for a player with a speed artifact
574 forward = (3*forward)>>1;
577 cmd->forwardmove += forward;
578 cmd->sidemove += side;
579 if(players[consoleplayer].playerstate == PST_LIVE)
591 cmd->lookfly |= flyheight<<4;
599 cmd->buttons = BT_SPECIAL | BTS_PAUSE;
605 cmd->buttons = BT_SPECIAL | BTS_SAVEGAME | (savegameslot<<BTS_SAVESHIFT);
618 void G_DoLoadLevel (void)
622 levelstarttic = gametic; // for time calculation
623 gamestate = GS_LEVEL;
624 for (i=0 ; i<MAXPLAYERS ; i++)
626 if (playeringame[i] && players[i].playerstate == PST_DEAD)
627 players[i].playerstate = PST_REBORN;
628 memset (players[i].frags,0,sizeof(players[i].frags));
631 SN_StopAllSequences();
632 P_SetupLevel (gameepisode, gamemap, 0, gameskill);
633 displayplayer = consoleplayer; // view the guy you are playing
634 starttime = I_GetTime ();
635 gameaction = ga_nothing;
639 // clear cmd building stuff
642 memset (gamekeydown, 0, sizeof(gamekeydown));
643 joyxmove = joyymove = 0;
645 sendpause = sendsave = paused = false;
646 memset (mousebuttons, 0, sizeof(mousebuttons));
647 memset (joybuttons, 0, sizeof(joybuttons));
652 ===============================================================================
656 = get info needed to make ticcmd_ts for the players
658 ===============================================================================
661 boolean G_Responder(event_t *ev)
664 extern boolean MenuActive;
666 plr = &players[consoleplayer];
667 if(ev->type == ev_keyup && ev->data1 == key_useartifact)
668 { // flag to denote that it's okay to use an artifact
671 plr->readyArtifact = plr->inventory[inv_ptr].type;
676 // Check for spy mode player cycle
677 if(gamestate == GS_LEVEL && ev->type == ev_keydown
678 && ev->data1 == KEY_F12 && !deathmatch)
679 { // Cycle the display player
683 if(displayplayer == MAXPLAYERS)
687 } while(!playeringame[displayplayer]
688 && displayplayer != consoleplayer);
693 { // Chat ate the event
696 if(gamestate == GS_LEVEL)
699 { // Status bar ate the event
703 { // Automap ate the event
711 if(ev->data1 == key_invleft)
713 inventoryTics = 5*35;
734 if(ev->data1 == key_invright)
736 inventoryTics = 5*35;
743 if(inv_ptr >= plr->inventorySlotNum)
759 if(ev->data1 == KEY_PAUSE && !MenuActive)
764 if(ev->data1 < NUMKEYS)
766 gamekeydown[ev->data1] = true;
768 return(true); // eat key down events
771 if(ev->data1 < NUMKEYS)
773 gamekeydown[ev->data1] = false;
775 return(false); // always let key up events filter down
779 mousebuttons[0] = ev->data1&1;
780 mousebuttons[1] = ev->data1&2;
781 mousebuttons[2] = ev->data1&4;
782 mousex = ev->data2*(mouseSensitivity+5)/10;
783 mousey = ev->data3*(mouseSensitivity+5)/10;
784 return(true); // eat events
787 joybuttons[0] = ev->data1&1;
788 joybuttons[1] = ev->data1&2;
789 joybuttons[2] = ev->data1&4;
790 joybuttons[3] = ev->data1&8;
791 joyxmove = ev->data2;
792 joyymove = ev->data3;
793 return(true); // eat events
802 //==========================================================================
806 //==========================================================================
814 // do player reborns if needed
816 for (i=0 ; i<MAXPLAYERS ; i++)
817 if (playeringame[i] && players[i].playerstate == PST_REBORN)
821 // do things to change the game state
823 while (gameaction != ga_nothing)
844 case ga_singlereborn:
852 gameaction = ga_nothing;
856 G_DoTeleportNewMap();
874 // get commands, check consistancy, and build new consistancy check
876 //buf = gametic%BACKUPTICS;
879 buf = (gametic/ticdup)%BACKUPTICS;
881 for (i=0 ; i<MAXPLAYERS ; i++)
884 cmd = &players[i].cmd;
886 memcpy (cmd, &netcmds[i][buf], sizeof(ticcmd_t));
889 G_ReadDemoTiccmd (cmd);
891 G_WriteDemoTiccmd (cmd);
893 if (netgame && !(gametic%ticdup) )
895 if (gametic > BACKUPTICS
896 && consistancy[i][buf] != cmd->consistancy)
898 I_Error ("consistency failure (%i should be %i)",cmd->consistancy, consistancy[i][buf]);
901 consistancy[i][buf] = players[i].mo->x;
903 consistancy[i][buf] = rndindex;
908 // check for special buttons
910 for (i=0 ; i<MAXPLAYERS ; i++)
913 if (players[i].cmd.buttons & BT_SPECIAL)
915 switch (players[i].cmd.buttons & BT_SPECIALMASK)
930 if (!savedescription[0])
934 strcpy (savedescription, "NET GAME");
938 strcpy(savedescription, "SAVE GAME");
942 (players[i].cmd.buttons & BTS_SAVEMASK)>>BTS_SAVESHIFT;
943 gameaction = ga_savegame;
949 // turn inventory off after a certain amount of time
950 if(inventory && !(--inventoryTics))
952 players[consoleplayer].readyArtifact =
953 players[consoleplayer].inventory[inv_ptr].type;
971 case GS_INTERMISSION:
985 ==============================================================================
987 PLAYER STRUCTURE FUNCTIONS
989 also see P_SpawnPlayer in P_Things
990 ==============================================================================
993 //==========================================================================
997 // Called when the player leaves a map.
999 //==========================================================================
1001 void G_PlayerExitMap(int playerNumber)
1007 player = &players[playerNumber];
1011 // // Strip all but one of each type of artifact
1012 // for(i = 0; i < player->inventorySlotNum; i++)
1014 // player->inventory[i].count = 1;
1016 // player->artifactCount = player->inventorySlotNum;
1020 // Strip all current powers (retain flight)
1021 flightPower = player->powers[pw_flight];
1022 memset(player->powers, 0, sizeof(player->powers));
1023 player->powers[pw_flight] = flightPower;
1027 player->powers[pw_flight] = 0;
1031 if(P_GetMapCluster(gamemap) != P_GetMapCluster(LeaveMap))
1032 { // Entering new cluster
1036 // Strip flight artifact
1037 for(i = 0; i < 25; i++)
1039 player->powers[pw_flight] = 0;
1040 P_PlayerUseArtifact(player, arti_fly);
1042 player->powers[pw_flight] = 0;
1046 if(player->morphTics)
1048 player->readyweapon = player->mo->special1; // Restore weapon
1049 player->morphTics = 0;
1051 player->messageTics = 0;
1052 player->lookdir = 0;
1053 player->mo->flags &= ~MF_SHADOW; // Remove invisibility
1054 player->extralight = 0; // Remove weapon flashes
1055 player->fixedcolormap = 0; // Remove torch
1056 player->damagecount = 0; // No palette changes
1057 player->bonuscount = 0;
1058 player->poisoncount = 0;
1059 if(player == &players[consoleplayer])
1061 SB_state = -1; // refresh the status bar
1062 viewangleoffset = 0;
1066 //==========================================================================
1070 // Called after a player dies. Almost everything is cleared and
1073 //==========================================================================
1075 void G_PlayerReborn(int player)
1078 int frags[MAXPLAYERS];
1079 int killcount, itemcount, secretcount;
1082 memcpy(frags, players[player].frags, sizeof(frags));
1083 killcount = players[player].killcount;
1084 itemcount = players[player].itemcount;
1085 secretcount = players[player].secretcount;
1086 worldTimer = players[player].worldTimer;
1088 p = &players[player];
1089 memset(p, 0, sizeof(*p));
1091 memcpy(players[player].frags, frags, sizeof(players[player].frags));
1092 players[player].killcount = killcount;
1093 players[player].itemcount = itemcount;
1094 players[player].secretcount = secretcount;
1095 players[player].worldTimer = worldTimer;
1096 players[player].class = PlayerClass[player];
1098 p->usedown = p->attackdown = true; // don't do anything immediately
1099 p->playerstate = PST_LIVE;
1100 p->health = MAXHEALTH;
1101 p->readyweapon = p->pendingweapon = WP_FIRST;
1102 p->weaponowned[WP_FIRST] = true;
1105 localQuakeHappening[player] = false;
1106 if(p == &players[consoleplayer])
1108 SB_state = -1; // refresh the status bar
1109 inv_ptr = 0; // reset the inventory pointer
1111 viewangleoffset = 0;
1116 ====================
1120 = Returns false if the player cannot be respawned at the given mapthing_t spot
1121 = because something is occupying it
1122 ====================
1125 void P_SpawnPlayer (mapthing_t *mthing);
1127 boolean G_CheckSpot (int playernum, mapthing_t *mthing)
1134 x = mthing->x << FRACBITS;
1135 y = mthing->y << FRACBITS;
1137 players[playernum].mo->flags2 &= ~MF2_PASSMOBJ;
1138 if (!P_CheckPosition (players[playernum].mo, x, y) )
1140 players[playernum].mo->flags2 |= MF2_PASSMOBJ;
1143 players[playernum].mo->flags2 |= MF2_PASSMOBJ;
1145 // spawn a teleport fog
1146 ss = R_PointInSubsector (x,y);
1147 an = ( ANG45 * (mthing->angle/45) ) >> ANGLETOFINESHIFT;
1149 mo = P_SpawnMobj (x+20*finecosine[an], y+20*finesine[an],
1150 ss->sector->floorheight+TELEFOGHEIGHT, MT_TFOG);
1152 if (players[consoleplayer].viewz != 1)
1153 S_StartSound (mo, SFX_TELEPORT); // don't start sound on first frame
1159 ====================
1161 = G_DeathMatchSpawnPlayer
1163 = Spawns a player at one of the random death match spots
1164 = called at level load and each death
1165 ====================
1168 void G_DeathMatchSpawnPlayer (int playernum)
1173 selections = deathmatch_p - deathmatchstarts;
1175 // This check has been moved to p_setup.c:P_LoadThings()
1176 //if (selections < 8)
1177 // I_Error ("Only %i deathmatch spots, 8 required", selections);
1179 for (j=0 ; j<20 ; j++)
1181 i = P_Random() % selections;
1182 if (G_CheckSpot (playernum, &deathmatchstarts[i]) )
1184 deathmatchstarts[i].type = playernum+1;
1185 P_SpawnPlayer (&deathmatchstarts[i]);
1190 // no good spot, so the player will probably get stuck
1191 P_SpawnPlayer (&playerstarts[0][playernum]);
1194 //==========================================================================
1198 //==========================================================================
1200 void G_DoReborn(int playernum)
1203 boolean oldWeaponowned[NUMWEAPONS];
1209 if(G_CheckDemoStatus())
1215 if(SV_RebornSlotAvailable())
1216 { // Use the reborn code if the slot is available
1217 gameaction = ga_singlereborn;
1220 { // Start a new game if there's no reborn info
1221 gameaction = ga_newgame;
1226 players[playernum].mo->player = NULL; // Dissassociate the corpse
1229 { // Spawn at random spot if in death match
1230 G_DeathMatchSpawnPlayer(playernum);
1234 // Cooperative net-play, retain keys and weapons
1235 oldKeys = players[playernum].keys;
1236 oldPieces = players[playernum].pieces;
1237 for(i = 0; i < NUMWEAPONS; i++)
1239 oldWeaponowned[i] = players[playernum].weaponowned[i];
1243 if(G_CheckSpot(playernum,
1244 &playerstarts[RebornPosition][playernum]))
1245 { // Appropriate player start spot is open
1246 P_SpawnPlayer(&playerstarts[RebornPosition][playernum]);
1251 // Try to spawn at one of the other player start spots
1252 for(i = 0; i < MAXPLAYERS; i++)
1254 if(G_CheckSpot(playernum, &playerstarts[RebornPosition][i]))
1255 { // Found an open start spot
1257 // Fake as other player
1258 playerstarts[RebornPosition][i].type = playernum+1;
1259 P_SpawnPlayer(&playerstarts[RebornPosition][i]);
1261 // Restore proper player type
1262 playerstarts[RebornPosition][i].type = i+1;
1270 if(foundSpot == false)
1271 { // Player's going to be inside something
1272 P_SpawnPlayer(&playerstarts[RebornPosition][playernum]);
1275 // Restore keys and weapons
1276 players[playernum].keys = oldKeys;
1277 players[playernum].pieces = oldPieces;
1278 for(bestWeapon = 0, i = 0; i < NUMWEAPONS; i++)
1280 if(oldWeaponowned[i])
1283 players[playernum].weaponowned[i] = true;
1286 players[playernum].mana[MANA_1] = 25;
1287 players[playernum].mana[MANA_2] = 25;
1289 { // Bring up the best weapon
1290 players[playernum].pendingweapon = bestWeapon;
1295 void G_ScreenShot (void)
1297 gameaction = ga_screenshot;
1300 //==========================================================================
1304 //==========================================================================
1306 void G_StartNewInit(void)
1309 SV_ClearRebornSlot();
1311 // Default the player start spot group to 0
1315 //==========================================================================
1319 //==========================================================================
1321 void G_StartNewGame(skill_t skill)
1326 realMap = P_TranslateMap(1);
1331 G_InitNew(TempSkill, 1, realMap);
1334 //==========================================================================
1338 // Only called by the warp cheat code. Works just like normal map to map
1339 // teleporting, but doesn't do any interlude stuff.
1341 //==========================================================================
1343 void G_TeleportNewMap(int map, int position)
1345 gameaction = ga_leavemap;
1347 LeavePosition = position;
1350 //==========================================================================
1352 // G_DoTeleportNewMap
1354 //==========================================================================
1356 void G_DoTeleportNewMap(void)
1358 SV_MapTeleport(LeaveMap, LeavePosition);
1359 gamestate = GS_LEVEL;
1360 gameaction = ga_nothing;
1361 RebornPosition = LeavePosition;
1366 void G_ExitLevel (void)
1369 gameaction = ga_completed;
1371 void G_SecretExitLevel (void)
1374 gameaction = ga_completed;
1378 //==========================================================================
1382 // Starts intermission routine, which is used only during hub exits,
1383 // and DeathMatch games.
1384 //==========================================================================
1386 void G_Completed(int map, int position)
1388 gameaction = ga_completed;
1390 LeavePosition = position;
1393 void G_DoCompleted(void)
1397 gameaction = ga_nothing;
1398 if(G_CheckDemoStatus())
1402 for(i = 0; i < MAXPLAYERS; i++)
1409 if(LeaveMap == -1 && LeavePosition == -1)
1411 gameaction = ga_victory;
1416 gamestate = GS_INTERMISSION;
1422 static int afterSecret[3] = { 7, 5, 5 };
1424 gameaction = ga_nothing;
1425 if(G_CheckDemoStatus())
1429 for(i = 0; i < MAXPLAYERS; i++)
1433 G_PlayerFinishLevel(i);
1437 if(secretexit == true)
1441 else if(gamemap == 9)
1442 { // Finished secret level
1443 gamemap = afterSecret[gameepisode-1];
1445 else if(gamemap == 8)
1447 gameaction = ga_victory;
1454 gamestate = GS_INTERMISSION;
1459 //============================================================================
1463 //============================================================================
1465 void G_WorldDone(void)
1467 gameaction = ga_worlddone;
1470 //============================================================================
1474 //============================================================================
1476 void G_DoWorldDone(void)
1478 gamestate = GS_LEVEL;
1480 gameaction = ga_nothing;
1484 //==========================================================================
1488 // Called by G_Ticker based on gameaction. Loads a game from the reborn
1491 //==========================================================================
1493 void G_DoSingleReborn(void)
1495 gameaction = ga_nothing;
1496 SV_LoadGame(SV_GetRebornSlot());
1500 //==========================================================================
1504 // Can be called by the startup code or the menu task.
1506 //==========================================================================
1508 static int GameLoadSlot;
1510 void G_LoadGame(int slot)
1512 GameLoadSlot = slot;
1513 gameaction = ga_loadgame;
1516 //==========================================================================
1520 // Called by G_Ticker based on gameaction.
1522 //==========================================================================
1524 void G_DoLoadGame(void)
1526 gameaction = ga_nothing;
1527 SV_LoadGame(GameLoadSlot);
1529 { // Copy the base slot to the reborn slot
1530 SV_UpdateRebornSlot();
1535 //==========================================================================
1539 // Called by the menu task. <description> is a 24 byte text string.
1541 //==========================================================================
1543 void G_SaveGame(int slot, char *description)
1545 savegameslot = slot;
1546 strcpy(savedescription, description);
1550 //==========================================================================
1554 // Called by G_Ticker based on gameaction.
1556 //==========================================================================
1558 void G_DoSaveGame(void)
1560 SV_SaveGame(savegameslot, savedescription);
1561 gameaction = ga_nothing;
1562 savedescription[0] = 0;
1563 P_SetMessage(&players[consoleplayer], TXT_GAMESAVED, true);
1566 //==========================================================================
1568 // G_DeferredNewGame
1570 //==========================================================================
1572 void G_DeferredNewGame(skill_t skill)
1575 gameaction = ga_newgame;
1578 //==========================================================================
1582 //==========================================================================
1584 void G_DoNewGame(void)
1586 G_StartNewGame(TempSkill);
1587 gameaction = ga_nothing;
1591 ====================
1595 = Can be called by the startup code or the menu task
1596 = consoleplayer, displayplayer, playeringame[] should be set
1597 ====================
1600 void G_DeferedInitNew(skill_t skill, int episode, int map)
1603 TempEpisode = episode;
1605 gameaction = ga_initnew;
1608 void G_DoInitNew(void)
1611 G_InitNew(TempSkill, TempEpisode, TempMap);
1612 gameaction = ga_nothing;
1615 void G_InitNew(skill_t skill, int episode, int map)
1628 if(skill > sk_nightmare)
1630 skill = sk_nightmare;
1641 // Force players to be initialized upon first level load
1642 for(i = 0; i < MAXPLAYERS; i++)
1644 players[i].playerstate = PST_REBORN;
1645 players[i].worldTimer = 0;
1648 // Set up a bunch of globals
1649 usergame = true; // will be set false if a demo
1651 demorecording = false;
1652 demoplayback = false;
1654 gameepisode = episode;
1657 BorderNeedRefresh = true;
1659 // Initialize the sky
1662 // Give one null ticcmd_t
1665 //for (i=0 ; i<MAXPLAYERS ; i++)
1666 // nettics[i] = 1; // one null event for this gametic
1667 //memset (localcmds,0,sizeof(localcmds));
1668 //memset (netcmds,0,sizeof(netcmds));
1674 ===============================================================================
1678 ===============================================================================
1681 #define DEMOMARKER 0x80
1683 void G_ReadDemoTiccmd (ticcmd_t *cmd)
1685 if (*demo_p == DEMOMARKER)
1686 { // end of demo data stream
1687 G_CheckDemoStatus ();
1690 cmd->forwardmove = ((signed char)*demo_p++);
1691 cmd->sidemove = ((signed char)*demo_p++);
1692 cmd->angleturn = ((unsigned char)*demo_p++)<<8;
1693 cmd->buttons = (unsigned char)*demo_p++;
1694 cmd->lookfly = (unsigned char)*demo_p++;
1695 cmd->arti = (unsigned char)*demo_p++;
1698 void G_WriteDemoTiccmd (ticcmd_t *cmd)
1700 if (gamekeydown['q']) // press q to end demo recording
1701 G_CheckDemoStatus ();
1702 *demo_p++ = cmd->forwardmove;
1703 *demo_p++ = cmd->sidemove;
1704 *demo_p++ = cmd->angleturn>>8;
1705 *demo_p++ = cmd->buttons;
1706 *demo_p++ = cmd->lookfly;
1707 *demo_p++ = cmd->arti;
1709 G_ReadDemoTiccmd (cmd); // make SURE it is exactly the same
1722 void G_RecordDemo (skill_t skill, int numplayers, int episode, int map, char *name)
1726 G_InitNew (skill, episode, map);
1728 strcpy (demoname, name);
1729 strcat (demoname, ".lmp");
1730 demobuffer = demo_p = Z_Malloc (0x20000,PU_STATIC,NULL);
1732 *demo_p++ = episode;
1735 for (i=0 ; i<MAXPLAYERS ; i++)
1737 *demo_p++ = playeringame[i];
1738 *demo_p++ = PlayerClass[i];
1740 demorecording = true;
1754 void G_DeferedPlayDemo (char *name)
1757 gameaction = ga_playdemo;
1760 void G_DoPlayDemo (void)
1763 int i, episode, map;
1765 gameaction = ga_nothing;
1766 demobuffer = demo_p = W_CacheLumpName (defdemoname, PU_STATIC);
1768 episode = *demo_p++;
1771 for (i=0 ; i<MAXPLAYERS ; i++)
1773 playeringame[i] = *demo_p++;
1774 PlayerClass[i] = *demo_p++;
1777 // Initialize world info, etc.
1780 precache = false; // don't spend a lot of time in loadlevel
1781 G_InitNew (skill, episode, map);
1784 demoplayback = true;
1796 void G_TimeDemo (char *name)
1801 demobuffer = demo_p = W_CacheLumpName (name, PU_STATIC);
1803 episode = *demo_p++;
1805 G_InitNew (skill, episode, map);
1807 demoplayback = true;
1818 = Called after a death or level completion to allow demos to be cleaned up
1819 = Returns true if a new demo loop action will take place
1823 boolean G_CheckDemoStatus (void)
1829 endtime = I_GetTime ();
1830 I_Error ("timed %i gametics in %i realtics",gametic
1831 , endtime-starttime);
1839 Z_ChangeTag (demobuffer, PU_CACHE);
1840 demoplayback = false;
1847 *demo_p++ = DEMOMARKER;
1848 M_WriteFile (demoname, demobuffer, demo_p - demobuffer);
1849 Z_Free (demobuffer);
1850 demorecording = false;
1851 I_Error ("Demo %s recorded",demoname);