WL_PLAY.C (24378B)
1 // WL_PLAY.C 2 3 #include "WL_DEF.H" 4 #pragma hdrstop 5 6 7 /* 8 ============================================================================= 9 10 LOCAL CONSTANTS 11 12 ============================================================================= 13 */ 14 15 #define sc_Question 0x35 16 17 /* 18 ============================================================================= 19 20 GLOBAL VARIABLES 21 22 ============================================================================= 23 */ 24 25 boolean madenoise; // true when shooting or screaming 26 27 exit_t playstate; 28 29 int DebugOk; 30 31 objtype objlist[MAXACTORS],*new,*obj,*player,*lastobj, 32 *objfreelist,*killerobj; 33 34 unsigned farmapylookup[MAPSIZE]; 35 byte *nearmapylookup[MAPSIZE]; 36 37 boolean singlestep,godmode,noclip; 38 int extravbls; 39 40 byte tilemap[MAPSIZE][MAPSIZE]; // wall values only 41 byte spotvis[MAPSIZE][MAPSIZE]; 42 objtype *actorat[MAPSIZE][MAPSIZE]; 43 44 // 45 // replacing refresh manager 46 // 47 unsigned mapwidth,mapheight,tics; 48 boolean compatability; 49 byte *updateptr; 50 unsigned mapwidthtable[64]; 51 unsigned uwidthtable[UPDATEHIGH]; 52 unsigned blockstarts[UPDATEWIDE*UPDATEHIGH]; 53 byte update[UPDATESIZE]; 54 55 // 56 // control info 57 // 58 boolean mouseenabled,joystickenabled,joypadenabled,joystickprogressive; 59 int joystickport; 60 int dirscan[4] = {sc_UpArrow,sc_RightArrow,sc_DownArrow,sc_LeftArrow}; 61 int buttonscan[NUMBUTTONS] = 62 {sc_Control,sc_Alt,sc_RShift,sc_Space,sc_1,sc_2,sc_3,sc_4}; 63 int buttonmouse[4]={bt_attack,bt_strafe,bt_use,bt_nobutton}; 64 int buttonjoy[4]={bt_attack,bt_strafe,bt_use,bt_run}; 65 66 int viewsize; 67 68 boolean buttonheld[NUMBUTTONS]; 69 70 boolean demorecord,demoplayback; 71 char far *demoptr, far *lastdemoptr; 72 memptr demobuffer; 73 74 // 75 // curent user input 76 // 77 int controlx,controly; // range from -100 to 100 per tic 78 boolean buttonstate[NUMBUTTONS]; 79 80 81 82 //=========================================================================== 83 84 85 void CenterWindow(word w,word h); 86 void InitObjList (void); 87 void RemoveObj (objtype *gone); 88 void PollControls (void); 89 void StopMusic(void); 90 void StartMusic(void); 91 void PlayLoop (void); 92 93 /* 94 ============================================================================= 95 96 LOCAL VARIABLES 97 98 ============================================================================= 99 */ 100 101 102 objtype dummyobj; 103 104 // 105 // LIST OF SONGS FOR EACH VERSION 106 // 107 int songs[]= 108 { 109 #ifndef SPEAR 110 // 111 // Episode One 112 // 113 GETTHEM_MUS, 114 SEARCHN_MUS, 115 POW_MUS, 116 SUSPENSE_MUS, 117 GETTHEM_MUS, 118 SEARCHN_MUS, 119 POW_MUS, 120 SUSPENSE_MUS, 121 122 WARMARCH_MUS, // Boss level 123 CORNER_MUS, // Secret level 124 125 // 126 // Episode Two 127 // 128 NAZI_OMI_MUS, 129 PREGNANT_MUS, 130 GOINGAFT_MUS, 131 HEADACHE_MUS, 132 NAZI_OMI_MUS, 133 PREGNANT_MUS, 134 HEADACHE_MUS, 135 GOINGAFT_MUS, 136 137 WARMARCH_MUS, // Boss level 138 DUNGEON_MUS, // Secret level 139 140 // 141 // Episode Three 142 // 143 INTROCW3_MUS, 144 NAZI_RAP_MUS, 145 TWELFTH_MUS, 146 ZEROHOUR_MUS, 147 INTROCW3_MUS, 148 NAZI_RAP_MUS, 149 TWELFTH_MUS, 150 ZEROHOUR_MUS, 151 152 ULTIMATE_MUS, // Boss level 153 PACMAN_MUS, // Secret level 154 155 // 156 // Episode Four 157 // 158 GETTHEM_MUS, 159 SEARCHN_MUS, 160 POW_MUS, 161 SUSPENSE_MUS, 162 GETTHEM_MUS, 163 SEARCHN_MUS, 164 POW_MUS, 165 SUSPENSE_MUS, 166 167 WARMARCH_MUS, // Boss level 168 CORNER_MUS, // Secret level 169 170 // 171 // Episode Five 172 // 173 NAZI_OMI_MUS, 174 PREGNANT_MUS, 175 GOINGAFT_MUS, 176 HEADACHE_MUS, 177 NAZI_OMI_MUS, 178 PREGNANT_MUS, 179 HEADACHE_MUS, 180 GOINGAFT_MUS, 181 182 WARMARCH_MUS, // Boss level 183 DUNGEON_MUS, // Secret level 184 185 // 186 // Episode Six 187 // 188 INTROCW3_MUS, 189 NAZI_RAP_MUS, 190 TWELFTH_MUS, 191 ZEROHOUR_MUS, 192 INTROCW3_MUS, 193 NAZI_RAP_MUS, 194 TWELFTH_MUS, 195 ZEROHOUR_MUS, 196 197 ULTIMATE_MUS, // Boss level 198 FUNKYOU_MUS // Secret level 199 #else 200 201 ////////////////////////////////////////////////////////////// 202 // 203 // SPEAR OF DESTINY TRACKS 204 // 205 ////////////////////////////////////////////////////////////// 206 XTIPTOE_MUS, 207 XFUNKIE_MUS, 208 XDEATH_MUS, 209 XGETYOU_MUS, // DON'T KNOW 210 ULTIMATE_MUS, // Trans Gr”sse 211 212 DUNGEON_MUS, 213 GOINGAFT_MUS, 214 POW_MUS, 215 TWELFTH_MUS, 216 ULTIMATE_MUS, // Barnacle Wilhelm BOSS 217 218 NAZI_OMI_MUS, 219 GETTHEM_MUS, 220 SUSPENSE_MUS, 221 SEARCHN_MUS, 222 ZEROHOUR_MUS, 223 ULTIMATE_MUS, // Super Mutant BOSS 224 225 XPUTIT_MUS, 226 ULTIMATE_MUS, // Death Knight BOSS 227 228 XJAZNAZI_MUS, // Secret level 229 XFUNKIE_MUS, // Secret level (DON'T KNOW) 230 231 XEVIL_MUS // Angel of Death BOSS 232 233 #endif 234 }; 235 236 237 /* 238 ============================================================================= 239 240 USER CONTROL 241 242 ============================================================================= 243 */ 244 245 246 #define BASEMOVE 35 247 #define RUNMOVE 70 248 #define BASETURN 35 249 #define RUNTURN 70 250 251 #define JOYSCALE 2 252 253 /* 254 =================== 255 = 256 = PollKeyboardButtons 257 = 258 =================== 259 */ 260 261 void PollKeyboardButtons (void) 262 { 263 int i; 264 265 for (i=0;i<NUMBUTTONS;i++) 266 if (Keyboard[buttonscan[i]]) 267 buttonstate[i] = true; 268 } 269 270 271 /* 272 =================== 273 = 274 = PollMouseButtons 275 = 276 =================== 277 */ 278 279 void PollMouseButtons (void) 280 { 281 int buttons; 282 283 buttons = IN_MouseButtons (); 284 285 if (buttons&1) 286 buttonstate[buttonmouse[0]] = true; 287 if (buttons&2) 288 buttonstate[buttonmouse[1]] = true; 289 if (buttons&4) 290 buttonstate[buttonmouse[2]] = true; 291 } 292 293 294 295 /* 296 =================== 297 = 298 = PollJoystickButtons 299 = 300 =================== 301 */ 302 303 void PollJoystickButtons (void) 304 { 305 int buttons; 306 307 buttons = IN_JoyButtons (); 308 309 if (joystickport && !joypadenabled) 310 { 311 if (buttons&4) 312 buttonstate[buttonjoy[0]] = true; 313 if (buttons&8) 314 buttonstate[buttonjoy[1]] = true; 315 } 316 else 317 { 318 if (buttons&1) 319 buttonstate[buttonjoy[0]] = true; 320 if (buttons&2) 321 buttonstate[buttonjoy[1]] = true; 322 if (joypadenabled) 323 { 324 if (buttons&4) 325 buttonstate[buttonjoy[2]] = true; 326 if (buttons&8) 327 buttonstate[buttonjoy[3]] = true; 328 } 329 } 330 } 331 332 333 /* 334 =================== 335 = 336 = PollKeyboardMove 337 = 338 =================== 339 */ 340 341 void PollKeyboardMove (void) 342 { 343 if (buttonstate[bt_run]) 344 { 345 if (Keyboard[dirscan[di_north]]) 346 controly -= RUNMOVE*tics; 347 if (Keyboard[dirscan[di_south]]) 348 controly += RUNMOVE*tics; 349 if (Keyboard[dirscan[di_west]]) 350 controlx -= RUNMOVE*tics; 351 if (Keyboard[dirscan[di_east]]) 352 controlx += RUNMOVE*tics; 353 } 354 else 355 { 356 if (Keyboard[dirscan[di_north]]) 357 controly -= BASEMOVE*tics; 358 if (Keyboard[dirscan[di_south]]) 359 controly += BASEMOVE*tics; 360 if (Keyboard[dirscan[di_west]]) 361 controlx -= BASEMOVE*tics; 362 if (Keyboard[dirscan[di_east]]) 363 controlx += BASEMOVE*tics; 364 } 365 } 366 367 368 /* 369 =================== 370 = 371 = PollMouseMove 372 = 373 =================== 374 */ 375 376 void PollMouseMove (void) 377 { 378 int mousexmove,mouseymove; 379 380 Mouse(MDelta); 381 mousexmove = _CX; 382 mouseymove = _DX; 383 384 controlx += mousexmove*10/(13-mouseadjustment); 385 controly += mouseymove*20/(13-mouseadjustment); 386 } 387 388 389 390 /* 391 =================== 392 = 393 = PollJoystickMove 394 = 395 =================== 396 */ 397 398 void PollJoystickMove (void) 399 { 400 int joyx,joyy; 401 402 INL_GetJoyDelta(joystickport,&joyx,&joyy); 403 404 if (joystickprogressive) 405 { 406 if (joyx > 64) 407 controlx += (joyx-64)*JOYSCALE*tics; 408 else if (joyx < -64) 409 controlx -= (-joyx-64)*JOYSCALE*tics; 410 if (joyy > 64) 411 controlx += (joyy-64)*JOYSCALE*tics; 412 else if (joyy < -64) 413 controly -= (-joyy-64)*JOYSCALE*tics; 414 } 415 else if (buttonstate[bt_run]) 416 { 417 if (joyx > 64) 418 controlx += RUNMOVE*tics; 419 else if (joyx < -64) 420 controlx -= RUNMOVE*tics; 421 if (joyy > 64) 422 controly += RUNMOVE*tics; 423 else if (joyy < -64) 424 controly -= RUNMOVE*tics; 425 } 426 else 427 { 428 if (joyx > 64) 429 controlx += BASEMOVE*tics; 430 else if (joyx < -64) 431 controlx -= BASEMOVE*tics; 432 if (joyy > 64) 433 controly += BASEMOVE*tics; 434 else if (joyy < -64) 435 controly -= BASEMOVE*tics; 436 } 437 } 438 439 440 /* 441 =================== 442 = 443 = PollControls 444 = 445 = Gets user or demo input, call once each frame 446 = 447 = controlx set between -100 and 100 per tic 448 = controly 449 = buttonheld[] the state of the buttons LAST frame 450 = buttonstate[] the state of the buttons THIS frame 451 = 452 =================== 453 */ 454 455 void PollControls (void) 456 { 457 int max,min,i; 458 byte buttonbits; 459 460 // 461 // get timing info for last frame 462 // 463 if (demoplayback) 464 { 465 while (TimeCount<lasttimecount+DEMOTICS) 466 ; 467 TimeCount = lasttimecount + DEMOTICS; 468 lasttimecount += DEMOTICS; 469 tics = DEMOTICS; 470 } 471 else if (demorecord) // demo recording and playback needs 472 { // to be constant 473 // 474 // take DEMOTICS or more tics, and modify Timecount to reflect time taken 475 // 476 while (TimeCount<lasttimecount+DEMOTICS) 477 ; 478 TimeCount = lasttimecount + DEMOTICS; 479 lasttimecount += DEMOTICS; 480 tics = DEMOTICS; 481 } 482 else 483 CalcTics (); 484 485 controlx = 0; 486 controly = 0; 487 memcpy (buttonheld,buttonstate,sizeof(buttonstate)); 488 memset (buttonstate,0,sizeof(buttonstate)); 489 490 if (demoplayback) 491 { 492 // 493 // read commands from demo buffer 494 // 495 buttonbits = *demoptr++; 496 for (i=0;i<NUMBUTTONS;i++) 497 { 498 buttonstate[i] = buttonbits&1; 499 buttonbits >>= 1; 500 } 501 502 controlx = *demoptr++; 503 controly = *demoptr++; 504 505 if (demoptr == lastdemoptr) 506 playstate = ex_completed; // demo is done 507 508 controlx *= (int)tics; 509 controly *= (int)tics; 510 511 return; 512 } 513 514 515 // 516 // get button states 517 // 518 PollKeyboardButtons (); 519 520 if (mouseenabled) 521 PollMouseButtons (); 522 523 if (joystickenabled) 524 PollJoystickButtons (); 525 526 // 527 // get movements 528 // 529 PollKeyboardMove (); 530 531 if (mouseenabled) 532 PollMouseMove (); 533 534 if (joystickenabled) 535 PollJoystickMove (); 536 537 // 538 // bound movement to a maximum 539 // 540 max = 100*tics; 541 min = -max; 542 if (controlx > max) 543 controlx = max; 544 else if (controlx < min) 545 controlx = min; 546 547 if (controly > max) 548 controly = max; 549 else if (controly < min) 550 controly = min; 551 552 if (demorecord) 553 { 554 // 555 // save info out to demo buffer 556 // 557 controlx /= (int)tics; 558 controly /= (int)tics; 559 560 buttonbits = 0; 561 562 for (i=NUMBUTTONS-1;i>=0;i--) 563 { 564 buttonbits <<= 1; 565 if (buttonstate[i]) 566 buttonbits |= 1; 567 } 568 569 *demoptr++ = buttonbits; 570 *demoptr++ = controlx; 571 *demoptr++ = controly; 572 573 if (demoptr >= lastdemoptr) 574 Quit ("Demo buffer overflowed!"); 575 576 controlx *= (int)tics; 577 controly *= (int)tics; 578 } 579 } 580 581 582 583 //========================================================================== 584 585 586 587 /////////////////////////////////////////////////////////////////////////// 588 // 589 // CenterWindow() - Generates a window of a given width & height in the 590 // middle of the screen 591 // 592 /////////////////////////////////////////////////////////////////////////// 593 594 #define MAXX 320 595 #define MAXY 160 596 597 void CenterWindow(word w,word h) 598 { 599 FixOfs (); 600 US_DrawWindow(((MAXX / 8) - w) / 2,((MAXY / 8) - h) / 2,w,h); 601 } 602 603 //=========================================================================== 604 605 606 /* 607 ===================== 608 = 609 = CheckKeys 610 = 611 ===================== 612 */ 613 614 void CheckKeys (void) 615 { 616 int i; 617 byte scan; 618 unsigned temp; 619 620 621 if (screenfaded || demoplayback) // don't do anything with a faded screen 622 return; 623 624 scan = LastScan; 625 626 627 #ifdef SPEAR 628 // 629 // SECRET CHEAT CODE: TAB-G-F10 630 // 631 if (Keyboard[sc_Tab] && 632 Keyboard[sc_G] && 633 Keyboard[sc_F10]) 634 { 635 WindowH = 160; 636 if (godmode) 637 { 638 Message ("God mode OFF"); 639 SD_PlaySound (NOBONUSSND); 640 } 641 else 642 { 643 Message ("God mode ON"); 644 SD_PlaySound (ENDBONUS2SND); 645 } 646 647 IN_Ack(); 648 godmode ^= 1; 649 DrawAllPlayBorderSides (); 650 IN_ClearKeysDown(); 651 return; 652 } 653 #endif 654 655 656 // 657 // SECRET CHEAT CODE: 'MLI' 658 // 659 if (Keyboard[sc_M] && 660 Keyboard[sc_L] && 661 Keyboard[sc_I]) 662 { 663 gamestate.health = 100; 664 gamestate.ammo = 99; 665 gamestate.keys = 3; 666 gamestate.score = 0; 667 gamestate.TimeCount += 42000L; 668 GiveWeapon (wp_chaingun); 669 670 DrawWeapon(); 671 DrawHealth(); 672 DrawKeys(); 673 DrawAmmo(); 674 DrawScore(); 675 676 ClearMemory (); 677 CA_CacheGrChunk (STARTFONT+1); 678 ClearSplitVWB (); 679 VW_ScreenToScreen (displayofs,bufferofs,80,160); 680 681 Message(STR_CHEATER1"\n" 682 STR_CHEATER2"\n\n" 683 STR_CHEATER3"\n" 684 STR_CHEATER4"\n" 685 STR_CHEATER5); 686 687 UNCACHEGRCHUNK(STARTFONT+1); 688 PM_CheckMainMem (); 689 IN_ClearKeysDown(); 690 IN_Ack(); 691 692 DrawAllPlayBorder (); 693 } 694 695 // 696 // OPEN UP DEBUG KEYS 697 // 698 #ifndef SPEAR 699 if (Keyboard[sc_BackSpace] && 700 Keyboard[sc_LShift] && 701 Keyboard[sc_Alt] && 702 MS_CheckParm("goobers")) 703 #else 704 if (Keyboard[sc_BackSpace] && 705 Keyboard[sc_LShift] && 706 Keyboard[sc_Alt] && 707 MS_CheckParm("debugmode")) 708 #endif 709 { 710 ClearMemory (); 711 CA_CacheGrChunk (STARTFONT+1); 712 ClearSplitVWB (); 713 VW_ScreenToScreen (displayofs,bufferofs,80,160); 714 715 Message("Debugging keys are\nnow available!"); 716 UNCACHEGRCHUNK(STARTFONT+1); 717 PM_CheckMainMem (); 718 IN_ClearKeysDown(); 719 IN_Ack(); 720 721 DrawAllPlayBorderSides (); 722 DebugOk=1; 723 } 724 725 // 726 // TRYING THE KEEN CHEAT CODE! 727 // 728 if (Keyboard[sc_B] && 729 Keyboard[sc_A] && 730 Keyboard[sc_T]) 731 { 732 ClearMemory (); 733 CA_CacheGrChunk (STARTFONT+1); 734 ClearSplitVWB (); 735 VW_ScreenToScreen (displayofs,bufferofs,80,160); 736 737 Message("Commander Keen is also\n" 738 "available from Apogee, but\n" 739 "then, you already know\n" 740 "that - right, Cheatmeister?!"); 741 742 UNCACHEGRCHUNK(STARTFONT+1); 743 PM_CheckMainMem (); 744 IN_ClearKeysDown(); 745 IN_Ack(); 746 747 DrawAllPlayBorder (); 748 } 749 750 // 751 // pause key weirdness can't be checked as a scan code 752 // 753 if (Paused) 754 { 755 bufferofs = displayofs; 756 LatchDrawPic (20-4,80-2*8,PAUSEDPIC); 757 SD_MusicOff(); 758 IN_Ack(); 759 IN_ClearKeysDown (); 760 SD_MusicOn(); 761 Paused = false; 762 if (MousePresent) 763 Mouse(MDelta); // Clear accumulated mouse movement 764 return; 765 } 766 767 768 // 769 // F1-F7/ESC to enter control panel 770 // 771 if ( 772 #ifndef DEBCHECK 773 scan == sc_F10 || 774 #endif 775 scan == sc_F9 || 776 scan == sc_F7 || 777 scan == sc_F8) // pop up quit dialog 778 { 779 ClearMemory (); 780 ClearSplitVWB (); 781 VW_ScreenToScreen (displayofs,bufferofs,80,160); 782 US_ControlPanel(scan); 783 784 DrawAllPlayBorderSides (); 785 786 if (scan == sc_F9) 787 StartMusic (); 788 789 PM_CheckMainMem (); 790 SETFONTCOLOR(0,15); 791 IN_ClearKeysDown(); 792 return; 793 } 794 795 if ( (scan >= sc_F1 && scan <= sc_F9) || scan == sc_Escape) 796 { 797 StopMusic (); 798 ClearMemory (); 799 VW_FadeOut (); 800 801 US_ControlPanel(scan); 802 803 SETFONTCOLOR(0,15); 804 IN_ClearKeysDown(); 805 DrawPlayScreen (); 806 if (!startgame && !loadedgame) 807 { 808 VW_FadeIn (); 809 StartMusic (); 810 } 811 if (loadedgame) 812 playstate = ex_abort; 813 lasttimecount = TimeCount; 814 if (MousePresent) 815 Mouse(MDelta); // Clear accumulated mouse movement 816 PM_CheckMainMem (); 817 return; 818 } 819 820 // 821 // TAB-? debug keys 822 // 823 if (Keyboard[sc_Tab] && DebugOk) 824 { 825 CA_CacheGrChunk (STARTFONT); 826 fontnumber=0; 827 SETFONTCOLOR(0,15); 828 DebugKeys(); 829 if (MousePresent) 830 Mouse(MDelta); // Clear accumulated mouse movement 831 lasttimecount = TimeCount; 832 return; 833 } 834 835 } 836 837 838 //=========================================================================== 839 840 /* 841 ############################################################################# 842 843 The objlist data structure 844 845 ############################################################################# 846 847 objlist containt structures for every actor currently playing. The structure 848 is accessed as a linked list starting at *player, ending when ob->next == 849 NULL. GetNewObj inserts a new object at the end of the list, meaning that 850 if an actor spawn another actor, the new one WILL get to think and react the 851 same frame. RemoveObj unlinks the given object and returns it to the free 852 list, but does not damage the objects ->next pointer, so if the current object 853 removes itself, a linked list following loop can still safely get to the 854 next element. 855 856 <backwardly linked free list> 857 858 ############################################################################# 859 */ 860 861 862 /* 863 ========================= 864 = 865 = InitActorList 866 = 867 = Call to clear out the actor object lists returning them all to the free 868 = list. Allocates a special spot for the player. 869 = 870 ========================= 871 */ 872 873 int objcount; 874 875 void InitActorList (void) 876 { 877 int i; 878 879 // 880 // init the actor lists 881 // 882 for (i=0;i<MAXACTORS;i++) 883 { 884 objlist[i].prev = &objlist[i+1]; 885 objlist[i].next = NULL; 886 } 887 888 objlist[MAXACTORS-1].prev = NULL; 889 890 objfreelist = &objlist[0]; 891 lastobj = NULL; 892 893 objcount = 0; 894 895 // 896 // give the player the first free spots 897 // 898 GetNewActor (); 899 player = new; 900 901 } 902 903 //=========================================================================== 904 905 /* 906 ========================= 907 = 908 = GetNewActor 909 = 910 = Sets the global variable new to point to a free spot in objlist. 911 = The free spot is inserted at the end of the liked list 912 = 913 = When the object list is full, the caller can either have it bomb out ot 914 = return a dummy object pointer that will never get used 915 = 916 ========================= 917 */ 918 919 void GetNewActor (void) 920 { 921 if (!objfreelist) 922 Quit ("GetNewActor: No free spots in objlist!"); 923 924 new = objfreelist; 925 objfreelist = new->prev; 926 memset (new,0,sizeof(*new)); 927 928 if (lastobj) 929 lastobj->next = new; 930 new->prev = lastobj; // new->next is allready NULL from memset 931 932 new->active = false; 933 lastobj = new; 934 935 objcount++; 936 } 937 938 //=========================================================================== 939 940 /* 941 ========================= 942 = 943 = RemoveObj 944 = 945 = Add the given object back into the free list, and unlink it from it's 946 = neighbors 947 = 948 ========================= 949 */ 950 951 void RemoveObj (objtype *gone) 952 { 953 objtype **spotat; 954 955 if (gone == player) 956 Quit ("RemoveObj: Tried to remove the player!"); 957 958 gone->state = NULL; 959 960 // 961 // fix the next object's back link 962 // 963 if (gone == lastobj) 964 lastobj = (objtype *)gone->prev; 965 else 966 gone->next->prev = gone->prev; 967 968 // 969 // fix the previous object's forward link 970 // 971 gone->prev->next = gone->next; 972 973 // 974 // add it back in to the free list 975 // 976 gone->prev = objfreelist; 977 objfreelist = gone; 978 979 objcount--; 980 } 981 982 /* 983 ============================================================================= 984 985 MUSIC STUFF 986 987 ============================================================================= 988 */ 989 990 991 /* 992 ================= 993 = 994 = StopMusic 995 = 996 ================= 997 */ 998 999 void StopMusic(void) 1000 { 1001 int i; 1002 1003 SD_MusicOff(); 1004 for (i = 0;i < LASTMUSIC;i++) 1005 if (audiosegs[STARTMUSIC + i]) 1006 { 1007 MM_SetPurge(&((memptr)audiosegs[STARTMUSIC + i]),3); 1008 MM_SetLock(&((memptr)audiosegs[STARTMUSIC + i]),false); 1009 } 1010 } 1011 1012 //========================================================================== 1013 1014 1015 /* 1016 ================= 1017 = 1018 = StartMusic 1019 = 1020 ================= 1021 */ 1022 1023 void StartMusic(void) 1024 { 1025 musicnames chunk; 1026 1027 SD_MusicOff(); 1028 chunk = songs[gamestate.mapon+gamestate.episode*10]; 1029 1030 // if ((chunk == -1) || (MusicMode != smm_AdLib)) 1031 //DEBUG control panel return; 1032 1033 MM_BombOnError (false); 1034 CA_CacheAudioChunk(STARTMUSIC + chunk); 1035 MM_BombOnError (true); 1036 if (mmerror) 1037 mmerror = false; 1038 else 1039 { 1040 MM_SetLock(&((memptr)audiosegs[STARTMUSIC + chunk]),true); 1041 SD_StartMusic((MusicGroup far *)audiosegs[STARTMUSIC + chunk]); 1042 } 1043 } 1044 1045 1046 /* 1047 ============================================================================= 1048 1049 PALETTE SHIFTING STUFF 1050 1051 ============================================================================= 1052 */ 1053 1054 #define NUMREDSHIFTS 6 1055 #define REDSTEPS 8 1056 1057 #define NUMWHITESHIFTS 3 1058 #define WHITESTEPS 20 1059 #define WHITETICS 6 1060 1061 1062 byte far redshifts[NUMREDSHIFTS][768]; 1063 byte far whiteshifts[NUMREDSHIFTS][768]; 1064 1065 int damagecount,bonuscount; 1066 boolean palshifted; 1067 1068 extern byte far gamepal; 1069 1070 /* 1071 ===================== 1072 = 1073 = InitRedShifts 1074 = 1075 ===================== 1076 */ 1077 1078 void InitRedShifts (void) 1079 { 1080 byte far *workptr, far *baseptr; 1081 int i,j,delta; 1082 1083 1084 // 1085 // fade through intermediate frames 1086 // 1087 for (i=1;i<=NUMREDSHIFTS;i++) 1088 { 1089 workptr = (byte far *)&redshifts[i-1][0]; 1090 baseptr = &gamepal; 1091 1092 for (j=0;j<=255;j++) 1093 { 1094 delta = 64-*baseptr; 1095 *workptr++ = *baseptr++ + delta * i / REDSTEPS; 1096 delta = -*baseptr; 1097 *workptr++ = *baseptr++ + delta * i / REDSTEPS; 1098 delta = -*baseptr; 1099 *workptr++ = *baseptr++ + delta * i / REDSTEPS; 1100 } 1101 } 1102 1103 for (i=1;i<=NUMWHITESHIFTS;i++) 1104 { 1105 workptr = (byte far *)&whiteshifts[i-1][0]; 1106 baseptr = &gamepal; 1107 1108 for (j=0;j<=255;j++) 1109 { 1110 delta = 64-*baseptr; 1111 *workptr++ = *baseptr++ + delta * i / WHITESTEPS; 1112 delta = 62-*baseptr; 1113 *workptr++ = *baseptr++ + delta * i / WHITESTEPS; 1114 delta = 0-*baseptr; 1115 *workptr++ = *baseptr++ + delta * i / WHITESTEPS; 1116 } 1117 } 1118 } 1119 1120 1121 /* 1122 ===================== 1123 = 1124 = ClearPaletteShifts 1125 = 1126 ===================== 1127 */ 1128 1129 void ClearPaletteShifts (void) 1130 { 1131 bonuscount = damagecount = 0; 1132 } 1133 1134 1135 /* 1136 ===================== 1137 = 1138 = StartBonusFlash 1139 = 1140 ===================== 1141 */ 1142 1143 void StartBonusFlash (void) 1144 { 1145 bonuscount = NUMWHITESHIFTS*WHITETICS; // white shift palette 1146 } 1147 1148 1149 /* 1150 ===================== 1151 = 1152 = StartDamageFlash 1153 = 1154 ===================== 1155 */ 1156 1157 void StartDamageFlash (int damage) 1158 { 1159 damagecount += damage; 1160 } 1161 1162 1163 /* 1164 ===================== 1165 = 1166 = UpdatePaletteShifts 1167 = 1168 ===================== 1169 */ 1170 1171 void UpdatePaletteShifts (void) 1172 { 1173 int red,white; 1174 1175 if (bonuscount) 1176 { 1177 white = bonuscount/WHITETICS +1; 1178 if (white>NUMWHITESHIFTS) 1179 white = NUMWHITESHIFTS; 1180 bonuscount -= tics; 1181 if (bonuscount < 0) 1182 bonuscount = 0; 1183 } 1184 else 1185 white = 0; 1186 1187 1188 if (damagecount) 1189 { 1190 red = damagecount/10 +1; 1191 if (red>NUMREDSHIFTS) 1192 red = NUMREDSHIFTS; 1193 1194 damagecount -= tics; 1195 if (damagecount < 0) 1196 damagecount = 0; 1197 } 1198 else 1199 red = 0; 1200 1201 if (red) 1202 { 1203 VW_WaitVBL(1); 1204 VL_SetPalette (redshifts[red-1]); 1205 palshifted = true; 1206 } 1207 else if (white) 1208 { 1209 VW_WaitVBL(1); 1210 VL_SetPalette (whiteshifts[white-1]); 1211 palshifted = true; 1212 } 1213 else if (palshifted) 1214 { 1215 VW_WaitVBL(1); 1216 VL_SetPalette (&gamepal); // back to normal 1217 palshifted = false; 1218 } 1219 } 1220 1221 1222 /* 1223 ===================== 1224 = 1225 = FinishPaletteShifts 1226 = 1227 = Resets palette to normal if needed 1228 = 1229 ===================== 1230 */ 1231 1232 void FinishPaletteShifts (void) 1233 { 1234 if (palshifted) 1235 { 1236 palshifted = 0; 1237 VW_WaitVBL(1); 1238 VL_SetPalette (&gamepal); 1239 } 1240 } 1241 1242 1243 /* 1244 ============================================================================= 1245 1246 CORE PLAYLOOP 1247 1248 ============================================================================= 1249 */ 1250 1251 1252 /* 1253 ===================== 1254 = 1255 = DoActor 1256 = 1257 ===================== 1258 */ 1259 1260 void DoActor (objtype *ob) 1261 { 1262 void (*think)(objtype *); 1263 1264 if (!ob->active && !areabyplayer[ob->areanumber]) 1265 return; 1266 1267 if (!(ob->flags&(FL_NONMARK|FL_NEVERMARK)) ) 1268 actorat[ob->tilex][ob->tiley] = NULL; 1269 1270 // 1271 // non transitional object 1272 // 1273 1274 if (!ob->ticcount) 1275 { 1276 think = ob->state->think; 1277 if (think) 1278 { 1279 think (ob); 1280 if (!ob->state) 1281 { 1282 RemoveObj (ob); 1283 return; 1284 } 1285 } 1286 1287 if (ob->flags&FL_NEVERMARK) 1288 return; 1289 1290 if ( (ob->flags&FL_NONMARK) && actorat[ob->tilex][ob->tiley]) 1291 return; 1292 1293 actorat[ob->tilex][ob->tiley] = ob; 1294 return; 1295 } 1296 1297 // 1298 // transitional object 1299 // 1300 ob->ticcount-=tics; 1301 while ( ob->ticcount <= 0) 1302 { 1303 think = ob->state->action; // end of state action 1304 if (think) 1305 { 1306 think (ob); 1307 if (!ob->state) 1308 { 1309 RemoveObj (ob); 1310 return; 1311 } 1312 } 1313 1314 ob->state = ob->state->next; 1315 1316 if (!ob->state) 1317 { 1318 RemoveObj (ob); 1319 return; 1320 } 1321 1322 if (!ob->state->tictime) 1323 { 1324 ob->ticcount = 0; 1325 goto think; 1326 } 1327 1328 ob->ticcount += ob->state->tictime; 1329 } 1330 1331 think: 1332 // 1333 // think 1334 // 1335 think = ob->state->think; 1336 if (think) 1337 { 1338 think (ob); 1339 if (!ob->state) 1340 { 1341 RemoveObj (ob); 1342 return; 1343 } 1344 } 1345 1346 if (ob->flags&FL_NEVERMARK) 1347 return; 1348 1349 if ( (ob->flags&FL_NONMARK) && actorat[ob->tilex][ob->tiley]) 1350 return; 1351 1352 actorat[ob->tilex][ob->tiley] = ob; 1353 } 1354 1355 //========================================================================== 1356 1357 1358 /* 1359 =================== 1360 = 1361 = PlayLoop 1362 = 1363 =================== 1364 */ 1365 long funnyticount; 1366 1367 1368 void PlayLoop (void) 1369 { 1370 int give; 1371 int helmetangle; 1372 1373 playstate = TimeCount = lasttimecount = 0; 1374 frameon = 0; 1375 running = false; 1376 anglefrac = 0; 1377 facecount = 0; 1378 funnyticount = 0; 1379 memset (buttonstate,0,sizeof(buttonstate)); 1380 ClearPaletteShifts (); 1381 1382 if (MousePresent) 1383 Mouse(MDelta); // Clear accumulated mouse movement 1384 1385 if (demoplayback) 1386 IN_StartAck (); 1387 1388 do 1389 { 1390 if (virtualreality) 1391 { 1392 helmetangle = peek (0x40,0xf0); 1393 player->angle += helmetangle; 1394 if (player->angle >= ANGLES) 1395 player->angle -= ANGLES; 1396 } 1397 1398 1399 PollControls(); 1400 1401 // 1402 // actor thinking 1403 // 1404 madenoise = false; 1405 1406 MoveDoors (); 1407 MovePWalls (); 1408 1409 for (obj = player;obj;obj = obj->next) 1410 DoActor (obj); 1411 1412 UpdatePaletteShifts (); 1413 1414 ThreeDRefresh (); 1415 1416 // 1417 // MAKE FUNNY FACE IF BJ DOESN'T MOVE FOR AWHILE 1418 // 1419 #ifdef SPEAR 1420 funnyticount += tics; 1421 if (funnyticount > 30l*70) 1422 { 1423 funnyticount = 0; 1424 StatusDrawPic (17,4,BJWAITING1PIC+(US_RndT()&1)); 1425 facecount = 0; 1426 } 1427 #endif 1428 1429 gamestate.TimeCount+=tics; 1430 1431 SD_Poll (); 1432 UpdateSoundLoc(); // JAB 1433 1434 if (screenfaded) 1435 VW_FadeIn (); 1436 1437 CheckKeys(); 1438 1439 // 1440 // debug aids 1441 // 1442 if (singlestep) 1443 { 1444 VW_WaitVBL(14); 1445 lasttimecount = TimeCount; 1446 } 1447 if (extravbls) 1448 VW_WaitVBL(extravbls); 1449 1450 if (demoplayback) 1451 { 1452 if (IN_CheckAck ()) 1453 { 1454 IN_ClearKeysDown (); 1455 playstate = ex_abort; 1456 } 1457 } 1458 1459 1460 if (virtualreality) 1461 { 1462 player->angle -= helmetangle; 1463 if (player->angle < 0) 1464 player->angle += ANGLES; 1465 } 1466 1467 }while (!playstate && !startgame); 1468 1469 if (playstate != ex_died) 1470 FinishPaletteShifts (); 1471 } 1472