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

  1. // WL_AGENT.C
  2.  
  3. #include "WL_DEF.H"
  4. #pragma hdrstop
  5.  
  6.  
  7. /*
  8. =============================================================================
  9.  
  10.                          LOCAL CONSTANTS
  11.  
  12. =============================================================================
  13. */
  14.  
  15. #define MAXMOUSETURN    10
  16.  
  17.  
  18. #define MOVESCALE        150l
  19. #define BACKMOVESCALE    100l
  20. #define ANGLESCALE        20
  21.  
  22. /*
  23. =============================================================================
  24.  
  25.                          GLOBAL VARIABLES
  26.  
  27. =============================================================================
  28. */
  29.  
  30.  
  31.  
  32. //
  33. // player state info
  34. //
  35. boolean        running;
  36. long        thrustspeed;
  37.  
  38. unsigned    plux,pluy;            // player coordinates scaled to unsigned
  39.  
  40. int            anglefrac;
  41. int            gotgatgun;    // JR
  42.  
  43. objtype        *LastAttacker;
  44.  
  45. /*
  46. =============================================================================
  47.  
  48.                          LOCAL VARIABLES
  49.  
  50. =============================================================================
  51. */
  52.  
  53.  
  54. void    T_Player (objtype *ob);
  55. void    T_Attack (objtype *ob);
  56.  
  57. statetype s_player = {false,0,0,T_Player,NULL,NULL};
  58. statetype s_attack = {false,0,0,T_Attack,NULL,NULL};
  59.  
  60.  
  61. long    playerxmove,playerymove;
  62.  
  63. struct atkinf
  64. {
  65.     char    tics,attack,frame;        // attack is 1 for gun, 2 for knife
  66. } attackinfo[4][14] =
  67.  
  68. {
  69. { {6,0,1},{6,2,2},{6,0,3},{6,-1,4} },
  70. { {6,0,1},{6,1,2},{6,0,3},{6,-1,4} },
  71. { {6,0,1},{6,1,2},{6,3,3},{6,-1,4} },
  72. { {6,0,1},{6,1,2},{6,4,3},{6,-1,4} },
  73. };
  74.  
  75.  
  76. int    strafeangle[9] = {0,90,180,270,45,135,225,315,0};
  77.  
  78. void DrawWeapon (void);
  79. void GiveWeapon (int weapon);
  80. void    GiveAmmo (int ammo);
  81.  
  82. //===========================================================================
  83.  
  84. //----------
  85.  
  86. void Attack (void);
  87. void Use (void);
  88. void Search (objtype *ob);
  89. void SelectWeapon (void);
  90. void SelectItem (void);
  91.  
  92. //----------
  93.  
  94. boolean TryMove (objtype *ob);
  95. void T_Player (objtype *ob);
  96.  
  97. void ClipMove (objtype *ob, long xmove, long ymove);
  98.  
  99. /*
  100. =============================================================================
  101.  
  102.                         CONTROL STUFF
  103.  
  104. =============================================================================
  105. */
  106.  
  107. /*
  108. ======================
  109. =
  110. = CheckWeaponChange
  111. =
  112. = Keys 1-4 change weapons
  113. =
  114. ======================
  115. */
  116.  
  117. void CheckWeaponChange (void)
  118. {
  119.     int    i,buttons;
  120.  
  121.     if (!gamestate.ammo)        // must use knife with no ammo
  122.         return;
  123.  
  124.     for (i=wp_knife ; i<=gamestate.bestweapon ; i++)
  125.         if (buttonstate[bt_readyknife+i-wp_knife])
  126.         {
  127.             gamestate.weapon = gamestate.chosenweapon = i;
  128.             DrawWeapon ();
  129.             return;
  130.         }
  131. }
  132.  
  133.  
  134. /*
  135. =======================
  136. =
  137. = ControlMovement
  138. =
  139. = Takes controlx,controly, and buttonstate[bt_strafe]
  140. =
  141. = Changes the player's angle and position
  142. =
  143. = There is an angle hack because when going 70 fps, the roundoff becomes
  144. = significant
  145. =
  146. =======================
  147. */
  148.  
  149. void ControlMovement (objtype *ob)
  150. {
  151.     long    oldx,oldy;
  152.     int        angle,maxxmove;
  153.     int        angleunits;
  154.     long    speed;
  155.  
  156.     thrustspeed = 0;
  157.  
  158.     oldx = player->x;
  159.     oldy = player->y;
  160.  
  161. //
  162. // side to side move
  163. //
  164.     if (buttonstate[bt_strafe])
  165.     {
  166.     //
  167.     // strafing
  168.     //
  169.     //
  170.         if (controlx > 0)
  171.         {
  172.             angle = ob->angle - ANGLES/4;
  173.             if (angle < 0)
  174.                 angle += ANGLES;
  175.             Thrust (angle,controlx*MOVESCALE);    // move to left
  176.         }
  177.         else if (controlx < 0)
  178.         {
  179.             angle = ob->angle + ANGLES/4;
  180.             if (angle >= ANGLES)
  181.                 angle -= ANGLES;
  182.             Thrust (angle,-controlx*MOVESCALE);    // move to right
  183.         }
  184.     }
  185.     else
  186.     {
  187.     //
  188.     // not strafing
  189.     //
  190.         anglefrac += controlx;
  191.         angleunits = anglefrac/ANGLESCALE;
  192.         anglefrac -= angleunits*ANGLESCALE;
  193.         ob->angle -= angleunits;
  194.  
  195.         if (ob->angle >= ANGLES)
  196.             ob->angle -= ANGLES;
  197.         if (ob->angle < 0)
  198.             ob->angle += ANGLES;
  199.  
  200.     }
  201.  
  202. //
  203. // forward/backwards move
  204. //
  205.     if (controly < 0)
  206.     {
  207.         Thrust (ob->angle,-controly*MOVESCALE);    // move forwards
  208.     }
  209.     else if (controly > 0)
  210.     {
  211.         angle = ob->angle + ANGLES/2;
  212.         if (angle >= ANGLES)
  213.             angle -= ANGLES;
  214.         Thrust (angle,controly*BACKMOVESCALE);        // move backwards
  215.     }
  216.  
  217.     if (gamestate.victoryflag)        // watching the BJ actor
  218.         return;
  219.  
  220. //
  221. // calculate total move
  222. //
  223.     playerxmove = player->x - oldx;
  224.     playerymove = player->y - oldy;
  225. }
  226.  
  227. /*
  228. =============================================================================
  229.  
  230.                     STATUS WINDOW STUFF
  231.  
  232. =============================================================================
  233. */
  234.  
  235.  
  236. /*
  237. ==================
  238. =
  239. = StatusDrawPic
  240. =
  241. ==================
  242. */
  243.  
  244. void StatusDrawPic (unsigned x, unsigned y, unsigned picnum)
  245. {
  246.     unsigned    temp;
  247.  
  248.     temp = bufferofs;
  249.     bufferofs = 0;
  250.  
  251.     bufferofs = PAGE1START+(200-STATUSLINES)*SCREENWIDTH;
  252.     LatchDrawPic (x,y,picnum);
  253.     bufferofs = PAGE2START+(200-STATUSLINES)*SCREENWIDTH;
  254.     LatchDrawPic (x,y,picnum);
  255.     bufferofs = PAGE3START+(200-STATUSLINES)*SCREENWIDTH;
  256.     LatchDrawPic (x,y,picnum);
  257.  
  258.     bufferofs = temp;
  259. }
  260.  
  261.  
  262. /*
  263. ==================
  264. =
  265. = DrawFace
  266. =
  267. ==================
  268. */
  269.  
  270. void DrawFace (void)
  271. {
  272.     if (gamestate.health)
  273.     {
  274.         #ifdef SPEAR
  275.         if (godmode)
  276.             StatusDrawPic (17,4,GODMODEFACE1PIC+gamestate.faceframe);
  277.         else
  278.         #endif
  279.         StatusDrawPic (17,4,FACE1APIC+3*((100-gamestate.health)/16)+gamestate.faceframe);
  280.     }
  281.     else
  282.     {
  283. #ifndef SPEAR
  284.      if (LastAttacker->obclass == needleobj)
  285.        StatusDrawPic (17,4,MUTANTBJPIC);
  286.      else
  287. #endif
  288.        StatusDrawPic (17,4,FACE8APIC);
  289.     }
  290. }
  291.  
  292.  
  293. /*
  294. ===============
  295. =
  296. = UpdateFace
  297. =
  298. = Calls draw face if time to change
  299. =
  300. ===============
  301. */
  302.  
  303. #define FACETICS    70
  304.  
  305. int    facecount;
  306.  
  307. void    UpdateFace (void)
  308. {
  309.  
  310.     if (SD_SoundPlaying() == GETGATLINGSND)
  311.       return;
  312.  
  313.     facecount += tics;
  314.     if (facecount > US_RndT())
  315.     {
  316.         gamestate.faceframe = (US_RndT()>>6);
  317.         if (gamestate.faceframe==3)
  318.             gamestate.faceframe = 1;
  319.  
  320.         facecount = 0;
  321.         DrawFace ();
  322.     }
  323. }
  324.  
  325.  
  326.  
  327. /*
  328. ===============
  329. =
  330. = LatchNumber
  331. =
  332. = right justifies and pads with blanks
  333. =
  334. ===============
  335. */
  336.  
  337. void    LatchNumber (int x, int y, int width, long number)
  338. {
  339.     unsigned    length,c;
  340.     char    str[20];
  341.  
  342.     ltoa (number,str,10);
  343.  
  344.     length = strlen (str);
  345.  
  346.     while (length<width)
  347.     {
  348.         StatusDrawPic (x,y,N_BLANKPIC);
  349.         x++;
  350.         width--;
  351.     }
  352.  
  353.     c= length <= width ? 0 : length-width;
  354.  
  355.     while (c<length)
  356.     {
  357.         StatusDrawPic (x,y,str[c]-'0'+ N_0PIC);
  358.         x++;
  359.         c++;
  360.     }
  361. }
  362.  
  363.  
  364. /*
  365. ===============
  366. =
  367. = DrawHealth
  368. =
  369. ===============
  370. */
  371.  
  372. void    DrawHealth (void)
  373. {
  374.     LatchNumber (21,16,3,gamestate.health);
  375. }
  376.  
  377.  
  378. /*
  379. ===============
  380. =
  381. = TakeDamage
  382. =
  383. ===============
  384. */
  385.  
  386. void    TakeDamage (int points,objtype *attacker)
  387. {
  388.     LastAttacker = attacker;
  389.  
  390.     if (gamestate.victoryflag)
  391.         return;
  392.     if (gamestate.difficulty==gd_baby)
  393.       points>>=2;
  394.  
  395.     if (!godmode)
  396.         gamestate.health -= points;
  397.  
  398.     if (gamestate.health<=0)
  399.     {
  400.         gamestate.health = 0;
  401.         playstate = ex_died;
  402.         killerobj = attacker;
  403.     }
  404.  
  405.     StartDamageFlash (points);
  406.  
  407.     gotgatgun=0;
  408.  
  409.     DrawHealth ();
  410.     DrawFace ();
  411.  
  412.     //
  413.     // MAKE BJ'S EYES BUG IF MAJOR DAMAGE!
  414.     //
  415.     #ifdef SPEAR
  416.     if (points > 30 && gamestate.health!=0 && !godmode)
  417.     {
  418.         StatusDrawPic (17,4,BJOUCHPIC);
  419.         facecount = 0;
  420.     }
  421.     #endif
  422.  
  423. }
  424.  
  425.  
  426. /*
  427. ===============
  428. =
  429. = HealSelf
  430. =
  431. ===============
  432. */
  433.  
  434. void    HealSelf (int points)
  435. {
  436.     gamestate.health += points;
  437.     if (gamestate.health>100)
  438.         gamestate.health = 100;
  439.  
  440.     DrawHealth ();
  441.     gotgatgun = 0;    // JR
  442.     DrawFace ();
  443. }
  444.  
  445.  
  446. //===========================================================================
  447.  
  448.  
  449. /*
  450. ===============
  451. =
  452. = DrawLevel
  453. =
  454. ===============
  455. */
  456.  
  457. void    DrawLevel (void)
  458. {
  459. #ifdef SPEAR
  460.     if (gamestate.mapon == 20)
  461.         LatchNumber (2,16,2,18);
  462.     else
  463. #endif
  464.     LatchNumber (2,16,2,gamestate.mapon+1);
  465. }
  466.  
  467. //===========================================================================
  468.  
  469.  
  470. /*
  471. ===============
  472. =
  473. = DrawLives
  474. =
  475. ===============
  476. */
  477.  
  478. void    DrawLives (void)
  479. {
  480.     LatchNumber (14,16,1,gamestate.lives);
  481. }
  482.  
  483.  
  484. /*
  485. ===============
  486. =
  487. = GiveExtraMan
  488. =
  489. ===============
  490. */
  491.  
  492. void    GiveExtraMan (void)
  493. {
  494.     if (gamestate.lives<9)
  495.         gamestate.lives++;
  496.     DrawLives ();
  497.     SD_PlaySound (BONUS1UPSND);
  498. }
  499.  
  500. //===========================================================================
  501.  
  502. /*
  503. ===============
  504. =
  505. = DrawScore
  506. =
  507. ===============
  508. */
  509.  
  510. void    DrawScore (void)
  511. {
  512.     LatchNumber (6,16,6,gamestate.score);
  513. }
  514.  
  515. /*
  516. ===============
  517. =
  518. = GivePoints
  519. =
  520. ===============
  521. */
  522.  
  523. void    GivePoints (long points)
  524. {
  525.     gamestate.score += points;
  526.     while (gamestate.score >= gamestate.nextextra)
  527.     {
  528.         gamestate.nextextra += EXTRAPOINTS;
  529.         GiveExtraMan ();
  530.     }
  531.     DrawScore ();
  532. }
  533.  
  534. //===========================================================================
  535.  
  536. /*
  537. ==================
  538. =
  539. = DrawWeapon
  540. =
  541. ==================
  542. */
  543.  
  544. void DrawWeapon (void)
  545. {
  546.     StatusDrawPic (32,8,KNIFEPIC+gamestate.weapon);
  547. }
  548.  
  549.  
  550. /*
  551. ==================
  552. =
  553. = DrawKeys
  554. =
  555. ==================
  556. */
  557.  
  558. void DrawKeys (void)
  559. {
  560.     if (gamestate.keys & 1)
  561.         StatusDrawPic (30,4,GOLDKEYPIC);
  562.     else
  563.         StatusDrawPic (30,4,NOKEYPIC);
  564.  
  565.     if (gamestate.keys & 2)
  566.         StatusDrawPic (30,20,SILVERKEYPIC);
  567.     else
  568.         StatusDrawPic (30,20,NOKEYPIC);
  569. }
  570.  
  571.  
  572.  
  573. /*
  574. ==================
  575. =
  576. = GiveWeapon
  577. =
  578. ==================
  579. */
  580.  
  581. void GiveWeapon (int weapon)
  582. {
  583.     GiveAmmo (6);
  584.  
  585.     if (gamestate.bestweapon<weapon)
  586.         gamestate.bestweapon = gamestate.weapon
  587.         = gamestate.chosenweapon = weapon;
  588.  
  589.     DrawWeapon ();
  590. }
  591.  
  592.  
  593. //===========================================================================
  594.  
  595. /*
  596. ===============
  597. =
  598. = DrawAmmo
  599. =
  600. ===============
  601. */
  602.  
  603. void    DrawAmmo (void)
  604. {
  605.     LatchNumber (27,16,2,gamestate.ammo);
  606. }
  607.  
  608.  
  609. /*
  610. ===============
  611. =
  612. = GiveAmmo
  613. =
  614. ===============
  615. */
  616.  
  617. void    GiveAmmo (int ammo)
  618. {
  619.     if (!gamestate.ammo)                // knife was out
  620.     {
  621.         if (!gamestate.attackframe)
  622.         {
  623.             gamestate.weapon = gamestate.chosenweapon;
  624.             DrawWeapon ();
  625.         }
  626.     }
  627.     gamestate.ammo += ammo;
  628.     if (gamestate.ammo > 99)
  629.         gamestate.ammo = 99;
  630.     DrawAmmo ();
  631. }
  632.  
  633. //===========================================================================
  634.  
  635. /*
  636. ==================
  637. =
  638. = GiveKey
  639. =
  640. ==================
  641. */
  642.  
  643. void GiveKey (int key)
  644. {
  645.     gamestate.keys |= (1<<key);
  646.     DrawKeys ();
  647. }
  648.  
  649.  
  650.  
  651. /*
  652. =============================================================================
  653.  
  654.                             MOVEMENT
  655.  
  656. =============================================================================
  657. */
  658.  
  659.  
  660. /*
  661. ===================
  662. =
  663. = GetBonus
  664. =
  665. ===================
  666. */
  667. void GetBonus (statobj_t *check)
  668. {
  669.     switch (check->itemnumber)
  670.     {
  671.     case    bo_firstaid:
  672.         if (gamestate.health == 100)
  673.             return;
  674.  
  675.         SD_PlaySound (HEALTH2SND);
  676.         HealSelf (25);
  677.         break;
  678.  
  679.     case    bo_key1:
  680.     case    bo_key2:
  681.     case    bo_key3:
  682.     case    bo_key4:
  683.         GiveKey (check->itemnumber - bo_key1);
  684.         SD_PlaySound (GETKEYSND);
  685.         break;
  686.  
  687.     case    bo_cross:
  688.         SD_PlaySound (BONUS1SND);
  689.         GivePoints (100);
  690.         gamestate.treasurecount++;
  691.         break;
  692.     case    bo_chalice:
  693.         SD_PlaySound (BONUS2SND);
  694.         GivePoints (500);
  695.         gamestate.treasurecount++;
  696.         break;
  697.     case    bo_bible:
  698.         SD_PlaySound (BONUS3SND);
  699.         GivePoints (1000);
  700.         gamestate.treasurecount++;
  701.         break;
  702.     case    bo_crown:
  703.         SD_PlaySound (BONUS4SND);
  704.         GivePoints (5000);
  705.         gamestate.treasurecount++;
  706.         break;
  707.  
  708.     case    bo_clip:
  709.         if (gamestate.ammo == 99)
  710.             return;
  711.  
  712.         SD_PlaySound (GETAMMOSND);
  713.         GiveAmmo (8);
  714.         break;
  715.     case    bo_clip2:
  716.         if (gamestate.ammo == 99)
  717.             return;
  718.  
  719.         SD_PlaySound (GETAMMOSND);
  720.         GiveAmmo (4);
  721.         break;
  722.  
  723. #ifdef SPEAR
  724.     case    bo_25clip:
  725.         if (gamestate.ammo == 99)
  726.           return;
  727.  
  728.         SD_PlaySound (GETAMMOBOXSND);
  729.         GiveAmmo (25);
  730.         break;
  731. #endif
  732.  
  733.     case    bo_machinegun:
  734.         SD_PlaySound (GETMACHINESND);
  735.         GiveWeapon (wp_machinegun);
  736.         break;
  737.     case    bo_chaingun:
  738.         SD_PlaySound (GETGATLINGSND);
  739.         GiveWeapon (wp_chaingun);
  740.  
  741.         StatusDrawPic (17,4,GOTGATLINGPIC);
  742.         facecount = 0;
  743.         gotgatgun = 1;
  744.         break;
  745.  
  746.     case    bo_fullheal:
  747.         SD_PlaySound (BONUS1UPSND);
  748.         HealSelf (99);
  749.         GiveAmmo (25);
  750.         GiveExtraMan ();
  751.         gamestate.treasurecount++;
  752.         break;
  753.  
  754.     case    bo_food:
  755.         if (gamestate.health == 100)
  756.             return;
  757.  
  758.         SD_PlaySound (HEALTH1SND);
  759.         HealSelf (10);
  760.         break;
  761.  
  762.     case    bo_alpo:
  763.         if (gamestate.health == 100)
  764.             return;
  765.  
  766.         SD_PlaySound (HEALTH1SND);
  767.         HealSelf (4);
  768.         break;
  769.  
  770.     case    bo_gibs:
  771.         if (gamestate.health >10)
  772.             return;
  773.  
  774.         SD_PlaySound (SLURPIESND);
  775.         HealSelf (1);
  776.         break;
  777.  
  778.     case    bo_spear:
  779.         spearflag = true;
  780.         spearx = player->x;
  781.         speary = player->y;
  782.         spearangle = player->angle;
  783.         playstate = ex_completed;
  784.     }
  785.  
  786.     StartBonusFlash ();
  787.     check->shapenum = -1;            // remove from list
  788. }
  789.  
  790.  
  791. /*
  792. ===================
  793. =
  794. = TryMove
  795. =
  796. = returns true if move ok
  797. = debug: use pointers to optimize
  798. ===================
  799. */
  800.  
  801. boolean TryMove (objtype *ob)
  802. {
  803.     int            xl,yl,xh,yh,x,y;
  804.     objtype        *check;
  805.     long        deltax,deltay;
  806.  
  807.     xl = (ob->x-PLAYERSIZE) >>TILESHIFT;
  808.     yl = (ob->y-PLAYERSIZE) >>TILESHIFT;
  809.  
  810.     xh = (ob->x+PLAYERSIZE) >>TILESHIFT;
  811.     yh = (ob->y+PLAYERSIZE) >>TILESHIFT;
  812.  
  813. //
  814. // check for solid walls
  815. //
  816.     for (y=yl;y<=yh;y++)
  817.         for (x=xl;x<=xh;x++)
  818.         {
  819.             check = actorat[x][y];
  820.             if (check && check<objlist)
  821.                 return false;
  822.         }
  823.  
  824. //
  825. // check for actors
  826. //
  827.     if (yl>0)
  828.         yl--;
  829.     if (yh<MAPSIZE-1)
  830.         yh++;
  831.     if (xl>0)
  832.         xl--;
  833.     if (xh<MAPSIZE-1)
  834.         xh++;
  835.  
  836.     for (y=yl;y<=yh;y++)
  837.         for (x=xl;x<=xh;x++)
  838.         {
  839.             check = actorat[x][y];
  840.             if (check > objlist
  841.             && (check->flags & FL_SHOOTABLE) )
  842.             {
  843.                 deltax = ob->x - check->x;
  844.                 if (deltax < -MINACTORDIST || deltax > MINACTORDIST)
  845.                     continue;
  846.                 deltay = ob->y - check->y;
  847.                 if (deltay < -MINACTORDIST || deltay > MINACTORDIST)
  848.                     continue;
  849.  
  850.                 return false;
  851.             }
  852.         }
  853.  
  854.     return true;
  855. }
  856.  
  857.  
  858. /*
  859. ===================
  860. =
  861. = ClipMove
  862. =
  863. ===================
  864. */
  865.  
  866. void ClipMove (objtype *ob, long xmove, long ymove)
  867. {
  868.     long    basex,basey;
  869.  
  870.     basex = ob->x;
  871.     basey = ob->y;
  872.  
  873.     ob->x = basex+xmove;
  874.     ob->y = basey+ymove;
  875.     if (TryMove (ob))
  876.         return;
  877.  
  878.     if (noclip && ob->x > 2*TILEGLOBAL && ob->y > 2*TILEGLOBAL &&
  879.     ob->x < (((long)(mapwidth-1))<<TILESHIFT)
  880.     && ob->y < (((long)(mapheight-1))<<TILESHIFT) )
  881.         return;        // walk through walls
  882.  
  883.     if (!SD_SoundPlaying())
  884.         SD_PlaySound (HITWALLSND);
  885.  
  886.     ob->x = basex+xmove;
  887.     ob->y = basey;
  888.     if (TryMove (ob))
  889.         return;
  890.  
  891.     ob->x = basex;
  892.     ob->y = basey+ymove;
  893.     if (TryMove (ob))
  894.         return;
  895.  
  896.     ob->x = basex;
  897.     ob->y = basey;
  898. }
  899.  
  900. //==========================================================================
  901.  
  902. /*
  903. ===================
  904. =
  905. = VictoryTile
  906. =
  907. ===================
  908. */
  909.  
  910. void VictoryTile (void)
  911. {
  912. #ifndef SPEAR
  913.     SpawnBJVictory ();
  914. #endif
  915.  
  916.     gamestate.victoryflag = true;
  917. }
  918.  
  919.  
  920. /*
  921. ===================
  922. =
  923. = Thrust
  924. =
  925. ===================
  926. */
  927.  
  928. void Thrust (int angle, long speed)
  929. {
  930.     long xmove,ymove;
  931.     long    slowmax;
  932.     unsigned    offset;
  933.  
  934.  
  935.     //
  936.     // ZERO FUNNY COUNTER IF MOVED!
  937.     //
  938.     #ifdef SPEAR
  939.     if (speed)
  940.         funnyticount = 0;
  941.     #endif
  942.  
  943.     thrustspeed += speed;
  944. //
  945. // moving bounds speed
  946. //
  947.     if (speed >= MINDIST*2)
  948.         speed = MINDIST*2-1;
  949.  
  950.     xmove = FixedByFrac(speed,costable[angle]);
  951.     ymove = -FixedByFrac(speed,sintable[angle]);
  952.  
  953.     ClipMove(player,xmove,ymove);
  954.  
  955.     player->tilex = player->x >> TILESHIFT;        // scale to tile values
  956.     player->tiley = player->y >> TILESHIFT;
  957.  
  958.     offset = farmapylookup[player->tiley]+player->tilex;
  959.     player->areanumber = *(mapsegs[0] + offset) -AREATILE;
  960.  
  961.     if (*(mapsegs[1] + offset) == EXITTILE)
  962.         VictoryTile ();
  963. }
  964.  
  965.  
  966. /*
  967. =============================================================================
  968.  
  969.                                 ACTIONS
  970.  
  971. =============================================================================
  972. */
  973.  
  974.  
  975. /*
  976. ===============
  977. =
  978. = Cmd_Fire
  979. =
  980. ===============
  981. */
  982.  
  983. void Cmd_Fire (void)
  984. {
  985.     buttonheld[bt_attack] = true;
  986.  
  987.     gamestate.weaponframe = 0;
  988.  
  989.     player->state = &s_attack;
  990.  
  991.     gamestate.attackframe = 0;
  992.     gamestate.attackcount =
  993.         attackinfo[gamestate.weapon][gamestate.attackframe].tics;
  994.     gamestate.weaponframe =
  995.         attackinfo[gamestate.weapon][gamestate.attackframe].frame;
  996. }
  997.  
  998. //===========================================================================
  999.  
  1000. /*
  1001. ===============
  1002. =
  1003. = Cmd_Use
  1004. =
  1005. ===============
  1006. */
  1007.  
  1008. void Cmd_Use (void)
  1009. {
  1010.     objtype     *check;
  1011.     int            checkx,checky,doornum,dir;
  1012.     boolean        elevatorok;
  1013.  
  1014.  
  1015. //
  1016. // find which cardinal direction the player is facing
  1017. //
  1018.     if (player->angle < ANGLES/8 || player->angle > 7*ANGLES/8)
  1019.     {
  1020.         checkx = player->tilex + 1;
  1021.         checky = player->tiley;
  1022.         dir = di_east;
  1023.         elevatorok = true;
  1024.     }
  1025.     else if (player->angle < 3*ANGLES/8)
  1026.     {
  1027.         checkx = player->tilex;
  1028.         checky = player->tiley-1;
  1029.         dir = di_north;
  1030.         elevatorok = false;
  1031.     }
  1032.     else if (player->angle < 5*ANGLES/8)
  1033.     {
  1034.         checkx = player->tilex - 1;
  1035.         checky = player->tiley;
  1036.         dir = di_west;
  1037.         elevatorok = true;
  1038.     }
  1039.     else
  1040.     {
  1041.         checkx = player->tilex;
  1042.         checky = player->tiley + 1;
  1043.         dir = di_south;
  1044.         elevatorok = false;
  1045.     }
  1046.  
  1047.     doornum = tilemap[checkx][checky];
  1048.     if (*(mapsegs[1]+farmapylookup[checky]+checkx) == PUSHABLETILE)
  1049.     {
  1050.     //
  1051.     // pushable wall
  1052.     //
  1053.  
  1054.         PushWall (checkx,checky,dir);
  1055.         return;
  1056.     }
  1057.     if (!buttonheld[bt_use] && doornum == ELEVATORTILE && elevatorok)
  1058.     {
  1059.     //
  1060.     // use elevator
  1061.     //
  1062.         buttonheld[bt_use] = true;
  1063.  
  1064.         tilemap[checkx][checky]++;        // flip switch
  1065.         if (*(mapsegs[0]+farmapylookup[player->tiley]+player->tilex) == ALTELEVATORTILE)
  1066.             playstate = ex_secretlevel;
  1067.         else
  1068.             playstate = ex_completed;
  1069.         SD_PlaySound (LEVELDONESND);
  1070.         SD_WaitSoundDone();
  1071.     }
  1072.     else if (!buttonheld[bt_use] && doornum & 0x80)
  1073.     {
  1074.         buttonheld[bt_use] = true;
  1075.         OperateDoor (doornum & ~0x80);
  1076.     }
  1077.     else
  1078.         SD_PlaySound (DONOTHINGSND);
  1079.  
  1080. }
  1081.  
  1082. /*
  1083. =============================================================================
  1084.  
  1085.                            PLAYER CONTROL
  1086.  
  1087. =============================================================================
  1088. */
  1089.  
  1090.  
  1091.  
  1092. /*
  1093. ===============
  1094. =
  1095. = SpawnPlayer
  1096. =
  1097. ===============
  1098. */
  1099.  
  1100. void SpawnPlayer (int tilex, int tiley, int dir)
  1101. {
  1102.     player->obclass = playerobj;
  1103.     player->active = true;
  1104.     player->tilex = tilex;
  1105.     player->tiley = tiley;
  1106.     player->areanumber =
  1107.         *(mapsegs[0] + farmapylookup[player->tiley]+player->tilex);
  1108.     player->x = ((long)tilex<<TILESHIFT)+TILEGLOBAL/2;
  1109.     player->y = ((long)tiley<<TILESHIFT)+TILEGLOBAL/2;
  1110.     player->state = &s_player;
  1111.     player->angle = (1-dir)*90;
  1112.     if (player->angle<0)
  1113.         player->angle += ANGLES;
  1114.     player->flags = FL_NEVERMARK;
  1115.     Thrust (0,0);                // set some variables
  1116.  
  1117.     InitAreas ();
  1118. }
  1119.  
  1120.  
  1121. //===========================================================================
  1122.  
  1123. /*
  1124. ===============
  1125. =
  1126. = T_KnifeAttack
  1127. =
  1128. = Update player hands, and try to do damage when the proper frame is reached
  1129. =
  1130. ===============
  1131. */
  1132.  
  1133. void    KnifeAttack (objtype *ob)
  1134. {
  1135.     objtype *check,*closest;
  1136.     long    dist;
  1137.  
  1138.     SD_PlaySound (ATKKNIFESND);
  1139. // actually fire
  1140.     dist = 0x7fffffff;
  1141.     closest = NULL;
  1142.     for (check=ob->next ; check ; check=check->next)
  1143.         if ( (check->flags & FL_SHOOTABLE)
  1144.         && (check->flags & FL_VISABLE)
  1145.         && abs (check->viewx-centerx) < shootdelta
  1146.         )
  1147.         {
  1148.             if (check->transx < dist)
  1149.             {
  1150.                 dist = check->transx;
  1151.                 closest = check;
  1152.             }
  1153.         }
  1154.  
  1155.     if (!closest || dist> 0x18000l)
  1156.     {
  1157.     // missed
  1158.  
  1159.         return;
  1160.     }
  1161.  
  1162. // hit something
  1163.     DamageActor (closest,US_RndT() >> 4);
  1164. }
  1165.  
  1166.  
  1167.  
  1168. void    GunAttack (objtype *ob)
  1169. {
  1170.     objtype *check,*closest,*oldclosest;
  1171.     int        damage;
  1172.     int        dx,dy,dist;
  1173.     long    viewdist;
  1174.  
  1175.     switch (gamestate.weapon)
  1176.     {
  1177.     case wp_pistol:
  1178.         SD_PlaySound (ATKPISTOLSND);
  1179.         break;
  1180.     case wp_machinegun:
  1181.         SD_PlaySound (ATKMACHINEGUNSND);
  1182.         break;
  1183.     case wp_chaingun:
  1184.         SD_PlaySound (ATKGATLINGSND);
  1185.         break;
  1186.     }
  1187.  
  1188.     madenoise = true;
  1189.  
  1190. //
  1191. // find potential targets
  1192. //
  1193.     viewdist = 0x7fffffffl;
  1194.     closest = NULL;
  1195.  
  1196.     while (1)
  1197.     {
  1198.         oldclosest = closest;
  1199.  
  1200.         for (check=ob->next ; check ; check=check->next)
  1201.             if ( (check->flags & FL_SHOOTABLE)
  1202.             && (check->flags & FL_VISABLE)
  1203.             && abs (check->viewx-centerx) < shootdelta
  1204.             )
  1205.             {
  1206.                 if (check->transx < viewdist)
  1207.                 {
  1208.                     viewdist = check->transx;
  1209.                     closest = check;
  1210.                 }
  1211.             }
  1212.  
  1213.         if (closest == oldclosest)
  1214.             return;                        // no more targets, all missed
  1215.  
  1216.     //
  1217.     // trace a line from player to enemey
  1218.     //
  1219.         if (CheckLine(closest))
  1220.             break;
  1221.  
  1222.     }
  1223.  
  1224. //
  1225. // hit something
  1226. //
  1227.     dx = abs(closest->tilex - player->tilex);
  1228.     dy = abs(closest->tiley - player->tiley);
  1229.     dist = dx>dy ? dx:dy;
  1230.  
  1231.     if (dist<2)
  1232.         damage = US_RndT() / 4;
  1233.     else if (dist<4)
  1234.         damage = US_RndT() / 6;
  1235.     else
  1236.     {
  1237.         if ( (US_RndT() / 12) < dist)        // missed
  1238.             return;
  1239.         damage = US_RndT() / 6;
  1240.     }
  1241.  
  1242.     DamageActor (closest,damage);
  1243. }
  1244.  
  1245. //===========================================================================
  1246.  
  1247. /*
  1248. ===============
  1249. =
  1250. = VictorySpin
  1251. =
  1252. ===============
  1253. */
  1254.  
  1255. void VictorySpin (void)
  1256. {
  1257.     long    desty;
  1258.  
  1259.     if (player->angle > 270)
  1260.     {
  1261.         player->angle -= tics * 3;
  1262.         if (player->angle < 270)
  1263.             player->angle = 270;
  1264.     }
  1265.     else if (player->angle < 270)
  1266.     {
  1267.         player->angle += tics * 3;
  1268.         if (player->angle > 270)
  1269.             player->angle = 270;
  1270.     }
  1271.  
  1272.     desty = (((long)player->tiley-5)<<TILESHIFT)-0x3000;
  1273.  
  1274.     if (player->y > desty)
  1275.     {
  1276.         player->y -= tics*4096;
  1277.         if (player->y < desty)
  1278.             player->y = desty;
  1279.     }
  1280. }
  1281.  
  1282.  
  1283. //===========================================================================
  1284.  
  1285. /*
  1286. ===============
  1287. =
  1288. = T_Attack
  1289. =
  1290. ===============
  1291. */
  1292.  
  1293. void    T_Attack (objtype *ob)
  1294. {
  1295.     struct    atkinf    *cur;
  1296.  
  1297.     UpdateFace ();
  1298.  
  1299.     if (gamestate.victoryflag)        // watching the BJ actor
  1300.     {
  1301.         VictorySpin ();
  1302.         return;
  1303.     }
  1304.  
  1305.     if ( buttonstate[bt_use] && !buttonheld[bt_use] )
  1306.         buttonstate[bt_use] = false;
  1307.  
  1308.     if ( buttonstate[bt_attack] && !buttonheld[bt_attack])
  1309.         buttonstate[bt_attack] = false;
  1310.  
  1311.     ControlMovement (ob);
  1312.     if (gamestate.victoryflag)        // watching the BJ actor
  1313.         return;
  1314.  
  1315.     plux = player->x >> UNSIGNEDSHIFT;            // scale to fit in unsigned
  1316.     pluy = player->y >> UNSIGNEDSHIFT;
  1317.     player->tilex = player->x >> TILESHIFT;        // scale to tile values
  1318.     player->tiley = player->y >> TILESHIFT;
  1319.  
  1320. //
  1321. // change frame and fire
  1322. //
  1323.     gamestate.attackcount -= tics;
  1324.     while (gamestate.attackcount <= 0)
  1325.     {
  1326.         cur = &attackinfo[gamestate.weapon][gamestate.attackframe];
  1327.         switch (cur->attack)
  1328.         {
  1329.         case -1:
  1330.             ob->state = &s_player;
  1331.             if (!gamestate.ammo)
  1332.             {
  1333.                 gamestate.weapon = wp_knife;
  1334.                 DrawWeapon ();
  1335.             }
  1336.             else
  1337.             {
  1338.                 if (gamestate.weapon != gamestate.chosenweapon)
  1339.                 {
  1340.                     gamestate.weapon = gamestate.chosenweapon;
  1341.                     DrawWeapon ();
  1342.                 }
  1343.             };
  1344.             gamestate.attackframe = gamestate.weaponframe = 0;
  1345.             return;
  1346.  
  1347.         case 4:
  1348.             if (!gamestate.ammo)
  1349.                 break;
  1350.             if (buttonstate[bt_attack])
  1351.                 gamestate.attackframe -= 2;
  1352.         case 1:
  1353.             if (!gamestate.ammo)
  1354.             {    // can only happen with chain gun
  1355.                 gamestate.attackframe++;
  1356.                 break;
  1357.             }
  1358.             GunAttack (ob);
  1359.             gamestate.ammo--;
  1360.             DrawAmmo ();
  1361.             break;
  1362.  
  1363.         case 2:
  1364.             KnifeAttack (ob);
  1365.             break;
  1366.  
  1367.         case 3:
  1368.             if (gamestate.ammo && buttonstate[bt_attack])
  1369.                 gamestate.attackframe -= 2;
  1370.             break;
  1371.         }
  1372.  
  1373.         gamestate.attackcount += cur->tics;
  1374.         gamestate.attackframe++;
  1375.         gamestate.weaponframe =
  1376.             attackinfo[gamestate.weapon][gamestate.attackframe].frame;
  1377.     }
  1378.  
  1379. }
  1380.  
  1381.  
  1382.  
  1383. //===========================================================================
  1384.  
  1385. /*
  1386. ===============
  1387. =
  1388. = T_Player
  1389. =
  1390. ===============
  1391. */
  1392.  
  1393. void    T_Player (objtype *ob)
  1394. {
  1395.     if (gamestate.victoryflag)        // watching the BJ actor
  1396.     {
  1397.         VictorySpin ();
  1398.         return;
  1399.     }
  1400.  
  1401.     UpdateFace ();
  1402.     CheckWeaponChange ();
  1403.  
  1404.     if ( buttonstate[bt_use] )
  1405.         Cmd_Use ();
  1406.  
  1407.     if ( buttonstate[bt_attack] && !buttonheld[bt_attack])
  1408.         Cmd_Fire ();
  1409.  
  1410.     ControlMovement (ob);
  1411.     if (gamestate.victoryflag)        // watching the BJ actor
  1412.         return;
  1413.  
  1414.  
  1415.     plux = player->x >> UNSIGNEDSHIFT;            // scale to fit in unsigned
  1416.     pluy = player->y >> UNSIGNEDSHIFT;
  1417.     player->tilex = player->x >> TILESHIFT;        // scale to tile values
  1418.     player->tiley = player->y >> TILESHIFT;
  1419. }
  1420.  
  1421.  
  1422.