g_game.c (22772B)
1 #include <string.h> 2 #include <stdlib.h> 3 4 #include "doomdef.h" 5 #include "doomstat.h" 6 #include "z_zone.h" 7 #include "f_finale.h" 8 #include "m_argv.h" 9 #include "m_misc.h" 10 #include "m_menu.h" 11 #include "m_random.h" 12 #include "i_system.h" 13 #include "p_setup.h" 14 #include "p_saveg.h" 15 #include "p_tick.h" 16 #include "d_main.h" 17 #include "wi_stuff.h" 18 #include "hu_stuff.h" 19 #include "st_stuff.h" 20 #include "am_map.h" 21 #include "v_video.h" 22 #include "w_wad.h" 23 #include "p_local.h" 24 #include "s_sound.h" 25 #include "sounds.h" 26 #include "r_data.h" 27 #include "g_game.h" 28 29 #define SAVEGAMESIZE 0x2c000 30 #define SAVESTRINGSIZE 24 31 #define MAXPLMOVE (forwardmove[1]) 32 #define TURBOTHRESHOLD 0x32 33 #define SLOWTURNTICS 6 34 #define NUMKEYS 256 35 #define BODYQUESIZE 32 36 #define VERSIONSIZE 16 37 #define DEMOMARKER 0x80 38 39 boolean G_CheckDemoStatus (); 40 void G_ReadDemoTiccmd (ticcmd_t* cmd); 41 void G_WriteDemoTiccmd (ticcmd_t* cmd); 42 void G_PlayerReborn (int player); 43 void G_InitNew (skill_t skill, int episode, int map); 44 void G_DoReborn (int playernum); 45 void G_DoLoadLevel (); 46 void G_DoNewGame (); 47 void G_DoLoadGame (); 48 void G_DoPlayDemo (); 49 void G_DoCompleted (); 50 void G_DoVictory (); 51 void G_DoWorldDone (); 52 void G_DoSaveGame (); 53 void R_ExecuteSetViewSize (); 54 55 extern gamestate_t wipegamestate; 56 extern boolean setsizeneeded; 57 extern char* pagename; 58 extern int skytexture; 59 skill_t d_skill; 60 int d_episode; 61 int d_map; 62 boolean secretexit; 63 gameaction_t gameaction; 64 gamestate_t gamestate; 65 skill_t gameskill; 66 boolean respawnmonsters; 67 int gameepisode; 68 int gamemap; 69 boolean paused; 70 boolean sendpause; 71 boolean sendsave; 72 boolean usergame; 73 boolean timingdemo; 74 boolean nodrawers; 75 boolean noblit; 76 int starttime; 77 boolean viewactive; 78 boolean deathmatch; 79 boolean netgame; 80 boolean playeringame[MAXPLAYERS]; 81 player_t players[MAXPLAYERS]; 82 int consoleplayer; 83 int displayplayer; 84 int gametic; 85 int levelstarttic; 86 int totalkills, totalitems, totalsecret; 87 char demoname[32]; 88 boolean demorecording; 89 boolean demoplayback; 90 boolean netdemo; 91 byte* demobuffer; 92 byte* demo_p; 93 byte* demoend; 94 boolean singledemo; 95 boolean precache = true; 96 wbstartstruct_t wminfo; 97 short consistancy[MAXPLAYERS][BACKUPTICS]; 98 byte* savebuffer; 99 int key_right; 100 int key_left; 101 int key_up; 102 int key_down; 103 int key_strafeleft; 104 int key_straferight; 105 int key_fire; 106 int key_use; 107 int key_strafe; 108 int key_speed; 109 int mousebfire; 110 int mousebstrafe; 111 int mousebforward; 112 int joybfire; 113 int joybstrafe; 114 int joybuse; 115 int joybspeed; 116 fixed_t forwardmove[2] = {0x19, 0x32}; 117 fixed_t sidemove[2] = {0x18, 0x28}; 118 fixed_t angleturn[3] = {640, 1280, 320}; 119 boolean gamekeydown[NUMKEYS]; 120 int turnheld; 121 boolean mousearray[4]; 122 boolean* mousebuttons = &mousearray[1]; 123 int mousex; 124 int mousey; 125 int dclicktime; 126 int dclickstate; 127 int dclicks; 128 int dclicktime2; 129 int dclickstate2; 130 int dclicks2; 131 int joyxmove; 132 int joyymove; 133 boolean joyarray[5]; 134 boolean* joybuttons = &joyarray[1]; 135 int savegameslot; 136 char savedescription[32]; 137 mobj_t* bodyque[BODYQUESIZE]; 138 int bodyqueslot; 139 void* statcopy; 140 char* defdemoname; 141 142 int pars[4][10] = { 143 {0}, 144 {0,30,75,120,90,165,180,180,30,165}, 145 {0,90,90,90,120,90,360,240,30,170}, 146 {0,90,45,90,150,90,90,165,30,135} 147 }; 148 149 int cpars[32] = { 150 30,90,120,120,90,150,120,120,270,90, 151 210,150,150,150,210,150,420,150,210,150, 152 240,150,180,150,150,300,330,420,300,180, 153 120,30 154 }; 155 156 int 157 G_CmdChecksum(ticcmd_t* cmd) 158 { 159 int i, sum; 160 161 for (sum = i = 0; i < sizeof(*cmd)/4 - 1; ++i) sum += ((int*)cmd)[i]; 162 return sum; 163 } 164 165 void 166 G_BuildTiccmd(ticcmd_t* cmd) 167 { 168 static ticcmd_t base; 169 int i, speed, tspeed, forward, side; 170 boolean strafe, bstrafe; 171 172 memcpy(cmd, &base, sizeof(*cmd)); 173 cmd->consistancy = consistancy[consoleplayer][maketic%BACKUPTICS]; 174 strafe = gamekeydown[key_strafe] || mousebuttons[mousebstrafe] || joybuttons[joybstrafe]; 175 speed = gamekeydown[key_speed] || joybuttons[joybspeed]; 176 forward = side = 0; 177 if (joyxmove < 0 || joyxmove > 0 || gamekeydown[key_right] || gamekeydown[key_left]) turnheld += ticdup; 178 else turnheld = 0; 179 if (turnheld < SLOWTURNTICS) tspeed = 2; 180 else tspeed = speed; 181 if (strafe) { 182 if (gamekeydown[key_right]) side += sidemove[speed]; 183 if (gamekeydown[key_left]) side -= sidemove[speed]; 184 if (joyxmove > 0) side += sidemove[speed]; 185 if (joyxmove < 0) side -= sidemove[speed]; 186 } 187 else { 188 if (gamekeydown[key_right]) cmd->angleturn -= angleturn[tspeed]; 189 if (gamekeydown[key_left]) cmd->angleturn += angleturn[tspeed]; 190 if (joyxmove > 0) cmd->angleturn -= angleturn[tspeed]; 191 if (joyxmove < 0) cmd->angleturn += angleturn[tspeed]; 192 } 193 if (gamekeydown[key_up]) forward += forwardmove[speed]; 194 if (gamekeydown[key_down]) forward -= forwardmove[speed]; 195 if (joyymove < 0) forward += forwardmove[speed]; 196 if (joyymove > 0) forward -= forwardmove[speed]; 197 if (gamekeydown[key_straferight]) side += sidemove[speed]; 198 if (gamekeydown[key_strafeleft]) side -= sidemove[speed]; 199 cmd->chatchar = HU_dequeueChatChar(); 200 if (gamekeydown[key_fire] || mousebuttons[mousebfire] || joybuttons[joybfire]) 201 cmd->buttons |= BT_ATTACK; 202 if (gamekeydown[key_use] || joybuttons[joybuse]) { 203 cmd->buttons |= BT_USE; 204 dclicks = 0; 205 } 206 for (i = 0; i < NUMWEAPONS - 1; ++i) 207 if (gamekeydown['1'+i]) { 208 cmd->buttons |= BT_CHANGE; 209 cmd->buttons |= i<<BT_WEAPONSHIFT; 210 break; 211 } 212 if (mousebuttons[mousebforward]) forward += forwardmove[speed]; 213 if (mousebuttons[mousebforward] != dclickstate && dclicktime > 1 ) { 214 dclickstate = mousebuttons[mousebforward]; 215 if (dclickstate) dclicks++; 216 if (dclicks == 2) { 217 cmd->buttons |= BT_USE; 218 dclicks = 0; 219 } else dclicktime = 0; 220 } else { 221 dclicktime += ticdup; 222 if (dclicktime > 20) { 223 dclicks = 0; 224 dclickstate = 0; 225 } 226 } 227 bstrafe = mousebuttons[mousebstrafe] || joybuttons[joybstrafe]; 228 if (bstrafe != dclickstate2 && dclicktime2 > 1 ) { 229 dclickstate2 = bstrafe; 230 if (dclickstate2) dclicks2++; 231 if (dclicks2 == 2) { 232 cmd->buttons |= BT_USE; 233 dclicks2 = 0; 234 } else dclicktime2 = 0; 235 } else { 236 dclicktime2 += ticdup; 237 if (dclicktime2 > 20) { 238 dclicks2 = 0; 239 dclickstate2 = 0; 240 } 241 } 242 forward += mousey; 243 if (strafe) side += mousex * 2; 244 else cmd->angleturn -= mousex*0x8; 245 mousex = mousey = 0; 246 if (forward > MAXPLMOVE) forward = MAXPLMOVE; 247 if (forward < -MAXPLMOVE) forward = -MAXPLMOVE; 248 if (side > MAXPLMOVE) side = MAXPLMOVE; 249 if (side < -MAXPLMOVE) side = -MAXPLMOVE; 250 cmd->forwardmove += forward; 251 cmd->sidemove += side; 252 if (sendpause) { 253 sendpause = false; 254 cmd->buttons = BT_SPECIAL | BTS_PAUSE; 255 } 256 if (sendsave) { 257 sendsave = false; 258 cmd->buttons = BT_SPECIAL | BTS_SAVEGAME | (savegameslot<<BTS_SAVESHIFT); 259 } 260 } 261 262 void 263 G_DoLoadLevel() 264 { 265 int i; 266 267 skyflatnum = R_FlatNumForName(SKYFLATNAME); 268 levelstarttic = gametic; 269 if (wipegamestate == GS_LEVEL) wipegamestate = -1; 270 gamestate = GS_LEVEL; 271 for (i = 0; i < MAXPLAYERS; ++i) { 272 if (playeringame[i] && players[i].playerstate == PST_DEAD) players[i].playerstate = PST_REBORN; 273 memset(players[i].frags,0,sizeof(players[i].frags)); 274 } 275 P_SetupLevel(gameepisode, gamemap, 0, gameskill); 276 displayplayer = consoleplayer; 277 starttime = I_GetTime(); 278 gameaction = ga_nothing; 279 Z_CheckHeap(); 280 memset(gamekeydown, 0, sizeof(gamekeydown)); 281 joyxmove = joyymove = 0; 282 mousex = mousey = 0; 283 sendpause = sendsave = paused = false; 284 memset(mousebuttons, 0, sizeof(*mousebuttons)); 285 memset(joybuttons, 0, sizeof(*joybuttons)); 286 } 287 288 boolean 289 G_Responder(event_t* ev) 290 { 291 if (gamestate == GS_LEVEL && ev->type == ev_keydown && ev->data1 == KEY_F12 && (singledemo || !deathmatch)) { 292 do { 293 displayplayer++; 294 if (displayplayer == MAXPLAYERS) displayplayer = 0; 295 } while (!playeringame[displayplayer] && displayplayer != consoleplayer); 296 return true; 297 } 298 if (gameaction == ga_nothing && !singledemo && (demoplayback || gamestate == GS_DEMOSCREEN)) { 299 if (ev->type == ev_keydown || (ev->type == ev_mouse && ev->data1) || (ev->type == ev_joystick && ev->data1)) { 300 M_StartControlPanel(); 301 return true; 302 } 303 return false; 304 } 305 if (gamestate == GS_LEVEL) { 306 if (HU_Responder(ev)) 307 return true; 308 if (ST_Responder(ev)) 309 return true; 310 if (AM_Responder(ev)) 311 return true; 312 } 313 if (gamestate == GS_FINALE) 314 if (F_Responder(ev)) return true; 315 316 switch (ev->type) { 317 case ev_keydown: 318 if (ev->data1 == KEY_PAUSE) { 319 sendpause = true; 320 return true; 321 } 322 if (ev->data1 <NUMKEYS) gamekeydown[ev->data1] = true; 323 return true; 324 case ev_keyup: 325 if (ev->data1 <NUMKEYS) gamekeydown[ev->data1] = false; 326 return false; 327 case ev_mouse: 328 mousebuttons[0] = ev->data1 & 1; 329 mousebuttons[1] = ev->data1 & 2; 330 mousebuttons[2] = ev->data1 & 4; 331 mousex = ev->data2*(mouseSensitivity+5)/10; 332 mousey = ev->data3*(mouseSensitivity+5)/10; 333 return true; 334 case ev_joystick: 335 joybuttons[0] = ev->data1 & 1; 336 joybuttons[1] = ev->data1 & 2; 337 joybuttons[2] = ev->data1 & 4; 338 joybuttons[3] = ev->data1 & 8; 339 joyxmove = ev->data2; 340 joyymove = ev->data3; 341 return true; 342 default: 343 return false; 344 } 345 } 346 347 void 348 G_Ticker() 349 { 350 int i, buf; 351 ticcmd_t* cmd; 352 353 354 for (i = 0; i < MAXPLAYERS; ++i) if(playeringame[i] && players[i].playerstate == PST_REBORN) G_DoReborn (i); 355 while (gameaction != ga_nothing) { 356 switch (gameaction) { 357 case ga_loadlevel: 358 G_DoLoadLevel(); 359 break; 360 case ga_newgame: 361 G_DoNewGame(); 362 break; 363 case ga_loadgame: 364 G_DoLoadGame(); 365 break; 366 case ga_savegame: 367 G_DoSaveGame(); 368 break; 369 case ga_playdemo: 370 G_DoPlayDemo(); 371 break; 372 case ga_completed: 373 G_DoCompleted(); 374 break; 375 case ga_victory: 376 F_StartFinale(); 377 break; 378 case ga_worlddone: 379 G_DoWorldDone(); 380 break; 381 case ga_nothing: 382 break; 383 } 384 } 385 buf = (gametic/ticdup)%BACKUPTICS; 386 for (i = 0; i < MAXPLAYERS; ++i) { 387 if (playeringame[i]) { 388 cmd = &players[i].cmd; 389 memcpy (cmd, &netcmds[i][buf], sizeof(ticcmd_t)); 390 if (demoplayback) G_ReadDemoTiccmd (cmd); 391 if (demorecording) G_WriteDemoTiccmd (cmd); 392 if (cmd->forwardmove > TURBOTHRESHOLD && !(gametic&31) && ((gametic>>5)&3) == i) { 393 static char turbomessage[80]; 394 extern char *player_names[4]; 395 sprintf (turbomessage, "%s is turbo!",player_names[i]); 396 players[consoleplayer].message = turbomessage; 397 } 398 if (netgame && !netdemo && !(gametic%ticdup) ) { 399 if (gametic > BACKUPTICS && consistancy[i][buf] != cmd->consistancy) I_Error("consistency failure (%i should be %i)", cmd->consistancy, consistancy[i][buf]); 400 if (players[i].mo) consistancy[i][buf] = players[i].mo->x; 401 else consistancy[i][buf] = rndindex; 402 } 403 } 404 } 405 for (i = 0; i < MAXPLAYERS; ++i) { 406 if (playeringame[i]) { 407 if (players[i].cmd.buttons & BT_SPECIAL){ 408 switch (players[i].cmd.buttons & BT_SPECIALMASK) { 409 case BTS_PAUSE: 410 paused ^= 1; 411 if (paused) S_PauseSound (); 412 else S_ResumeSound (); 413 break; 414 case BTS_SAVEGAME: 415 if (!savedescription[0]) strcpy(savedescription, "NET GAME"); 416 savegameslot = (players[i].cmd.buttons & BTS_SAVEMASK)>>BTS_SAVESHIFT; 417 gameaction = ga_savegame; 418 break; 419 } 420 } 421 } 422 } 423 switch (gamestate) { 424 case GS_LEVEL: 425 P_Ticker(); 426 ST_Ticker(); 427 AM_Ticker(); 428 HU_Ticker(); 429 break; 430 case GS_INTERMISSION: 431 WI_Ticker(); 432 break; 433 case GS_FINALE: 434 F_Ticker(); 435 break; 436 case GS_DEMOSCREEN: 437 D_PageTicker(); 438 break; 439 } 440 } 441 442 void 443 G_InitPlayer(int player) 444 { 445 G_PlayerReborn(player); 446 } 447 448 void 449 G_PlayerFinishLevel(int player) 450 { 451 player_t* p; 452 453 p = &players[player]; 454 memset (p->powers, 0, sizeof (p->powers)); 455 memset (p->cards, 0, sizeof (p->cards)); 456 p->mo->flags &= ~MF_SHADOW; 457 p->extralight = 0; 458 p->fixedcolormap = 0; 459 p->damagecount = 0; 460 p->bonuscount = 0; 461 } 462 463 void 464 G_PlayerReborn(int player) 465 { 466 player_t* p; 467 int i, killcount, itemcount, secretcount, frags[MAXPLAYERS]; 468 469 memcpy(frags,players[player].frags,sizeof(frags)); 470 killcount = players[player].killcount; 471 itemcount = players[player].itemcount; 472 secretcount = players[player].secretcount; 473 p = &players[player]; 474 memset(p, 0, sizeof(*p)); 475 memcpy(players[player].frags, frags, sizeof(players[player].frags)); 476 players[player].killcount = killcount; 477 players[player].itemcount = itemcount; 478 players[player].secretcount = secretcount; 479 p->usedown = p->attackdown = true; 480 p->playerstate = PST_LIVE; 481 p->health = MAXHEALTH; 482 p->readyweapon = p->pendingweapon = wp_pistol; 483 p->weaponowned[wp_fist] = true; 484 p->weaponowned[wp_pistol] = true; 485 p->ammo[am_clip] = 50; 486 for (i = 0; i < NUMAMMO; ++i) p->maxammo[i] = maxammo[i]; 487 } 488 489 void P_SpawnPlayer(mapthing_t* mthing); 490 491 boolean 492 G_CheckSpot(int playernum, mapthing_t* mthing) 493 { 494 subsector_t* ss; 495 mobj_t* mo; 496 fixed_t x, y; 497 unsigned an; 498 int i; 499 500 if (!players[playernum].mo) { 501 for (i = 0; i < playernum; ++i) 502 if (players[i].mo->x == mthing->x << FRACBITS && players[i].mo->y == mthing->y << FRACBITS) 503 return false; 504 return true; 505 } 506 x = mthing->x << FRACBITS; 507 y = mthing->y << FRACBITS; 508 if (!P_CheckPosition (players[playernum].mo, x, y)) return false; 509 if (bodyqueslot >= BODYQUESIZE) P_RemoveMobj (bodyque[bodyqueslot%BODYQUESIZE]); 510 bodyque[bodyqueslot%BODYQUESIZE] = players[playernum].mo; 511 bodyqueslot++; 512 ss = R_PointInSubsector(x,y); 513 an = (ANG45 * (mthing->angle/45)) >> ANGLETOFINESHIFT; 514 mo = P_SpawnMobj (x+20*finecosine[an], y+20*finesine[an], ss->sector->floorheight, MT_TFOG); 515 if (players[consoleplayer].viewz != 1) S_StartSound (mo, sfx_telept); 516 return true; 517 } 518 519 void 520 G_DeathMatchSpawnPlayer(int playernum) 521 { 522 int i, j, selections; 523 524 selections = deathmatch_p - deathmatchstarts; 525 if (selections < 4) I_Error ("Only %i deathmatch spots, 4 required", selections); 526 for (j = 0; j < 20; ++j) { 527 i = P_Random() % selections; 528 if (G_CheckSpot (playernum, &deathmatchstarts[i])) { 529 deathmatchstarts[i].type = playernum+1; 530 P_SpawnPlayer (&deathmatchstarts[i]); 531 return; 532 } 533 } 534 P_SpawnPlayer(&playerstarts[playernum]); 535 } 536 537 void 538 G_DoReborn(int playernum) 539 { 540 int i; 541 542 if (!netgame) gameaction = ga_loadlevel; 543 else { 544 players[playernum].mo->player = NULL; 545 if (deathmatch) { 546 G_DeathMatchSpawnPlayer (playernum); 547 return; 548 } 549 if (G_CheckSpot(playernum, &playerstarts[playernum])) { 550 P_SpawnPlayer (&playerstarts[playernum]); 551 return; 552 } 553 for (i = 0; i < MAXPLAYERS; ++i) { 554 if (G_CheckSpot (playernum, &playerstarts[i])) { 555 playerstarts[i].type = playernum+1; 556 P_SpawnPlayer (&playerstarts[i]); 557 playerstarts[i].type = i+1; 558 return; 559 } 560 } 561 P_SpawnPlayer(&playerstarts[playernum]); 562 } 563 } 564 565 void 566 G_ExitLevel() 567 { 568 secretexit = false; 569 gameaction = ga_completed; 570 } 571 572 void 573 G_SecretExitLevel() 574 { 575 secretexit = true; 576 gameaction = ga_completed; 577 } 578 579 void 580 G_DoCompleted() 581 { 582 int i; 583 584 gameaction = ga_nothing; 585 for (i = 0; i < MAXPLAYERS; ++i) 586 if (playeringame[i]) 587 G_PlayerFinishLevel (i); 588 if (automapactive) AM_Stop(); 589 if (gamemap == 9) 590 for (i = 0; i < MAXPLAYERS; ++i) players[i].didsecret = true; 591 wminfo.didsecret = players[consoleplayer].didsecret; 592 wminfo.epsd = gameepisode -1; 593 wminfo.last = gamemap -1; 594 if (secretexit) wminfo.next = 8; 595 else if (gamemap == 9) { 596 switch (gameepisode) { 597 case 1: 598 wminfo.next = 3; 599 break; 600 case 2: 601 wminfo.next = 5; 602 break; 603 case 3: 604 wminfo.next = 6; 605 break; 606 case 4: 607 wminfo.next = 2; 608 break; 609 } 610 } else wminfo.next = gamemap; 611 wminfo.maxkills = totalkills; 612 wminfo.maxitems = totalitems; 613 wminfo.maxsecret = totalsecret; 614 wminfo.maxfrags = 0; 615 wminfo.partime = 35*pars[gameepisode][gamemap]; 616 wminfo.pnum = consoleplayer; 617 for (i = 0; i < MAXPLAYERS; ++i) { 618 wminfo.plyr[i].in = playeringame[i]; 619 wminfo.plyr[i].skills = players[i].killcount; 620 wminfo.plyr[i].sitems = players[i].itemcount; 621 wminfo.plyr[i].ssecret = players[i].secretcount; 622 wminfo.plyr[i].stime = leveltime; memcpy(wminfo.plyr[i].frags, players[i].frags, sizeof(wminfo.plyr[i].frags)); 623 } 624 gamestate = GS_INTERMISSION; 625 viewactive = false; 626 automapactive = false; 627 if (statcopy) memcpy(statcopy, &wminfo, sizeof(wminfo)); 628 WI_Start (&wminfo); 629 } 630 631 void 632 G_WorldDone() 633 { 634 gameaction = ga_worlddone; 635 if (secretexit) players[consoleplayer].didsecret = true; 636 } 637 638 void 639 G_DoWorldDone() 640 { 641 gamestate = GS_LEVEL; 642 gamemap = wminfo.next+1; 643 G_DoLoadLevel(); 644 gameaction = ga_nothing; 645 viewactive = true; 646 } 647 648 char savename[256]; 649 650 void G_LoadGame (char* name) 651 { 652 strcpy (savename, name); 653 gameaction = ga_loadgame; 654 } 655 656 void 657 G_DoLoadGame() 658 { 659 int i, a, b, c; 660 char vcheck[VERSIONSIZE]; 661 662 gameaction = ga_nothing; 663 M_ReadFile(savename, &savebuffer); 664 save_p = savebuffer + SAVESTRINGSIZE; 665 memset(vcheck, 0, sizeof(vcheck)); 666 sprintf (vcheck, "version %i", VERSION); 667 if (strcmp ((char*)save_p, vcheck)) return; 668 save_p += VERSIONSIZE; 669 gameskill = *save_p++; 670 gameepisode = *save_p++; 671 gamemap = *save_p++; 672 for (i = 0; i < MAXPLAYERS; ++i) playeringame[i] = *save_p++; 673 G_InitNew(gameskill, gameepisode, gamemap); 674 a = *save_p++; 675 b = *save_p++; 676 c = *save_p++; 677 leveltime = (a<<16) + (b<<8) + c; 678 P_UnArchivePlayers(); 679 P_UnArchiveWorld(); 680 P_UnArchiveThinkers(); 681 P_UnArchiveSpecials(); 682 if (*save_p != 0x1d) I_Error("Bad savegame"); 683 Z_Free(savebuffer); 684 if (setsizeneeded) R_ExecuteSetViewSize(); 685 R_FillBackScreen(); 686 } 687 688 void 689 G_SaveGame(int slot, char* description) 690 { 691 savegameslot = slot; 692 strcpy(savedescription, description); 693 sendsave = true; 694 } 695 696 void 697 G_DoSaveGame() 698 { 699 char* description; 700 char name[100]; 701 char name2[VERSIONSIZE]; 702 int i, length; 703 704 if (M_CheckParm("-cdrom")) 705 sprintf(name, "c:\\doomdata\\%s%d.dsg", lang[SAVEGAMENAME], savegameslot); 706 else 707 sprintf(name, "%s%d.dsg", lang[SAVEGAMENAME], savegameslot); 708 description = savedescription; 709 save_p = savebuffer = screens[1]+0x4000; 710 memcpy (save_p, description, SAVESTRINGSIZE); 711 save_p += SAVESTRINGSIZE; 712 memset (name2,0,sizeof(name2)); 713 sprintf (name2,"version %i",VERSION); 714 memcpy (save_p, name2, VERSIONSIZE); 715 save_p += VERSIONSIZE; 716 *save_p++ = gameskill; 717 *save_p++ = gameepisode; 718 *save_p++ = gamemap; 719 for (i=0 ; i<MAXPLAYERS ; i++) 720 *save_p++ = playeringame[i]; 721 *save_p++ = leveltime>>16; 722 *save_p++ = leveltime>>8; 723 *save_p++ = leveltime; 724 P_ArchivePlayers(); 725 P_ArchiveWorld(); 726 P_ArchiveThinkers(); 727 P_ArchiveSpecials(); 728 *save_p++ = 0x1d; 729 length = save_p - savebuffer; 730 if (length > SAVEGAMESIZE) I_Error("Savegame buffer overrun"); 731 M_WriteFile(name, savebuffer, length); 732 gameaction = ga_nothing; 733 savedescription[0] = 0; 734 players[consoleplayer].message = lang[GGSAVED]; 735 R_FillBackScreen(); 736 } 737 738 void 739 G_DeferedInitNew(skill_t skill, int episode, int map) 740 { 741 d_skill = skill; 742 d_episode = episode; 743 d_map = map; 744 gameaction = ga_newgame; 745 } 746 747 void 748 G_DoNewGame() 749 { 750 demoplayback = false; 751 netdemo = false; 752 netgame = false; 753 deathmatch = false; 754 playeringame[1] = playeringame[2] = playeringame[3] = 0; 755 respawnparm = false; 756 fastparm = false; 757 nomonsters = false; 758 consoleplayer = 0; 759 G_InitNew (d_skill, d_episode, d_map); 760 gameaction = ga_nothing; 761 } 762 763 void 764 G_InitNew(skill_t skill, int episode, int map) 765 { 766 int i; 767 768 if (paused) { 769 paused = false; 770 S_ResumeSound(); 771 } 772 if (skill > sk_nightmare) 773 skill = sk_nightmare; 774 episode = 1; 775 if (map < 1) map = 1; 776 if (map > 9) map = 9; 777 M_ClearRandom(); 778 if (skill == sk_nightmare || respawnparm) 779 respawnmonsters = true; 780 else respawnmonsters = false; 781 if (fastparm || (skill == sk_nightmare && gameskill != sk_nightmare)) { 782 for (i = S_SARG_RUN1; i <= S_SARG_PAIN2; ++i) states[i].tics >>= 1; 783 mobjinfo[MT_BRUISERSHOT].speed = 20*FRACUNIT; 784 mobjinfo[MT_HEADSHOT].speed = 20*FRACUNIT; 785 mobjinfo[MT_TROOPSHOT].speed = 20*FRACUNIT; 786 } 787 if (skill != sk_nightmare && gameskill == sk_nightmare) { 788 for (i = S_SARG_RUN1; i <= S_SARG_PAIN2; ++i) states[i].tics <<= 1; 789 mobjinfo[MT_BRUISERSHOT].speed = 15*FRACUNIT; 790 mobjinfo[MT_HEADSHOT].speed = 10*FRACUNIT; 791 mobjinfo[MT_TROOPSHOT].speed = 10*FRACUNIT; 792 } 793 for (i = 0; i < MAXPLAYERS; ++i) players[i].playerstate = PST_REBORN; 794 usergame = true; 795 paused = false; 796 demoplayback = false; 797 automapactive = false; 798 viewactive = true; 799 gameepisode = episode; 800 gamemap = map; 801 gameskill = skill; 802 viewactive = true; 803 switch(episode) { 804 case 1: 805 skytexture = R_TextureNumForName("SKY1"); 806 break; 807 case 2: 808 skytexture = R_TextureNumForName("SKY2"); 809 break; 810 case 3: 811 skytexture = R_TextureNumForName("SKY3"); 812 break; 813 case 4: 814 skytexture = R_TextureNumForName("SKY4"); 815 break; 816 } 817 G_DoLoadLevel(); 818 } 819 820 void 821 G_ReadDemoTiccmd(ticcmd_t* cmd) 822 { 823 if (*demo_p == DEMOMARKER) { 824 G_CheckDemoStatus(); 825 return; 826 } 827 cmd->forwardmove = ((signed char)*demo_p++); 828 cmd->sidemove = ((signed char)*demo_p++); 829 cmd->angleturn = ((unsigned char)*demo_p++)<<8; 830 cmd->buttons = (unsigned char)*demo_p++; 831 } 832 833 void 834 G_WriteDemoTiccmd(ticcmd_t* cmd) 835 { 836 if (gamekeydown['q']) G_CheckDemoStatus(); 837 *demo_p++ = cmd->forwardmove; 838 *demo_p++ = cmd->sidemove; 839 *demo_p++ = (cmd->angleturn+128)>>8; 840 *demo_p++ = cmd->buttons; 841 demo_p -= 4; 842 if (demo_p > demoend - 16) { 843 G_CheckDemoStatus(); 844 return; 845 } 846 G_ReadDemoTiccmd(cmd); 847 } 848 849 void 850 G_BeginRecording() 851 { 852 int i; 853 854 demo_p = demobuffer; 855 *demo_p++ = VERSION; 856 *demo_p++ = gameskill; 857 *demo_p++ = gameepisode; 858 *demo_p++ = gamemap; 859 *demo_p++ = deathmatch; 860 *demo_p++ = respawnparm; 861 *demo_p++ = fastparm; 862 *demo_p++ = nomonsters; 863 *demo_p++ = consoleplayer; 864 for (i = 0; i < MAXPLAYERS; ++i) 865 *demo_p++ = playeringame[i]; 866 } 867 868 void 869 G_DeferedPlayDemo(char* name) 870 { 871 defdemoname = name; 872 gameaction = ga_playdemo; 873 } 874 875 void 876 G_DoPlayDemo() 877 { 878 skill_t skill; 879 int i, episode, map; 880 881 gameaction = ga_nothing; 882 demobuffer = demo_p = W_CacheLumpName (defdemoname, PU_STATIC); 883 if (*demo_p++ != VERSION) { 884 fprintf( stderr, "Demo is from a different game version!\n"); 885 gameaction = ga_nothing; 886 return; 887 } 888 889 skill = *demo_p++; 890 episode = *demo_p++; 891 map = *demo_p++; 892 deathmatch = *demo_p++; 893 respawnparm = *demo_p++; 894 fastparm = *demo_p++; 895 nomonsters = *demo_p++; 896 consoleplayer = *demo_p++; 897 for (i = 0; i < MAXPLAYERS; ++i) playeringame[i] = *demo_p++; 898 if (playeringame[1]) { 899 netgame = true; 900 netdemo = true; 901 } 902 precache = false; 903 G_InitNew(skill, episode, map); 904 precache = true; 905 usergame = false; 906 demoplayback = true; 907 } 908 909 boolean 910 G_CheckDemoStatus() 911 { 912 int endtime; 913 914 if (timingdemo) { 915 endtime = I_GetTime(); 916 I_Error("timed %i gametics in %i realtics", gametic , endtime-starttime); 917 } 918 if (demoplayback) { 919 if (singledemo) I_Quit (); 920 Z_ChangeTag(demobuffer, PU_CACHE); 921 demoplayback = false; 922 netdemo = false; 923 netgame = false; 924 deathmatch = false; 925 playeringame[1] = playeringame[2] = playeringame[3] = 0; 926 respawnparm = false; 927 fastparm = false; 928 nomonsters = false; 929 consoleplayer = 0; 930 D_AdvanceDemo(); 931 return true; 932 } 933 if (demorecording) { 934 *demo_p++ = DEMOMARKER; 935 M_WriteFile(demoname, demobuffer, demo_p - demobuffer); 936 Z_Free(demobuffer); 937 demorecording = false; 938 I_Error("Demo %s recorded",demoname); 939 } 940 return false; 941 }