home *** CD-ROM | disk | FTP | other *** search
/ Black Art of 3D Game Programming / Black_Art_of_3D_Game_Programming.iso / source / borland / chap_18 / krk.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-29  |  140.0 KB  |  4,974 lines

  1.  
  2. // KRK.C - Version 1.0, Andre' LaMothe
  3.  
  4. // I N C L U D E S ///////////////////////////////////////////////////////////
  5.  
  6. #include <io.h>
  7. #include <conio.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <dos.h>
  11. #include <bios.h>
  12. #include <fcntl.h>
  13. #include <memory.h>
  14. #include <malloc.h>
  15. #include <math.h>
  16. #include <string.h>
  17.  
  18. // include all of our stuff
  19.  
  20. #include "black3.h"
  21. #include "black4.h"
  22. #include "black5.h"
  23. #include "black6.h"
  24. #include "black8.h"
  25. #include "black9.h"
  26.  
  27. #include "black18.h"    // the newest version of the 3-D library
  28.  
  29. // D E F I N E S /////////////////////////////////////////////////////////////
  30.  
  31. // defines for the radar scanner
  32.  
  33. #define SCANNER_X               12      // position of scanner
  34. #define SCANNER_Y               135
  35. #define SCANNER_WIDTH           57      // size of scanner area
  36. #define SCANNER_HEIGHT          42
  37.  
  38. // commands that can be sent to the scanner engine
  39.  
  40. #define SCANNER_CLEAR           0       // clear the scanner
  41. #define SCANNER_LOGO            1       // draw the KRK logo
  42. #define SCANNER_ERASE_BLIPS     2       // erase all the radar blips
  43. #define SCANNER_DRAW_BLIPS      3       // draw all the radar blips
  44.  
  45. // defines for the general multi function tactical display
  46.  
  47. #define TACTICAL_X              249     // position of tactical
  48. #define TACTICAL_Y              134
  49. #define TACTICAL_WIDTH          57      // size of tactical
  50. #define TACTICAL_HEIGHT         34
  51.  
  52. // different modes of operation for the tactical display
  53.  
  54. #define TACTICAL_MODE_STS       0       // ship status mode
  55. #define TACTICAL_MODE_HULL      1       // hull damage report
  56. #define TACTICAL_MODE_OFF       2       // tactical display off
  57.  
  58. // these are the different icon indexes for the tactical display
  59.  
  60. #define TACTICAL_ICON_BLANK     0       // a black square
  61. #define TACTICAL_ICON_KRK       1       // the kill or be killed logo
  62. #define TACTICAL_ICON_GAUGE     2       // the gauge set
  63. #define TACTICAL_ICON_TALLON    3       // the tallon hull
  64. #define TACTICAL_ICON_SLIDER    4       // the slider hull
  65.  
  66. #define TACTICAL_ICON_WIDTH     38      // size of sprite bitmaps for tactical
  67. #define TACTICAL_ICON_HEIGHT    28
  68.  
  69. // commands the drawing engine of the tactical display
  70.  
  71. #define TACTICAL_CLEAR          0       // clear the tactical
  72. #define TACTICAL_DRAW           1       // draw the tactical
  73. #define TACTICAL_UPDATE         2       // refresh the tactical
  74.  
  75. // the main menu selection system defines
  76.  
  77. #define SELECT_BOX_SX           104     // starting position of selection boxes
  78. #define SELECT_BOX_SY           58
  79. #define SELECT_BOX_DY           19      // vertical change between boxes
  80. #define SELECT_BOX_WIDTH        94      // dimensions of selection boxes
  81. #define SELECT_BOX_HEIGHT       10
  82.  
  83. #define SELECT_LGT_SX           86      // starting position of little lights by box
  84. #define SELECT_LGT_SY           61
  85. #define SELECT_LGT_DY           19      // vertical change to next light
  86. #define SELECT_LGT_WIDTH        4       // dimensions of light
  87. #define SELECT_LGT_HEIGHT       4
  88.  
  89. #define MAX_SELECTION           3       // maximum number of selections
  90.  
  91. // defines for the background moutain scape
  92.  
  93. #define MOUNTAIN_HEIGHT         43      // height of mountain
  94. #define MOUNTAIN_WIDTH          320     // total width of backdrop
  95. #define MOUNTAIN_Y_POS          56      // starting y position to map down backdrop
  96.  
  97. // starting position of the intro startup sequence
  98.  
  99. #define START_MESS_X            2
  100. #define START_MESS_Y            8
  101.  
  102. // position of alpha numeric input area
  103.  
  104. #define DISPLAY_X              0
  105. #define DISPLAY_Y              0
  106.  
  107.  
  108. // defines for the aliens and logic
  109.  
  110. #define ALIEN_DEAD              0      // alien is dead
  111. #define ALIEN_DYING             1      // alien is dying
  112. #define ALIEN_NEW_STATE         2      // alien wishes a new state
  113. #define ALIEN_ATTACK            3      // alien is attacking player
  114. #define ALIEN_RANDOM            4      // alien is moving in random directions
  115. #define ALIEN_EVADE             5      // alien is evading player
  116. #define ALIEN_STOP              6      // alien is at a full stop
  117. #define ALIEN_TURN              7      // alien is making a turn
  118.  
  119. #define NUM_ALIENS              4      // total number of aliens in game
  120.  
  121. #define ALIEN_TALLON            0      // id for an alien with a tallon class ship
  122. #define ALIEN_SLIDER            1      // is for an alien with a slider class ship
  123.  
  124. // dimesions of the game world
  125.  
  126. #define GAME_MAX_WORLD_X        7500    // x dimensions
  127. #define GAME_MIN_WORLD_X        -7500
  128.  
  129. #define GAME_MAX_WORLD_Y        400     // y dimensions
  130. #define GAME_MIN_WORLD_Y        -400
  131.  
  132. #define GAME_MAX_WORLD_Z        7500    // z dimensions
  133. #define GAME_MIN_WORLD_Z        -7500
  134.  
  135. #define GUN_HEIGHT              -10    // height of weapon system from ground level
  136.  
  137. #define NUM_DYNAMIC              3     // total number of dynamic game objects
  138.  
  139. #define NUM_MISSILES             12    // maxium number of missiles in the game
  140.  
  141. // possible missle states
  142.  
  143. #define MISSILE_INACTIVE         0     // an inactive missile
  144. #define MISSILE_ACTIVE           1     // an active and moving moving
  145.  
  146. #define MAX_PLAYER_MISSILES      6     // maximum number of missiles player
  147.                                        // can fire at once
  148.  
  149. // used to track who fired a missile, helps for collision detection
  150.  
  151. #define NO_OWNER                 0     // no owner, can cause damage to anyone
  152. #define PLAYER_OWNER             1     // the player fired it
  153. #define ALIEN_OWNER              2     // an alien fired it
  154. #define OTHER_OWNDER             3     // an unknown fired it
  155.  
  156. // these are used to index into the 3-D models
  157.  
  158. #define MISSILES_TEMPLATE        0     // the missile model
  159. #define TALLONS_TEMPLATE         1     // the tallon model
  160. #define SLIDERS_TEMPLATE         2     // the slider model
  161.  
  162.  
  163. // these define the number of each object type
  164.  
  165. #define NUM_STATIONARY           6    // total number of stationary object types
  166.  
  167. #define NUM_OBSTACLES_1          32   // number of rocks
  168. #define NUM_OBSTACLES_2          32   // number of crystals
  169. #define NUM_BARRIERS             8    // number of lasrer barriers
  170. #define NUM_TOWERS               4    // number of control towers
  171. #define NUM_STATIONS             1    // number of power stations
  172. #define NUM_TELEPODS             4    // number of telepods
  173.  
  174. // these are the model indices
  175.  
  176. #define OBSTACLES_1_TEMPLATE     0    // the rock model
  177. #define OBSTACLES_2_TEMPLATE     1    // the crystal model
  178. #define BARRIERS_TEMPLATE        2    // the laser barrier model
  179. #define TOWERS_TEMPLATE          3    // the control tower model
  180. #define STATIONS_TEMPLATE        4    // the power station model
  181. #define TELEPODS_TEMPLATE        5    // the telepod model
  182.  
  183. // digital sound system
  184.  
  185. #define KRKMIS_VOC                  0  // the sound a missile makess
  186. #define KRKEMIS_VOC                 1  // the sound an enemy missile makes
  187. #define KRKTAC_VOC                  2  // tactical engaging
  188. #define KRKSCN_VOC                  3  // scanner engaging
  189. #define KRKHUD_VOC                  4  // hud engaging
  190. #define KRKPOW_VOC                  5  // powering up
  191. #define KRKKEY_VOC                  6  // a key was pressed
  192. #define KRKEX1_VOC                  7  // the alien explosion
  193. #define KRKEX2_VOC                  8  // the blast of an alien
  194.  
  195. #define NUM_SOUND_FX                9      // the number of sound fx loaded in
  196.  
  197. // color fx registers for a multitude of objects
  198.  
  199. #define SHIELDS_REG                 232    // the insrument panel shields color register
  200. #define RADAR_REG                   233    // the insrument panel radar color register
  201. #define COMM_REG                    234    // the insrument panel communications color register
  202. #define HUD_REG                     235    // the insrument panel hud color register
  203.  
  204. #define STS_REG                     236    // the insrument panel ship status color register
  205. #define HULL_REG                    237    // the insrument panel hull color register
  206. #define OFF_REG                     238    // the insrument panel off color register
  207.  
  208. #define PLAYERS_WEAPON_FIRE_REG     239    // the little light that glows when the player fires
  209.  
  210. #define ENGINES_TALLON_REG          240    // the engine flicker for tallons
  211. #define ENGINES_SLIDER_REG          241    // the engine flicker for sliders
  212. #define BARRIERS_REG                242    // the laser barriers
  213. #define SHIELDS_FLICKER_REG         243    // the shields (not implemented)
  214.  
  215. #define START_PANEL_REG             224    // the start register for the main menu fx
  216. #define END_PANEL_REG               (224+7)// the end register for the main menu fx
  217.  
  218. #define SELECT_REG                  254    // the glowing currently selected main menu item
  219.  
  220. #define ALIEN_EXPL_BASE_REG         244    // the aliens that are killed all
  221.                                            // get allocated a color register at this base
  222.  
  223. // defines for the grdient sky and ground
  224.  
  225. #define SKY_COLOR_1                 50     // reds
  226. #define SKY_COLOR_2                 52
  227. #define SKY_COLOR_3                 53
  228.  
  229. #define GND_COLOR_1                 216    // browns
  230. #define GND_COLOR_2                 215
  231. #define GND_COLOR_3                 214
  232.  
  233. // music system
  234.  
  235. #define NUM_INTRO_SEQUENCES    11 // the number of elements in intro music score
  236. #define NUM_GAME_SEQUENCES     18 // the number of elements in game music score
  237.  
  238. // defines for briefing instructions
  239.  
  240. #define NUM_PAGES              8
  241. #define NUM_LINES_PAGE         17
  242. #define NUM_SHIP_SPECS         7
  243.  
  244.  
  245. // state of the game itself
  246.  
  247. #define GAME_SETUP             0   // the game is in the setup mode
  248. #define GAME_LINKING           1   // the communications link is being established
  249. #define GAME_RUNNING           2   // the game is running
  250. #define GAME_PAUSED            3   // the game is paused (not implemented)
  251. #define GAME_OVER              4   // what do you think
  252.  
  253. // general object states
  254.  
  255. #define DEAD                   0   // these are general states for any
  256. #define ALIVE                  1   // object
  257. #define DYING                  2
  258.  
  259. // defines for the ship state machine
  260.  
  261. #define SHIP_STABLE            0   // the ship is stable
  262. #define SHIP_HIT               1   // the ship has been hit
  263. #define SHIP_TELEPORT          2   // the ship is teleporting (not implemented)
  264.  
  265. #define SHIP_FLAME_COLOR       96  // odd ball, the starting base color register
  266.                                    // that is used to flicker the screen to simulate
  267.                                    // a torpedo blast
  268.  
  269. // used to indicate which ship type the player is using
  270.  
  271. #define PLAYER_TALLON          0
  272. #define PLAYER_SLIDER          1
  273.  
  274. // defines for setup selections
  275.  
  276. #define SETUP_CHALLENGE             0
  277. #define SETUP_SELECT_MECH           1
  278. #define SETUP_RULES                 2
  279. #define SETUP_EXIT                  3
  280.  
  281. #define NUM_SETUP                   4   // number of setup choices
  282.  
  283. // size of the "tech" font used in intro
  284.  
  285. #define TECH_FONT_WIDTH             4   // width of high tech font
  286. #define TECH_FONT_HEIGHT            7   // height of high tech font
  287. #define NUM_TECH_FONT               64  // number of characters in tech font
  288.  
  289. // S T R U C T U R E S ///////////////////////////////////////////////////////
  290.  
  291. // this structure is used to replicate static similar objects based on the
  292. // same model
  293.  
  294. typedef struct fixed_obj_typ
  295.         {
  296.         int state;        // state of object
  297.         int rx,ry,rz;     // rotation rate of object
  298.         float x,y,z;      // position of object
  299.  
  300.         } fixed_obj, *fixed_obj_ptr;
  301.  
  302. // this structure is used for all projectiles in the game, similar
  303. // to the above structure except with added fields for animation, collision,
  304. // etc.
  305.  
  306. typedef struct proj_obj_typ
  307.         {
  308.  
  309.         int state;            // state of projectile
  310.         int owner;            // owner of projectile
  311.         int lifetime;         // lifetime of projectile
  312.  
  313.         vector_3d direction;  // direction and velocity of projectile
  314.  
  315.         float x,y,z;          // position of projectile
  316.  
  317.         } missile_obj, proj_obj, *missile_obj_ptr, *proj_obj_ptr;
  318.  
  319. // this data structure is used to hold and alien attacker
  320.  
  321. typedef struct alien_typ
  322.         {
  323.         int state;                // state of alien
  324.         int counter_1;            // counters
  325.         int counter_2;
  326.         int threshold_1;          // thresholds for counters
  327.         int threshold_2;
  328.         int aux_1;                // auxialliary variables for whatever
  329.         int aux_2;
  330.         int color_reg;            // color register of alien during explosion
  331.         RGB_color color;          // actual rgb color of explosion
  332.         int type;                 // type of alien
  333.         int angular_heading;      // curr angle about y axis, i.e. yaw
  334.  
  335.         int speed;                // speed of ship
  336.  
  337.         vector_3d direction;      // the current trajectory vector
  338.  
  339.         float x,y,z;              // position of alien
  340.  
  341.         } alien, *alien_ptr;
  342.  
  343. // P R O T O T Y P E S //////////////////////////////////////////////////////
  344.  
  345. void Select_Mech(void);
  346.  
  347. void Misc_Color_Init(void);
  348.  
  349. void Tallon_Color_FX(void);
  350.  
  351. void Slider_Color_FX(void);
  352.  
  353. void Barrier_Color_FX(void);
  354.  
  355. void Draw_Hud(void);
  356.  
  357. void Draw_Tactical(int command);
  358.  
  359. void Load_Tactical(void);
  360.  
  361. void Draw_Scanner(int command);
  362.  
  363. void Init_Missiles(void);
  364.  
  365. void Move_Missiles(void);
  366.  
  367. void Draw_Missiles(void);
  368.  
  369. int Start_Missile(int owner,
  370.                   vector_3d_ptr pos,
  371.                   vector_3d_ptr dir,
  372.                   int speed,
  373.                   int lifetime);
  374.  
  375. void Init_Aliens(void);
  376.  
  377. void Process_Aliens(void);
  378.  
  379. void Draw_Aliens(void);
  380.  
  381. void Draw_Background(int mountain_pos);
  382.  
  383. void Draw_Box(int x1,int y1,int x2, int y2,int color);
  384.  
  385. void Tech_Print(int x,int y,char *string,unsigned char far *destination);
  386.  
  387. void Font_Engine_1(int x,int y,
  388.                    int font,int color,
  389.                    char *string,unsigned char far *destination);
  390.  
  391. void Panel_FX(int reset);
  392.  
  393. void Intro_Planet(void);
  394.  
  395. void Closing_Screen(void);
  396.  
  397. void Intro_Waite(void);
  398.  
  399. void Intro_KRK(void);
  400.  
  401. void Intro_Controls(void);
  402.  
  403. void Intro_Briefing(void);
  404.  
  405. void Reset_System(void);
  406.  
  407. void Music_Init(void);
  408.  
  409. void Music_Close(void);
  410.  
  411. void Digital_FX_Init(void);
  412.  
  413. void Digital_FX_Close(void);
  414.  
  415. int Digital_FX_Play(int the_effect, int priority);
  416.  
  417. int Parse_Commands(int argc, char **argv);
  418.  
  419. void Draw_Stationary_Objects(void);
  420.  
  421. void Set_3D_View(void);
  422.  
  423. void Load_3D_Objects(void);
  424.  
  425. // G L O B A L S  ////////////////////////////////////////////////////////////
  426.  
  427. object static_obj[NUM_STATIONARY];      // there are six basic stationary object types
  428.  
  429. fixed_obj obstacles_1[NUM_OBSTACLES_1]; // general obstacles, rocks etc.
  430. fixed_obj obstacles_2[NUM_OBSTACLES_2]; // general obstacles, rocks etc.
  431.  
  432. fixed_obj barriers[NUM_BARRIERS];       // boundary universe boundaries
  433. fixed_obj towers[NUM_TOWERS];           // the control towers
  434. fixed_obj stations[NUM_STATIONS];       // the power stations
  435. fixed_obj telepods[NUM_TELEPODS];       // the teleporters
  436.  
  437.  
  438. object dynamic_obj[NUM_DYNAMIC];        // this array holds the models
  439.                                         // for the dynamic game objects
  440.  
  441. alien aliens[NUM_ALIENS];               // take a wild guess!
  442.  
  443. missile_obj missiles[NUM_MISSILES];     // holds the missiles
  444.  
  445. int active_player_missiles = 0;         // how many missiles has player activated
  446.  
  447. int total_active_missiles = 0;          // total active missiles
  448.  
  449. layer mountains;              // the background mountains
  450.  
  451. pcx_picture image_pcx,        // general PCX image used to load background and imagery
  452.             image_controls;   // this holds the controls screen
  453.  
  454. sprite tactical_spr,          // holds the images for the tactical displays
  455.        buttons_spr;           // holds the images for the control buttons
  456.  
  457. RGB_color color_1,color_2;    // used for temporaries during color rotation
  458.  
  459. RGB_palette game_palette;     // this will hold the startup system palette
  460.  
  461. bitmap tech_font[NUM_TECH_FONT];   // the tech font bitmaps
  462.  
  463. int game_state = GAME_SETUP;       // the overall state of the game
  464.  
  465. int scanner_state  = 0,            // state of scanner
  466.     hud_state      = 0,
  467.     tactical_state = TACTICAL_MODE_OFF;
  468.  
  469. int ship_pitch  = 0,   // current direction of ship
  470.     ship_yaw    = 0,   // not used
  471.     ship_roll   = 0,   // not used
  472.     ship_speed  = 0,   // speed of ship
  473.     ship_energy = 50,  // current energy of ship
  474.     ship_damage = 0,   // current damage up to 50 points
  475.     ship_message = 0,  // current message to ship state machine
  476.     ship_timer   = 0,  // a little timer
  477.     ship_kills   = 0,  // how many bad guys has player killed
  478.     ship_deaths  = 0;  // how many times has player been killed
  479.  
  480. vector_3d unit_z          = {0,0,1,1},  // a unit vector in the Z direction
  481.           ship_direction  = {0,0,1,1};  // the ships direction
  482.  
  483. int players_ship_type = PLAYER_TALLON;  // the player starts off with a tallon
  484.  
  485. // musical sequence information
  486.  
  487. int music_enabled   = 0,      // flags that enable music and sound FX
  488.     digital_enabled = 0;
  489.  
  490. int digital_FX_priority = 10; // the priority tracker of the current effect
  491.  
  492. int intro_sequence[] = {0+12,1+12,2+12,3+12,1+12,2+12,3+12,2+12,3+12,1+12,
  493.                         2+12,3+12,2+12,2+12};
  494.  
  495. int intro_seq_index  = 0; // starting intro index number of sequence to be played
  496.  
  497. int game_sequence[]  = {11,8,2,3,1,2,5,8,6,1,0,2,4,5,2,1,0,3,4,8};
  498.  
  499. int game_seq_index   = 0; // starting game index number of sequence to be played
  500.  
  501. music song;    // the music structure
  502.  
  503. // sound fx stuff
  504.  
  505. sound digital_FX[NUM_SOUND_FX];
  506.  
  507. // basic colors
  508.  
  509. RGB_color  bright_red   = {63,0,0},    // bright red
  510.            bright_blue  = {0,0,63},    // bright blue
  511.            bright_green = {0,63,0},    // bright green
  512.  
  513.            medium_red   = {48,0,0},    // medium red
  514.            medium_blue  = {0,0,48},    // medium blue
  515.            medium_green = {0,48,0},    // medium green
  516.  
  517.            dark_red     = {32,0,0},    // dark red
  518.            dark_blue    = {0,0,32},    // dark blue
  519.            dark_green   = {0,32,0},    // dark green
  520.  
  521.                   black = {0,0,0},     // pure black
  522.                   white = {63,63,63},  // pure white
  523.  
  524.            color_1,color_2,color_3;    // general color variables
  525.  
  526. // the instruction pages
  527.  
  528. char *instructions[]={"KILL OR BE KILLED                  ",
  529.                       "                                   ",
  530.                       "INTERGALACTIC BATTLE FEDERATION    ",
  531.                       "THESE RULES APPLY TO ALL ENTRIES   ",
  532.                       "                                   ",
  533.                       "1. YOU MAY FREELY DESTROY ALL AND  ",
  534.                       "   ANY ENEMY THAT YOU MAY MEET UP  ",
  535.                       "   WITH.                           ",
  536.                       "                                   ",
  537.                       "2. ANY PARTICIPANT EXHIBITING MERCY",
  538.                       "   IN ANY FORM WILL BE SUMMARILY   ",
  539.                       "   TERMINATED. YOU MUST KILL!      ",
  540.                       "                                   ",
  541.                       "3. LEAVING THE GAME GRID WHILE     ",
  542.                       "   THERE ARE ANY OPPONENTS ALIVE IS",
  543.                       "   FORBIDDEN.                      ",
  544.                       "                1                  ",
  545.  
  546.                       "PLAYING THE GAME                   ",
  547.                       "                                   ",
  548.                       "AT THE MAIN MENU SELECT THE BATTLE ",
  549.                       "MECH THAT YOU WISH TO PLAY WITH    ",
  550.                       "BY USING THE (SELECT MECH) OPTION  ",
  551.                       "ITEM. YOU WILL THEN BE SENT TO     ",
  552.                       "THE HOLOGRAPHIC SPECIFICATION AREA.",
  553.                       "                                   ",
  554.                       "USE THE RIGHT AND LEFT ARROW KEYS  ",
  555.                       "TO VIEW DIFFERENT MECHS. WHEN YOU  ",
  556.                       "ARE SATIFIED THEN PRESS (ENTER).   ",
  557.                       "                                   ",
  558.                       "TO EXIT WITHOUT MAKING A SELECTION ",
  559.                       "PRESS (ESC).                       ",
  560.                       "                                   ",
  561.                       "                                   ",
  562.                       "                2                  ",
  563.  
  564.                       "AFTER YOU HAVE SELECTED A MECH THEN",
  565.                       "SELECT THE (CHALLENGE) ITEM OF THE ",
  566.                       "MAIN MENU. YOU WILL ENTER INTO THE ",
  567.                       "GAME AREA AT ITS EXACT CENTER.     ",
  568.                       "                                   ",
  569.                       "THE GAME AREA CONSISTS OF OBSTACLES",
  570.                       "SUCH AS ROCKS AND CRYSTAL GROWTHS. ",
  571.                       "                                   ",
  572.                       "AROUND THE PERIMETER OF THE GAME   ",
  573.                       "GRID IS AN LASER BARRIER SYSTEM    ",
  574.                       "POWERED BY LARGE BLACK MONOLITHS   ",
  575.                       "WITH GREEN BEACONS. STAY AWAY FROM ",
  576.                       "THESE IF POSSIBLE. AS NOTED ABOVE  ",
  577.                       "YOU WILL BE POSITIONED AT THE EXACT",
  578.                       "CENTER OF THE GAME GRID. IN FACT,  ",
  579.                       "THE POSITION YOU ARE STARTED AT    ",
  580.                       "                3                  ",
  581.  
  582.                       "IS THE LOCATION OF THE MAIN POWER  ",
  583.                       "SOURCE FOR THE GAME GRID. IT MAY BE",
  584.                       "POSSIBLE TO RE-CHARGE BY DRIVING   ",
  585.                       "OVER THIS ROTATING ENERGY SOURCE.  ",
  586.                       "                                   ",
  587.                       "HOWEVER, THERE ARE FOUR COM TOWERS ",
  588.                       "OVERLOOKING THIS CENTRAL POWER     ",
  589.                       "STATION AND ENTRIES TRYING TO STEEL",
  590.                       "POWER MAY BE DEALT WITH...         ",
  591.                       "                                   ",
  592.                       "FINALLY TO MAKE THE GAME MORE      ",
  593.                       "INTERESTING THERE ARE FOUR TELEPODS",
  594.                       "LOCATED AT THE FOUR CORNERS OF THE ",
  595.                       "GAME GRID. TO TELEPORT TO ANOTHER  ",
  596.                       "POD, SIMPLY NAVIGATE UNDER ONE OF  ",
  597.                       "THE PODS.                          ",
  598.                       "                4                  ",
  599.  
  600.                       "CONTROLING THE SHIP                ",
  601.                       "                                   ",
  602.                       "BOTH SHIPS HAVE THE SAME CONTROLS  ",
  603.                       "THEREFORE THE FOLLOWING EXPLAINA-  ",
  604.                       "TION IS VALID FOR BOTH TALLON AND  ",
  605.                       "SLIDER PILOTS.                     ",
  606.                       "                                   ",
  607.                       "INFORMATION DISPLAYS               ",
  608.                       "                                   ",
  609.                       "THE SHIPS ARE FITTED WITH THE      ",
  610.                       "FOLLOWING DISPLAYS.                ",
  611.                       "                                   ",
  612.                       "1. SCANNERS                        ",
  613.                       "2. HEADS UP DISPLAY (HUD)          ",
  614.                       "3. MULTI-FUNCTION DISPLAY (MFD)    ",
  615.                       "                                   ",
  616.                       "                5                  ",
  617.  
  618.                       "ENGAGING THE DISPLAYS              ",
  619.                       "                                   ",
  620.                       " SCANNER....S TOGGLES              ",
  621.                       " HUD........H TOGGLES              ",
  622.                       " MFD........T TO SELECT VARIOUS    ",
  623.                       "              DATA OUTPUTS.        ",
  624.                       "                                   ",
  625.                       "THE SCANNER IS LOCATED ON THE LEFT ",
  626.                       "MAIN VIEW SCREEN AND THE MFD IS    ",
  627.                       "LOCATED ON THE RIGHT MAIN VIEWING  ",
  628.                       "SCREEN.                            ",
  629.                       "                                   ",
  630.                       "THE SCANNER REPRESENTS YOU AS A    ",
  631.                       "BLUE BLIP AND YOU ENEMIES AS RED.  ",
  632.                       "OTHER IMPORTANT OBJECTS ARE ALSO   ",
  633.                       "SCANNED AND DISPLAYED.             ",
  634.                       "                6                  ",
  635.  
  636.                       "THE MFD IS CURRENTLY FIT TO DISPLAY",
  637.                       "TWO MAIN DATA SETS. THE FIRST IS   ",
  638.                       "THE SHIPS SPEED, DAMAGE AND ENERGY ",
  639.                       "IN LINEAR GRAPHS AND THE SECOND IS ",
  640.                       "AN OUTSIDE HULL DAMAGE SYSTEM.     ",
  641.                       "                                   ",
  642.                       "THE HUD IS A STANDARD POSITION,    ",
  643.                       "TRAJECTORY AND SPEED INDICATOR.    ",
  644.                       "                                   ",
  645.                       "MOTION AND WEAPONS CONTROL         ",
  646.                       "                                   ",
  647.                       "TO ROTATE THE SHIP RIGHT AND LEFT  ",
  648.                       "USE THE RIGHT AND LEFT ARROW KEYS. ",
  649.                       "                                   ",
  650.                       "TO INCREASE FORWARD THRUST USE THE ",
  651.                       "UP ARROW AND TO DECREASE THRUST USE",
  652.                       "                7                  ",
  653.  
  654.  
  655.                       "THE DOWN ARROW.                    ",
  656.                       "                                   ",
  657.                       "TO FIRE THE PULSE CANNON PRESS THE ",
  658.                       "SPACE BAR.                         ",
  659.                       "                                   ",
  660.                       "TO EXIT THE GAME PRESS ESCAPE.     ",
  661.                       "                                   ",
  662.                       "HAVE FUN AND REMEMBER:             ",
  663.                       "                                   ",
  664.                       "KILL OR BE KILLED!!!               ",
  665.                       "                                   ",
  666.                       "                                   ",
  667.                       "                                   ",
  668.                       "                                   ",
  669.                       "                                   ",
  670.                       "                                   ",
  671.                       "           END OF FILE             ",};
  672.  
  673.  
  674. // specification for the tallon
  675.  
  676. char *tallon_specs[] = {"MASS:      2567 KS        ",
  677.                         "LENGTH:    25.3 M         ",
  678.                         "HEAT DIS:  2.3 E.S        ",
  679.                         "WEAPONS:   POSITRON PLASMA",
  680.                         "SHIELDS:   STANDARD E-MAG ",
  681.                         "MAX SPD:   50 M.S         ",
  682.                         "ANG VEL:   72 D.S         ",
  683.                         "PROP UNIT: FUSION PULSE   "};
  684.  
  685. // specifications for the slider
  686.  
  687. char *slider_specs[] = {"MASS:      2245 KS        ",
  688.                         "LENGTH:    22.3 M         ",
  689.                         "HEAT DIS:  3.4 E.S        ",
  690.                         "WEAPONS:   POSITRON PLASMA",
  691.                         "SHIELDS:   STANDARD E-MAG ",
  692.                         "MAX SPD:   45 M.S         ",
  693.                         "ANG VEL:   80 D.S         ",
  694.                         "PROP UNIT: FUSION PULSE   "};
  695.  
  696. // F U N C T I O N S ////////////////////////////////////////////////////////
  697.  
  698. void Select_Mech(void)
  699. {
  700. // this function allows the user to select a ship via the keyboard
  701. // the function draw the ship in wire frame, displays the specifications
  702. // of the ship and then allows the user to select or escape
  703.  
  704. int done=0,               // event loop exit flag
  705.     current_ship_type,    // current displayed ship
  706.     index;                // looping variable
  707.  
  708. // set current ship to the actual one player is using
  709.  
  710. current_ship_type = players_ship_type;
  711.  
  712. // clear the screen
  713.  
  714. Fill_Screen(0);
  715.  
  716. // make sure user isn't hitting the enter key still
  717.  
  718. while(keys_active);
  719.  
  720. // enter into main event loop
  721.  
  722. while(!done)
  723.      {
  724.      // clear the double buffer
  725.  
  726.      Fill_Double_Buffer_32(0);
  727.  
  728.      // get user input
  729.  
  730.      if (keys_active)
  731.         {
  732.  
  733.         // test for various inputs
  734.  
  735.         if (keyboard_state[MAKE_RIGHT])
  736.            {
  737.            // move to next ship
  738.  
  739.            // click the next button
  740.  
  741.            if (++current_ship_type==2)
  742.               current_ship_type=0;
  743.  
  744.            // make a key sound
  745.  
  746.            Digital_FX_Play(KRKKEY_VOC,3);
  747.  
  748.            } // end if
  749.         else
  750.         if (keyboard_state[MAKE_LEFT])
  751.            {
  752.            // move to previous ship
  753.  
  754.            // click the previous button
  755.  
  756.            if (--current_ship_type<0)
  757.               current_ship_type=1;
  758.  
  759.            // make a key sound
  760.  
  761.            Digital_FX_Play(KRKKEY_VOC,3);
  762.  
  763.            } // end if
  764.         else
  765.         if (keyboard_state[MAKE_ENTER])
  766.            {
  767.            // select the current ship
  768.  
  769.            // make players ship the selected ship
  770.  
  771.            players_ship_type = current_ship_type;
  772.  
  773.            // exit
  774.  
  775.            done = 1;
  776.  
  777.            // make a key sound
  778.  
  779.            Digital_FX_Play(KRKKEY_VOC,3);
  780.  
  781.            } // end if
  782.         else
  783.         if (keyboard_state[MAKE_ESC])
  784.            {
  785.            // exit this menu and go back to main menu
  786.  
  787.            // exit
  788.  
  789.            done = 1;
  790.  
  791.            // make a key sound
  792.  
  793.            Digital_FX_Play(KRKKEY_VOC,3);
  794.  
  795.            } // end if
  796.  
  797.         } // end if keys active
  798.  
  799.      // draw the object and it's stats
  800.  
  801.      if (current_ship_type==PLAYER_TALLON)
  802.         {
  803.         // change heading of tallon model
  804.  
  805.         if ((dynamic_obj[TALLONS_TEMPLATE].state+=5)>360)
  806.             dynamic_obj[TALLONS_TEMPLATE].state-=360;
  807.  
  808.         // perform the rotation
  809.  
  810.         Rotate_Object(&dynamic_obj[TALLONS_TEMPLATE],0,5,0);
  811.  
  812.         // update object template with new heading
  813.  
  814.         // set world position to a reasonable spot
  815.  
  816.         dynamic_obj[TALLONS_TEMPLATE].world_pos.x = -50;
  817.         dynamic_obj[TALLONS_TEMPLATE].world_pos.y = 0;
  818.         dynamic_obj[TALLONS_TEMPLATE].world_pos.z = 400;
  819.  
  820.         // convert object local coordinates to world coordinates
  821.  
  822.         Local_To_World_Object(&dynamic_obj[TALLONS_TEMPLATE]);
  823.  
  824.         // draw the object in wireframe
  825.  
  826.         Draw_Object_Wire(&dynamic_obj[TALLONS_TEMPLATE],12);
  827.  
  828.         // draw the stats
  829.  
  830.         Font_Engine_1(0,130,0,12,"TALLON SPECIFICATIONS",video_buffer);
  831.  
  832.         // draw the specfication strings
  833.  
  834.         for (index=0; index<NUM_SHIP_SPECS; index++)
  835.             Font_Engine_1(4,140+8*index,0,12,tallon_specs[index],video_buffer);
  836.  
  837.         } // end
  838.      else
  839.         {
  840.         // else must be a slider
  841.  
  842.         // change heading of slider model
  843.  
  844.         if ((dynamic_obj[SLIDERS_TEMPLATE].state+=5)>360)
  845.             dynamic_obj[SLIDERS_TEMPLATE].state-=360;
  846.  
  847.         // perform the rotation
  848.  
  849.         Rotate_Object(&dynamic_obj[SLIDERS_TEMPLATE],0,5,0);
  850.  
  851.         // set world position to a reasonable spot
  852.  
  853.         dynamic_obj[SLIDERS_TEMPLATE].world_pos.x = -50;
  854.         dynamic_obj[SLIDERS_TEMPLATE].world_pos.y = 0;
  855.         dynamic_obj[SLIDERS_TEMPLATE].world_pos.z = 400;
  856.  
  857.         // convert object local coordinates to world coordinates
  858.  
  859.         Local_To_World_Object(&dynamic_obj[SLIDERS_TEMPLATE]);
  860.  
  861.         // draw the object in wireframe
  862.  
  863.         Draw_Object_Wire(&dynamic_obj[SLIDERS_TEMPLATE],12);
  864.  
  865.         // draw the stats
  866.  
  867.         Font_Engine_1(0,130,0,12,"SLIDER SPECIFICATIONS",video_buffer);
  868.  
  869.         // draw the specfication strings
  870.  
  871.         for (index=0; index<NUM_SHIP_SPECS; index++)
  872.             Font_Engine_1(4,140+8*index,0,12,slider_specs[index],video_buffer);
  873.  
  874.         } // end else
  875.  
  876.      // draw the buttons
  877.  
  878.      buttons_spr.x          = 260;
  879.      buttons_spr.y          = 20;
  880.      buttons_spr.curr_frame = 4;
  881.  
  882.      Sprite_Draw((sprite_ptr)&buttons_spr,double_buffer,0);
  883.  
  884.      buttons_spr.y          = 40;
  885.      buttons_spr.curr_frame = 6;
  886.  
  887.      Sprite_Draw((sprite_ptr)&buttons_spr,double_buffer,0);
  888.  
  889.      buttons_spr.y          = 60;
  890.      buttons_spr.curr_frame = 2;
  891.  
  892.      Sprite_Draw((sprite_ptr)&buttons_spr,double_buffer,0);
  893.  
  894.      buttons_spr.y          = 80;
  895.      buttons_spr.curr_frame = 0;
  896.  
  897.      Sprite_Draw((sprite_ptr)&buttons_spr,double_buffer,0);
  898.  
  899.      // draw the headers
  900.  
  901.      Font_Engine_1(60,0,0,12,"KILL OR BE KILLED BATTLE MECH SELECTION",double_buffer);
  902.  
  903.      // display double buffer
  904.  
  905.      Display_Double_Buffer_32(double_buffer,0);
  906.  
  907.      // slow things down a bit
  908.  
  909.      Time_Delay(1);
  910.  
  911.      // check on music
  912.  
  913.      if (music_enabled)
  914.         {
  915.         // test if piece is complete or has been stopped
  916.  
  917.         if (Music_Status()==2 || Music_Status()==0)
  918.            {
  919.            // advance to next sequence
  920.  
  921.            if (++intro_seq_index==14)
  922.               intro_seq_index=0;
  923.  
  924.            Music_Play((music_ptr)&song,intro_sequence[intro_seq_index]);
  925.  
  926.            } // end if
  927.  
  928.         } // end if music enabled
  929.  
  930.      } // end while
  931.  
  932. } // end Select_Mech
  933.  
  934. /////////////////////////////////////////////////////////////////////////////
  935.  
  936. void Misc_Color_Init(void)
  937. {
  938. // this function initializes various color registers for the game phase of
  939. // KRK
  940.  
  941. Write_Color_Reg(SHIELDS_REG,                  (RGB_color_ptr)&dark_blue);
  942. Write_Color_Reg(RADAR_REG,                    (RGB_color_ptr)&dark_blue);
  943. Write_Color_Reg(COMM_REG,                     (RGB_color_ptr)&dark_blue);
  944. Write_Color_Reg(HUD_REG,                      (RGB_color_ptr)&dark_blue);
  945. Write_Color_Reg(STS_REG,                      (RGB_color_ptr)&dark_green);
  946. Write_Color_Reg(HULL_REG,                     (RGB_color_ptr)&dark_green);
  947. Write_Color_Reg(OFF_REG,                      (RGB_color_ptr)&bright_green);
  948. Write_Color_Reg(PLAYERS_WEAPON_FIRE_REG,      (RGB_color_ptr)&black);
  949. Write_Color_Reg(ENGINES_TALLON_REG,           (RGB_color_ptr)&black);
  950. Write_Color_Reg(ENGINES_SLIDER_REG,           (RGB_color_ptr)&black);
  951. Write_Color_Reg(BARRIERS_REG,                 (RGB_color_ptr)&black);
  952. Write_Color_Reg(SHIELDS_FLICKER_REG,           (RGB_color_ptr)&black);
  953.  
  954. } // end Misc_Color_Init
  955.  
  956. ////////////////////////////////////////////////////////////////////////////
  957.  
  958. void Tallon_Color_FX(void)
  959. {
  960. // this function flickers the tallons engines
  961.  
  962. static int engine_counter=0; // used to track time from call to call
  963.  
  964. // test if it's time to change color
  965.  
  966. if (++engine_counter==1)
  967.    Write_Color_Reg(ENGINES_TALLON_REG,(RGB_color_ptr)&bright_blue);
  968. else
  969. if (engine_counter==2)
  970.    Write_Color_Reg(ENGINES_TALLON_REG,(RGB_color_ptr)&medium_blue);
  971. else
  972. if (engine_counter==3)
  973.    engine_counter=0;
  974.  
  975.  
  976. } // end Tallon_Color_FX
  977.  
  978. /////////////////////////////////////////////////////////////////////////////
  979.  
  980. void Slider_Color_FX(void)
  981. {
  982. // this function flickers the sliders engines
  983.  
  984. static int engine_counter=0; // used to track time from call to call
  985.  
  986. // test if it's time to change color
  987.  
  988. if (++engine_counter==1)
  989.    Write_Color_Reg(ENGINES_SLIDER_REG,(RGB_color_ptr)&bright_green);
  990. else
  991. if (engine_counter==2)
  992.    Write_Color_Reg(ENGINES_SLIDER_REG,(RGB_color_ptr)&medium_green);
  993. else
  994. if (engine_counter==3)
  995.    engine_counter=0;
  996.  
  997. } // end Slider_Color_FX
  998.  
  999. /////////////////////////////////////////////////////////////////////////////
  1000.  
  1001. void Barrier_Color_FX(void)
  1002. {
  1003. // this function flickers the game grid barriers beacon
  1004.  
  1005. static int beacon_counter=0; // used to track time from call to call
  1006.  
  1007. // test if it's time to change color
  1008.  
  1009. if (++beacon_counter==1)
  1010.    Write_Color_Reg(BARRIERS_REG,(RGB_color_ptr)&bright_green);
  1011. else
  1012. if (beacon_counter==10)
  1013.    Write_Color_Reg(BARRIERS_REG,(RGB_color_ptr)&dark_green);
  1014. else
  1015. if (beacon_counter==25)
  1016.    beacon_counter=0;
  1017.  
  1018. } // end Barrier_Color_FX
  1019.  
  1020. /////////////////////////////////////////////////////////////////////////////
  1021.  
  1022. void Draw_Hud(void)
  1023. {
  1024. // this function draws the heads up display
  1025.  
  1026. char buffer[64]; // local working buffer
  1027.  
  1028. // create the string with the x,y,z and heading in it
  1029.  
  1030. sprintf(buffer,"X(%5d) Y(%5d) Z(%5d) TRAJ(%4d) KILLS:(%3d)",(int)view_point.x,
  1031.                                                             (int)view_point.y,
  1032.                                                             (int)view_point.z,
  1033.                                                             (int)ship_yaw,
  1034.                                                             (int)ship_kills);
  1035. // print the string to the double buffer
  1036.  
  1037. Font_Engine_1(16,10,0,12,buffer,double_buffer);
  1038.  
  1039. } // end Draw_Hud
  1040.  
  1041. /////////////////////////////////////////////////////////////////////////////
  1042.  
  1043. void Draw_Tactical(int command)
  1044. {
  1045. // this function is responsible for both draw the static tactical displays
  1046. // and updating the currently active tactical display
  1047.  
  1048. int index,    // looping variable
  1049.     color,    // holds a temp color
  1050.     length;   // used to hold length of indicator bars
  1051.  
  1052. // test command and see what caller wants done
  1053.  
  1054. switch(command)
  1055.       {
  1056.  
  1057.       case TACTICAL_CLEAR:
  1058.            {
  1059.            // totally clear the tactical display
  1060.  
  1061.            Draw_Rectangle(TACTICAL_X,
  1062.                           TACTICAL_Y,
  1063.                           TACTICAL_X+TACTICAL_WIDTH-1,
  1064.                           TACTICAL_Y+TACTICAL_HEIGHT-1,
  1065.                           0);
  1066.  
  1067.  
  1068.            } break;
  1069.  
  1070.       case TACTICAL_DRAW:
  1071.            {
  1072.            // based on tactical to be displayed render static portion
  1073.            // of it
  1074.  
  1075.            if (tactical_state==TACTICAL_MODE_STS)
  1076.               {
  1077.               tactical_spr.curr_frame = 2;
  1078.  
  1079.               // update button illuminations
  1080.  
  1081.               Write_Color_Reg(STS_REG, (RGB_color_ptr)&bright_green);
  1082.               Write_Color_Reg(HULL_REG,(RGB_color_ptr)&dark_green);
  1083.               Write_Color_Reg(OFF_REG, (RGB_color_ptr)&dark_green);
  1084.  
  1085.               } // end if
  1086.  
  1087.            else
  1088.            if (tactical_state==TACTICAL_MODE_HULL)
  1089.               {
  1090.               // which hull should be displayed
  1091.  
  1092.               if (players_ship_type==PLAYER_TALLON)
  1093.                  tactical_spr.curr_frame = 3;
  1094.               else
  1095.                  tactical_spr.curr_frame = 4;
  1096.  
  1097.               // update button illuminations
  1098.  
  1099.               Write_Color_Reg(STS_REG, (RGB_color_ptr)&dark_green);
  1100.               Write_Color_Reg(HULL_REG,(RGB_color_ptr)&bright_green);
  1101.               Write_Color_Reg(OFF_REG, (RGB_color_ptr)&dark_green);
  1102.  
  1103.  
  1104.               } // end if
  1105.            else
  1106.               {
  1107.               tactical_spr.curr_frame = 1;
  1108.  
  1109.               // update button illuminations
  1110.  
  1111.               Write_Color_Reg(STS_REG, (RGB_color_ptr)&dark_green);
  1112.               Write_Color_Reg(HULL_REG,(RGB_color_ptr)&dark_green);
  1113.               Write_Color_Reg(OFF_REG, (RGB_color_ptr)&bright_green);
  1114.  
  1115.               } // end else
  1116.  
  1117.            // now draw display
  1118.  
  1119.            tactical_spr.x = TACTICAL_X + 8;
  1120.            tactical_spr.y = TACTICAL_Y + 6;
  1121.  
  1122.            Sprite_Draw((sprite_ptr)&tactical_spr, video_buffer,0);
  1123.  
  1124.            } break;
  1125.  
  1126.       case TACTICAL_UPDATE:
  1127.            {
  1128.            // based on tactical state update display accordingly
  1129.  
  1130.            switch(tactical_state)
  1131.                  {
  1132.  
  1133.                  case TACTICAL_MODE_STS:
  1134.                       {
  1135.  
  1136.                       // draw velocity gauge
  1137.  
  1138.                       length = (ship_speed<<1)/5;
  1139.  
  1140.                       // test for negative values
  1141.  
  1142.                       if (length<0)
  1143.                          {
  1144.                          // invert value
  1145.  
  1146.                          length = -length;
  1147.  
  1148.                          // show negative velocity with red
  1149.  
  1150.                          color = 32;
  1151.  
  1152.                          } // end if
  1153.                       else
  1154.                          {
  1155.                          // show positive velocity with red
  1156.  
  1157.                          color = 144;
  1158.  
  1159.                          } // end else
  1160.  
  1161.                       // do a little out of bounds check
  1162.  
  1163.                       if (length>20)
  1164.                          length = 20;
  1165.  
  1166.                       // draw visible portion of digital indicator
  1167.  
  1168.                       if (length>0)
  1169.                          {
  1170.  
  1171.                          Line_H(TACTICAL_X+8+16,
  1172.                                 TACTICAL_X+8+16+length,
  1173.                                 TACTICAL_Y+6+5,
  1174.                                 color);
  1175.  
  1176.                          Line_H(TACTICAL_X+8+16,
  1177.                                 TACTICAL_X+8+16+length,
  1178.                                 TACTICAL_Y+6+5+1,
  1179.                                 color);
  1180.                          }
  1181.  
  1182.                       // undraw old line (if any)
  1183.  
  1184.                       if (++length<=20)
  1185.                          {
  1186.                          // erase old line
  1187.  
  1188.                          Line_H(TACTICAL_X+8+16+length,
  1189.                                 TACTICAL_X+8+16+20,
  1190.                                 TACTICAL_Y+6+5,
  1191.                                 0);
  1192.  
  1193.                          Line_H(TACTICAL_X+8+16+length,
  1194.                                 TACTICAL_X+8+16+20,
  1195.                                 TACTICAL_Y+6+5+1,
  1196.                                0);
  1197.  
  1198.                          } // end if erase needed
  1199.  
  1200.                       // draw damage gauge
  1201.  
  1202.                       length = (ship_damage<<1)/5;
  1203.  
  1204.                       // check for negative values
  1205.  
  1206.                       if (length<0)
  1207.                          length = -length;
  1208.  
  1209.                       // draw visible portion of digital indicator
  1210.  
  1211.                       if (length>0)
  1212.                          {
  1213.  
  1214.                          Line_H(TACTICAL_X+8+16,
  1215.                                 TACTICAL_X+8+16+length,
  1216.                                 TACTICAL_Y+6+5+8,
  1217.                                 96);
  1218.  
  1219.                          Line_H(TACTICAL_X+8+16,
  1220.                                 TACTICAL_X+8+16+length,
  1221.                                 TACTICAL_Y+6+5+8+1,
  1222.                                 96);
  1223.  
  1224.                          } // end if
  1225.  
  1226.                       if (++length<=20)
  1227.                          {
  1228.                          // erase old line
  1229.  
  1230.                          Line_H(TACTICAL_X+8+16+length,
  1231.                                 TACTICAL_X+8+16+20,
  1232.                                 TACTICAL_Y+6+5+8,
  1233.                                 0);
  1234.  
  1235.                          Line_H(TACTICAL_X+8+16+length,
  1236.                                 TACTICAL_X+8+16+20,
  1237.                                 TACTICAL_Y+6+5+8+1,
  1238.                                0);
  1239.  
  1240.                          } // end if erase needed
  1241.  
  1242.                       // draw energy gauge
  1243.  
  1244.                       length = (ship_energy<<1)/5;
  1245.  
  1246.                       // check for negative values
  1247.  
  1248.                       if (length<0)
  1249.                          length = -length;
  1250.  
  1251.                       // draw visible portion of digital indicator
  1252.  
  1253.                       if (length>0)
  1254.                          {
  1255.  
  1256.                          Line_H(TACTICAL_X+8+16,
  1257.                                 TACTICAL_X+8+16+length,
  1258.                                 TACTICAL_Y+6+5+16,
  1259.                                 96);
  1260.  
  1261.                          Line_H(TACTICAL_X+8+16,
  1262.                                 TACTICAL_X+8+16+length,
  1263.                                 TACTICAL_Y+6+5+16+1,
  1264.                                 96);
  1265.                          }
  1266.  
  1267.                       // undraw remainder of gauge
  1268.  
  1269.                       if (++length<=20)
  1270.                          {
  1271.                          // erase old line
  1272.  
  1273.                          Line_H(TACTICAL_X+8+16+length,
  1274.                                 TACTICAL_X+8+16+20,
  1275.                                 TACTICAL_Y+6+5+16,
  1276.                                 0);
  1277.  
  1278.                          Line_H(TACTICAL_X+8+16+length,
  1279.                                 TACTICAL_X+8+16+20,
  1280.                                 TACTICAL_Y+6+5+16+1,
  1281.                                0);
  1282.  
  1283.                          } // end if erase needed
  1284.  
  1285.                       } break;
  1286.  
  1287.                  case TACTICAL_MODE_HULL:
  1288.                       {
  1289.                       // do nothing for now
  1290.  
  1291.                       } break;
  1292.  
  1293.                  case TACTICAL_MODE_OFF:
  1294.                       {
  1295.                       // do nothing for now
  1296.  
  1297.                       } break;
  1298.  
  1299.                  default:break;
  1300.  
  1301.                  } // end switch
  1302.  
  1303.            } break;
  1304.  
  1305.       default:break;
  1306.  
  1307.       } // end switch
  1308.  
  1309. } // end Draw_Tactical
  1310.  
  1311. /////////////////////////////////////////////////////////////////////////////
  1312.  
  1313. void Load_Tactical(void)
  1314. {
  1315. // this function loads various icons for the tactical displays
  1316.  
  1317. int index; // looping variable
  1318.  
  1319. // load the imagery for the icons for display
  1320.  
  1321. PCX_Init((pcx_picture_ptr)&image_pcx);
  1322. PCX_Load("krkdis.pcx", (pcx_picture_ptr)&image_pcx,1);
  1323.  
  1324. // intialize the tactical sprite
  1325.  
  1326. Sprite_Init((sprite_ptr)&tactical_spr,0,0,38,28,0,0,0,0,0,0);
  1327.  
  1328. // extract the bitmaps for heads up text
  1329.  
  1330. for (index=0; index<5; index++)
  1331.     PCX_Get_Sprite((pcx_picture_ptr)&image_pcx,
  1332.                    (sprite_ptr)&tactical_spr,index,index,0);
  1333.  
  1334. // delete pcx file
  1335.  
  1336. PCX_Delete((pcx_picture_ptr)&image_pcx);
  1337.  
  1338. // load the imagery for the control buttons
  1339.  
  1340. PCX_Init((pcx_picture_ptr)&image_pcx);
  1341. PCX_Load("krkbutt.pcx", (pcx_picture_ptr)&image_pcx,1);
  1342.  
  1343. // intialize the tactical sprite
  1344.  
  1345. Sprite_Init((sprite_ptr)&buttons_spr,0,0,42,12,0,0,0,0,0,0);
  1346.  
  1347. // extract the bitmaps for heads up text
  1348.  
  1349. for (index=0; index<8; index++)
  1350.     PCX_Get_Sprite((pcx_picture_ptr)&image_pcx,
  1351.                    (sprite_ptr)&buttons_spr,index,index%4,index/4);
  1352.  
  1353. // delete pcx file
  1354.  
  1355. PCX_Delete((pcx_picture_ptr)&image_pcx);
  1356.  
  1357. } // end Load_Tactical
  1358.  
  1359. //////////////////////////////////////////////////////////////////////////////
  1360.  
  1361. void Draw_Scanner(int command)
  1362. {
  1363.  
  1364. // this function draws the scanner, it has three modes, clear, erase blips,
  1365. // and draw blips
  1366.  
  1367. int index,  // looping variable
  1368.     xb,yb;  // temporary blip locations
  1369.  
  1370. // holds the scanner clips
  1371.  
  1372. static int blip_x[24],      // these arrays hold the blips from call to call
  1373.            blip_y[24],
  1374.            active_blips=0;  // totall number of active blips this frame
  1375.  
  1376. // what is the command
  1377.  
  1378. if (command==SCANNER_CLEAR)
  1379.    {
  1380.    // clear the scanner image
  1381.  
  1382.    Draw_Rectangle(SCANNER_X,
  1383.                   SCANNER_Y,
  1384.                   SCANNER_X+SCANNER_WIDTH-1,
  1385.                   SCANNER_Y+SCANNER_HEIGHT-1,
  1386.                   0);
  1387.  
  1388.    // reset number of blips
  1389.  
  1390.    active_blips=0;
  1391.  
  1392.    // exit
  1393.  
  1394.    return;
  1395.  
  1396.    } // end if clear
  1397.  
  1398. if (command==SCANNER_LOGO)
  1399.    {
  1400.    // clear the scanner surface off
  1401.  
  1402.    tactical_spr.curr_frame = 1;
  1403.    tactical_spr.x          = SCANNER_X + 8;
  1404.    tactical_spr.y          = SCANNER_Y + 6;
  1405.  
  1406.    Sprite_Draw((sprite_ptr)&tactical_spr, video_buffer,0);
  1407.  
  1408.    // reset number of blips
  1409.  
  1410.    active_blips=0;
  1411.  
  1412.    // exit
  1413.  
  1414.    return;
  1415.  
  1416.    } // end if
  1417.  
  1418. // now determine if scanner is being drawn or erased
  1419.  
  1420. if (command==SCANNER_ERASE_BLIPS)
  1421.    {
  1422.    // erase all the scanner blips
  1423.  
  1424.    // simply loop thru blips and erase them
  1425.  
  1426.    for (index=0; index<active_blips; index++)
  1427.        Write_Pixel(blip_x[index],blip_y[index],0);
  1428.  
  1429.    return;
  1430.  
  1431.    } // end if
  1432. else
  1433.    {
  1434.    // reset number of active blips
  1435.  
  1436.    active_blips = 0;
  1437.  
  1438.    // draw all the scanner blips
  1439.  
  1440.    // first barriers
  1441.  
  1442.    for (index=0; index<NUM_BARRIERS; index++)
  1443.        {
  1444.        // compute blip position
  1445.  
  1446.        xb = SCANNER_X+(8000+barriers[index].x)/282;
  1447.        yb = SCANNER_Y+(8000-barriers[index].z)/382;
  1448.  
  1449.        // draw the blip
  1450.  
  1451.        Write_Pixel(xb,yb,7);
  1452.  
  1453.        // save the blip
  1454.  
  1455.        blip_x[active_blips] = xb;
  1456.        blip_y[active_blips] = yb;
  1457.  
  1458.        // increment number of blips
  1459.  
  1460.        active_blips++;
  1461.  
  1462.        } // end for index
  1463.  
  1464.    // now telepods
  1465.  
  1466.    for (index=0; index<NUM_TELEPODS; index++)
  1467.        {
  1468.        // compute blip position
  1469.  
  1470.        xb = SCANNER_X+(8000+telepods[index].x)/282;
  1471.        yb = SCANNER_Y+(8000-telepods[index].z)/382;
  1472.  
  1473.        // draw the blip
  1474.  
  1475.        Write_Pixel(xb,yb,5);
  1476.  
  1477.        // save the blip
  1478.  
  1479.        blip_x[active_blips] = xb;
  1480.        blip_y[active_blips] = yb;
  1481.  
  1482.        // increment number of blips
  1483.  
  1484.        active_blips++;
  1485.  
  1486.        } // end for index
  1487.  
  1488.    // now power stations
  1489.  
  1490.    for (index=0; index<NUM_STATIONS; index++)
  1491.        {
  1492.        // compute blip position
  1493.  
  1494.        xb = SCANNER_X+(8000+stations[index].x)/282;
  1495.        yb = SCANNER_Y+(8000-stations[index].z)/382;
  1496.  
  1497.        // draw the blip
  1498.  
  1499.        Write_Pixel(xb,yb,13);
  1500.  
  1501.        // save the blip
  1502.  
  1503.        blip_x[active_blips] = xb;
  1504.        blip_y[active_blips] = yb;
  1505.  
  1506.        // increment number of blips
  1507.  
  1508.        active_blips++;
  1509.  
  1510.        } // end for index
  1511.  
  1512.    // now aliens
  1513.  
  1514.    for (index=0; index<NUM_ALIENS; index++)
  1515.        {
  1516.  
  1517.        if (aliens[index].state!=ALIEN_DEAD)
  1518.           {
  1519.  
  1520.           // compute blip position
  1521.  
  1522.           xb = SCANNER_X+(8000+aliens[index].x)/282;
  1523.           yb = SCANNER_Y+(8000-aliens[index].z)/382;
  1524.  
  1525.           // draw the blip
  1526.  
  1527.           Write_Pixel(xb,yb,12);
  1528.  
  1529.           // save the blip
  1530.  
  1531.           blip_x[active_blips] = xb;
  1532.           blip_y[active_blips] = yb;
  1533.  
  1534.           // increment number of blips
  1535.  
  1536.           active_blips++;
  1537.  
  1538.           } // end if
  1539.  
  1540.        } // end for index
  1541.  
  1542.    // finally the player
  1543.  
  1544.    // compute blip position
  1545.  
  1546.    xb = SCANNER_X+(8000+view_point.x)/282;
  1547.    yb = SCANNER_Y+(8000-view_point.z)/382;
  1548.  
  1549.    // draw the blip
  1550.  
  1551.    Write_Pixel(xb,yb,9);
  1552.  
  1553.    // save the blip
  1554.  
  1555.    blip_x[active_blips] = xb;
  1556.    blip_y[active_blips] = yb;
  1557.  
  1558.    // increment number of blips
  1559.  
  1560.    active_blips++;
  1561.  
  1562.    } // end else
  1563.  
  1564. } // end Draw_Scanner
  1565.  
  1566. //////////////////////////////////////////////////////////////////////////////
  1567.  
  1568. void Init_Missiles(void)
  1569. {
  1570. // this function resets the missile array and gets them ready for use
  1571.  
  1572. int index; // looping variable
  1573.  
  1574. // initialize all missiles to a known state
  1575.  
  1576. for (index=0; index<NUM_MISSILES; index++)
  1577.     {
  1578.  
  1579.     missiles[index].state       = MISSILE_INACTIVE;
  1580.     missiles[index].owner       = NO_OWNER;
  1581.     missiles[index].lifetime    = 0;
  1582.  
  1583.     missiles[index].direction.x = 0;
  1584.     missiles[index].direction.y = 0;
  1585.     missiles[index].direction.z = 0;
  1586.  
  1587.     missiles[index].x           = 0;
  1588.     missiles[index].y           = 0;
  1589.     missiles[index].z           = 0;
  1590.  
  1591.     } // end for index
  1592.  
  1593. // reset number of active missiles
  1594.  
  1595. active_player_missiles = 0;
  1596. total_active_missiles  = 0;
  1597.  
  1598. } // end Init_Missiles
  1599.  
  1600. /////////////////////////////////////////////////////////////////////////////
  1601.  
  1602. void Move_Missiles(void)
  1603. {
  1604. // this function moves all the missiles
  1605.  
  1606. int index,            // looping variables
  1607.     index_2,
  1608.     radius_tallon,    // used to hold the radius of the ships
  1609.     radius_slider,
  1610.     radius_player,
  1611.     dx,               // used during distance calculations
  1612.     dz,
  1613.     dist,
  1614.     min;
  1615.  
  1616. // pre-compute radi of alien ship types
  1617.  
  1618. radius_tallon = (0.75*dynamic_obj[TALLONS_TEMPLATE].radius);
  1619. radius_slider = (0.75*dynamic_obj[SLIDERS_TEMPLATE].radius);
  1620.  
  1621. // compute radius of players ship
  1622.  
  1623. if (players_ship_type==PLAYER_TALLON)
  1624.    radius_player = dynamic_obj[TALLONS_TEMPLATE].radius;
  1625. else
  1626.    radius_player = dynamic_obj[SLIDERS_TEMPLATE].radius;
  1627.  
  1628. // move all the missiles and test for collisions
  1629.  
  1630. for (index=0; index<NUM_MISSILES; index++)
  1631.     {
  1632.     // for each missile that is active, move it and test it against bounds
  1633.     // and lifetime
  1634.  
  1635.     if (missiles[index].state==MISSILE_ACTIVE)
  1636.        {
  1637.        // process missile
  1638.  
  1639.        // first move missile
  1640.  
  1641.        missiles[index].x+=missiles[index].direction.x;
  1642.        missiles[index].y+=missiles[index].direction.y;
  1643.        missiles[index].z+=missiles[index].direction.z;
  1644.  
  1645.        // test for collisions with aliens if player fired this missile
  1646.  
  1647.        if (missiles[index].owner==PLAYER_OWNER)
  1648.           {
  1649.           for (index_2=0; index_2<NUM_ALIENS; index_2++)
  1650.               {
  1651.  
  1652.               // test if alien is not dead or dying
  1653.  
  1654.               if (aliens[index_2].state!=ALIEN_DEAD &&
  1655.                   aliens[index_2].state!=ALIEN_DYING)
  1656.                  {
  1657.  
  1658.                  // test if missiles center is within bounding radius
  1659.                  // of alien ship
  1660.  
  1661.                  // compute distance based on taylor expansion about 12% error
  1662.                  // max
  1663.  
  1664.                  // first find |dx| and |dz|
  1665.  
  1666.                  if ( (dx = ((int)aliens[index_2].x - (int)missiles[index].x) ) < 0)
  1667.                     dx=-dx;
  1668.  
  1669.                  if ( (dz = ((int)aliens[index_2].z - (int)missiles[index].z)) < 0)
  1670.                     dz=-dz;
  1671.  
  1672.                  // compute minimum delta
  1673.  
  1674.                  if (dx<=dz)
  1675.                     min=dx;
  1676.                  else
  1677.                     min=dz;
  1678.  
  1679.                  // compute distance
  1680.  
  1681.                  dist = dx + dz - (min >> 1);
  1682.  
  1683.                  // test distance against average radius of alien ship
  1684.  
  1685.                  if (aliens[index_2].type==ALIEN_TALLON)
  1686.                     {
  1687.                     if (dist<=radius_tallon)
  1688.                        {
  1689.                        // kill missile
  1690.  
  1691.                        missiles[index].lifetime=-1;
  1692.  
  1693.                        // send message to aliens that this one is dying
  1694.  
  1695.                        aliens[index_2].state       = ALIEN_DYING;
  1696.                        aliens[index_2].counter_1   = 0;
  1697.                        aliens[index_2].threshold_1 = 20;
  1698.  
  1699.                        aliens[index_2].speed         = 0;
  1700.  
  1701.                        aliens[index_2].color.red   = 0;
  1702.                        aliens[index_2].color.green = 0;
  1703.                        aliens[index_2].color.blue  = 0;
  1704.  
  1705.                        // lets hear him fry
  1706.  
  1707.                        Digital_FX_Play(KRKEX1_VOC,0);
  1708.  
  1709.                        // add one more notch to my 6 shooter!
  1710.  
  1711.                        ship_kills++;
  1712.  
  1713.                        // move to next missile
  1714.  
  1715.                        continue;
  1716.  
  1717.                        } // end if
  1718.  
  1719.                     } // end if tallon
  1720.                  else
  1721.                  if (aliens[index_2].type==ALIEN_SLIDER)
  1722.                     {
  1723.                     if (dist<=radius_slider)
  1724.                        {
  1725.                        // kill missile
  1726.  
  1727.                        missiles[index].lifetime=-1;
  1728.  
  1729.                        // send message to aliens that this one is dying
  1730.  
  1731.                        aliens[index_2].state       = ALIEN_DYING;
  1732.                        aliens[index_2].counter_1   = 0;
  1733.                        aliens[index_2].threshold_1 = 20;
  1734.  
  1735.                        aliens[index_2].speed       = 0;
  1736.  
  1737.                        aliens[index_2].color.red   = 0;
  1738.                        aliens[index_2].color.green = 0;
  1739.                        aliens[index_2].color.blue  = 0;
  1740.  
  1741.                        // lets hear him fry
  1742.  
  1743.                        Digital_FX_Play(KRKEX1_VOC,0);
  1744.  
  1745.                        // add one more notch to my 6 shooter!
  1746.  
  1747.                        ship_kills++;
  1748.  
  1749.                        // move to next missile
  1750.  
  1751.                        continue;
  1752.  
  1753.                        } // end if
  1754.  
  1755.                     } // end if slider
  1756.  
  1757.                  } // end if alien not dead
  1758.  
  1759.               } // end for
  1760.  
  1761.           } // end if player fired missile
  1762.        else
  1763.           {
  1764.           // this missile must be an aliens, so test it against ship
  1765.  
  1766.           if ( (dx = ((int)view_point.x - (int)missiles[index].x) ) < 0)
  1767.              dx=-dx;
  1768.  
  1769.           if ( (dz = ((int)view_point.z - (int)missiles[index].z)) < 0)
  1770.              dz=-dz;
  1771.  
  1772.           // compute minimum delta
  1773.  
  1774.           if (dx<=dz)
  1775.              min=dx;
  1776.           else
  1777.              min=dz;
  1778.  
  1779.           // compute distance
  1780.  
  1781.           dist = dx + dz - (min >> 1);
  1782.  
  1783.           // test for collision
  1784.  
  1785.           if (dist<=radius_player)
  1786.              {
  1787.              // send message to player
  1788.  
  1789.              ship_message = SHIP_HIT;
  1790.              ship_timer   = 25;
  1791.  
  1792.              // add some sound
  1793.  
  1794.              Digital_FX_Play(KRKEX2_VOC,0);
  1795.  
  1796.              // add some damage
  1797.  
  1798.              if (++ship_damage>50)
  1799.                 ship_damage=50;
  1800.  
  1801.              // kill missile
  1802.  
  1803.              missiles[index].lifetime=-1;
  1804.  
  1805.              } // end if collision
  1806.  
  1807.           } // end else alien
  1808.  
  1809.        // test for out of bounds
  1810.  
  1811.        if (missiles[index].x > GAME_MAX_WORLD_X+500 ||
  1812.            missiles[index].x < GAME_MIN_WORLD_X-500 ||
  1813.  
  1814.            missiles[index].z > GAME_MAX_WORLD_Z+500 ||
  1815.            missiles[index].z < GAME_MIN_WORLD_Z-500 )
  1816.            {
  1817.  
  1818.            // de-activate missile
  1819.  
  1820.            missiles[index].state = MISSILE_INACTIVE;
  1821.  
  1822.            if (missiles[index].owner==PLAYER_OWNER)
  1823.               active_player_missiles--;
  1824.  
  1825.            // decrement total always
  1826.  
  1827.            total_active_missiles--;
  1828.  
  1829.            } // end if
  1830.        else
  1831.        if ((--missiles[index].lifetime)<0)
  1832.            {
  1833.            // missile has died out (ran out of energy)
  1834.  
  1835.            missiles[index].state = MISSILE_INACTIVE;
  1836.  
  1837.            if (missiles[index].owner==PLAYER_OWNER)
  1838.               active_player_missiles--;
  1839.  
  1840.            // decrement total always
  1841.  
  1842.            total_active_missiles--;
  1843.  
  1844.            } // end if
  1845.  
  1846.        } // end if missile alive
  1847.  
  1848.     } // end for index
  1849.  
  1850. // only rotate if there are active missiles
  1851.  
  1852. if (total_active_missiles)
  1853.    Rotate_Object(&dynamic_obj[MISSILES_TEMPLATE],0,0,30);
  1854.  
  1855. } // end Move_Missiles
  1856.  
  1857. /////////////////////////////////////////////////////////////////////////////
  1858.  
  1859. void Draw_Missiles(void)
  1860. {
  1861. // this function draws all the missiles (in 3d)
  1862.  
  1863. int index; // looping variable
  1864.  
  1865. for (index=0; index<NUM_MISSILES; index++)
  1866.     {
  1867.     // test if missile is active before starting 3-D processing
  1868.  
  1869.     if (missiles[index].state==MISSILE_ACTIVE)
  1870.        {
  1871.  
  1872.        // test if object is visible
  1873.  
  1874.        // now before we continue to process object, we must
  1875.        // move it to the proper world position
  1876.  
  1877.        dynamic_obj[MISSILES_TEMPLATE].world_pos.x = missiles[index].x;
  1878.        dynamic_obj[MISSILES_TEMPLATE].world_pos.y = missiles[index].y;
  1879.        dynamic_obj[MISSILES_TEMPLATE].world_pos.z = missiles[index].z;
  1880.  
  1881.        if (!Remove_Object(&dynamic_obj[MISSILES_TEMPLATE],OBJECT_CULL_XYZ_MODE))
  1882.           {
  1883.           // convert object local coordinates to world coordinate
  1884.  
  1885.           Local_To_World_Object(&dynamic_obj[MISSILES_TEMPLATE]);
  1886.  
  1887.           // remove the backfaces and shade object
  1888.  
  1889.           Remove_Backfaces_And_Shade(&dynamic_obj[MISSILES_TEMPLATE],-1);
  1890.  
  1891.           // convert world coordinates to camera coordinate
  1892.  
  1893.           World_To_Camera_Object(&dynamic_obj[MISSILES_TEMPLATE]);
  1894.  
  1895.           // clip the objects polygons against viewing volume
  1896.  
  1897.           Clip_Object_3D(&dynamic_obj[MISSILES_TEMPLATE],CLIP_Z_MODE);
  1898.  
  1899.           // generate the final polygon list
  1900.  
  1901.           Generate_Poly_List(&dynamic_obj[MISSILES_TEMPLATE],ADD_TO_POLY_LIST);
  1902.  
  1903.           } // end if object is outside viewing volume
  1904.  
  1905.        } // end if missile active
  1906.  
  1907.     } // end for index
  1908.  
  1909. } // end Draw_Missiles
  1910.  
  1911. //////////////////////////////////////////////////////////////////////////////
  1912.  
  1913. int Start_Missile(int owner,
  1914.                   vector_3d_ptr pos,
  1915.                   vector_3d_ptr dir,
  1916.                   int speed,
  1917.                   int lifetime)
  1918. {
  1919. // this function starts a missile up by hunting for a unused missile, initializing
  1920. // it and then starting it with the proper parameters
  1921.  
  1922. int index; // looping variable
  1923.  
  1924. // first test if this is a missile fired by player, if so, test if player
  1925. // is getting greedy
  1926.  
  1927. if (owner==PLAYER_OWNER && active_player_missiles>=MAX_PLAYER_MISSILES)
  1928.    return(0);
  1929.  
  1930. // hunt for an inactive missile
  1931.  
  1932. for (index=0; index<NUM_MISSILES; index++)
  1933.     {
  1934.     // is this missile free?
  1935.  
  1936.     if (missiles[index].state==MISSILE_INACTIVE)
  1937.        {
  1938.  
  1939.        // set this missile up
  1940.  
  1941.        missiles[index].state       = MISSILE_ACTIVE;
  1942.        missiles[index].owner       = owner;
  1943.        missiles[index].lifetime    = lifetime;
  1944.  
  1945.        missiles[index].direction.x = speed*dir->x;
  1946.        missiles[index].direction.y = speed*dir->y;
  1947.        missiles[index].direction.z = speed*dir->z;
  1948.  
  1949.        // start missile at center of viewport plus one step out
  1950.  
  1951.        missiles[index].x           =            pos->x+dir->x;
  1952.        missiles[index].y           = GUN_HEIGHT+pos->y+dir->y;
  1953.        missiles[index].z           =            pos->z+dir->z;
  1954.  
  1955.        // test if player fired the missile and update active missiles
  1956.  
  1957.        if (owner==PLAYER_OWNER)
  1958.           {
  1959.           // there's now one more missile
  1960.           active_player_missiles++;
  1961.  
  1962.           // play sound fx
  1963.  
  1964.           Digital_FX_Play(KRKMIS_VOC,2);
  1965.  
  1966.           }
  1967.        else
  1968.           {
  1969.           // must be alien
  1970.  
  1971.           // play sound fx
  1972.  
  1973.           Digital_FX_Play(KRKEMIS_VOC,3);
  1974.  
  1975.           } // end else
  1976.  
  1977.        // increment total active missiles
  1978.  
  1979.        total_active_missiles++;
  1980.  
  1981.        // exit loop baby!
  1982.  
  1983.        return(1);
  1984.  
  1985.        } // end if
  1986.  
  1987.     } // end for index
  1988.  
  1989. // couldn't satisfy request, let caller know
  1990.  
  1991. return(0);
  1992.  
  1993. } // end Start_Missile
  1994.  
  1995. //////////////////////////////////////////////////////////////////////////////
  1996.  
  1997. void Init_Aliens(void)
  1998. {
  1999. // this function initializes the alien structures
  2000.  
  2001. int index; // looping variable
  2002.  
  2003. for (index=0; index<NUM_ALIENS; index++)
  2004.     {
  2005.  
  2006.     aliens[index].state           = ALIEN_NEW_STATE;
  2007.     aliens[index].counter_1       = 0;
  2008.     aliens[index].counter_2       = 0;
  2009.     aliens[index].threshold_1     = 0;
  2010.     aliens[index].threshold_2     = 0;
  2011.     aliens[index].aux_1           = 0;
  2012.     aliens[index].aux_2           = 0;
  2013.     aliens[index].color_reg       = ALIEN_EXPL_BASE_REG+index;
  2014.  
  2015.  
  2016.     aliens[index].color.red       = 0;
  2017.     aliens[index].color.green     = 0;
  2018.     aliens[index].color.blue      = 0;
  2019.  
  2020.     aliens[index].type            = index%2;
  2021.     aliens[index].speed           = 0;
  2022.  
  2023.     aliens[index].angular_heading = 0;
  2024.  
  2025.     aliens[index].direction.x     = 0;
  2026.     aliens[index].direction.y     = 0;
  2027.     aliens[index].direction.z     = 0;
  2028.  
  2029.     aliens[index].x               = -2000 + rand()%4000;
  2030.     aliens[index].y               = 0;
  2031.     aliens[index].z               = -2000 + rand()%4000;
  2032.  
  2033.     } // end for index
  2034.  
  2035. } // end Init_Aliens
  2036.  
  2037. //////////////////////////////////////////////////////////////////////////////
  2038.  
  2039. void Process_Aliens(void)
  2040. {
  2041. // this function performs AI for the aliens and transforms them
  2042.  
  2043. int index,      // looping variable
  2044.     which_pod;  // used to select which telepod to start a dead alien at
  2045.  
  2046. float head_x,   // used to compute final heading of alien
  2047.       head_z,
  2048.       target_x, // used to compute desired target heading for alien
  2049.       target_z,
  2050.       normal_y, // the y component of a normal vector
  2051.       distance; // distance between alien and player
  2052.  
  2053.  
  2054. vector_3d alien_pos,    // temp to hold alien position
  2055.           alien_dir;    // temp to hold alien direction
  2056.  
  2057. // this holds the aliens personality probability table.
  2058. // here are the meanings of the values and the current distribution
  2059.  
  2060. // 0 attack, 30%
  2061. // 1 random, 20%
  2062. // 2 evade,  10%
  2063. // 3 stop,   10%
  2064. // 4 turn,   20%
  2065.  
  2066. static int alien_personality[10]={0,1,4,0,1,4,3,0,2,3};
  2067.  
  2068. // first process live aliens
  2069.  
  2070. for (index=0; index<NUM_ALIENS; index++)
  2071.     {
  2072.     // is this alien alive?
  2073.  
  2074.     if (aliens[index].state!=ALIEN_DEAD)
  2075.        {
  2076.  
  2077.        // based on state of alien, do the right thing
  2078.  
  2079.        switch(aliens[index].state)
  2080.              {
  2081.              case ALIEN_DEAD:
  2082.                   {
  2083.                   // process dead state
  2084.  
  2085.                   aliens[index].state = ALIEN_NEW_STATE;
  2086.  
  2087.                   } break;
  2088.  
  2089.              case ALIEN_DYING:
  2090.                   {
  2091.                   // continue dying
  2092.  
  2093.                   // increase intensity of color
  2094.  
  2095.                   if ((aliens[index].color.green+=4)>63)
  2096.                       aliens[index].color.green = 63;
  2097.  
  2098.                   // set color register
  2099.  
  2100.                   Write_Color_Reg(aliens[index].color_reg,(RGB_color_ptr)&aliens[index].color);
  2101.  
  2102.                   // is death sequence complete?
  2103.  
  2104.                   if (++aliens[index].counter_1 > aliens[index].threshold_1)
  2105.                      {
  2106.                      // tell state machine to select a new state
  2107.  
  2108.                      aliens[index].state = ALIEN_DEAD;
  2109.  
  2110.                      Write_Color_Reg(aliens[index].color_reg,(RGB_color_ptr)&black);
  2111.  
  2112.                      } // end if
  2113.  
  2114.                   } break;
  2115.  
  2116.              case ALIEN_NEW_STATE:
  2117.                   {
  2118.  
  2119.                   // a new state has been requested, select a new state based
  2120.                   // on probability and personality
  2121.  
  2122.                   switch(alien_personality[rand()%10])
  2123.                         {
  2124.                         case 0: // attack
  2125.  
  2126.                              {
  2127.                              // the alien is going to attack the player
  2128.  
  2129.                              // how long for total state
  2130.  
  2131.                              aliens[index].counter_1   = 0;
  2132.                              aliens[index].threshold_1 = 50 + rand()%150;
  2133.  
  2134.                              // set time between heading adjustements
  2135.  
  2136.                              aliens[index].counter_2   = 0;
  2137.                              aliens[index].threshold_2 = 3 + rand()%5;
  2138.  
  2139.                              // set speed
  2140.  
  2141.                              aliens[index].speed = 45 + rand()%5;
  2142.  
  2143.                              // set new state
  2144.  
  2145.                              aliens[index].state = ALIEN_ATTACK;
  2146.  
  2147.                              } break;
  2148.  
  2149.                         case 1:  // random
  2150.                              {
  2151.  
  2152.                              // how long for total state
  2153.  
  2154.                              aliens[index].counter_1   = 0;
  2155.                              aliens[index].threshold_1 = 50 + rand()%150;
  2156.  
  2157.                              // how often for random direction changes
  2158.  
  2159.                              aliens[index].counter_2   = 0;
  2160.                              aliens[index].threshold_2 = 10 + rand()%50;
  2161.  
  2162.                              // set speed
  2163.  
  2164.                              aliens[index].speed = 40 + rand()%25;
  2165.  
  2166.                              // and set new state
  2167.  
  2168.                              aliens[index].state = ALIEN_RANDOM;
  2169.  
  2170.                              } break;
  2171.  
  2172.                         case 2:  // evade
  2173.                              {
  2174.  
  2175.                              // how long for total state
  2176.  
  2177.                              aliens[index].counter_1   = 0;
  2178.                              aliens[index].threshold_1 = 50 + rand()%150;
  2179.  
  2180.                              // set time between heading adjustements
  2181.  
  2182.                              aliens[index].counter_2   = 0;
  2183.                              aliens[index].threshold_2 = 3 + rand()%5;
  2184.  
  2185.                              // set speed
  2186.  
  2187.                              aliens[index].speed = 50 + rand()%5;
  2188.  
  2189.                              // set new state
  2190.  
  2191.                              aliens[index].state = ALIEN_EVADE;
  2192.  
  2193.                              } break;
  2194.  
  2195.                         case 3: // stop
  2196.                              {
  2197.                              // set number of frames for alien to stop
  2198.  
  2199.                              aliens[index].counter_1   = 0;
  2200.                              aliens[index].threshold_1 = 5 + rand()%10;
  2201.  
  2202.                              // set speed to 0
  2203.  
  2204.                              aliens[index].speed = 0;
  2205.  
  2206.                              // and set new state
  2207.  
  2208.                              aliens[index].state = ALIEN_STOP;
  2209.  
  2210.                              } break;
  2211.  
  2212.  
  2213.                         case 4:  // turn
  2214.                              {
  2215.  
  2216.                              // set amount of time for turn
  2217.  
  2218.                              aliens[index].counter_1   = 0;
  2219.                              aliens[index].threshold_1 = 20 + rand()%20;
  2220.  
  2221.                              // set angular turning rate
  2222.  
  2223.                              aliens[index].aux_1 = -5+rand()%11;
  2224.  
  2225.                              // set speed for turn
  2226.  
  2227.                              aliens[index].speed = 35+rand()%30;
  2228.  
  2229.                              // and set new state
  2230.  
  2231.                              aliens[index].state = ALIEN_TURN;
  2232.  
  2233.                              } break;
  2234.  
  2235.                         default: break;
  2236.  
  2237.                         } // end switch
  2238.  
  2239.                   } break;
  2240.  
  2241.              case ALIEN_ATTACK:
  2242.                   {
  2243.                   // continue tracking player
  2244.  
  2245.                   // test if it's time to adjust heading to track player
  2246.  
  2247.                   if (++aliens[index].counter_2 > aliens[index].threshold_2)
  2248.                      {
  2249.  
  2250.                      // adjust heading toward player, use a heuristic approach
  2251.                      // that simply tries to keep turing the alien toward
  2252.                      // the player, later maybe we could add a bit of
  2253.                      // trajectory lookahead, so the alien could intercept
  2254.                      // the player???
  2255.  
  2256.  
  2257.                      // to determine which way the alien needs to turn we
  2258.                      // can use the following trick: based on the current
  2259.                      // trajectory of the alien and the vector from the
  2260.                      // alien to the player, we can compute a normal vector
  2261.  
  2262.                      // compute heading vector (happens to be a unit vector)
  2263.  
  2264.                      head_x = sin_look[aliens[index].angular_heading];
  2265.                      head_z = cos_look[aliens[index].angular_heading];
  2266.  
  2267.                      // compute target trajectory vector, players position
  2268.                      // minus aliens position
  2269.  
  2270.                      target_x = view_point.x - aliens[index].x;
  2271.                      target_z = view_point.z - aliens[index].z;
  2272.  
  2273.                      // now compute y component of normal
  2274.  
  2275.                      normal_y = (head_z*target_x - head_x*target_z);
  2276.  
  2277.                      // based on the sign of the result we can determine if
  2278.                      // we should turn the alien right or left, but be careful
  2279.                      // we are in a LEFT HANDED system!
  2280.  
  2281.                      if (normal_y>=0)
  2282.                         aliens[index].angular_heading+=(10+rand()%10);
  2283.                      else
  2284.                         aliens[index].angular_heading-=(10+rand()%10);
  2285.  
  2286.                      // check angle for overflow/underflow
  2287.  
  2288.                      if (aliens[index].angular_heading >=360)
  2289.                         aliens[index].angular_heading-=360;
  2290.                      else
  2291.                      if (aliens[index].angular_heading < 0)
  2292.                         aliens[index].angular_heading+=360;
  2293.  
  2294.                      // reset counter
  2295.  
  2296.                      aliens[index].counter_2 = 0;
  2297.  
  2298.                      } // end if
  2299.  
  2300.                   // test if attacking sequence is complete
  2301.  
  2302.                   if (++aliens[index].counter_1 > aliens[index].threshold_1)
  2303.                      {
  2304.                      // tell state machine to select a new state
  2305.  
  2306.                      aliens[index].state = ALIEN_NEW_STATE;
  2307.  
  2308.                      } // end if
  2309.  
  2310.                   // try and fire a missile
  2311.  
  2312.                   distance = fabs(view_point.x - aliens[index].x) +
  2313.                              fabs(view_point.z - aliens[index].z);
  2314.  
  2315.                   if ((rand()%15)==1 && distance<3500)
  2316.                      {
  2317.                      // create local vectors
  2318.  
  2319.                      // first position
  2320.  
  2321.                      alien_pos.x = aliens[index].x;
  2322.                      alien_pos.y = 45; // alien y centerline
  2323.                      alien_pos.z = aliens[index].z;
  2324.  
  2325.                      // now direction
  2326.  
  2327.                      alien_dir.x = sin_look[aliens[index].angular_heading];
  2328.                      alien_dir.y = 0;
  2329.                      alien_dir.z = cos_look[aliens[index].angular_heading];
  2330.  
  2331.                      // start the missle
  2332.  
  2333.                      Start_Missile(ALIEN_OWNER,
  2334.                                    &alien_pos,
  2335.                                    &alien_dir,
  2336.                                    aliens[index].speed+25,
  2337.                                    75);
  2338.  
  2339.                      } // end if fire a missile
  2340.  
  2341.                   } break;
  2342.  
  2343.              case ALIEN_RANDOM:
  2344.                   {
  2345.                   // continue moving in randomly selected direction
  2346.  
  2347.                   // test if it's time to select a new direction
  2348.  
  2349.                   if (++aliens[index].counter_2 > aliens[index].threshold_2)
  2350.                      {
  2351.  
  2352.                      // select a new direction  +- 30 degrees
  2353.  
  2354.                      aliens[index].angular_heading+=(-30 + 10*rand()%7);
  2355.  
  2356.                      // check angle for overflow/underflow
  2357.  
  2358.                      if (aliens[index].angular_heading >=360)
  2359.                         aliens[index].angular_heading-=360;
  2360.                      else
  2361.                      if (aliens[index].angular_heading < 0)
  2362.                         aliens[index].angular_heading+=360;
  2363.  
  2364.                      // reset counter
  2365.  
  2366.                      aliens[index].counter_2 = 0;
  2367.  
  2368.                      } // end if
  2369.  
  2370.                   // test if entire random sequence is complete
  2371.  
  2372.                   if (++aliens[index].counter_1 > aliens[index].threshold_1)
  2373.                      {
  2374.                      // tell state machine to select a new state
  2375.  
  2376.                      aliens[index].state = ALIEN_NEW_STATE;
  2377.  
  2378.                      } // end if
  2379.  
  2380.                   } break;
  2381.  
  2382.              case ALIEN_EVADE:
  2383.                   {
  2384.                   // continue evading player
  2385.  
  2386.                   // test if it's time to adjust heading to evade player
  2387.  
  2388.                   if (++aliens[index].counter_2 > aliens[index].threshold_2)
  2389.                      {
  2390.  
  2391.                      // adjust heading away from player, use a heuristic approach
  2392.                      // that simply tries to keep turing the alien away from
  2393.                      // the player
  2394.  
  2395.                      // to determine which way the alien needs to turn we
  2396.                      // can use the following trick: based on the current
  2397.                      // trajectory of the alien and the vector from the
  2398.                      // alien to the player, we can compute a normal vector
  2399.  
  2400.                      // compute heading vector (happens to be a unit vector)
  2401.  
  2402.                      head_x = sin_look[aliens[index].angular_heading];
  2403.                      head_z = cos_look[aliens[index].angular_heading];
  2404.  
  2405.                      // compute target trajectory vector, players position
  2406.                      // minus aliens position
  2407.  
  2408.                      target_x = view_point.x - aliens[index].x;
  2409.                      target_z = view_point.z - aliens[index].z;
  2410.  
  2411.                      // now compute y component of normal
  2412.  
  2413.                      normal_y = (head_z*target_x - head_x*target_z);
  2414.  
  2415.                      // based on the sign of the result we can determine if
  2416.                      // we should turn the alien right or left, but be careful
  2417.                      // we are in a LEFT HANDED system!
  2418.  
  2419.                      if (normal_y>=0)
  2420.                         aliens[index].angular_heading-=(10+rand()%10);
  2421.                      else
  2422.                         aliens[index].angular_heading+=(10+rand()%10);
  2423.  
  2424.                      // check angle for overflow/underflow
  2425.  
  2426.                      if (aliens[index].angular_heading >=360)
  2427.                         aliens[index].angular_heading-=360;
  2428.                      else
  2429.                      if (aliens[index].angular_heading < 0)
  2430.                         aliens[index].angular_heading+=360;
  2431.  
  2432.                      // reset counter
  2433.  
  2434.                      aliens[index].counter_2 = 0;
  2435.  
  2436.                      } // end if
  2437.  
  2438.                   // test if attacking sequence is complete
  2439.  
  2440.                   if (++aliens[index].counter_1 > aliens[index].threshold_1)
  2441.                      {
  2442.                      // tell state machine to select a new state
  2443.  
  2444.                      aliens[index].state = ALIEN_NEW_STATE;
  2445.  
  2446.                      } // end if
  2447.  
  2448.                   } break;
  2449.  
  2450.              case ALIEN_STOP:
  2451.                   {
  2452.                   // sit still and rotate
  2453.  
  2454.                   // test if stopping sequence is complete
  2455.  
  2456.                   if (++aliens[index].counter_1 > aliens[index].threshold_1)
  2457.                      {
  2458.                      // tell state machine to select a new state
  2459.  
  2460.                      aliens[index].state = ALIEN_NEW_STATE;
  2461.  
  2462.                      } // end if
  2463.  
  2464.                   } break;
  2465.  
  2466.              case ALIEN_TURN:
  2467.                   {
  2468.                   // continue turn
  2469.  
  2470.                   aliens[index].angular_heading+=aliens[index].aux_1;
  2471.  
  2472.                   // check angle for overflow/underflow
  2473.  
  2474.                   if (aliens[index].angular_heading >=360)
  2475.                      aliens[index].angular_heading-=360;
  2476.                   else
  2477.                   if (aliens[index].angular_heading < 0)
  2478.                      aliens[index].angular_heading+=360;
  2479.  
  2480.                   // test if turning sequence is complete
  2481.  
  2482.                   if (++aliens[index].counter_1 > aliens[index].threshold_1)
  2483.                      {
  2484.                      // tell state machine to select a new state
  2485.  
  2486.                      aliens[index].state = ALIEN_NEW_STATE;
  2487.  
  2488.                      } // end if
  2489.  
  2490.                   } break;
  2491.  
  2492.              default: break;
  2493.  
  2494.              } // end switch
  2495.  
  2496.        // now move the alien based on direction
  2497.  
  2498.        aliens[index].x +=  (aliens[index].speed*sin_look[aliens[index].angular_heading]);
  2499.        aliens[index].z +=  (aliens[index].speed*cos_look[aliens[index].angular_heading]);
  2500.  
  2501.        // perform bounds checking, if an alien hits an edge warp to other side
  2502.  
  2503.        if (aliens[index].x>(GAME_MAX_WORLD_X+750))
  2504.            aliens[index].x=(GAME_MIN_WORLD_X-500);
  2505.        else
  2506.        if (aliens[index].x<(GAME_MIN_WORLD_X-750))
  2507.            aliens[index].x=(GAME_MAX_WORLD_X+500);
  2508.  
  2509.        if (aliens[index].z>(GAME_MAX_WORLD_Z+750))
  2510.            aliens[index].z=(GAME_MIN_WORLD_Z-500);
  2511.        else
  2512.        if (aliens[index].z<(GAME_MIN_WORLD_Z-750))
  2513.            aliens[index].z=(GAME_MAX_WORLD_Z+500);
  2514.  
  2515.        } // end if alive
  2516.  
  2517.     } // end for index
  2518.  
  2519. // try and turn on dead guys at teleporters 10% chance
  2520.  
  2521. if ((rand()%10)==1)
  2522.    for (index=0; index<NUM_ALIENS; index++)
  2523.        {
  2524.        // test if this one is dead
  2525.  
  2526.        if (aliens[index].state==ALIEN_DEAD)
  2527.           {
  2528.  
  2529.           // set state to new state
  2530.  
  2531.           aliens[index].state = ALIEN_NEW_STATE;
  2532.  
  2533.           // select telepod position to start at
  2534.  
  2535.           which_pod = rand()%NUM_TELEPODS;
  2536.  
  2537.           aliens[index].x = telepods[which_pod].x;
  2538.           aliens[index].z = telepods[which_pod].z;
  2539.  
  2540.           // that's enough for now!
  2541.  
  2542.           break;
  2543.  
  2544.           } // end if
  2545.  
  2546.        } // end for index
  2547.  
  2548. } // end Process_Aliens
  2549.  
  2550. //////////////////////////////////////////////////////////////////////////////
  2551.  
  2552. void Draw_Aliens(void)
  2553. {
  2554. // this function simply draws the aliens
  2555.  
  2556. int index,       // looping variable
  2557.     diff_angle;  // used to track anglular difference between virtual object
  2558.                  // and real object
  2559.  
  2560. // draw all the aliens (ya all four of them!)
  2561.  
  2562. for (index=0; index<NUM_ALIENS; index++)
  2563.     {
  2564.     // test if missile is alive before starting 3-D processing
  2565.  
  2566.     if (aliens[index].state!=ALIEN_DEAD)
  2567.        {
  2568.  
  2569.        // which kind of alien are we dealing with?
  2570.  
  2571.        if (aliens[index].type == ALIEN_TALLON)
  2572.           {
  2573.  
  2574.           dynamic_obj[TALLONS_TEMPLATE].world_pos.x = aliens[index].x;
  2575.           dynamic_obj[TALLONS_TEMPLATE].world_pos.y = aliens[index].y;
  2576.           dynamic_obj[TALLONS_TEMPLATE].world_pos.z = aliens[index].z;
  2577.  
  2578.           if (!Remove_Object(&dynamic_obj[TALLONS_TEMPLATE],OBJECT_CULL_XYZ_MODE))
  2579.              {
  2580.  
  2581.              // rotate tallon model to proper direction for this copy of it
  2582.  
  2583.              // look in state field of model to determine current angle and then
  2584.              // compare it to the desired angle, compute the difference and
  2585.              // use the result as the rotation angle to rotate the model
  2586.              // into the proper orientation for this copy of it
  2587.  
  2588.              diff_angle = aliens[index].angular_heading -
  2589.                           dynamic_obj[TALLONS_TEMPLATE].state;
  2590.  
  2591.              // fix the sign of the angle
  2592.  
  2593.              if (diff_angle<0)
  2594.                  diff_angle+=360;
  2595.  
  2596.              // perform the rotation
  2597.  
  2598.              Rotate_Object(&dynamic_obj[TALLONS_TEMPLATE],0,diff_angle,0);
  2599.  
  2600.              // update object template with new heading
  2601.  
  2602.              dynamic_obj[TALLONS_TEMPLATE].state = aliens[index].angular_heading;
  2603.  
  2604.              // convert object local coordinates to world coordinate
  2605.  
  2606.              Local_To_World_Object(&dynamic_obj[TALLONS_TEMPLATE]);
  2607.  
  2608.              // remove the backfaces and shade object
  2609.  
  2610.              if (aliens[index].state==ALIEN_DYING)
  2611.                  Remove_Backfaces_And_Shade(&dynamic_obj[TALLONS_TEMPLATE],aliens[index].color_reg);
  2612.              else
  2613.                  Remove_Backfaces_And_Shade(&dynamic_obj[TALLONS_TEMPLATE],-1);
  2614.  
  2615.              // convert world coordinates to camera coordinate
  2616.  
  2617.              World_To_Camera_Object(&dynamic_obj[TALLONS_TEMPLATE]);
  2618.  
  2619.              // clip the objects polygons against viewing volume
  2620.  
  2621.              Clip_Object_3D(&dynamic_obj[TALLONS_TEMPLATE],CLIP_Z_MODE);
  2622.  
  2623.              // generate the final polygon list
  2624.  
  2625.              Generate_Poly_List(&dynamic_obj[TALLONS_TEMPLATE],ADD_TO_POLY_LIST);
  2626.  
  2627.              } // end if object is outside viewing volume
  2628.  
  2629.           } // end if tallon
  2630.        else
  2631.           {
  2632.  
  2633.           dynamic_obj[SLIDERS_TEMPLATE].world_pos.x = aliens[index].x;
  2634.           dynamic_obj[SLIDERS_TEMPLATE].world_pos.y = aliens[index].y;
  2635.           dynamic_obj[SLIDERS_TEMPLATE].world_pos.z = aliens[index].z;
  2636.  
  2637.           if (!Remove_Object(&dynamic_obj[SLIDERS_TEMPLATE],OBJECT_CULL_XYZ_MODE))
  2638.              {
  2639.  
  2640.              // rotate slider model to proper direction for this copy of it
  2641.  
  2642.              // look in state field of model to determine current angle and then
  2643.              // compare it to the desired angle, compute the difference and
  2644.              // use the result as the rotation angle to rotate the model
  2645.              // into the proper orientation for this copy of it
  2646.  
  2647.              diff_angle = aliens[index].angular_heading -
  2648.                           dynamic_obj[SLIDERS_TEMPLATE].state;
  2649.  
  2650.              // fix the sign of the angle
  2651.  
  2652.              if (diff_angle<0)
  2653.                  diff_angle+=360;
  2654.  
  2655.              // perform the rotation
  2656.  
  2657.              Rotate_Object(&dynamic_obj[SLIDERS_TEMPLATE],0,diff_angle,0);
  2658.  
  2659.              // update object template with new heading
  2660.  
  2661.              dynamic_obj[SLIDERS_TEMPLATE].state = aliens[index].angular_heading;
  2662.  
  2663.              // convert object local coordinates to world coordinate
  2664.  
  2665.              Local_To_World_Object(&dynamic_obj[SLIDERS_TEMPLATE]);
  2666.  
  2667.              // remove the backfaces and shade object
  2668.  
  2669.              if (aliens[index].state==ALIEN_DYING)
  2670.                  Remove_Backfaces_And_Shade(&dynamic_obj[SLIDERS_TEMPLATE],aliens[index].color_reg);
  2671.              else
  2672.                  Remove_Backfaces_And_Shade(&dynamic_obj[SLIDERS_TEMPLATE],-1);
  2673.  
  2674.              // convert world coordinates to camera coordinate
  2675.  
  2676.              World_To_Camera_Object(&dynamic_obj[SLIDERS_TEMPLATE]);
  2677.  
  2678.              // clip the objects polygons against viewing volume
  2679.  
  2680.              Clip_Object_3D(&dynamic_obj[SLIDERS_TEMPLATE],CLIP_Z_MODE);
  2681.  
  2682.              // generate the final polygon list
  2683.  
  2684.              Generate_Poly_List(&dynamic_obj[SLIDERS_TEMPLATE],ADD_TO_POLY_LIST);
  2685.  
  2686.              } // end if object is outside viewing volume
  2687.  
  2688.           } // end else slider
  2689.  
  2690.        } // end if alien alive
  2691.  
  2692.     } // end for index
  2693.  
  2694. } // end Draw_Aliens
  2695.  
  2696. /////////////////////////////////////////////////////////////////////////////
  2697.  
  2698. void Draw_Background(int mountain_pos)
  2699. {
  2700. // this function draw the gradient sky and ground for the 3-D view
  2701.  
  2702. long color; // used to build up a 4 byte color
  2703.  
  2704. // this function draws the background and mountains for the foreground
  2705. // 3-D image
  2706.  
  2707. // the sky has three layers
  2708.  
  2709. // draw layer 1
  2710.  
  2711. color = SKY_COLOR_1;
  2712.  
  2713. color = color | (color << 8);
  2714. color = color | (color << 16);
  2715.  
  2716. fquadset(double_buffer, color, 4*320/4);
  2717.  
  2718. // draw layer 2
  2719.  
  2720. color = SKY_COLOR_2;
  2721.  
  2722. color = color | (color << 8);
  2723. color = color | (color << 16);
  2724.  
  2725. fquadset(double_buffer+320*4, color, 8*320/4);
  2726.  
  2727. // draw layer 3
  2728.  
  2729. color = SKY_COLOR_3;
  2730.  
  2731. color = color | (color << 8);
  2732. color = color | (color << 16);
  2733.  
  2734. fquadset(double_buffer+320*12, color, 44*320/4);
  2735.  
  2736. // now draw the scrolling mountainscape
  2737.  
  2738. Layer_Draw((layer_ptr)&mountains,mountain_pos,0,
  2739.            double_buffer,MOUNTAIN_Y_POS,MOUNTAIN_HEIGHT,0);
  2740.  
  2741. // now draw the ground
  2742.  
  2743. // layer 1
  2744.  
  2745. color = GND_COLOR_1;
  2746.  
  2747. color = color | (color << 8);
  2748. color = color | (color << 16);
  2749.  
  2750. fquadset(double_buffer+320*99, color, 3*320/4);
  2751.  
  2752. // layer 2
  2753.  
  2754. color = GND_COLOR_2;
  2755.  
  2756. color = color | (color << 8);
  2757. color = color | (color << 16);
  2758.  
  2759. fquadset(double_buffer+320*102, color, 6*320/4);
  2760.  
  2761. color = GND_COLOR_3;
  2762.  
  2763. color = color | (color << 8);
  2764. color = color | (color << 16);
  2765.  
  2766. fquadset(double_buffer+320*108, color, 21*320/4);
  2767.  
  2768. } // end Draw_Background
  2769.  
  2770. /////////////////////////////////////////////////////////////////////////////
  2771.  
  2772. void Draw_Box(int x1,int y1,int x2, int y2,int color)
  2773. {
  2774. // this function draws a hollow rectangle
  2775.  
  2776. Line_H(x1,x2,y1,color);
  2777. Line_H(x1,x2,y2,color);
  2778. Line_V(y1,y2,x1,color);
  2779. Line_V(y1,y2,x2,color);
  2780.  
  2781. } // end Draw_Box
  2782.  
  2783. ///////////////////////////////////////////////////////////////////////////////
  2784.  
  2785. void Tech_Print(int x,int y,char *string,unsigned char far *destination)
  2786. {
  2787. // this function is used to print text out like a teletypwriter,it looks
  2788. // cool, trust me!
  2789.  
  2790. int length,  // length of input string
  2791.     index,   // looping variable
  2792.     counter; // used to time process
  2793.  
  2794. char buffer[3];  // a little string used to call font engine with
  2795.  
  2796. // compute length of input string
  2797.  
  2798. length = strlen(string);
  2799.  
  2800. // print the string out a character at a time
  2801.  
  2802. for (index=0; index<length; index++)
  2803.     {
  2804.     // the first character is the actual printable character
  2805.  
  2806.     buffer[0] = string[index];
  2807.  
  2808.     // null terminate
  2809.  
  2810.     buffer[1] = 0;
  2811.  
  2812.     // print the string
  2813.  
  2814.     Font_Engine_1(x,y,0,0,buffer,destination);
  2815.  
  2816.     // move to next position
  2817.  
  2818.     x+=(TECH_FONT_WIDTH+1);
  2819.  
  2820.     // wait a bit  1/70th of a second
  2821.  
  2822.     Wait_For_Vertical_Retrace();
  2823.  
  2824.     // clear the cursor
  2825.  
  2826.     } // end for
  2827.  
  2828. // done!
  2829.  
  2830. } // end Tech_Print
  2831.  
  2832. //////////////////////////////////////////////////////////////////////////////
  2833.  
  2834. void Font_Engine_1(int x,int y,
  2835.                    int font,int color,
  2836.                    char *string,unsigned char far *destination)
  2837. {
  2838. // this function prints a string out using one of the graphics fonts that
  2839. // we have drawn, note this first version doesn't use the font field, but
  2840. // we'll throw it in to keep the interface open for a future version
  2841.  
  2842. static int font_loaded=0;   // this is used to track the first time the
  2843.                             // function is loaded
  2844.  
  2845. int index,    // loop index
  2846.     c_index,  // character index
  2847.     length;   // used to compute lengths of strings
  2848.  
  2849. // test if this is the first time this function is called, if so load the
  2850. // font
  2851.  
  2852. if (!font_loaded)
  2853.    {
  2854.    // load the 4x7 tech font
  2855.  
  2856.    PCX_Init((pcx_picture_ptr)&image_pcx);
  2857.    PCX_Load("krkfnt.pcx", (pcx_picture_ptr)&image_pcx,1);
  2858.  
  2859.    // allocate memory for each bitmap and load character
  2860.  
  2861.    for (index=0; index<NUM_TECH_FONT; index++)
  2862.        {
  2863.        // allocate memory for charcter
  2864.  
  2865.        Bitmap_Allocate((bitmap_ptr)&tech_font[index],
  2866.                        TECH_FONT_WIDTH,TECH_FONT_HEIGHT);
  2867.  
  2868.        // set size of character
  2869.  
  2870.        tech_font[index].width = TECH_FONT_WIDTH;
  2871.        tech_font[index].height= TECH_FONT_HEIGHT;
  2872.  
  2873.        // extract bitmap from PCX buffer
  2874.  
  2875.        tech_font[index].x = 1 + (index % 16) * (TECH_FONT_WIDTH+1);
  2876.        tech_font[index].y = 1 + (index / 16) * (TECH_FONT_HEIGHT+1);
  2877.  
  2878.        Bitmap_Get((bitmap_ptr)&tech_font[index],
  2879.                   (unsigned char far *)image_pcx.buffer);
  2880.  
  2881.        } // end for index
  2882.    // font is loaded, delete pcx file and set flag
  2883.  
  2884.    PCX_Delete((pcx_picture_ptr)&image_pcx);
  2885.  
  2886.    font_loaded=1;
  2887.  
  2888.    } // end if first time
  2889. else
  2890.    {
  2891.    // print the sent string
  2892.  
  2893.    // pre-compute length of string
  2894.  
  2895.    length=strlen(string);
  2896.  
  2897.    // print the string character by character
  2898.  
  2899.    for (index=0; index<length; index++)
  2900.        {
  2901.        // extract the character index from the space character
  2902.  
  2903.        c_index = string[index] - ' ';
  2904.  
  2905.        // set bitmap position
  2906.  
  2907.        tech_font[c_index].y = y;
  2908.        tech_font[c_index].x = x;
  2909.  
  2910.        // display bitmap
  2911.  
  2912.        Bitmap_Put((bitmap_ptr)&tech_font[c_index],
  2913.                   (unsigned char far*)destination,0);
  2914.  
  2915.        // move to next character position
  2916.  
  2917.        x+=(TECH_FONT_WIDTH+1);
  2918.  
  2919.        } // end for index
  2920.  
  2921.    } // end else print string
  2922.  
  2923. } // end Font_Engine_1
  2924.  
  2925. /////////////////////////////////////////////////////////////////////////////
  2926.  
  2927. void Panel_FX(int reset)
  2928. {
  2929. // this function performs all of the special effects for the control panel
  2930.  
  2931. int index; // looping variable
  2932.  
  2933. static int panel_counter = 0;  // used to time the color rotation of the panel
  2934.  
  2935. static int entered=0; // flags if function has been entered yet
  2936.  
  2937. // test if this is the first time in function
  2938.  
  2939. if (!entered || reset)
  2940.    {
  2941.    // set entrance flag
  2942.  
  2943.    entered = 1;
  2944.  
  2945.    // set up color registers
  2946.  
  2947.    for (index=START_PANEL_REG; index<=END_PANEL_REG; index++)
  2948.        {
  2949.        // generate the color
  2950.  
  2951.        color_1.red   = 0;
  2952.        color_1.green = 0;
  2953.        color_1.blue  = 0;
  2954.  
  2955.        // write the data
  2956.  
  2957.        Write_Color_Reg(index, (RGB_color_ptr)&color_1);
  2958.  
  2959.        } // end for
  2960.  
  2961.    color_1.red   = 63;
  2962.  
  2963.    Write_Color_Reg(START_PANEL_REG,(RGB_color_ptr)&color_1);
  2964.  
  2965.    Write_Color_Reg(START_PANEL_REG+3,(RGB_color_ptr)&color_1);
  2966.  
  2967.    // set up selection indicator color
  2968.  
  2969.    color_1.red   = 30;
  2970.    color_1.green = 0;
  2971.    color_1.blue  = 0;
  2972.  
  2973.    Write_Color_Reg(SELECT_REG, (RGB_color_ptr)&color_1);
  2974.  
  2975.    } // end if entered
  2976.  
  2977. // is it time to update colors?
  2978.  
  2979. if (++panel_counter>2)
  2980.    {
  2981.    // reset counter
  2982.  
  2983.    panel_counter=0;
  2984.  
  2985.    // do animation to colors
  2986.  
  2987.    Read_Color_Reg(END_PANEL_REG, (RGB_color_ptr)&color_1);
  2988.  
  2989.    for (index=END_PANEL_REG; index>START_PANEL_REG; index--)
  2990.        {
  2991.        // read the (i-1)th register
  2992.  
  2993.        Read_Color_Reg(index-1, (RGB_color_ptr)&color_2);
  2994.  
  2995.        // assign it to the ith
  2996.  
  2997.        Write_Color_Reg(index, (RGB_color_ptr)&color_2);
  2998.  
  2999.        } // end rotate loop
  3000.  
  3001.     // place the value of the first color register into the last to
  3002.     // complete the rotation
  3003.  
  3004.     Write_Color_Reg(START_PANEL_REG, (RGB_color_ptr)&color_1);
  3005.  
  3006.    } // end if time
  3007.  
  3008. // update selection color
  3009.  
  3010. Read_Color_Reg(SELECT_REG, (RGB_color_ptr)&color_1);
  3011.  
  3012. if ((color_1.red+=5) > 63)
  3013.    color_1.red = 25;
  3014.  
  3015. Write_Color_Reg(SELECT_REG, (RGB_color_ptr)&color_1);
  3016.  
  3017. } // end Panel_FX
  3018.  
  3019. /////////////////////////////////////////////////////////////////////////////
  3020.  
  3021. void Intro_Planet(void)
  3022. {
  3023. // this function does the introdcution to centari alpha 3
  3024.  
  3025. int index; // looping variable
  3026.  
  3027. // data output fields
  3028.  
  3029. static char *template[]={"PLANET:   ",
  3030.                          "TYPE:     ",
  3031.                          "MASS:     ",
  3032.                          "TEMP:     ",
  3033.                          "PERIOD:   ",
  3034.                          "LIFEFORMS:",
  3035.                          "STATUS:   ",};
  3036.  
  3037. // the data for each field
  3038.  
  3039. static char *data[] = {" CENTARI ALPHA 3",
  3040.                        " F-CLASS, AMMONIUM ATMOSPHERE",
  3041.                        " 20.6 KELA",
  3042.                        " 150.2 DEG",
  3043.                        " 3.2 TELGANS",
  3044.                        " SILICA BASED, PHOSPOROUS METABOLIZERS",
  3045.                        " BATTLE AREA - RESTRICTED" };
  3046.  
  3047. // load in the KRK title screen
  3048.  
  3049. PCX_Init((pcx_picture_ptr)&image_pcx);
  3050. PCX_Load("krkredp.pcx",(pcx_picture_ptr)&image_pcx,1);
  3051.  
  3052. // show the PCX buffer
  3053.  
  3054. PCX_Show_Buffer((pcx_picture_ptr)&image_pcx);
  3055.  
  3056. // done with data so delete it
  3057.  
  3058. PCX_Delete((pcx_picture_ptr)&image_pcx);
  3059.  
  3060. // do special effects
  3061.  
  3062. Time_Delay(50);
  3063.  
  3064. // draw out statistics
  3065.  
  3066. for (index=0; index<7; index++)
  3067.     {
  3068.  
  3069.     // draw header field
  3070.  
  3071.     Font_Engine_1(START_MESS_X,START_MESS_Y+index*10,0,0,
  3072.                   template[index],
  3073.                   video_buffer);
  3074.  
  3075.  
  3076.     // draw information for field
  3077.  
  3078.     Tech_Print(START_MESS_X+80,START_MESS_Y+index*10,data[index],video_buffer);
  3079.  
  3080.     Time_Delay(20);
  3081.  
  3082.     } // end for index
  3083.  
  3084. // wait for a sec
  3085.  
  3086. Time_Delay(50);
  3087.  
  3088. } // end Intro_Planet
  3089.  
  3090. //////////////////////////////////////////////////////////////////////////////
  3091.  
  3092. void Closing_Screen(void)
  3093. {
  3094. // this function prints the credits
  3095.  
  3096. int index;  // looping variable
  3097.  
  3098. static char *extra_credits[] = {"EXTRA CREDITS",
  3099.                                 "             ",
  3100.                                 "MUSICAL MASTERY BY",
  3101.                                 "DEAN HUDSON OF",
  3102.                                 "ECLIPSE PRODUCTIONS",
  3103.                                 "                   ",
  3104.                                 "MIDPAK INSTRUMENTATION CONSULTING BY",
  3105.                                 "ROB WALLACE OF",
  3106.                                 "WALLACE MUSIC & SOUND",
  3107.                                 "                     ",
  3108.                                 "TITLE SCREEN BY",
  3109.                                 "RICHARD BENSON"};
  3110.  
  3111. // blank the screen
  3112.  
  3113. Fill_Screen(0);
  3114.  
  3115. // restore pallete
  3116.  
  3117. Write_Palette(0,255,(RGB_palette_ptr)&game_palette);
  3118.  
  3119. if (music_enabled)
  3120.    {
  3121.    Music_Stop();
  3122.    Music_Play((music_ptr)&song,11);
  3123.    } // end if
  3124.  
  3125. // print out the credits
  3126.  
  3127. for (index=0; index<=11; index++)
  3128.     {
  3129.  
  3130.     Tech_Print(160-(TECH_FONT_WIDTH+1)*(strlen(extra_credits[index])/2),
  3131.                8+index*(TECH_FONT_HEIGHT+4),
  3132.                extra_credits[index],video_buffer);
  3133.  
  3134.     if (keys_active)
  3135.        return;
  3136.  
  3137.     Time_Delay(10);
  3138.  
  3139.     } // end for index
  3140.  
  3141. Time_Delay(50);
  3142.  
  3143. // scroll them away
  3144.  
  3145. for (index=0; index<135; index++)
  3146.     {
  3147.     fquadcpy(video_buffer,video_buffer+320,16000-80);
  3148.  
  3149.     // test for exit
  3150.  
  3151.     if (keys_active)
  3152.        return;
  3153.  
  3154.     } // end for index
  3155.  
  3156. } // end Closing_Screen
  3157.  
  3158. //////////////////////////////////////////////////////////////////////////////
  3159.  
  3160. void Intro_Waite(void)
  3161. {
  3162. // load in the waite group title screen
  3163.  
  3164. PCX_Init((pcx_picture_ptr)&image_pcx);
  3165. PCX_Load("waite.pcx",(pcx_picture_ptr)&image_pcx,1);
  3166.  
  3167. // done with data so delete it
  3168.  
  3169. PCX_Delete((pcx_picture_ptr)&image_pcx);
  3170.  
  3171. // show the PCX buffer
  3172.  
  3173. PCX_Show_Buffer((pcx_picture_ptr)&image_pcx);
  3174.  
  3175. // do special effects
  3176.  
  3177. // wait for a sec
  3178.  
  3179. Time_Delay(40);
  3180.  
  3181. Screen_Transition(SCREEN_WHITENESS);
  3182.  
  3183. // blank the screen
  3184.  
  3185. Fill_Screen(0);
  3186.  
  3187. } // end Intro_Waite
  3188.  
  3189. //////////////////////////////////////////////////////////////////////////////
  3190.  
  3191. void Intro_KRK(void)
  3192. {
  3193. // load in the main title screen group title screen
  3194.  
  3195. PCX_Init((pcx_picture_ptr)&image_pcx);
  3196. PCX_Load("krkfirst.pcx",(pcx_picture_ptr)&image_pcx,1);
  3197.  
  3198. // done with data so delete it
  3199.  
  3200. PCX_Delete((pcx_picture_ptr)&image_pcx);
  3201.  
  3202. // show the PCX buffer
  3203.  
  3204. PCX_Show_Buffer((pcx_picture_ptr)&image_pcx);
  3205.  
  3206. // do special effects
  3207.  
  3208. // wait for a sec
  3209.  
  3210. Time_Delay(50);
  3211.  
  3212. Screen_Transition(SCREEN_DARKNESS);
  3213.  
  3214. // blank the screen
  3215.  
  3216. Fill_Screen(0);
  3217.  
  3218. } // end Intro_KRK
  3219.  
  3220. //////////////////////////////////////////////////////////////////////////////
  3221.  
  3222. void Intro_Controls(void)
  3223. {
  3224. // this function displays the controls screen
  3225.  
  3226. // load in the starblazer controls screen
  3227.  
  3228. PCX_Init((pcx_picture_ptr)&image_controls);
  3229. PCX_Load("krkredpc.pcx",(pcx_picture_ptr)&image_controls,1);
  3230.  
  3231. // copy controls data to video buffer
  3232.  
  3233. PCX_Show_Buffer((pcx_picture_ptr)&image_controls);
  3234.  
  3235. // delete pcx file
  3236.  
  3237. PCX_Delete((pcx_picture_ptr)&image_controls);
  3238.  
  3239. } // end Intro_Controls
  3240.  
  3241. ////////////////////////////////////////////////////////////////////////////
  3242.  
  3243. void Intro_Briefing(void)
  3244. {
  3245. // this function displays the briefing screen
  3246.  
  3247. int done=0, // exit flag
  3248.     page=0, // current page user is reading
  3249.     index;  // looping variable
  3250.  
  3251. // load in the starblazer controls screen
  3252.  
  3253. PCX_Init((pcx_picture_ptr)&image_controls);
  3254. PCX_Load("krkins.pcx",(pcx_picture_ptr)&image_controls,0);
  3255.  
  3256. // copy controls data to video buffer
  3257.  
  3258. PCX_Show_Buffer((pcx_picture_ptr)&image_controls);
  3259.  
  3260. // delete pcx file
  3261.  
  3262. PCX_Delete((pcx_picture_ptr)&image_controls);
  3263.  
  3264. // display the first page
  3265.  
  3266. for (index=0; index<NUM_LINES_PAGE; index++)
  3267.     Font_Engine_1(78,24+index*8,0,0,instructions[index+page*17],video_buffer);
  3268.  
  3269. // enter main event loop
  3270.  
  3271. while(!done)
  3272.      {
  3273.      // has the user pressed a key
  3274.  
  3275.      if (keys_active>0)
  3276.         {
  3277.  
  3278.         if (keyboard_state[MAKE_UP])
  3279.            {
  3280.            // page up
  3281.  
  3282.            if (--page<0)
  3283.               page = 0;
  3284.  
  3285.            // press button
  3286.  
  3287.            Digital_FX_Play(KRKKEY_VOC,3);
  3288.  
  3289.            Time_Delay(2);
  3290.  
  3291.            } // end if up
  3292.  
  3293.         if (keyboard_state[MAKE_DOWN])
  3294.            {
  3295.            // page down
  3296.  
  3297.            if (++page>=NUM_PAGES)
  3298.               page = NUM_PAGES-1;
  3299.  
  3300.            // press button
  3301.  
  3302.            Digital_FX_Play(KRKKEY_VOC,3);
  3303.  
  3304.            Time_Delay(2);
  3305.  
  3306.            } // end if down
  3307.  
  3308.         if (keyboard_state[MAKE_ESC])
  3309.            {
  3310.  
  3311.            Digital_FX_Play(KRKKEY_VOC,3);
  3312.  
  3313.            done=1;
  3314.  
  3315.            } // end if esc
  3316.  
  3317.         // refresh display
  3318.  
  3319.         for (index=0; index<NUM_LINES_PAGE; index++)
  3320.             Font_Engine_1(78,24+index*8,0,0,instructions[index+page*17],video_buffer);
  3321.  
  3322.         } // end if a key has been pressed
  3323.  
  3324.      // wait a sec
  3325.  
  3326.      Time_Delay(1);
  3327.  
  3328.      // check on music
  3329.  
  3330.      if (music_enabled)
  3331.         {
  3332.         // test if piece is complete or has been stopped
  3333.  
  3334.         if (Music_Status()==2 || Music_Status()==0)
  3335.            {
  3336.            // advance to next sequence
  3337.  
  3338.            if (++intro_seq_index==14)
  3339.               intro_seq_index=0;
  3340.  
  3341.            Music_Play((music_ptr)&song,intro_sequence[intro_seq_index]);
  3342.  
  3343.            } // end if
  3344.  
  3345.         } // end if music enabled
  3346.  
  3347.      } // end main while
  3348.  
  3349. } // end Intro_Briefing
  3350.  
  3351. //////////////////////////////////////////////////////////////////////////////
  3352.  
  3353. void Reset_System(void)
  3354. {
  3355. // this function resets everything so the game can be ran again
  3356. // I hope I didn't leave anything out?
  3357.  
  3358. scanner_state  = 0;
  3359. hud_state      = 0;
  3360. tactical_state = TACTICAL_MODE_OFF;
  3361.  
  3362. ship_pitch     = 0;
  3363. ship_yaw       = 0;
  3364. ship_roll      = 0;
  3365. ship_speed     = 0;
  3366. ship_energy    = 50;
  3367. ship_damage    = 0;
  3368. ship_message   = SHIP_STABLE;
  3369. ship_timer     = 0;
  3370. ship_kills     = 0;
  3371. ship_deaths    = 0;
  3372.  
  3373. // reset back to power station
  3374.  
  3375. view_point.x = 0;
  3376. view_point.z = 0;
  3377.  
  3378. } // end Reset_System
  3379.  
  3380. /////////////////////////////////////////////////////////////////////////////
  3381.  
  3382. void Music_Init(void)
  3383. {
  3384. // this function loads the music and resets all the indexes
  3385.  
  3386. static int loaded=0;
  3387.  
  3388. // has the music already been loaded
  3389.  
  3390. if (!music_enabled)
  3391.    return;
  3392.  
  3393. if (!loaded)
  3394.    {
  3395.    Music_Load("krkmus.xmi",(music_ptr)&song);
  3396.    loaded=1;
  3397.    } // end if not loaded
  3398.  
  3399. // reset sequence counters
  3400.  
  3401. game_seq_index=0;
  3402. intro_seq_index=0;
  3403.  
  3404. } // end Music_Init
  3405.  
  3406. /////////////////////////////////////////////////////////////////////////////
  3407.  
  3408. void Music_Close(void)
  3409. {
  3410. // this function unloads the music files
  3411.  
  3412. if (!music_enabled)
  3413.    return;
  3414.  
  3415. // turn off music and unload song
  3416.  
  3417. Music_Stop();
  3418. Music_Unload((music_ptr)&song);
  3419.  
  3420. } // end Music_Close
  3421.  
  3422. //////////////////////////////////////////////////////////////////////////////
  3423.  
  3424. void Digital_FX_Init(void)
  3425. {
  3426. // this function initializes the digital sound fx system
  3427.  
  3428. static int loaded=0;
  3429.  
  3430. if (!digital_enabled)
  3431.    return;
  3432.  
  3433. // have the sound fx been loaded?
  3434.  
  3435. if (!loaded)
  3436.    {
  3437.    // load int sounds
  3438.  
  3439.    Sound_Load("KRKMIS.VOC" ,  (sound_ptr)&digital_FX[KRKMIS_VOC ] ,1);
  3440.    Sound_Load("KRKEMIS2.VOC",  (sound_ptr)&digital_FX[KRKEMIS_VOC],1);
  3441.    Sound_Load("KRKTAC.VOC" ,  (sound_ptr)&digital_FX[KRKTAC_VOC ],1);
  3442.    Sound_Load("KRKSCN.VOC" ,  (sound_ptr)&digital_FX[KRKSCN_VOC ],1);
  3443.    Sound_Load("KRKHUD.VOC" ,  (sound_ptr)&digital_FX[KRKHUD_VOC ],1);
  3444.  
  3445.    Sound_Load("KRKKEY.VOC" ,  (sound_ptr)&digital_FX[KRKKEY_VOC ],1);
  3446.    Sound_Load("KRKEX1.VOC" ,  (sound_ptr)&digital_FX[KRKEX1_VOC ],1);
  3447.    Sound_Load("KRKEX2.VOC" ,  (sound_ptr)&digital_FX[KRKEX2_VOC ],1);
  3448.  
  3449.    // set loaded flag
  3450.  
  3451.    loaded=1;
  3452.  
  3453.    } // end if sound effects aren't loaded
  3454.  
  3455. } // end Digital_FX_Init
  3456.  
  3457. ///////////////////////////////////////////////////////////////////////////////
  3458.  
  3459. void Digital_FX_Close(void)
  3460. {
  3461. // this function unloads all the digital FX
  3462.  
  3463. if (!digital_enabled)
  3464.    return;
  3465.  
  3466. // unload all the sound fx from memory
  3467.  
  3468. Sound_Unload((sound_ptr)&digital_FX[KRKMIS_VOC]);
  3469. Sound_Unload((sound_ptr)&digital_FX[KRKEMIS_VOC]);
  3470. Sound_Unload((sound_ptr)&digital_FX[KRKTAC_VOC]);
  3471. Sound_Unload((sound_ptr)&digital_FX[KRKSCN_VOC]);
  3472. Sound_Unload((sound_ptr)&digital_FX[KRKHUD_VOC]);
  3473.  
  3474. Sound_Unload((sound_ptr)&digital_FX[KRKPOW_VOC]);
  3475. Sound_Unload((sound_ptr)&digital_FX[KRKKEY_VOC]);
  3476. Sound_Unload((sound_ptr)&digital_FX[KRKEX1_VOC]);
  3477. Sound_Unload((sound_ptr)&digital_FX[KRKEX2_VOC]);
  3478.  
  3479. } // end Digital_FX_Close
  3480.  
  3481. /////////////////////////////////////////////////////////////////////////////
  3482.  
  3483. int Digital_FX_Play(int the_effect, int priority)
  3484. {
  3485. // this function is used to play a digital effect using a pre-emptive priority
  3486. // scheme. The algorithm works like this: if a sound is playing then its
  3487. // priority is compared to the sound that is being requested to be played
  3488. // if the new sound has higher priority (a smaller number) then the currenlty
  3489. // playing sound is pre-empted for the new sound and the global FX priority
  3490. // is set to the new sound. If there is no sound playing then the new sound
  3491. // is simple played and the global priority is set
  3492.  
  3493. // is the digital fx system on-line?
  3494.  
  3495. if (!digital_enabled)
  3496.    return(0);
  3497.  
  3498. // is there a sound playing?
  3499.  
  3500. if (!Sound_Status() || (priority <= digital_FX_priority))
  3501.    {
  3502.    // start new sound
  3503.  
  3504.    Sound_Stop();
  3505.  
  3506.    Sound_Play((sound_ptr)&digital_FX[the_effect]);
  3507.  
  3508.    // set the priority
  3509.  
  3510.    digital_FX_priority = priority;
  3511.  
  3512.    return(1);
  3513.  
  3514.    } // end if
  3515. else // the current sound is of higher priority
  3516.    return(0);
  3517.  
  3518. } // end Digital_FX_Play
  3519.  
  3520. /////////////////////////////////////////////////////////////////////////////
  3521.  
  3522. int Parse_Commands(int argc, char **argv)
  3523. {
  3524. // this function is used to parse the commands line parameters that are to be
  3525. // used as switched to enable different modes of operation
  3526.  
  3527. int index;  // looping variable
  3528.  
  3529. for (index=1; index<argc; index++)
  3530.     {
  3531.     // get the first character from the string
  3532.  
  3533.     switch(argv[index][0])
  3534.           {
  3535.  
  3536.           case 's': // enable sound effects
  3537.           case 'S':
  3538.                {
  3539.                digital_enabled=1;
  3540.                } break;
  3541.  
  3542.           case 'm': // enable nusic
  3543.           case 'M':
  3544.                {
  3545.                music_enabled=1;
  3546.                } break;
  3547.  
  3548.           // more commands would go here...
  3549.  
  3550.           default:break;
  3551.  
  3552.           } // end switch
  3553.  
  3554.     } // end for index
  3555.  
  3556. } // end Parse_Commands
  3557.  
  3558. ////////////////////////////////////////////////////////////////////////////
  3559.  
  3560. void Draw_Stationary_Objects(void)
  3561. {
  3562. // this function draws all the stationary non active objects
  3563.  
  3564. int index; // looping index
  3565.  
  3566. // phase 0: obstacle type one
  3567.  
  3568. for (index=0; index<NUM_OBSTACLES_1; index++)
  3569.     {
  3570.     // test if object is visible
  3571.  
  3572.     // now before we continue to process object, we must
  3573.     // move it to the proper world position
  3574.  
  3575.     static_obj[OBSTACLES_1_TEMPLATE].world_pos.x = obstacles_1[index].x;
  3576.     static_obj[OBSTACLES_1_TEMPLATE].world_pos.y = obstacles_1[index].y;
  3577.     static_obj[OBSTACLES_1_TEMPLATE].world_pos.z = obstacles_1[index].z;
  3578.  
  3579.     if (!Remove_Object(&static_obj[OBSTACLES_1_TEMPLATE],OBJECT_CULL_XYZ_MODE))
  3580.        {
  3581.  
  3582.        // convert object local coordinates to world coordinate
  3583.  
  3584.        Local_To_World_Object(&static_obj[OBSTACLES_1_TEMPLATE]);
  3585.  
  3586.        // remove the backfaces and shade object
  3587.  
  3588.        Remove_Backfaces_And_Shade(&static_obj[OBSTACLES_1_TEMPLATE],-1);
  3589.  
  3590.        // convert world coordinates to camera coordinate
  3591.  
  3592.        World_To_Camera_Object(&static_obj[OBSTACLES_1_TEMPLATE]);
  3593.  
  3594.        // clip the objects polygons against viewing volume
  3595.  
  3596.        Clip_Object_3D(&static_obj[OBSTACLES_1_TEMPLATE],CLIP_Z_MODE);
  3597.  
  3598.        // generate the final polygon list
  3599.  
  3600.        Generate_Poly_List(&static_obj[OBSTACLES_1_TEMPLATE],ADD_TO_POLY_LIST);
  3601.        }
  3602.  
  3603.     }  // end for index
  3604.  
  3605. // phase 1: obstacle type two
  3606.  
  3607. for (index=0; index<NUM_OBSTACLES_2; index++)
  3608.     {
  3609.     // test if object is visible
  3610.  
  3611.     // now before we continue to process object, we must
  3612.     // move it to the proper world position
  3613.  
  3614.     static_obj[OBSTACLES_2_TEMPLATE].world_pos.x = obstacles_2[index].x;
  3615.     static_obj[OBSTACLES_2_TEMPLATE].world_pos.y = obstacles_2[index].y;
  3616.     static_obj[OBSTACLES_2_TEMPLATE].world_pos.z = obstacles_2[index].z;
  3617.  
  3618.     if (!Remove_Object(&static_obj[OBSTACLES_2_TEMPLATE],OBJECT_CULL_XYZ_MODE))
  3619.        {
  3620.  
  3621.        // convert object local coordinates to world coordinate
  3622.  
  3623.        Local_To_World_Object(&static_obj[OBSTACLES_2_TEMPLATE]);
  3624.  
  3625.        // remove the backfaces and shade object
  3626.  
  3627.        Remove_Backfaces_And_Shade(&static_obj[OBSTACLES_2_TEMPLATE],-1);
  3628.  
  3629.        // convert world coordinates to camera coordinate
  3630.  
  3631.        World_To_Camera_Object(&static_obj[OBSTACLES_2_TEMPLATE]);
  3632.  
  3633.        // clip the objects polygons against viewing volume
  3634.  
  3635.        Clip_Object_3D(&static_obj[OBSTACLES_2_TEMPLATE],CLIP_Z_MODE);
  3636.  
  3637.        // generate the final polygon list
  3638.  
  3639.        Generate_Poly_List(&static_obj[OBSTACLES_2_TEMPLATE],ADD_TO_POLY_LIST);
  3640.        }
  3641.  
  3642.     }  // end for index
  3643.  
  3644. // phase 2: the towers
  3645.  
  3646. for (index=0; index<NUM_TOWERS; index++)
  3647.     {
  3648.     // test if object is visible
  3649.  
  3650.     // now before we continue to process object, we must
  3651.     // move it to the proper world position
  3652.  
  3653.     static_obj[TOWERS_TEMPLATE].world_pos.x = towers[index].x;
  3654.     static_obj[TOWERS_TEMPLATE].world_pos.y = towers[index].y;
  3655.     static_obj[TOWERS_TEMPLATE].world_pos.z = towers[index].z;
  3656.  
  3657.     if (!Remove_Object(&static_obj[TOWERS_TEMPLATE],OBJECT_CULL_XYZ_MODE))
  3658.        {
  3659.  
  3660.        // convert object local coordinates to world coordinate
  3661.  
  3662.        Local_To_World_Object(&static_obj[TOWERS_TEMPLATE]);
  3663.  
  3664.        // remove the backfaces and shade object
  3665.  
  3666.        Remove_Backfaces_And_Shade(&static_obj[TOWERS_TEMPLATE],-1);
  3667.  
  3668.        // convert world coordinates to camera coordinate
  3669.  
  3670.        World_To_Camera_Object(&static_obj[TOWERS_TEMPLATE]);
  3671.  
  3672.        // clip the objects polygons against viewing volume
  3673.  
  3674.        Clip_Object_3D(&static_obj[TOWERS_TEMPLATE],CLIP_Z_MODE);
  3675.  
  3676.        // generate the final polygon list
  3677.  
  3678.        Generate_Poly_List(&static_obj[TOWERS_TEMPLATE],ADD_TO_POLY_LIST);
  3679.        }
  3680.  
  3681.     }  // end for index
  3682.  
  3683.  
  3684. // phase 3: the barriers
  3685.  
  3686. for (index=0; index<NUM_BARRIERS; index++)
  3687.     {
  3688.     // test if object is visible
  3689.  
  3690.     // now before we continue to process object, we must
  3691.     // move it to the proper world position
  3692.  
  3693.     static_obj[BARRIERS_TEMPLATE].world_pos.x = barriers[index].x;
  3694.     static_obj[BARRIERS_TEMPLATE].world_pos.y = barriers[index].y;
  3695.     static_obj[BARRIERS_TEMPLATE].world_pos.z = barriers[index].z;
  3696.  
  3697.     if (!Remove_Object(&static_obj[BARRIERS_TEMPLATE],OBJECT_CULL_XYZ_MODE))
  3698.        {
  3699.  
  3700.        // convert object local coordinates to world coordinate
  3701.  
  3702.        Local_To_World_Object(&static_obj[BARRIERS_TEMPLATE]);
  3703.  
  3704.        // remove the backfaces and shade object
  3705.  
  3706.        Remove_Backfaces_And_Shade(&static_obj[BARRIERS_TEMPLATE],-1);
  3707.  
  3708.        // convert world coordinates to camera coordinate
  3709.  
  3710.        World_To_Camera_Object(&static_obj[BARRIERS_TEMPLATE]);
  3711.  
  3712.        // clip the objects polygons against viewing volume
  3713.  
  3714.        Clip_Object_3D(&static_obj[BARRIERS_TEMPLATE],CLIP_Z_MODE);
  3715.  
  3716.        // generate the final polygon list
  3717.  
  3718.        Generate_Poly_List(&static_obj[BARRIERS_TEMPLATE],ADD_TO_POLY_LIST);
  3719.        }
  3720.  
  3721.     }  // end for index
  3722.  
  3723.  
  3724.  
  3725. // phase 4: the main power station
  3726.  
  3727. for (index=0; index<NUM_STATIONS; index++)
  3728.     {
  3729.     // test if object is visible
  3730.  
  3731.     // now before we continue to process object, we must
  3732.     // move it to the proper world position
  3733.  
  3734.     static_obj[STATIONS_TEMPLATE].world_pos.x = stations[index].x;
  3735.     static_obj[STATIONS_TEMPLATE].world_pos.y = stations[index].y;
  3736.     static_obj[STATIONS_TEMPLATE].world_pos.z = stations[index].z;
  3737.  
  3738.     if (!Remove_Object(&static_obj[STATIONS_TEMPLATE],OBJECT_CULL_XYZ_MODE))
  3739.        {
  3740.        // convert object local coordinates to world coordinate
  3741.  
  3742.        Local_To_World_Object(&static_obj[STATIONS_TEMPLATE]);
  3743.  
  3744.        // remove the backfaces and shade object
  3745.  
  3746.        Remove_Backfaces_And_Shade(&static_obj[STATIONS_TEMPLATE],-1);
  3747.  
  3748.        // convert world coordinates to camera coordinate
  3749.  
  3750.        World_To_Camera_Object(&static_obj[STATIONS_TEMPLATE]);
  3751.  
  3752.        // clip the objects polygons against viewing volume
  3753.  
  3754.        Clip_Object_3D(&static_obj[STATIONS_TEMPLATE],CLIP_Z_MODE);
  3755.  
  3756.        // generate the final polygon list
  3757.  
  3758.        Generate_Poly_List(&static_obj[STATIONS_TEMPLATE],ADD_TO_POLY_LIST);
  3759.        }
  3760.  
  3761.     }  // end for index
  3762.  
  3763. // phase 5: the telepods
  3764.  
  3765. for (index=0; index<NUM_TELEPODS; index++)
  3766.     {
  3767.     // test if object is visible
  3768.  
  3769.     // now before we continue to process object, we must
  3770.     // move it to the proper world position
  3771.  
  3772.     static_obj[TELEPODS_TEMPLATE].world_pos.x = telepods[index].x;
  3773.     static_obj[TELEPODS_TEMPLATE].world_pos.y = telepods[index].y;
  3774.     static_obj[TELEPODS_TEMPLATE].world_pos.z = telepods[index].z;
  3775.  
  3776.     if (!Remove_Object(&static_obj[TELEPODS_TEMPLATE],OBJECT_CULL_XYZ_MODE))
  3777.        {
  3778.        // convert object local coordinates to world coordinate
  3779.  
  3780.        Local_To_World_Object(&static_obj[TELEPODS_TEMPLATE]);
  3781.  
  3782.        // remove the backfaces and shade object
  3783.  
  3784.        Remove_Backfaces_And_Shade(&static_obj[TELEPODS_TEMPLATE],-1);
  3785.  
  3786.        // convert world coordinates to camera coordinate
  3787.  
  3788.        World_To_Camera_Object(&static_obj[TELEPODS_TEMPLATE]);
  3789.  
  3790.        // clip the objects polygons against viewing volume
  3791.  
  3792.        Clip_Object_3D(&static_obj[TELEPODS_TEMPLATE],CLIP_Z_MODE);
  3793.  
  3794.        // generate the final polygon list
  3795.  
  3796.        Generate_Poly_List(&static_obj[TELEPODS_TEMPLATE],ADD_TO_POLY_LIST);
  3797.        }
  3798.  
  3799.     }  // end for index
  3800.  
  3801. } // end Draw_Stationary_Objects
  3802.  
  3803. ///////////////////////////////////////////////////////////////////////////////
  3804.  
  3805. void Set_3D_View(void)
  3806. {
  3807. // this function sets up the 3d viewing system for the game
  3808.  
  3809. // set 2-D clipping region to take into consideration the instrument panels
  3810.  
  3811. poly_clip_min_y  = 0;
  3812. poly_clip_max_y  = 128;
  3813.  
  3814. // set up viewing and 3D clipping parameters
  3815.  
  3816. clip_near_z      = 125,
  3817. clip_far_z       = 6000,
  3818. viewing_distance = 250;
  3819.  
  3820. // turn the damn light up a bit!
  3821.  
  3822. ambient_light    = 8;
  3823.  
  3824. light_source.x   = 0.918926;
  3825. light_source.y   = 0.248436;
  3826. light_source.z   = -0.306359;
  3827.  
  3828. view_point.x = 0;
  3829. view_point.y = 40;
  3830. view_point.z = 0;
  3831.  
  3832. } // end Set_3D_View
  3833.  
  3834. ////////////////////////////////////////////////////////////////////////////////
  3835.  
  3836. void Load_3D_Objects(void)
  3837. {
  3838. // this function loads the 3-D models
  3839.  
  3840. int index; // looping variable
  3841.  
  3842. // load in dynamic game objects
  3843.  
  3844. // load in missile template
  3845.  
  3846. PLG_Load_Object(&dynamic_obj[MISSILES_TEMPLATE],"missile.plg",2);
  3847.  
  3848. // first fix template object at (0,0,0)
  3849.  
  3850. dynamic_obj[MISSILES_TEMPLATE].world_pos.x = 0;
  3851. dynamic_obj[MISSILES_TEMPLATE].world_pos.y = 0;
  3852. dynamic_obj[MISSILES_TEMPLATE].world_pos.z = 0;
  3853.  
  3854.  
  3855. // load in tallon alien template
  3856.  
  3857. PLG_Load_Object(&dynamic_obj[TALLONS_TEMPLATE],"tallon.plg",1);
  3858.  
  3859. // first fix template object at (0,0,0)
  3860.  
  3861. dynamic_obj[TALLONS_TEMPLATE].world_pos.x = 0;
  3862. dynamic_obj[TALLONS_TEMPLATE].world_pos.y = 0;
  3863. dynamic_obj[TALLONS_TEMPLATE].world_pos.z = 0;
  3864.  
  3865. // the "state" field is going to track the current angle of the object
  3866.  
  3867. dynamic_obj[TALLONS_TEMPLATE].state = 0; // pointing directly down the positive
  3868.                                          // Z-axis, this is the neutral position
  3869.  
  3870. // load in slider alien template
  3871.  
  3872. PLG_Load_Object(&dynamic_obj[SLIDERS_TEMPLATE],"slider.plg",1);
  3873.  
  3874. // first fix template object at (0,0,0)
  3875.  
  3876. dynamic_obj[SLIDERS_TEMPLATE].world_pos.x = 0;
  3877. dynamic_obj[SLIDERS_TEMPLATE].world_pos.y = 0;
  3878. dynamic_obj[SLIDERS_TEMPLATE].world_pos.z = 0;
  3879.  
  3880. // the "state" field is going to track the current angle of the object
  3881.  
  3882. dynamic_obj[SLIDERS_TEMPLATE].state = 0; // pointing directly down the positive
  3883.                                          // Z-axis, this is the neutral position
  3884.  
  3885.  
  3886. // load in static game objects, background, obstacles, etc.
  3887.  
  3888. // load in obstacle one template
  3889.  
  3890. PLG_Load_Object(&static_obj[OBSTACLES_1_TEMPLATE],"pylons.plg",1);
  3891.  
  3892. // first fix template object at (0,0,0)
  3893.  
  3894. static_obj[OBSTACLES_1_TEMPLATE].world_pos.x = 0;
  3895. static_obj[OBSTACLES_1_TEMPLATE].world_pos.y = 0;
  3896. static_obj[OBSTACLES_1_TEMPLATE].world_pos.z = 0;
  3897.  
  3898. // now position all obstacle copies
  3899.  
  3900. for (index=0; index<NUM_OBSTACLES_1; index++)
  3901.     {
  3902.  
  3903.     obstacles_1[index].state = 1;
  3904.     obstacles_1[index].rx    = 0;
  3905.     obstacles_1[index].ry    = 0;
  3906.     obstacles_1[index].rz    = 0;
  3907.     obstacles_1[index].x     = -8000 + rand()%16000;
  3908.     obstacles_1[index].y     = 0;
  3909.     obstacles_1[index].z     = -8000 + rand()%16000;
  3910.  
  3911.     } // end for index
  3912.  
  3913.  
  3914. // load in obstacle two template
  3915.  
  3916. PLG_Load_Object(&static_obj[OBSTACLES_2_TEMPLATE],"rock.plg",1);
  3917.  
  3918. // first fix template object at (0,0,0)
  3919.  
  3920. static_obj[OBSTACLES_2_TEMPLATE].world_pos.x = 0;
  3921. static_obj[OBSTACLES_2_TEMPLATE].world_pos.y = 0;
  3922. static_obj[OBSTACLES_2_TEMPLATE].world_pos.z = 0;
  3923.  
  3924. // now position all obstacle copies
  3925.  
  3926. for (index=0; index<NUM_OBSTACLES_2; index++)
  3927.     {
  3928.  
  3929.     obstacles_2[index].state = 1;
  3930.     obstacles_2[index].rx    = 0;
  3931.     obstacles_2[index].ry    = 0;
  3932.     obstacles_2[index].rz    = 0;
  3933.     obstacles_2[index].x     = -8000 + rand()%16000;
  3934.     obstacles_2[index].y     = 0;
  3935.     obstacles_2[index].z     = -8000 + rand()%16000;
  3936.  
  3937.     } // end for index
  3938.  
  3939. // load in tower template
  3940.  
  3941. PLG_Load_Object(&static_obj[TOWERS_TEMPLATE],"tower.plg",2);
  3942.  
  3943. // first fix template object at (0,0,0)
  3944.  
  3945. static_obj[TOWERS_TEMPLATE].world_pos.x = 0;
  3946. static_obj[TOWERS_TEMPLATE].world_pos.y = 0;
  3947. static_obj[TOWERS_TEMPLATE].world_pos.z = 0;
  3948.  
  3949. // now position all tower copies
  3950.  
  3951. for (index=0; index<NUM_TOWERS; index++)
  3952.     {
  3953.  
  3954.     towers[index].state = 1;
  3955.     towers[index].rx    = 0;
  3956.     towers[index].ry    = 0;
  3957.     towers[index].rz    = 0;
  3958.     towers[index].x     = 0;
  3959.     towers[index].y     = 0;
  3960.     towers[index].z     = 0;
  3961.  
  3962.     } // end for index
  3963.  
  3964. // position the towers
  3965.  
  3966. towers[0].x = -1500;
  3967. towers[0].z = 1500;
  3968.  
  3969. towers[1].x = -1500;
  3970. towers[1].z = -1500;
  3971.  
  3972. towers[2].x = 1500;
  3973. towers[2].z = -1500;
  3974.  
  3975. towers[3].x = 1500;
  3976. towers[3].z = 1500;
  3977.  
  3978.  
  3979.  
  3980. // load in telepod template
  3981.  
  3982. PLG_Load_Object(&static_obj[TELEPODS_TEMPLATE],"tele.plg",2);
  3983.  
  3984. // first fix template object at (0,0,0)
  3985.  
  3986. static_obj[TELEPODS_TEMPLATE].world_pos.x = 0;
  3987. static_obj[TELEPODS_TEMPLATE].world_pos.y = 0;
  3988. static_obj[TELEPODS_TEMPLATE].world_pos.z = 0;
  3989.  
  3990. // now position all tower copies
  3991.  
  3992. for (index=0; index<NUM_TELEPODS; index++)
  3993.     {
  3994.  
  3995.     telepods[index].state = 1;
  3996.     telepods[index].rx    = 0;
  3997.     telepods[index].ry    = 0;
  3998.     telepods[index].rz    = 0;
  3999.     telepods[index].x     = 0;
  4000.     telepods[index].y     = 0;
  4001.     telepods[index].z     = 0;
  4002.  
  4003.     } // end for index
  4004.  
  4005. // position the telepods
  4006.  
  4007. telepods[0].x = -6000;
  4008. telepods[0].z = 6000;
  4009.  
  4010. telepods[1].x = -6000;
  4011. telepods[1].z = -6000;
  4012.  
  4013. telepods[2].x = 6000;
  4014. telepods[2].z = -6000;
  4015.  
  4016. telepods[3].x = 6000;
  4017. telepods[3].z = 6000;
  4018.  
  4019.  
  4020. // load in universe boundary template
  4021.  
  4022. PLG_Load_Object(&static_obj[BARRIERS_TEMPLATE],"barrier.plg",2);
  4023.  
  4024. // first fix template object at (0,0,0)
  4025.  
  4026. static_obj[BARRIERS_TEMPLATE].world_pos.x = 0;
  4027. static_obj[BARRIERS_TEMPLATE].world_pos.y = 0;
  4028. static_obj[BARRIERS_TEMPLATE].world_pos.z = 0;
  4029.  
  4030. // now position all barrier copies
  4031.  
  4032. for (index=0; index<NUM_BARRIERS; index++)
  4033.     {
  4034.  
  4035.     barriers[index].state = 1;
  4036.     barriers[index].rx    = 0;
  4037.     barriers[index].ry    = 15;
  4038.     barriers[index].rz    = 0;
  4039.     barriers[index].x     = 0;
  4040.     barriers[index].y     = 0;
  4041.     barriers[index].z     = 0;
  4042.  
  4043.     } // end for index
  4044.  
  4045. // position the barriers
  4046.  
  4047. barriers[0].x = -8000;
  4048. barriers[0].z = 8000;
  4049.  
  4050. barriers[1].x = -8000;
  4051. barriers[1].z = 0;
  4052.  
  4053. barriers[2].x = -8000;
  4054. barriers[2].z = -8000;
  4055.  
  4056. barriers[3].x = 0;
  4057. barriers[3].z = -8000;
  4058.  
  4059. barriers[4].x = 8000;
  4060. barriers[4].z = -8000;
  4061.  
  4062. barriers[5].x = 8000;
  4063. barriers[5].z = 0;
  4064.  
  4065. barriers[6].x = 8000;
  4066. barriers[6].z = 8000;
  4067.  
  4068. barriers[7].x = 0;
  4069. barriers[7].z = 8000;
  4070.  
  4071. // load in power station template
  4072.  
  4073. PLG_Load_Object(&static_obj[STATIONS_TEMPLATE],"station.plg",2);
  4074.  
  4075. // first fix template object at (0,0,0)
  4076.  
  4077. static_obj[STATIONS_TEMPLATE].world_pos.x = 0;
  4078. static_obj[STATIONS_TEMPLATE].world_pos.y = 0;
  4079. static_obj[STATIONS_TEMPLATE].world_pos.z = 0;
  4080.  
  4081. // now position all power stations
  4082.  
  4083. for (index=0; index<NUM_STATIONS; index++)
  4084.     {
  4085.  
  4086.     stations[index].state = 1;
  4087.     stations[index].rx    = 0;
  4088.     stations[index].ry    = 0;
  4089.     stations[index].rz    = 0;
  4090.     stations[index].x     = 0;
  4091.     stations[index].y     = 0;
  4092.     stations[index].z     = 0;
  4093.  
  4094.     } // end for index
  4095.  
  4096. } // end Load_3D_Models
  4097.  
  4098.  
  4099.  
  4100.  
  4101. // M A I N //////////////////////////////////////////////////////////////////
  4102.  
  4103. void main(int argc, char **argv)
  4104. {
  4105.  
  4106. // the main controls most of the platyer and remote logic, normally we would
  4107. // probably move most of the code into functions, but for instructional purposes
  4108. // this is easier to follow, believe me there are already enough function calls
  4109. // to make your head spin!
  4110.  
  4111. int index,               // looping variable
  4112.     sel,                 // used for input
  4113.     players_key_state,   // state of players input
  4114.     current_sel=0,       // currently highlighted interface selection
  4115.     weapons_lit_count=0; // times how long the light flash from a missile
  4116.                          // should be displayed when player fires
  4117.  
  4118. unsigned char seed;      // a random number seed
  4119.  
  4120. char buffer[64],         // general buffer
  4121.      number[32],         // used to print strings
  4122.      ch;                 // used for keyboard input
  4123.  
  4124.  
  4125.  
  4126. //INITIALIZATION SECTION///////////////////////////////////////////////////////
  4127.  
  4128. // set up viewing system
  4129.  
  4130. Set_3D_View();
  4131.  
  4132. // build all look up tables
  4133.  
  4134. Build_Look_Up_Tables();
  4135.  
  4136. // load in all 3d models
  4137.  
  4138. Load_3D_Objects();
  4139.  
  4140. // parse the command line and set up configuration
  4141.  
  4142. Parse_Commands(argc,argv);
  4143.  
  4144. // set the graphics mode to mode 13h
  4145.  
  4146. Set_Graphics_Mode(GRAPHICS_MODE13);
  4147.  
  4148. // start up music system
  4149.  
  4150. if (music_enabled)
  4151.    {
  4152.    Music_Init();
  4153.    Music_Play((music_ptr)&song,16);
  4154.    } // end if music enabled
  4155.  
  4156. //INTRODUCTION SECTION/////////////////////////////////////////////////////////
  4157.  
  4158. // put up Waite header
  4159.  
  4160. Intro_Waite();
  4161.  
  4162. // put up my header
  4163.  
  4164. Intro_KRK();
  4165.  
  4166. // seed the random number generator with time
  4167.  
  4168. srand((unsigned int)Timer_Query());
  4169.  
  4170. Tech_Print(START_MESS_X,START_MESS_Y," KILL OR BE KILLED 1.0 STARTING UP...",video_buffer);
  4171. Time_Delay(5);
  4172.  
  4173. // initialize font engine
  4174.  
  4175. Font_Engine_1(0,0,0,0,NULL,NULL);
  4176. Tech_Print(START_MESS_X,START_MESS_Y+16," LANGUAGE TRANSLATION ENABLED",video_buffer);
  4177.  
  4178. // create the double buffer
  4179.  
  4180. Create_Double_Buffer(129);
  4181. Tech_Print(START_MESS_X,START_MESS_Y+26," DOUBLE BUFFER CREATED",video_buffer);
  4182.  
  4183. // install the keyboard driver
  4184.  
  4185. Keyboard_Install_Driver();
  4186. Tech_Print(START_MESS_X,START_MESS_Y+36," NEURAL INTERFACE ACTIVATED",video_buffer);
  4187.  
  4188. // load and create background layer
  4189.  
  4190. Tech_Print(START_MESS_X,START_MESS_Y+46," BACKGROUND ENABLED",video_buffer);
  4191.  
  4192. PCX_Init((pcx_picture_ptr)&image_pcx);
  4193. PCX_Load("krkbak.pcx",(pcx_picture_ptr)&image_pcx,1);
  4194. PCX_Copy_To_Buffer((pcx_picture_ptr)&image_pcx,double_buffer);
  4195. PCX_Delete((pcx_picture_ptr)&image_pcx);
  4196.  
  4197. Layer_Create((layer_ptr)&mountains,MOUNTAIN_WIDTH,MOUNTAIN_HEIGHT);
  4198. Layer_Build((layer_ptr)&mountains,0,0,
  4199.             double_buffer,
  4200.             0,36,SCREEN_WIDTH,43);
  4201.  
  4202.  
  4203. Load_Tactical();
  4204. Tech_Print(START_MESS_X,START_MESS_Y+56," TACTICAL ONLINE",video_buffer);
  4205.  
  4206.  
  4207. // memory problem
  4208.  
  4209. if (digital_enabled)
  4210.    {
  4211.    Sound_Load("KRKPOW.VOC" ,  (sound_ptr)&digital_FX[KRKPOW_VOC ],1);
  4212.    Digital_FX_Play(KRKPOW_VOC,3);
  4213.    Sound_Unload((sound_ptr)&digital_FX[KRKPOW_VOC]);
  4214.    } // end if
  4215.  
  4216. // end memory problem
  4217.  
  4218. // all systems powered
  4219.  
  4220. Tech_Print(START_MESS_X,START_MESS_Y+108," ALL SYSTEMS POWERED AND AVAILABLE",video_buffer);
  4221.  
  4222. for (index=0; index<3; index++)
  4223.     {
  4224.     // draw the message and the erase the message
  4225.     Font_Engine_1(START_MESS_X,START_MESS_Y+108,0,0," ALL SYSTEMS POWERED AND AVAILABLE",video_buffer);
  4226.     Time_Delay(8);
  4227.  
  4228.     Font_Engine_1(START_MESS_X,START_MESS_Y+108,0,0,"                                  ",video_buffer);
  4229.     Time_Delay(8);
  4230.  
  4231.     } // end for
  4232.  
  4233. // start up digital FX system
  4234.  
  4235. if (digital_enabled)
  4236.    {
  4237.    Digital_FX_Init();
  4238.    } // end if digital sound enabled
  4239.  
  4240.  
  4241. // do intro piece
  4242.  
  4243. Intro_Planet();
  4244.  
  4245. // save the system pallete here because we are going to really thrash it!!!
  4246.  
  4247. Read_Palette(0,255,(RGB_palette_ptr)&game_palette);
  4248.  
  4249.  
  4250. //MAIN EVENT LOOP//////////////////////////////////////////////////////////////
  4251.  
  4252.  
  4253. // main event loop ///////////////////////////////////////////////////////////
  4254.  
  4255. while(game_state!=GAME_OVER)
  4256.      {
  4257.      // test the overall game state
  4258.  
  4259.  
  4260. //SETUP SECTION////////////////////////////////////////////////////////////////
  4261.  
  4262.      if (game_state==GAME_SETUP)
  4263.         {
  4264.  
  4265.         // user in in the setup state
  4266.  
  4267.         Intro_Controls();
  4268.  
  4269.         Draw_Box(SELECT_BOX_SX,
  4270.                  SELECT_BOX_SY+current_sel*SELECT_BOX_DY,
  4271.                  SELECT_BOX_SX+SELECT_BOX_WIDTH,
  4272.                  SELECT_BOX_SY+SELECT_BOX_HEIGHT+current_sel*SELECT_BOX_DY,
  4273.                  254);
  4274.  
  4275.  
  4276.         Draw_Rectangle(SELECT_LGT_SX,
  4277.                       SELECT_LGT_SY+current_sel*SELECT_LGT_DY,
  4278.                       SELECT_LGT_SX+SELECT_LGT_WIDTH,
  4279.                       SELECT_LGT_SY+SELECT_LGT_HEIGHT+current_sel*SELECT_LGT_DY,
  4280.                       254);
  4281.  
  4282.         // restore pallete
  4283.  
  4284.         Write_Palette(0,255,(RGB_palette_ptr)&game_palette);
  4285.  
  4286.         // enter setup event loop
  4287.  
  4288.         Panel_FX(1);
  4289.  
  4290.         while(game_state==GAME_SETUP)
  4291.              {
  4292.              // this event loop is for the setup phase
  4293.  
  4294.              // test for up or down
  4295.  
  4296.              if (keyboard_state[MAKE_UP])
  4297.                 {
  4298.  
  4299.                 // erase current cursor position
  4300.  
  4301.                 Draw_Box(SELECT_BOX_SX,
  4302.                          SELECT_BOX_SY+current_sel*SELECT_BOX_DY,
  4303.                          SELECT_BOX_SX+SELECT_BOX_WIDTH,
  4304.                          SELECT_BOX_SY+SELECT_BOX_HEIGHT+current_sel*SELECT_BOX_DY,
  4305.                          0);
  4306.  
  4307.                 Draw_Rectangle(SELECT_LGT_SX,
  4308.                                SELECT_LGT_SY+current_sel*SELECT_LGT_DY,
  4309.                                SELECT_LGT_SX+SELECT_LGT_WIDTH,
  4310.                                SELECT_LGT_SY+SELECT_LGT_HEIGHT+current_sel*SELECT_LGT_DY,
  4311.                                0);
  4312.  
  4313.                 // move up one and draw cursor and box
  4314.  
  4315.                 if (--current_sel<0)
  4316.                    current_sel = MAX_SELECTION;
  4317.  
  4318.                 // draw the new selected selection
  4319.  
  4320.                 Draw_Box(SELECT_BOX_SX,
  4321.                          SELECT_BOX_SY+current_sel*SELECT_BOX_DY,
  4322.                          SELECT_BOX_SX+SELECT_BOX_WIDTH,
  4323.                          SELECT_BOX_SY+SELECT_BOX_HEIGHT+current_sel*SELECT_BOX_DY,
  4324.                          254);
  4325.  
  4326.  
  4327.                 Draw_Rectangle(SELECT_LGT_SX,
  4328.                               SELECT_LGT_SY+current_sel*SELECT_LGT_DY,
  4329.                               SELECT_LGT_SX+SELECT_LGT_WIDTH,
  4330.                               SELECT_LGT_SY+SELECT_LGT_HEIGHT+current_sel*SELECT_LGT_DY,
  4331.                               254);
  4332.  
  4333.  
  4334.                 Digital_FX_Play(KRKKEY_VOC,3);
  4335.  
  4336.                 Time_Delay(1);
  4337.  
  4338.                 } // end if
  4339.  
  4340.              if (keyboard_state[MAKE_DOWN])
  4341.                 {
  4342.  
  4343.                 // erase current cursor position
  4344.  
  4345.                 Draw_Box(SELECT_BOX_SX,
  4346.                          SELECT_BOX_SY+current_sel*SELECT_BOX_DY,
  4347.                          SELECT_BOX_SX+SELECT_BOX_WIDTH,
  4348.                          SELECT_BOX_SY+SELECT_BOX_HEIGHT+current_sel*SELECT_BOX_DY,
  4349.                          0);
  4350.  
  4351.  
  4352.                 Draw_Rectangle(SELECT_LGT_SX,
  4353.                               SELECT_LGT_SY+current_sel*SELECT_LGT_DY,
  4354.                               SELECT_LGT_SX+SELECT_LGT_WIDTH,
  4355.                               SELECT_LGT_SY+SELECT_LGT_HEIGHT+current_sel*SELECT_LGT_DY,
  4356.                               0);
  4357.  
  4358.  
  4359.                 // move up one and draw cursor and box
  4360.  
  4361.                 if (++current_sel>MAX_SELECTION)
  4362.                    current_sel = 0;
  4363.  
  4364.                 // draw the new selected selection
  4365.  
  4366.                 Draw_Box(SELECT_BOX_SX,
  4367.                          SELECT_BOX_SY+current_sel*SELECT_BOX_DY,
  4368.                          SELECT_BOX_SX+SELECT_BOX_WIDTH,
  4369.                          SELECT_BOX_SY+SELECT_BOX_HEIGHT+current_sel*SELECT_BOX_DY,
  4370.                          SELECT_REG);
  4371.  
  4372.  
  4373.                 Draw_Rectangle(SELECT_LGT_SX,
  4374.                               SELECT_LGT_SY+current_sel*SELECT_LGT_DY,
  4375.                               SELECT_LGT_SX+SELECT_LGT_WIDTH,
  4376.                               SELECT_LGT_SY+SELECT_LGT_HEIGHT+current_sel*SELECT_LGT_DY,
  4377.                               SELECT_REG);
  4378.  
  4379.                 Digital_FX_Play(KRKKEY_VOC,3);
  4380.  
  4381.                 Time_Delay(1);
  4382.  
  4383.                 } // end if
  4384.  
  4385.              // test for a selection via enter key
  4386.  
  4387.              if (keyboard_state[MAKE_ENTER])
  4388.                 {
  4389.  
  4390.                 Digital_FX_Play(KRKKEY_VOC,3);
  4391.  
  4392.                 // what is the selection?
  4393.  
  4394.                 switch(current_sel)
  4395.                       {
  4396.  
  4397.                       case 0:
  4398.                            {
  4399.  
  4400.                            game_state = GAME_RUNNING;
  4401.  
  4402.                            } break;
  4403.  
  4404.                       case 1:
  4405.                            {
  4406.                            // call the mech selection function
  4407.  
  4408.                            Select_Mech();
  4409.  
  4410.                            // re-draw main menu
  4411.  
  4412.                            Intro_Controls();
  4413.  
  4414.                            } break;
  4415.  
  4416.  
  4417.                       case 2:
  4418.                            {
  4419.                            // show user the rules and instructions
  4420.  
  4421.                            Intro_Briefing();
  4422.  
  4423.                            // re-draw main menu
  4424.  
  4425.                            Intro_Controls();
  4426.  
  4427.                            } break;
  4428.  
  4429.                       case 3:
  4430.                            {
  4431.  
  4432.                            game_state = GAME_OVER;
  4433.  
  4434.                            } break;
  4435.  
  4436.                       default: break;
  4437.  
  4438.                       } //  end switch
  4439.  
  4440.                 Draw_Box(SELECT_BOX_SX,
  4441.                          SELECT_BOX_SY+current_sel*SELECT_BOX_DY,
  4442.                          SELECT_BOX_SX+SELECT_BOX_WIDTH,
  4443.                          SELECT_BOX_SY+SELECT_BOX_HEIGHT+current_sel*SELECT_BOX_DY,
  4444.                          254);
  4445.  
  4446.  
  4447.                 Draw_Rectangle(SELECT_LGT_SX,
  4448.                               SELECT_LGT_SY+current_sel*SELECT_LGT_DY,
  4449.                               SELECT_LGT_SX+SELECT_LGT_WIDTH,
  4450.                               SELECT_LGT_SY+SELECT_LGT_HEIGHT+current_sel*SELECT_LGT_DY,
  4451.                               254);
  4452.  
  4453.  
  4454.                 } // end if
  4455.  
  4456.              // slow things down a bit
  4457.  
  4458.              Time_Delay(1);
  4459.  
  4460.              // check on music
  4461.  
  4462.              if (music_enabled)
  4463.                 {
  4464.                 // test if piece is complete or has been stopped
  4465.  
  4466.                 if (Music_Status()==2 || Music_Status()==0)
  4467.                    {
  4468.                    // advance to next sequence
  4469.  
  4470.                    if (++intro_seq_index==14)
  4471.                       intro_seq_index=0;
  4472.  
  4473.                    Music_Play((music_ptr)&song,intro_sequence[intro_seq_index]);
  4474.  
  4475.                    } // end if
  4476.  
  4477.                 } // end if music enabled
  4478.  
  4479.              // do special fx
  4480.  
  4481.              Panel_FX(0);
  4482.  
  4483.              } // end setup event loop
  4484.  
  4485.         } // end if in control state
  4486.  
  4487. //GAME RUNNING SECTION/////////////////////////////////////////////////////////
  4488.  
  4489.      else
  4490.      if (game_state==GAME_RUNNING)
  4491.         {
  4492.  
  4493.         // restore pallete
  4494.  
  4495.         Write_Palette(0,255,(RGB_palette_ptr)&game_palette);
  4496.  
  4497.         // reset system variables
  4498.  
  4499.         Reset_System();
  4500.  
  4501.         // restart everything
  4502.  
  4503.         Init_Missiles();
  4504.  
  4505.         Init_Aliens();
  4506.  
  4507.         // start music
  4508.  
  4509.         if (music_enabled)
  4510.            {
  4511.            Music_Stop();
  4512.  
  4513.            // start from begining sequence
  4514.  
  4515.            game_seq_index=0;
  4516.  
  4517.            Music_Play((music_ptr)&song,game_sequence[game_seq_index]);
  4518.  
  4519.            } // end if music enabled
  4520.  
  4521.         // clear double buffer
  4522.  
  4523.         Fill_Double_Buffer_32(0);
  4524.  
  4525.         // load in instrument area
  4526.  
  4527.         PCX_Init((pcx_picture_ptr)&image_pcx);
  4528.         PCX_Load("krkcp.pcx", (pcx_picture_ptr)&image_pcx,1);
  4529.         PCX_Show_Buffer((pcx_picture_ptr)&image_pcx);
  4530.         PCX_Delete((pcx_picture_ptr)&image_pcx);
  4531.  
  4532.         // set up displays
  4533.  
  4534.         Draw_Scanner(SCANNER_CLEAR);
  4535.         Draw_Scanner(SCANNER_LOGO);
  4536.  
  4537.         Draw_Tactical(TACTICAL_CLEAR);
  4538.         Draw_Tactical(TACTICAL_DRAW);
  4539.  
  4540.         // reset color animation registers
  4541.  
  4542.         Misc_Color_Init();
  4543.  
  4544.         // enter into the main game loop
  4545.  
  4546.         while(game_state==GAME_RUNNING)
  4547.              {
  4548.              // compute starting time of this frame
  4549.  
  4550.              starting_time = Timer_Query();
  4551.  
  4552.              // keyboard input section
  4553.  
  4554.              // change ship velocity
  4555.  
  4556.              if (keyboard_state[MAKE_UP])
  4557.                 {
  4558.                 // speed up
  4559.  
  4560.                 if ((ship_speed+=5)>55)
  4561.                     ship_speed=55;
  4562.  
  4563.                 } // end if speed increase
  4564.  
  4565.              if (keyboard_state[MAKE_DOWN])
  4566.                 {
  4567.                 // slow down
  4568.  
  4569.                 if ((ship_speed-=5)<-55)
  4570.                     ship_speed=-55;
  4571.  
  4572.                 } // end if speed decrease
  4573.  
  4574.              // test for turns
  4575.  
  4576.              if (keyboard_state[MAKE_RIGHT])
  4577.                 {
  4578.                 // rotate ship to right
  4579.  
  4580.                 if ((ship_yaw+=4)>=360)
  4581.                    ship_yaw-=360;
  4582.  
  4583.                 } // end if
  4584.  
  4585.              if (keyboard_state[MAKE_LEFT])
  4586.                 {
  4587.  
  4588.                 // rotate ship to left
  4589.  
  4590.                 if ((ship_yaw-=4)<0)
  4591.                    ship_yaw+=360;
  4592.  
  4593.                 } // end if
  4594.  
  4595.              // test for weapons fire
  4596.  
  4597.              if (keyboard_state[MAKE_SPACE])
  4598.                 {
  4599.                 // fire a missile
  4600.  
  4601.                 Start_Missile(PLAYER_OWNER,
  4602.                               &view_point,
  4603.                               &ship_direction,
  4604.                               ship_speed+30,
  4605.                               100);
  4606.  
  4607.                 // illuminate instrument panel to denote a shot has
  4608.                 // been fired
  4609.  
  4610.                 Write_Color_Reg(PLAYERS_WEAPON_FIRE_REG,(RGB_color_ptr)&bright_red);
  4611.  
  4612.                 // set timer to turn off illumination
  4613.  
  4614.                 weapons_lit_count = 2;
  4615.  
  4616.                 } // end if
  4617.  
  4618.               // instrumentation checks
  4619.  
  4620.               // left hand scanner
  4621.  
  4622.               if (keyboard_state[MAKE_S])
  4623.                  {
  4624.                  if (scanner_state==1)
  4625.                     {
  4626.                     // turn the scanner off
  4627.  
  4628.                     scanner_state=0;
  4629.  
  4630.                     // replace krk logo
  4631.  
  4632.                     Draw_Scanner(SCANNER_CLEAR);
  4633.  
  4634.                     Draw_Scanner(SCANNER_LOGO);
  4635.  
  4636.                     }
  4637.                  else
  4638.                     {
  4639.                     // turn the scanner on
  4640.  
  4641.                     scanner_state=1;
  4642.  
  4643.                     // clear the scanner area for radar inage
  4644.  
  4645.                     Draw_Scanner(SCANNER_CLEAR);
  4646.  
  4647.                     Digital_FX_Play(KRKSCN_VOC,1);
  4648.  
  4649.  
  4650.                     } // end else
  4651.  
  4652.                  } // end
  4653.  
  4654.              // right half tactical display
  4655.  
  4656.              if (keyboard_state[MAKE_T])
  4657.                 {
  4658.  
  4659.                 // test if tactical was off
  4660.  
  4661.                 if (tactical_state==TACTICAL_MODE_OFF)
  4662.                    {
  4663.                    // playe sound
  4664.  
  4665.                    Digital_FX_Play(KRKTAC_VOC,1);
  4666.  
  4667.  
  4668.                    } // end if
  4669.  
  4670.                 // toggle to next state of tactical display
  4671.  
  4672.                 // clear tactical display before next state
  4673.  
  4674.                 Draw_Tactical(TACTICAL_CLEAR);
  4675.  
  4676.                 // move to next state
  4677.  
  4678.                 if (++tactical_state>TACTICAL_MODE_OFF)
  4679.                    tactical_state = TACTICAL_MODE_STS;
  4680.  
  4681.                 // based on new tactical state draw proper display
  4682.  
  4683.                 Draw_Tactical(TACTICAL_DRAW);
  4684.  
  4685.                 } // end if
  4686.  
  4687.              // heads up display
  4688.  
  4689.              if (keyboard_state[MAKE_H])
  4690.                 {
  4691.                 // toggle hud
  4692.  
  4693.                 if (hud_state==1)
  4694.                    {
  4695.                    hud_state=0;
  4696.  
  4697.                    // set indicator to proper illumination
  4698.  
  4699.                    Write_Color_Reg(HUD_REG,(RGB_color_ptr)&dark_blue);
  4700.  
  4701.                    } // end if
  4702.                 else
  4703.                    {
  4704.                    hud_state = 1;
  4705.  
  4706.                    // set indicator to proper illumination
  4707.  
  4708.                    Write_Color_Reg(HUD_REG,(RGB_color_ptr)&bright_blue);
  4709.  
  4710.                    Digital_FX_Play(KRKHUD_VOC,1);
  4711.  
  4712.                    } // end else
  4713.  
  4714.                 } // end if
  4715.  
  4716.              // test for exit
  4717.  
  4718.              if (keyboard_state[MAKE_ESC])
  4719.                 game_state=GAME_SETUP;
  4720.  
  4721.  
  4722.              // motion and control section
  4723.  
  4724.              // create a trajectory vector aligned with view direction
  4725.  
  4726.              ship_direction.x = sin_look[ship_yaw];
  4727.              ship_direction.y = 0;
  4728.              ship_direction.z = cos_look[ship_yaw];
  4729.  
  4730.              // move viewpoint based on ship trajectory
  4731.  
  4732.              view_point.x+=ship_direction.x*ship_speed;
  4733.              view_point.z+=ship_direction.z*ship_speed;
  4734.  
  4735.              // move objects here
  4736.  
  4737.              Move_Missiles();
  4738.  
  4739.              // move and perform AI for aliens
  4740.  
  4741.              Process_Aliens();
  4742.  
  4743.              // test ship against universe boundaries
  4744.  
  4745.              if (view_point.x>GAME_MAX_WORLD_X)
  4746.                  view_point.x=GAME_MAX_WORLD_X;
  4747.              else
  4748.              if (view_point.x<GAME_MIN_WORLD_X)
  4749.                  view_point.x=GAME_MIN_WORLD_X;
  4750.  
  4751.              if (view_point.z>GAME_MAX_WORLD_Z)
  4752.                  view_point.z=GAME_MAX_WORLD_Z;
  4753.              else
  4754.              if (view_point.z<GAME_MIN_WORLD_Z)
  4755.                  view_point.z=GAME_MIN_WORLD_Z;
  4756.  
  4757.              // add in vibrational noise due to terrain
  4758.  
  4759.              if (ship_speed)
  4760.                  view_point.y = 40+rand()%(1+abs(ship_speed)/8);
  4761.              else
  4762.                  view_point.y = 40;
  4763.  
  4764.              // test for ship hit message
  4765.  
  4766.              if (ship_message == SHIP_HIT)
  4767.                 {
  4768.                 // do screen shake
  4769.  
  4770.                 view_point.y = 40+5*(rand()%10);
  4771.  
  4772.                 // perform color fx
  4773.  
  4774.                 // test if shake complete
  4775.  
  4776.                 if (--ship_timer < 0)
  4777.                    {
  4778.                    // reset ships state
  4779.  
  4780.                    ship_message = SHIP_STABLE;
  4781.  
  4782.                    view_point.y = 40;
  4783.  
  4784.                    // reset colors
  4785.  
  4786.                    } // end if screen shake complete
  4787.  
  4788.                 } // end if
  4789.  
  4790.  
  4791.              // transform stationary objects here
  4792.  
  4793.              Rotate_Object(&static_obj[STATIONS_TEMPLATE],0,10,0);
  4794.  
  4795.              Rotate_Object(&static_obj[TELEPODS_TEMPLATE],0,15,0);
  4796.  
  4797.              // set view angles based on trajectory of ship
  4798.  
  4799.              view_angle.ang_y = ship_yaw;
  4800.  
  4801.              // now that user has possible moved viewpoint, create the global
  4802.              // world to camera transformation matrix
  4803.  
  4804.              Create_World_To_Camera();
  4805.  
  4806.              // reset the polygon list
  4807.  
  4808.              Generate_Poly_List(NULL,RESET_POLY_LIST);
  4809.  
  4810.              // perform general 3-D pipeline for all 3-D objects
  4811.  
  4812.              // first draw stationary objects
  4813.  
  4814.              Draw_Stationary_Objects();
  4815.  
  4816.              // draw dynamic objects
  4817.  
  4818.              Draw_Aliens();
  4819.  
  4820.              // draw the missiles
  4821.  
  4822.              Draw_Missiles();
  4823.  
  4824.              // draw background
  4825.  
  4826.              Draw_Background((int)(ship_yaw*.885));
  4827.  
  4828.              // sort the polygons
  4829.  
  4830.              Sort_Poly_List();
  4831.  
  4832.              // draw the polygon list
  4833.  
  4834.              Draw_Poly_List();
  4835.  
  4836.              // draw the instruments here
  4837.  
  4838.              if (scanner_state==1)
  4839.                 {
  4840.                 // erase old blips
  4841.  
  4842.                 Draw_Scanner(SCANNER_ERASE_BLIPS);
  4843.  
  4844.                 // refresh scanner image
  4845.  
  4846.                 Draw_Scanner(SCANNER_DRAW_BLIPS);
  4847.  
  4848.                 } // end if
  4849.  
  4850.              // update tactical display
  4851.  
  4852.              if (tactical_state!=TACTICAL_MODE_OFF)
  4853.                  Draw_Tactical(TACTICAL_UPDATE);
  4854.  
  4855.              if (hud_state==1)
  4856.                 Draw_Hud();
  4857.  
  4858.              // do special color fx
  4859.  
  4860.              // flicker the engines of the aliens
  4861.  
  4862.              Tallon_Color_FX();
  4863.  
  4864.              Slider_Color_FX();
  4865.  
  4866.              // strobe the perimeter barriers
  4867.  
  4868.              Barrier_Color_FX();
  4869.  
  4870.              // take care of weapons flash
  4871.  
  4872.              if (weapons_lit_count>0)
  4873.                 {
  4874.                 // test if it's time to to off flash
  4875.  
  4876.                 if (--weapons_lit_count==0)
  4877.                    Write_Color_Reg(PLAYERS_WEAPON_FIRE_REG,(RGB_color_ptr)&black);
  4878.  
  4879.                 } // end if
  4880.  
  4881.              // test if screen should be colored to simulate fire blast
  4882.  
  4883.              if (ship_message==SHIP_HIT)
  4884.                 {
  4885.                 // test for time intervals
  4886.  
  4887.                 if (ship_timer>5 && (rand()%3)==1)
  4888.                    Fill_Double_Buffer_32(SHIP_FLAME_COLOR+rand()%16);
  4889.  
  4890.                 } // end if ship hit
  4891.  
  4892.              // display double buffer
  4893.  
  4894.              Display_Double_Buffer_32(double_buffer,0);
  4895.  
  4896.              // lock onto 18 frames per second max
  4897.  
  4898.              while((Timer_Query()-starting_time)<1);
  4899.  
  4900.              // check on music
  4901.  
  4902.              if (music_enabled)
  4903.                 {
  4904.                 if (Music_Status()==2 || Music_Status()==0)
  4905.                    {
  4906.  
  4907.                    // advance to next sequence
  4908.  
  4909.                    if (++game_seq_index==21)
  4910.                       game_seq_index=0;
  4911.  
  4912.                    Music_Play((music_ptr)&song,game_sequence[game_seq_index]);
  4913.  
  4914.                     } // end if
  4915.  
  4916.                  } // end if music enabled
  4917.  
  4918.              } // end game loop
  4919.  
  4920.         // test if there is a winner or user just decided to exit
  4921.  
  4922.         Screen_Transition(SCREEN_DARKNESS);
  4923.  
  4924.         // restart intro music
  4925.  
  4926.         if (music_enabled)
  4927.            {
  4928.            // stop game music, start intro music again
  4929.  
  4930.            intro_seq_index=0;
  4931.            Music_Stop();
  4932.            Music_Play((music_ptr)&song,intro_sequence[intro_seq_index]);
  4933.  
  4934.            } // end if music enabled
  4935.  
  4936.         } // end if running
  4937.  
  4938.      } // end main system event loop
  4939.  
  4940. //GAME OVER SECTION////////////////////////////////////////////////////////////
  4941.  
  4942. // exit in a very cool way
  4943.  
  4944. Screen_Transition(SCREEN_SWIPE_X);
  4945.  
  4946. // free up all resources
  4947.  
  4948. Delete_Double_Buffer();
  4949.  
  4950. // close down FX
  4951.  
  4952. Digital_FX_Close();
  4953.  
  4954. // show the credits
  4955.  
  4956. Closing_Screen();
  4957.  
  4958. // close down music
  4959.  
  4960. Music_Close();
  4961.  
  4962. // remove the keyboard handler
  4963.  
  4964. Keyboard_Remove_Driver();
  4965.  
  4966. Set_Graphics_Mode(TEXT_MODE);
  4967.  
  4968. // see ya!
  4969.  
  4970. printf("\nKILL OR BE KILLED:Normal Shutdown.\n");
  4971.  
  4972. } // end main
  4973.  
  4974.