|
|
1.1.1.2 ! root 1: ! 2: // G_game.c ! 3: ! 4: #include <stdio.h> ! 5: #include <string.h> ! 6: #include "DoomDef.h" ! 7: #include "P_local.h" ! 8: #include "soundst.h" ! 9: ! 10: // Macros ! 11: ! 12: #define SVG_RAM 0 ! 13: #define SVG_FILE 1 ! 14: #define SAVE_GAME_TERMINATOR 0x1d ! 15: #define AM_STARTKEY 9 ! 16: ! 17: // Functions ! 18: ! 19: boolean G_CheckDemoStatus (void); ! 20: void G_ReadDemoTiccmd (ticcmd_t *cmd); ! 21: void G_WriteDemoTiccmd (ticcmd_t *cmd); ! 22: void G_PlayerReborn (int player); ! 23: void G_InitNew (skill_t skill, int episode, int map); ! 24: ! 25: void G_DoReborn (int playernum); ! 26: ! 27: void G_DoLoadLevel (void); ! 28: void G_DoNewGame (void); ! 29: void G_DoLoadGame (void); ! 30: void G_DoPlayDemo (void); ! 31: void G_DoCompleted (void); ! 32: void G_DoVictory (void); ! 33: void G_DoWorldDone (void); ! 34: void G_DoSaveGame (void); ! 35: ! 36: void D_PageTicker(void); ! 37: void D_AdvanceDemo(void); ! 38: ! 39: struct ! 40: { ! 41: mobjtype_t type; ! 42: int speed[2]; ! 43: } MonsterMissileInfo[] = ! 44: { ! 45: { MT_IMPBALL, 10, 20 }, ! 46: { MT_MUMMYFX1, 9, 18 }, ! 47: { MT_KNIGHTAXE, 9, 18 }, ! 48: { MT_REDAXE, 9, 18 }, ! 49: { MT_BEASTBALL, 12, 20 }, ! 50: { MT_WIZFX1, 18, 24 }, ! 51: { MT_SNAKEPRO_A, 14, 20 }, ! 52: { MT_SNAKEPRO_B, 14, 20 }, ! 53: { MT_HEADFX1, 13, 20 }, ! 54: { MT_HEADFX3, 10, 18 }, ! 55: { MT_MNTRFX1, 20, 26 }, ! 56: { MT_MNTRFX2, 14, 20 }, ! 57: { MT_SRCRFX1, 20, 28 }, ! 58: { MT_SOR2FX1, 20, 28 }, ! 59: { -1, -1, -1 } // Terminator ! 60: }; ! 61: ! 62: FILE *SaveGameFP; ! 63: int SaveGameType; ! 64: ! 65: gameaction_t gameaction; ! 66: gamestate_t gamestate; ! 67: skill_t gameskill; ! 68: boolean respawnmonsters; ! 69: int gameepisode; ! 70: int gamemap; ! 71: int prevmap; ! 72: ! 73: boolean paused; ! 74: boolean sendpause; // send a pause event next tic ! 75: boolean sendsave; // send a save event next tic ! 76: boolean usergame; // ok to save / end game ! 77: ! 78: boolean timingdemo; // if true, exit with report on completion ! 79: int starttime; // for comparative timing purposes ! 80: ! 81: boolean viewactive; ! 82: ! 83: boolean deathmatch; // only if started as net death ! 84: boolean netgame; // only true if packets are broadcast ! 85: boolean playeringame[MAXPLAYERS]; ! 86: player_t players[MAXPLAYERS]; ! 87: ! 88: int consoleplayer; // player taking events and displaying ! 89: int displayplayer; // view being displayed ! 90: int gametic; ! 91: int levelstarttic; // gametic at level start ! 92: int totalkills, totalitems, totalsecret; // for intermission ! 93: ! 94: char demoname[32]; ! 95: boolean demorecording; ! 96: boolean demoplayback; ! 97: byte *demobuffer, *demo_p; ! 98: boolean singledemo; // quit after playing a demo from cmdline ! 99: ! 100: boolean precache = true; // if true, load all graphics at start ! 101: ! 102: short consistancy[MAXPLAYERS][BACKUPTICS]; ! 103: ! 104: byte *savebuffer, *save_p; ! 105: ! 106: ! 107: // ! 108: // controls (have defaults) ! 109: // ! 110: int key_right, key_left, key_up, key_down; ! 111: int key_strafeleft, key_straferight; ! 112: int key_fire, key_use, key_strafe, key_speed; ! 113: int key_flyup, key_flydown, key_flycenter; ! 114: int key_lookup, key_lookdown, key_lookcenter; ! 115: int key_invleft, key_invright, key_useartifact; ! 116: ! 117: int mousebfire; ! 118: int mousebstrafe; ! 119: int mousebforward; ! 120: ! 121: int joybfire; ! 122: int joybstrafe; ! 123: int joybuse; ! 124: int joybspeed; ! 125: ! 126: ! 127: ! 128: #define MAXPLMOVE 0x32 ! 129: ! 130: fixed_t forwardmove[2] = {0x19, 0x32}; ! 131: fixed_t sidemove[2] = {0x18, 0x28}; ! 132: fixed_t angleturn[3] = {640, 1280, 320}; // + slow turn ! 133: #define SLOWTURNTICS 6 ! 134: ! 135: #define NUMKEYS 256 ! 136: boolean gamekeydown[NUMKEYS]; ! 137: int turnheld; // for accelerative turning ! 138: int lookheld; ! 139: ! 140: ! 141: boolean mousearray[4]; ! 142: boolean *mousebuttons = &mousearray[1]; ! 143: // allow [-1] ! 144: int mousex, mousey; // mouse values are used once ! 145: int dclicktime, dclickstate, dclicks; ! 146: int dclicktime2, dclickstate2, dclicks2; ! 147: ! 148: int joyxmove, joyymove; // joystick values are repeated ! 149: boolean joyarray[5]; ! 150: boolean *joybuttons = &joyarray[1]; // allow [-1] ! 151: ! 152: int savegameslot; ! 153: char savedescription[32]; ! 154: ! 155: int inventoryTics; ! 156: ! 157: #ifdef __WATCOMC__ ! 158: extern externdata_t *i_ExternData; ! 159: #endif ! 160: ! 161: //============================================================================= ! 162: // Not used - ripped out for Heretic ! 163: /* ! 164: int G_CmdChecksum(ticcmd_t *cmd) ! 165: { ! 166: int i; ! 167: int sum; ! 168: ! 169: sum = 0; ! 170: for(i = 0; i < sizeof(*cmd)/4-1; i++) 1.1 root 171: { 1.1.1.2 ! root 172: sum += ((int *)cmd)[i]; 1.1 root 173: } 1.1.1.2 ! root 174: return(sum); ! 175: } ! 176: */ ! 177: ! 178: /* ! 179: ==================== ! 180: = ! 181: = G_BuildTiccmd ! 182: = ! 183: = Builds a ticcmd from all of the available inputs or reads it from the ! 184: = demo buffer. ! 185: = If recording a demo, write it out ! 186: ==================== ! 187: */ 1.1 root 188: 1.1.1.2 ! root 189: extern boolean inventory; ! 190: extern int curpos; ! 191: extern int inv_ptr; ! 192: ! 193: extern int isCyberPresent; // is CyberMan present? ! 194: boolean usearti = true; ! 195: void I_ReadCyberCmd (ticcmd_t *cmd); ! 196: ! 197: void G_BuildTiccmd (ticcmd_t *cmd) 1.1 root 198: { 1.1.1.2 ! root 199: int i; ! 200: boolean strafe, bstrafe; ! 201: int speed, tspeed, lspeed; ! 202: int forward, side; ! 203: int look, arti; ! 204: int flyheight; ! 205: ! 206: extern boolean noartiskip; ! 207: ! 208: #ifdef __WATCOMC__ ! 209: int angleDelta; ! 210: static int oldAngle; ! 211: extern int newViewAngleOff; ! 212: static int externInvKey; ! 213: extern boolean automapactive; ! 214: event_t ev; ! 215: #endif ! 216: ! 217: ! 218: memset (cmd,0,sizeof(*cmd)); ! 219: //cmd->consistancy = ! 220: // consistancy[consoleplayer][(maketic*ticdup)%BACKUPTICS]; ! 221: cmd->consistancy = ! 222: consistancy[consoleplayer][maketic%BACKUPTICS]; ! 223: if (isCyberPresent) ! 224: I_ReadCyberCmd (cmd); ! 225: ! 226: //printf ("cons: %i\n",cmd->consistancy); ! 227: ! 228: strafe = gamekeydown[key_strafe] || mousebuttons[mousebstrafe] ! 229: || joybuttons[joybstrafe]; ! 230: speed = gamekeydown[key_speed] || joybuttons[joybspeed] ! 231: || joybuttons[joybspeed]; ! 232: #ifdef __WATCOMC__ ! 233: if(useexterndriver) ! 234: { ! 235: speed |= (i_ExternData->buttons&EBT_SPEED); ! 236: strafe |= (i_ExternData->buttons&EBT_STRAFE); ! 237: } ! 238: #endif ! 239: ! 240: forward = side = look = arti = flyheight = 0; ! 241: ! 242: // ! 243: // use two stage accelerative turning on the keyboard and joystick ! 244: // ! 245: if (joyxmove < 0 || joyxmove > 0 ! 246: || gamekeydown[key_right] || gamekeydown[key_left]) ! 247: turnheld += ticdup; 1.1 root 248: else 1.1.1.2 ! root 249: turnheld = 0; ! 250: if (turnheld < SLOWTURNTICS) ! 251: tspeed = 2; // slow turn ! 252: else ! 253: tspeed = speed; 1.1 root 254: 1.1.1.2 ! root 255: if(gamekeydown[key_lookdown] || gamekeydown[key_lookup]) ! 256: { ! 257: lookheld += ticdup; ! 258: } ! 259: else ! 260: { ! 261: lookheld = 0; ! 262: } ! 263: if(lookheld < SLOWTURNTICS) ! 264: { ! 265: lspeed = 1; ! 266: } ! 267: else ! 268: { ! 269: lspeed = 2; ! 270: } ! 271: ! 272: // ! 273: // let movement keys cancel each other out ! 274: // ! 275: if(strafe) ! 276: { ! 277: if (gamekeydown[key_right]) ! 278: side += sidemove[speed]; ! 279: if (gamekeydown[key_left]) ! 280: side -= sidemove[speed]; ! 281: if (joyxmove > 0) ! 282: side += sidemove[speed]; ! 283: if (joyxmove < 0) ! 284: side -= sidemove[speed]; ! 285: } ! 286: else ! 287: { ! 288: if (gamekeydown[key_right]) ! 289: cmd->angleturn -= angleturn[tspeed]; ! 290: if (gamekeydown[key_left]) ! 291: cmd->angleturn += angleturn[tspeed]; ! 292: if (joyxmove > 0) ! 293: cmd->angleturn -= angleturn[tspeed]; ! 294: if (joyxmove < 0) ! 295: cmd->angleturn += angleturn[tspeed]; ! 296: } 1.1 root 297: 1.1.1.2 ! root 298: if (gamekeydown[key_up]) ! 299: forward += forwardmove[speed]; ! 300: if (gamekeydown[key_down]) ! 301: forward -= forwardmove[speed]; ! 302: if (joyymove < 0) ! 303: forward += forwardmove[speed]; ! 304: if (joyymove > 0) ! 305: forward -= forwardmove[speed]; ! 306: if (gamekeydown[key_straferight]) ! 307: side += sidemove[speed]; ! 308: if (gamekeydown[key_strafeleft]) ! 309: side -= sidemove[speed]; 1.1 root 310: 1.1.1.2 ! root 311: // Look up/down/center keys ! 312: if(gamekeydown[key_lookup]) ! 313: { ! 314: look = lspeed; ! 315: } ! 316: if(gamekeydown[key_lookdown]) ! 317: { ! 318: look = -lspeed; ! 319: } ! 320: #ifdef __WATCOMC__ ! 321: if(gamekeydown[key_lookcenter] && !useexterndriver) ! 322: { ! 323: look = TOCENTER; ! 324: } ! 325: #else ! 326: if(gamekeydown[key_lookcenter]) ! 327: { ! 328: look = TOCENTER; ! 329: } ! 330: #endif ! 331: ! 332: #ifdef __WATCOMC__ ! 333: if(useexterndriver && look != TOCENTER && (gamestate == GS_LEVEL || ! 334: gamestate == GS_INTERMISSION)) ! 335: { ! 336: if(i_ExternData->moveForward) 1.1 root 337: { 1.1.1.2 ! root 338: forward += i_ExternData->moveForward; ! 339: if(speed) 1.1 root 340: { 1.1.1.2 ! root 341: forward <<= 1; 1.1 root 342: } 343: } 1.1.1.2 ! root 344: if(i_ExternData->angleTurn) ! 345: { ! 346: if(strafe) ! 347: { ! 348: side += i_ExternData->angleTurn; ! 349: } ! 350: else ! 351: { ! 352: cmd->angleturn += i_ExternData->angleTurn; ! 353: } ! 354: } ! 355: if(i_ExternData->moveSideways) ! 356: { ! 357: side += i_ExternData->moveSideways; ! 358: if(speed) ! 359: { ! 360: side <<= 1; ! 361: } ! 362: } ! 363: if(i_ExternData->buttons&EBT_CENTERVIEW) 1.1 root 364: { 1.1.1.2 ! root 365: look = TOCENTER; ! 366: oldAngle = 0; 1.1 root 367: } 1.1.1.2 ! root 368: else if(i_ExternData->pitch) ! 369: { ! 370: angleDelta = i_ExternData->pitch-oldAngle; ! 371: if(abs(angleDelta) < 35) ! 372: { ! 373: look = angleDelta/5; ! 374: } ! 375: else ! 376: { ! 377: look = 7*(angleDelta > 0 ? 1 : -1); ! 378: } ! 379: if(look == TOCENTER) ! 380: { ! 381: look++; ! 382: } ! 383: oldAngle += look*5; ! 384: } ! 385: if(i_ExternData->flyDirection) ! 386: { ! 387: if(i_ExternData->flyDirection > 0) ! 388: { ! 389: flyheight = 5; ! 390: } ! 391: else ! 392: { ! 393: flyheight = -5; ! 394: } ! 395: } ! 396: if(abs(newViewAngleOff-i_ExternData->angleHead) < 3000) ! 397: { ! 398: newViewAngleOff = i_ExternData->angleHead; ! 399: } ! 400: if(i_ExternData->buttons&EBT_FIRE) 1.1 root 401: { 1.1.1.2 ! root 402: cmd->buttons |= BT_ATTACK; ! 403: } ! 404: if(i_ExternData->buttons&EBT_OPENDOOR) ! 405: { ! 406: cmd->buttons |= BT_USE; ! 407: } ! 408: if(i_ExternData->buttons&EBT_PAUSE) ! 409: { ! 410: cmd->buttons = BT_SPECIAL | BTS_PAUSE; ! 411: i_ExternData->buttons &= ~EBT_PAUSE; ! 412: } ! 413: if(externInvKey&EBT_USEARTIFACT) ! 414: { ! 415: ev.type = ev_keyup; ! 416: ev.data1 = key_useartifact; ! 417: D_PostEvent(&ev); ! 418: externInvKey &= ~EBT_USEARTIFACT; ! 419: } ! 420: else if(i_ExternData->buttons&EBT_USEARTIFACT) ! 421: { ! 422: externInvKey |= EBT_USEARTIFACT; ! 423: ev.type = ev_keydown; ! 424: ev.data1 = key_useartifact; ! 425: D_PostEvent(&ev); ! 426: } ! 427: if(externInvKey&EBT_INVENTORYRIGHT) ! 428: { ! 429: ev.type = ev_keyup; ! 430: ev.data1 = key_invright; ! 431: D_PostEvent(&ev); ! 432: externInvKey &= ~EBT_INVENTORYRIGHT; ! 433: } ! 434: else if(i_ExternData->buttons&EBT_INVENTORYRIGHT) ! 435: { ! 436: externInvKey |= EBT_INVENTORYRIGHT; ! 437: ev.type = ev_keydown; ! 438: ev.data1 = key_invright; ! 439: D_PostEvent(&ev); ! 440: } ! 441: if(externInvKey&EBT_INVENTORYLEFT) ! 442: { ! 443: ev.type = ev_keyup; ! 444: ev.data1 = key_invleft; ! 445: D_PostEvent(&ev); ! 446: externInvKey &= ~EBT_INVENTORYLEFT; ! 447: } ! 448: else if(i_ExternData->buttons&EBT_INVENTORYLEFT) ! 449: { ! 450: externInvKey |= EBT_INVENTORYLEFT; ! 451: ev.type = ev_keydown; ! 452: ev.data1 = key_invleft; ! 453: D_PostEvent(&ev); ! 454: } ! 455: if(i_ExternData->buttons&EBT_FLYDROP) ! 456: { ! 457: flyheight = TOCENTER; ! 458: } ! 459: if(gamestate == GS_LEVEL) ! 460: { ! 461: if(externInvKey&EBT_MAP) ! 462: { // AutoMap ! 463: ev.type = ev_keyup; ! 464: ev.data1 = AM_STARTKEY; ! 465: D_PostEvent(&ev); ! 466: externInvKey &= ~EBT_MAP; ! 467: } ! 468: else if(i_ExternData->buttons&EBT_MAP) ! 469: { ! 470: externInvKey |= EBT_MAP; ! 471: ev.type = ev_keydown; ! 472: ev.data1 = AM_STARTKEY; ! 473: D_PostEvent(&ev); ! 474: } ! 475: } ! 476: #if 0 ! 477: if((i = (i_ExternData->buttons>>EBT_WEAPONSHIFT)&EBT_WEAPONMASK) != 0) ! 478: { ! 479: cmd->buttons |= BT_CHANGE; ! 480: cmd->buttons |= (i-1)<<BT_WEAPONSHIFT; ! 481: } ! 482: #endif ! 483: if(i_ExternData->buttons&EBT_WEAPONCYCLE) ! 484: { ! 485: int curWeapon; ! 486: player_t *pl; ! 487: ! 488: pl = &players[consoleplayer]; ! 489: curWeapon = pl->readyweapon; ! 490: for(curWeapon = (curWeapon+1)&7; curWeapon != pl->readyweapon; ! 491: curWeapon = (curWeapon+1)&7) 1.1 root 492: { 1.1.1.2 ! root 493: if(pl->weaponowned[curWeapon]) ! 494: { ! 495: if(curWeapon >= wp_goldwand && curWeapon <= wp_mace && ! 496: !pl->ammo[wpnlev1info[curWeapon].ammo]) ! 497: { // weapon that requires ammo is empty ! 498: continue; ! 499: } ! 500: break; ! 501: } 1.1 root 502: } 1.1.1.2 ! root 503: cmd->buttons |= BT_CHANGE; ! 504: cmd->buttons |= curWeapon<<BT_WEAPONSHIFT; ! 505: } ! 506: } 1.1 root 507: #endif 508: 1.1.1.2 ! root 509: // Fly up/down/drop keys ! 510: if(gamekeydown[key_flyup]) ! 511: { ! 512: flyheight = 5; // note that the actual flyheight will be twice this ! 513: } ! 514: if(gamekeydown[key_flydown]) ! 515: { ! 516: flyheight = -5; ! 517: } ! 518: if(gamekeydown[key_flycenter]) ! 519: { ! 520: flyheight = TOCENTER; ! 521: #ifdef __WATCOMC__ ! 522: if(!useexterndriver) ! 523: { ! 524: look = TOCENTER; 1.1 root 525: } 1.1.1.2 ! root 526: #else ! 527: look = TOCENTER; 1.1 root 528: #endif 1.1.1.2 ! root 529: } ! 530: ! 531: // Use artifact key ! 532: if(gamekeydown[key_useartifact]) ! 533: { ! 534: if(gamekeydown[key_speed] && !noartiskip) ! 535: { ! 536: if(players[consoleplayer].inventory[inv_ptr].type != arti_none) ! 537: { ! 538: gamekeydown[key_useartifact] = false; ! 539: cmd->arti = 0xff; // skip artifact code ! 540: } ! 541: } ! 542: else ! 543: { ! 544: if(inventory) ! 545: { ! 546: players[consoleplayer].readyArtifact = ! 547: players[consoleplayer].inventory[inv_ptr].type; ! 548: inventory = false; ! 549: cmd->arti = 0; ! 550: usearti = false; ! 551: } ! 552: else if(usearti) ! 553: { ! 554: cmd->arti = players[consoleplayer].inventory[inv_ptr].type; ! 555: usearti = false; ! 556: } ! 557: } ! 558: } ! 559: if(gamekeydown[127] && !cmd->arti ! 560: && !players[consoleplayer].powers[pw_weaponlevel2]) ! 561: { ! 562: gamekeydown[127] = false; ! 563: cmd->arti = arti_tomeofpower; ! 564: } ! 565: ! 566: // ! 567: // buttons ! 568: // ! 569: cmd->chatchar = CT_dequeueChatChar(); ! 570: ! 571: if (gamekeydown[key_fire] || mousebuttons[mousebfire] ! 572: || joybuttons[joybfire]) ! 573: cmd->buttons |= BT_ATTACK; ! 574: ! 575: if (gamekeydown[key_use] || joybuttons[joybuse] ) ! 576: { ! 577: cmd->buttons |= BT_USE; ! 578: dclicks = 0; // clear double clicks if hit use button ! 579: } ! 580: ! 581: for(i = 0; i < NUMWEAPONS-2; i++) ! 582: { ! 583: if(gamekeydown['1'+i]) ! 584: { ! 585: cmd->buttons |= BT_CHANGE; ! 586: cmd->buttons |= i<<BT_WEAPONSHIFT; ! 587: break; ! 588: } ! 589: } ! 590: ! 591: // ! 592: // mouse ! 593: // ! 594: if (mousebuttons[mousebforward]) ! 595: { ! 596: forward += forwardmove[speed]; ! 597: } ! 598: ! 599: // ! 600: // forward double click ! 601: // ! 602: if (mousebuttons[mousebforward] != dclickstate && dclicktime > 1 ) ! 603: { ! 604: dclickstate = mousebuttons[mousebforward]; ! 605: if (dclickstate) ! 606: dclicks++; ! 607: if (dclicks == 2) ! 608: { ! 609: cmd->buttons |= BT_USE; ! 610: dclicks = 0; ! 611: } ! 612: else ! 613: dclicktime = 0; ! 614: } ! 615: else ! 616: { ! 617: dclicktime += ticdup; ! 618: if (dclicktime > 20) ! 619: { ! 620: dclicks = 0; ! 621: dclickstate = 0; ! 622: } ! 623: } ! 624: ! 625: // ! 626: // strafe double click ! 627: // ! 628: bstrafe = mousebuttons[mousebstrafe] ! 629: || joybuttons[joybstrafe]; ! 630: if (bstrafe != dclickstate2 && dclicktime2 > 1 ) ! 631: { ! 632: dclickstate2 = bstrafe; ! 633: if (dclickstate2) ! 634: dclicks2++; ! 635: if (dclicks2 == 2) ! 636: { ! 637: cmd->buttons |= BT_USE; ! 638: dclicks2 = 0; ! 639: } ! 640: else ! 641: dclicktime2 = 0; ! 642: } ! 643: else ! 644: { ! 645: dclicktime2 += ticdup; ! 646: if (dclicktime2 > 20) ! 647: { ! 648: dclicks2 = 0; ! 649: dclickstate2 = 0; ! 650: } ! 651: } ! 652: ! 653: if (strafe) ! 654: { ! 655: side += mousex*2; ! 656: } ! 657: else ! 658: { ! 659: cmd->angleturn -= mousex*0x8; ! 660: } ! 661: forward += mousey; ! 662: mousex = mousey = 0; ! 663: ! 664: if (forward > MAXPLMOVE) ! 665: forward = MAXPLMOVE; ! 666: else if (forward < -MAXPLMOVE) ! 667: forward = -MAXPLMOVE; ! 668: if (side > MAXPLMOVE) ! 669: side = MAXPLMOVE; ! 670: else if (side < -MAXPLMOVE) ! 671: side = -MAXPLMOVE; ! 672: ! 673: cmd->forwardmove += forward; ! 674: cmd->sidemove += side; ! 675: if(players[consoleplayer].playerstate == PST_LIVE) ! 676: { ! 677: if(look < 0) ! 678: { ! 679: look += 16; ! 680: } ! 681: cmd->lookfly = look; ! 682: } ! 683: if(flyheight < 0) ! 684: { ! 685: flyheight += 16; ! 686: } ! 687: cmd->lookfly |= flyheight<<4; ! 688: ! 689: // ! 690: // special buttons ! 691: // ! 692: if (sendpause) ! 693: { ! 694: sendpause = false; ! 695: cmd->buttons = BT_SPECIAL | BTS_PAUSE; ! 696: } 1.1 root 697: 1.1.1.2 ! root 698: if (sendsave) ! 699: { ! 700: sendsave = false; ! 701: cmd->buttons = BT_SPECIAL | BTS_SAVEGAME | (savegameslot<<BTS_SAVESHIFT); 1.1 root 702: } 1.1.1.2 ! root 703: 1.1 root 704: } 705: 706: 1.1.1.2 ! root 707: /* ! 708: ============== ! 709: = ! 710: = G_DoLoadLevel ! 711: = ! 712: ============== ! 713: */ ! 714: ! 715: void G_DoLoadLevel (void) ! 716: { ! 717: int i; ! 718: ! 719: levelstarttic = gametic; // for time calculation ! 720: gamestate = GS_LEVEL; ! 721: for (i=0 ; i<MAXPLAYERS ; i++) ! 722: { ! 723: if (playeringame[i] && players[i].playerstate == PST_DEAD) ! 724: players[i].playerstate = PST_REBORN; ! 725: memset (players[i].frags,0,sizeof(players[i].frags)); ! 726: } ! 727: ! 728: P_SetupLevel (gameepisode, gamemap, 0, gameskill); ! 729: displayplayer = consoleplayer; // view the guy you are playing ! 730: starttime = I_GetTime (); ! 731: gameaction = ga_nothing; ! 732: Z_CheckHeap (); ! 733: ! 734: // ! 735: // clear cmd building stuff ! 736: // ! 737: ! 738: memset (gamekeydown, 0, sizeof(gamekeydown)); ! 739: joyxmove = joyymove = 0; ! 740: mousex = mousey = 0; ! 741: sendpause = sendsave = paused = false; ! 742: memset (mousebuttons, 0, sizeof(mousebuttons)); ! 743: memset (joybuttons, 0, sizeof(joybuttons)); 1.1 root 744: } 745: 1.1.1.2 ! root 746: 1.1 root 747: /* 1.1.1.2 ! root 748: =============================================================================== 1.1 root 749: = 1.1.1.2 ! root 750: = G_Responder ! 751: = ! 752: = get info needed to make ticcmd_ts for the players 1.1 root 753: = 1.1.1.2 ! root 754: =============================================================================== 1.1 root 755: */ 756: 1.1.1.2 ! root 757: boolean G_Responder(event_t *ev) 1.1 root 758: { 1.1.1.2 ! root 759: player_t *plr; ! 760: extern boolean MenuActive; ! 761: ! 762: plr = &players[consoleplayer]; ! 763: if(ev->type == ev_keyup && ev->data1 == key_useartifact) ! 764: { // flag to denote that it's okay to use an artifact ! 765: if(!inventory) ! 766: { ! 767: plr->readyArtifact = plr->inventory[inv_ptr].type; ! 768: } ! 769: usearti = true; ! 770: } ! 771: ! 772: // Check for spy mode player cycle ! 773: if(gamestate == GS_LEVEL && ev->type == ev_keydown ! 774: && ev->data1 == KEY_F12 && !deathmatch) ! 775: { // Cycle the display player ! 776: do ! 777: { ! 778: displayplayer++; ! 779: if(displayplayer == MAXPLAYERS) ! 780: { ! 781: displayplayer = 0; ! 782: } ! 783: } while(!playeringame[displayplayer] ! 784: && displayplayer != consoleplayer); ! 785: return(true); ! 786: } ! 787: ! 788: if(gamestate == GS_LEVEL) ! 789: { ! 790: if(CT_Responder(ev)) ! 791: { // Chat ate the event ! 792: return(true); ! 793: } ! 794: if(SB_Responder(ev)) ! 795: { // Status bar ate the event ! 796: return(true); ! 797: } ! 798: if(AM_Responder(ev)) ! 799: { // Automap ate the event ! 800: return(true); ! 801: } ! 802: } ! 803: ! 804: switch(ev->type) 1.1 root 805: { 1.1.1.2 ! root 806: case ev_keydown: ! 807: if(ev->data1 == key_invleft) ! 808: { ! 809: inventoryTics = 5*35; ! 810: if(!inventory) ! 811: { ! 812: inventory = true; ! 813: break; ! 814: } ! 815: inv_ptr--; ! 816: if(inv_ptr < 0) ! 817: { ! 818: inv_ptr = 0; ! 819: } ! 820: else ! 821: { ! 822: curpos--; ! 823: if(curpos < 0) ! 824: { ! 825: curpos = 0; ! 826: } ! 827: } ! 828: return(true); ! 829: } ! 830: if(ev->data1 == key_invright) ! 831: { ! 832: inventoryTics = 5*35; ! 833: if(!inventory) ! 834: { ! 835: inventory = true; ! 836: break; ! 837: } ! 838: inv_ptr++; ! 839: if(inv_ptr >= plr->inventorySlotNum) ! 840: { ! 841: inv_ptr--; ! 842: if(inv_ptr < 0) ! 843: inv_ptr = 0; ! 844: } ! 845: else ! 846: { ! 847: curpos++; ! 848: if(curpos > 6) ! 849: { ! 850: curpos = 6; ! 851: } ! 852: } ! 853: return(true); ! 854: } ! 855: if(ev->data1 == KEY_PAUSE && !MenuActive) ! 856: { ! 857: sendpause = true; ! 858: return(true); ! 859: } ! 860: if(ev->data1 < NUMKEYS) ! 861: { ! 862: gamekeydown[ev->data1] = true; ! 863: } ! 864: return(true); // eat key down events ! 865: ! 866: case ev_keyup: ! 867: if(ev->data1 < NUMKEYS) ! 868: { ! 869: gamekeydown[ev->data1] = false; ! 870: } ! 871: return(false); // always let key up events filter down ! 872: ! 873: case ev_mouse: ! 874: mousebuttons[0] = ev->data1&1; ! 875: mousebuttons[1] = ev->data1&2; ! 876: mousebuttons[2] = ev->data1&4; ! 877: mousex = ev->data2*(mouseSensitivity+5)/10; ! 878: mousey = ev->data3*(mouseSensitivity+5)/10; ! 879: return(true); // eat events ! 880: ! 881: case ev_joystick: ! 882: joybuttons[0] = ev->data1&1; ! 883: joybuttons[1] = ev->data1&2; ! 884: joybuttons[2] = ev->data1&4; ! 885: joybuttons[3] = ev->data1&8; ! 886: joyxmove = ev->data2; ! 887: joyymove = ev->data3; ! 888: return(true); // eat events ! 889: ! 890: default: ! 891: break; 1.1 root 892: } 1.1.1.2 ! root 893: return(false); 1.1 root 894: } 895: 1.1.1.2 ! root 896: /* ! 897: =============================================================================== ! 898: = ! 899: = G_Ticker ! 900: = ! 901: =============================================================================== ! 902: */ ! 903: ! 904: void G_Ticker (void) ! 905: { ! 906: int i, buf; ! 907: ticcmd_t *cmd; ! 908: ! 909: // ! 910: // do player reborns if needed ! 911: // ! 912: for (i=0 ; i<MAXPLAYERS ; i++) ! 913: if (playeringame[i] && players[i].playerstate == PST_REBORN) ! 914: G_DoReborn (i); ! 915: ! 916: // ! 917: // do things to change the game state ! 918: // ! 919: while (gameaction != ga_nothing) ! 920: { ! 921: switch (gameaction) ! 922: { ! 923: case ga_loadlevel: ! 924: G_DoLoadLevel (); ! 925: break; ! 926: case ga_newgame: ! 927: G_DoNewGame (); ! 928: break; ! 929: case ga_loadgame: ! 930: G_DoLoadGame (); ! 931: break; ! 932: case ga_savegame: ! 933: G_DoSaveGame (); ! 934: break; ! 935: case ga_playdemo: ! 936: G_DoPlayDemo (); ! 937: break; ! 938: case ga_screenshot: ! 939: M_ScreenShot (); ! 940: gameaction = ga_nothing; ! 941: break; ! 942: case ga_completed: ! 943: G_DoCompleted (); ! 944: break; ! 945: case ga_worlddone: ! 946: G_DoWorldDone(); ! 947: break; ! 948: case ga_victory: ! 949: F_StartFinale(); ! 950: break; ! 951: default: ! 952: break; ! 953: } ! 954: } ! 955: ! 956: ! 957: // ! 958: // get commands, check consistancy, and build new consistancy check ! 959: // ! 960: //buf = gametic%BACKUPTICS; ! 961: buf = (gametic/ticdup)%BACKUPTICS; ! 962: ! 963: for (i=0 ; i<MAXPLAYERS ; i++) ! 964: if (playeringame[i]) ! 965: { ! 966: cmd = &players[i].cmd; ! 967: ! 968: memcpy (cmd, &netcmds[i][buf], sizeof(ticcmd_t)); ! 969: ! 970: if (demoplayback) ! 971: G_ReadDemoTiccmd (cmd); ! 972: if (demorecording) ! 973: G_WriteDemoTiccmd (cmd); ! 974: ! 975: if (netgame && !(gametic%ticdup) ) ! 976: { ! 977: if (gametic > BACKUPTICS ! 978: && consistancy[i][buf] != cmd->consistancy) ! 979: { ! 980: I_Error ("consistency failure (%i should be %i)",cmd->consistancy, consistancy[i][buf]); ! 981: } ! 982: if (players[i].mo) ! 983: consistancy[i][buf] = players[i].mo->x; ! 984: else ! 985: consistancy[i][buf] = rndindex; ! 986: } ! 987: } ! 988: ! 989: // ! 990: // check for special buttons ! 991: // ! 992: for (i=0 ; i<MAXPLAYERS ; i++) ! 993: if (playeringame[i]) ! 994: { ! 995: if (players[i].cmd.buttons & BT_SPECIAL) ! 996: { ! 997: switch (players[i].cmd.buttons & BT_SPECIALMASK) ! 998: { ! 999: case BTS_PAUSE: ! 1000: paused ^= 1; ! 1001: if(paused) ! 1002: { ! 1003: S_PauseSound(); ! 1004: } ! 1005: else ! 1006: { ! 1007: S_ResumeSound(); ! 1008: } ! 1009: break; ! 1010: ! 1011: case BTS_SAVEGAME: ! 1012: if (!savedescription[0]) ! 1013: { ! 1014: if(netgame) ! 1015: { ! 1016: strcpy (savedescription, "NET GAME"); ! 1017: } ! 1018: else ! 1019: { ! 1020: strcpy(savedescription, "SAVE GAME"); ! 1021: } ! 1022: } ! 1023: savegameslot = ! 1024: (players[i].cmd.buttons & BTS_SAVEMASK)>>BTS_SAVESHIFT; ! 1025: gameaction = ga_savegame; ! 1026: break; ! 1027: } ! 1028: } ! 1029: } ! 1030: // turn inventory off after a certain amount of time ! 1031: if(inventory && !(--inventoryTics)) ! 1032: { ! 1033: players[consoleplayer].readyArtifact = ! 1034: players[consoleplayer].inventory[inv_ptr].type; ! 1035: inventory = false; ! 1036: cmd->arti = 0; ! 1037: } ! 1038: // ! 1039: // do main actions ! 1040: // ! 1041: // ! 1042: // do main actions ! 1043: // ! 1044: switch (gamestate) ! 1045: { ! 1046: case GS_LEVEL: ! 1047: P_Ticker (); ! 1048: SB_Ticker (); ! 1049: AM_Ticker (); ! 1050: CT_Ticker(); ! 1051: break; ! 1052: case GS_INTERMISSION: ! 1053: IN_Ticker (); ! 1054: break; ! 1055: case GS_FINALE: ! 1056: F_Ticker(); ! 1057: break; ! 1058: case GS_DEMOSCREEN: ! 1059: D_PageTicker (); ! 1060: break; ! 1061: } ! 1062: } ! 1063: ! 1064: ! 1065: /* ! 1066: ============================================================================== ! 1067: ! 1068: PLAYER STRUCTURE FUNCTIONS ! 1069: ! 1070: also see P_SpawnPlayer in P_Things ! 1071: ============================================================================== ! 1072: */ ! 1073: ! 1074: /* ! 1075: ==================== ! 1076: = ! 1077: = G_InitPlayer ! 1078: = ! 1079: = Called at the start ! 1080: = Called by the game initialization functions ! 1081: ==================== ! 1082: */ ! 1083: ! 1084: void G_InitPlayer (int player) ! 1085: { ! 1086: player_t *p; ! 1087: ! 1088: // set up the saved info ! 1089: p = &players[player]; ! 1090: ! 1091: // clear everything else to defaults ! 1092: G_PlayerReborn (player); ! 1093: ! 1094: } ! 1095: ! 1096: ! 1097: /* ! 1098: ==================== ! 1099: = ! 1100: = G_PlayerFinishLevel ! 1101: = ! 1102: = Can when a player completes a level ! 1103: ==================== ! 1104: */ ! 1105: extern int curpos; ! 1106: extern int inv_ptr; ! 1107: extern int playerkeys; ! 1108: ! 1109: void G_PlayerFinishLevel(int player) ! 1110: { ! 1111: player_t *p; ! 1112: int i; ! 1113: ! 1114: /* // BIG HACK ! 1115: inv_ptr = 0; ! 1116: curpos = 0; ! 1117: */ ! 1118: // END HACK ! 1119: p = &players[player]; ! 1120: for(i=0; i<p->inventorySlotNum; i++) ! 1121: { ! 1122: p->inventory[i].count = 1; ! 1123: } ! 1124: p->artifactCount = p->inventorySlotNum; ! 1125: ! 1126: if(!deathmatch) ! 1127: { ! 1128: for(i = 0; i < 16; i++) ! 1129: { ! 1130: P_PlayerUseArtifact(p, arti_fly); ! 1131: } ! 1132: } ! 1133: memset(p->powers, 0, sizeof(p->powers)); ! 1134: memset(p->keys, 0, sizeof(p->keys)); ! 1135: playerkeys = 0; ! 1136: // memset(p->inventory, 0, sizeof(p->inventory)); ! 1137: if(p->chickenTics) ! 1138: { ! 1139: p->readyweapon = p->mo->special1; // Restore weapon ! 1140: p->chickenTics = 0; ! 1141: } ! 1142: p->messageTics = 0; ! 1143: p->lookdir = 0; ! 1144: p->mo->flags &= ~MF_SHADOW; // Remove invisibility ! 1145: p->extralight = 0; // Remove weapon flashes ! 1146: p->fixedcolormap = 0; // Remove torch ! 1147: p->damagecount = 0; // No palette changes ! 1148: p->bonuscount = 0; ! 1149: p->rain1 = NULL; ! 1150: p->rain2 = NULL; ! 1151: if(p == &players[consoleplayer]) ! 1152: { ! 1153: SB_state = -1; // refresh the status bar ! 1154: } ! 1155: } ! 1156: ! 1157: /* ! 1158: ==================== ! 1159: = ! 1160: = G_PlayerReborn ! 1161: = ! 1162: = Called after a player dies ! 1163: = almost everything is cleared and initialized ! 1164: ==================== ! 1165: */ ! 1166: ! 1167: void G_PlayerReborn(int player) ! 1168: { ! 1169: player_t *p; ! 1170: int i; ! 1171: int frags[MAXPLAYERS]; ! 1172: int killcount, itemcount, secretcount; ! 1173: boolean secret; ! 1174: ! 1175: secret = false; ! 1176: memcpy(frags, players[player].frags, sizeof(frags)); ! 1177: killcount = players[player].killcount; ! 1178: itemcount = players[player].itemcount; ! 1179: secretcount = players[player].secretcount; ! 1180: ! 1181: p = &players[player]; ! 1182: if(p->didsecret) ! 1183: { ! 1184: secret = true; ! 1185: } ! 1186: memset(p, 0, sizeof(*p)); ! 1187: ! 1188: memcpy(players[player].frags, frags, sizeof(players[player].frags)); ! 1189: players[player].killcount = killcount; ! 1190: players[player].itemcount = itemcount; ! 1191: players[player].secretcount = secretcount; ! 1192: ! 1193: p->usedown = p->attackdown = true; // don't do anything immediately ! 1194: p->playerstate = PST_LIVE; ! 1195: p->health = MAXHEALTH; ! 1196: p->readyweapon = p->pendingweapon = wp_goldwand; ! 1197: p->weaponowned[wp_staff] = true; ! 1198: p->weaponowned[wp_goldwand] = true; ! 1199: p->messageTics = 0; ! 1200: p->lookdir = 0; ! 1201: p->ammo[am_goldwand] = 50; ! 1202: for(i = 0; i < NUMAMMO; i++) ! 1203: { ! 1204: p->maxammo[i] = maxammo[i]; ! 1205: } ! 1206: if(gamemap == 9 || secret) ! 1207: { ! 1208: p->didsecret = true; ! 1209: } ! 1210: if(p == &players[consoleplayer]) ! 1211: { ! 1212: SB_state = -1; // refresh the status bar ! 1213: inv_ptr = 0; // reset the inventory pointer ! 1214: curpos = 0; ! 1215: } ! 1216: } ! 1217: ! 1218: /* ! 1219: ==================== ! 1220: = ! 1221: = G_CheckSpot ! 1222: = ! 1223: = Returns false if the player cannot be respawned at the given mapthing_t spot ! 1224: = because something is occupying it ! 1225: ==================== ! 1226: */ ! 1227: ! 1228: void P_SpawnPlayer (mapthing_t *mthing); ! 1229: ! 1230: boolean G_CheckSpot (int playernum, mapthing_t *mthing) ! 1231: { ! 1232: fixed_t x,y; ! 1233: subsector_t *ss; ! 1234: unsigned an; ! 1235: mobj_t *mo; ! 1236: ! 1237: x = mthing->x << FRACBITS; ! 1238: y = mthing->y << FRACBITS; ! 1239: ! 1240: players[playernum].mo->flags2 &= ~MF2_PASSMOBJ; ! 1241: if (!P_CheckPosition (players[playernum].mo, x, y) ) ! 1242: { ! 1243: players[playernum].mo->flags2 |= MF2_PASSMOBJ; ! 1244: return false; ! 1245: } ! 1246: players[playernum].mo->flags2 |= MF2_PASSMOBJ; ! 1247: ! 1248: // spawn a teleport fog ! 1249: ss = R_PointInSubsector (x,y); ! 1250: an = ( ANG45 * (mthing->angle/45) ) >> ANGLETOFINESHIFT; ! 1251: ! 1252: mo = P_SpawnMobj (x+20*finecosine[an], y+20*finesine[an] ! 1253: , ss->sector->floorheight+TELEFOGHEIGHT ! 1254: , MT_TFOG); ! 1255: ! 1256: if (players[consoleplayer].viewz != 1) ! 1257: S_StartSound (mo, sfx_telept); // don't start sound on first frame ! 1258: ! 1259: return true; ! 1260: } ! 1261: ! 1262: /* ! 1263: ==================== ! 1264: = ! 1265: = G_DeathMatchSpawnPlayer ! 1266: = ! 1267: = Spawns a player at one of the random death match spots ! 1268: = called at level load and each death ! 1269: ==================== ! 1270: */ ! 1271: ! 1272: void G_DeathMatchSpawnPlayer (int playernum) ! 1273: { ! 1274: int i,j; ! 1275: int selections; ! 1276: ! 1277: selections = deathmatch_p - deathmatchstarts; ! 1278: if (selections < 4) ! 1279: I_Error ("Only %i deathmatch spots, 4 required", selections); ! 1280: ! 1281: for (j=0 ; j<20 ; j++) ! 1282: { ! 1283: i = P_Random() % selections; ! 1284: if (G_CheckSpot (playernum, &deathmatchstarts[i]) ) ! 1285: { ! 1286: deathmatchstarts[i].type = playernum+1; ! 1287: P_SpawnPlayer (&deathmatchstarts[i]); ! 1288: return; ! 1289: } ! 1290: } ! 1291: ! 1292: // no good spot, so the player will probably get stuck ! 1293: P_SpawnPlayer (&playerstarts[playernum]); ! 1294: } ! 1295: ! 1296: /* ! 1297: ==================== ! 1298: = ! 1299: = G_DoReborn ! 1300: = ! 1301: ==================== ! 1302: */ ! 1303: ! 1304: void G_DoReborn (int playernum) ! 1305: { ! 1306: int i; ! 1307: ! 1308: if (G_CheckDemoStatus ()) ! 1309: return; ! 1310: if (!netgame) ! 1311: gameaction = ga_loadlevel; // reload the level from scratch ! 1312: else ! 1313: { // respawn at the start ! 1314: players[playernum].mo->player = NULL; // dissasociate the corpse ! 1315: ! 1316: // spawn at random spot if in death match ! 1317: if (deathmatch) ! 1318: { ! 1319: G_DeathMatchSpawnPlayer (playernum); ! 1320: return; ! 1321: } ! 1322: ! 1323: if (G_CheckSpot (playernum, &playerstarts[playernum]) ) ! 1324: { ! 1325: P_SpawnPlayer (&playerstarts[playernum]); ! 1326: return; ! 1327: } ! 1328: // try to spawn at one of the other players spots ! 1329: for (i=0 ; i<MAXPLAYERS ; i++) ! 1330: if (G_CheckSpot (playernum, &playerstarts[i]) ) ! 1331: { ! 1332: playerstarts[i].type = playernum+1; // fake as other player ! 1333: P_SpawnPlayer (&playerstarts[i]); ! 1334: playerstarts[i].type = i+1; // restore ! 1335: return; ! 1336: } ! 1337: // he's going to be inside something. Too bad. ! 1338: P_SpawnPlayer (&playerstarts[playernum]); ! 1339: } ! 1340: } ! 1341: ! 1342: ! 1343: void G_ScreenShot (void) ! 1344: { ! 1345: gameaction = ga_screenshot; ! 1346: } ! 1347: ! 1348: ! 1349: /* ! 1350: ==================== ! 1351: = ! 1352: = G_DoCompleted ! 1353: = ! 1354: ==================== ! 1355: */ ! 1356: ! 1357: boolean secretexit; ! 1358: ! 1359: void G_ExitLevel (void) ! 1360: { ! 1361: secretexit = false; ! 1362: gameaction = ga_completed; ! 1363: } ! 1364: ! 1365: void G_SecretExitLevel (void) ! 1366: { ! 1367: secretexit = true; ! 1368: gameaction = ga_completed; ! 1369: } ! 1370: ! 1371: void G_DoCompleted(void) ! 1372: { ! 1373: int i; ! 1374: static int afterSecret[5] = { 7, 5, 5, 5, 4 }; ! 1375: ! 1376: gameaction = ga_nothing; ! 1377: if(G_CheckDemoStatus()) ! 1378: { ! 1379: return; ! 1380: } ! 1381: for(i = 0; i < MAXPLAYERS; i++) ! 1382: { ! 1383: if(playeringame[i]) ! 1384: { ! 1385: G_PlayerFinishLevel(i); ! 1386: } ! 1387: } ! 1388: prevmap = gamemap; ! 1389: if(secretexit == true) ! 1390: { ! 1391: gamemap = 9; ! 1392: } ! 1393: else if(gamemap == 9) ! 1394: { // Finished secret level ! 1395: gamemap = afterSecret[gameepisode-1]; ! 1396: } ! 1397: else if(gamemap == 8) ! 1398: { ! 1399: gameaction = ga_victory; ! 1400: return; ! 1401: } ! 1402: else ! 1403: { ! 1404: gamemap++; ! 1405: } ! 1406: gamestate = GS_INTERMISSION; ! 1407: IN_Start(); ! 1408: } ! 1409: ! 1410: //============================================================================ ! 1411: // ! 1412: // G_WorldDone ! 1413: // ! 1414: //============================================================================ ! 1415: ! 1416: void G_WorldDone(void) ! 1417: { ! 1418: gameaction = ga_worlddone; ! 1419: } ! 1420: ! 1421: //============================================================================ ! 1422: // ! 1423: // G_DoWorldDone ! 1424: // ! 1425: //============================================================================ ! 1426: ! 1427: void G_DoWorldDone(void) ! 1428: { ! 1429: gamestate = GS_LEVEL; ! 1430: G_DoLoadLevel(); ! 1431: gameaction = ga_nothing; ! 1432: viewactive = true; ! 1433: } ! 1434: ! 1435: //--------------------------------------------------------------------------- ! 1436: // ! 1437: // PROC G_LoadGame ! 1438: // ! 1439: // Can be called by the startup code or the menu task. ! 1440: // ! 1441: //--------------------------------------------------------------------------- ! 1442: ! 1443: char savename[256]; ! 1444: ! 1445: void G_LoadGame(char *name) ! 1446: { ! 1447: strcpy(savename, name); ! 1448: gameaction = ga_loadgame; ! 1449: } ! 1450: ! 1451: //--------------------------------------------------------------------------- ! 1452: // ! 1453: // PROC G_DoLoadGame ! 1454: // ! 1455: // Called by G_Ticker based on gameaction. ! 1456: // ! 1457: //--------------------------------------------------------------------------- ! 1458: ! 1459: #define VERSIONSIZE 16 ! 1460: ! 1461: void G_DoLoadGame(void) ! 1462: { ! 1463: int length; ! 1464: int i; ! 1465: int a, b, c; ! 1466: char vcheck[VERSIONSIZE]; ! 1467: ! 1468: gameaction = ga_nothing; ! 1469: ! 1470: length = M_ReadFile(savename, &savebuffer); ! 1471: save_p = savebuffer+SAVESTRINGSIZE; ! 1472: // Skip the description field ! 1473: memset(vcheck, 0, sizeof(vcheck)); ! 1474: sprintf(vcheck, "version %i", VERSION); ! 1475: if (strcmp (save_p, vcheck)) ! 1476: { // Bad version ! 1477: return; ! 1478: } ! 1479: save_p += VERSIONSIZE; ! 1480: gameskill = *save_p++; ! 1481: gameepisode = *save_p++; ! 1482: gamemap = *save_p++; ! 1483: for(i = 0; i < MAXPLAYERS; i++) ! 1484: { ! 1485: playeringame[i] = *save_p++; ! 1486: } ! 1487: // Load a base level ! 1488: G_InitNew(gameskill, gameepisode, gamemap); ! 1489: ! 1490: // Create leveltime ! 1491: a = *save_p++; ! 1492: b = *save_p++; ! 1493: c = *save_p++; ! 1494: leveltime = (a<<16)+(b<<8)+c; ! 1495: ! 1496: // De-archive all the modifications ! 1497: P_UnArchivePlayers(); ! 1498: P_UnArchiveWorld(); ! 1499: P_UnArchiveThinkers(); ! 1500: P_UnArchiveSpecials(); ! 1501: ! 1502: if(*save_p != SAVE_GAME_TERMINATOR) ! 1503: { // Missing savegame termination marker ! 1504: I_Error("Bad savegame"); ! 1505: } ! 1506: Z_Free(savebuffer); ! 1507: } ! 1508: ! 1509: ! 1510: /* ! 1511: ==================== ! 1512: = ! 1513: = G_InitNew ! 1514: = ! 1515: = Can be called by the startup code or the menu task ! 1516: = consoleplayer, displayplayer, playeringame[] should be set ! 1517: ==================== ! 1518: */ ! 1519: ! 1520: skill_t d_skill; ! 1521: int d_episode; ! 1522: int d_map; ! 1523: ! 1524: void G_DeferedInitNew (skill_t skill, int episode, int map) ! 1525: { ! 1526: d_skill = skill; ! 1527: d_episode = episode; ! 1528: d_map = map; ! 1529: gameaction = ga_newgame; ! 1530: } ! 1531: ! 1532: void G_DoNewGame (void) ! 1533: { ! 1534: G_InitNew (d_skill, d_episode, d_map); ! 1535: gameaction = ga_nothing; ! 1536: } ! 1537: ! 1538: extern int skytexture; ! 1539: ! 1540: void G_InitNew(skill_t skill, int episode, int map) ! 1541: { ! 1542: int i; ! 1543: int speed; ! 1544: static char *skyLumpNames[5] = ! 1545: { ! 1546: "SKY1", "SKY2", "SKY3", "SKY1", "SKY3" ! 1547: }; ! 1548: ! 1549: if(paused) ! 1550: { ! 1551: paused = false; ! 1552: S_ResumeSound(); ! 1553: } ! 1554: if(skill < sk_baby) ! 1555: skill = sk_baby; ! 1556: if(skill > sk_nightmare) ! 1557: skill = sk_nightmare; ! 1558: if(episode < 1) ! 1559: episode = 1; ! 1560: // Up to 9 episodes for testing ! 1561: if(episode > 9) ! 1562: episode = 9; ! 1563: if(map < 1) ! 1564: map = 1; ! 1565: if(map > 9) ! 1566: map = 9; ! 1567: M_ClearRandom(); ! 1568: if(respawnparm) ! 1569: { ! 1570: respawnmonsters = true; ! 1571: } ! 1572: else ! 1573: { ! 1574: respawnmonsters = false; ! 1575: } ! 1576: // Set monster missile speeds ! 1577: speed = skill == sk_nightmare; ! 1578: for(i = 0; MonsterMissileInfo[i].type != -1; i++) ! 1579: { ! 1580: mobjinfo[MonsterMissileInfo[i].type].speed ! 1581: = MonsterMissileInfo[i].speed[speed]<<FRACBITS; ! 1582: } ! 1583: // Force players to be initialized upon first level load ! 1584: for(i = 0; i < MAXPLAYERS; i++) ! 1585: { ! 1586: players[i].playerstate = PST_REBORN; ! 1587: players[i].didsecret = false; ! 1588: } ! 1589: // Set up a bunch of globals ! 1590: usergame = true; // will be set false if a demo ! 1591: paused = false; ! 1592: demorecording = false; ! 1593: demoplayback = false; ! 1594: viewactive = true; ! 1595: gameepisode = episode; ! 1596: gamemap = map; ! 1597: gameskill = skill; ! 1598: viewactive = true; ! 1599: BorderNeedRefresh = true; ! 1600: ! 1601: // Set the sky map ! 1602: if(episode > 5) ! 1603: { ! 1604: skytexture = R_TextureNumForName("SKY1"); ! 1605: } ! 1606: else ! 1607: { ! 1608: skytexture = R_TextureNumForName(skyLumpNames[episode-1]); ! 1609: } ! 1610: ! 1611: // ! 1612: // give one null ticcmd_t ! 1613: // ! 1614: #if 0 ! 1615: gametic = 0; ! 1616: maketic = 1; ! 1617: for (i=0 ; i<MAXPLAYERS ; i++) ! 1618: nettics[i] = 1; // one null event for this gametic ! 1619: memset (localcmds,0,sizeof(localcmds)); ! 1620: memset (netcmds,0,sizeof(netcmds)); ! 1621: #endif ! 1622: G_DoLoadLevel(); ! 1623: } ! 1624: ! 1625: ! 1626: /* ! 1627: =============================================================================== ! 1628: ! 1629: DEMO RECORDING ! 1630: ! 1631: =============================================================================== ! 1632: */ ! 1633: ! 1634: #define DEMOMARKER 0x80 ! 1635: ! 1636: void G_ReadDemoTiccmd (ticcmd_t *cmd) ! 1637: { ! 1638: if (*demo_p == DEMOMARKER) ! 1639: { // end of demo data stream ! 1640: G_CheckDemoStatus (); ! 1641: return; ! 1642: } ! 1643: cmd->forwardmove = ((signed char)*demo_p++); ! 1644: cmd->sidemove = ((signed char)*demo_p++); ! 1645: cmd->angleturn = ((unsigned char)*demo_p++)<<8; ! 1646: cmd->buttons = (unsigned char)*demo_p++; ! 1647: cmd->lookfly = (unsigned char)*demo_p++; ! 1648: cmd->arti = (unsigned char)*demo_p++; ! 1649: } ! 1650: ! 1651: void G_WriteDemoTiccmd (ticcmd_t *cmd) ! 1652: { ! 1653: if (gamekeydown['q']) // press q to end demo recording ! 1654: G_CheckDemoStatus (); ! 1655: *demo_p++ = cmd->forwardmove; ! 1656: *demo_p++ = cmd->sidemove; ! 1657: *demo_p++ = cmd->angleturn>>8; ! 1658: *demo_p++ = cmd->buttons; ! 1659: *demo_p++ = cmd->lookfly; ! 1660: *demo_p++ = cmd->arti; ! 1661: demo_p -= 6; ! 1662: G_ReadDemoTiccmd (cmd); // make SURE it is exactly the same ! 1663: } ! 1664: ! 1665: ! 1666: ! 1667: /* ! 1668: =================== ! 1669: = ! 1670: = G_RecordDemo ! 1671: = ! 1672: =================== ! 1673: */ ! 1674: ! 1675: void G_RecordDemo (skill_t skill, int numplayers, int episode, int map, char *name) ! 1676: { ! 1677: int i; ! 1678: ! 1679: G_InitNew (skill, episode, map); ! 1680: usergame = false; ! 1681: strcpy (demoname, name); ! 1682: strcat (demoname, ".lmp"); ! 1683: demobuffer = demo_p = Z_Malloc (0x20000,PU_STATIC,NULL); ! 1684: *demo_p++ = skill; ! 1685: *demo_p++ = episode; ! 1686: *demo_p++ = map; ! 1687: ! 1688: for (i=0 ; i<MAXPLAYERS ; i++) ! 1689: *demo_p++ = playeringame[i]; ! 1690: ! 1691: demorecording = true; ! 1692: } ! 1693: ! 1694: ! 1695: /* ! 1696: =================== ! 1697: = ! 1698: = G_PlayDemo ! 1699: = ! 1700: =================== ! 1701: */ ! 1702: ! 1703: char *defdemoname; ! 1704: ! 1705: void G_DeferedPlayDemo (char *name) ! 1706: { ! 1707: defdemoname = name; ! 1708: gameaction = ga_playdemo; ! 1709: } ! 1710: ! 1711: void G_DoPlayDemo (void) ! 1712: { ! 1713: skill_t skill; ! 1714: int i, episode, map; ! 1715: ! 1716: gameaction = ga_nothing; ! 1717: demobuffer = demo_p = W_CacheLumpName (defdemoname, PU_STATIC); ! 1718: skill = *demo_p++; ! 1719: episode = *demo_p++; ! 1720: map = *demo_p++; ! 1721: ! 1722: for (i=0 ; i<MAXPLAYERS ; i++) ! 1723: playeringame[i] = *demo_p++; ! 1724: ! 1725: precache = false; // don't spend a lot of time in loadlevel ! 1726: G_InitNew (skill, episode, map); ! 1727: precache = true; ! 1728: usergame = false; ! 1729: demoplayback = true; ! 1730: } ! 1731: ! 1732: ! 1733: /* ! 1734: =================== ! 1735: = ! 1736: = G_TimeDemo ! 1737: = ! 1738: =================== ! 1739: */ ! 1740: ! 1741: void G_TimeDemo (char *name) ! 1742: { ! 1743: skill_t skill; ! 1744: int episode, map; ! 1745: ! 1746: demobuffer = demo_p = W_CacheLumpName (name, PU_STATIC); ! 1747: skill = *demo_p++; ! 1748: episode = *demo_p++; ! 1749: map = *demo_p++; ! 1750: G_InitNew (skill, episode, map); ! 1751: usergame = false; ! 1752: demoplayback = true; ! 1753: timingdemo = true; ! 1754: singletics = true; ! 1755: } ! 1756: ! 1757: ! 1758: /* ! 1759: =================== ! 1760: = ! 1761: = G_CheckDemoStatus ! 1762: = ! 1763: = Called after a death or level completion to allow demos to be cleaned up ! 1764: = Returns true if a new demo loop action will take place ! 1765: =================== ! 1766: */ ! 1767: ! 1768: boolean G_CheckDemoStatus (void) ! 1769: { ! 1770: int endtime; ! 1771: ! 1772: if (timingdemo) ! 1773: { ! 1774: endtime = I_GetTime (); ! 1775: I_Error ("timed %i gametics in %i realtics",gametic ! 1776: , endtime-starttime); ! 1777: } ! 1778: ! 1779: if (demoplayback) ! 1780: { ! 1781: if (singledemo) ! 1782: I_Quit (); ! 1783: ! 1784: Z_ChangeTag (demobuffer, PU_CACHE); ! 1785: demoplayback = false; ! 1786: D_AdvanceDemo (); ! 1787: return true; ! 1788: } ! 1789: ! 1790: if (demorecording) ! 1791: { ! 1792: *demo_p++ = DEMOMARKER; ! 1793: M_WriteFile (demoname, demobuffer, demo_p - demobuffer); ! 1794: Z_Free (demobuffer); ! 1795: demorecording = false; ! 1796: I_Error ("Demo %s recorded",demoname); ! 1797: } ! 1798: ! 1799: return false; ! 1800: } ! 1801: ! 1802: /**************************************************************************/ ! 1803: /**************************************************************************/ ! 1804: ! 1805: //========================================================================== ! 1806: // ! 1807: // G_SaveGame ! 1808: // ! 1809: // Called by the menu task. <description> is a 24 byte text string. ! 1810: // ! 1811: //========================================================================== ! 1812: ! 1813: void G_SaveGame(int slot, char *description) ! 1814: { ! 1815: savegameslot = slot; ! 1816: strcpy(savedescription, description); ! 1817: sendsave = true; ! 1818: } ! 1819: ! 1820: //========================================================================== ! 1821: // ! 1822: // G_DoSaveGame ! 1823: // ! 1824: // Called by G_Ticker based on gameaction. ! 1825: // ! 1826: //========================================================================== ! 1827: ! 1828: void G_DoSaveGame(void) ! 1829: { ! 1830: int i; ! 1831: char name[100]; ! 1832: char verString[VERSIONSIZE]; ! 1833: char *description; ! 1834: ! 1835: if(cdrom) ! 1836: { ! 1837: sprintf(name, SAVEGAMENAMECD"%d.hsg", savegameslot); ! 1838: } ! 1839: else ! 1840: { ! 1841: sprintf(name, SAVEGAMENAME"%d.hsg", savegameslot); ! 1842: } ! 1843: description = savedescription; ! 1844: ! 1845: SV_Open(name); ! 1846: SV_Write(description, SAVESTRINGSIZE); ! 1847: memset(verString, 0, sizeof(verString)); ! 1848: sprintf(verString, "version %i", VERSION); ! 1849: SV_Write(verString, VERSIONSIZE); ! 1850: SV_WriteByte(gameskill); ! 1851: SV_WriteByte(gameepisode); ! 1852: SV_WriteByte(gamemap); ! 1853: for(i = 0; i < MAXPLAYERS; i++) ! 1854: { ! 1855: SV_WriteByte(playeringame[i]); ! 1856: } ! 1857: SV_WriteByte(leveltime>>16); ! 1858: SV_WriteByte(leveltime>>8); ! 1859: SV_WriteByte(leveltime); ! 1860: P_ArchivePlayers(); ! 1861: P_ArchiveWorld(); ! 1862: P_ArchiveThinkers(); ! 1863: P_ArchiveSpecials(); ! 1864: SV_Close(name); ! 1865: ! 1866: gameaction = ga_nothing; ! 1867: savedescription[0] = 0; ! 1868: P_SetMessage(&players[consoleplayer], TXT_GAMESAVED, true); ! 1869: } ! 1870: ! 1871: //========================================================================== ! 1872: // ! 1873: // SV_Open ! 1874: // ! 1875: //========================================================================== ! 1876: ! 1877: void SV_Open(char *fileName) ! 1878: { ! 1879: MallocFailureOk = true; ! 1880: save_p = savebuffer = Z_Malloc(SAVEGAMESIZE, PU_STATIC, NULL); ! 1881: MallocFailureOk = false; ! 1882: if(savebuffer == NULL) ! 1883: { // Not enough memory - use file save method ! 1884: SaveGameType = SVG_FILE; ! 1885: SaveGameFP = fopen(fileName, "wb"); ! 1886: } ! 1887: else ! 1888: { ! 1889: SaveGameType = SVG_RAM; ! 1890: } ! 1891: } ! 1892: ! 1893: //========================================================================== ! 1894: // ! 1895: // SV_Close ! 1896: // ! 1897: //========================================================================== ! 1898: ! 1899: void SV_Close(char *fileName) ! 1900: { ! 1901: int length; ! 1902: ! 1903: SV_WriteByte(SAVE_GAME_TERMINATOR); ! 1904: if(SaveGameType == SVG_RAM) ! 1905: { ! 1906: length = save_p-savebuffer; ! 1907: if(length > SAVEGAMESIZE) ! 1908: { ! 1909: I_Error("Savegame buffer overrun"); ! 1910: } ! 1911: M_WriteFile(fileName, savebuffer, length); ! 1912: Z_Free(savebuffer); ! 1913: } ! 1914: else ! 1915: { // SVG_FILE ! 1916: fclose(SaveGameFP); ! 1917: } ! 1918: } ! 1919: ! 1920: //========================================================================== ! 1921: // ! 1922: // SV_Write ! 1923: // ! 1924: //========================================================================== ! 1925: ! 1926: void SV_Write(void *buffer, int size) ! 1927: { ! 1928: if(SaveGameType == SVG_RAM) ! 1929: { ! 1930: memcpy(save_p, buffer, size); ! 1931: save_p += size; ! 1932: } ! 1933: else ! 1934: { // SVG_FILE ! 1935: fwrite(buffer, size, 1, SaveGameFP); ! 1936: } ! 1937: } ! 1938: ! 1939: void SV_WriteByte(byte val) ! 1940: { ! 1941: SV_Write(&val, sizeof(byte)); ! 1942: } ! 1943: ! 1944: void SV_WriteWord(unsigned short val) ! 1945: { ! 1946: SV_Write(&val, sizeof(unsigned short)); ! 1947: } ! 1948: ! 1949: void SV_WriteLong(unsigned int val) ! 1950: { ! 1951: SV_Write(&val, sizeof(int)); ! 1952: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.