|
|
1.1.1.4 ! root 1: // Emacs style mode select -*- C++ -*- ! 2: //----------------------------------------------------------------------------- 1.1.1.2 root 3: // 1.1.1.4 ! root 4: // $Id:$ 1.1.1.2 root 5: // 1.1.1.4 ! root 6: // Copyright (C) 1993-1996 by id Software, Inc. 1.1.1.2 root 7: // 1.1.1.4 ! root 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. 1.1.1.2 root 11: // 1.1.1.4 ! root 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 ! 15: // for more details. 1.1.1.2 root 16: // 1.1.1.4 ! root 17: // $Log:$ 1.1.1.2 root 18: // 1.1.1.4 ! root 19: // DESCRIPTION: none 1.1.1.2 root 20: // 1.1.1.4 ! root 21: //----------------------------------------------------------------------------- 1.1.1.2 root 22: 23: 1.1.1.4 ! root 24: static const char ! 25: rcsid[] = "$Id: g_game.c,v 1.8 1997/02/03 22:45:09 b1 Exp $"; 1.1.1.2 root 26: 1.1.1.4 ! root 27: #include <string.h> ! 28: #include <stdlib.h> 1.1 root 29: 1.1.1.4 ! root 30: #include "doomdef.h" ! 31: #include "doomstat.h" 1.1 root 32: 1.1.1.4 ! root 33: #include "z_zone.h" ! 34: #include "f_finale.h" ! 35: #include "m_argv.h" ! 36: #include "m_misc.h" ! 37: #include "m_menu.h" ! 38: #include "m_random.h" ! 39: #include "i_system.h" ! 40: ! 41: #include "p_setup.h" ! 42: #include "p_saveg.h" ! 43: #include "p_tick.h" ! 44: ! 45: #include "d_main.h" ! 46: ! 47: #include "wi_stuff.h" ! 48: #include "hu_stuff.h" ! 49: #include "st_stuff.h" ! 50: #include "am_map.h" ! 51: ! 52: // Needs access to LFB. ! 53: #include "v_video.h" ! 54: ! 55: #include "w_wad.h" ! 56: ! 57: #include "p_local.h" ! 58: ! 59: #include "s_sound.h" ! 60: ! 61: // Data. ! 62: #include "dstrings.h" ! 63: #include "sounds.h" ! 64: ! 65: // SKY handling - still the wrong place. ! 66: #include "r_data.h" ! 67: #include "r_sky.h" ! 68: ! 69: ! 70: ! 71: #include "g_game.h" ! 72: ! 73: ! 74: #define SAVEGAMESIZE 0x2c000 ! 75: #define SAVESTRINGSIZE 24 ! 76: ! 77: ! 78: ! 79: boolean G_CheckDemoStatus (void); ! 80: void G_ReadDemoTiccmd (ticcmd_t* cmd); ! 81: void G_WriteDemoTiccmd (ticcmd_t* cmd); ! 82: void G_PlayerReborn (int player); ! 83: void G_InitNew (skill_t skill, int episode, int map); ! 84: ! 85: void G_DoReborn (int playernum); ! 86: ! 87: void G_DoLoadLevel (void); ! 88: void G_DoNewGame (void); ! 89: void G_DoLoadGame (void); ! 90: void G_DoPlayDemo (void); ! 91: void G_DoCompleted (void); ! 92: void G_DoVictory (void); ! 93: void G_DoWorldDone (void); ! 94: void G_DoSaveGame (void); ! 95: ! 96: ! 97: gameaction_t gameaction; ! 98: gamestate_t gamestate; ! 99: skill_t gameskill; ! 100: boolean respawnmonsters; ! 101: int gameepisode; ! 102: int gamemap; ! 103: ! 104: boolean paused; ! 105: boolean sendpause; // send a pause event next tic ! 106: boolean sendsave; // send a save event next tic ! 107: boolean usergame; // ok to save / end game ! 108: ! 109: boolean timingdemo; // if true, exit with report on completion ! 110: boolean nodrawers; // for comparative timing purposes ! 111: boolean noblit; // for comparative timing purposes ! 112: int starttime; // for comparative timing purposes ! 113: ! 114: boolean viewactive; ! 115: ! 116: boolean deathmatch; // only if started as net death ! 117: boolean netgame; // only true if packets are broadcast ! 118: boolean playeringame[MAXPLAYERS]; ! 119: player_t players[MAXPLAYERS]; ! 120: ! 121: int consoleplayer; // player taking events and displaying ! 122: int displayplayer; // view being displayed ! 123: int gametic; ! 124: int levelstarttic; // gametic at level start ! 125: int totalkills, totalitems, totalsecret; // for intermission ! 126: ! 127: char demoname[32]; ! 128: boolean demorecording; ! 129: boolean demoplayback; ! 130: boolean netdemo; ! 131: byte* demobuffer; ! 132: byte* demo_p; ! 133: byte* demoend; ! 134: boolean singledemo; // quit after playing a demo from cmdline ! 135: ! 136: boolean precache = true; // if true, load all graphics at start ! 137: ! 138: wbstartstruct_t wminfo; // parms for world map / intermission ! 139: ! 140: short consistancy[MAXPLAYERS][BACKUPTICS]; ! 141: ! 142: byte* savebuffer; ! 143: ! 144: ! 145: // ! 146: // controls (have defaults) ! 147: // ! 148: int key_right; ! 149: int key_left; 1.1 root 150: 1.1.1.4 ! root 151: int key_up; ! 152: int key_down; ! 153: int key_strafeleft; ! 154: int key_straferight; ! 155: int key_fire; ! 156: int key_use; ! 157: int key_strafe; ! 158: int key_speed; ! 159: ! 160: int mousebfire; ! 161: int mousebstrafe; ! 162: int mousebforward; ! 163: ! 164: int joybfire; ! 165: int joybstrafe; ! 166: int joybuse; ! 167: int joybspeed; ! 168: ! 169: ! 170: ! 171: #define MAXPLMOVE (forwardmove[1]) ! 172: ! 173: #define TURBOTHRESHOLD 0x32 ! 174: ! 175: fixed_t forwardmove[2] = {0x19, 0x32}; ! 176: fixed_t sidemove[2] = {0x18, 0x28}; ! 177: fixed_t angleturn[3] = {640, 1280, 320}; // + slow turn ! 178: ! 179: #define SLOWTURNTICS 6 ! 180: ! 181: #define NUMKEYS 256 ! 182: ! 183: boolean gamekeydown[NUMKEYS]; ! 184: int turnheld; // for accelerative turning ! 185: ! 186: boolean mousearray[4]; ! 187: boolean* mousebuttons = &mousearray[1]; // allow [-1] ! 188: ! 189: // mouse values are used once ! 190: int mousex; ! 191: int mousey; ! 192: ! 193: int dclicktime; ! 194: int dclickstate; ! 195: int dclicks; ! 196: int dclicktime2; ! 197: int dclickstate2; ! 198: int dclicks2; ! 199: ! 200: // joystick values are repeated ! 201: int joyxmove; ! 202: int joyymove; ! 203: boolean joyarray[5]; ! 204: boolean* joybuttons = &joyarray[1]; // allow [-1] ! 205: ! 206: int savegameslot; ! 207: char savedescription[32]; ! 208: ! 209: ! 210: #define BODYQUESIZE 32 ! 211: ! 212: mobj_t* bodyque[BODYQUESIZE]; ! 213: int bodyqueslot; ! 214: ! 215: void* statcopy; // for statistics driver ! 216: ! 217: ! 218: ! 219: int G_CmdChecksum (ticcmd_t* cmd) ! 220: { ! 221: int i; ! 222: int sum = 0; ! 223: ! 224: for (i=0 ; i< sizeof(*cmd)/4 - 1 ; i++) ! 225: sum += ((int *)cmd)[i]; ! 226: ! 227: return sum; ! 228: } ! 229: ! 230: ! 231: // ! 232: // G_BuildTiccmd ! 233: // Builds a ticcmd from all of the available inputs ! 234: // or reads it from the demo buffer. ! 235: // If recording a demo, write it out ! 236: // ! 237: void G_BuildTiccmd (ticcmd_t* cmd) ! 238: { ! 239: int i; ! 240: boolean strafe; ! 241: boolean bstrafe; ! 242: int speed; ! 243: int tspeed; ! 244: int forward; ! 245: int side; ! 246: ! 247: ticcmd_t* base; 1.1.1.2 root 248: 1.1.1.4 ! root 249: base = I_BaseTiccmd (); // empty, or external driver ! 250: memcpy (cmd,base,sizeof(*cmd)); 1.1.1.3 root 251: 1.1.1.4 ! root 252: cmd->consistancy = ! 253: consistancy[consoleplayer][maketic%BACKUPTICS]; 1.1.1.2 root 254: 1.1.1.4 ! root 255: ! 256: strafe = gamekeydown[key_strafe] || mousebuttons[mousebstrafe] ! 257: || joybuttons[joybstrafe]; ! 258: speed = gamekeydown[key_speed] || joybuttons[joybspeed]; ! 259: ! 260: forward = side = 0; ! 261: ! 262: // use two stage accelerative turning ! 263: // on the keyboard and joystick ! 264: if (joyxmove < 0 ! 265: || joyxmove > 0 ! 266: || gamekeydown[key_right] ! 267: || gamekeydown[key_left]) ! 268: turnheld += ticdup; ! 269: else ! 270: turnheld = 0; ! 271: ! 272: if (turnheld < SLOWTURNTICS) ! 273: tspeed = 2; // slow turn ! 274: else ! 275: tspeed = speed; ! 276: ! 277: // let movement keys cancel each other out ! 278: if (strafe) ! 279: { ! 280: if (gamekeydown[key_right]) ! 281: { ! 282: // fprintf(stderr, "strafe right\n"); ! 283: side += sidemove[speed]; ! 284: } ! 285: if (gamekeydown[key_left]) ! 286: { ! 287: // fprintf(stderr, "strafe left\n"); ! 288: side -= sidemove[speed]; ! 289: } ! 290: if (joyxmove > 0) ! 291: side += sidemove[speed]; ! 292: if (joyxmove < 0) ! 293: side -= sidemove[speed]; ! 294: ! 295: } ! 296: else ! 297: { ! 298: if (gamekeydown[key_right]) ! 299: cmd->angleturn -= angleturn[tspeed]; ! 300: if (gamekeydown[key_left]) ! 301: cmd->angleturn += angleturn[tspeed]; ! 302: if (joyxmove > 0) ! 303: cmd->angleturn -= angleturn[tspeed]; ! 304: if (joyxmove < 0) ! 305: cmd->angleturn += angleturn[tspeed]; ! 306: } ! 307: ! 308: if (gamekeydown[key_up]) ! 309: { ! 310: // fprintf(stderr, "up\n"); ! 311: forward += forwardmove[speed]; ! 312: } ! 313: if (gamekeydown[key_down]) ! 314: { ! 315: // fprintf(stderr, "down\n"); ! 316: forward -= forwardmove[speed]; ! 317: } ! 318: if (joyymove < 0) ! 319: forward += forwardmove[speed]; ! 320: if (joyymove > 0) ! 321: forward -= forwardmove[speed]; ! 322: if (gamekeydown[key_straferight]) ! 323: side += sidemove[speed]; ! 324: if (gamekeydown[key_strafeleft]) ! 325: side -= sidemove[speed]; ! 326: ! 327: // buttons ! 328: cmd->chatchar = HU_dequeueChatChar(); ! 329: ! 330: if (gamekeydown[key_fire] || mousebuttons[mousebfire] ! 331: || joybuttons[joybfire]) ! 332: cmd->buttons |= BT_ATTACK; ! 333: ! 334: if (gamekeydown[key_use] || joybuttons[joybuse] ) ! 335: { ! 336: cmd->buttons |= BT_USE; ! 337: // clear double clicks if hit use button ! 338: dclicks = 0; ! 339: } ! 340: ! 341: // chainsaw overrides ! 342: for (i=0 ; i<NUMWEAPONS-1 ; i++) ! 343: if (gamekeydown['1'+i]) ! 344: { ! 345: cmd->buttons |= BT_CHANGE; ! 346: cmd->buttons |= i<<BT_WEAPONSHIFT; ! 347: break; ! 348: } ! 349: ! 350: // mouse ! 351: if (mousebuttons[mousebforward]) ! 352: forward += forwardmove[speed]; ! 353: ! 354: // forward double click ! 355: if (mousebuttons[mousebforward] != dclickstate && dclicktime > 1 ) ! 356: { ! 357: dclickstate = mousebuttons[mousebforward]; ! 358: if (dclickstate) ! 359: dclicks++; ! 360: if (dclicks == 2) ! 361: { ! 362: cmd->buttons |= BT_USE; ! 363: dclicks = 0; ! 364: } ! 365: else ! 366: dclicktime = 0; ! 367: } ! 368: else ! 369: { ! 370: dclicktime += ticdup; ! 371: if (dclicktime > 20) ! 372: { ! 373: dclicks = 0; ! 374: dclickstate = 0; ! 375: } ! 376: } ! 377: ! 378: // strafe double click ! 379: bstrafe = ! 380: mousebuttons[mousebstrafe] ! 381: || joybuttons[joybstrafe]; ! 382: if (bstrafe != dclickstate2 && dclicktime2 > 1 ) ! 383: { ! 384: dclickstate2 = bstrafe; ! 385: if (dclickstate2) ! 386: dclicks2++; ! 387: if (dclicks2 == 2) ! 388: { ! 389: cmd->buttons |= BT_USE; ! 390: dclicks2 = 0; ! 391: } ! 392: else ! 393: dclicktime2 = 0; ! 394: } ! 395: else ! 396: { ! 397: dclicktime2 += ticdup; ! 398: if (dclicktime2 > 20) ! 399: { ! 400: dclicks2 = 0; ! 401: dclickstate2 = 0; ! 402: } ! 403: } ! 404: ! 405: forward += mousey; ! 406: if (strafe) ! 407: side += mousex*2; ! 408: else ! 409: cmd->angleturn -= mousex*0x8; ! 410: ! 411: mousex = mousey = 0; ! 412: ! 413: if (forward > MAXPLMOVE) ! 414: forward = MAXPLMOVE; ! 415: else if (forward < -MAXPLMOVE) ! 416: forward = -MAXPLMOVE; ! 417: if (side > MAXPLMOVE) ! 418: side = MAXPLMOVE; ! 419: else if (side < -MAXPLMOVE) ! 420: side = -MAXPLMOVE; ! 421: ! 422: cmd->forwardmove += forward; ! 423: cmd->sidemove += side; ! 424: ! 425: // special buttons ! 426: if (sendpause) ! 427: { ! 428: sendpause = false; ! 429: cmd->buttons = BT_SPECIAL | BTS_PAUSE; ! 430: } ! 431: ! 432: if (sendsave) ! 433: { ! 434: sendsave = false; ! 435: cmd->buttons = BT_SPECIAL | BTS_SAVEGAME | (savegameslot<<BTS_SAVESHIFT); ! 436: } ! 437: } ! 438: ! 439: ! 440: // ! 441: // G_DoLoadLevel ! 442: // ! 443: extern gamestate_t wipegamestate; ! 444: ! 445: void G_DoLoadLevel (void) ! 446: { ! 447: int i; ! 448: ! 449: // Set the sky map. ! 450: // First thing, we have a dummy sky texture name, ! 451: // a flat. The data is in the WAD only because ! 452: // we look for an actual index, instead of simply ! 453: // setting one. ! 454: skyflatnum = R_FlatNumForName ( SKYFLATNAME ); ! 455: ! 456: // DOOM determines the sky texture to be used ! 457: // depending on the current episode, and the game version. ! 458: if ( (gamemode == commercial) ! 459: || ( gamemode == pack_tnt ) ! 460: || ( gamemode == pack_plut ) ) ! 461: { ! 462: skytexture = R_TextureNumForName ("SKY3"); ! 463: if (gamemap < 12) ! 464: skytexture = R_TextureNumForName ("SKY1"); ! 465: else ! 466: if (gamemap < 21) ! 467: skytexture = R_TextureNumForName ("SKY2"); ! 468: } ! 469: ! 470: levelstarttic = gametic; // for time calculation ! 471: ! 472: if (wipegamestate == GS_LEVEL) ! 473: wipegamestate = -1; // force a wipe ! 474: ! 475: gamestate = GS_LEVEL; ! 476: ! 477: for (i=0 ; i<MAXPLAYERS ; i++) ! 478: { ! 479: if (playeringame[i] && players[i].playerstate == PST_DEAD) ! 480: players[i].playerstate = PST_REBORN; ! 481: memset (players[i].frags,0,sizeof(players[i].frags)); ! 482: } ! 483: ! 484: P_SetupLevel (gameepisode, gamemap, 0, gameskill); ! 485: displayplayer = consoleplayer; // view the guy you are playing ! 486: starttime = I_GetTime (); ! 487: gameaction = ga_nothing; ! 488: Z_CheckHeap (); ! 489: ! 490: // clear cmd building stuff ! 491: memset (gamekeydown, 0, sizeof(gamekeydown)); ! 492: joyxmove = joyymove = 0; ! 493: mousex = mousey = 0; ! 494: sendpause = sendsave = paused = false; ! 495: memset (mousebuttons, 0, sizeof(mousebuttons)); ! 496: memset (joybuttons, 0, sizeof(joybuttons)); ! 497: } ! 498: ! 499: 1.1.1.2 root 500: // 1.1.1.4 ! root 501: // G_Responder ! 502: // Get info needed to make ticcmd_ts for the players. 1.1.1.3 root 503: // 1.1.1.4 ! root 504: boolean G_Responder (event_t* ev) ! 505: { ! 506: // allow spy mode changes even during the demo ! 507: if (gamestate == GS_LEVEL && ev->type == ev_keydown ! 508: && ev->data1 == KEY_F12 && (singledemo || !deathmatch) ) ! 509: { ! 510: // spy mode ! 511: do ! 512: { ! 513: displayplayer++; ! 514: if (displayplayer == MAXPLAYERS) ! 515: displayplayer = 0; ! 516: } while (!playeringame[displayplayer] && displayplayer != consoleplayer); ! 517: return true; ! 518: } ! 519: ! 520: // any other key pops up menu if in demos ! 521: if (gameaction == ga_nothing && !singledemo && ! 522: (demoplayback || gamestate == GS_DEMOSCREEN) ! 523: ) ! 524: { ! 525: if (ev->type == ev_keydown || ! 526: (ev->type == ev_mouse && ev->data1) || ! 527: (ev->type == ev_joystick && ev->data1) ) ! 528: { ! 529: M_StartControlPanel (); ! 530: return true; ! 531: } ! 532: return false; ! 533: } ! 534: ! 535: if (gamestate == GS_LEVEL) ! 536: { ! 537: #if 0 ! 538: if (devparm && ev->type == ev_keydown && ev->data1 == ';') ! 539: { ! 540: G_DeathMatchSpawnPlayer (0); ! 541: return true; ! 542: } ! 543: #endif ! 544: if (HU_Responder (ev)) ! 545: return true; // chat ate the event ! 546: if (ST_Responder (ev)) ! 547: return true; // status window ate it ! 548: if (AM_Responder (ev)) ! 549: return true; // automap ate it ! 550: } ! 551: ! 552: if (gamestate == GS_FINALE) ! 553: { ! 554: if (F_Responder (ev)) ! 555: return true; // finale ate the event ! 556: } ! 557: ! 558: switch (ev->type) ! 559: { ! 560: case ev_keydown: ! 561: if (ev->data1 == KEY_PAUSE) ! 562: { ! 563: sendpause = true; ! 564: return true; ! 565: } ! 566: if (ev->data1 <NUMKEYS) ! 567: gamekeydown[ev->data1] = true; ! 568: return true; // eat key down events ! 569: ! 570: case ev_keyup: ! 571: if (ev->data1 <NUMKEYS) ! 572: gamekeydown[ev->data1] = false; ! 573: return false; // always let key up events filter down ! 574: ! 575: case ev_mouse: ! 576: mousebuttons[0] = ev->data1 & 1; ! 577: mousebuttons[1] = ev->data1 & 2; ! 578: mousebuttons[2] = ev->data1 & 4; ! 579: mousex = ev->data2*(mouseSensitivity+5)/10; ! 580: mousey = ev->data3*(mouseSensitivity+5)/10; ! 581: return true; // eat events ! 582: ! 583: case ev_joystick: ! 584: joybuttons[0] = ev->data1 & 1; ! 585: joybuttons[1] = ev->data1 & 2; ! 586: joybuttons[2] = ev->data1 & 4; ! 587: joybuttons[3] = ev->data1 & 8; ! 588: joyxmove = ev->data2; ! 589: joyymove = ev->data3; ! 590: return true; // eat events ! 591: ! 592: default: ! 593: break; ! 594: } ! 595: ! 596: return false; ! 597: } ! 598: ! 599: ! 600: 1.1.1.3 root 601: // 602: // G_Ticker 1.1.1.4 ! root 603: // Make ticcmd_ts for the players. 1.1.1.3 root 604: // 1.1.1.4 ! root 605: void G_Ticker (void) ! 606: { ! 607: int i; ! 608: int buf; ! 609: ticcmd_t* cmd; ! 610: ! 611: // do player reborns if needed ! 612: for (i=0 ; i<MAXPLAYERS ; i++) ! 613: if (playeringame[i] && players[i].playerstate == PST_REBORN) ! 614: G_DoReborn (i); ! 615: ! 616: // do things to change the game state ! 617: while (gameaction != ga_nothing) ! 618: { ! 619: switch (gameaction) ! 620: { ! 621: case ga_loadlevel: ! 622: G_DoLoadLevel (); ! 623: break; ! 624: case ga_newgame: ! 625: G_DoNewGame (); ! 626: break; ! 627: case ga_loadgame: ! 628: G_DoLoadGame (); ! 629: break; ! 630: case ga_savegame: ! 631: G_DoSaveGame (); ! 632: break; ! 633: case ga_playdemo: ! 634: G_DoPlayDemo (); ! 635: break; ! 636: case ga_completed: ! 637: G_DoCompleted (); ! 638: break; ! 639: case ga_victory: ! 640: F_StartFinale (); ! 641: break; ! 642: case ga_worlddone: ! 643: G_DoWorldDone (); ! 644: break; ! 645: case ga_screenshot: ! 646: M_ScreenShot (); ! 647: gameaction = ga_nothing; ! 648: break; ! 649: case ga_nothing: ! 650: break; ! 651: } ! 652: } ! 653: ! 654: // get commands, check consistancy, ! 655: // and build new consistancy check ! 656: buf = (gametic/ticdup)%BACKUPTICS; ! 657: ! 658: for (i=0 ; i<MAXPLAYERS ; i++) ! 659: { ! 660: if (playeringame[i]) ! 661: { ! 662: cmd = &players[i].cmd; ! 663: ! 664: memcpy (cmd, &netcmds[i][buf], sizeof(ticcmd_t)); ! 665: ! 666: if (demoplayback) ! 667: G_ReadDemoTiccmd (cmd); ! 668: if (demorecording) ! 669: G_WriteDemoTiccmd (cmd); ! 670: ! 671: // check for turbo cheats ! 672: if (cmd->forwardmove > TURBOTHRESHOLD ! 673: && !(gametic&31) && ((gametic>>5)&3) == i ) ! 674: { ! 675: static char turbomessage[80]; ! 676: extern char *player_names[4]; ! 677: sprintf (turbomessage, "%s is turbo!",player_names[i]); ! 678: players[consoleplayer].message = turbomessage; ! 679: } 1.1.1.3 root 680: 1.1.1.4 ! root 681: if (netgame && !netdemo && !(gametic%ticdup) ) ! 682: { ! 683: if (gametic > BACKUPTICS ! 684: && consistancy[i][buf] != cmd->consistancy) ! 685: { ! 686: I_Error ("consistency failure (%i should be %i)", ! 687: cmd->consistancy, consistancy[i][buf]); ! 688: } ! 689: if (players[i].mo) ! 690: consistancy[i][buf] = players[i].mo->x; ! 691: else ! 692: consistancy[i][buf] = rndindex; ! 693: } ! 694: } ! 695: } ! 696: ! 697: // check for special buttons ! 698: for (i=0 ; i<MAXPLAYERS ; i++) ! 699: { ! 700: if (playeringame[i]) ! 701: { ! 702: if (players[i].cmd.buttons & BT_SPECIAL) ! 703: { ! 704: switch (players[i].cmd.buttons & BT_SPECIALMASK) ! 705: { ! 706: case BTS_PAUSE: ! 707: paused ^= 1; ! 708: if (paused) ! 709: S_PauseSound (); ! 710: else ! 711: S_ResumeSound (); ! 712: break; ! 713: ! 714: case BTS_SAVEGAME: ! 715: if (!savedescription[0]) ! 716: strcpy (savedescription, "NET GAME"); ! 717: savegameslot = ! 718: (players[i].cmd.buttons & BTS_SAVEMASK)>>BTS_SAVESHIFT; ! 719: gameaction = ga_savegame; ! 720: break; ! 721: } ! 722: } ! 723: } ! 724: } ! 725: ! 726: // do main actions ! 727: switch (gamestate) ! 728: { ! 729: case GS_LEVEL: ! 730: P_Ticker (); ! 731: ST_Ticker (); ! 732: AM_Ticker (); ! 733: HU_Ticker (); ! 734: break; ! 735: ! 736: case GS_INTERMISSION: ! 737: WI_Ticker (); ! 738: break; ! 739: ! 740: case GS_FINALE: ! 741: F_Ticker (); ! 742: break; ! 743: ! 744: case GS_DEMOSCREEN: ! 745: D_PageTicker (); ! 746: break; ! 747: } ! 748: } ! 749: ! 750: ! 751: // ! 752: // PLAYER STRUCTURE FUNCTIONS ! 753: // also see P_SpawnPlayer in P_Things ! 754: // ! 755: ! 756: // ! 757: // G_InitPlayer ! 758: // Called at the start. ! 759: // Called by the game initialization functions. ! 760: // ! 761: void G_InitPlayer (int player) ! 762: { ! 763: player_t* p; ! 764: ! 765: // set up the saved info ! 766: p = &players[player]; ! 767: ! 768: // clear everything else to defaults ! 769: G_PlayerReborn (player); ! 770: ! 771: } ! 772: ! 773: ! 774: ! 775: // ! 776: // G_PlayerFinishLevel ! 777: // Can when a player completes a level. ! 778: // ! 779: void G_PlayerFinishLevel (int player) ! 780: { ! 781: player_t* p; ! 782: ! 783: p = &players[player]; ! 784: ! 785: memset (p->powers, 0, sizeof (p->powers)); ! 786: memset (p->cards, 0, sizeof (p->cards)); ! 787: p->mo->flags &= ~MF_SHADOW; // cancel invisibility ! 788: p->extralight = 0; // cancel gun flashes ! 789: p->fixedcolormap = 0; // cancel ir gogles ! 790: p->damagecount = 0; // no palette changes ! 791: p->bonuscount = 0; ! 792: } ! 793: 1.1.1.2 root 794: 1.1.1.3 root 795: // 796: // G_PlayerReborn 1.1.1.4 ! root 797: // Called after a player dies ! 798: // almost everything is cleared and initialized 1.1.1.3 root 799: // 1.1.1.4 ! root 800: void G_PlayerReborn (int player) ! 801: { ! 802: player_t* p; ! 803: int i; ! 804: int frags[MAXPLAYERS]; ! 805: int killcount; ! 806: int itemcount; ! 807: int secretcount; ! 808: ! 809: memcpy (frags,players[player].frags,sizeof(frags)); ! 810: killcount = players[player].killcount; ! 811: itemcount = players[player].itemcount; ! 812: secretcount = players[player].secretcount; ! 813: ! 814: p = &players[player]; ! 815: memset (p, 0, sizeof(*p)); ! 816: ! 817: memcpy (players[player].frags, frags, sizeof(players[player].frags)); ! 818: players[player].killcount = killcount; ! 819: players[player].itemcount = itemcount; ! 820: players[player].secretcount = secretcount; ! 821: ! 822: p->usedown = p->attackdown = true; // don't do anything immediately ! 823: p->playerstate = PST_LIVE; ! 824: p->health = MAXHEALTH; ! 825: p->readyweapon = p->pendingweapon = wp_pistol; ! 826: p->weaponowned[wp_fist] = true; ! 827: p->weaponowned[wp_pistol] = true; ! 828: p->ammo[am_clip] = 50; ! 829: ! 830: for (i=0 ; i<NUMAMMO ; i++) ! 831: p->maxammo[i] = maxammo[i]; ! 832: 1.1.1.2 root 833: } 834: 1.1.1.4 ! root 835: // ! 836: // G_CheckSpot ! 837: // Returns false if the player cannot be respawned ! 838: // at the given mapthing_t spot ! 839: // because something is occupying it ! 840: // ! 841: void P_SpawnPlayer (mapthing_t* mthing); ! 842: ! 843: boolean ! 844: G_CheckSpot ! 845: ( int playernum, ! 846: mapthing_t* mthing ) ! 847: { ! 848: fixed_t x; ! 849: fixed_t y; ! 850: subsector_t* ss; ! 851: unsigned an; ! 852: mobj_t* mo; ! 853: int i; 1.1.1.3 root 854: 1.1.1.4 ! root 855: if (!players[playernum].mo) ! 856: { ! 857: // first spawn of level, before corpses ! 858: for (i=0 ; i<playernum ; i++) ! 859: if (players[i].mo->x == mthing->x << FRACBITS ! 860: && players[i].mo->y == mthing->y << FRACBITS) ! 861: return false; 1.1.1.2 root 862: return true; 1.1.1.4 ! root 863: } ! 864: ! 865: x = mthing->x << FRACBITS; ! 866: y = mthing->y << FRACBITS; ! 867: ! 868: if (!P_CheckPosition (players[playernum].mo, x, y) ) ! 869: return false; ! 870: ! 871: // flush an old corpse if needed ! 872: if (bodyqueslot >= BODYQUESIZE) ! 873: P_RemoveMobj (bodyque[bodyqueslot%BODYQUESIZE]); ! 874: bodyque[bodyqueslot%BODYQUESIZE] = players[playernum].mo; ! 875: bodyqueslot++; 1.1.1.3 root 876: 1.1.1.4 ! root 877: // spawn a teleport fog ! 878: ss = R_PointInSubsector (x,y); ! 879: an = ( ANG45 * (mthing->angle/45) ) >> ANGLETOFINESHIFT; ! 880: ! 881: mo = P_SpawnMobj (x+20*finecosine[an], y+20*finesine[an] ! 882: , ss->sector->floorheight ! 883: , MT_TFOG); ! 884: ! 885: if (players[consoleplayer].viewz != 1) ! 886: S_StartSound (mo, sfx_telept); // don't start sound on first frame ! 887: ! 888: return true; ! 889: } 1.1.1.2 root 890: 891: 1.1.1.3 root 892: // 1.1.1.4 ! root 893: // G_DeathMatchSpawnPlayer ! 894: // Spawns a player at one of the random death match spots ! 895: // called at level load and each death ! 896: // ! 897: void G_DeathMatchSpawnPlayer (int playernum) ! 898: { ! 899: int i,j; ! 900: int selections; ! 901: ! 902: selections = deathmatch_p - deathmatchstarts; ! 903: if (selections < 4) ! 904: I_Error ("Only %i deathmatch spots, 4 required", selections); ! 905: ! 906: for (j=0 ; j<20 ; j++) ! 907: { ! 908: i = P_Random() % selections; ! 909: if (G_CheckSpot (playernum, &deathmatchstarts[i]) ) ! 910: { ! 911: deathmatchstarts[i].type = playernum+1; ! 912: P_SpawnPlayer (&deathmatchstarts[i]); ! 913: return; ! 914: } ! 915: } ! 916: ! 917: // no good spot, so the player will probably get stuck ! 918: P_SpawnPlayer (&playerstarts[playernum]); ! 919: } 1.1.1.2 root 920: 1.1.1.4 ! root 921: // ! 922: // G_DoReborn ! 923: // ! 924: void G_DoReborn (int playernum) ! 925: { ! 926: int i; ! 927: ! 928: if (!netgame) ! 929: { ! 930: // reload the level from scratch ! 931: gameaction = ga_loadlevel; ! 932: } ! 933: else ! 934: { ! 935: // respawn at the start ! 936: ! 937: // first dissasociate the corpse ! 938: players[playernum].mo->player = NULL; ! 939: ! 940: // spawn at random spot if in death match ! 941: if (deathmatch) ! 942: { ! 943: G_DeathMatchSpawnPlayer (playernum); ! 944: return; ! 945: } ! 946: ! 947: if (G_CheckSpot (playernum, &playerstarts[playernum]) ) ! 948: { ! 949: P_SpawnPlayer (&playerstarts[playernum]); ! 950: return; 1.1.1.3 root 951: } 952: 1.1.1.4 ! root 953: // try to spawn at one of the other players spots ! 954: for (i=0 ; i<MAXPLAYERS ; i++) 1.1.1.3 root 955: { 1.1.1.4 ! root 956: if (G_CheckSpot (playernum, &playerstarts[i]) ) ! 957: { ! 958: playerstarts[i].type = playernum+1; // fake as other player ! 959: P_SpawnPlayer (&playerstarts[i]); ! 960: playerstarts[i].type = i+1; // restore ! 961: return; ! 962: } ! 963: // he's going to be inside something. Too bad. ! 964: } ! 965: P_SpawnPlayer (&playerstarts[playernum]); ! 966: } ! 967: } ! 968: ! 969: ! 970: void G_ScreenShot (void) ! 971: { ! 972: gameaction = ga_screenshot; ! 973: } ! 974: ! 975: ! 976: ! 977: // DOOM Par Times ! 978: int pars[4][10] = ! 979: { ! 980: {0}, ! 981: {0,30,75,120,90,165,180,180,30,165}, ! 982: {0,90,90,90,120,90,360,240,30,170}, ! 983: {0,90,45,90,150,90,90,165,30,135} ! 984: }; ! 985: ! 986: // DOOM II Par Times ! 987: int cpars[32] = ! 988: { ! 989: 30,90,120,120,90,150,120,120,270,90, // 1-10 ! 990: 210,150,150,150,210,150,420,150,210,150, // 11-20 ! 991: 240,150,180,150,150,300,330,420,300,180, // 21-30 ! 992: 120,30 // 31-32 ! 993: }; ! 994: 1.1.1.3 root 995: 996: // 1.1.1.4 ! root 997: // G_DoCompleted 1.1.1.3 root 998: // 1.1.1.4 ! root 999: boolean secretexit; ! 1000: extern char* pagename; ! 1001: ! 1002: void G_ExitLevel (void) ! 1003: { ! 1004: secretexit = false; ! 1005: gameaction = ga_completed; ! 1006: } ! 1007: ! 1008: // Here's for the german edition. ! 1009: void G_SecretExitLevel (void) ! 1010: { ! 1011: // IF NO WOLF3D LEVELS, NO SECRET EXIT! ! 1012: if ( (gamemode == commercial) ! 1013: && (W_CheckNumForName("map31")<0)) 1.1.1.2 root 1014: secretexit = false; 1.1.1.4 ! root 1015: else ! 1016: secretexit = true; ! 1017: gameaction = ga_completed; ! 1018: } ! 1019: ! 1020: void G_DoCompleted (void) ! 1021: { ! 1022: int i; ! 1023: ! 1024: gameaction = ga_nothing; ! 1025: ! 1026: for (i=0 ; i<MAXPLAYERS ; i++) ! 1027: if (playeringame[i]) ! 1028: G_PlayerFinishLevel (i); // take away cards and stuff ! 1029: ! 1030: if (automapactive) ! 1031: AM_Stop (); ! 1032: ! 1033: if ( gamemode != commercial) ! 1034: switch(gamemap) 1.1.1.2 root 1035: { 1.1.1.4 ! root 1036: case 8: ! 1037: gameaction = ga_victory; ! 1038: return; ! 1039: case 9: ! 1040: for (i=0 ; i<MAXPLAYERS ; i++) ! 1041: players[i].didsecret = true; ! 1042: break; 1.1.1.2 root 1043: } 1.1.1.4 ! root 1044: ! 1045: //#if 0 Hmmm - why? ! 1046: if ( (gamemap == 8) ! 1047: && (gamemode != commercial) ) ! 1048: { ! 1049: // victory ! 1050: gameaction = ga_victory; ! 1051: return; ! 1052: } ! 1053: ! 1054: if ( (gamemap == 9) ! 1055: && (gamemode != commercial) ) ! 1056: { ! 1057: // exit secret level ! 1058: for (i=0 ; i<MAXPLAYERS ; i++) ! 1059: players[i].didsecret = true; ! 1060: } ! 1061: //#endif ! 1062: ! 1063: ! 1064: wminfo.didsecret = players[consoleplayer].didsecret; ! 1065: wminfo.epsd = gameepisode -1; ! 1066: wminfo.last = gamemap -1; ! 1067: ! 1068: // wminfo.next is 0 biased, unlike gamemap ! 1069: if ( gamemode == commercial) ! 1070: { ! 1071: if (secretexit) ! 1072: switch(gamemap) ! 1073: { ! 1074: case 15: wminfo.next = 30; break; ! 1075: case 31: wminfo.next = 31; break; ! 1076: } 1.1.1.2 root 1077: else 1.1.1.4 ! root 1078: switch(gamemap) ! 1079: { ! 1080: case 31: ! 1081: case 32: wminfo.next = 15; break; ! 1082: default: wminfo.next = gamemap; ! 1083: } ! 1084: } ! 1085: else ! 1086: { ! 1087: if (secretexit) ! 1088: wminfo.next = 8; // go to secret level ! 1089: else if (gamemap == 9) ! 1090: { ! 1091: // returning from secret level ! 1092: switch (gameepisode) ! 1093: { ! 1094: case 1: ! 1095: wminfo.next = 3; ! 1096: break; ! 1097: case 2: ! 1098: wminfo.next = 5; ! 1099: break; ! 1100: case 3: ! 1101: wminfo.next = 6; ! 1102: break; ! 1103: case 4: ! 1104: wminfo.next = 2; ! 1105: break; ! 1106: } ! 1107: } ! 1108: else ! 1109: wminfo.next = gamemap; // go to next level ! 1110: } ! 1111: ! 1112: wminfo.maxkills = totalkills; ! 1113: wminfo.maxitems = totalitems; ! 1114: wminfo.maxsecret = totalsecret; ! 1115: wminfo.maxfrags = 0; ! 1116: if ( gamemode == commercial ) ! 1117: wminfo.partime = 35*cpars[gamemap-1]; ! 1118: else ! 1119: wminfo.partime = 35*pars[gameepisode][gamemap]; ! 1120: wminfo.pnum = consoleplayer; ! 1121: ! 1122: for (i=0 ; i<MAXPLAYERS ; i++) ! 1123: { ! 1124: wminfo.plyr[i].in = playeringame[i]; ! 1125: wminfo.plyr[i].skills = players[i].killcount; ! 1126: wminfo.plyr[i].sitems = players[i].itemcount; ! 1127: wminfo.plyr[i].ssecret = players[i].secretcount; ! 1128: wminfo.plyr[i].stime = leveltime; ! 1129: memcpy (wminfo.plyr[i].frags, players[i].frags ! 1130: , sizeof(wminfo.plyr[i].frags)); ! 1131: } ! 1132: ! 1133: gamestate = GS_INTERMISSION; ! 1134: viewactive = false; ! 1135: automapactive = false; ! 1136: ! 1137: if (statcopy) ! 1138: memcpy (statcopy, &wminfo, sizeof(wminfo)); ! 1139: ! 1140: WI_Start (&wminfo); ! 1141: } 1.1.1.3 root 1142: 1143: 1.1.1.2 root 1144: // 1.1.1.4 ! root 1145: // G_WorldDone 1.1.1.2 root 1146: // 1.1.1.4 ! root 1147: void G_WorldDone (void) ! 1148: { ! 1149: gameaction = ga_worlddone; ! 1150: ! 1151: if (secretexit) ! 1152: players[consoleplayer].didsecret = true; ! 1153: ! 1154: if ( gamemode == commercial ) ! 1155: { ! 1156: switch (gamemap) ! 1157: { ! 1158: case 15: ! 1159: case 31: ! 1160: if (!secretexit) ! 1161: break; ! 1162: case 6: ! 1163: case 11: ! 1164: case 20: ! 1165: case 30: ! 1166: F_StartFinale (); ! 1167: break; ! 1168: } ! 1169: } ! 1170: } ! 1171: ! 1172: void G_DoWorldDone (void) ! 1173: { ! 1174: gamestate = GS_LEVEL; ! 1175: gamemap = wminfo.next+1; ! 1176: G_DoLoadLevel (); ! 1177: gameaction = ga_nothing; ! 1178: viewactive = true; ! 1179: } ! 1180: ! 1181: ! 1182: ! 1183: // ! 1184: // G_InitFromSavegame ! 1185: // Can be called by the startup code or the menu task. ! 1186: // ! 1187: extern boolean setsizeneeded; ! 1188: void R_ExecuteSetViewSize (void); ! 1189: ! 1190: char savename[256]; ! 1191: ! 1192: void G_LoadGame (char* name) ! 1193: { ! 1194: strcpy (savename, name); ! 1195: gameaction = ga_loadgame; ! 1196: } ! 1197: ! 1198: #define VERSIONSIZE 16 ! 1199: ! 1200: ! 1201: void G_DoLoadGame (void) ! 1202: { ! 1203: int length; ! 1204: int i; ! 1205: int a,b,c; ! 1206: char vcheck[VERSIONSIZE]; ! 1207: ! 1208: gameaction = ga_nothing; ! 1209: ! 1210: length = M_ReadFile (savename, &savebuffer); ! 1211: save_p = savebuffer + SAVESTRINGSIZE; ! 1212: ! 1213: // skip the description field ! 1214: memset (vcheck,0,sizeof(vcheck)); ! 1215: sprintf (vcheck,"version %i",VERSION); ! 1216: if (strcmp (save_p, vcheck)) ! 1217: return; // bad version ! 1218: save_p += VERSIONSIZE; ! 1219: ! 1220: gameskill = *save_p++; ! 1221: gameepisode = *save_p++; ! 1222: gamemap = *save_p++; ! 1223: for (i=0 ; i<MAXPLAYERS ; i++) ! 1224: playeringame[i] = *save_p++; ! 1225: ! 1226: // load a base level ! 1227: G_InitNew (gameskill, gameepisode, gamemap); ! 1228: ! 1229: // get the times ! 1230: a = *save_p++; ! 1231: b = *save_p++; ! 1232: c = *save_p++; ! 1233: leveltime = (a<<16) + (b<<8) + c; ! 1234: ! 1235: // dearchive all the modifications ! 1236: P_UnArchivePlayers (); ! 1237: P_UnArchiveWorld (); ! 1238: P_UnArchiveThinkers (); ! 1239: P_UnArchiveSpecials (); ! 1240: ! 1241: if (*save_p != 0x1d) ! 1242: I_Error ("Bad savegame"); ! 1243: ! 1244: // done ! 1245: Z_Free (savebuffer); ! 1246: ! 1247: if (setsizeneeded) ! 1248: R_ExecuteSetViewSize (); ! 1249: ! 1250: // draw the pattern into the back screen ! 1251: R_FillBackScreen (); ! 1252: } ! 1253: 1.1.1.2 root 1254: 1.1.1.3 root 1255: // 1256: // G_SaveGame 1.1.1.4 ! root 1257: // Called by the menu task. ! 1258: // Description is a 24 byte text string 1.1.1.3 root 1259: // 1.1.1.4 ! root 1260: void ! 1261: G_SaveGame ! 1262: ( int slot, ! 1263: char* description ) ! 1264: { ! 1265: savegameslot = slot; ! 1266: strcpy (savedescription, description); ! 1267: sendsave = true; ! 1268: } ! 1269: ! 1270: void G_DoSaveGame (void) ! 1271: { ! 1272: char name[100]; ! 1273: char name2[VERSIONSIZE]; ! 1274: char* description; ! 1275: int length; ! 1276: int i; ! 1277: ! 1278: if (M_CheckParm("-cdrom")) ! 1279: sprintf(name,"c:\\doomdata\\"SAVEGAMENAME"%d.dsg",savegameslot); ! 1280: else ! 1281: sprintf (name,SAVEGAMENAME"%d.dsg",savegameslot); ! 1282: description = savedescription; ! 1283: ! 1284: save_p = savebuffer = screens[1]+0x4000; ! 1285: ! 1286: memcpy (save_p, description, SAVESTRINGSIZE); ! 1287: save_p += SAVESTRINGSIZE; ! 1288: memset (name2,0,sizeof(name2)); ! 1289: sprintf (name2,"version %i",VERSION); ! 1290: memcpy (save_p, name2, VERSIONSIZE); ! 1291: save_p += VERSIONSIZE; ! 1292: ! 1293: *save_p++ = gameskill; ! 1294: *save_p++ = gameepisode; ! 1295: *save_p++ = gamemap; ! 1296: for (i=0 ; i<MAXPLAYERS ; i++) ! 1297: *save_p++ = playeringame[i]; ! 1298: *save_p++ = leveltime>>16; ! 1299: *save_p++ = leveltime>>8; ! 1300: *save_p++ = leveltime; ! 1301: ! 1302: P_ArchivePlayers (); ! 1303: P_ArchiveWorld (); ! 1304: P_ArchiveThinkers (); ! 1305: P_ArchiveSpecials (); ! 1306: ! 1307: *save_p++ = 0x1d; // consistancy marker ! 1308: ! 1309: length = save_p - savebuffer; ! 1310: if (length > SAVEGAMESIZE) ! 1311: I_Error ("Savegame buffer overrun"); ! 1312: M_WriteFile (name, savebuffer, length); ! 1313: gameaction = ga_nothing; ! 1314: savedescription[0] = 0; ! 1315: ! 1316: players[consoleplayer].message = GGSAVED; ! 1317: ! 1318: // draw the pattern into the back screen ! 1319: R_FillBackScreen (); ! 1320: } ! 1321: ! 1322: ! 1323: // ! 1324: // G_InitNew ! 1325: // Can be called by the startup code or the menu task, ! 1326: // consoleplayer, displayplayer, playeringame[] should be set. ! 1327: // ! 1328: skill_t d_skill; ! 1329: int d_episode; ! 1330: int d_map; ! 1331: ! 1332: void ! 1333: G_DeferedInitNew ! 1334: ( skill_t skill, ! 1335: int episode, ! 1336: int map) ! 1337: { ! 1338: d_skill = skill; ! 1339: d_episode = episode; ! 1340: d_map = map; ! 1341: gameaction = ga_newgame; ! 1342: } ! 1343: ! 1344: ! 1345: void G_DoNewGame (void) ! 1346: { ! 1347: demoplayback = false; ! 1348: netdemo = false; ! 1349: netgame = false; ! 1350: deathmatch = false; ! 1351: playeringame[1] = playeringame[2] = playeringame[3] = 0; ! 1352: respawnparm = false; ! 1353: fastparm = false; ! 1354: nomonsters = false; ! 1355: consoleplayer = 0; ! 1356: G_InitNew (d_skill, d_episode, d_map); ! 1357: gameaction = ga_nothing; ! 1358: } ! 1359: ! 1360: // The sky texture to be used instead of the F_SKY1 dummy. ! 1361: extern int skytexture; ! 1362: ! 1363: ! 1364: void ! 1365: G_InitNew ! 1366: ( skill_t skill, ! 1367: int episode, ! 1368: int map ) ! 1369: { ! 1370: int i; ! 1371: ! 1372: if (paused) ! 1373: { ! 1374: paused = false; ! 1375: S_ResumeSound (); ! 1376: } ! 1377: 1.1.1.2 root 1378: 1.1.1.4 ! root 1379: if (skill > sk_nightmare) ! 1380: skill = sk_nightmare; 1.1.1.2 root 1381: 1382: 1.1.1.4 ! root 1383: // This was quite messy with SPECIAL and commented parts. ! 1384: // Supposedly hacks to make the latest edition work. ! 1385: // It might not work properly. ! 1386: if (episode < 1) ! 1387: episode = 1; ! 1388: ! 1389: if ( gamemode == retail ) ! 1390: { ! 1391: if (episode > 4) ! 1392: episode = 4; ! 1393: } ! 1394: else if ( gamemode == shareware ) ! 1395: { ! 1396: if (episode > 1) ! 1397: episode = 1; // only start episode 1 on shareware ! 1398: } ! 1399: else ! 1400: { ! 1401: if (episode > 3) ! 1402: episode = 3; ! 1403: } ! 1404: ! 1405: ! 1406: ! 1407: if (map < 1) ! 1408: map = 1; ! 1409: ! 1410: if ( (map > 9) ! 1411: && ( gamemode != commercial) ) ! 1412: map = 9; ! 1413: ! 1414: M_ClearRandom (); ! 1415: ! 1416: if (skill == sk_nightmare || respawnparm ) ! 1417: respawnmonsters = true; ! 1418: else ! 1419: respawnmonsters = false; ! 1420: ! 1421: if (fastparm || (skill == sk_nightmare && gameskill != sk_nightmare) ) ! 1422: { ! 1423: for (i=S_SARG_RUN1 ; i<=S_SARG_PAIN2 ; i++) ! 1424: states[i].tics >>= 1; ! 1425: mobjinfo[MT_BRUISERSHOT].speed = 20*FRACUNIT; ! 1426: mobjinfo[MT_HEADSHOT].speed = 20*FRACUNIT; ! 1427: mobjinfo[MT_TROOPSHOT].speed = 20*FRACUNIT; ! 1428: } ! 1429: else if (skill != sk_nightmare && gameskill == sk_nightmare) ! 1430: { ! 1431: for (i=S_SARG_RUN1 ; i<=S_SARG_PAIN2 ; i++) ! 1432: states[i].tics <<= 1; ! 1433: mobjinfo[MT_BRUISERSHOT].speed = 15*FRACUNIT; ! 1434: mobjinfo[MT_HEADSHOT].speed = 10*FRACUNIT; ! 1435: mobjinfo[MT_TROOPSHOT].speed = 10*FRACUNIT; ! 1436: } ! 1437: ! 1438: ! 1439: // force players to be initialized upon first level load ! 1440: for (i=0 ; i<MAXPLAYERS ; i++) ! 1441: players[i].playerstate = PST_REBORN; ! 1442: ! 1443: usergame = true; // will be set false if a demo ! 1444: paused = false; ! 1445: demoplayback = false; ! 1446: automapactive = false; ! 1447: viewactive = true; ! 1448: gameepisode = episode; ! 1449: gamemap = map; ! 1450: gameskill = skill; ! 1451: ! 1452: viewactive = true; ! 1453: ! 1454: // set the sky map for the episode ! 1455: if ( gamemode == commercial) ! 1456: { ! 1457: skytexture = R_TextureNumForName ("SKY3"); ! 1458: if (gamemap < 12) ! 1459: skytexture = R_TextureNumForName ("SKY1"); ! 1460: else ! 1461: if (gamemap < 21) ! 1462: skytexture = R_TextureNumForName ("SKY2"); ! 1463: } ! 1464: else ! 1465: switch (episode) ! 1466: { ! 1467: case 1: ! 1468: skytexture = R_TextureNumForName ("SKY1"); ! 1469: break; ! 1470: case 2: ! 1471: skytexture = R_TextureNumForName ("SKY2"); ! 1472: break; ! 1473: case 3: ! 1474: skytexture = R_TextureNumForName ("SKY3"); ! 1475: break; ! 1476: case 4: // Special Edition sky ! 1477: skytexture = R_TextureNumForName ("SKY4"); ! 1478: break; ! 1479: } ! 1480: ! 1481: G_DoLoadLevel (); ! 1482: } ! 1483: 1.1.1.2 root 1484: 1.1.1.3 root 1485: // 1.1.1.4 ! root 1486: // DEMO RECORDING ! 1487: // ! 1488: #define DEMOMARKER 0x80 1.1.1.2 root 1489: 1490: 1.1.1.4 ! root 1491: void G_ReadDemoTiccmd (ticcmd_t* cmd) ! 1492: { ! 1493: if (*demo_p == DEMOMARKER) ! 1494: { ! 1495: // end of demo data stream ! 1496: G_CheckDemoStatus (); ! 1497: return; ! 1498: } ! 1499: cmd->forwardmove = ((signed char)*demo_p++); ! 1500: cmd->sidemove = ((signed char)*demo_p++); ! 1501: cmd->angleturn = ((unsigned char)*demo_p++)<<8; ! 1502: cmd->buttons = (unsigned char)*demo_p++; ! 1503: } ! 1504: ! 1505: ! 1506: void G_WriteDemoTiccmd (ticcmd_t* cmd) ! 1507: { ! 1508: if (gamekeydown['q']) // press q to end demo recording ! 1509: G_CheckDemoStatus (); ! 1510: *demo_p++ = cmd->forwardmove; ! 1511: *demo_p++ = cmd->sidemove; ! 1512: *demo_p++ = (cmd->angleturn+128)>>8; ! 1513: *demo_p++ = cmd->buttons; ! 1514: demo_p -= 4; ! 1515: if (demo_p > demoend - 16) ! 1516: { ! 1517: // no more space ! 1518: G_CheckDemoStatus (); ! 1519: return; ! 1520: } 1.1.1.3 root 1521: 1.1.1.4 ! root 1522: G_ReadDemoTiccmd (cmd); // make SURE it is exactly the same ! 1523: } ! 1524: ! 1525: ! 1526: ! 1527: // ! 1528: // G_RecordDemo ! 1529: // ! 1530: void G_RecordDemo (char* name) ! 1531: { ! 1532: int i; ! 1533: int maxsize; 1.1.1.3 root 1534: 1.1.1.4 ! root 1535: usergame = false; ! 1536: strcpy (demoname, name); ! 1537: strcat (demoname, ".lmp"); ! 1538: maxsize = 0x20000; ! 1539: i = M_CheckParm ("-maxdemo"); ! 1540: if (i && i<myargc-1) ! 1541: maxsize = atoi(myargv[i+1])*1024; ! 1542: demobuffer = Z_Malloc (maxsize,PU_STATIC,NULL); ! 1543: demoend = demobuffer + maxsize; 1.1.1.3 root 1544: 1.1.1.4 ! root 1545: demorecording = true; ! 1546: } ! 1547: ! 1548: ! 1549: void G_BeginRecording (void) ! 1550: { ! 1551: int i; ! 1552: ! 1553: demo_p = demobuffer; 1.1.1.3 root 1554: 1.1.1.4 ! root 1555: *demo_p++ = VERSION; ! 1556: *demo_p++ = gameskill; ! 1557: *demo_p++ = gameepisode; ! 1558: *demo_p++ = gamemap; ! 1559: *demo_p++ = deathmatch; ! 1560: *demo_p++ = respawnparm; ! 1561: *demo_p++ = fastparm; ! 1562: *demo_p++ = nomonsters; ! 1563: *demo_p++ = consoleplayer; ! 1564: ! 1565: for (i=0 ; i<MAXPLAYERS ; i++) ! 1566: *demo_p++ = playeringame[i]; ! 1567: } ! 1568: ! 1569: ! 1570: // ! 1571: // G_PlayDemo ! 1572: // ! 1573: ! 1574: char* defdemoname; ! 1575: ! 1576: void G_DeferedPlayDemo (char* name) ! 1577: { ! 1578: defdemoname = name; ! 1579: gameaction = ga_playdemo; ! 1580: } ! 1581: ! 1582: void G_DoPlayDemo (void) ! 1583: { ! 1584: skill_t skill; ! 1585: int i, episode, map; ! 1586: ! 1587: gameaction = ga_nothing; ! 1588: demobuffer = demo_p = W_CacheLumpName (defdemoname, PU_STATIC); ! 1589: if ( *demo_p++ != VERSION) ! 1590: { ! 1591: fprintf( stderr, "Demo is from a different game version!\n"); ! 1592: gameaction = ga_nothing; ! 1593: return; ! 1594: } ! 1595: ! 1596: skill = *demo_p++; ! 1597: episode = *demo_p++; ! 1598: map = *demo_p++; ! 1599: deathmatch = *demo_p++; ! 1600: respawnparm = *demo_p++; ! 1601: fastparm = *demo_p++; ! 1602: nomonsters = *demo_p++; ! 1603: consoleplayer = *demo_p++; 1.1.1.3 root 1604: 1.1.1.4 ! root 1605: for (i=0 ; i<MAXPLAYERS ; i++) ! 1606: playeringame[i] = *demo_p++; ! 1607: if (playeringame[1]) ! 1608: { ! 1609: netgame = true; ! 1610: netdemo = true; ! 1611: } ! 1612: ! 1613: // don't spend a lot of time in loadlevel ! 1614: precache = false; ! 1615: G_InitNew (skill, episode, map); ! 1616: precache = true; ! 1617: ! 1618: usergame = false; ! 1619: demoplayback = true; ! 1620: } ! 1621: ! 1622: // ! 1623: // G_TimeDemo ! 1624: // ! 1625: void G_TimeDemo (char* name) ! 1626: { ! 1627: nodrawers = M_CheckParm ("-nodraw"); ! 1628: noblit = M_CheckParm ("-noblit"); ! 1629: timingdemo = true; ! 1630: singletics = true; ! 1631: ! 1632: defdemoname = name; ! 1633: gameaction = ga_playdemo; ! 1634: } ! 1635: ! 1636: ! 1637: /* ! 1638: =================== ! 1639: = ! 1640: = G_CheckDemoStatus ! 1641: = ! 1642: = Called after a death or level completion to allow demos to be cleaned up ! 1643: = Returns true if a new demo loop action will take place ! 1644: =================== ! 1645: */ ! 1646: ! 1647: boolean G_CheckDemoStatus (void) ! 1648: { ! 1649: int endtime; ! 1650: ! 1651: if (timingdemo) ! 1652: { ! 1653: endtime = I_GetTime (); ! 1654: I_Error ("timed %i gametics in %i realtics",gametic ! 1655: , endtime-starttime); ! 1656: } ! 1657: ! 1658: if (demoplayback) ! 1659: { ! 1660: if (singledemo) ! 1661: I_Quit (); ! 1662: ! 1663: Z_ChangeTag (demobuffer, PU_CACHE); ! 1664: demoplayback = false; ! 1665: netdemo = false; ! 1666: netgame = false; ! 1667: deathmatch = false; ! 1668: playeringame[1] = playeringame[2] = playeringame[3] = 0; ! 1669: respawnparm = false; ! 1670: fastparm = false; ! 1671: nomonsters = false; ! 1672: consoleplayer = 0; ! 1673: D_AdvanceDemo (); ! 1674: return true; ! 1675: } ! 1676: ! 1677: if (demorecording) ! 1678: { ! 1679: *demo_p++ = DEMOMARKER; ! 1680: M_WriteFile (demoname, demobuffer, demo_p - demobuffer); ! 1681: Z_Free (demobuffer); ! 1682: demorecording = false; ! 1683: I_Error ("Demo %s recorded",demoname); ! 1684: } ! 1685: ! 1686: return false; ! 1687: } ! 1688: ! 1689: ! 1690:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.