1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
6 // Copyright (C) 1993-1996 by id Software, Inc.
8 // This source is available for distribution and/or modification
9 // only under the terms of the DOOM Source Code License as
10 // published by id Software. All rights reserved.
12 // The source is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
21 //-----------------------------------------------------------------------------
25 rcsid[] = "$Id: g_game.c,v 1.8 1997/02/03 22:45:09 b1 Exp $";
49 // Needs access to LFB.
62 // SKY handling - still the wrong place.
71 #define SAVEGAMESIZE 0x2c000
72 #define SAVESTRINGSIZE 24
76 boolean G_CheckDemoStatus (void);
77 void G_ReadDemoTiccmd (ticcmd_t* cmd);
78 void G_WriteDemoTiccmd (ticcmd_t* cmd);
79 void G_PlayerReborn (int player);
80 void G_InitNew (skill_t skill, int episode, int map);
82 void G_DoReborn (int playernum);
84 void G_DoLoadLevel (void);
85 void G_DoNewGame (void);
86 void G_DoLoadGame (void);
87 void G_DoPlayDemo (void);
88 void G_DoCompleted (void);
89 void G_DoVictory (void);
90 void G_DoWorldDone (void);
91 void G_DoSaveGame (void);
94 gameaction_t gameaction;
95 gamestate_t gamestate;
97 boolean respawnmonsters;
102 boolean sendpause; // send a pause event next tic
103 boolean sendsave; // send a save event next tic
104 boolean usergame; // ok to save / end game
106 boolean timingdemo; // if true, exit with report on completion
107 boolean nodrawers; // for comparative timing purposes
108 boolean noblit; // for comparative timing purposes
109 int starttime; // for comparative timing purposes
113 boolean deathmatch; // only if started as net death
114 boolean netgame; // only true if packets are broadcast
115 boolean playeringame[MAXPLAYERS];
116 player_t players[MAXPLAYERS];
118 int consoleplayer; // player taking events and displaying
119 int displayplayer; // view being displayed
121 int levelstarttic; // gametic at level start
122 int totalkills, totalitems, totalsecret; // for intermission
125 boolean demorecording;
126 boolean demoplayback;
131 boolean singledemo; // quit after playing a demo from cmdline
133 boolean precache = true; // if true, load all graphics at start
135 wbstartstruct_t wminfo; // parms for world map / intermission
137 short consistancy[MAXPLAYERS][BACKUPTICS];
143 // controls (have defaults)
168 #define MAXPLMOVE (forwardmove[1])
170 #define TURBOTHRESHOLD 0x32
172 fixed_t forwardmove[2] = {0x19, 0x32};
173 fixed_t sidemove[2] = {0x18, 0x28};
174 fixed_t angleturn[3] = {640, 1280, 320}; // + slow turn
176 #define SLOWTURNTICS 6
180 boolean gamekeydown[NUMKEYS];
181 int turnheld; // for accelerative turning
183 boolean mousearray[4];
184 boolean* mousebuttons = &mousearray[1]; // allow [-1]
186 // mouse values are used once
197 // joystick values are repeated
201 boolean* joybuttons = &joyarray[1]; // allow [-1]
204 char savedescription[32];
207 #define BODYQUESIZE 32
209 mobj_t* bodyque[BODYQUESIZE];
212 void* statcopy; // for statistics driver
216 int G_CmdChecksum (ticcmd_t* cmd)
221 for (i=0 ; i< sizeof(*cmd)/4 - 1 ; i++)
222 sum += ((int *)cmd)[i];
230 // Builds a ticcmd from all of the available inputs
231 // or reads it from the demo buffer.
232 // If recording a demo, write it out
234 void G_BuildTiccmd (ticcmd_t* cmd)
246 base = I_BaseTiccmd (); // empty, or external driver
247 memcpy (cmd,base,sizeof(*cmd));
250 consistancy[consoleplayer][maketic%BACKUPTICS];
253 strafe = gamekeydown[key_strafe] || mousebuttons[mousebstrafe]
254 || joybuttons[joybstrafe];
255 speed = gamekeydown[key_speed] || joybuttons[joybspeed];
259 // use two stage accelerative turning
260 // on the keyboard and joystick
263 || gamekeydown[key_right]
264 || gamekeydown[key_left])
269 if (turnheld < SLOWTURNTICS)
270 tspeed = 2; // slow turn
274 // let movement keys cancel each other out
277 if (gamekeydown[key_right])
279 // fprintf(stderr, "strafe right\n");
280 side += sidemove[speed];
282 if (gamekeydown[key_left])
284 // fprintf(stderr, "strafe left\n");
285 side -= sidemove[speed];
288 side += sidemove[speed];
290 side -= sidemove[speed];
295 if (gamekeydown[key_right])
296 cmd->angleturn -= angleturn[tspeed];
297 if (gamekeydown[key_left])
298 cmd->angleturn += angleturn[tspeed];
300 cmd->angleturn -= angleturn[tspeed];
302 cmd->angleturn += angleturn[tspeed];
305 if (gamekeydown[key_up])
307 // fprintf(stderr, "up\n");
308 forward += forwardmove[speed];
310 if (gamekeydown[key_down])
312 // fprintf(stderr, "down\n");
313 forward -= forwardmove[speed];
316 forward += forwardmove[speed];
318 forward -= forwardmove[speed];
319 if (gamekeydown[key_straferight])
320 side += sidemove[speed];
321 if (gamekeydown[key_strafeleft])
322 side -= sidemove[speed];
325 cmd->chatchar = HU_dequeueChatChar();
327 if (gamekeydown[key_fire] || mousebuttons[mousebfire]
328 || joybuttons[joybfire])
329 cmd->buttons |= BT_ATTACK;
331 if (gamekeydown[key_use] || joybuttons[joybuse] )
333 cmd->buttons |= BT_USE;
334 // clear double clicks if hit use button
338 // chainsaw overrides
339 for (i=0 ; i<NUMWEAPONS-1 ; i++)
340 if (gamekeydown['1'+i])
342 cmd->buttons |= BT_CHANGE;
343 cmd->buttons |= i<<BT_WEAPONSHIFT;
348 if (mousebuttons[mousebforward])
349 forward += forwardmove[speed];
351 // forward double click
352 if (mousebuttons[mousebforward] != dclickstate && dclicktime > 1 )
354 dclickstate = mousebuttons[mousebforward];
359 cmd->buttons |= BT_USE;
367 dclicktime += ticdup;
375 // strafe double click
377 mousebuttons[mousebstrafe]
378 || joybuttons[joybstrafe];
379 if (bstrafe != dclickstate2 && dclicktime2 > 1 )
381 dclickstate2 = bstrafe;
386 cmd->buttons |= BT_USE;
394 dclicktime2 += ticdup;
395 if (dclicktime2 > 20)
406 cmd->angleturn -= mousex*0x8;
410 if (forward > MAXPLMOVE)
412 else if (forward < -MAXPLMOVE)
413 forward = -MAXPLMOVE;
414 if (side > MAXPLMOVE)
416 else if (side < -MAXPLMOVE)
419 cmd->forwardmove += forward;
420 cmd->sidemove += side;
426 cmd->buttons = BT_SPECIAL | BTS_PAUSE;
432 cmd->buttons = BT_SPECIAL | BTS_SAVEGAME | (savegameslot<<BTS_SAVESHIFT);
440 extern gamestate_t wipegamestate;
442 void G_DoLoadLevel (void)
447 // First thing, we have a dummy sky texture name,
448 // a flat. The data is in the WAD only because
449 // we look for an actual index, instead of simply
451 skyflatnum = R_FlatNumForName ( SKYFLATNAME );
453 // DOOM determines the sky texture to be used
454 // depending on the current episode, and the game version.
455 if ( (gamemode == commercial)
456 || ( gamemode == pack_tnt )
457 || ( gamemode == pack_plut ) )
459 skytexture = R_TextureNumForName ("SKY3");
461 skytexture = R_TextureNumForName ("SKY1");
464 skytexture = R_TextureNumForName ("SKY2");
467 levelstarttic = gametic; // for time calculation
469 if (wipegamestate == GS_LEVEL)
470 wipegamestate = -1; // force a wipe
472 gamestate = GS_LEVEL;
474 for (i=0 ; i<MAXPLAYERS ; i++)
476 if (playeringame[i] && players[i].playerstate == PST_DEAD)
477 players[i].playerstate = PST_REBORN;
478 memset (players[i].frags,0,sizeof(players[i].frags));
481 P_SetupLevel (gameepisode, gamemap);
482 displayplayer = consoleplayer; // view the guy you are playing
483 starttime = I_GetTime ();
484 gameaction = ga_nothing;
487 // clear cmd building stuff
488 memset (gamekeydown, 0, sizeof(gamekeydown));
489 joyxmove = joyymove = 0;
491 sendpause = sendsave = paused = false;
492 memset (mousebuttons, 0, sizeof(mousebuttons));
493 memset (joybuttons, 0, sizeof(joybuttons));
499 // Get info needed to make ticcmd_ts for the players.
501 boolean G_Responder (event_t* ev)
503 // allow spy mode changes even during the demo
504 if (gamestate == GS_LEVEL && ev->type == ev_keydown
505 && ev->data1 == KEY_F12 && (singledemo || !deathmatch) )
511 if (displayplayer == MAXPLAYERS)
513 } while (!playeringame[displayplayer] && displayplayer != consoleplayer);
517 // any other key pops up menu if in demos
518 if (gameaction == ga_nothing && !singledemo &&
519 (demoplayback || gamestate == GS_DEMOSCREEN)
522 if (ev->type == ev_keydown ||
523 (ev->type == ev_mouse && ev->data1) ||
524 (ev->type == ev_joystick && ev->data1) )
526 M_StartControlPanel ();
532 if (gamestate == GS_LEVEL)
534 if (HU_Responder (ev))
535 return true; // chat ate the event
536 if (ST_Responder (ev))
537 return true; // status window ate it
538 if (AM_Responder (ev))
539 return true; // automap ate it
542 if (gamestate == GS_FINALE)
544 if (F_Responder (ev))
545 return true; // finale ate the event
551 if (ev->data1 == KEY_PAUSE)
556 if (ev->data1 <NUMKEYS)
557 gamekeydown[ev->data1] = true;
558 return true; // eat key down events
561 if (ev->data1 <NUMKEYS)
562 gamekeydown[ev->data1] = false;
563 return false; // always let key up events filter down
566 mousebuttons[0] = ev->data1 & 1;
567 mousebuttons[1] = ev->data1 & 2;
568 mousebuttons[2] = ev->data1 & 4;
569 mousex = ev->data2*(mouseSensitivity+5)/10;
570 mousey = ev->data3*(mouseSensitivity+5)/10;
571 return true; // eat events
574 joybuttons[0] = ev->data1 & 1;
575 joybuttons[1] = ev->data1 & 2;
576 joybuttons[2] = ev->data1 & 4;
577 joybuttons[3] = ev->data1 & 8;
578 joyxmove = ev->data2;
579 joyymove = ev->data3;
580 return true; // eat events
593 // Make ticcmd_ts for the players.
601 // do player reborns if needed
602 for (i=0 ; i<MAXPLAYERS ; i++)
603 if (playeringame[i] && players[i].playerstate == PST_REBORN)
606 // do things to change the game state
607 while (gameaction != ga_nothing)
637 gameaction = ga_nothing;
644 // get commands, check consistancy,
645 // and build new consistancy check
646 buf = (gametic/ticdup)%BACKUPTICS;
648 for (i=0 ; i<MAXPLAYERS ; i++)
652 cmd = &players[i].cmd;
654 memcpy (cmd, &netcmds[i][buf], sizeof(ticcmd_t));
657 G_ReadDemoTiccmd (cmd);
659 G_WriteDemoTiccmd (cmd);
661 // check for turbo cheats
662 if (cmd->forwardmove > TURBOTHRESHOLD
663 && !(gametic&31) && ((gametic>>5)&3) == i )
665 static char turbomessage[80];
666 extern char *player_names[4];
667 sprintf (turbomessage, "%s is turbo!",player_names[i]);
668 players[consoleplayer].message = turbomessage;
671 if (netgame && !netdemo && !(gametic%ticdup) )
673 if (gametic > BACKUPTICS
674 && consistancy[i][buf] != cmd->consistancy)
676 I_Error ("consistency failure (%i should be %i)",
677 cmd->consistancy, consistancy[i][buf]);
680 consistancy[i][buf] = players[i].mo->x;
682 consistancy[i][buf] = rndindex;
687 // check for special buttons
688 for (i=0 ; i<MAXPLAYERS ; i++)
692 if (players[i].cmd.buttons & BT_SPECIAL)
694 switch (players[i].cmd.buttons & BT_SPECIALMASK)
705 if (!savedescription[0])
706 strcpy (savedescription, "NET GAME");
708 (players[i].cmd.buttons & BTS_SAVEMASK)>>BTS_SAVESHIFT;
709 gameaction = ga_savegame;
726 case GS_INTERMISSION:
742 // PLAYER STRUCTURE FUNCTIONS
743 // also see P_SpawnPlayer in P_Things
748 // Called at the start.
749 // Called by the game initialization functions.
751 void G_InitPlayer (int player)
753 // clear everything else to defaults
754 G_PlayerReborn (player);
760 // G_PlayerFinishLevel
761 // Can when a player completes a level.
763 void G_PlayerFinishLevel (int player)
767 p = &players[player];
769 memset (p->powers, 0, sizeof (p->powers));
770 memset (p->cards, 0, sizeof (p->cards));
771 p->mo->flags &= ~MF_SHADOW; // cancel invisibility
772 p->extralight = 0; // cancel gun flashes
773 p->fixedcolormap = 0; // cancel ir gogles
774 p->damagecount = 0; // no palette changes
781 // Called after a player dies
782 // almost everything is cleared and initialized
784 void G_PlayerReborn (int player)
788 int frags[MAXPLAYERS];
793 memcpy (frags,players[player].frags,sizeof(frags));
794 killcount = players[player].killcount;
795 itemcount = players[player].itemcount;
796 secretcount = players[player].secretcount;
798 p = &players[player];
799 memset (p, 0, sizeof(*p));
801 memcpy (players[player].frags, frags, sizeof(players[player].frags));
802 players[player].killcount = killcount;
803 players[player].itemcount = itemcount;
804 players[player].secretcount = secretcount;
806 p->usedown = p->attackdown = true; // don't do anything immediately
807 p->playerstate = PST_LIVE;
808 p->health = MAXHEALTH;
809 p->readyweapon = p->pendingweapon = wp_pistol;
810 p->weaponowned[wp_fist] = true;
811 p->weaponowned[wp_pistol] = true;
812 p->ammo[am_clip] = 50;
814 for (i=0 ; i<NUMAMMO ; i++)
815 p->maxammo[i] = maxammo[i];
821 // Returns false if the player cannot be respawned
822 // at the given mapthing_t spot
823 // because something is occupying it
825 void P_SpawnPlayer (mapthing_t* mthing);
839 if (!players[playernum].mo)
841 // first spawn of level, before corpses
842 for (i=0 ; i<playernum ; i++)
843 if (players[i].mo->x == mthing->x << FRACBITS
844 && players[i].mo->y == mthing->y << FRACBITS)
849 x = mthing->x << FRACBITS;
850 y = mthing->y << FRACBITS;
852 if (!P_CheckPosition (players[playernum].mo, x, y) )
855 // flush an old corpse if needed
856 if (bodyqueslot >= BODYQUESIZE)
857 P_RemoveMobj (bodyque[bodyqueslot%BODYQUESIZE]);
858 bodyque[bodyqueslot%BODYQUESIZE] = players[playernum].mo;
861 // spawn a teleport fog
862 ss = R_PointInSubsector (x,y);
863 an = ( ANG45 * (mthing->angle/45) ) >> ANGLETOFINESHIFT;
865 mo = P_SpawnMobj (x+20*finecosine[an], y+20*finesine[an]
866 , ss->sector->floorheight
869 if (players[consoleplayer].viewz != 1)
870 S_StartSound (mo, sfx_telept); // don't start sound on first frame
877 // G_DeathMatchSpawnPlayer
878 // Spawns a player at one of the random death match spots
879 // called at level load and each death
881 void G_DeathMatchSpawnPlayer (int playernum)
886 selections = deathmatch_p - deathmatchstarts;
888 I_Error ("Only %i deathmatch spots, 4 required", selections);
890 for (j=0 ; j<20 ; j++)
892 i = P_Random() % selections;
893 if (G_CheckSpot (playernum, &deathmatchstarts[i]) )
895 deathmatchstarts[i].type = playernum+1;
896 P_SpawnPlayer (&deathmatchstarts[i]);
901 // no good spot, so the player will probably get stuck
902 P_SpawnPlayer (&playerstarts[playernum]);
908 void G_DoReborn (int playernum)
914 // reload the level from scratch
915 gameaction = ga_loadlevel;
919 // respawn at the start
921 // first dissasociate the corpse
922 players[playernum].mo->player = NULL;
924 // spawn at random spot if in death match
927 G_DeathMatchSpawnPlayer (playernum);
931 if (G_CheckSpot (playernum, &playerstarts[playernum]) )
933 P_SpawnPlayer (&playerstarts[playernum]);
937 // try to spawn at one of the other players spots
938 for (i=0 ; i<MAXPLAYERS ; i++)
940 if (G_CheckSpot (playernum, &playerstarts[i]) )
942 playerstarts[i].type = playernum+1; // fake as other player
943 P_SpawnPlayer (&playerstarts[i]);
944 playerstarts[i].type = i+1; // restore
947 // he's going to be inside something. Too bad.
949 P_SpawnPlayer (&playerstarts[playernum]);
954 void G_ScreenShot (void)
956 gameaction = ga_screenshot;
965 {0,30,75,120,90,165,180,180,30,165},
966 {0,90,90,90,120,90,360,240,30,170},
967 {0,90,45,90,150,90,90,165,30,135}
973 30,90,120,120,90,150,120,120,270,90, // 1-10
974 210,150,150,150,210,150,420,150,210,150, // 11-20
975 240,150,180,150,150,300,330,420,300,180, // 21-30
984 extern char* pagename;
986 void G_ExitLevel (void)
989 gameaction = ga_completed;
992 // Here's for the german edition.
993 void G_SecretExitLevel (void)
995 // IF NO WOLF3D LEVELS, NO SECRET EXIT!
996 if ( (gamemode == commercial)
997 && (W_CheckNumForName("map31")<0))
1001 gameaction = ga_completed;
1004 void G_DoCompleted (void)
1008 gameaction = ga_nothing;
1010 for (i=0 ; i<MAXPLAYERS ; i++)
1011 if (playeringame[i])
1012 G_PlayerFinishLevel (i); // take away cards and stuff
1017 if ( gamemode != commercial)
1021 gameaction = ga_victory;
1024 for (i=0 ; i<MAXPLAYERS ; i++)
1025 players[i].didsecret = true;
1031 && (gamemode != commercial) )
1034 gameaction = ga_victory;
1039 && (gamemode != commercial) )
1041 // exit secret level
1042 for (i=0 ; i<MAXPLAYERS ; i++)
1043 players[i].didsecret = true;
1048 wminfo.didsecret = players[consoleplayer].didsecret;
1049 wminfo.epsd = gameepisode -1;
1050 wminfo.last = gamemap -1;
1052 // wminfo.next is 0 biased, unlike gamemap
1053 if ( gamemode == commercial)
1058 case 15: wminfo.next = 30; break;
1059 case 31: wminfo.next = 31; break;
1065 case 32: wminfo.next = 15; break;
1066 default: wminfo.next = gamemap;
1072 wminfo.next = 8; // go to secret level
1073 else if (gamemap == 9)
1075 // returning from secret level
1076 switch (gameepisode)
1093 wminfo.next = gamemap; // go to next level
1096 wminfo.maxkills = totalkills;
1097 wminfo.maxitems = totalitems;
1098 wminfo.maxsecret = totalsecret;
1099 wminfo.maxfrags = 0;
1100 if ( gamemode == commercial )
1101 wminfo.partime = 35*cpars[gamemap-1];
1103 wminfo.partime = 35*pars[gameepisode][gamemap];
1104 wminfo.pnum = consoleplayer;
1106 for (i=0 ; i<MAXPLAYERS ; i++)
1108 wminfo.plyr[i].in = playeringame[i];
1109 wminfo.plyr[i].skills = players[i].killcount;
1110 wminfo.plyr[i].sitems = players[i].itemcount;
1111 wminfo.plyr[i].ssecret = players[i].secretcount;
1112 wminfo.plyr[i].stime = leveltime;
1113 memcpy (wminfo.plyr[i].frags, players[i].frags
1114 , sizeof(wminfo.plyr[i].frags));
1117 gamestate = GS_INTERMISSION;
1119 automapactive = false;
1122 memcpy (statcopy, &wminfo, sizeof(wminfo));
1131 void G_WorldDone (void)
1133 gameaction = ga_worlddone;
1136 players[consoleplayer].didsecret = true;
1138 if ( gamemode == commercial )
1156 void G_DoWorldDone (void)
1158 gamestate = GS_LEVEL;
1159 gamemap = wminfo.next+1;
1161 gameaction = ga_nothing;
1168 // G_InitFromSavegame
1169 // Can be called by the startup code or the menu task.
1171 extern boolean setsizeneeded;
1172 void R_ExecuteSetViewSize (void);
1176 void G_LoadGame (char* name)
1178 strcpy (savename, name);
1179 gameaction = ga_loadgame;
1182 #define VERSIONSIZE 16
1185 void G_DoLoadGame (void)
1189 char vcheck[VERSIONSIZE];
1191 gameaction = ga_nothing;
1193 M_ReadFile (savename, &savebuffer);
1194 save_p = savebuffer + SAVESTRINGSIZE;
1196 // skip the description field
1197 memset (vcheck,0,sizeof(vcheck));
1198 sprintf (vcheck,"version %i",VERSION);
1199 if (strcmp ((char*)save_p, vcheck))
1200 return; // bad version
1201 save_p += VERSIONSIZE;
1203 gameskill = *save_p++;
1204 gameepisode = *save_p++;
1205 gamemap = *save_p++;
1206 for (i=0 ; i<MAXPLAYERS ; i++)
1207 playeringame[i] = *save_p++;
1209 // load a base level
1210 G_InitNew (gameskill, gameepisode, gamemap);
1216 leveltime = (a<<16) + (b<<8) + c;
1218 // dearchive all the modifications
1219 P_UnArchivePlayers ();
1220 P_UnArchiveWorld ();
1221 P_UnArchiveThinkers ();
1222 P_UnArchiveSpecials ();
1224 if (*save_p != 0x1d)
1225 I_Error ("Bad savegame");
1228 Z_Free (savebuffer);
1231 R_ExecuteSetViewSize ();
1233 // draw the pattern into the back screen
1234 R_FillBackScreen ();
1240 // Called by the menu task.
1241 // Description is a 24 byte text string
1248 savegameslot = slot;
1249 strcpy (savedescription, description);
1253 void G_DoSaveGame (void)
1256 char name2[VERSIONSIZE];
1261 if (M_CheckParm("-cdrom"))
1262 sprintf(name,"c:\\doomdata\\"SAVEGAMENAME"%d.dsg",savegameslot);
1264 sprintf (name,SAVEGAMENAME"%d.dsg",savegameslot);
1265 description = savedescription;
1267 save_p = savebuffer = screens[1]+0x4000;
1269 memcpy (save_p, description, SAVESTRINGSIZE);
1270 save_p += SAVESTRINGSIZE;
1271 memset (name2,0,sizeof(name2));
1272 sprintf (name2,"version %i",VERSION);
1273 memcpy (save_p, name2, VERSIONSIZE);
1274 save_p += VERSIONSIZE;
1276 *save_p++ = gameskill;
1277 *save_p++ = gameepisode;
1278 *save_p++ = gamemap;
1279 for (i=0 ; i<MAXPLAYERS ; i++)
1280 *save_p++ = playeringame[i];
1281 *save_p++ = leveltime>>16;
1282 *save_p++ = leveltime>>8;
1283 *save_p++ = leveltime;
1285 P_ArchivePlayers ();
1287 P_ArchiveThinkers ();
1288 P_ArchiveSpecials ();
1290 *save_p++ = 0x1d; // consistancy marker
1292 length = save_p - savebuffer;
1293 if (length > SAVEGAMESIZE)
1294 I_Error ("Savegame buffer overrun");
1295 M_WriteFile (name, savebuffer, length);
1296 gameaction = ga_nothing;
1297 savedescription[0] = 0;
1299 players[consoleplayer].message = GGSAVED;
1301 // draw the pattern into the back screen
1302 R_FillBackScreen ();
1308 // Can be called by the startup code or the menu task,
1309 // consoleplayer, displayplayer, playeringame[] should be set.
1322 d_episode = episode;
1324 gameaction = ga_newgame;
1328 void G_DoNewGame (void)
1330 demoplayback = false;
1334 playeringame[1] = playeringame[2] = playeringame[3] = 0;
1335 respawnparm = false;
1339 G_InitNew (d_skill, d_episode, d_map);
1340 gameaction = ga_nothing;
1343 // The sky texture to be used instead of the F_SKY1 dummy.
1344 extern int skytexture;
1362 if (skill > sk_nightmare)
1363 skill = sk_nightmare;
1366 // This was quite messy with SPECIAL and commented parts.
1367 // Supposedly hacks to make the latest edition work.
1368 // It might not work properly.
1372 if ( gamemode == retail )
1377 else if ( gamemode == shareware )
1380 episode = 1; // only start episode 1 on shareware
1394 && ( gamemode != commercial) )
1399 if (skill == sk_nightmare || respawnparm )
1400 respawnmonsters = true;
1402 respawnmonsters = false;
1404 if (fastparm || (skill == sk_nightmare && gameskill != sk_nightmare) )
1406 for (i=S_SARG_RUN1 ; i<=S_SARG_PAIN2 ; i++)
1407 states[i].tics >>= 1;
1408 mobjinfo[MT_BRUISERSHOT].speed = 20*FRACUNIT;
1409 mobjinfo[MT_HEADSHOT].speed = 20*FRACUNIT;
1410 mobjinfo[MT_TROOPSHOT].speed = 20*FRACUNIT;
1412 else if (skill != sk_nightmare && gameskill == sk_nightmare)
1414 for (i=S_SARG_RUN1 ; i<=S_SARG_PAIN2 ; i++)
1415 states[i].tics <<= 1;
1416 mobjinfo[MT_BRUISERSHOT].speed = 15*FRACUNIT;
1417 mobjinfo[MT_HEADSHOT].speed = 10*FRACUNIT;
1418 mobjinfo[MT_TROOPSHOT].speed = 10*FRACUNIT;
1422 // force players to be initialized upon first level load
1423 for (i=0 ; i<MAXPLAYERS ; i++)
1424 players[i].playerstate = PST_REBORN;
1426 usergame = true; // will be set false if a demo
1428 demoplayback = false;
1429 automapactive = false;
1431 gameepisode = episode;
1436 // set the sky map for the episode
1437 if ( gamemode == commercial)
1439 skytexture = R_TextureNumForName ("SKY3");
1441 skytexture = R_TextureNumForName ("SKY1");
1444 skytexture = R_TextureNumForName ("SKY2");
1450 skytexture = R_TextureNumForName ("SKY1");
1453 skytexture = R_TextureNumForName ("SKY2");
1456 skytexture = R_TextureNumForName ("SKY3");
1458 case 4: // Special Edition sky
1459 skytexture = R_TextureNumForName ("SKY4");
1470 #define DEMOMARKER 0x80
1473 void G_ReadDemoTiccmd (ticcmd_t* cmd)
1475 if (*demo_p == DEMOMARKER)
1477 // end of demo data stream
1478 G_CheckDemoStatus ();
1481 cmd->forwardmove = ((signed char)*demo_p++);
1482 cmd->sidemove = ((signed char)*demo_p++);
1483 cmd->angleturn = ((unsigned char)*demo_p++)<<8;
1484 cmd->buttons = (unsigned char)*demo_p++;
1488 void G_WriteDemoTiccmd (ticcmd_t* cmd)
1490 if (gamekeydown['q']) // press q to end demo recording
1491 G_CheckDemoStatus ();
1492 *demo_p++ = cmd->forwardmove;
1493 *demo_p++ = cmd->sidemove;
1494 *demo_p++ = (cmd->angleturn+128)>>8;
1495 *demo_p++ = cmd->buttons;
1497 if (demo_p > demoend - 16)
1500 G_CheckDemoStatus ();
1504 G_ReadDemoTiccmd (cmd); // make SURE it is exactly the same
1512 void G_RecordDemo (char* name)
1518 strcpy (demoname, name);
1519 strcat (demoname, ".lmp");
1521 i = M_CheckParm ("-maxdemo");
1522 if (i && i<myargc-1)
1523 maxsize = atoi(myargv[i+1])*1024;
1524 demobuffer = Z_Malloc (maxsize,PU_STATIC,NULL);
1525 demoend = demobuffer + maxsize;
1527 demorecording = true;
1531 void G_BeginRecording (void)
1535 demo_p = demobuffer;
1537 *demo_p++ = VERSION;
1538 *demo_p++ = gameskill;
1539 *demo_p++ = gameepisode;
1540 *demo_p++ = gamemap;
1541 *demo_p++ = deathmatch;
1542 *demo_p++ = respawnparm;
1543 *demo_p++ = fastparm;
1544 *demo_p++ = nomonsters;
1545 *demo_p++ = consoleplayer;
1547 for (i=0 ; i<MAXPLAYERS ; i++)
1548 *demo_p++ = playeringame[i];
1558 void G_DeferedPlayDemo (char* name)
1561 gameaction = ga_playdemo;
1564 void G_DoPlayDemo (void)
1567 int i, episode, map;
1569 gameaction = ga_nothing;
1570 demobuffer = demo_p = W_CacheLumpName (defdemoname, PU_STATIC);
1571 switch (*demo_p++) {
1575 fprintf(stderr, "Demo is from a different game version!\n");
1576 fprintf(stderr, "VERSION=%d demover=%d\n", VERSION, *demo_p);
1579 gameaction = ga_nothing;
1585 episode = *demo_p++;
1587 deathmatch = *demo_p++;
1588 respawnparm = *demo_p++;
1589 fastparm = *demo_p++;
1590 nomonsters = *demo_p++;
1591 consoleplayer = *demo_p++;
1593 // PORTME TODO : MAXPLAYERS assumes 4 in demo format
1594 for (i=0 ; i<MAXPLAYERS ; i++)
1595 playeringame[i] = *demo_p++;
1596 if (playeringame[1])
1602 // don't spend a lot of time in loadlevel
1604 G_InitNew (skill, episode, map);
1608 demoplayback = true;
1614 void G_TimeDemo (char* name)
1616 nodrawers = M_CheckParm ("-nodraw");
1617 noblit = M_CheckParm ("-noblit");
1622 gameaction = ga_playdemo;
1631 = Called after a death or level completion to allow demos to be cleaned up
1632 = Returns true if a new demo loop action will take place
1636 boolean G_CheckDemoStatus (void)
1642 endtime = I_GetTime ();
1643 I_Error ("timed %i gametics in %i realtics",gametic
1644 , endtime-starttime);
1652 Z_ChangeTag (demobuffer, PU_CACHE);
1653 demoplayback = false;
1657 playeringame[1] = playeringame[2] = playeringame[3] = 0;
1658 respawnparm = false;
1668 *demo_p++ = DEMOMARKER;
1669 M_WriteFile (demoname, demobuffer, demo_p - demobuffer);
1670 Z_Free (demobuffer);
1671 demorecording = false;
1672 I_Error ("Demo %s recorded",demoname);