home *** CD-ROM | disk | FTP | other *** search
/ 100 af Verdens Bedste Spil / 100Spil.iso / dos / wolf3d / source / wolfsrc.1 / WL_PLAY.C < prev    next >
C/C++ Source or Header  |  1993-02-04  |  26KB  |  1,473 lines

  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.  
  1473.