home *** CD-ROM | disk | FTP | other *** search
/ Freelog Special Issue 2 / Freelog_HS_3_Setp_Oct_Nov_2000_CD2.mdx / Arcade / Orbit / src / hud.c < prev    next >
C/C++ Source or Header  |  1999-09-11  |  31KB  |  1,429 lines

  1. /*
  2.  
  3. ORBIT, a freeware space combat simulator
  4. Copyright (C) 1999  Steve Belczyk <steve1@genesis.nred.ma.us>
  5.  
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or (at your option) any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  19.  
  20. */
  21.  
  22. #include "orbit.h"
  23.  
  24. static GLubyte throt_stipple[] = {
  25.     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  26.     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  27.     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  28.     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  29.     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  30.     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  31.     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  32.     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  33.     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  34.     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  35.     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  36.     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  37.     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  38.     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  39.     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  40.     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff
  41.     };
  42.  
  43. InitHud()
  44. /*
  45.  *  Initialize the HUD
  46.  */
  47. {
  48.     InitRadar();
  49.     MakeRadarCircleList();
  50.  
  51.     /* Figure out throttle coords */
  52.     hud.throt_min[0] = radar.fcenter[0] - 1.4*radar.fradius;
  53.     hud.throt_min[1] = radar.fcenter[1] - 0.9*radar.fradius;
  54.     hud.throt_max[0] = hud.throt_min[0] + 0.2*radar.fradius;
  55.     hud.throt_max[1] = hud.throt_min[1] + 1.8*radar.fradius;
  56.     hud.throt_mid[0] = hud.throt_min[0];
  57.     hud.throt_mid[1] = (hud.throt_min[1] + hud.throt_max[1]) / 2.0;
  58.  
  59.     /* Target name */
  60.     hud.targ_name[0] = radar.fcenter[0] + 2.0*radar.fradius;
  61.     hud.targ_name[1] = radar.fcenter[1] - radar.fradius + 10.0;
  62.  
  63.     /* Target range */
  64.     hud.targ_range[0] = hud.targ_name[0];
  65.     hud.targ_range[1] = hud.targ_name[1] - 10.0;
  66.  
  67.     /* Waypoint */
  68.     hud.waypoint[0] = hud.targ_range[0];
  69.     hud.waypoint[1] = hud.targ_range[1];
  70.  
  71.     /* Weapon name */
  72.     hud.weapon[0] = hud.targ_name[0];
  73.     hud.weapon[1] = radar.fcenter[1] + radar.fradius - 20.0;
  74.  
  75.     /* Velocity */
  76.     hud.vel[0] = radar.fcenter[0] - 3.0 * radar.fradius;
  77.     hud.vel[1] = hud.throt_mid[1] - 5.0;
  78.  
  79.     /* Shields display */
  80.     hud.shields_min[0] = radar.fcenter[0] + 1.2*radar.fradius;
  81.     hud.shields_max[0] = hud.shields_min[0] + 0.2*radar.fradius;
  82.     hud.shields_min[1] = hud.throt_min[1];
  83.     hud.shields_max[1] = hud.throt_max[1];
  84.  
  85.     /* Target shields */
  86.     hud.targshields_min[0] = radar.fcenter[0] + 1.5*radar.fradius;
  87.     hud.targshields_max[0] = hud.targshields_min[0] + 0.2*radar.fradius;
  88.     hud.targshields_min[1] = hud.throt_min[1];
  89.     hud.targshields_max[1] = hud.throt_max[1];
  90.  
  91.     lock.target = -1;
  92.     lock.type = LOCK_ENEMY;
  93. }
  94.  
  95. static GLubyte center_cursor[8] =
  96.     { 0x10, 0x10, 0x00, 0xc6, 0x00, 0x10, 0x10, 0x00 };
  97.  
  98. Hud()
  99. /*
  100.  *  Show the Heads Up Display
  101.  */
  102. {
  103.     char buf[256];
  104.  
  105.     /* Set up viewing matrix */
  106.     glMatrixMode (GL_MODELVIEW);
  107.     glPushMatrix();
  108.     glLoadIdentity();
  109.  
  110.     glMatrixMode (GL_PROJECTION);
  111.     glPushMatrix();
  112.     glLoadIdentity();
  113.  
  114.     glOrtho (0.0, ((double)ScreenWidth), 0.0, ((double)ScreenHeight), -1.0, 1.0);
  115.  
  116.     /* Disable three-D stuff */
  117.     glDisable (GL_DEPTH_TEST);
  118.     glDisable (GL_CULL_FACE);
  119.     glDisable (GL_LIGHTING);
  120.  
  121.     /* Try displaying a crosshair */
  122.     if (drawhud)
  123.     {
  124.         glColor3d (0.8, 0.8, 0.8);
  125.         glRasterPos2i (ScreenWidth/2, ScreenHeight/2);
  126.         glBitmap (8, 8, 3.0, 5.0, 0.0, 0.0, center_cursor);
  127.  
  128.         /* Display the radar */
  129.         Radar();
  130.  
  131.         /* Display the throttle */
  132.         Throttle();
  133.  
  134.         /* Velocity */
  135.         PlayerVel();
  136.  
  137.         /* Show target stuff */
  138.         TargetStuff();
  139.  
  140.         /* Current weapon */
  141.         ShowWeapon();
  142.  
  143.         /* Waypoint stuff */
  144.         WaypointStuff();
  145.  
  146.         /* Shields display */
  147.         Shields();
  148.  
  149.         /* Print the performance monitor */
  150.         if (showfps)
  151.         {
  152.             glColor3d (1.0, 1.0, 1.0);
  153.             glRasterPos2i (1, 5);
  154.  
  155.             sprintf (buf, "fps: %2.1f  ", fps);
  156.             Print (GLUT_BITMAP_HELVETICA_10, buf);
  157.  
  158.             /* Show bandwidth */
  159.             if (am_client || am_server)
  160.             {
  161.                 if (recv_bps > 0.0)
  162.                 {
  163.                     glColor3d (1.0, 0.0, 0.0);
  164.                     glRasterPos2i (1, 15);
  165.                     sprintf (buf, "R:%4.0lf  ", recv_bps);
  166.                     Print (GLUT_BITMAP_HELVETICA_10, buf);
  167.                 }
  168.  
  169.                 if (xmit_bps > 0.0)
  170.                 {
  171.                     glColor3d (0.0, 1.0, 0.0);
  172.                     glRasterPos2i (1, 25);
  173.                     sprintf (buf, "S:%4.0lf  ", xmit_bps);
  174.                     Print (GLUT_BITMAP_HELVETICA_10, buf);
  175.                 }
  176.             }
  177.         }
  178.     }
  179.  
  180.     /* Display the message console */
  181.     DisplayConsole();
  182.  
  183.     /* Display ceter-of-screen messages */
  184.     DrawMessage();
  185.  
  186.     glMatrixMode (GL_PROJECTION);
  187.     glPopMatrix();
  188.  
  189.     glMatrixMode (GL_MODELVIEW);
  190.     glPopMatrix();
  191.  
  192.     /* Draw various on-screen cursors */
  193.     if (drawhud)
  194.     {
  195.         /* The locked target */
  196.         DrawLock();
  197.  
  198.         /* Motion cursors */
  199.         DrawMotionCursors();
  200.  
  201.         /* Waypoint cursor */
  202.         DrawWaypoint();
  203.     }
  204.  
  205.     /* Re-enable three-D stuff */
  206.     glEnable (GL_DEPTH_TEST);
  207.     glEnable (GL_CULL_FACE);
  208.     glEnable (GL_LIGHTING);
  209. }
  210.  
  211. RadarCoords (v, x, y)
  212. double v[3], *x, *y;
  213. /*
  214.  *  Compute the two-D radar coordinates of an object
  215.  */
  216. {
  217.     double v2[3], v3[3], v4[3], t, r;
  218.  
  219.     /* Compute coords of object relative to player */
  220.     Vsub (v2, v, player.pos);
  221.  
  222.     /* Normalize that */
  223.     Normalize (v2);
  224.  
  225.     /* Distance of blip from center of radar is cosine of angle
  226.        between view direction and direction to object */
  227.     radarR = Dotp (player.view, v2);
  228.  
  229.     /* Find magnitude of projection of v2 onto view vector */
  230.     t = Dotp (v2, player.view);
  231.  
  232.     /* Determine projection of object on plane perpendicular
  233.        to viewing plane */
  234.     Vmul (v3, player.view, -t);
  235.     Vadd (v4, v3, v2);
  236.  
  237.     /* Handle special case of null v4, meaning object is on
  238.        line of sight */
  239.     if (0.0 == Mag2(v4))
  240.     {
  241.         radarCOS = 1.0;
  242.         radarSIN = 0.0;
  243.         return;
  244.     }
  245.  
  246.     /* Else normalize v4 */
  247.     Normalize (v4);
  248.  
  249.     /* v4 is now a vector from player's viewpoint to projection
  250.        of object on the player's plane.  Compute angle from player's
  251.        up vector to object */
  252.     radarCOS = Dotp (player.up, v4);
  253.     radarSIN = Dotp (player.right, v4);
  254.  
  255.     /* Convert to cartesian */
  256.     r = (1.0 - radarR) / 2.0;
  257.     *x = radar.fcenter[0] + radar.fradius * -r * radarSIN;
  258.     *y = radar.fcenter[1] + radar.fradius * r * radarCOS;
  259. }
  260.  
  261. Radar()
  262. /*
  263.  *  Display the Wing Commander-like radar
  264.  */
  265. {
  266.     /* Draw the circle around the radar */
  267.     DrawRadarCircle();
  268.  
  269.     /* Draw the objects */
  270.     RadarPlanets();
  271.     RadarTargets();
  272.     RadarMissiles();
  273.     RadarWaypoint();
  274. }
  275.  
  276. InitRadar()
  277. /*
  278.  *  Set up the radar coordinates
  279.  */
  280. {
  281.     radar.fcenter[0] = ScreenWidth / 2.0;
  282.     radar.center[0] = (int) radar.fcenter[0];
  283.  
  284.     radar.fcenter[1] = ScreenHeight / 8.0;
  285.     radar.center[1] = (int) radar.fcenter[1];
  286.  
  287.     radar.fradius = ScreenHeight / 8.0 - 10.0;
  288.     radar.radius = (int) radar.fradius;
  289. }
  290.  
  291. DrawRadarCircle()
  292. {
  293.     glCallList (radar.list);
  294. }
  295.  
  296. MakeRadarCircleList()
  297. /*
  298.  *  Define the radar circle list
  299.  */
  300. {
  301.     double x, y, theta;
  302.  
  303.     /* Delete the list if it already exists */
  304.     if (glIsList (radar.list)) glDeleteLists (radar.list, 1);
  305.  
  306.     radar.list = glGenLists (1);
  307.     glNewList (radar.list, GL_COMPILE);
  308.  
  309.     glEnable (GL_POLYGON_STIPPLE);
  310.     glPolygonStipple (throt_stipple);
  311.  
  312.     /* Fill in radar circle */
  313.     glColor3d (0.0, 0.0, 0.1);
  314.     glBegin (GL_POLYGON);
  315.     for (theta=0.0; theta<6.29; theta+=0.314)
  316.     {
  317.         y = (double) sin ((double) theta);
  318.         x = (double) cos ((double) theta);
  319.  
  320.         x = radar.fcenter[0] + x * radar.fradius;
  321.         y = radar.fcenter[1] + y * radar.fradius;
  322.  
  323.         glVertex2d (x, y);
  324.     }
  325.     glEnd();
  326.  
  327.     /* Draw yellow border */
  328.     glColor3d (0.3, 0.3, 0.0);
  329.     glBegin (GL_LINE_LOOP);
  330.     for (theta=0.0; theta<6.29; theta+=0.314)
  331.     {
  332.         y = (double) sin ((double) theta);
  333.         x = (double) cos ((double) theta);
  334.  
  335.         x = radar.fcenter[0] + x * radar.fradius;
  336.         y = radar.fcenter[1] + y * radar.fradius;
  337.  
  338.         glVertex2d (x, y);
  339.     }
  340.     glEnd();
  341.  
  342.     /* Draw inner circle */
  343.     glBegin (GL_LINE_LOOP);
  344.     for (theta=0.0; theta<6.29; theta+=0.314)
  345.     {
  346.         y = (double) sin ((double) theta);
  347.         x = (double) cos ((double) theta);
  348.  
  349.         x = radar.fcenter[0] + x * radar.fradius / 2.0;
  350.         y = radar.fcenter[1] + y * radar.fradius / 2.0;
  351.  
  352.         glVertex2d (x, y);
  353.     }
  354.     glEnd();
  355.  
  356.     /* Draw connecting lines */
  357.     glBegin (GL_LINES);
  358.     x = radar.fcenter[0] + 0.7071 * radar.fradius;
  359.     y = radar.fcenter[1] + 0.7071 * radar.fradius;
  360.     glVertex2d (x, y);
  361.     x = radar.fcenter[0] + 0.7071 * radar.fradius / 2.0;
  362.     y = radar.fcenter[1] + 0.7071 * radar.fradius / 2.0;
  363.     glVertex2d (x, y);
  364.  
  365.     glBegin (GL_LINES);
  366.     x = radar.fcenter[0] - 0.7071 * radar.fradius;
  367.     y = radar.fcenter[1] + 0.7071 * radar.fradius;
  368.     glVertex2d (x, y);
  369.     x = radar.fcenter[0] - 0.7071 * radar.fradius / 2.0;
  370.     y = radar.fcenter[1] + 0.7071 * radar.fradius / 2.0;
  371.     glVertex2d (x, y);
  372.  
  373.     glBegin (GL_LINES);
  374.     x = radar.fcenter[0] - 0.7071 * radar.fradius;
  375.     y = radar.fcenter[1] - 0.7071 * radar.fradius;
  376.     glVertex2d (x, y);
  377.     x = radar.fcenter[0] - 0.7071 * radar.fradius / 2.0;
  378.     y = radar.fcenter[1] - 0.7071 * radar.fradius / 2.0;
  379.     glVertex2d (x, y);
  380.  
  381.     glBegin (GL_LINES);
  382.     x = radar.fcenter[0] + 0.7071 * radar.fradius;
  383.     y = radar.fcenter[1] - 0.7071 * radar.fradius;
  384.     glVertex2d (x, y);
  385.     x = radar.fcenter[0] + 0.7071 * radar.fradius / 2.0;
  386.     y = radar.fcenter[1] - 0.7071 * radar.fradius / 2.0;
  387.     glVertex2d (x, y);
  388.  
  389.     glEnd();
  390.  
  391.     glDisable (GL_POLYGON_STIPPLE);
  392.  
  393.     glEndList();
  394. }
  395.  
  396. RadarPlanets()
  397. /*
  398.  *  Draw the planets on the radar
  399.  */
  400. {
  401.     int p;
  402.     double x, y;
  403.  
  404.     for (p=0; p<NPLANETS; p++)
  405.     {
  406.         if (!planet[p].hidden)
  407.         {
  408.             if ((!planet[p].is_moon) || (planet[p].range2 < (1000.0 * 1000.0)))
  409.             {
  410.                 /* Convert to radar coords */
  411.                 RadarCoords (planet[p].pos, &x, &y);
  412.  
  413.                 /* Draw it */
  414.                 if ( (lock.type == LOCK_PLANET) &&
  415.                      (lock.target == p) )
  416.                 {
  417.                     glPointSize (4.0);
  418.                 }
  419.                 else
  420.                 {
  421.                     glPointSize (3.0);
  422.                 }
  423.                 glBegin (GL_POINTS);
  424.                 if (planet[p].is_moon)
  425.                     glColor3d (0.0, 1.0, 1.0);
  426.                 else
  427.                     glColor3d (0.0, 0.0, 1.0);
  428.                 glVertex2d (x, y);
  429.                 glEnd();
  430.             }
  431.         }
  432.     }
  433. }
  434.  
  435. RadarTargets()
  436. /*
  437.  *  Draw the targets on the radar
  438.  */
  439. {
  440.     double x, y;
  441.     int i;
  442.  
  443. /*    glColor3d (0.9, 0.0, 0.0);    */
  444.  
  445.     for (i=0; i<NTARGETS; i++)
  446.     {
  447.         /* Is this a network game and this target is us? */
  448. /*        if (am_client && (i == client[clientme.client].target)) continue;    */
  449.         if (am_server && (i == client[server.client].target)) continue;
  450.  
  451.         if ( (target[i].age > 0.0) &&
  452.              (target[i].range2 < TARG_MAXRANGE2) &&
  453.              (!target[i].hidden) &&
  454.              (!target[i].invisible) )
  455.         {
  456.             /* Convert to radar coords */
  457.             RadarCoords (target[i].pos, &x, &y);
  458.  
  459.             /* Select color */
  460.             if (target[i].friendly)
  461.                 glColor3d (0.0, 0.9, 0.0);
  462.             else
  463.                 glColor3d (0.9, 0.0, 0.0);
  464.  
  465.             /* Draw locked target bigger */
  466.             if (i == lock.target)
  467.             {
  468.                 glPointSize (3.0);
  469.                 glBegin (GL_POINTS);
  470.                 glVertex2d (x, y);
  471.             }
  472.             else
  473.             {
  474.                 /* Just Draw it */
  475.                 glPointSize (2.0);
  476.                 glBegin (GL_POINTS);
  477.                 glVertex2d (x, y);
  478.             }
  479.  
  480.             glEnd();
  481.         }
  482.     }
  483.     glEnd();
  484. }
  485.  
  486. RadarMissiles()
  487. /*
  488.  *  Draw the missiles on the radar
  489.  */
  490. {
  491.     double x, y;
  492.     int i;
  493.  
  494.     glPointSize (1.0);
  495.     glBegin (GL_POINTS);
  496.  
  497.     /* Missiles are yellow */
  498.     glColor3d (1.0, 1.0, 0.0);
  499.  
  500.     for (i=0; i<NMSLS; i++)
  501.     {
  502.         if (msl[i].age > 0.0)
  503.         {
  504.             /* Convert to radar coords */
  505.             RadarCoords (msl[i].pos, &x, &y);
  506.  
  507.             /* Draw it */
  508.             glVertex2d (x, y);
  509.         }
  510.     }
  511.     glEnd();
  512. }
  513.  
  514. RadarWaypoint()
  515. /*
  516.  *  Draw the current waypoint
  517.  */
  518. {
  519.     double x, y;
  520.     int w;
  521.  
  522.     if ((-1) == (w = player.waypoint)) return;
  523.  
  524.     glPointSize (2.0);
  525.     glBegin (GL_POINTS);
  526.     glColor3d (1.0, 1.0, 1.0);
  527.     RadarCoords (waypoint[w].pos, &x, &y);
  528.     glVertex2d (x, y);
  529.     glEnd();
  530. }
  531.  
  532. LockNearest()
  533. /*
  534.  *  Lock onto the nearest target
  535.  */
  536. {
  537.     int t, ok;
  538.     double d;
  539.  
  540.     d = -1.0;
  541.  
  542.     if (lock.type == LOCK_ENEMY)
  543.     {
  544.         for (t=0; t<NTARGETS; t++)
  545.         {
  546.             if (am_client || am_server)
  547.             {
  548.                 /* Can lock distant targets in network games */
  549.                 ok = ( (target[t].age > 0.0) &&
  550.                      (!target[t].hidden) &&
  551.                      (!target[t].invisible) &&
  552.                      (!target[t].friendly) );
  553.             }
  554.             else
  555.             {
  556.                 ok = ( (target[t].age > 0.0) &&
  557.                      (!target[t].hidden) &&
  558.                      (!target[t].invisible) &&
  559.                      (!target[t].friendly) &&
  560.                      (target[t].range2 < TARG_MAXRANGE2) );
  561.             }
  562.  
  563.             if (ok)
  564.             {
  565.                 if ( (d < 0.0) || (target[t].range2 < d) )
  566.                 {
  567.                     d = target[t].range2;
  568.                     lock.target = t;
  569.                 }
  570.             }
  571.         }
  572.     }
  573.     else if (lock.type == LOCK_FRIENDLY)
  574.     {
  575.         for (t=0; t<NTARGETS; t++)
  576.         {
  577.             if ( (target[t].age > 0.0) &&
  578.                  (!target[t].hidden) &&
  579.                  (!target[t].invisible) &&
  580.                  (target[t].range2 < TARG_MAXRANGE2) &&
  581.                  (target[t].friendly) )
  582.             {
  583.                 if ( (d < 0.0) || (target[t].range2 < d) )
  584.                 {
  585.                     d = target[t].range2;
  586.                     lock.target = t;
  587.                 }
  588.             }
  589.         }
  590.     }
  591.     else if (lock.type == LOCK_PLANET)
  592.     {
  593.         for (t=0; t<NPLANETS; t++)
  594.         {
  595.             if (!planet[t].hidden)
  596.             {
  597.                 if ( (d < 0.0) || (planet[t].absrange2 < d) )
  598.                 {
  599.                     d = planet[t].absrange2;
  600.                     lock.target = t;
  601.                 }
  602.             }
  603.         }
  604.     }
  605. }
  606.  
  607. LockNext()
  608. /*
  609.  *  Lock onto next target
  610.  */
  611. {
  612.     int t, tt, old, ok;
  613.  
  614.     old = lock.target;
  615.  
  616.     /* Check if we're not locked yet */
  617.     if (lock.target == -1) lock.target = 0;
  618.  
  619.     if (lock.type == LOCK_ENEMY)
  620.     {
  621.         for (t=lock.target; t<lock.target+NTARGETS; t++)
  622.         {
  623.             tt = t % NTARGETS;
  624.  
  625.             if (am_client || am_server)
  626.             {
  627.                 /* Can lock distant targets in network games */
  628.                 ok = ( (target[tt].age > 0.0) &&
  629.                      (!target[tt].hidden) &&
  630.                      (!target[tt].invisible) &&
  631.                      (!target[tt].friendly) &&
  632.                      (tt != old) );
  633.             }
  634.             else
  635.             {
  636.                 ok = ( (target[tt].age > 0.0) &&
  637.                      (!target[tt].hidden) &&
  638.                      (!target[tt].invisible) &&
  639.                      (!target[tt].friendly) &&
  640.                      (target[tt].range2 < TARG_MAXRANGE2) &&
  641.                      (tt != old) );
  642.             }
  643.  
  644.             if (ok)
  645.             {
  646.                 lock.target = tt;
  647.                 return;
  648.             }
  649.         }
  650.     }
  651.     else if (lock.type == LOCK_FRIENDLY)
  652.     {
  653.         for (t=lock.target; t<lock.target+NTARGETS; t++)
  654.         {
  655.             tt = t % NTARGETS;
  656.  
  657.             if ( (target[tt].age > 0.0) &&
  658.                 (!target[tt].hidden) &&
  659.                 (!target[tt].invisible) &&
  660.                 (target[tt].friendly) &&
  661.                 (target[tt].range2 < TARG_MAXRANGE2) &&
  662.                 (tt != old) )
  663.             {
  664.                 lock.target = tt;
  665.                 return;
  666.             }
  667.         }
  668.     }
  669.     else if (lock.type == LOCK_PLANET)
  670.     {
  671.         do
  672.         {
  673.             lock.target = (lock.target + 1) % NPLANETS;
  674.         } while ( (planet[lock.target].is_moon &&
  675.                (planet[lock.target].range2 > (5000.0*5000.0)) ) ||
  676.                   planet[lock.target].hidden);
  677.         return;
  678.     }
  679.  
  680.     /* Nothing new to lock onto */
  681.     lock.target = old;
  682. }
  683.  
  684. LockPrev()
  685. /*
  686.  *  Lock onto previous target
  687.  */
  688. {
  689.     int t, tt, old, ok;
  690.  
  691.     old = lock.target;
  692.  
  693.     /* Check if we're not locked yet */
  694.     if (lock.target == -1) lock.target = 0;
  695.  
  696.     if (lock.type == LOCK_ENEMY)
  697.     {
  698.         for (t=lock.target+NTARGETS; t>lock.target; t--)
  699.         {
  700.             tt = t % NTARGETS;
  701.  
  702.             if (am_client || am_server)
  703.             {
  704.                 ok = ( (target[tt].age > 0.0) &&
  705.                      (!target[tt].hidden) &&
  706.                      (!target[tt].invisible) &&
  707.                      (!target[tt].friendly) &&
  708.                      (tt != old) );
  709.             }
  710.             else
  711.             {
  712.                 ok = ( (target[tt].age > 0.0) &&
  713.                      (!target[tt].hidden) &&
  714.                      (!target[tt].invisible) &&
  715.                      (!target[tt].friendly) &&
  716.                      (target[tt].range2 < TARG_MAXRANGE2) &&
  717.                      (tt != old) );
  718.             }
  719.  
  720.             if (ok)
  721.             {
  722.                 lock.target = tt;
  723.                 return;
  724.             }
  725.         }
  726.     }
  727.     else if (lock.type == LOCK_FRIENDLY)
  728.     {
  729.         for (t=lock.target+NTARGETS; t>lock.target; t--)
  730.         {
  731.             tt = t % NTARGETS;
  732.  
  733.             if ( (target[tt].age > 0.0) &&
  734.                 (!target[tt].hidden) &&
  735.                 (!target[tt].invisible) &&
  736.                 (target[tt].friendly) &&
  737.                 (target[tt].range2 < TARG_MAXRANGE2) &&
  738.                 (tt != old) )
  739.             {
  740.                 lock.target = tt;
  741.                 return;
  742.             }
  743.         }
  744.     }
  745.     else if (lock.type == LOCK_PLANET)
  746.     {
  747.         do
  748.         {
  749.             lock.target = (lock.target + NPLANETS - 1) % NPLANETS;
  750.         } while ( (planet[lock.target].is_moon &&
  751.                (planet[lock.target].range2 > (5000.0*5000.0)) ) ||
  752.                   planet[lock.target].hidden);
  753.         return;
  754.     }
  755.  
  756.     /* Nothing new to lock onto */
  757.     lock.target = old;
  758. }
  759.  
  760. CheckLock()
  761. /*
  762.  *  Sanity checks on the locked target
  763.  */
  764. {
  765.     int l;
  766.  
  767.     l = lock.target;
  768.  
  769.     if (lock.type == LOCK_PLANET)
  770.     {
  771.         /* Can't lock hidden planets */
  772.         if (planet[l].hidden) lock.target = -1;
  773.     }
  774.  
  775.     if (lock.type == LOCK_FRIENDLY)
  776.     {
  777.         if (!target[l].friendly) lock.type = LOCK_ENEMY;
  778.         if (target[l].hidden) lock.target = -1;
  779.         if (target[l].invisible) lock.target = -1;
  780.         if (target[l].age == 0.0) lock.target = -1;
  781.         if (target[l].range2 > TARG_MAXRANGE2) lock.target = -1;
  782.     }
  783.  
  784.     if (lock.type == LOCK_ENEMY)
  785.     {
  786.         if (target[l].friendly) lock.type = LOCK_FRIENDLY;
  787.         if (target[l].hidden) lock.target = -1;
  788.         if (target[l].invisible) lock.target = -1;
  789.         if (target[l].age == 0.0) lock.target = -1;
  790.  
  791.         if (!am_client && !am_server)
  792.         {
  793.             if (target[l].range2 > TARG_MAXRANGE2) lock.target = -1;
  794.         }
  795.     }
  796. }
  797.  
  798. static GLubyte lock_cursor[32] =
  799.     { 0xff, 0xff, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
  800.       0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
  801.       0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
  802.       0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xff, 0xff };
  803.  
  804. static GLubyte aim_cursor[8] =
  805.     { 0x81, 0x42, 0x24, 0x00, 0x00, 0x24, 0x42, 0x81 };
  806.  
  807. static GLubyte motion_cursor[8] =
  808.     { 0x18, 0x24, 0x42, 0x81, 0x81, 0x42, 0x24, 0x18 };
  809.  
  810. static GLubyte waypoint_cursor[8] =
  811.     { 0x3c, 0x00, 0x81, 0x81, 0x81, 0x81, 0x00, 0x3c };
  812.  
  813. DrawLock()
  814. /*
  815.  *  Draw the lock cursor
  816.  */
  817. {
  818.     char v;
  819.     double vtarg[3], v1[3];
  820.  
  821.     /* Don't bother if we're not locked */
  822.     if (lock.target == -1) return;
  823.  
  824.     /* Planets are special */
  825.     if (lock.type == LOCK_PLANET)
  826.     {
  827.         DrawPlanetLock();
  828.         return;
  829.     }
  830.  
  831.     /* Or if out of range */
  832.     if (!am_client && !am_server)
  833.     {
  834.         if (target[lock.target].range2 > TARG_MAXRANGE2) return;
  835.     }
  836.  
  837.     /* Select color */
  838.     if (target[lock.target].friendly)
  839.         glColor3d (0.0, 0.9, 0.0);
  840.     else
  841.         glColor3d (0.9, 0.0, 0.0);
  842.  
  843.     /* Set raster position, check if valid */
  844.     Vsub (v1, target[lock.target].pos, player.pos);
  845.     glRasterPos3dv (v1);
  846.     glGetBooleanv (GL_CURRENT_RASTER_POSITION_VALID, &v);
  847.     if (v)
  848.     {
  849.         /* Draw cursor */
  850.         glBitmap (16, 16, 8.0, 8.0, 0.0, 0.0, lock_cursor);
  851.     }
  852.  
  853.     /* Try to draw the aiming cursor */
  854.     if (target[lock.target].range2 > weapon[player.weapon].range2) return;
  855.     if (!target[lock.target].friendly)
  856.     {
  857.         if (!am_client && !am_server)
  858.         {
  859.             Vmul (v1, player.up, -0.01);
  860.             Vadd (v1, v1, player.pos);
  861.         }
  862.         else
  863.         {
  864.             Vset (v1, player.pos);
  865.         }
  866.         if (Aim (vtarg, v1, player.vel,
  867.                 target[lock.target].pos, target[lock.target].vel,
  868.                 weapon[player.weapon].speed) )
  869.         {
  870.             glColor3d (1.0, 1.0, 0.0);
  871.             Vsub (vtarg, vtarg, player.pos);
  872.             glRasterPos3dv (vtarg);
  873.             glGetBooleanv (GL_CURRENT_RASTER_POSITION_VALID, &v);
  874.             if (v)
  875.             {
  876.                 glBitmap (8, 8, 4.0, 4.0, 0.0, 0.0, aim_cursor);
  877.             }
  878.         }
  879.     }
  880. }
  881.  
  882. DrawPlanetLock()
  883. {
  884.     int p;
  885.     char v;
  886.     double v1[3];
  887.  
  888.     p = lock.target;
  889.  
  890.     if (planet[p].is_moon)
  891.         glColor3d (0.0, 1.0, 1.0);
  892.     else
  893.         glColor3d (0.0, 0.0, 1.0);
  894.  
  895.     /* Set raster postition, check if valid */
  896.     Vsub (v1, planet[p].pos, player.pos);
  897.     glRasterPos3dv (v1);
  898.     glGetBooleanv (GL_CURRENT_RASTER_POSITION_VALID, &v);
  899.     if (v)
  900.     {
  901.         /* Draw cursor */
  902.         glBitmap (16, 16, 8.0, 8.0, 0.0, 0.0, lock_cursor);
  903.     }
  904. }
  905.  
  906. DrawWaypoint()
  907. {
  908.     int w;
  909.     char v;
  910.     double v1[3];
  911.  
  912.     w = player.waypoint;
  913.     if (w == (-1)) return;
  914.  
  915.     glColor3d (0.8, 0.8, 1.8);
  916.  
  917.     /* Set raster postition, check if valid */
  918.     Vsub (v1, waypoint[w].pos, player.pos);
  919.     glRasterPos3dv (v1);
  920.     glGetBooleanv (GL_CURRENT_RASTER_POSITION_VALID, &v);
  921.     if (v)
  922.     {
  923.         /* Draw cursor */
  924.         glBitmap (8, 8, 3.0, 4.0, 0.0, 0.0, waypoint_cursor);
  925.     }
  926. }
  927.  
  928. DrawMotionCursors()
  929. /*
  930.  *  Show forward and reverse motion
  931.  */
  932. {
  933.     double vn[3];
  934.     char v;
  935.  
  936.     /* Not in arcade mode */
  937.     if (player.flightmodel == FLIGHT_ARCADE) return;
  938.  
  939.     /* Not unless we're moving */
  940.     if ( (0.0 == player.vel[0]) &&
  941.          (0.0 == player.vel[1]) &&
  942.          (0.0 == player.vel[2]) ) return;
  943.  
  944.     /* Forward cursor */
  945.     Vset (vn, player.vel);
  946.     Normalize (vn);
  947.  
  948.     glColor3d (0.0, 0.8, 0.0);
  949.     glRasterPos3dv (vn);
  950.     glGetBooleanv (GL_CURRENT_RASTER_POSITION_VALID, &v);
  951.     if (v)
  952.     {
  953.         /* Draw cursor */
  954.         glBitmap (8, 8, 4.0, 4.0, 0.0, 0.0, motion_cursor);
  955.     }
  956.  
  957.     /* Reverse cursor */
  958.     Vmul (vn, vn, -1.0);
  959.     
  960.     glColor3d (0.8, 0.0, 0.0);
  961.     glRasterPos3dv (vn);
  962.     glGetBooleanv (GL_CURRENT_RASTER_POSITION_VALID, &v);
  963.     if (v)
  964.     {
  965.         /* Draw cursor */
  966.         glBitmap (8, 8, 4.0, 4.0, 0.0, 0.0, motion_cursor);
  967.     }
  968. }
  969.  
  970. int Aim (vtarg, pos0, vel0, pos1, vel1, vel)
  971. double vtarg[3], pos0[3], vel0[3], pos1[3], vel1[3], vel;
  972. /*
  973.  *  Something at position pos0, with velocity vector vel0,
  974.  *  wants to shoot a missile with velocity "vel" at a target
  975.  *  at position pos1, moving with vector vel1.
  976.  *
  977.  *  Coord of place to shoot will be in vtarg, unless there is
  978.  *  no solution, in which case we return FALSE.
  979.  */
  980. {
  981.     double va[3], vb[3], A, B, C, D, t, t1, t2, rootD;
  982.  
  983.     /* va is position of target wrt shooter */
  984.     Vsub (va, pos1, pos0);
  985.  
  986.     /* vb is relative velocity of target */
  987.     Vsub (vb, vel1, vel0);
  988.  
  989.     /* If there's a solution, then there exists some t such
  990.        that target postion (va) plus t times its velocity (vb)
  991.        is as far away from shooter (origin) as a missile can
  992.        travel in time t (t*vel).  If you work it out you get
  993.        a pretty simple quadratic equation. */
  994.  
  995.     /* Set up coefficients of quadratic equation */
  996.     A = vb[0]*vb[0] + vb[1]*vb[1] + vb[2]*vb[2] - vel*vel;
  997.     B = 2.0*va[0]*vb[0] + 2.0*va[1]*vb[1] + 2.0*va[2]*vb[2];
  998.     C = va[0]*va[0] + va[1]*va[1] + va[2]*va[2];
  999.  
  1000.     /* This is the kind of stuff you thought you'd never
  1001.        use in real life, isn't it? */
  1002.  
  1003.     /* A == 0 is special case */
  1004.     if (A == 0.0)
  1005.     {
  1006.         /* A==0 && B==0 implies no solution */
  1007.         if (B == 0.0) return (0);
  1008.  
  1009.         /* Simple solution */
  1010.         t = (-C / B);
  1011.  
  1012.         /* Can't shoot missiles backwards */
  1013.         if (t < 0.0) return (0);
  1014.     }
  1015.     else
  1016.     {
  1017.         /* More complicated cases */
  1018.         /* Compute discriminant */
  1019.         D = B*B - 4.0*A*C;
  1020.  
  1021.         /* D < 0 implies no solution */
  1022.         if (D < 0.0) return (0);
  1023.  
  1024.         /* D == 0 implies one solution */
  1025.         if (D == 0.0)
  1026.         {
  1027.             t = -B / (2.0 * A);
  1028.             if (t <= 0.0) return (0);
  1029.         }
  1030.         else
  1031.         {
  1032.             /* Two solutions */
  1033.             rootD = sqrt (D);
  1034.             t1 = (-B + rootD) / (2.0 * A);
  1035.             t2 = (-B - rootD) / (2.0 * A);
  1036.  
  1037.             /* We need a non-negative solution */
  1038.             if ( (t1 < 0.0) && (t2 < 0.0) ) return (0);
  1039.  
  1040.             if (t1 < 0.0)
  1041.                 t = t2;
  1042.             else if (t2 < 0.0)
  1043.                 t = t1;
  1044.             else
  1045.             {
  1046.                 /* Both non-negative, choose lesser
  1047.                    (closer to target) */
  1048.                 if (t1 < t2)
  1049.                     t = t1;
  1050.                 else
  1051.                     t = t2;
  1052.             }
  1053.         }
  1054.     }
  1055.  
  1056.     /* Whew!  We have a solution in t now. */
  1057.     Vmul (vtarg, vb, t);
  1058.     Vadd (vtarg, vtarg, va);
  1059.     Vadd (vtarg, vtarg, pos0);
  1060.  
  1061.     return (1);
  1062. }
  1063.  
  1064. ArcadeThrottle()
  1065. /*
  1066.  *  Draw the throttle for arcade mode
  1067.  */
  1068. {
  1069.     double y;
  1070.  
  1071.     glEnable (GL_POLYGON_STIPPLE);
  1072.     glPolygonStipple (throt_stipple);
  1073.  
  1074.     /* First draw unshaded background */
  1075.     glColor3f (0.0, 0.25, 0.0);
  1076.     glBegin (GL_QUAD_STRIP);
  1077.     glVertex2d (hud.throt_min[0], hud.throt_min[1]);
  1078.     glVertex2d (hud.throt_max[0], hud.throt_min[1]);
  1079.     glVertex2d (hud.throt_min[0], hud.throt_max[1]);
  1080.     glVertex2d (hud.throt_max[0], hud.throt_max[1]);
  1081.     glEnd();
  1082.  
  1083.     if (player.throttle > MAX_THROTTLE)
  1084.     {
  1085.         y = hud.throt_min[1] + (player.throttle / MAX_WARP_THROTTLE) *
  1086.             (hud.throt_max[1] - hud.throt_min[1]);
  1087.     }
  1088.     else
  1089.     {
  1090.         y = hud.throt_min[1] + (player.throttle / MAX_THROTTLE) *
  1091.             (hud.throt_max[1] - hud.throt_min[1]);
  1092.     }
  1093.  
  1094.     glColor3f (0.0, 0.75, 0.0);
  1095.     glBegin (GL_QUAD_STRIP);
  1096.     glVertex2d (hud.throt_min[0], hud.throt_min[1]);
  1097.     glVertex2d (hud.throt_max[0], hud.throt_min[1]);
  1098.     glVertex2d (hud.throt_min[0], y);
  1099.     glVertex2d (hud.throt_max[0], y);
  1100.     glEnd();
  1101.  
  1102.     glDisable (GL_POLYGON_STIPPLE);
  1103.  
  1104.     /* If travelling at warp speed, put a border around throttle */
  1105.     if (player.throttle > MAX_THROTTLE)
  1106.     {
  1107.         glColor3f (0.5, 0.5, 0.0);
  1108.         glBegin (GL_LINE_LOOP);
  1109.         glVertex2d (hud.throt_min[0], hud.throt_min[1]);
  1110.         glVertex2d (hud.throt_max[0], hud.throt_min[1]);
  1111.         glVertex2d (hud.throt_max[0], hud.throt_max[1]);
  1112.         glVertex2d (hud.throt_min[0], hud.throt_max[1]);
  1113.         glEnd();
  1114.     }
  1115. }
  1116.  
  1117. Throttle()
  1118. /*
  1119.  *  Draw the throttle
  1120.  */
  1121. {
  1122.     double y;
  1123.  
  1124.     /* Arcade mode is special */
  1125.     if (player.flightmodel == FLIGHT_ARCADE)
  1126.     {
  1127.         ArcadeThrottle();
  1128.         return;
  1129.     }
  1130.  
  1131.     glEnable (GL_POLYGON_STIPPLE);
  1132.     glPolygonStipple (throt_stipple);
  1133.  
  1134.     /* First draw unshaded background */
  1135.     glColor3f (0.25, 0.0, 0.0);
  1136.     glBegin (GL_QUAD_STRIP);
  1137.     glVertex2d (hud.throt_min[0], hud.throt_min[1]);
  1138.     glVertex2d (hud.throt_max[0], hud.throt_min[1]);
  1139.     glVertex2d (hud.throt_min[0], hud.throt_mid[1]);
  1140.     glVertex2d (hud.throt_max[0], hud.throt_mid[1]);
  1141.     glEnd();
  1142.     glColor3f (0.0, 0.25, 0.0);
  1143.     glBegin (GL_QUAD_STRIP);
  1144.     glVertex2d (hud.throt_min[0], hud.throt_mid[1]);
  1145.     glVertex2d (hud.throt_max[0], hud.throt_mid[1]);
  1146.     glVertex2d (hud.throt_min[0], hud.throt_max[1]);
  1147.     glVertex2d (hud.throt_max[0], hud.throt_max[1]);
  1148.     glEnd();
  1149.  
  1150.     /* Now show the throttle */
  1151.     if (player.move_forward > 0.0)
  1152.     {
  1153.         glColor3f (0.0, 0.75, 0.0);
  1154.         y = hud.throt_mid[1] + player.move_forward *
  1155.             (hud.throt_max[1] - hud.throt_mid[1]);
  1156.         glBegin (GL_QUAD_STRIP);
  1157.         glVertex2d (hud.throt_min[0], hud.throt_mid[1]);
  1158.         glVertex2d (hud.throt_max[0], hud.throt_mid[1]);
  1159.         glVertex2d (hud.throt_min[0], y);
  1160.         glVertex2d (hud.throt_max[0], y);
  1161.         glEnd();
  1162.     }
  1163.     else if (player.move_backward > 0.0)
  1164.     {
  1165.         glColor3f (0.75, 0.0, 0.0);
  1166.         y = hud.throt_mid[1] - player.move_backward *
  1167.             (hud.throt_mid[1] - hud.throt_min[1]);
  1168.         glBegin (GL_QUAD_STRIP);
  1169.         glVertex2d (hud.throt_min[0], hud.throt_mid[1]);
  1170.         glVertex2d (hud.throt_max[0], hud.throt_mid[1]);
  1171.         glVertex2d (hud.throt_min[0], y);
  1172.         glVertex2d (hud.throt_max[0], y);
  1173.         glEnd();
  1174.     }
  1175.  
  1176.     glDisable (GL_POLYGON_STIPPLE);
  1177.  
  1178.     /* If travelling at warp speed, put a border around throttle */
  1179.     if (warpspeed)
  1180.     {
  1181.         glColor3f (0.5, 0.5, 0.0);
  1182.         glBegin (GL_LINE_LOOP);
  1183.         glVertex2d (hud.throt_min[0], hud.throt_min[1]);
  1184.         glVertex2d (hud.throt_max[0], hud.throt_min[1]);
  1185.         glVertex2d (hud.throt_max[0], hud.throt_max[1]);
  1186.         glVertex2d (hud.throt_min[0], hud.throt_max[1]);
  1187.         glEnd();
  1188.     }
  1189. }
  1190.  
  1191. TargetStuff()
  1192. /*
  1193.  *  Show stuff about the locked target
  1194.  */
  1195. {
  1196.     int t;
  1197.     double r;
  1198.     char buf[32];
  1199.  
  1200.     /* Planet lock is special */
  1201.     if (lock.type == LOCK_PLANET)
  1202.     {
  1203.         PlanetStuff();
  1204.         return;
  1205.     }
  1206.  
  1207.     if (-1 != (t = lock.target))
  1208.     {
  1209.         /* Bail if too far away */
  1210.         if (!am_client && !am_server)
  1211.         {
  1212.             if (target[lock.target].range2 > TARG_MAXRANGE2) return;
  1213.         }
  1214.  
  1215.         /* Target name */
  1216.         if (target[t].friendly)
  1217.             glColor3f (0.0, 0.8, 0.0);
  1218.         else
  1219.             glColor3f (0.8, 0.0, 0.0);
  1220.  
  1221.         glRasterPos2dv (hud.targ_name);
  1222.  
  1223.         /* Target range */
  1224.         r = sqrt (target[t].range2) * KM_TO_UNITS1;
  1225.         sprintf (buf, "%s:%2.0lf", target[t].name, r);
  1226.         Print (GLUT_BITMAP_HELVETICA_10, buf);
  1227.  
  1228.         /* Target shields */
  1229.         TargetShields (t);
  1230.     }
  1231. }
  1232.  
  1233. WaypointStuff()
  1234. {
  1235.     int w;
  1236.     double r, v[3];
  1237.     char buf[32];
  1238.  
  1239.     if (player.waypoint == (-1)) return;
  1240.  
  1241.     w = player.waypoint;
  1242.     glColor3f (0.8, 0.8, 0.8);
  1243.     glRasterPos2dv (hud.waypoint);
  1244.     Vsub (v, waypoint[w].pos, player.pos);
  1245.     r = Mag (v) * KM_TO_UNITS1;
  1246.     sprintf (buf, "%d:%2.0lf", w+1, r);
  1247.     Print (GLUT_BITMAP_HELVETICA_10, buf);
  1248. }
  1249.  
  1250. PlayerVel()
  1251. {
  1252.     double r;
  1253.     char buf[64];
  1254.  
  1255.     /* Player velocity */
  1256.     r = Mag (player.vel) * KM_TO_UNITS1;
  1257.  
  1258.     if (r == 0.0)
  1259.         glColor3f (0.0, 0.0, 0.8);
  1260.     else if (Dotp (player.view, player.vel) >= 0.0)
  1261.         glColor3f (0.0, 0.8, 0.0);
  1262.     else
  1263.         glColor3f (0.8, 0.0, 0.0);
  1264.  
  1265.     sprintf (buf, "%2.0lf", r);
  1266.     hud.vel[0] = hud.throt_min[0] - 5 - 
  1267.         glutBitmapLength (GLUT_BITMAP_HELVETICA_10, buf);
  1268.     glRasterPos2dv (hud.vel);
  1269.     Print (GLUT_BITMAP_HELVETICA_10, buf);
  1270. }
  1271.  
  1272. PlanetStuff()
  1273. {
  1274.     int p;
  1275.     double r;
  1276.     char buf[64];
  1277.  
  1278.     if (-1 == (p = lock.target)) return;
  1279.  
  1280.     if (planet[p].is_moon)
  1281.         glColor3d (0.0, 0.8, 0.8);
  1282.     else
  1283.         glColor3d (0.0, 0.0, 0.8);
  1284.  
  1285.     glRasterPos2dv (hud.targ_name);
  1286.  
  1287.     /* Planet range */
  1288.     r = (sqrt(planet[p].absrange2) - planet[p].radius) * KM_TO_UNITS1;
  1289.     sprintf (buf, "%s:%2.0lf", planet[p].name, r);
  1290.  
  1291.     Print (GLUT_BITMAP_HELVETICA_10, buf);
  1292. }
  1293.  
  1294. Shields()
  1295. /*
  1296.  *  Draw the shield status
  1297.  */
  1298. {
  1299.     float color[3];
  1300.     double y;
  1301.  
  1302.     glEnable (GL_POLYGON_STIPPLE);
  1303.     glPolygonStipple (throt_stipple);
  1304.  
  1305.     if (player.shields > player.maxshields*0.66)
  1306.     {
  1307.         color[0] = color[2] = 0.0;
  1308.         color[1] = 0.25;
  1309.     }
  1310.     else if (player.shields > player.maxshields*0.33)
  1311.     {
  1312.         color[0] = color[1] = 0.25;
  1313.         color[2] = 0.0;
  1314.     }
  1315.     else
  1316.     {
  1317.         color[0] = 0.25;
  1318.         color[1] = color[2] = 0.0;
  1319.     }
  1320.  
  1321.     y = hud.shields_min[1] +
  1322.         (player.shields / player.maxshields) *
  1323.         (hud.shields_max[1] - hud.shields_min[1]);
  1324.  
  1325.     /* First draw unshaded background */
  1326.     if (player.shields < player.maxshields)
  1327.     {
  1328.         glColor3fv (color);
  1329.         glBegin (GL_QUAD_STRIP);
  1330.         glVertex2d (hud.shields_min[0], y);
  1331.         glVertex2d (hud.shields_max[0], y);
  1332.         glVertex2d (hud.shields_min[0], hud.shields_max[1]);
  1333.         glVertex2d (hud.shields_max[0], hud.shields_max[1]);
  1334.         glEnd();
  1335.     }
  1336.  
  1337.     /* Now show the shields */
  1338.     color[0] *= 3.0;
  1339.     color[1] *= 3.0;
  1340.  
  1341.     glColor3fv (color);
  1342.     glBegin (GL_QUAD_STRIP);
  1343.     glVertex2d (hud.shields_min[0], hud.shields_min[1]);
  1344.     glVertex2d (hud.shields_max[0], hud.shields_min[1]);
  1345.     glVertex2d (hud.shields_min[0], y);
  1346.     glVertex2d (hud.shields_max[0], y);
  1347.     glEnd();
  1348.  
  1349.     glDisable (GL_POLYGON_STIPPLE);
  1350. }
  1351.  
  1352. ShowWeapon()
  1353. /*
  1354.  *  Show the current weapon
  1355.  */
  1356. {
  1357.     /* Set color depending if it's ready to fire */
  1358.     if (player.msl_idle >= weapon[player.weapon].idle)
  1359.     {
  1360.         glColor3f (0.8, 0.0, 0.8);
  1361.     }
  1362.     else
  1363.     {
  1364.         glColor3f (0.5, 0.5, 0.5);
  1365.     }
  1366.     glRasterPos2dv (hud.weapon);
  1367.     Print (GLUT_BITMAP_HELVETICA_10, weapon[player.weapon].name);
  1368. }
  1369.  
  1370. TargetShields (t)
  1371. int t;
  1372. /*
  1373.  *  Draw the target's shield status
  1374.  */
  1375. {
  1376.     float color[3];
  1377.     double y;
  1378.  
  1379.     glEnable (GL_POLYGON_STIPPLE);
  1380.     glPolygonStipple (throt_stipple);
  1381.  
  1382.     if (target[t].shields > target[t].maxshields*0.66)
  1383.     {
  1384.         color[0] = color[2] = 0.0;
  1385.         color[1] = 0.25;
  1386.     }
  1387.     else if (target[t].shields > target[t].maxshields*0.33)
  1388.     {
  1389.         color[0] = color[1] = 0.25;
  1390.         color[2] = 0.0;
  1391.     }
  1392.     else
  1393.     {
  1394.         color[0] = 0.25;
  1395.         color[1] = color[2] = 0.0;
  1396.     }
  1397.  
  1398.     y = hud.targshields_min[1] +
  1399.         (target[t].shields / target[t].maxshields) *
  1400.         (hud.targshields_max[1] - hud.targshields_min[1]);
  1401.  
  1402.     /* First draw unshaded background */
  1403.     if (target[t].shields < target[t].maxshields)
  1404.     {
  1405.         glColor3fv (color);
  1406.         glBegin (GL_QUAD_STRIP);
  1407.         glVertex2d (hud.targshields_min[0], y);
  1408.         glVertex2d (hud.targshields_max[0], y);
  1409.         glVertex2d (hud.targshields_min[0], hud.targshields_max[1]);
  1410.         glVertex2d (hud.targshields_max[0], hud.targshields_max[1]);
  1411.         glEnd();
  1412.     }
  1413.  
  1414.     /* Now show the shields */
  1415.     color[0] *= 3.0;
  1416.     color[1] *= 3.0;
  1417.  
  1418.     glColor3fv (color);
  1419.     glBegin (GL_QUAD_STRIP);
  1420.     glVertex2d (hud.targshields_min[0], hud.targshields_min[1]);
  1421.     glVertex2d (hud.targshields_max[0], hud.targshields_min[1]);
  1422.     glVertex2d (hud.targshields_min[0], y);
  1423.     glVertex2d (hud.targshields_max[0], y);
  1424.     glEnd();
  1425.  
  1426.     glDisable (GL_POLYGON_STIPPLE);
  1427. }
  1428.  
  1429.