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 I_ReadCyberCmd (cmd);
218 //printf ("cons: %i\n",cmd->consistancy);
219 strafe = gamekeydown[key_strafe] || mousebuttons[mousebstrafe]
220 || joybuttons[joybstrafe];
222 speed = gamekeydown[key_speed] || joybuttons[joybspeed]
223 || joybuttons[joybspeed];
224 if(alwaysrun && !demoplayback && !demorecording)
226 forward = side = look = arti = flyheight = 0;
229 // use two stage accelerative turning on the keyboard and joystick
231 if (joyxmove < 0 || joyxmove > 0
232 || gamekeydown[key_right] || gamekeydown[key_left])
236 if (turnheld < SLOWTURNTICS)
237 tspeed = 2; // slow turn
241 if(gamekeydown[key_lookdown] || gamekeydown[key_lookup])
249 if(lookheld < SLOWTURNTICS)
259 // let movement keys cancel each other out
263 if (gamekeydown[key_right])
265 side += sidemove[pClass][speed];
267 if (gamekeydown[key_left])
269 side -= sidemove[pClass][speed];
273 side += sidemove[pClass][speed];
277 side -= sidemove[pClass][speed];
282 if (gamekeydown[key_right])
283 cmd->angleturn -= angleturn[tspeed];
284 if (gamekeydown[key_left])
285 cmd->angleturn += angleturn[tspeed];
287 cmd->angleturn -= angleturn[tspeed];
289 cmd->angleturn += angleturn[tspeed];
292 if (gamekeydown[key_up])
294 forward += forwardmove[pClass][speed];
296 if (gamekeydown[key_down])
298 forward -= forwardmove[pClass][speed];
302 forward += forwardmove[pClass][speed];
306 forward -= forwardmove[pClass][speed];
308 if (gamekeydown[key_straferight])
310 side += sidemove[pClass][speed];
312 if (gamekeydown[key_strafeleft])
314 side -= sidemove[pClass][speed];
317 // Look up/down/center keys
318 if(gamekeydown[key_lookup])
322 if(gamekeydown[key_lookdown])
326 if(gamekeydown[key_lookcenter])
331 // Fly up/down/drop keys
332 if(gamekeydown[key_flyup])
334 flyheight = 5; // note that the actual flyheight will be twice this
336 if(gamekeydown[key_flydown])
340 if(gamekeydown[key_flycenter])
342 flyheight = TOCENTER;
346 if(gamekeydown[key_useartifact])
348 if(gamekeydown[key_speed] && artiskip)
350 if(players[consoleplayer].inventory[inv_ptr].type != arti_none)
351 { // Skip an artifact
352 gamekeydown[key_useartifact] = false;
353 P_PlayerNextArtifact(&players[consoleplayer]);
360 players[consoleplayer].readyArtifact =
361 players[consoleplayer].inventory[inv_ptr].type;
369 players[consoleplayer].inventory[inv_ptr].type&AFLAG_MASK;
374 if(gamekeydown[key_jump] || mousebuttons[mousebjump]
375 || joybuttons[joybjump])
377 cmd->arti |= AFLAG_JUMP;
379 if(mn_SuicideConsole)
381 cmd->arti |= AFLAG_SUICIDE;
382 mn_SuicideConsole = false;
386 if(gamekeydown[KEY_BACKSPACE] && !cmd->arti)
388 gamekeydown[KEY_BACKSPACE] = false; // Use one of each artifact
389 cmd->arti = NUMARTIFACTS;
391 else if(gamekeydown[KEY_BACKSLASH] && !cmd->arti
392 && (players[consoleplayer].mo->health < MAXHEALTH))
394 gamekeydown[KEY_BACKSLASH] = false;
395 cmd->arti = arti_health;
397 else if(gamekeydown[KEY_ZERO] && !cmd->arti)
399 gamekeydown[KEY_ZERO] = false;
400 cmd->arti = arti_poisonbag;
402 else if(gamekeydown[KEY_NINE] && !cmd->arti)
404 gamekeydown[KEY_NINE] = false;
405 cmd->arti = arti_blastradius;
407 else if(gamekeydown[KEY_EIGHT] && !cmd->arti)
409 gamekeydown[KEY_EIGHT] = false;
410 cmd->arti = arti_teleport;
412 else if(gamekeydown[KEY_SEVEN] && !cmd->arti)
414 gamekeydown[KEY_SEVEN] = false;
415 cmd->arti = arti_teleportother;
417 else if(gamekeydown[KEY_SIX] && !cmd->arti)
419 gamekeydown[KEY_SIX] = false;
420 cmd->arti = arti_egg;
422 else if(gamekeydown[KEY_FIVE] && !cmd->arti
423 && !players[consoleplayer].powers[pw_invulnerability])
425 gamekeydown[KEY_FIVE] = false;
426 cmd->arti = arti_invulnerability;
432 cmd->chatchar = CT_dequeueChatChar();
433 if (gamekeydown[key_fire] || mousebuttons[mousebfire]
434 || joybuttons[joybfire])
435 cmd->buttons |= BT_ATTACK;
437 if (gamekeydown[key_use] || joybuttons[joybuse] )
439 cmd->buttons |= BT_USE;
440 dclicks = 0; // clear double clicks if hit use button
443 for(i = 0; i < NUMWEAPONS; i++)
445 if(gamekeydown['1'+i])
447 cmd->buttons |= BT_CHANGE;
448 cmd->buttons |= i<<BT_WEAPONSHIFT;
457 printf( "%d %d %d %d <%d %d>\n",
458 mousebuttons[mousebfire], mousebuttons[mousebforward],
459 mousebuttons[mousebjump], mousebuttons[mousebstrafe],
462 if (mousebuttons[mousebforward])
464 forward += forwardmove[pClass][speed];
468 // forward double click
470 if (mousebuttons[mousebforward] != dclickstate && dclicktime > 1 )
472 dclickstate = mousebuttons[mousebforward];
477 cmd->buttons |= BT_USE;
485 dclicktime += ticdup;
494 // strafe double click
496 bstrafe = mousebuttons[mousebstrafe]
497 || joybuttons[joybstrafe];
498 if (bstrafe != dclickstate2 && dclicktime2 > 1 )
500 dclickstate2 = bstrafe;
505 cmd->buttons |= BT_USE;
513 dclicktime2 += ticdup;
514 if (dclicktime2 > 20)
526 cmd->angleturn -= mousex*0x8;
529 if( demorecording || demoplayback || (mouselook == 0) )
535 // We'll directly change the viewing pitch of the console player.
536 float adj = ((mousey*0x4)<<16) / (float) ANGLE_180*180*110.0/85.0;
537 float newlookdir = 0; /* jim initialiser added to prevent warning */
539 adj *= 2; //Speed up the X11 mlook a little.
542 newlookdir = players[consoleplayer].lookdir + adj;
543 else if(mouselook == 2)
544 newlookdir = players[consoleplayer].lookdir - adj;
546 // vertical view angle taken from p_user.c line 249.
547 if( newlookdir > 90 )
549 if( newlookdir < -110 )
552 players[consoleplayer].lookdir = newlookdir;
557 if (forward > MaxPlayerMove[pClass])
559 forward = MaxPlayerMove[pClass];
561 else if (forward < -MaxPlayerMove[pClass])
563 forward = -MaxPlayerMove[pClass];
565 if (side > MaxPlayerMove[pClass])
567 side = MaxPlayerMove[pClass];
569 else if (side < -MaxPlayerMove[pClass])
571 side = -MaxPlayerMove[pClass];
573 if(players[consoleplayer].powers[pw_speed]
574 && !players[consoleplayer].morphTics)
575 { // Adjust for a player with a speed artifact
576 forward = (3*forward)>>1;
579 cmd->forwardmove += forward;
580 cmd->sidemove += side;
581 if(players[consoleplayer].playerstate == PST_LIVE)
593 cmd->lookfly |= flyheight<<4;
601 cmd->buttons = BT_SPECIAL | BTS_PAUSE;
607 cmd->buttons = BT_SPECIAL | BTS_SAVEGAME | (savegameslot<<BTS_SAVESHIFT);
620 void G_DoLoadLevel (void)
624 levelstarttic = gametic; // for time calculation
625 gamestate = GS_LEVEL;
626 for (i=0 ; i<MAXPLAYERS ; i++)
628 if (playeringame[i] && players[i].playerstate == PST_DEAD)
629 players[i].playerstate = PST_REBORN;
630 memset (players[i].frags,0,sizeof(players[i].frags));
633 SN_StopAllSequences();
634 P_SetupLevel (gameepisode, gamemap, 0, gameskill);
635 displayplayer = consoleplayer; // view the guy you are playing
636 starttime = I_GetTime ();
637 gameaction = ga_nothing;
641 // clear cmd building stuff
644 memset (gamekeydown, 0, sizeof(gamekeydown));
645 joyxmove = joyymove = 0;
647 sendpause = sendsave = paused = false;
648 memset (mousebuttons, 0, sizeof(mousebuttons));
649 memset (joybuttons, 0, sizeof(joybuttons));
654 ===============================================================================
658 = get info needed to make ticcmd_ts for the players
660 ===============================================================================
663 boolean G_Responder(event_t *ev)
666 extern boolean MenuActive;
668 plr = &players[consoleplayer];
669 if(ev->type == ev_keyup && ev->data1 == key_useartifact)
670 { // flag to denote that it's okay to use an artifact
673 plr->readyArtifact = plr->inventory[inv_ptr].type;
678 // Check for spy mode player cycle
679 if(gamestate == GS_LEVEL && ev->type == ev_keydown
680 && ev->data1 == KEY_F12 && !deathmatch)
681 { // Cycle the display player
685 if(displayplayer == MAXPLAYERS)
689 } while(!playeringame[displayplayer]
690 && displayplayer != consoleplayer);
695 { // Chat ate the event
698 if(gamestate == GS_LEVEL)
701 { // Status bar ate the event
705 { // Automap ate the event
713 if(ev->data1 == key_invleft)
715 inventoryTics = 5*35;
736 if(ev->data1 == key_invright)
738 inventoryTics = 5*35;
745 if(inv_ptr >= plr->inventorySlotNum)
761 if(ev->data1 == KEY_PAUSE && !MenuActive)
766 if(ev->data1 < NUMKEYS)
768 gamekeydown[ev->data1] = true;
770 return(true); // eat key down events
773 if(ev->data1 < NUMKEYS)
775 gamekeydown[ev->data1] = false;
777 return(false); // always let key up events filter down
781 mousebuttons[0] = ev->data1&1;
782 mousebuttons[1] = ev->data1&2;
783 mousebuttons[2] = ev->data1&4;
784 mousex = ev->data2*(mouseSensitivity+5)/10;
785 mousey = ev->data3*(mouseSensitivity+5)/10;
786 return(true); // eat events
789 joybuttons[0] = ev->data1&1;
790 joybuttons[1] = ev->data1&2;
791 joybuttons[2] = ev->data1&4;
792 joybuttons[3] = ev->data1&8;
793 joyxmove = ev->data2;
794 joyymove = ev->data3;
795 return(true); // eat events
804 //==========================================================================
808 //==========================================================================
816 // do player reborns if needed
818 for (i=0 ; i<MAXPLAYERS ; i++)
819 if (playeringame[i] && players[i].playerstate == PST_REBORN)
823 // do things to change the game state
825 while (gameaction != ga_nothing)
846 case ga_singlereborn:
854 gameaction = ga_nothing;
858 G_DoTeleportNewMap();
876 // get commands, check consistancy, and build new consistancy check
878 //buf = gametic%BACKUPTICS;
881 buf = (gametic/ticdup)%BACKUPTICS;
883 for (i=0 ; i<MAXPLAYERS ; i++)
886 cmd = &players[i].cmd;
888 memcpy (cmd, &netcmds[i][buf], sizeof(ticcmd_t));
891 G_ReadDemoTiccmd (cmd);
893 G_WriteDemoTiccmd (cmd);
895 if (netgame && !(gametic%ticdup) )
897 if (gametic > BACKUPTICS
898 && consistancy[i][buf] != cmd->consistancy)
900 I_Error ("consistency failure (%i should be %i)",cmd->consistancy, consistancy[i][buf]);
903 consistancy[i][buf] = players[i].mo->x;
905 consistancy[i][buf] = rndindex;
910 // check for special buttons
912 for (i=0 ; i<MAXPLAYERS ; i++)
915 if (players[i].cmd.buttons & BT_SPECIAL)
917 switch (players[i].cmd.buttons & BT_SPECIALMASK)
932 if (!savedescription[0])
936 strcpy (savedescription, "NET GAME");
940 strcpy(savedescription, "SAVE GAME");
944 (players[i].cmd.buttons & BTS_SAVEMASK)>>BTS_SAVESHIFT;
945 gameaction = ga_savegame;
951 // turn inventory off after a certain amount of time
952 if(inventory && !(--inventoryTics))
954 players[consoleplayer].readyArtifact =
955 players[consoleplayer].inventory[inv_ptr].type;
973 case GS_INTERMISSION:
987 ==============================================================================
989 PLAYER STRUCTURE FUNCTIONS
991 also see P_SpawnPlayer in P_Things
992 ==============================================================================
995 //==========================================================================
999 // Called when the player leaves a map.
1001 //==========================================================================
1003 void G_PlayerExitMap(int playerNumber)
1009 player = &players[playerNumber];
1013 // // Strip all but one of each type of artifact
1014 // for(i = 0; i < player->inventorySlotNum; i++)
1016 // player->inventory[i].count = 1;
1018 // player->artifactCount = player->inventorySlotNum;
1022 // Strip all current powers (retain flight)
1023 flightPower = player->powers[pw_flight];
1024 memset(player->powers, 0, sizeof(player->powers));
1025 player->powers[pw_flight] = flightPower;
1029 player->powers[pw_flight] = 0;
1033 if(P_GetMapCluster(gamemap) != P_GetMapCluster(LeaveMap))
1034 { // Entering new cluster
1038 // Strip flight artifact
1039 for(i = 0; i < 25; i++)
1041 player->powers[pw_flight] = 0;
1042 P_PlayerUseArtifact(player, arti_fly);
1044 player->powers[pw_flight] = 0;
1048 if(player->morphTics)
1050 player->readyweapon = player->mo->special1; // Restore weapon
1051 player->morphTics = 0;
1053 player->messageTics = 0;
1054 player->lookdir = 0;
1055 player->mo->flags &= ~MF_SHADOW; // Remove invisibility
1056 player->extralight = 0; // Remove weapon flashes
1057 player->fixedcolormap = 0; // Remove torch
1058 player->damagecount = 0; // No palette changes
1059 player->bonuscount = 0;
1060 player->poisoncount = 0;
1061 if(player == &players[consoleplayer])
1063 SB_state = -1; // refresh the status bar
1064 viewangleoffset = 0;
1068 //==========================================================================
1072 // Called after a player dies. Almost everything is cleared and
1075 //==========================================================================
1077 void G_PlayerReborn(int player)
1080 int frags[MAXPLAYERS];
1081 int killcount, itemcount, secretcount;
1084 memcpy(frags, players[player].frags, sizeof(frags));
1085 killcount = players[player].killcount;
1086 itemcount = players[player].itemcount;
1087 secretcount = players[player].secretcount;
1088 worldTimer = players[player].worldTimer;
1090 p = &players[player];
1091 memset(p, 0, sizeof(*p));
1093 memcpy(players[player].frags, frags, sizeof(players[player].frags));
1094 players[player].killcount = killcount;
1095 players[player].itemcount = itemcount;
1096 players[player].secretcount = secretcount;
1097 players[player].worldTimer = worldTimer;
1098 players[player].class = PlayerClass[player];
1100 p->usedown = p->attackdown = true; // don't do anything immediately
1101 p->playerstate = PST_LIVE;
1102 p->health = MAXHEALTH;
1103 p->readyweapon = p->pendingweapon = WP_FIRST;
1104 p->weaponowned[WP_FIRST] = true;
1107 localQuakeHappening[player] = false;
1108 if(p == &players[consoleplayer])
1110 SB_state = -1; // refresh the status bar
1111 inv_ptr = 0; // reset the inventory pointer
1113 viewangleoffset = 0;
1118 ====================
1122 = Returns false if the player cannot be respawned at the given mapthing_t spot
1123 = because something is occupying it
1124 ====================
1127 void P_SpawnPlayer (mapthing_t *mthing);
1129 boolean G_CheckSpot (int playernum, mapthing_t *mthing)
1136 x = mthing->x << FRACBITS;
1137 y = mthing->y << FRACBITS;
1139 players[playernum].mo->flags2 &= ~MF2_PASSMOBJ;
1140 if (!P_CheckPosition (players[playernum].mo, x, y) )
1142 players[playernum].mo->flags2 |= MF2_PASSMOBJ;
1145 players[playernum].mo->flags2 |= MF2_PASSMOBJ;
1147 // spawn a teleport fog
1148 ss = R_PointInSubsector (x,y);
1149 an = ( ANG45 * (mthing->angle/45) ) >> ANGLETOFINESHIFT;
1151 mo = P_SpawnMobj (x+20*finecosine[an], y+20*finesine[an],
1152 ss->sector->floorheight+TELEFOGHEIGHT, MT_TFOG);
1154 if (players[consoleplayer].viewz != 1)
1155 S_StartSound (mo, SFX_TELEPORT); // don't start sound on first frame
1161 ====================
1163 = G_DeathMatchSpawnPlayer
1165 = Spawns a player at one of the random death match spots
1166 = called at level load and each death
1167 ====================
1170 void G_DeathMatchSpawnPlayer (int playernum)
1175 selections = deathmatch_p - deathmatchstarts;
1177 // This check has been moved to p_setup.c:P_LoadThings()
1178 //if (selections < 8)
1179 // I_Error ("Only %i deathmatch spots, 8 required", selections);
1181 for (j=0 ; j<20 ; j++)
1183 i = P_Random() % selections;
1184 if (G_CheckSpot (playernum, &deathmatchstarts[i]) )
1186 deathmatchstarts[i].type = playernum+1;
1187 P_SpawnPlayer (&deathmatchstarts[i]);
1192 // no good spot, so the player will probably get stuck
1193 P_SpawnPlayer (&playerstarts[0][playernum]);
1196 //==========================================================================
1200 //==========================================================================
1202 void G_DoReborn(int playernum)
1205 boolean oldWeaponowned[NUMWEAPONS];
1211 if(G_CheckDemoStatus())
1217 if(SV_RebornSlotAvailable())
1218 { // Use the reborn code if the slot is available
1219 gameaction = ga_singlereborn;
1222 { // Start a new game if there's no reborn info
1223 gameaction = ga_newgame;
1228 players[playernum].mo->player = NULL; // Dissassociate the corpse
1231 { // Spawn at random spot if in death match
1232 G_DeathMatchSpawnPlayer(playernum);
1236 // Cooperative net-play, retain keys and weapons
1237 oldKeys = players[playernum].keys;
1238 oldPieces = players[playernum].pieces;
1239 for(i = 0; i < NUMWEAPONS; i++)
1241 oldWeaponowned[i] = players[playernum].weaponowned[i];
1245 if(G_CheckSpot(playernum,
1246 &playerstarts[RebornPosition][playernum]))
1247 { // Appropriate player start spot is open
1248 P_SpawnPlayer(&playerstarts[RebornPosition][playernum]);
1253 // Try to spawn at one of the other player start spots
1254 for(i = 0; i < MAXPLAYERS; i++)
1256 if(G_CheckSpot(playernum, &playerstarts[RebornPosition][i]))
1257 { // Found an open start spot
1259 // Fake as other player
1260 playerstarts[RebornPosition][i].type = playernum+1;
1261 P_SpawnPlayer(&playerstarts[RebornPosition][i]);
1263 // Restore proper player type
1264 playerstarts[RebornPosition][i].type = i+1;
1272 if(foundSpot == false)
1273 { // Player's going to be inside something
1274 P_SpawnPlayer(&playerstarts[RebornPosition][playernum]);
1277 // Restore keys and weapons
1278 players[playernum].keys = oldKeys;
1279 players[playernum].pieces = oldPieces;
1280 for(bestWeapon = 0, i = 0; i < NUMWEAPONS; i++)
1282 if(oldWeaponowned[i])
1285 players[playernum].weaponowned[i] = true;
1288 players[playernum].mana[MANA_1] = 25;
1289 players[playernum].mana[MANA_2] = 25;
1291 { // Bring up the best weapon
1292 players[playernum].pendingweapon = bestWeapon;
1297 void G_ScreenShot (void)
1299 gameaction = ga_screenshot;
1302 //==========================================================================
1306 //==========================================================================
1308 void G_StartNewInit(void)
1311 SV_ClearRebornSlot();
1313 // Default the player start spot group to 0
1317 //==========================================================================
1321 //==========================================================================
1323 void G_StartNewGame(skill_t skill)
1328 realMap = P_TranslateMap(1);
1333 G_InitNew(TempSkill, 1, realMap);
1336 //==========================================================================
1340 // Only called by the warp cheat code. Works just like normal map to map
1341 // teleporting, but doesn't do any interlude stuff.
1343 //==========================================================================
1345 void G_TeleportNewMap(int map, int position)
1347 gameaction = ga_leavemap;
1349 LeavePosition = position;
1352 //==========================================================================
1354 // G_DoTeleportNewMap
1356 //==========================================================================
1358 void G_DoTeleportNewMap(void)
1360 SV_MapTeleport(LeaveMap, LeavePosition);
1361 gamestate = GS_LEVEL;
1362 gameaction = ga_nothing;
1363 RebornPosition = LeavePosition;
1368 void G_ExitLevel (void)
1371 gameaction = ga_completed;
1373 void G_SecretExitLevel (void)
1376 gameaction = ga_completed;
1380 //==========================================================================
1384 // Starts intermission routine, which is used only during hub exits,
1385 // and DeathMatch games.
1386 //==========================================================================
1388 void G_Completed(int map, int position)
1390 gameaction = ga_completed;
1392 LeavePosition = position;
1395 void G_DoCompleted(void)
1399 gameaction = ga_nothing;
1400 if(G_CheckDemoStatus())
1404 for(i = 0; i < MAXPLAYERS; i++)
1411 if(LeaveMap == -1 && LeavePosition == -1)
1413 gameaction = ga_victory;
1418 gamestate = GS_INTERMISSION;
1424 static int afterSecret[3] = { 7, 5, 5 };
1426 gameaction = ga_nothing;
1427 if(G_CheckDemoStatus())
1431 for(i = 0; i < MAXPLAYERS; i++)
1435 G_PlayerFinishLevel(i);
1439 if(secretexit == true)
1443 else if(gamemap == 9)
1444 { // Finished secret level
1445 gamemap = afterSecret[gameepisode-1];
1447 else if(gamemap == 8)
1449 gameaction = ga_victory;
1456 gamestate = GS_INTERMISSION;
1461 //============================================================================
1465 //============================================================================
1467 void G_WorldDone(void)
1469 gameaction = ga_worlddone;
1472 //============================================================================
1476 //============================================================================
1478 void G_DoWorldDone(void)
1480 gamestate = GS_LEVEL;
1482 gameaction = ga_nothing;
1486 //==========================================================================
1490 // Called by G_Ticker based on gameaction. Loads a game from the reborn
1493 //==========================================================================
1495 void G_DoSingleReborn(void)
1497 gameaction = ga_nothing;
1498 SV_LoadGame(SV_GetRebornSlot());
1502 //==========================================================================
1506 // Can be called by the startup code or the menu task.
1508 //==========================================================================
1510 static int GameLoadSlot;
1512 void G_LoadGame(int slot)
1514 GameLoadSlot = slot;
1515 gameaction = ga_loadgame;
1518 //==========================================================================
1522 // Called by G_Ticker based on gameaction.
1524 //==========================================================================
1526 void G_DoLoadGame(void)
1528 gameaction = ga_nothing;
1529 SV_LoadGame(GameLoadSlot);
1531 { // Copy the base slot to the reborn slot
1532 SV_UpdateRebornSlot();
1537 //==========================================================================
1541 // Called by the menu task. <description> is a 24 byte text string.
1543 //==========================================================================
1545 void G_SaveGame(int slot, char *description)
1547 savegameslot = slot;
1548 strcpy(savedescription, description);
1552 //==========================================================================
1556 // Called by G_Ticker based on gameaction.
1558 //==========================================================================
1560 void G_DoSaveGame(void)
1562 SV_SaveGame(savegameslot, savedescription);
1563 gameaction = ga_nothing;
1564 savedescription[0] = 0;
1565 P_SetMessage(&players[consoleplayer], TXT_GAMESAVED, true);
1568 //==========================================================================
1570 // G_DeferredNewGame
1572 //==========================================================================
1574 void G_DeferredNewGame(skill_t skill)
1577 gameaction = ga_newgame;
1580 //==========================================================================
1584 //==========================================================================
1586 void G_DoNewGame(void)
1588 G_StartNewGame(TempSkill);
1589 gameaction = ga_nothing;
1593 ====================
1597 = Can be called by the startup code or the menu task
1598 = consoleplayer, displayplayer, playeringame[] should be set
1599 ====================
1602 void G_DeferedInitNew(skill_t skill, int episode, int map)
1605 TempEpisode = episode;
1607 gameaction = ga_initnew;
1610 void G_DoInitNew(void)
1613 G_InitNew(TempSkill, TempEpisode, TempMap);
1614 gameaction = ga_nothing;
1617 void G_InitNew(skill_t skill, int episode, int map)
1630 if(skill > sk_nightmare)
1632 skill = sk_nightmare;
1643 // Force players to be initialized upon first level load
1644 for(i = 0; i < MAXPLAYERS; i++)
1646 players[i].playerstate = PST_REBORN;
1647 players[i].worldTimer = 0;
1650 // Set up a bunch of globals
1651 usergame = true; // will be set false if a demo
1653 demorecording = false;
1654 demoplayback = false;
1656 gameepisode = episode;
1659 BorderNeedRefresh = true;
1661 // Initialize the sky
1664 // Give one null ticcmd_t
1667 //for (i=0 ; i<MAXPLAYERS ; i++)
1668 // nettics[i] = 1; // one null event for this gametic
1669 //memset (localcmds,0,sizeof(localcmds));
1670 //memset (netcmds,0,sizeof(netcmds));
1676 ===============================================================================
1680 ===============================================================================
1683 #define DEMOMARKER 0x80
1685 void G_ReadDemoTiccmd (ticcmd_t *cmd)
1687 if (*demo_p == DEMOMARKER)
1688 { // end of demo data stream
1689 G_CheckDemoStatus ();
1692 cmd->forwardmove = ((signed char)*demo_p++);
1693 cmd->sidemove = ((signed char)*demo_p++);
1694 cmd->angleturn = ((unsigned char)*demo_p++)<<8;
1695 cmd->buttons = (unsigned char)*demo_p++;
1696 cmd->lookfly = (unsigned char)*demo_p++;
1697 cmd->arti = (unsigned char)*demo_p++;
1700 void G_WriteDemoTiccmd (ticcmd_t *cmd)
1702 if (gamekeydown['q']) // press q to end demo recording
1703 G_CheckDemoStatus ();
1704 *demo_p++ = cmd->forwardmove;
1705 *demo_p++ = cmd->sidemove;
1706 *demo_p++ = cmd->angleturn>>8;
1707 *demo_p++ = cmd->buttons;
1708 *demo_p++ = cmd->lookfly;
1709 *demo_p++ = cmd->arti;
1711 G_ReadDemoTiccmd (cmd); // make SURE it is exactly the same
1724 void G_RecordDemo (skill_t skill, int numplayers, int episode, int map, char *name)
1728 G_InitNew (skill, episode, map);
1730 strcpy (demoname, name);
1731 strcat (demoname, ".lmp");
1732 demobuffer = demo_p = Z_Malloc (0x20000,PU_STATIC,NULL);
1734 *demo_p++ = episode;
1737 for (i=0 ; i<MAXPLAYERS ; i++)
1739 *demo_p++ = playeringame[i];
1740 *demo_p++ = PlayerClass[i];
1742 demorecording = true;
1756 void G_DeferedPlayDemo (char *name)
1759 gameaction = ga_playdemo;
1762 void G_DoPlayDemo (void)
1765 int i, episode, map;
1767 gameaction = ga_nothing;
1768 demobuffer = demo_p = W_CacheLumpName (defdemoname, PU_STATIC);
1770 episode = *demo_p++;
1773 for (i=0 ; i<MAXPLAYERS ; i++)
1775 playeringame[i] = *demo_p++;
1776 PlayerClass[i] = *demo_p++;
1779 // Initialize world info, etc.
1782 precache = false; // don't spend a lot of time in loadlevel
1783 G_InitNew (skill, episode, map);
1786 demoplayback = true;
1798 void G_TimeDemo (char *name)
1803 demobuffer = demo_p = W_CacheLumpName (name, PU_STATIC);
1805 episode = *demo_p++;
1807 G_InitNew (skill, episode, map);
1809 demoplayback = true;
1820 = Called after a death or level completion to allow demos to be cleaned up
1821 = Returns true if a new demo loop action will take place
1825 boolean G_CheckDemoStatus (void)
1831 endtime = I_GetTime ();
1832 I_Error ("timed %i gametics in %i realtics",gametic
1833 , endtime-starttime);
1841 Z_ChangeTag (demobuffer, PU_CACHE);
1842 demoplayback = false;
1849 *demo_p++ = DEMOMARKER;
1850 M_WriteFile (demoname, demobuffer, demo_p - demobuffer);
1851 Z_Free (demobuffer);
1852 demorecording = false;
1853 I_Error ("Demo %s recorded",demoname);