Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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