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 */
540 adj *= 2; //Speed up the X11 mlook a little.
544 newlookdir = players[consoleplayer].lookdir + adj;
545 else if(mouselook == 2)
546 newlookdir = players[consoleplayer].lookdir - adj;
548 // vertical view angle taken from p_user.c line 249.
549 if( newlookdir > 90 )
551 if( newlookdir < -110 )
554 players[consoleplayer].lookdir = newlookdir;
559 if (forward > MaxPlayerMove[pClass])
561 forward = MaxPlayerMove[pClass];
563 else if (forward < -MaxPlayerMove[pClass])
565 forward = -MaxPlayerMove[pClass];
567 if (side > MaxPlayerMove[pClass])
569 side = MaxPlayerMove[pClass];
571 else if (side < -MaxPlayerMove[pClass])
573 side = -MaxPlayerMove[pClass];
575 if(players[consoleplayer].powers[pw_speed]
576 && !players[consoleplayer].morphTics)
577 { // Adjust for a player with a speed artifact
578 forward = (3*forward)>>1;
581 cmd->forwardmove += forward;
582 cmd->sidemove += side;
583 if(players[consoleplayer].playerstate == PST_LIVE)
595 cmd->lookfly |= flyheight<<4;
603 cmd->buttons = BT_SPECIAL | BTS_PAUSE;
609 cmd->buttons = BT_SPECIAL | BTS_SAVEGAME | (savegameslot<<BTS_SAVESHIFT);
622 void G_DoLoadLevel (void)
626 levelstarttic = gametic; // for time calculation
627 gamestate = GS_LEVEL;
628 for (i=0 ; i<MAXPLAYERS ; i++)
630 if (playeringame[i] && players[i].playerstate == PST_DEAD)
631 players[i].playerstate = PST_REBORN;
632 memset (players[i].frags,0,sizeof(players[i].frags));
635 SN_StopAllSequences();
636 P_SetupLevel (gameepisode, gamemap, 0, gameskill);
637 displayplayer = consoleplayer; // view the guy you are playing
638 starttime = I_GetTime ();
639 gameaction = ga_nothing;
643 // clear cmd building stuff
646 memset (gamekeydown, 0, sizeof(gamekeydown));
647 joyxmove = joyymove = 0;
649 sendpause = sendsave = paused = false;
650 memset (mousebuttons, 0, sizeof(mousebuttons));
651 memset (joybuttons, 0, sizeof(joybuttons));
656 ===============================================================================
660 = get info needed to make ticcmd_ts for the players
662 ===============================================================================
665 boolean G_Responder(event_t *ev)
668 extern boolean MenuActive;
670 plr = &players[consoleplayer];
671 if(ev->type == ev_keyup && ev->data1 == key_useartifact)
672 { // flag to denote that it's okay to use an artifact
675 plr->readyArtifact = plr->inventory[inv_ptr].type;
680 // Check for spy mode player cycle
681 if(gamestate == GS_LEVEL && ev->type == ev_keydown
682 && ev->data1 == KEY_F12 && !deathmatch)
683 { // Cycle the display player
687 if(displayplayer == MAXPLAYERS)
691 } while(!playeringame[displayplayer]
692 && displayplayer != consoleplayer);
697 { // Chat ate the event
700 if(gamestate == GS_LEVEL)
703 { // Status bar ate the event
707 { // Automap ate the event
715 if(ev->data1 == key_invleft)
717 inventoryTics = 5*35;
738 if(ev->data1 == key_invright)
740 inventoryTics = 5*35;
747 if(inv_ptr >= plr->inventorySlotNum)
763 if(ev->data1 == KEY_PAUSE && !MenuActive)
768 if(ev->data1 < NUMKEYS)
770 gamekeydown[ev->data1] = true;
772 return(true); // eat key down events
775 if(ev->data1 < NUMKEYS)
777 gamekeydown[ev->data1] = false;
779 return(false); // always let key up events filter down
783 mousebuttons[0] = ev->data1&1;
784 mousebuttons[1] = ev->data1&2;
785 mousebuttons[2] = ev->data1&4;
786 mousex = ev->data2*(mouseSensitivity+5)/10;
787 mousey = ev->data3*(mouseSensitivity+5)/10;
788 return(true); // eat events
791 joybuttons[0] = ev->data1&1;
792 joybuttons[1] = ev->data1&2;
793 joybuttons[2] = ev->data1&4;
794 joybuttons[3] = ev->data1&8;
795 joyxmove = ev->data2;
796 joyymove = ev->data3;
797 return(true); // eat events
806 //==========================================================================
810 //==========================================================================
818 // do player reborns if needed
820 for (i=0 ; i<MAXPLAYERS ; i++)
821 if (playeringame[i] && players[i].playerstate == PST_REBORN)
825 // do things to change the game state
827 while (gameaction != ga_nothing)
848 case ga_singlereborn:
856 gameaction = ga_nothing;
860 G_DoTeleportNewMap();
878 // get commands, check consistancy, and build new consistancy check
880 //buf = gametic%BACKUPTICS;
883 buf = (gametic/ticdup)%BACKUPTICS;
885 for (i=0 ; i<MAXPLAYERS ; i++)
888 cmd = &players[i].cmd;
890 memcpy (cmd, &netcmds[i][buf], sizeof(ticcmd_t));
893 G_ReadDemoTiccmd (cmd);
895 G_WriteDemoTiccmd (cmd);
897 if (netgame && !(gametic%ticdup) )
899 if (gametic > BACKUPTICS
900 && consistancy[i][buf] != cmd->consistancy)
902 I_Error ("consistency failure (%i should be %i)",cmd->consistancy, consistancy[i][buf]);
905 consistancy[i][buf] = players[i].mo->x;
907 consistancy[i][buf] = rndindex;
912 // check for special buttons
914 for (i=0 ; i<MAXPLAYERS ; i++)
917 if (players[i].cmd.buttons & BT_SPECIAL)
919 switch (players[i].cmd.buttons & BT_SPECIALMASK)
934 if (!savedescription[0])
938 strcpy (savedescription, "NET GAME");
942 strcpy(savedescription, "SAVE GAME");
946 (players[i].cmd.buttons & BTS_SAVEMASK)>>BTS_SAVESHIFT;
947 gameaction = ga_savegame;
953 // turn inventory off after a certain amount of time
954 if(inventory && !(--inventoryTics))
956 players[consoleplayer].readyArtifact =
957 players[consoleplayer].inventory[inv_ptr].type;
975 case GS_INTERMISSION:
989 ==============================================================================
991 PLAYER STRUCTURE FUNCTIONS
993 also see P_SpawnPlayer in P_Things
994 ==============================================================================
997 //==========================================================================
1001 // Called when the player leaves a map.
1003 //==========================================================================
1005 void G_PlayerExitMap(int playerNumber)
1011 player = &players[playerNumber];
1015 // // Strip all but one of each type of artifact
1016 // for(i = 0; i < player->inventorySlotNum; i++)
1018 // player->inventory[i].count = 1;
1020 // player->artifactCount = player->inventorySlotNum;
1024 // Strip all current powers (retain flight)
1025 flightPower = player->powers[pw_flight];
1026 memset(player->powers, 0, sizeof(player->powers));
1027 player->powers[pw_flight] = flightPower;
1031 player->powers[pw_flight] = 0;
1035 if(P_GetMapCluster(gamemap) != P_GetMapCluster(LeaveMap))
1036 { // Entering new cluster
1040 // Strip flight artifact
1041 for(i = 0; i < 25; i++)
1043 player->powers[pw_flight] = 0;
1044 P_PlayerUseArtifact(player, arti_fly);
1046 player->powers[pw_flight] = 0;
1050 if(player->morphTics)
1052 player->readyweapon = player->mo->special1; // Restore weapon
1053 player->morphTics = 0;
1055 player->messageTics = 0;
1056 player->lookdir = 0;
1057 player->mo->flags &= ~MF_SHADOW; // Remove invisibility
1058 player->extralight = 0; // Remove weapon flashes
1059 player->fixedcolormap = 0; // Remove torch
1060 player->damagecount = 0; // No palette changes
1061 player->bonuscount = 0;
1062 player->poisoncount = 0;
1063 if(player == &players[consoleplayer])
1065 SB_state = -1; // refresh the status bar
1066 viewangleoffset = 0;
1070 //==========================================================================
1074 // Called after a player dies. Almost everything is cleared and
1077 //==========================================================================
1079 void G_PlayerReborn(int player)
1082 int frags[MAXPLAYERS];
1083 int killcount, itemcount, secretcount;
1086 memcpy(frags, players[player].frags, sizeof(frags));
1087 killcount = players[player].killcount;
1088 itemcount = players[player].itemcount;
1089 secretcount = players[player].secretcount;
1090 worldTimer = players[player].worldTimer;
1092 p = &players[player];
1093 memset(p, 0, sizeof(*p));
1095 memcpy(players[player].frags, frags, sizeof(players[player].frags));
1096 players[player].killcount = killcount;
1097 players[player].itemcount = itemcount;
1098 players[player].secretcount = secretcount;
1099 players[player].worldTimer = worldTimer;
1100 players[player].class = PlayerClass[player];
1102 p->usedown = p->attackdown = true; // don't do anything immediately
1103 p->playerstate = PST_LIVE;
1104 p->health = MAXHEALTH;
1105 p->readyweapon = p->pendingweapon = WP_FIRST;
1106 p->weaponowned[WP_FIRST] = true;
1109 localQuakeHappening[player] = false;
1110 if(p == &players[consoleplayer])
1112 SB_state = -1; // refresh the status bar
1113 inv_ptr = 0; // reset the inventory pointer
1115 viewangleoffset = 0;
1120 ====================
1124 = Returns false if the player cannot be respawned at the given mapthing_t spot
1125 = because something is occupying it
1126 ====================
1129 void P_SpawnPlayer (mapthing_t *mthing);
1131 boolean G_CheckSpot (int playernum, mapthing_t *mthing)
1138 x = mthing->x << FRACBITS;
1139 y = mthing->y << FRACBITS;
1141 players[playernum].mo->flags2 &= ~MF2_PASSMOBJ;
1142 if (!P_CheckPosition (players[playernum].mo, x, y) )
1144 players[playernum].mo->flags2 |= MF2_PASSMOBJ;
1147 players[playernum].mo->flags2 |= MF2_PASSMOBJ;
1149 // spawn a teleport fog
1150 ss = R_PointInSubsector (x,y);
1151 an = ( ANG45 * (mthing->angle/45) ) >> ANGLETOFINESHIFT;
1153 mo = P_SpawnMobj (x+20*finecosine[an], y+20*finesine[an],
1154 ss->sector->floorheight+TELEFOGHEIGHT, MT_TFOG);
1156 if (players[consoleplayer].viewz != 1)
1157 S_StartSound (mo, SFX_TELEPORT); // don't start sound on first frame
1163 ====================
1165 = G_DeathMatchSpawnPlayer
1167 = Spawns a player at one of the random death match spots
1168 = called at level load and each death
1169 ====================
1172 void G_DeathMatchSpawnPlayer (int playernum)
1177 selections = deathmatch_p - deathmatchstarts;
1179 // This check has been moved to p_setup.c:P_LoadThings()
1180 //if (selections < 8)
1181 // I_Error ("Only %i deathmatch spots, 8 required", selections);
1183 for (j=0 ; j<20 ; j++)
1185 i = P_Random() % selections;
1186 if (G_CheckSpot (playernum, &deathmatchstarts[i]) )
1188 deathmatchstarts[i].type = playernum+1;
1189 P_SpawnPlayer (&deathmatchstarts[i]);
1194 // no good spot, so the player will probably get stuck
1195 P_SpawnPlayer (&playerstarts[0][playernum]);
1198 //==========================================================================
1202 //==========================================================================
1204 void G_DoReborn(int playernum)
1207 boolean oldWeaponowned[NUMWEAPONS];
1213 if(G_CheckDemoStatus())
1219 if(SV_RebornSlotAvailable())
1220 { // Use the reborn code if the slot is available
1221 gameaction = ga_singlereborn;
1224 { // Start a new game if there's no reborn info
1225 gameaction = ga_newgame;
1230 players[playernum].mo->player = NULL; // Dissassociate the corpse
1233 { // Spawn at random spot if in death match
1234 G_DeathMatchSpawnPlayer(playernum);
1238 // Cooperative net-play, retain keys and weapons
1239 oldKeys = players[playernum].keys;
1240 oldPieces = players[playernum].pieces;
1241 for(i = 0; i < NUMWEAPONS; i++)
1243 oldWeaponowned[i] = players[playernum].weaponowned[i];
1247 if(G_CheckSpot(playernum,
1248 &playerstarts[RebornPosition][playernum]))
1249 { // Appropriate player start spot is open
1250 P_SpawnPlayer(&playerstarts[RebornPosition][playernum]);
1255 // Try to spawn at one of the other player start spots
1256 for(i = 0; i < MAXPLAYERS; i++)
1258 if(G_CheckSpot(playernum, &playerstarts[RebornPosition][i]))
1259 { // Found an open start spot
1261 // Fake as other player
1262 playerstarts[RebornPosition][i].type = playernum+1;
1263 P_SpawnPlayer(&playerstarts[RebornPosition][i]);
1265 // Restore proper player type
1266 playerstarts[RebornPosition][i].type = i+1;
1274 if(foundSpot == false)
1275 { // Player's going to be inside something
1276 P_SpawnPlayer(&playerstarts[RebornPosition][playernum]);
1279 // Restore keys and weapons
1280 players[playernum].keys = oldKeys;
1281 players[playernum].pieces = oldPieces;
1282 for(bestWeapon = 0, i = 0; i < NUMWEAPONS; i++)
1284 if(oldWeaponowned[i])
1287 players[playernum].weaponowned[i] = true;
1290 players[playernum].mana[MANA_1] = 25;
1291 players[playernum].mana[MANA_2] = 25;
1293 { // Bring up the best weapon
1294 players[playernum].pendingweapon = bestWeapon;
1299 void G_ScreenShot (void)
1301 gameaction = ga_screenshot;
1304 //==========================================================================
1308 //==========================================================================
1310 void G_StartNewInit(void)
1313 SV_ClearRebornSlot();
1315 // Default the player start spot group to 0
1319 //==========================================================================
1323 //==========================================================================
1325 void G_StartNewGame(skill_t skill)
1330 realMap = P_TranslateMap(1);
1335 G_InitNew(TempSkill, 1, realMap);
1338 //==========================================================================
1342 // Only called by the warp cheat code. Works just like normal map to map
1343 // teleporting, but doesn't do any interlude stuff.
1345 //==========================================================================
1347 void G_TeleportNewMap(int map, int position)
1349 gameaction = ga_leavemap;
1351 LeavePosition = position;
1354 //==========================================================================
1356 // G_DoTeleportNewMap
1358 //==========================================================================
1360 void G_DoTeleportNewMap(void)
1362 SV_MapTeleport(LeaveMap, LeavePosition);
1363 gamestate = GS_LEVEL;
1364 gameaction = ga_nothing;
1365 RebornPosition = LeavePosition;
1370 void G_ExitLevel (void)
1373 gameaction = ga_completed;
1375 void G_SecretExitLevel (void)
1378 gameaction = ga_completed;
1382 //==========================================================================
1386 // Starts intermission routine, which is used only during hub exits,
1387 // and DeathMatch games.
1388 //==========================================================================
1390 void G_Completed(int map, int position)
1392 gameaction = ga_completed;
1394 LeavePosition = position;
1397 void G_DoCompleted(void)
1401 gameaction = ga_nothing;
1402 if(G_CheckDemoStatus())
1406 for(i = 0; i < MAXPLAYERS; i++)
1413 if(LeaveMap == -1 && LeavePosition == -1)
1415 gameaction = ga_victory;
1420 gamestate = GS_INTERMISSION;
1426 static int afterSecret[3] = { 7, 5, 5 };
1428 gameaction = ga_nothing;
1429 if(G_CheckDemoStatus())
1433 for(i = 0; i < MAXPLAYERS; i++)
1437 G_PlayerFinishLevel(i);
1441 if(secretexit == true)
1445 else if(gamemap == 9)
1446 { // Finished secret level
1447 gamemap = afterSecret[gameepisode-1];
1449 else if(gamemap == 8)
1451 gameaction = ga_victory;
1458 gamestate = GS_INTERMISSION;
1463 //============================================================================
1467 //============================================================================
1469 void G_WorldDone(void)
1471 gameaction = ga_worlddone;
1474 //============================================================================
1478 //============================================================================
1480 void G_DoWorldDone(void)
1482 gamestate = GS_LEVEL;
1484 gameaction = ga_nothing;
1488 //==========================================================================
1492 // Called by G_Ticker based on gameaction. Loads a game from the reborn
1495 //==========================================================================
1497 void G_DoSingleReborn(void)
1499 gameaction = ga_nothing;
1500 SV_LoadGame(SV_GetRebornSlot());
1504 //==========================================================================
1508 // Can be called by the startup code or the menu task.
1510 //==========================================================================
1512 static int GameLoadSlot;
1514 void G_LoadGame(int slot)
1516 GameLoadSlot = slot;
1517 gameaction = ga_loadgame;
1520 //==========================================================================
1524 // Called by G_Ticker based on gameaction.
1526 //==========================================================================
1528 void G_DoLoadGame(void)
1530 gameaction = ga_nothing;
1531 SV_LoadGame(GameLoadSlot);
1533 { // Copy the base slot to the reborn slot
1534 SV_UpdateRebornSlot();
1539 //==========================================================================
1543 // Called by the menu task. <description> is a 24 byte text string.
1545 //==========================================================================
1547 void G_SaveGame(int slot, char *description)
1549 savegameslot = slot;
1550 strcpy(savedescription, description);
1554 //==========================================================================
1558 // Called by G_Ticker based on gameaction.
1560 //==========================================================================
1562 void G_DoSaveGame(void)
1564 SV_SaveGame(savegameslot, savedescription);
1565 gameaction = ga_nothing;
1566 savedescription[0] = 0;
1567 P_SetMessage(&players[consoleplayer], TXT_GAMESAVED, true);
1570 //==========================================================================
1572 // G_DeferredNewGame
1574 //==========================================================================
1576 void G_DeferredNewGame(skill_t skill)
1579 gameaction = ga_newgame;
1582 //==========================================================================
1586 //==========================================================================
1588 void G_DoNewGame(void)
1590 G_StartNewGame(TempSkill);
1591 gameaction = ga_nothing;
1595 ====================
1599 = Can be called by the startup code or the menu task
1600 = consoleplayer, displayplayer, playeringame[] should be set
1601 ====================
1604 void G_DeferedInitNew(skill_t skill, int episode, int map)
1607 TempEpisode = episode;
1609 gameaction = ga_initnew;
1612 void G_DoInitNew(void)
1615 G_InitNew(TempSkill, TempEpisode, TempMap);
1616 gameaction = ga_nothing;
1619 void G_InitNew(skill_t skill, int episode, int map)
1632 if(skill > sk_nightmare)
1634 skill = sk_nightmare;
1645 // Force players to be initialized upon first level load
1646 for(i = 0; i < MAXPLAYERS; i++)
1648 players[i].playerstate = PST_REBORN;
1649 players[i].worldTimer = 0;
1652 // Set up a bunch of globals
1653 usergame = true; // will be set false if a demo
1655 demorecording = false;
1656 demoplayback = false;
1658 gameepisode = episode;
1661 BorderNeedRefresh = true;
1663 // Initialize the sky
1666 // Give one null ticcmd_t
1669 //for (i=0 ; i<MAXPLAYERS ; i++)
1670 // nettics[i] = 1; // one null event for this gametic
1671 //memset (localcmds,0,sizeof(localcmds));
1672 //memset (netcmds,0,sizeof(netcmds));
1678 ===============================================================================
1682 ===============================================================================
1685 #define DEMOMARKER 0x80
1687 void G_ReadDemoTiccmd (ticcmd_t *cmd)
1689 if (*demo_p == DEMOMARKER)
1690 { // end of demo data stream
1691 G_CheckDemoStatus ();
1694 cmd->forwardmove = ((signed char)*demo_p++);
1695 cmd->sidemove = ((signed char)*demo_p++);
1696 cmd->angleturn = ((unsigned char)*demo_p++)<<8;
1697 cmd->buttons = (unsigned char)*demo_p++;
1698 cmd->lookfly = (unsigned char)*demo_p++;
1699 cmd->arti = (unsigned char)*demo_p++;
1702 void G_WriteDemoTiccmd (ticcmd_t *cmd)
1704 if (gamekeydown['q']) // press q to end demo recording
1705 G_CheckDemoStatus ();
1706 *demo_p++ = cmd->forwardmove;
1707 *demo_p++ = cmd->sidemove;
1708 *demo_p++ = cmd->angleturn>>8;
1709 *demo_p++ = cmd->buttons;
1710 *demo_p++ = cmd->lookfly;
1711 *demo_p++ = cmd->arti;
1713 G_ReadDemoTiccmd (cmd); // make SURE it is exactly the same
1726 void G_RecordDemo (skill_t skill, int numplayers, int episode, int map, char *name)
1730 G_InitNew (skill, episode, map);
1732 strcpy (demoname, name);
1733 strcat (demoname, ".lmp");
1734 demobuffer = demo_p = Z_Malloc (0x20000,PU_STATIC,NULL);
1736 *demo_p++ = episode;
1739 for (i=0 ; i<MAXPLAYERS ; i++)
1741 *demo_p++ = playeringame[i];
1742 *demo_p++ = PlayerClass[i];
1744 demorecording = true;
1758 void G_DeferedPlayDemo (char *name)
1761 gameaction = ga_playdemo;
1764 void G_DoPlayDemo (void)
1767 int i, episode, map;
1769 gameaction = ga_nothing;
1770 demobuffer = demo_p = W_CacheLumpName (defdemoname, PU_STATIC);
1772 episode = *demo_p++;
1775 for (i=0 ; i<MAXPLAYERS ; i++)
1777 playeringame[i] = *demo_p++;
1778 PlayerClass[i] = *demo_p++;
1781 // Initialize world info, etc.
1784 precache = false; // don't spend a lot of time in loadlevel
1785 G_InitNew (skill, episode, map);
1788 demoplayback = true;
1800 void G_TimeDemo (char *name)
1805 demobuffer = demo_p = W_CacheLumpName (name, PU_STATIC);
1807 episode = *demo_p++;
1809 G_InitNew (skill, episode, map);
1811 demoplayback = true;
1822 = Called after a death or level completion to allow demos to be cleaned up
1823 = Returns true if a new demo loop action will take place
1827 boolean G_CheckDemoStatus (void)
1833 endtime = I_GetTime ();
1834 I_Error ("timed %i gametics in %i realtics",gametic
1835 , endtime-starttime);
1843 Z_ChangeTag (demobuffer, PU_CACHE);
1844 demoplayback = false;
1851 *demo_p++ = DEMOMARKER;
1852 M_WriteFile (demoname, demobuffer, demo_p - demobuffer);
1853 Z_Free (demobuffer);
1854 demorecording = false;
1855 I_Error ("Demo %s recorded",demoname);