1 /*
2     GL-117
3     Copyright 2001, 2002 Thomas A. Drexl aka heptargon
4 
5     This file is part of GL-117.
6 
7     GL-117 is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 2 of the License, or
10     (at your option) any later version.
11 
12     GL-117 is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
16 
17     You should have received a copy of the GNU General Public License
18     along with GL-117; if not, write to the Free Software
19     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20 */
21 
22 /* This file includes the main program. */
23 
24 /* To fully understand the GL-117 code, please read the methods from bottom to top! */
25 
26 /*
27 TODO:
28 - options => video => resolution and fullscreen (both with restart)
29 - correct transport2 (left side corrupt in VRML) and add mission with transport2
30 - southern seashore landscape (additional missions)
31 - alpine snow landscape (additional missions)
32 - tree colors (fall, spring), draw more tree textures
33 - particle systems: rain, clouds to fly through
34 */
35 
36 #ifndef IS_MAIN_H
37 
38 #include "main.h"
39 #include "menu.h"
40 #include "maploader.h"
41 #include "dirs.h"
42 #include "gl.h"
43 #include "land.h"
44 #include "net.h"
45 #include "mathtab.h"
46 #include "cockpit.h"
47 #include "conf.h"
48 #include "mission.h"
49 #include "glland.h"
50 #include "common.h"
51 
52 #include <ctype.h>
53 
54 int mousex, mousey;
55 
56 int debug = 1;
57 bool multiplayer = false, isserver = false;
58 int day = 1;
59 int weather = WEATHER_SUNNY;
60 float sungamma = 45.0;
61 
62 int camera = 0;
63 float camx = 0, camy = 0, camz = 0, camphi = 0, camgamma = 0, camtheta = 0;
64 float view_x = 0, view_y = 0;
65 float sunlight = 1.0, sunlight_dest = 1.0;
66 
67 float blackout = 0, redout = 0;
68 
69 int lighting = 1;
70 int mode = 0;
71 
72 // pre-defined screen resolutions (x, y, bpp, fullscreen)
73 int resolution [4] [4] =
74         { { 1024, 768, 32, 1 },
75           { 800, 600, 32, 1 },
76           { 640, 480, 32, 1 },
77           { 640, 480, 32, 0 } };
78 
79 float nearclippingplane = 0.25; // do NOT lower this!
80 
81 bool sunblinding = false;
82 
83 Dirs *dirs;
84 Server *server = NULL;
85 Client *client = NULL;
86 
87 /*#ifdef HAVE_SDL
88 SDL_Thread *threadnet = NULL;
89 #endif*/
90 
91 int game = GAME_INIT;
92 
93 int debuglevel = LOG_MOST;
94 int showcollision = 0;
95 int brightness = 0;
96 int contrast = 10;
97 
98 SoundSystem *sound = NULL;
99 
100 GL *gl;
101 
getView()102 float getView ()
103 {
104   if (weather == WEATHER_THUNDERSTORM && view > 40.0)
105     return 40.0;
106   return view;
107 }
108 
109 int clouds = 0;
110 
111 CTexture *texradar1, *texradar2, *texarrow;//, *texcounter;
112 
113 MapLoader *maploader;
114 
115 float visibleangle = 80.0F;
116 
117 
118 
119 
120 
121 
122 
123 CTexture *texsun, *texflare1, *texflare2, *texflare3, *texflare4, *texmoon = NULL, *texcross, *texcross2, *texranks, *texmedals;
124 CTexture *texclouds1, *texclouds2, *texclouds3;
125 
126 PilotList *pilots;
127 
128 CExplosion *explosion [maxexplosion];
129 CBlackSmoke *blacksmoke [maxblacksmoke];
130 GLLandscape *l = NULL;
131 Font *font1, *font2;
132 
133 CTexture *textitle;
134 
135 Uint32 lasttime = 0;
136 
137 
138 
139 
140 
141 CLoad3DS g_Load3ds;
142 CModel model_fig;
143 CModel model_figa;
144 CModel model_figb;
145 CModel model_figc;
146 CModel model_figd;
147 CModel model_fige;
148 CModel model_figf;
149 CModel model_figg;
150 CModel model_figh;
151 CModel model_figi;
152 CModel model_figt;
153 CModel model_figu;
154 CModel model_cannon1;
155 CModel model_cannon2;
156 CModel model_cannon1b;
157 CModel model_cannon2b;
158 CModel model_flare1;
159 CModel model_chaff1;
160 CModel model_missile1;
161 CModel model_missile2;
162 CModel model_missile3;
163 CModel model_missile4;
164 CModel model_missile5;
165 CModel model_missile6;
166 CModel model_missile7;
167 CModel model_missile8;
168 CModel model_flak1;
169 CModel model_flarak1;
170 CModel model_tent1;
171 CModel model_ship1;
172 CModel model_ship2;
173 CModel model_gl117;
174 CModel model_tank1;
175 CModel model_container1;
176 CModel model_truck1;
177 CModel model_truck2;
178 CModel model_trsam;
179 CModel model_pickup1;
180 CModel model_pickup2;
181 CModel model_tank2;
182 CModel model_tent4;
183 CModel model_hall1;
184 CModel model_hall2;
185 CModel model_oilrig;
186 CModel model_egg;
187 CModel model_radar;
188 CModel model_mine1;
189 CModel model_aster1;
190 CModel model_base1;
191 CModel model_barrier1;
192 CModel model_rubble1;
193 CModel model_depot1;
194 CModel model_house1;
195 
196 DynamicObj *flare [maxflare];
197 DynamicObj *chaff [maxchaff];
198 AIObj *missile [maxmissile];
199 DynamicObj *laser [maxlaser];
200 AIObj *fighter [maxfighter];
201 Star *star [maxstar];
202 DynamicObj *groundobj [maxgroundobj];
203 Flash *flash1;
204 
205 Space *space;
206 
207 AIObj *fplayer;
208 CSpaceObj *sphere;
209 CSphere *objsphere;
210 HighClouds *highclouds;
211 HighClouds *highclouds2;
212 
213 CModel *obj, *objlaser, *objmissile;
214 CVector3 *clip1, *clip2, *tlnull, *tlinf, *tlminf;
215 CRotation *rotnull, *rotmissile;
216 
217 GLenum polygonMode = GL_FILL;
218 
219 GLfloat light_position0[] = { 0.0, 0.5, -1.0, 0 };
220 
221 #define max(x,y) ((x)>(y)?(x):(y))
222 
223 int NX, NY;
224 
225 int joysticks;
226 
227 Mission *mission = NULL;
228 Mission *missionnew = NULL;
229 
230 int keyb_elev = 0, keyb_roll = 0, keyb_rudder = 0;
231 int keyb_lshift = 0;
232 
233 Container allmenus;
234 Container famemenu;
235 Container fightermenu;
236 Container missionmenu;
237 Container quitmenu;
238 Container statsmenu;
239 Component *currentsubmenu = NULL;
240 Component *currentoptmenu = NULL;
241 
242 Container *mainmenu, *submenu [10], *optmenu [5], *controlsmenu [5];
243 Button *mainbutton [10];
244 Button *optbutton [10];
245 
246 
247 
248 bool firststart = false;
249 
250 bool missionactive = false;
251 
252 CColor colorwhite (255, 255, 255, 255);
253 CColor colorblue (50, 50, 255, 255);
254 CColor colorgreen (100, 255, 100, 255);
255 CColor colororange (255, 150, 100, 255);
256 CColor colorred (255, 0, 0, 255);
257 CColor coloryellow (255, 255, 0, 200);
258 CColor colorgrey (150, 150, 150, 200);
259 CColor colorlightgrey (210, 210, 210, 255);
260 
261 
drawRank(float xp,float yp,float zp,int rank,float zoom)262 void drawRank (float xp, float yp, float zp, int rank, float zoom)
263 {
264   rank --;
265   if (rank < 0) return;
266   float x = xp / 10.0, y = yp / 10.0, z = zp;
267   float tx1 = 0.5 * (rank % 2);
268   float tx2 = tx1 + 0.5;
269   float ty1 = 0.755 - 0.25 * (rank / 2);
270   float ty2 = ty1 + 0.24;
271   zoom /= 10;
272   gl->enableTextures (texranks->textureID);
273   if (antialiasing) gl->enableLinearTexture (texranks->textureID);
274   else gl->disableLinearTexture (texranks->textureID);
275   gl->enableAlphaBlending ();
276   glEnable (GL_ALPHA_TEST);
277   glAlphaFunc (GL_GEQUAL, 0.35);
278 
279   // Example how to pass the glBegin()...glEnd() code using vertex lists
280 /*  float vertex [sizeof (float) * 9];
281 	glEnableClientState(GL_VERTEX_ARRAY);
282 	glEnableClientState(GL_COLOR_ARRAY);
283 	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
284 	glVertexPointer (3,	GL_FLOAT,	sizeof (float) * 9, &vertex [0]);
285 	glColorPointer (4, GL_FLOAT, sizeof (float) * 9, &vertex [3]);
286 	glTexCoordPointer (2, GL_FLOAT, sizeof (float) * 9, &vertex [7]);
287 
288   int mz = 0;
289   vertex [mz ++] = x; vertex [mz ++] = y; vertex [mz ++] = z;
290   vertex [mz ++] = 1; vertex [mz ++] = 1; vertex [mz ++] = 1; vertex [mz ++] = 200.0F/255.0F;
291   vertex [mz ++] = tx1; vertex [mz ++] = ty1;
292   vertex [mz ++] = x + zoom * 2; vertex [mz ++] = y; vertex [mz ++] = z;
293   vertex [mz ++] = 1; vertex [mz ++] = 1; vertex [mz ++] = 1; vertex [mz ++] = 200.0F/255.0F;
294   vertex [mz ++] = tx2; vertex [mz ++] = ty1;
295   vertex [mz ++] = x + zoom * 2; vertex [mz ++] = y + zoom; vertex [mz ++] = z;
296   vertex [mz ++] = 1; vertex [mz ++] = 1; vertex [mz ++] = 1; vertex [mz ++] = 200.0F/255.0F;
297   vertex [mz ++] = tx2; vertex [mz ++] = ty2;
298   vertex [mz ++] = x; vertex [mz ++] = y + zoom; vertex [mz ++] = z;
299   vertex [mz ++] = 1; vertex [mz ++] = 1; vertex [mz ++] = 1; vertex [mz ++] = 200.0F/255.0F;
300   vertex [mz ++] = tx1; vertex [mz ++] = ty2;
301 
302   glDrawArrays (GL_QUADS, 0, 4);*/
303 
304   glBegin (GL_QUADS);
305   glColor4ub (255, 255, 255, 200);
306   glTexCoord2f (tx1, ty1);
307   glVertex3f (x, y, z);
308   glTexCoord2f (tx2, ty1);
309   glVertex3f (x + zoom * 2, y, z);
310   glTexCoord2f (tx2, ty2);
311   glVertex3f (x + zoom * 2, y + zoom, z);
312   glTexCoord2f (tx1, ty2);
313   glVertex3f (x, y + zoom, z);
314   glEnd ();
315 
316   glDisable (GL_ALPHA_TEST);
317   gl->disableAlphaBlending ();
318   glDisable (GL_TEXTURE_2D);
319 }
320 
drawMedal(float xp,float yp,float zp,int medal,float zoom,int missionid)321 void drawMedal (float xp, float yp, float zp, int medal, float zoom, int missionid)
322 {
323   if (medal < 0) return;
324   if (missionid < MISSION_CAMPAIGN1 || missionid > MISSION_CAMPAIGN2) return;
325   float x = xp / 10.0 - zoom / 20, y = yp / 10.0 - zoom / 20, z = zp;
326   float tx1 = 0.5 * (medal % 2);
327   float tx2 = tx1 + 0.5;
328   float ty1 = 0.5 * (medal / 2);
329   float ty2 = ty1 + 0.5;
330   zoom /= 10;
331   gl->enableTextures (texmedals->textureID);
332   if (antialiasing) gl->enableLinearTexture (texmedals->textureID);
333   else gl->disableLinearTexture (texmedals->textureID);
334   gl->enableAlphaBlending ();
335   glEnable (GL_ALPHA_TEST);
336   glAlphaFunc (GL_GEQUAL, 0.1);
337   glBegin (GL_QUADS);
338   glColor4ub (255, 255, 255, 200);
339   glTexCoord2f (tx1, ty1);
340   glVertex3f (x, y, z);
341   glTexCoord2f (tx2, ty1);
342   glVertex3f (x + zoom, y, z);
343   glTexCoord2f (tx2, ty2);
344   glVertex3f (x + zoom, y + zoom, z);
345   glTexCoord2f (tx1, ty2);
346   glVertex3f (x, y + zoom, z);
347   glEnd ();
348   glDisable (GL_ALPHA_TEST);
349   gl->disableAlphaBlending ();
350   glDisable (GL_TEXTURE_2D);
351 }
352 
drawMouseCursor()353 void drawMouseCursor ()
354 {
355   glPushMatrix ();
356   glMatrixMode (GL_PROJECTION);
357   glPushMatrix ();
358   glLoadIdentity ();
359   gluOrtho2D (0, width, 0, height);
360   glScalef (1, -1, 1);
361   glTranslatef (0, -height, 0);
362   glMatrixMode (GL_MODELVIEW);
363   glLoadIdentity ();
364   gl->enableAlphaBlending ();
365   glEnable (GL_ALPHA_TEST);
366   glAlphaFunc (GL_GEQUAL, 0.1);
367   glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
368   gl->enableTextures (texcross2->textureID);
369   int crossradius = width / 35;
370 
371   glTranslatef (mousex, mousey, 0);
372   glBegin (GL_QUADS);
373   glColor4ub (255, 255, 255, 255);
374   glTexCoord2i (0, 0);
375   glVertex2d (-crossradius, -crossradius);
376   glTexCoord2i (0, 1);
377   glVertex2d (-crossradius, crossradius);
378   glTexCoord2i (1, 1);
379   glVertex2d (crossradius, crossradius);
380   glTexCoord2i (1, 0);
381   glVertex2d (crossradius, -crossradius);
382   glEnd ();
383   glDisable (GL_ALPHA_TEST);
384   glDisable (GL_TEXTURE_2D);
385   gl->disableAlphaBlending ();
386   glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
387   glMatrixMode (GL_PROJECTION);
388   glPopMatrix ();
389   glMatrixMode (GL_MODELVIEW);
390   glPopMatrix ();
391 
392   glPopMatrix ();
393 }
394 
getMedal(int score)395 int getMedal (int score)
396 {
397   if (score >= 350) return 1;
398   else if (score >= 300) return 0;
399   else if (score >= 250) return 3;
400   else if (score >= 200) return 2;
401   return -1;
402 }
403 
gl117_rotateColors(int inittimer_gl117)404 void gl117_rotateColors (int inittimer_gl117)
405 {
406   int i;
407   for (i = 0; i < model_gl117.numObjects; i ++)
408   {
409     for (int i2 = 0; i2 < model_gl117.object [i]->numVertices; i2 ++)
410     {
411       model_gl117.object [i]->vertex [i2].color.c [0] = (int) (75.0F * SIN(i2 * 100 + inittimer_gl117 / 2) + 155.0F);
412       model_gl117.object [i]->vertex [i2].color.c [1] = model_gl117.object [i]->vertex [i2].color.c [0];
413       model_gl117.object [i]->vertex [i2].color.c [2] = 100;
414     }
415   }
416 }
417 
adjustBrightness()418 void adjustBrightness ()
419 {
420   // adjust brightness setting (blending)
421   if (brightness < 0)
422   {
423     glColor4ub (0, 0, 0, -brightness);
424     float xf = 2.0, yf = 1.5, zf = 1.0;
425     glDisable (GL_DEPTH_TEST);
426     glEnable (GL_BLEND);
427     glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
428     glBegin (GL_QUADS);
429     glVertex3f (-xf, -yf, -zf);
430     glVertex3f (-xf, yf, -zf);
431     glVertex3f (xf, yf, -zf);
432     glVertex3f (xf, -yf, -zf);
433     glEnd ();
434     glDisable (GL_BLEND);
435 //    glEnable (GL_DEPTH_TEST);
436   }
437   else if (brightness > 0)
438   {
439     glColor4ub (255, 255, 255, brightness);
440     float xf = 2.0, yf = 1.5, zf = 1.0;
441     glDisable (GL_DEPTH_TEST);
442     glEnable (GL_BLEND);
443     glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
444     glBegin (GL_QUADS);
445     glVertex3f (-xf, -yf, -zf);
446     glVertex3f (-xf, yf, -zf);
447     glVertex3f (xf, yf, -zf);
448     glVertex3f (xf, -yf, -zf);
449     glEnd ();
450     glDisable (GL_BLEND);
451 //    glEnable (GL_DEPTH_TEST);
452   }
453 }
454 
455 
456 
457 #ifndef USE_GLUT
458 SDL_Joystick *sdljoystick [maxjoysticks];
459 int sdljoystickaxes [maxjoysticks];
460 #endif
461 
462 int sdldisplay = true;
463 int sdlreshape = true;
464 Cockpit *cockpit;
465 float fps = 30;
466 
467 int glutwindow;
468 
469 
470 
471 bool initing = true;
472 int flash = 0;
473 int lastshield = 0;
474 
getTrainingIdFromValue(int n)475 int getTrainingIdFromValue (int n)
476 {
477   int z = 0;
478   if (n == z ++) return MISSION_TUTORIAL;
479   else if (n == z ++) return MISSION_TUTORIAL2;
480   else if (n == z ++) return MISSION_DOGFIGHT;
481   else if (n == z ++) return MISSION_TUTORIAL3;
482   else if (n == z ++) return MISSION_FREEFLIGHT1;
483   else if (n == z ++) return MISSION_DEATHMATCH1;
484   else if (n == z ++) return MISSION_DEATHMATCH2;
485   else if (n == z ++) return MISSION_DEATHMATCH3;
486   else if (n == z ++) return MISSION_TEAMBASE1;
487   else if (n == z ++) return MISSION_WAVES1;
488   else
489   {
490     return MISSION_CUSTOM1 + n - 10;
491   }
492   return 0;
493 }
494 
getCampaignIdFromValue(int n)495 int getCampaignIdFromValue (int n)
496 {
497   int z = 0;
498   if (n == z ++) return MISSION_TEST1;
499   else if (n == z ++) return MISSION_TEST2;
500   else if (n == z ++) return MISSION_TRANSPORT;
501   else if (n == z ++) return MISSION_CONVOY;
502   else if (n == z ++) return MISSION_DOGFIGHT2;
503   else if (n == z ++) return MISSION_AIRBATTLE;
504   else if (n == z ++) return MISSION_SADEFENSE;
505   else if (n == z ++) return MISSION_SCOUT;
506   else if (n == z ++) return MISSION_BASE;
507   else if (n == z ++) return MISSION_DEPOT;
508   else if (n == z ++) return MISSION_DEFEND1;
509   else if (n == z ++) return MISSION_DOGFIGHT3;
510   else if (n == z ++) return MISSION_TANK1;
511   else if (n == z ++) return MISSION_CONVOY2;
512   else if (n == z ++) return MISSION_SHIP1;
513   else if (n == z ++) return MISSION_SHIP2;
514   else if (n == z ++) return MISSION_SHIP3;
515   else if (n == z ++) return MISSION_CANYON1;
516   else if (n == z ++) return MISSION_CANYON2;
517   else if (n == z ++) return MISSION_TUNNEL1;
518   else if (n == z ++) return MISSION_CANYON3;
519   else if (n == z ++) return MISSION_MOON1;
520   else if (n == z ++) return MISSION_MOONBATTLE;
521   else if (n == z ++) return MISSION_MOON2;
522   else if (n == z ++) return MISSION_MOON3;
523   return 0;
524 }
525 
getCampaignValueFromId(int n)526 int getCampaignValueFromId (int n)
527 {
528   int z = 0;
529   if (n == MISSION_TEST1) z = 0;
530   else if (n == MISSION_TEST2) z = 1;
531   else if (n == MISSION_TRANSPORT) z = 2;
532   else if (n == MISSION_CONVOY) z = 3;
533   else if (n == MISSION_DOGFIGHT2) z = 4;
534   else if (n == MISSION_AIRBATTLE) z = 5;
535   else if (n == MISSION_SADEFENSE) z = 6;
536   else if (n == MISSION_SCOUT) z = 7;
537   else if (n == MISSION_BASE) z = 8;
538   else if (n == MISSION_DEPOT) z = 9;
539   else if (n == MISSION_DEFEND1) z = 10;
540   else if (n == MISSION_DOGFIGHT3) z = 11;
541   else if (n == MISSION_TANK1) z = 12;
542   else if (n == MISSION_CONVOY2) z = 13;
543   else if (n == MISSION_SHIP1) z = 14;
544   else if (n == MISSION_SHIP2) z = 15;
545   else if (n == MISSION_SHIP3) z = 16;
546   else if (n == MISSION_CANYON1) z = 17;
547   else if (n == MISSION_CANYON2) z = 18;
548   else if (n == MISSION_TUNNEL1) z = 19;
549   else if (n == MISSION_CANYON3) z = 20;
550   else if (n == MISSION_MOON1) z = 21;
551   else if (n == MISSION_MOONBATTLE) z = 22;
552   else if (n == MISSION_MOON2) z = 23;
553   else if (n == MISSION_MOON3) z = 24;
554   return z;
555 }
556 
setPlaneVolume()557 void setPlaneVolume ()
558 {
559   if (game == GAME_PLAY)
560   {
561     int lev = (int) ((float) 128 * fplayer->thrust / fplayer->maxthrust) - 32;
562     sound->stop (SOUND_PLANE1);
563     sound->engine = (int) (fplayer->thrust / fplayer->maxthrust * 20) - 10;
564     sound->setVolume (SOUND_PLANE1, lev);
565     sound->playLoop (SOUND_PLANE1);
566   }
567   else
568   {
569     sound->setVolume (SOUND_PLANE1, 0);
570   }
571 }
572 
setLightSource(int gamma)573 void setLightSource (int gamma)
574 {
575   light_position0 [0] = -cosi [gamma];
576   light_position0 [1] = sine [gamma];
577   light_position0 [2] = 0;
578   glLightfv (GL_LIGHT0, GL_POSITION, light_position0);
579 }
580 
getModel(int id)581 CModel *getModel (int id)
582 {
583   if (id == FIGHTER_FALCON) return &model_fig;
584   else if (id == FIGHTER_SWALLOW) return &model_figa;
585   else if (id == FIGHTER_HAWK) return &model_figb;
586   else if (id == FIGHTER_HAWK2) return &model_figc;
587   else if (id == FIGHTER_BUZZARD) return &model_figd;
588   else if (id == FIGHTER_CROW) return &model_fige;
589   else if (id == FIGHTER_PHOENIX) return &model_figf;
590   else if (id == FIGHTER_REDARROW) return &model_figg;
591   else if (id == FIGHTER_BLACKBIRD) return &model_figh;
592   else if (id == FIGHTER_STORM) return &model_figi;
593   else if (id == FIGHTER_TRANSPORT) return &model_figt;
594   else if (id == FIGHTER_TRANSPORT2) return &model_figu;
595   else if (id == MISSILE_AIR1) return &model_missile1;
596   else if (id == MISSILE_AIR2) return &model_missile2;
597   else if (id == MISSILE_AIR3) return &model_missile3;
598   else if (id == MISSILE_GROUND1) return &model_missile4;
599   else if (id == MISSILE_GROUND2) return &model_missile5;
600   else if (id == MISSILE_DF1) return &model_missile6;
601   else if (id == MISSILE_FF1) return &model_missile7;
602   else if (id == MISSILE_FF2) return &model_missile8;
603   else if (id == TANK_AIR1) return &model_tank1;
604   else if (id == TANK_GROUND1) return &model_tank2;
605   else if (id == TANK_TRSAM1) return &model_trsam;
606   else if (id == TANK_PICKUP1) return &model_pickup1;
607   else if (id == TANK_TRUCK1) return &model_truck1;
608   else if (id == TANK_TRUCK2) return &model_truck2;
609   else if (id == SHIP_CRUISER) return &model_ship1;
610   else if (id == SHIP_DESTROYER1) return &model_ship2;
611   else if (id == FLAK_AIR1) return &model_flak1;
612   else if (id == FLARAK_AIR1) return &model_flarak1;
613   else if (id == STATIC_TENT1) return &model_tent1;
614   else if (id == STATIC_TENT4) return &model_tent4;
615   else if (id == STATIC_CONTAINER1) return &model_container1;
616   else if (id == STATIC_HALL1) return &model_hall1;
617   else if (id == STATIC_HALL2) return &model_hall2;
618   else if (id == STATIC_OILRIG1) return &model_oilrig;
619   else if (id == STATIC_COMPLEX1) return &model_egg;
620   else if (id == STATIC_RADAR1) return &model_radar;
621   else if (id == STATIC_BASE1) return &model_base1;
622   else if (id == STATIC_DEPOT1) return &model_depot1;
623   else if (id == STATIC_BARRIER1) return &model_barrier1;
624   else if (id == ASTEROID) return &model_aster1;
625   return &model_fig;
626 }
627 
game_levelInit()628 int game_levelInit ()
629 {
630   int i, i2;
631 
632   // init all objects
633   for (i = 0; i < maxfighter; i ++)
634   {
635     fighter [i]->dinit ();
636     fighter [i]->aiinit ();
637 //    fighter [i]->fighterinit ();
638     fighter [i]->explode = 0;
639     fighter [i]->tl->x = 0;
640     fighter [i]->tl->z = -i * 10;
641     fighter [i]->party = 0;
642     fighter [i]->zoom = 0.35;
643     fighter [i]->deactivate ();
644     fighter [i]->recheight = 15;
645     fighter [i]->recthrust = 0.2;
646     fighter [i]->rectheta = 0;
647     fighter [i]->o = &model_fig;
648   }
649   for (i = 0; i < maxgroundobj; i ++)
650   {
651     groundobj [i]->dinit ();
652     groundobj [i]->zoom = 1;
653     groundobj [i]->id = STATIC_PASSIVE;
654     groundobj [i]->deactivate ();
655   }
656 
657 //  if (l != NULL) delete l;
658   if (!multiplayer || isserver || !isserver) // clients do not need the mission
659   {
660     Mission *missionold = mission;
661     mission = missionnew;
662     missionnew = NULL;
663     mission->difficulty = difficulty;
664     mission->start ();
665     if (mission->id >= MISSION_CUSTOM1 && mission->id <= MISSION_CUSTOM2)
666     {
667       if (((MissionCustom *) mission)->reterror)
668       {
669         display ("Could not startup mission", LOG_ERROR);
670         delete mission;
671         mission = missionold;
672         return 0;
673       }
674     }
675     if (missionold != NULL)
676     { delete missionold; missionold = NULL; }
677   }
678 
679   initing = true;
680   flash = 0;
681 
682   if (clouds == 0) highclouds->setTexture (NULL);
683   else if (clouds == 1) highclouds->setTexture (texclouds1);
684   else if (clouds == 2) highclouds->setTexture (texclouds2);
685   else if (clouds == 3) highclouds->setTexture (texclouds3);
686 
687   if (clouds == 0) highclouds2->setTexture (NULL);
688   else if (clouds == 1) highclouds2->setTexture (texclouds2);
689   else if (clouds == 2) highclouds2->setTexture (NULL);
690   else if (clouds == 3) highclouds2->setTexture (NULL);
691 
692   // place missiles to racks
693   for (i = 0; i < maxfighter; i ++)
694   {
695     if (fighter [i]->id >= FIGHTER1 && fighter [i]->id <= FIGHTER2)
696       for (i2 = 0; i2 < 4; i2 ++)
697       {
698         int type = fighter [i]->missilerack [i2];
699         CModel *rm = getModel (MISSILE1 + type);
700         fighter [i]->refmodel [i2 * 3] = rm;
701         fighter [i]->refmodel [i2 * 3 + 1] = rm;
702         fighter [i]->refmodel [i2 * 3 + 2] = rm;
703         fighter [i]->reftl [i2 * 3 + 1].z = fighter [i]->reftl [i2 * 3].z - 0.04;
704         fighter [i]->reftl [i2 * 3 + 2].z = fighter [i]->reftl [i2 * 3].z + 0.04;
705         fighter [i]->reftl [i2 * 3].y = fighter [i]->reftl [i2 * 3 + 1].y - 0.04;
706         int tmp = fighter [i]->missilerackn [i2];
707         fighter [i]->refscale [i2 * 3] = 0.25;
708         fighter [i]->refscale [i2 * 3 + 1] = 0.25;
709         fighter [i]->refscale [i2 * 3 + 2] = 0.25;
710         if (tmp < 3) fighter [i]->refscale [i2 * 3] = 0;
711         if (tmp < 2) fighter [i]->refscale [i2 * 3 + 1] = 0;
712       }
713   }
714 
715   // initialize object's height over the surface
716   for (i = 0; i < maxfighter; i ++)
717   {
718     if (fighter [i]->id >= FLAK1 && fighter [i]->id <= FLAK2)
719     {
720       fighter [i]->tl->y = l->getExactHeight (fighter [i]->tl->x, fighter [i]->tl->z) + fighter [i]->zoom;
721     }
722     else if (fighter [i]->id == SHIP_DESTROYER1)
723     {
724       fighter [i]->tl->y = l->getExactHeight (fighter [i]->tl->x, fighter [i]->tl->z) + fighter [i]->zoom / 4;
725     }
726     else if (fighter [i]->id == SHIP_CRUISER)
727     {
728       fighter [i]->tl->y = l->getExactHeight (fighter [i]->tl->x, fighter [i]->tl->z) + fighter [i]->zoom / 4;
729     }
730     else if (fighter [i]->id >= TANK1 && fighter [i]->id <= TANK2)
731     {
732       fighter [i]->tl->y = l->getExactHeight (fighter [i]->tl->x, fighter [i]->tl->z) + fighter [i]->zoom * 0.55;
733     }
734     else if (fighter [i]->id == STATIC_TENT1)
735     {
736       fighter [i]->tl->y = l->getExactHeight (fighter [i]->tl->x, fighter [i]->tl->z);
737     }
738     else if (fighter [i]->id == STATIC_CONTAINER1)
739     {
740       fighter [i]->tl->y = l->getExactHeight (fighter [i]->tl->x, fighter [i]->tl->z) + fighter [i]->zoom / 2;
741     }
742     else if (fighter [i]->id == STATIC_HALL1)
743     {
744       fighter [i]->tl->y = l->getExactHeight (fighter [i]->tl->x, fighter [i]->tl->z) + fighter [i]->zoom / 3;
745     }
746     else if (fighter [i]->id == STATIC_HALL2)
747     {
748       fighter [i]->tl->y = l->getExactHeight (fighter [i]->tl->x, fighter [i]->tl->z) + fighter [i]->zoom / 3;
749     }
750     else if (fighter [i]->id == STATIC_TENT4)
751     {
752       fighter [i]->tl->y = l->getExactHeight (fighter [i]->tl->x, fighter [i]->tl->z) + fighter [i]->zoom / 3;
753     }
754     else if (fighter [i]->id == STATIC_OILRIG1)
755     {
756       fighter [i]->tl->y = l->getExactHeight (fighter [i]->tl->x, fighter [i]->tl->z) + fighter [i]->zoom / 5;
757     }
758     else if (fighter [i]->id == STATIC_COMPLEX1)
759     {
760       fighter [i]->tl->y = l->getExactHeight (fighter [i]->tl->x, fighter [i]->tl->z) + 0.55 * fighter [i]->zoom;
761     }
762     else if (fighter [i]->id == STATIC_RADAR1)
763     {
764       fighter [i]->tl->y = l->getExactHeight (fighter [i]->tl->x, fighter [i]->tl->z) + 0.7 * fighter [i]->zoom;
765     }
766     else if (fighter [i]->id == STATIC_BASE1)
767     {
768       fighter [i]->tl->y = l->getExactHeight (fighter [i]->tl->x, fighter [i]->tl->z) + 0.5 * fighter [i]->zoom;
769     }
770     else if (fighter [i]->id == STATIC_DEPOT1)
771     {
772       fighter [i]->tl->y = l->getExactHeight (fighter [i]->tl->x, fighter [i]->tl->z) + 0.5 * fighter [i]->zoom;
773     }
774     else if (fighter [i]->id == STATIC_BARRIER1)
775     {
776       fighter [i]->tl->y = l->getExactHeight (fighter [i]->tl->x, fighter [i]->tl->z) + 0.3 * fighter [i]->zoom;
777     }
778     else if (fighter [i]->id == MISSILE_MINE1)
779     {
780       fighter [i]->tl->y = l->getHeight (fighter [i]->tl->x, fighter [i]->tl->z) + 5 + myrandom (20);
781     }
782     else if (fighter [i]->id == ASTEROID)
783     {
784       ;
785     }
786     else
787     {
788       fighter [i]->tl->y = l->getHeight (fighter [i]->tl->x, fighter [i]->tl->z) + 20;
789     }
790   }
791 
792   for (i = 0; i < maxlaser; i ++)
793   {
794     laser [i]->deactivate ();
795     if (day)
796     {
797       laser [i]->o = &model_cannon1;
798       laser [i]->zoom = 0.08;
799       laser [i]->drawlight = false;
800     }
801     else
802     {
803       laser [i]->o = &model_cannon2;
804       laser [i]->zoom = 0.1;
805     }
806   }
807 
808   for (i = 0; i < maxmissile; i ++)
809   {
810     missile [i]->aiinit ();
811     missile [i]->deactivate ();
812   }
813 
814   for (i = 0; i < maxflare; i ++)
815   {
816     flare [i]->dinit ();
817     flare [i]->deactivate ();
818   }
819 
820   for (i = 0; i < maxchaff; i ++)
821   {
822     chaff [i]->dinit ();
823     chaff [i]->deactivate ();
824   }
825 
826   for (i = 0; i < maxstar; i ++)
827   {
828     star [i]->phi = myrandom (360);
829     star [i]->gamma = myrandom (85);
830     star [i]->size = 0.6 + 0.15 * myrandom (8);
831   }
832 
833   CColor skycolor;
834 
835   if (day && weather == WEATHER_SUNNY)
836   {
837     if (sungamma < 35)
838     {
839       skycolor.setColor ((unsigned short) (127 + 70 - 2 * sungamma), 127, 127);
840       objsphere->setColor (&skycolor);
841     }
842     else
843     {
844       skycolor.setColor (127, 127, 127 + 5);
845       objsphere->setColor (&skycolor);
846     }
847     if (sungamma < 35)
848     {
849       gl->fogcolor [0] = (float) (127 + 70 - 2 * sungamma) / 256.0;
850       gl->fogcolor [1] = 0.5;
851       gl->fogcolor [2] = 0.5;
852     }
853     else
854     {
855       gl->fogcolor [0] = 0.5;
856       gl->fogcolor [1] = 0.5;
857       gl->fogcolor [2] = 0.52;
858     }
859     skycolor.setColor (50, 200, 255);
860     objsphere->setNorthPoleColor (&skycolor, 1.8);
861     if (sungamma < 35)
862     {
863       skycolor.setColor ((unsigned short) (180 + 70 - 2 * sungamma), 180, 180);
864       objsphere->setPoleColor (270, (int) (90 - sungamma), &skycolor, 0.3);
865     }
866     else
867     {
868       skycolor.setColor (200, 200, 200);
869       objsphere->setPoleColor (270, (int) (90 - sungamma), &skycolor, 0.3);
870     }
871   }
872   else if (!day && weather == WEATHER_SUNNY)
873   {
874     skycolor.setColor (64, 64, 64);
875     objsphere->setColor (&skycolor);
876     gl->fogcolor [0] = 0.25;
877     gl->fogcolor [1] = 0.25;
878     gl->fogcolor [2] = 0.25;
879     if (l->type != LAND_MOON)
880     {
881       skycolor.setColor (0, 0, 170);
882       objsphere->setNorthPoleColor (&skycolor, 1.8);
883       skycolor.setColor (64, 64, 64);
884       objsphere->setPoleColor (270, (int) (90 - sungamma), &skycolor, 0.3);
885     }
886     else
887     {
888       skycolor.setColor (0, 0, 0);
889       objsphere->setNorthPoleColor (&skycolor, 1.8);
890     }
891   }
892   else if (day && weather == WEATHER_THUNDERSTORM)
893   {
894     skycolor.setColor (102, 102, 102);
895     objsphere->setColor (&skycolor);
896     gl->fogcolor [0] = 0.4;
897     gl->fogcolor [1] = 0.4;
898     gl->fogcolor [2] = 0.4;
899     skycolor.setColor (102, 102, 102);
900     objsphere->setNorthPoleColor (&skycolor, 1.8);
901   }
902   else if (!day && weather == WEATHER_THUNDERSTORM)
903   {
904     skycolor.setColor (40, 40, 40);
905     objsphere->setColor (&skycolor);
906     gl->fogcolor [0] = 0.16;
907     gl->fogcolor [1] = 0.16;
908     gl->fogcolor [2] = 0.16;
909     skycolor.setColor (40, 40, 40);
910     objsphere->setNorthPoleColor (&skycolor, 1.8);
911   }
912   else if (weather == WEATHER_CLOUDY)
913   {
914     skycolor.setColor (20, 20, 20);
915     objsphere->setColor (&skycolor);
916     gl->fogcolor [0] = 0.08;
917     gl->fogcolor [1] = 0.08;
918     gl->fogcolor [2] = 0.08;
919   }
920   glDeleteLists (objsphere->list1, 1);
921   glDeleteLists (objsphere->list2, 1);
922   glDeleteLists (objsphere->list3, 1);
923   objsphere->list1 = -1;
924   objsphere->list2 = -1;
925   objsphere->list3 = -1;
926 
927 //  glLightfv( GL_LIGHT0, GL_AMBIENT, light_ambient );
928 /*  float light_specular [3] = {0.5, 0.5, 0.5};
929   glLightfv( GL_LIGHT0, GL_SPECULAR, light_specular );*/
930   setLightSource ((int) sungamma);
931   glLightModeli (GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
932 //  glLightModeli (GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
933   glEnable (GL_LIGHT0);                // Turn on a light with defaults set
934   float light_ambient [4] = {0.2, 0.2, 0.2, 1.0};
935   float light_diffuse [4] = {1.0, 1.0, 1.0, 1.0};
936   float light_specular [4] = {1.0, 1.0, 1.0, 1.0};
937   glLightfv (GL_LIGHT0, GL_AMBIENT, light_ambient);
938   glLightfv (GL_LIGHT0, GL_DIFFUSE, light_diffuse);
939   glLightfv (GL_LIGHT0, GL_SPECULAR, light_specular);
940   glEnable (GL_LIGHTING);                // Turn on lighting
941   glEnable (GL_COLOR_MATERIAL);            // Allow color
942 
943   glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
944 //  glDisable (GL_DITHER);
945 
946   fplayer->missiletype = fplayer->firstMissile ();
947   initing = false;
948   lastshield = (int) fplayer->shield;
949 
950   fps = 30;
951 
952   redout = 0;
953   blackout = 0;
954 
955   if (!fplayer->ai)
956     fplayer->realism = physics;
957 
958 /*#ifdef HAVE_SDL_NET
959   if (multiplayer)
960   {
961     if (threadnet != NULL)
962       SDL_KillThread (threadnet);
963     threadnet = SDL_CreateThread (net_thread_main, NULL);
964   }
965 #endif*/
966 
967   return 1;
968 }
969 
game_reshape()970 void game_reshape ()
971 {
972   glViewport(0, 0, (GLint) width, (GLint) height);
973 
974   glMatrixMode (GL_PROJECTION);
975   glLoadIdentity ();
976 
977   float v = getView ();
978   if (camera == 50) v = 100000.0;
979   gluPerspective (visibleangle, (float) width / height, nearclippingplane * GLOBALSCALE, v * GLOBALSCALE);
980   glPolygonMode (GL_FRONT_AND_BACK, polygonMode);
981 
982 #ifndef USE_GLUT
983 /*  if (controls == 1)
984     SDL_ShowCursor (1);
985   else*/
986     SDL_ShowCursor (0);
987 #endif
988 }
989 
menu_reshape()990 void menu_reshape ()
991 {
992   glViewport(0, 0, (GLint) width, (GLint) height);
993 
994   glMatrixMode (GL_PROJECTION);
995   glLoadIdentity ();
996 
997   float v = getView ();
998   if (camera == 50) v = 100000.0;
999   gluPerspective (visibleangle, 1.0, nearclippingplane * GLOBALSCALE, v * GLOBALSCALE);
1000   glPolygonMode (GL_FRONT_AND_BACK, polygonMode);
1001 
1002 #ifndef USE_GLUT
1003   SDL_ShowCursor (0);
1004 #endif
1005 }
1006 
credits_reshape()1007 void credits_reshape ()
1008 {
1009   glViewport(0, 0, (GLint) width, (GLint) height);
1010 
1011   glMatrixMode (GL_PROJECTION);
1012   glLoadIdentity ();
1013 
1014   float v = getView ();
1015   if (camera == 50) v = 100000.0;
1016   gluPerspective (visibleangle, 1.0, nearclippingplane * GLOBALSCALE, v * GLOBALSCALE);
1017   glPolygonMode (GL_FRONT_AND_BACK, polygonMode);
1018 
1019 #ifndef USE_GLUT
1020   SDL_ShowCursor (0);
1021 #endif
1022 }
1023 
stats_reshape()1024 void stats_reshape ()
1025 {
1026   glViewport(0, 0, (GLint) width, (GLint) height);
1027 
1028   glMatrixMode (GL_PROJECTION);
1029   glLoadIdentity ();
1030 
1031   float v = getView ();
1032   if (camera == 50) v = 100000.0;
1033   gluPerspective (visibleangle, 1.0, nearclippingplane * GLOBALSCALE, v * GLOBALSCALE);
1034   glPolygonMode (GL_FRONT_AND_BACK, polygonMode);
1035 
1036 #ifndef USE_GLUT
1037   SDL_ShowCursor (0);
1038 #endif
1039 }
1040 
playRandomMusic()1041 void playRandomMusic ()
1042 {
1043   int r = myrandom (6);
1044   if (r == 0)
1045     sound->loadMusic (MUSIC_DARK1);
1046   else if (r == 1)
1047     sound->loadMusic (MUSIC_STANDBY1);
1048   else if (r == 2)
1049     sound->loadMusic (MUSIC_ELECTRO1);
1050   else if (r == 3)
1051     sound->loadMusic (MUSIC_STARS1);
1052   else if (r == 4)
1053     sound->loadMusic (MUSIC_SOFTTEC1);
1054   else
1055     sound->loadMusic (MUSIC_AMBIENT1);
1056   sound->playMusic (1);
1057 #ifdef HAVE_SDL_MIXER
1058   Mix_HookMusicFinished (playRandomMusic);
1059 #endif
1060 }
1061 
switch_menu()1062 void switch_menu ()
1063 {
1064   lasttime = 0;
1065   setLightSource ((int) sungamma);
1066   game = GAME_MENU;
1067   menu_reshape ();
1068   sound->stop (SOUND_PLANE1);
1069   if (!sound->musicplaying)
1070     playRandomMusic ();
1071   allmenus.visible = true;
1072   allmenus.components [0]->setVisible (true);
1073   if (currentsubmenu)
1074   {
1075     currentsubmenu->setVisible (true);
1076   }
1077   if (missionactive)
1078     mainbutton [6]->setVisible (true);
1079   else
1080     mainbutton [6]->setVisible (false);
1081 #ifdef HAVE_SDL
1082   SDL_WM_GrabInput (SDL_GRAB_OFF);
1083 #endif
1084 }
1085 
1086 bool ispromoted;
1087 int statsitemselected = 0;
1088 
switch_stats()1089 void switch_stats ()
1090 {
1091   lasttime = 0;
1092   setLightSource ((int) sungamma);
1093   game = GAME_STATS;
1094   statsitemselected = 0;
1095   int lastrank = pilots->pilot [pilots->aktpilot]->ranking;
1096   (void) pilots->pilot [pilots->aktpilot]->getRank ();
1097   ispromoted = false;
1098   if (lastrank < pilots->pilot [pilots->aktpilot]->ranking)
1099     ispromoted = true;
1100   stats_reshape ();
1101   sound->stop (SOUND_PLANE1);
1102   if (!sound->musicplaying)
1103   {
1104     int missionstate = mission->processtimer (1);
1105     if (missionstate == 1)
1106       sound->loadMusic (MUSIC_WINNER1);
1107     else
1108       sound->loadMusic (MUSIC_LOSER1);
1109     sound->playMusic ();
1110   }
1111 }
1112 
createMission(int missionid)1113 void createMission (int missionid)
1114 {
1115   if (missionid >= MISSION_MULTIPLAYER)
1116   {
1117     multiplayer = true;
1118   }
1119   else
1120   {
1121     multiplayer = false;
1122     isserver = false;
1123   }
1124   if (missionnew != NULL) delete missionnew;
1125   if (missionid == MISSION_DEMO) missionnew = new MissionDemo1 ();
1126   else if (missionid == MISSION_TEST1) missionnew = new MissionTest1 ();
1127   else if (missionid == MISSION_TEST2) missionnew = new MissionTest2 ();
1128   else if (missionid == MISSION_TRANSPORT) missionnew = new MissionTransport ();
1129   else if (missionid == MISSION_CONVOY) missionnew = new MissionConvoy ();
1130   else if (missionid == MISSION_DOGFIGHT2) missionnew = new MissionDogfight2 ();
1131   else if (missionid == MISSION_AIRBATTLE) missionnew = new MissionAirBattle ();
1132   else if (missionid == MISSION_SADEFENSE) missionnew = new MissionGround1 ();
1133   else if (missionid == MISSION_SCOUT) missionnew = new MissionScout ();
1134   else if (missionid == MISSION_BASE) missionnew = new MissionBase ();
1135   else if (missionid == MISSION_DEPOT) missionnew = new MissionDepot ();
1136   else if (missionid == MISSION_DEFEND1) missionnew = new MissionDefend1 ();
1137   else if (missionid == MISSION_DOGFIGHT3) missionnew = new MissionDogfight3 ();
1138   else if (missionid == MISSION_TANK1) missionnew = new MissionTank1 ();
1139   else if (missionid == MISSION_CONVOY2) missionnew = new MissionConvoy2 ();
1140   else if (missionid == MISSION_SHIP1) missionnew = new MissionShip1 ();
1141   else if (missionid == MISSION_SHIP2) missionnew = new MissionShip2 ();
1142   else if (missionid == MISSION_SHIP3) missionnew = new MissionShip3 ();
1143   else if (missionid == MISSION_CANYON1) missionnew = new MissionCanyon1 ();
1144   else if (missionid == MISSION_CANYON2) missionnew = new MissionCanyon2 ();
1145   else if (missionid == MISSION_CANYON3) missionnew = new MissionCanyon3 ();
1146   else if (missionid == MISSION_TUNNEL1) missionnew = new MissionTunnel1 ();
1147   else if (missionid == MISSION_MOON1) missionnew = new MissionMoonDefense1 ();
1148   else if (missionid == MISSION_MOONBATTLE) missionnew = new MissionMoonBattle ();
1149   else if (missionid == MISSION_MOON2) missionnew = new MissionMoonDogfight1 ();
1150   else if (missionid == MISSION_MOON3) missionnew = new MissionMoonBase1 ();
1151   else if (missionid == MISSION_TUTORIAL) missionnew = new MissionTutorial1 ();
1152   else if (missionid == MISSION_TUTORIAL2) missionnew = new MissionTutorial2 ();
1153   else if (missionid == MISSION_DOGFIGHT) missionnew = new MissionDogfight1 ();
1154   else if (missionid == MISSION_TUTORIAL3) missionnew = new MissionTutorial3 ();
1155   else if (missionid == MISSION_FREEFLIGHT1) missionnew = new MissionFreeFlight1 ();
1156   else if (missionid == MISSION_DEATHMATCH1) missionnew = new MissionDeathmatch1 ();
1157   else if (missionid == MISSION_DEATHMATCH2) missionnew = new MissionDeathmatch2 ();
1158   else if (missionid == MISSION_DEATHMATCH3) missionnew = new MissionDeathmatch3 ();
1159   else if (missionid == MISSION_TEAMBASE1) missionnew = new MissionTeamBase1 ();
1160   else if (missionid == MISSION_WAVES1) missionnew = new MissionWaves1 ();
1161   else if (missionid == MISSION_MULTIPLAYER_DOGFIGHT) missionnew = new MissionMultiDogfight1 ();
1162   else if (missionid >= MISSION_CUSTOM1 && missionid <= MISSION_CUSTOM2)
1163   {
1164     missionnew = new MissionCustom ();
1165     missionnew->id = missionid;
1166     ((MissionCustom *) missionnew)->init ();
1167   }
1168   if (mission != NULL)
1169   {
1170     if (mission->id == missionnew->id)
1171     {
1172       missionnew->wantfighter = mission->wantfighter;
1173       missionnew->wantweapon = mission->wantweapon;
1174     }
1175   }
1176 }
1177 
switch_mission(int missionid)1178 void switch_mission (int missionid)
1179 {
1180   lasttime = 0;
1181   setLightSource (60);
1182   game = GAME_MISSION;
1183   createMission (missionid);
1184   if (missionid >= MISSION_CUSTOM1 && missionid <= MISSION_CUSTOM2)
1185   {
1186     if (((MissionCustom *) missionnew)->reterror)
1187     {
1188       display ("Could not init mission", LOG_ERROR);
1189       // play error sound
1190       switch_menu ();
1191       return;
1192     }
1193   }
1194   menu_reshape ();
1195   sound->stop (SOUND_PLANE1);
1196   if (!sound->musicplaying)
1197     playRandomMusic ();
1198 }
1199 
switch_fame()1200 void switch_fame ()
1201 {
1202   lasttime = 0;
1203   setLightSource (60);
1204   game = GAME_FAME;
1205   menu_reshape ();
1206   sound->stop (SOUND_PLANE1);
1207   if (!sound->musicplaying)
1208     playRandomMusic ();
1209 }
1210 
switch_fighter()1211 void switch_fighter ()
1212 {
1213   lasttime = 0;
1214   setLightSource (60);
1215   game = GAME_FIGHTER;
1216   menu_reshape ();
1217   sound->stop (SOUND_PLANE1);
1218   if (!sound->musicplaying)
1219     playRandomMusic ();
1220 }
1221 
switch_create()1222 void switch_create ()
1223 {
1224   lasttime = 0;
1225   setLightSource (60);
1226   game = GAME_CREATE;
1227   isserver = true;
1228   if (server != NULL) delete server;
1229   server = new Server ();
1230   menu_reshape ();
1231   sound->stop (SOUND_PLANE1);
1232   if (!sound->musicplaying)
1233     playRandomMusic ();
1234 }
1235 
switch_join()1236 void switch_join ()
1237 {
1238   lasttime = 0;
1239   setLightSource (60);
1240   game = GAME_JOIN;
1241   isserver = false;
1242   if (client != NULL) delete client;
1243   client = new Client ();
1244   menu_reshape ();
1245   sound->stop (SOUND_PLANE1);
1246   if (!sound->musicplaying)
1247     playRandomMusic ();
1248 }
1249 
1250 int creditstimer, finishtimer;
1251 
switch_credits()1252 void switch_credits ()
1253 {
1254   lasttime = 0;
1255   game = GAME_CREDITS;
1256   creditstimer = 50 * timestep;
1257   credits_reshape ();
1258   sound->stop (SOUND_PLANE1);
1259   sound->stop (SOUND_CANNON1);
1260 }
1261 
switch_finish()1262 void switch_finish ()
1263 {
1264   lasttime = 0;
1265   game = GAME_FINISH;
1266   creditstimer = 50 * timestep;
1267   credits_reshape ();
1268   if (sound->musicplaying)
1269     sound->haltMusic ();
1270   sound->loadMusic (MUSIC_ELECTRO1);
1271   sound->playMusic ();
1272   sound->stop (SOUND_PLANE1);
1273   sound->stop (SOUND_CANNON1);
1274 }
1275 
switch_quit()1276 void switch_quit ()
1277 {
1278   lasttime = 0;
1279   game = GAME_QUIT;
1280   save_saveconfig (); // this configuration seems to work => save it
1281 }
1282 
switch_game()1283 void switch_game ()
1284 {
1285   lasttime = 0;
1286   setLightSource ((int) sungamma);
1287   game = GAME_PLAY;
1288   game_reshape ();
1289   if (sound->musicplaying)
1290     sound->haltMusic ();
1291   sound->playLoop (SOUND_PLANE1);
1292   setPlaneVolume ();
1293 #ifdef HAVE_SDL
1294   SDL_WM_GrabInput (SDL_GRAB_ON);
1295 #endif
1296 }
1297 
1298 bool startcannon = false;
1299 
event_setAntialiasing()1300 void event_setAntialiasing ()
1301 {
1302   if (antialiasing)
1303   {
1304     gl->enableLinearTexture (font1->texture->textureID);
1305     gl->enableLinearTexture (font2->texture->textureID);
1306     if (texmoon != NULL)
1307     {
1308       gl->enableLinearTexture (texmoon->textureID);
1309       gl->enableLinearTexture (texsun->textureID);
1310       gl->enableLinearTexture (texearth->textureID);
1311     }
1312   }
1313   else
1314   {
1315     gl->disableLinearTexture (font1->texture->textureID);
1316     gl->disableLinearTexture (font2->texture->textureID);
1317     if (texmoon != NULL)
1318     {
1319       gl->disableLinearTexture (texmoon->textureID);
1320       gl->disableLinearTexture (texsun->textureID);
1321       gl->disableLinearTexture (texearth->textureID);
1322     }
1323   }
1324 }
1325 
event_fireCannon()1326 void event_fireCannon ()
1327 {
1328   if (!fplayer->active) return;
1329   if (fplayer->firecannonttl > 0) return;
1330   if (fplayer->ammo == 0) return;
1331 #ifdef USE_GLUT
1332   fplayer->fireCannon (laser);
1333 #else
1334   fplayer->autofire = true;
1335 #endif
1336 }
1337 
event_stopCannon()1338 void event_stopCannon ()
1339 {
1340   fplayer->autofire = false;
1341 }
1342 
event_fireMissile()1343 void event_fireMissile ()
1344 {
1345   if (!fplayer->active) return;
1346   if (fplayer->firemissilettl > 0) return;
1347   if (fplayer->fireMissile (fplayer->missiletype + MISSILE1, missile))
1348     sound->play (SOUND_MISSILE1, false);
1349 }
1350 
event_fireChaff()1351 void event_fireChaff ()
1352 {
1353   if (!fplayer->active) return;
1354   if (fplayer->firechaffttl > 0) return;
1355   if (fplayer->fireChaff (chaff, missile))
1356     sound->play (SOUND_CHAFF1, false);
1357 }
1358 
event_fireFlare()1359 void event_fireFlare ()
1360 {
1361   if (!fplayer->active) return;
1362   if (fplayer->fireflarettl > 0) return;
1363   if (fplayer->fireFlare (flare, missile))
1364     sound->play (SOUND_CHAFF1, false);
1365 }
1366 
event_selectMissile()1367 void event_selectMissile ()
1368 {
1369   if (!fplayer->active) return;
1370   fplayer->missiletype = fplayer->nextMissile (fplayer->missiletype);
1371 }
1372 
event_targetNearest()1373 void event_targetNearest ()
1374 {
1375   if (!fplayer->active) return;
1376   fplayer->targetNearestEnemy ((AIObj **) fighter);
1377   sound->play (SOUND_CLICK1, false);
1378 }
1379 
event_targetNext()1380 void event_targetNext ()
1381 {
1382   if (!fplayer->active) return;
1383   fplayer->targetNext ((AIObj **) fighter);
1384   sound->play (SOUND_CLICK1, false);
1385 }
1386 
event_targetPrevious()1387 void event_targetPrevious ()
1388 {
1389   if (!fplayer->active) return;
1390   fplayer->targetPrevious ((AIObj **) fighter);
1391   sound->play (SOUND_CLICK1, false);
1392 }
1393 
event_targetLocking()1394 void event_targetLocking ()
1395 {
1396   if (!fplayer->active) return;
1397   fplayer->targetLockingEnemy ((AIObj **) fighter);
1398   sound->play (SOUND_CLICK1, false);
1399 }
1400 
event_thrustUp()1401 void event_thrustUp ()
1402 {
1403   if (!fplayer->active) return;
1404   fplayer->thrustUp ();
1405   fplayer->thrustUp ();
1406 }
1407 
event_thrustDown()1408 void event_thrustDown ()
1409 {
1410   if (!fplayer->active) return;
1411   fplayer->thrustDown ();
1412   fplayer->thrustDown ();
1413 }
1414 
game_key(int key,int x,int y)1415 void game_key (int key, int x, int y)
1416 {
1417   unsigned int hikey = key;
1418   unsigned int lokey = key;
1419 
1420   if (camera == 50 && game == GAME_PAUSE)
1421   {
1422     camera = 0;
1423     game = GAME_PLAY;
1424     return;
1425   }
1426   else if (key == 27)
1427   {
1428     switch_menu ();
1429   }
1430   else if (hikey == key_firemissile || lokey == key_firemissile)
1431   {
1432     event_fireMissile ();
1433   }
1434   else if (hikey == key_dropflare || lokey == key_dropflare)
1435   {
1436     event_fireFlare ();
1437   }
1438   else if (hikey == key_dropchaff || lokey == key_dropchaff)
1439   {
1440     event_fireChaff ();
1441   }
1442   else if (hikey == key_firecannon || lokey == key_firecannon)
1443   {
1444     event_fireCannon ();
1445   }
1446   else if (hikey == key_selectmissile || lokey == key_selectmissile)
1447   {
1448     event_selectMissile ();
1449   }
1450   else if (hikey == key_thrustup || lokey == key_thrustup)
1451   {
1452     event_thrustUp ();
1453   }
1454   else if (hikey == key_thrustdown || lokey == key_thrustdown)
1455   {
1456     event_thrustDown ();
1457   }
1458   else if (key >= '1' && key <= '9')
1459   {
1460     fplayer->recthrust = fplayer->maxthrust * (1.0 / 18.0 * (key - '0') + 0.5);
1461     sound->play (SOUND_CLICK1, false);
1462   }
1463   else if (hikey == key_targetnearest || lokey == key_targetnearest)
1464   {
1465     event_targetNearest ();
1466   }
1467   else if (hikey == key_targetnext || lokey == key_targetnext)
1468   {
1469     event_targetNext ();
1470   }
1471   else if (hikey == key_targetprevious || lokey == key_targetprevious)
1472   {
1473     event_targetPrevious ();
1474   }
1475   else if (hikey == key_targetlocking || lokey == key_targetlocking)
1476   {
1477     event_targetLocking ();
1478   }
1479 /*  else if (key == 'K')
1480   {
1481     if (fplayer->target != NULL)
1482       fplayer->target->shield = -1;
1483   }
1484   else if (key == 'V')
1485   {
1486     visibleangle += 10.0;
1487     if (visibleangle > 120.0) visibleangle = 50.0;
1488   }*/
1489   else if (hikey == key_firecannon || lokey == key_firecannon)
1490   {
1491     fplayer->autofire = false;
1492   }
1493 
1494   switch (key - 256) // standard special keys
1495   {
1496     case KEY_LSHIFT:
1497       keyb_lshift = 1;
1498       break;
1499     case KEY_UP:
1500       keyb_elev = -1;
1501       break;
1502     case KEY_DOWN:
1503       keyb_elev = 1;
1504       break;
1505     case KEY_LEFT:
1506       if (keyb_lshift) keyb_rudder = -1;
1507       else keyb_roll = 1;
1508       break;
1509     case KEY_RIGHT:
1510       if (keyb_lshift) keyb_rudder = 1;
1511       else keyb_roll = -1;
1512       break;
1513     case KEY_F1:
1514       camera = 0;
1515       game_reshape ();
1516       break;
1517     case KEY_F2:
1518       camera = 1;
1519       game_reshape ();
1520       break;
1521     case KEY_F3:
1522       camera = 2;
1523       game_reshape ();
1524       break;
1525     case KEY_F4:
1526       camera = 6;
1527       game_reshape ();
1528       break;
1529     case KEY_F5:
1530       camera = 7;
1531       game_reshape ();
1532       break;
1533     case KEY_F6:
1534       camera = 9;
1535       game_reshape ();
1536       break;
1537     case KEY_F7:
1538       camera = 8;
1539       game_reshape ();
1540       break;
1541     case KEY_F8:
1542       camera = 5;
1543       game_reshape ();
1544       break;
1545     default:
1546       return;
1547   }
1548 
1549 #ifdef USE_GLUT
1550   glutPostRedisplay();
1551 #else
1552   sdldisplay = true;
1553 #endif
1554 }
1555 
game_keyup(int key,int x,int y)1556 void game_keyup (int key, int x, int y)
1557 {
1558   unsigned int hikey = (unsigned int) key;
1559   unsigned int lokey = (unsigned int) key;
1560 
1561   if (hikey == key_firecannon || lokey == key_firecannon)
1562   {
1563     event_stopCannon ();
1564   }
1565 
1566   switch (key - 256) // standard special keys
1567   {
1568     case KEY_LSHIFT:
1569       keyb_lshift = 0;
1570       break;
1571     case KEY_UP:
1572       keyb_elev = 0;
1573       break;
1574     case KEY_DOWN:
1575       keyb_elev = 0;
1576       break;
1577     case KEY_LEFT:
1578       keyb_roll = 0;
1579       keyb_rudder = 0;
1580       break;
1581     case KEY_RIGHT:
1582       keyb_roll = 0;
1583       keyb_rudder = 0;
1584       break;
1585     case KEY_LALT:
1586       keyb_rudder = 0;
1587       break;
1588     case KEY_LCTRL:
1589       keyb_rudder = 0;
1590       break;
1591   }
1592 
1593 #ifdef USE_GLUT
1594     glutPostRedisplay();
1595 #else
1596     sdldisplay = true;
1597 #endif
1598 }
1599 
1600 int aktcam = 0;
1601 
game_mouse(int button,int state,int x,int y)1602 void game_mouse (int button, int state, int x, int y)
1603 {
1604   if (state == MOUSE_DOWN && fplayer->active)
1605   {
1606     if (button == mouse_firecannon)
1607     {
1608       fplayer->autofire = !fplayer->autofire;
1609     }
1610     else if (button == mouse_firemissile)
1611     {
1612       event_fireMissile ();
1613     }
1614     else if (button == mouse_selectmissile)
1615     {
1616       event_selectMissile ();
1617     }
1618   }
1619 }
1620 
1621 float dtheta = 0, dgamma = 0;
1622 
1623 int lastmousex = 0;
1624 
1625 int lastmx = 0, lastmy = 0;
1626 
game_mouserelmotion(int xrel,int yrel)1627 void game_mouserelmotion (int xrel, int yrel)
1628 {
1629   if (controls != CONTROLS_MOUSE || !mouse_relative) return;
1630   float xr = (float) xrel / width, yr = (float) yrel / height;
1631 
1632   float roll = (float) -xr * 20;
1633 
1634   if (roll > 1.0F) roll = 1.0F;
1635   else if (roll < -1.0F) roll = -1.0F;
1636   fplayer->rolleffect = roll;
1637   if (roll < 1E-3)
1638     fplayer->ruddereffect = (float) xr * 200;
1639   else
1640     fplayer->ruddereffect = 0.0f;
1641   if (fplayer->ruddereffect > 1.0) fplayer->ruddereffect = 1.0;
1642   else if (fplayer->ruddereffect < -1.0) fplayer->ruddereffect = -1.0;
1643 
1644   fplayer->elevatoreffect = (float) yr * fabs (yr) * 20000;
1645   if (!mouse_reverse) fplayer->elevatoreffect *= -1;
1646   if (fplayer->elevatoreffect > 1.0f) fplayer->elevatoreffect = 1.0f;
1647   else if (fplayer->elevatoreffect < -0.5f) fplayer->elevatoreffect = -0.5f;
1648 }
1649 
game_mousemotion(int x,int y)1650 void game_mousemotion (int x, int y)
1651 {
1652   if (controls != CONTROLS_MOUSE || mouse_relative) return;
1653 
1654   float mx = width / 2, my = height / 2;
1655   float dx = x - mx, dy = my - y;
1656   dx *= mouse_sensitivity / 70.0F;
1657   dy *= mouse_sensitivity / 70.0F;
1658   if (mouse_reverse)
1659     dy *= -1;
1660 
1661 // mouse interface code added by Lourens Veen
1662   float nx = dx / width; // normalised x-coordinate, -1 at lefthand
1663                          // side of the screen, 1 at righthand side
1664   if (mouse_autorudder)
1665   {
1666     if (fabs(nx) < (1.0f/3.0f))
1667     if (nx < 0.0f)
1668       fplayer->ruddereffect = 729.0f*nx*(nx+1.0f/3.0f)*(nx+1.0f/3.0f)/4.0f;
1669     else
1670       fplayer->ruddereffect = 729.0f*nx*(nx-1.0f/3.0f)*(nx-1.0f/3.0f)/4.0f;
1671     else
1672       fplayer->ruddereffect = 0.0f;
1673   }
1674   else
1675   {
1676     fplayer->ruddereffect = 0;
1677   }
1678 
1679   const float roll_deadarea = (float) mouse_autorudder / 1000.0F; //(1.0f/30.0f);
1680 
1681   if (fabs(nx) > roll_deadarea)
1682   {
1683     if (nx > 0.0f) nx -= roll_deadarea;
1684     else nx += roll_deadarea;
1685 
1686     if (nx > 0)
1687       fplayer->rolleffect = -(exp(log(nx) * 1.3f)) * 3.0f;
1688     else
1689       fplayer->rolleffect = (exp(log(-nx) * 1.3f)) * 3.0f;
1690 
1691     if (fplayer->rolleffect < -1.0F) fplayer->rolleffect = -1.0F;
1692     if (fplayer->rolleffect > 1.0F) fplayer->rolleffect = 1.0F;
1693   }
1694   else
1695     fplayer->rolleffect = 0.0f;
1696 
1697   fplayer->elevatoreffect = dy / height * 2.5;
1698   if (fplayer->elevatoreffect > 1.0f) fplayer->elevatoreffect = 1.0f;
1699   else if (fplayer->elevatoreffect < -0.5f) fplayer->elevatoreffect = -0.5f;
1700 
1701 #ifdef USE_GLUT
1702   glutPostRedisplay();
1703 #else
1704   sdldisplay = true;
1705 #endif
1706 }
1707 
1708 int jaxis [maxjaxis * maxjoysticks];
1709 
getJoystickAxisIndex(int n)1710 int getJoystickAxisIndex (int n)
1711 {
1712   int idx = (n / 1000) * 10 + (n % 1000);
1713   if (idx < 0) idx = 0;
1714   if (idx >= maxjaxis) idx = 0;
1715   return idx;
1716 }
1717 
game_joystickaxis(int x,int y,int rudder,int throttle)1718 void game_joystickaxis (int x, int y, int rudder, int throttle)
1719 {
1720   if (fplayer->ai) return;
1721   float xx = x / 32768.0;
1722   xx *= fabs (xx);
1723   fplayer->rolleffect = (float) -xx;
1724   fplayer->elevatoreffect = (float) y / 30000;
1725   if (fplayer->elevatoreffect > 1.0) fplayer->elevatoreffect = 1.0;
1726   else if (fplayer->elevatoreffect < -1.0) fplayer->elevatoreffect = -1.0;
1727   if (fplayer->elevatoreffect < -0.5) fplayer->elevatoreffect = -0.5;
1728   fplayer->ruddereffect = (float) rudder / 30000;
1729   if (fplayer->ruddereffect > 1.0) fplayer->ruddereffect = 1.0;
1730   else if (fplayer->ruddereffect < -1.0) fplayer->ruddereffect = -1.0;
1731   fplayer->recthrust = fplayer->maxthrust * 0.75 - fplayer->maxthrust / 4 * throttle / 32638;
1732 }
1733 
game_joystickbutton(int button)1734 void game_joystickbutton (int button)
1735 {
1736   if (!fplayer->active) return;
1737   if (button == joystick_firecannon)
1738   {
1739     fplayer->fireCannon (laser);
1740 #ifdef HAVE_SDL_MIXER
1741     if (!startcannon)
1742     {
1743       sound->playLoop (SOUND_CANNON1);
1744       startcannon = true;
1745     }
1746 #else
1747     sound->play (SOUND_CANNON1, 1);
1748 #endif
1749   }
1750   if (button == joystick_firemissile)
1751   {
1752     event_fireMissile ();
1753   }
1754   if (button == joystick_dropflare)
1755   {
1756     event_fireFlare ();
1757   }
1758   if (button == joystick_dropchaff)
1759   {
1760     event_fireChaff ();
1761   }
1762   if (button == joystick_selectmissile)
1763   {
1764     event_selectMissile ();
1765   }
1766   if (button == joystick_targetnearest)
1767   {
1768     event_targetNearest ();
1769   }
1770   if (button == joystick_targetlocking)
1771   {
1772     event_targetLocking ();
1773   }
1774   if (button == joystick_targetnext)
1775   {
1776     event_targetNext ();
1777   }
1778   if (button == joystick_targetprevious)
1779   {
1780     event_targetPrevious ();
1781   }
1782   if (button == joystick_thrustup)
1783   {
1784     event_thrustUp ();
1785   }
1786   if (button == joystick_thrustdown)
1787   {
1788     event_thrustDown ();
1789   }
1790 }
1791 
game_joystickhat(int normhat)1792 void game_joystickhat (int normhat)
1793 {
1794 #ifndef USE_GLUT
1795   game_joystickbutton (normhat);
1796 #endif
1797 }
1798 
1799 int frames = 0, time2 = 0, time1 = 0;
1800 
frame()1801 void frame ()
1802 {
1803   frames ++;
1804 #ifndef USE_GLUT
1805   time2 = SDL_GetTicks ();
1806 #else
1807   time2 = glutGet (GLUT_ELAPSED_TIME);
1808 #endif
1809   if (time2 - time1 > 1000)
1810   {
1811     if (time2 - time1 < 1500)
1812       fps = (float) frames * 1000.0 / (time2 - time1);
1813     time1 = time2;
1814     frames = 0;
1815   }
1816 }
1817 
game_view()1818 void game_view ()
1819 {
1820   frame ();
1821 #ifdef USE_GLUT
1822   glutSwapBuffers();
1823 #else
1824   SDL_GL_SwapBuffers ();
1825 #endif
1826 }
1827 
1828 int missionending = 0;
1829 int missionstate = 0;
1830 
1831 int menuitem = 0, menutimer = 0, menuitemselected = -1, missionmenutimer;
1832 int missionmenuitemselected = 0, missionmenufighterselected = -1, missionmenuweaponselected = -1;
1833 
drawCircles(CColor * colorstd)1834 void drawCircles (CColor *colorstd)
1835 {
1836   int i;
1837   float zf = -3, yf, xf;
1838   int t = 360 - (missionmenutimer * 10 / timestep) % 360;
1839   for (i = 0; i < 20; i ++)
1840   {
1841     yf = -3 + 0.3 * i; // - (float) (missionmenutimer & 63) / 64.0;
1842     glBegin (GL_QUAD_STRIP);
1843     for (int i2 = 0; i2 < 20; i2 ++)
1844     {
1845       xf = -3 + 0.3 * i2;
1846       yf = -3 + 0.3 * i;
1847       float cola = sine [(int) (sqrt (xf * xf + yf * yf) * 200 + t) % 360] / 10 + 0.2;
1848       if (colorstd == &colorblue) glColor3f (0, 0, cola);
1849       else glColor3f (cola, 0, 0);
1850       glVertex3f (xf, yf, zf);
1851       yf = -3 + 0.3 * (i + 1);
1852       cola = sine [(int) (sqrt (xf * xf + yf * yf) * 200 + t) % 360] / 10 + 0.2;
1853       if (colorstd == &colorblue) glColor3f (0, 0, cola);
1854       else glColor3f (cola, 0, 0);
1855       glVertex3f (xf, yf, zf);
1856     }
1857     glEnd ();
1858   }
1859 }
1860 
drawQuads(CColor * colorstd)1861 void drawQuads (CColor *colorstd)
1862 {
1863   int i;
1864   float zf = -3, yf;
1865   for (i = 0; i < 14; i ++)
1866   {
1867     yf = -3 + 0.5 * i - (float) (missionmenutimer / timestep & 63) / 64.0;
1868     glBegin (GL_QUAD_STRIP);
1869     for (int i2 = 0; i2 < 14; i2 ++)
1870     {
1871       float cola = sine [(i * 100+missionmenutimer*4 / timestep) % 360] / 10 + sine [(i2 * 100) % 360] / 10 + 0.2;
1872       if (colorstd == &colorblue) glColor3f (0, 0, cola);
1873       else glColor3f (cola, 0, 0);
1874       glVertex3f (-3 + 0.5 * i2, -3 + 0.5 * i, zf + sine [(i * 100) % 360] / 2);
1875       cola = sine [((i+1) * 100+missionmenutimer*4 / timestep) % 360] / 10 + sine [(i2 * 100) % 360] / 10 + 0.2;
1876       if (colorstd == &colorblue) glColor3f (0, 0, cola);
1877       else glColor3f (cola, 0, 0);
1878       glVertex3f (-3 + 0.5 * i2, -2.5 + 0.5 * i, zf + sine [((i+1) * 100) % 360] / 2);
1879     }
1880     glEnd ();
1881   }
1882 }
1883 
drawPlasma(CColor * colorstd)1884 void drawPlasma (CColor *colorstd)
1885 {
1886   int i;
1887   float yf;
1888   float zf1 = -2.98;
1889   float yind = 200.0 * sin (0.003 * missionmenutimer / timestep) + 200.0;
1890   float xind = 200.0 * cos (0.003 * missionmenutimer / timestep) + 200.0;
1891   float yind2 = -200.0 * sin (0.003 * missionmenutimer / timestep) + 200.0;
1892   float xind2 = -200.0 * cos (0.003 * missionmenutimer / timestep) + 200.0;
1893   for (i = 0; i < 21; i ++)
1894   {
1895     yf = -2.5 + 0.25 * i;
1896     float yif = yind + i * 5;
1897     int yi = (int) yif;
1898     float yr = yif - yi;
1899     float yif2 = yind2 + i * 5;
1900     int yi2 = (int) yif2;
1901     float yr2 = yif2 - yi2;
1902     glBegin (GL_QUAD_STRIP);
1903     for (int i2 = 0; i2 < 21; i2 ++)
1904     {
1905       float xf = -2.5 + 0.25 * i2;
1906       float xif = xind + i2 * 5;
1907       int xi = (int) xif;
1908       float xr = xif - xi;
1909       float xif2 = xind2 + i2 * 5;
1910       int xi2 = (int) xif2;
1911       float xr2 = xif2 - xi2;
1912       float h1 = xr * yr * l->h [yi + 1] [xi + 1] + (1.0 - xr) * (1.0 - yr) * l->h [yi] [xi] +
1913                  xr * (1.0 - yr) * l->h [yi] [xi + 1] + (1.0 - xr) * yr * l->h [yi + 1] [xi];
1914       float h2 = xr * yr * l->h [yi + 1 + 5] [xi + 1] + (1.0 - xr) * (1.0 - yr) * l->h [yi + 5] [xi] +
1915                  xr * (1.0 - yr) * l->h [yi + 5] [xi + 1] + (1.0 - xr) * yr * l->h [yi + 1 + 5] [xi];
1916       float h3 = xr2 * yr2 * l->h [yi2 + 1] [xi2 + 1] + (1.0 - xr2) * (1.0 - yr2) * l->h [yi2] [xi2] +
1917                  xr2 * (1.0 - yr2) * l->h [yi2] [xi2 + 1] + (1.0 - xr2) * yr2 * l->h [yi2 + 1] [xi2];
1918       float h4 = xr2 * yr2 * l->h [yi2 + 1 + 5] [xi2 + 1] + (1.0 - xr2) * (1.0 - yr2) * l->h [yi2 + 5] [xi2] +
1919                  xr2 * (1.0 - yr2) * l->h [yi2 + 5] [xi2 + 1] + (1.0 - xr2) * yr2 * l->h [yi2 + 1 + 5] [xi2];
1920       float intens = sin (0.15 * (h1 / 256 + 0.5 * missionmenutimer / timestep)) * 0.14 + 0.14;
1921       float intens2 = sin (0.15 * (h3 / 256 + 0.5 * missionmenutimer / timestep)) * 0.06 + 0.06;
1922       if (colorstd == &colorblue) glColor3f (intens2, 0, intens);
1923       else glColor3f (intens, 0, intens2);
1924       glVertex3f (xf, yf, zf1);
1925       intens = sin (0.15 * (h2 / 256 + 0.5 * missionmenutimer / timestep)) * 0.16 + 0.16;
1926       intens2 = sin (0.15 * (h4 / 256 + 0.5 * missionmenutimer / timestep)) * 0.08 + 0.08;
1927       if (colorstd == &colorblue) glColor3f (intens2, 0, intens);
1928       else glColor3f (intens, 0, intens2);
1929       glVertex3f (xf, yf + 0.25, zf1);
1930     }
1931     glEnd ();
1932   }
1933 }
1934 
menu_key(unsigned char key,int x,int y)1935 void menu_key (unsigned char key, int x, int y)
1936 {
1937   if (key == 27)
1938   {
1939     if (missionactive)
1940     {
1941       switch_game ();
1942     }
1943     else
1944     {
1945       switch_quit ();
1946     }
1947   }
1948 }
1949 
pleaseWait()1950 void pleaseWait ()
1951 {
1952   float xf = 1.0, yf = 0.2, zf = -2.5;
1953   int c1 = 100, c2 = 10, c3 = 180;
1954   glBegin (GL_QUADS);
1955   glColor4ub (c2, c2, c2, 255);
1956   glVertex3f (-xf, -yf, zf);
1957   glColor4ub (c1, c1, c1, 255);
1958   glVertex3f (xf, -yf, zf);
1959   glColor4ub (c2, c2, c2, 255);
1960   glVertex3f (xf, yf, zf);
1961   glColor4ub (c1, c1, c1, 255);
1962   glVertex3f (-xf, yf, zf);
1963   glEnd ();
1964   glLineWidth (LINEWIDTH(1));
1965   glBegin (GL_LINE_STRIP);
1966   glColor4ub (c3, c3, c3, 255);
1967   glVertex3f (-xf, -yf, zf);
1968   glVertex3f (xf, -yf, zf);
1969   glVertex3f (xf, yf, zf);
1970   glVertex3f (-xf, yf, zf);
1971   glVertex3f (-xf, -yf, zf);
1972   glEnd ();
1973 
1974   font1->drawTextCentered (0, -0.5, -1.5, "PLEASE WAIT...", &colorwhite);
1975   game_view ();
1976 }
1977 
stats_key(unsigned char key,int x,int y)1978 void stats_key (unsigned char key, int x, int y)
1979 {
1980   if (key == 27)
1981   {
1982     pleaseWait ();
1983     display ("Initing new mission", LOG_MOST);
1984     missionactive = false;
1985     createMission (MISSION_DEMO);
1986     game_levelInit ();
1987     sound->haltMusic ();
1988     switch_menu ();
1989   }
1990 }
1991 
credits_key(unsigned char key,int x,int y)1992 void credits_key (unsigned char key, int x, int y)
1993 {
1994   if (key)
1995   {
1996 //    sound->haltMusic ();
1997     switch_menu ();
1998   }
1999 }
2000 
finish_key(unsigned char key,int x,int y)2001 void finish_key (unsigned char key, int x, int y)
2002 {
2003   if (key)
2004   {
2005 //    sound->haltMusic ();
2006     switch_menu ();
2007   }
2008 }
2009 
mission_key(unsigned char key,int x,int y)2010 void mission_key (unsigned char key, int x, int y)
2011 {
2012   if (key == 27)
2013   {
2014     switch_menu ();
2015   }
2016   else if (key == 13)
2017   {
2018     pleaseWait ();
2019     if (!game_levelInit ())
2020     {
2021       switch_menu ();
2022       return;
2023     }
2024     switch_game ();
2025     missionactive = true;
2026   }
2027 }
2028 
fame_key(unsigned char key,int x,int y)2029 void fame_key (unsigned char key, int x, int y)
2030 {
2031   if (key == 27)
2032   {
2033     switch_menu ();
2034   }
2035 }
2036 
create_key(unsigned char key,int x,int y)2037 void create_key (unsigned char key, int x, int y)
2038 {
2039   if (key == 's')
2040   {
2041 //    server->sendMessage (0, "s", 1);
2042     if (server->checkStart())
2043     {
2044       printf ("Starting..");
2045       createMission (MISSION_MULTIPLAYER_DOGFIGHT);
2046       game_levelInit ();
2047       switch_game ();
2048       missionactive = true;
2049     }
2050   }
2051   if (key == 27)
2052   {
2053     switch_menu ();
2054   }
2055 }
2056 
join_key(unsigned char key,int x,int y)2057 void join_key (unsigned char key, int x, int y)
2058 {
2059   if (key == 's')
2060   {
2061     createMission (MISSION_MULTIPLAYER_DOGFIGHT);
2062     game_levelInit ();
2063     switch_game ();
2064     missionactive = true;
2065   }
2066   if (key == 27)
2067   {
2068     switch_menu ();
2069   }
2070 }
2071 
fighter_key(unsigned char key,int x,int y)2072 void fighter_key (unsigned char key, int x, int y)
2073 {
2074   if (key == 27)
2075   {
2076     switch_menu ();
2077   }
2078 }
2079 
getModelText(int id)2080 char *getModelText (int id)
2081 {
2082   if (id == FIGHTER_FALCON)
2083     return "THE FALCON IS A NIMBLE AND\nFAST FIGHTER PROVIDING\nBOTH AIR-AIR AND\nAIR-GROUND-MISSILES.";
2084   else if (id == FIGHTER_HAWK)
2085     return "THE HAWK IS A TYPICAL\nALLROUNDER AND DESIGNED\nFOR GROUND ATTACKS.";
2086   else if (id == FIGHTER_HAWK2)
2087     return "THE HAWK II IS A ...";
2088   return "NO INFO";
2089 }
2090 
getModelName(int id)2091 char *getModelName (int id)
2092 {
2093   if (id == FIGHTER_FALCON)
2094     return "GL-16 FALCON";
2095   else if (id == FIGHTER_HAWK)
2096     return "GL-22 HAWK";
2097   else if (id == FIGHTER_HAWK2)
2098     return "GL-23 HAWK II";
2099   else if (id == FIGHTER_REDARROW)
2100     return "GL-15 REDARROW";
2101   else if (id == FIGHTER_PHOENIX)
2102     return "GL-117 PHOENIX";
2103   else if (id == FIGHTER_STORM)
2104     return "GL-50 STORM";
2105   else if (id == FIGHTER_CROW)
2106     return "CROW";
2107   else if (id == FIGHTER_BUZZARD)
2108     return "BUZZARD";
2109   else if (id == FIGHTER_SWALLOW)
2110     return "SWALLOW";
2111   else if (id == FIGHTER_BLACKBIRD)
2112     return "BLACKBIRD";
2113   else if (id == MISSILE_AIR1)
2114     return "AIR-AIR MISSILE PACK";
2115   else if (id == MISSILE_GROUND1)
2116     return "AIR-GROUND MISSILE PACK";
2117   else if (id == MISSILE_DF1)
2118     return "DUMB FIRE MISSILE PACK";
2119   return "NO INFO";
2120 }
2121 
mission_mouse(int button,int state,int x,int y)2122 void mission_mouse (int button, int state, int x, int y)
2123 {
2124   float rx = (float) x / width;
2125   float ry = (float) y / height;
2126   missionmenuitemselected = -1;
2127 
2128   missionmenufighterselected = -1;
2129   if (ry >= 0.53 && ry <= 0.65)
2130   {
2131     if (rx >= 0.18 && rx < 0.28)
2132     {
2133       missionmenufighterselected = 0;
2134       if (state == MOUSE_DOWN)
2135         missionnew->wantfighter = 0;
2136     }
2137     if (rx >= 0.28 && rx < 0.38 && missionnew->selfighters >= 2)
2138     {
2139       missionmenufighterselected = 1;
2140       if (state == MOUSE_DOWN)
2141         missionnew->wantfighter = 1;
2142     }
2143     if (rx >= 0.38 && rx < 0.48 && missionnew->selfighters >= 3)
2144     {
2145       missionmenufighterselected = 2;
2146       if (state == MOUSE_DOWN)
2147         missionnew->wantfighter = 2;
2148     }
2149   }
2150 
2151   missionmenuweaponselected = -1;
2152   if (ry >= 0.53 && ry <= 0.65)
2153   {
2154     if (rx >= 0.54 && rx < 0.64)
2155     {
2156       missionmenuweaponselected = 0;
2157       if (state == MOUSE_DOWN)
2158         missionnew->wantweapon = 0;
2159     }
2160     if (rx >= 0.64 && rx < 0.74 && missionnew->selweapons >= 2)
2161     {
2162       missionmenuweaponselected = 1;
2163       if (state == MOUSE_DOWN)
2164         missionnew->wantweapon = 1;
2165     }
2166     if (rx >= 0.74 && rx < 0.84 && missionnew->selweapons >= 3)
2167     {
2168       missionmenuweaponselected = 2;
2169       if (state == MOUSE_DOWN)
2170         missionnew->wantweapon = 2;
2171     }
2172   }
2173 }
2174 
drawArrow(float x,float y,float w,float h)2175 void drawArrow (float x, float y, float w, float h)
2176 {
2177   float zf = -3;
2178   gl->enableTextures (texarrow->textureID);
2179   gl->enableAlphaBlending ();
2180   glBegin (GL_QUADS);
2181   glColor3ub (180, 180, 180);
2182 
2183   if (w > h)
2184   {
2185     glTexCoord2f (0, 1);
2186     glVertex3f (x, y, zf);
2187     glTexCoord2f (0, 0);
2188     glVertex3f (x + w, y, zf);
2189     glTexCoord2f (1, 0);
2190     glVertex3f (x + w, y + h, zf);
2191     glTexCoord2f (1, 1);
2192     glVertex3f (x, y + h, zf);
2193   }
2194   else
2195   {
2196     glTexCoord2f (1, 0);
2197     glVertex3f (x, y - h, zf);
2198     glTexCoord2f (1, 1);
2199     glVertex3f (x, y, zf);
2200     glTexCoord2f (0, 1);
2201     glVertex3f (x + w, y, zf);
2202     glTexCoord2f (0, 0);
2203     glVertex3f (x + w, y - h, zf);
2204   }
2205 
2206   glEnd ();
2207   glDisable (GL_BLEND);
2208   glDisable (GL_TEXTURE_2D);
2209 }
2210 
mission_display()2211 void mission_display ()
2212 {
2213   allmenus.setVisible (false);
2214   missionmenu.setVisible (true);
2215   missionmenu.draw ();
2216 
2217   char buf [256];
2218   int i;
2219   float piloty = 5;
2220   Pilot *p = pilots->pilot [pilots->aktpilot];
2221   CColor *colorstd = &colorred;
2222   if (p->mission_state [missionnew->id] == 1)
2223     colorstd = &colorblue;
2224   CColor *col = &menu_colwhite;
2225   Font *font2 = font1;
2226 
2227   CVector3 vec;
2228   CVector3 tl (-4.5, 5.5, -8.0);
2229   CRotation rot;
2230   rot.a = 270;
2231   rot.b = (270 - missionmenutimer * 4 / timestep) % 360;
2232   rot.c = 90;
2233 
2234   // Draw dummy missile
2235   glEnable (GL_LIGHTING);
2236   model_missile1.draw (&vec, &tl, &rot, 0.05, 1.0, 0);
2237   glDisable (GL_LIGHTING);
2238 
2239   glEnable (GL_LIGHTING);
2240   glEnable (GL_DEPTH_TEST);
2241 
2242   tl.x = -0.24; tl.y = -0.075; tl.z = -0.5;
2243   rot.a = 300;
2244   rot.b = 0;
2245   for (i = 0; i < missionnew->selfighters; i ++)
2246   {
2247     tl.x = -0.24 + (float) i * 0.085;
2248     if (missionnew->wantfighter == i)
2249       rot.c = (5 + missionmenutimer * 4 / timestep) % 360;
2250     else
2251       rot.c = 5;
2252     getModel (missionnew->selfighter [i])->draw (&vec, &tl, &rot, 0.04, 0.1, 0);
2253   }
2254 
2255   tl.x = 0; tl.y = -0.075; tl.z = -0.5;
2256   rot.a = 300;
2257   rot.b = 0;
2258   for (i = 0; i < missionnew->selweapons; i ++)
2259   {
2260     tl.x = 0.08 + (float) i * 0.07;
2261     if (missionnew->wantweapon == i)
2262       rot.c = (5 + missionmenutimer * 4 / timestep) % 360;
2263     else
2264       rot.c = 5;
2265     getModel (missionnew->selweapon [i])->draw (&vec, &tl, &rot, 0.04, 0.1, 0);
2266   }
2267   glDisable (GL_DEPTH_TEST);
2268   glDisable (GL_LIGHTING);
2269 
2270 
2271   float textx = -12, texty = 9.8;
2272   font1->zoom = 0.105;
2273   font2->zoom = 0.105;
2274   float fontscale = 1.05;
2275   font1->drawTextCentered (0, texty / fontscale, -2, missionnew->name, col);
2276   texty -= 1.1;
2277   font1->zoom = 0.05;
2278   font2->zoom = 0.05;
2279   fontscale = 0.5;
2280   font1->drawText (textx / fontscale, texty / fontscale, -2, "BRIEFING:", col);
2281   texty -= 1;
2282   font1->drawText (textx / fontscale, texty / fontscale, -2, missionnew->briefing, col);
2283 
2284   float xstats = 0.8, ystats = 5;
2285   float xstatstab = 5;
2286   font1->drawText (xstats / fontscale, ystats / fontscale, -2, "STATUS:", col);
2287   if (p->mission_state [missionnew->id] == 1)
2288     font1->drawText (xstatstab / fontscale, ystats / fontscale, -2, "SUCCESS", colorstd);
2289   else if (p->mission_state [missionnew->id] == 2)
2290     font1->drawText (xstatstab / fontscale, ystats / fontscale, -2, "FAILED", colorstd);
2291   else
2292     font1->drawText (xstatstab / fontscale, ystats / fontscale, -2, "EMPTY", colorstd);
2293   if (missionnew->id >= MISSION_CAMPAIGN1 && missionnew->id <= MISSION_CAMPAIGN2)
2294   {
2295     texty = ystats - 0.7;
2296     font1->drawText (xstats / fontscale, texty / fontscale, -2, "SCORE:", col);
2297     int score = p->mission_score [missionnew->id];
2298     if (score < -10000 || score > 100000) score = 0;
2299     sprintf (buf, "%d", score);
2300     font1->drawText (xstatstab / fontscale, texty / fontscale, -2, buf, colorstd);
2301     texty -= 0.7;
2302     font1->drawText (xstats / fontscale, texty / fontscale, -2, "KILLS:", col);
2303     sprintf (buf, "%d AIRCRAFTS", p->mission_fighterkills [missionnew->id]);
2304     font1->drawText (xstatstab / fontscale, texty / fontscale, -2, buf, colorstd);
2305 //    drawMedal (xstatstab + 2, ystats - 3, -2, getMedal (p->mission_score [missionnew->id]), 2, mission->id);
2306   }
2307   else
2308   {
2309     texty = ystats - 0.7;
2310     font1->drawText (xstats / fontscale, texty / fontscale, -2, "SCORE:", col);
2311     font1->drawText (xstatstab / fontscale, texty / fontscale, -2, "TRAINING", col);
2312   }
2313 
2314   font1->drawText (textx / fontscale, piloty / fontscale, -2, "PILOTS:", col);
2315   strcpy (buf, pilots->pilot [pilots->aktpilot]->getShortRank ());
2316   strcat (buf, " ");
2317   strcat (buf, pilots->pilot [pilots->aktpilot]->name);
2318   font2->drawText ((textx + 1.5) / fontscale, (piloty - 0.8) / fontscale, -2, buf, col);
2319   drawRank (textx, piloty - 0.8, -2, pilots->pilot [pilots->aktpilot]->ranking, 0.5);
2320   for (i = 1; i < missionnew->alliedfighters; i ++)
2321     if (missionnew->alliedpilot [i - 1] >= 0 && missionnew->alliedpilot [i - 1] < 100)
2322     {
2323       drawRank (textx, piloty - 1 - 0.6 * i, -2, pilots->pilot [pilots->aktpilot]->tp [missionnew->alliedpilot [i - 1]]->ranking, 0.5);
2324       font2->drawText ((textx + 1.5) / fontscale, (piloty - 1 - 0.6 * i) / fontscale, -2, pilots->pilot [pilots->aktpilot]->tp [missionnew->alliedpilot [i - 1]]->getShortName (), col);
2325     }
2326 
2327   font1->drawText (textx / fontscale, -1 / fontscale, -2, "CHOOSE FIGHTER:", col);
2328   font1->drawText (xstats / fontscale, -1 / fontscale, -2, "CHOOSE WEAPON PACK:", col);
2329   font2->drawText (textx / fontscale, -6 / fontscale, -2, getModelName (missionnew->selfighter [missionnew->wantfighter]), col);
2330   font2->drawText (xstats / fontscale, -6 / fontscale, -2, getModelName (missionnew->selweapon [missionnew->wantweapon]), col);
2331   font1->zoom = 0.1;
2332   font2->zoom = 0.1;
2333 
2334   drawMouseCursor ();
2335 }
2336 
fame_mouse(int button,int state,int x,int y)2337 void fame_mouse (int button, int state, int x, int y)
2338 {
2339   missionmenuitemselected = -1;
2340 }
2341 
create_mouse(int button,int state,int x,int y)2342 void create_mouse (int button, int state, int x, int y)
2343 {
2344   float rx = (float) x / width;
2345   float ry = (float) y / height;
2346   missionmenuitemselected = -1;
2347 
2348   if (ry >= 0.8 && ry <= 0.9)
2349   {
2350     if (rx >= 0.4 && rx <= 0.6)
2351     {
2352       missionmenuitemselected = 0;
2353       if (state == MOUSE_DOWN)
2354       {
2355         create_key (27, 0, 0);
2356       }
2357     }
2358   }
2359 }
2360 
create_display()2361 void create_display ()
2362 {
2363   CColor *colorstd = &colorblue;
2364 
2365   glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2366   glMatrixMode (GL_MODELVIEW);
2367   glLoadIdentity ();
2368   glPushMatrix ();
2369 
2370   drawQuads (colorstd);
2371 
2372 #ifdef HAVE_SDL_NET
2373   float my = 0;
2374   int i;
2375   for (i = 0; i < server->num_clients; i ++)
2376   {
2377     font1->drawTextCentered (0, my, -2.5, server->clients [i].name);
2378     my -= 2;
2379   }
2380 #endif
2381 
2382   font1->drawTextCentered (0, 9, -1.5, "CREATE GAME");
2383 
2384   if (missionmenuitemselected == 0)
2385     font1->drawTextScaled (-2, -12, -2, "BACK", colorstd, -missionmenutimer * 5);
2386   else
2387     font1->drawText (-2, -12, -2, "BACK");
2388 
2389   glPopMatrix ();
2390 
2391   adjustBrightness ();
2392 
2393   drawMouseCursor ();
2394 }
2395 
join_mouse(int button,int state,int x,int y)2396 void join_mouse (int button, int state, int x, int y)
2397 {
2398   float rx = (float) x / width;
2399   float ry = (float) y / height;
2400   missionmenuitemselected = -1;
2401 
2402   if (ry >= 0.8 && ry <= 0.9)
2403   {
2404     if (rx >= 0.4 && rx <= 0.6)
2405     {
2406       missionmenuitemselected = 0;
2407       if (state == MOUSE_DOWN)
2408       {
2409         create_key (27, 0, 0);
2410       }
2411     }
2412   }
2413 }
2414 
join_display()2415 void join_display ()
2416 {
2417   CColor *colorstd = &colorblue;
2418 
2419   glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2420   glMatrixMode (GL_MODELVIEW);
2421   glLoadIdentity ();
2422   glPushMatrix ();
2423 
2424   drawQuads (colorstd);
2425 
2426   font1->drawTextCentered (0, 9, -1.5, "JOIN GAME");
2427 
2428   if (missionmenuitemselected == 0)
2429     font1->drawTextScaled (-2, -12, -2, "BACK", colorstd, -missionmenutimer * 5);
2430   else
2431     font1->drawText (-2, -12, -2, "BACK");
2432 
2433   glPopMatrix ();
2434 
2435   adjustBrightness ();
2436 
2437   drawMouseCursor ();
2438 }
2439 
2440 int aktfighter = 0;
2441 
fighter_mouse(int button,int state,int x,int y)2442 void fighter_mouse (int button, int state, int x, int y)
2443 {
2444 }
2445 
fighter_display()2446 void fighter_display ()
2447 {
2448   allmenus.setVisible (false);
2449   fightermenu.setVisible (true);
2450   fightermenu.draw ();
2451   AIObj ffighter;
2452 
2453   char buf [256];
2454   int i;
2455 
2456   CVector3 vec;
2457   CVector3 tl;
2458   tl.y = -0.04;
2459   tl.z = -0.4;
2460   CRotation rot;
2461   rot.a = 300;
2462   rot.b = 0;
2463   rot.c = (5 + missionmenutimer * 4 / timestep) % 360;
2464   CModel *model = NULL;
2465   int id = 0;
2466   if (aktfighter == 0) { model = &model_fig; id = FIGHTER_FALCON; }
2467   else if (aktfighter == 1) { model = &model_fige; id = FIGHTER_CROW; }
2468   else if (aktfighter == 2) { model = &model_figb; id = FIGHTER_HAWK; }
2469   else if (aktfighter == 3) { model = &model_figi; id = FIGHTER_STORM; }
2470   else if (aktfighter == 4) { model = &model_figa; id = FIGHTER_SWALLOW; }
2471   else if (aktfighter == 5) { model = &model_figd; id = FIGHTER_BUZZARD; }
2472   else if (aktfighter == 6) { model = &model_figc; id = FIGHTER_HAWK2; }
2473   else if (aktfighter == 7) { model = &model_figg; id = FIGHTER_REDARROW; }
2474   else if (aktfighter == 8) { model = &model_figf; id = FIGHTER_PHOENIX; }
2475   else if (aktfighter == 9) { model = &model_figh; id = FIGHTER_BLACKBIRD; }
2476 
2477   glEnable (GL_DEPTH_TEST);
2478   glEnable (GL_LIGHTING);
2479   model->draw (&vec, &tl, &rot, 0.11, 0.5, 0);
2480   glDisable (GL_LIGHTING);
2481   glDisable (GL_DEPTH_TEST);
2482 
2483   ffighter.o = model;
2484   ffighter.newinit (id, 1, 0);
2485 
2486   float fontzoom = 0.7;
2487   float textx = -9.5;
2488   font1->zoom = 0.07;
2489   font1->drawText (textx / fontzoom, 9.7 / fontzoom, -2, getModelName (id), &menu_colwhite);
2490   float yf = 9.6 - 1.35;
2491   strcpy (buf, "TYPE: ");
2492   if (ffighter.id == FIGHTER_FALCON || ffighter.id == FIGHTER_CROW || ffighter.id == FIGHTER_BUZZARD || ffighter.id == FIGHTER_REDARROW || ffighter.id == FIGHTER_BLACKBIRD)
2493     strcat (buf, "FIGHTER");
2494   else if (ffighter.id == FIGHTER_HAWK || ffighter.id == FIGHTER_HAWK2)
2495     strcat (buf, "FIGHTER-BOMBER");
2496   else
2497     strcat (buf, "BOMBER");
2498   font1->drawText (textx / fontzoom, yf / fontzoom, -2, buf, &menu_colwhite);
2499   yf -= 1;
2500   strcpy (buf, "SPEED: ");
2501   int stars = (int) ((ffighter.maxthrust - 0.2) * 40);
2502   font1->drawText (textx / fontzoom, yf / fontzoom, -2, buf, &menu_colwhite);
2503   for (i = 0; i < stars; i ++)
2504     drawMedal (4 + i * 1.1, yf + 0.7, -2, 0, 1, MISSION_CAMPAIGN1);
2505   yf -= 1;
2506   strcpy (buf, "NIMBILITY: ");
2507   stars = (int) ((ffighter.manoeverability - 0.3) * 20 + 1);
2508   font1->drawText (textx / fontzoom, yf / fontzoom, -2, buf, &menu_colwhite);
2509   for (i = 0; i < stars; i ++)
2510     drawMedal (4 + i * 1.1, yf + 0.7, -2, 0, 1, MISSION_CAMPAIGN1);
2511   yf -= 1;
2512   strcpy (buf, "SHIELD: ");
2513   stars = (int) ((ffighter.maxshield - 30) / 30);
2514   font1->drawText (textx / fontzoom, yf / fontzoom, -2, buf, &menu_colwhite);
2515   for (i = 0; i < stars; i ++)
2516     drawMedal (4 + i * 1.1, yf + 0.7, -2, 0, 1, MISSION_CAMPAIGN1);
2517   yf -= 1;
2518   strcpy (buf, "FIREPOWER: ");
2519   stars = ffighter.statfirepower;
2520   font1->drawText (textx / fontzoom, yf / fontzoom, -2, buf, &menu_colwhite);
2521   for (i = 0; i < stars; i ++)
2522     drawMedal (4 + i * 1.1, yf + 0.7, -2, 0, 1, MISSION_CAMPAIGN1);
2523   font1->zoom = 0.1;
2524 
2525   drawMouseCursor ();
2526 }
2527 
fame_display()2528 void fame_display ()
2529 {
2530   allmenus.setVisible (false);
2531   famemenu.setVisible (true);
2532   famemenu.draw ();
2533 
2534   char buf [256];
2535   int i, i2;
2536   Pilot *p = pilots->pilot [pilots->aktpilot];
2537 
2538   float textx = -10;
2539   int sum = 0;
2540   for (i = MISSION_CAMPAIGN1; i < MISSION_CAMPAIGN2; i ++)
2541     sum += p->mission_fighterkills [i];
2542   p->tp [10]->fighterkills = sum;
2543   strcpy (p->tp [10]->name, p->name);
2544   p->tp [10]->ranking = p->ranking;
2545   int index [11];
2546   for (i = 0; i < 11; i ++)
2547     index [i] = i;
2548   for (i = 0; i < 11; i ++)
2549     for (i2 = 0; i2 < i; i2 ++)
2550     {
2551       if (p->tp [index [i]]->fighterkills < p->tp [index [i2]]->fighterkills)
2552       {
2553         int temp = index [i];
2554         index [i] = index [i2];
2555         index [i2] = temp;
2556       }
2557     }
2558 
2559   for (i = 0; i < 11; i ++)
2560   {
2561     font1->zoom = 0.07;
2562     drawRank (textx + 0.2, i - 3.7, -2, p->tp [index [i]]->ranking, 0.7);
2563     sprintf (buf, "%s %s", p->tp [index [i]]->getRank (), p->tp [index [i]]->name);
2564     font1->drawText ((textx + 2) / 0.7, (i - 3.7) / 0.7, -2, buf, &menu_colwhite);
2565     sprintf (buf, "%d", p->tp [index [i]]->fighterkills);
2566     font1->drawText ((textx + 18) / 0.7, (i - 3.7) / 0.7, -2, buf, &menu_colwhite);
2567     font1->zoom = 0.1;
2568   }
2569 
2570   drawMouseCursor ();
2571 }
2572 
2573 CModel *explsphere;
2574 CSphere *mysphere;
2575 
game_quit()2576 void game_quit ()
2577 {
2578   int i;
2579   volumesound = sound->volumesound;
2580   volumemusic = sound->volumemusic;
2581   save_config ();
2582   save_configInterface ();
2583   pilots->save (dirs->getSaves ("pilots"));
2584   display ("Pilots saved", LOG_MOST);
2585   for (i = 0; i < maxlaser; i ++)
2586     delete (laser [i]);
2587   for (i = 0; i < maxmissile; i ++)
2588     delete (missile [i]);
2589   for (i = 0; i < maxflare; i ++)
2590     delete (flare [i]);
2591   for (i = 0; i < maxchaff; i ++)
2592     delete (chaff [i]);
2593   for (i = 0; i < maxexplosion; i ++)
2594     delete (explosion [i]);
2595   for (i = 0; i < maxstar; i ++)
2596     delete (star [i]);
2597   for (i = 0; i < maxgroundobj; i ++)
2598     delete (groundobj [i]);
2599   for (i = 0; i < maxblacksmoke; i ++)
2600     delete (blacksmoke [i]);
2601   delete pilots;
2602   delete tlinf;
2603   delete tlminf;
2604   delete tlnull;
2605   delete explsphere;
2606   delete objsphere;
2607   delete sphere;
2608   delete flash1;
2609   delete cockpit;
2610   delete font1;
2611   delete font2;
2612   delete space;
2613   delete dirs;
2614   delete gl;
2615 #ifndef USE_GLUT
2616 //  SDL_CloseAudio();
2617 //  SDL_FreeWAV(wave.sound);
2618 //  SDL_Quit (); // done atexit()
2619   delete sound;
2620 #endif
2621   exit (EXIT_NORMAL);
2622 }
2623 
quit_key(unsigned char key,int x,int y)2624 void quit_key (unsigned char key, int x, int y)
2625 {
2626   if (key == 'y' || key == 'Y')
2627     game_quit ();
2628   else
2629     switch_menu ();
2630 }
2631 
quit_mouse(int button,int state,int x,int y)2632 void quit_mouse (int button, int state, int x, int y)
2633 {
2634   float rx = (float) x / width;
2635   float ry = (float) y / height;
2636   missionmenuitemselected = -1;
2637 
2638   if (ry >= 0.5 && ry <= 0.55)
2639   {
2640     if (rx >= 0.35 && rx <= 0.45)
2641     {
2642       missionmenuitemselected = 0;
2643       if (state == MOUSE_DOWN)
2644       {
2645         quit_key ('y', 0, 0);
2646       }
2647     }
2648     if (rx >= 0.55 && rx <= 0.65)
2649     {
2650       missionmenuitemselected = 1;
2651       if (state == MOUSE_DOWN)
2652       {
2653         quit_key (27, 0, 0);
2654       }
2655     }
2656   }
2657 }
2658 
menu_mouse(int button,int state,int x,int y)2659 void menu_mouse (int button, int state, int x, int y)
2660 {
2661 }
2662 
stats_mouse(int button,int state,int x,int y)2663 void stats_mouse (int button, int state, int x, int y)
2664 {
2665 }
2666 
2667 
2668 
2669 /****************************************************************************
2670   DISPLAY EVENTS
2671 ****************************************************************************/
2672 
drawMissionElement(float x,float y,float z,int thismissionid,int missionid,int selected,char * string)2673 void drawMissionElement (float x, float y, float z, int thismissionid, int missionid, int selected, char *string)
2674 {
2675   Pilot *p = pilots->pilot [pilots->aktpilot];
2676   drawMedal (x - 0.8, y + 0.6, z, getMedal (p->mission_score [thismissionid]), 1.0, thismissionid);
2677 }
2678 
stats_display()2679 void stats_display ()
2680 {
2681   allmenus.setVisible (false);
2682   statsmenu.setVisible (true);
2683   statsmenu.draw ();
2684 
2685   float yf = 1.4, zf = -2.5;
2686 
2687   drawMedal (-5.5, 5.8, -1.5, getMedal (fplayer->score), 1.6, mission->id);
2688   drawMedal (5.5, 5.8, -1.5, getMedal (fplayer->score), 1.6, mission->id);
2689 
2690   char buf [100];
2691   float xf1 = -12, xf2 = 0, xf3 = 8;
2692   float linedist = 1.3, linedist2 = 1.1;
2693   yf = 6.5; zf = -2.5;
2694   CColor *color;
2695   Pilot *p = pilots->pilot [pilots->aktpilot];
2696 
2697   color = &menu_colwhite;
2698   if (missionstate == 1)
2699   {
2700     font1->drawTextCentered (0, 7, -2, "SUCCESS", &colorblue);
2701   }
2702   else
2703   {
2704     font1->drawTextCentered (0, 7, -2, "FAILED", &colorred);
2705   }
2706 
2707   font1->drawText (xf1, yf, zf, "SCORE:", color);
2708   sprintf (buf, "%d", fplayer->score);
2709   font1->drawText (xf3, yf, zf, buf, color);
2710   yf -= linedist * 1.2;
2711 
2712   font1->drawText (xf1, yf, zf, "DIFFICULTY:", color);
2713   if (mission->difficulty == 0) font1->drawText (xf2, yf, zf, "EASY", color);
2714   else if (mission->difficulty == 1) font1->drawText (xf2, yf, zf, "NORMAL", color);
2715   else if (mission->difficulty == 2) font1->drawText (xf2, yf, zf, "HARD", color);
2716   if (mission->difficulty == 0) font1->drawText (xf3, yf, zf, "-25", color);
2717   else if (mission->difficulty == 1) font1->drawText (xf3, yf, zf, "+25", color);
2718   else if (mission->difficulty == 2) font1->drawText (xf3, yf, zf, "+75", color);
2719   yf -= linedist;
2720 
2721   font1->drawText (xf1, yf, zf, "FLIGHT MODEL:", color);
2722   if (!fplayer->realism) font1->drawText (xf2, yf, zf, "ACTION", color);
2723   else font1->drawText (xf2, yf, zf, "SIM", color);
2724   if (!fplayer->realism) font1->drawText (xf3, yf, zf, "-25", color);
2725   else font1->drawText (xf3, yf, zf, "+25", color);
2726 
2727   int timebonus = 0;
2728   if (mission->timer < mission->maxtime)
2729     timebonus = (mission->maxtime - mission->timer) * 100 / mission->maxtime;
2730   yf -= linedist;
2731   font1->drawText (xf1, yf, zf, "TIME BONUS:", color);
2732   sprintf (buf, "%d%%", timebonus);
2733   font1->drawText (xf2, yf, zf, buf, color);
2734   sprintf (buf, "+%d", timebonus);
2735   font1->drawText (xf3, yf, zf, buf, color);
2736   int shieldbonus = (int) (fplayer->shield * 100 / fplayer->maxshield);
2737   yf -= linedist;
2738   font1->drawText (xf1, yf, zf, "SHIELD BONUS:", color);
2739   sprintf (buf, "%d%%", shieldbonus);
2740   font1->drawText (xf2, yf, zf, buf, color);
2741   sprintf (buf, "+%d", shieldbonus);
2742   font1->drawText (xf3, yf, zf, buf, color);
2743   yf -= linedist;
2744   font1->drawText (xf1, yf, zf, "KILLS:", color);
2745   if (fplayer->fighterkills > 0)
2746   {
2747     sprintf (buf, "%d AIR", fplayer->fighterkills);
2748     font1->drawText (xf2, yf, zf, buf, color);
2749     sprintf (buf, "+%d", fplayer->fighterkills * 20);
2750     font1->drawText (xf3, yf, zf, buf, color);
2751     yf -= linedist2;
2752   }
2753   if (fplayer->tankkills > 0)
2754   {
2755     sprintf (buf, "%d TANKS", fplayer->tankkills);
2756     font1->drawText (xf2, yf, zf, buf, color);
2757     sprintf (buf, "+%d", fplayer->tankkills * 10);
2758     font1->drawText (xf3, yf, zf, buf, color);
2759     yf -= linedist2;
2760   }
2761   if (fplayer->shipkills > 0)
2762   {
2763     sprintf (buf, "%d SHIPS", fplayer->shipkills);
2764     font1->drawText (xf2, yf, zf, buf, color);
2765     sprintf (buf, "+%d", fplayer->shipkills * 12);
2766     font1->drawText (xf3, yf, zf, buf, color);
2767     yf -= linedist2;
2768   }
2769   if (fplayer->otherkills > 0)
2770   {
2771     sprintf (buf, "%d OTHERS", fplayer->otherkills);
2772     font1->drawText (xf2, yf, zf, buf, color);
2773     sprintf (buf, "+%d", fplayer->otherkills * 5);
2774     font1->drawText (xf3, yf, zf, buf, color);
2775     yf -= linedist2;
2776   }
2777   yf -= (linedist - linedist2);
2778 
2779   if (ispromoted)
2780   {
2781     yf = -6;
2782     font1->drawTextCentered (0, yf, zf, "PROMOTED TO", color);
2783     yf -= 1.5;
2784     sprintf (buf, "%s", p->getRank ());
2785     font1->drawTextCentered (0, yf, zf, buf, color);
2786     drawRank (-11, yf + 0.2, zf, pilots->pilot [pilots->aktpilot]->ranking, 2);
2787     drawRank (7, yf + 0.2, zf, pilots->pilot [pilots->aktpilot]->ranking, 2);
2788   }
2789   yf = -9;
2790 
2791   drawMouseCursor ();
2792 }
2793 
test()2794 void test ()
2795 {
2796   view ++;
2797   if (view > VIEW_MAX) view = VIEW_MIN;
2798 }
2799 
menu_display()2800 void menu_display ()
2801 {
2802   int i;
2803 
2804   glInitNames ();
2805   glPushName (0);
2806 
2807   glMatrixMode (GL_MODELVIEW);
2808   glLoadIdentity ();
2809 
2810   int menutimernorm = menutimer * 5 / timestep;
2811   if (menutimernorm != 0) menutimernorm %= 360;
2812   if (menutimernorm < 0) menutimernorm *= -1;
2813   CColor color2 (255, 255, (int) (255.0 * cosi [menutimernorm]), 255);
2814 
2815   Pilot *p = pilots->pilot [pilots->aktpilot];
2816 
2817   if (allmenus.components [3]->isVisible ())
2818   {
2819     ((Container *) allmenus.components [3])->components [0]->setVisible (true);
2820     for (i = 1; i < 25; i ++)
2821     {
2822       if (p->mission_state [getCampaignIdFromValue (i - 1)] == 1)
2823         ((Container *) allmenus.components [3])->components [i]->setVisible (true);
2824       else
2825         ((Container *) allmenus.components [3])->components [i]->setVisible (false);
2826     }
2827   }
2828 
2829   allmenus.draw ();
2830 
2831   if (allmenus.components [1]->isVisible ())
2832   {
2833     float textx2 = -0.7, yf = 10.15, zf = -2, ydiff = 1;
2834     drawRank (textx2, yf, zf, pilots->pilot [pilots->aktpilot]->ranking, 0.8);
2835     yf -= 2;
2836     for (i = 0; i < pilots->aktpilots; i ++)
2837     {
2838       drawRank (textx2, yf, zf, pilots->pilot [i]->ranking, 0.8);
2839       yf -= ydiff;
2840     }
2841   }
2842 
2843   if (allmenus.components [3]->isVisible ())
2844   {
2845     float textx2 = 11, yf = 9.05, zf = -2, ydiff = 0.8;
2846     for (i = 0; i < 24; i ++)
2847     {
2848       drawMedal (textx2 - 0.8, yf + 0.6, zf, getMedal (p->mission_score [getCampaignIdFromValue (i)]), 0.8, getCampaignIdFromValue (i));
2849       yf -= ydiff;
2850     }
2851   }
2852 
2853   drawMouseCursor ();
2854 }
2855 
selectMouse(int x,int y,int motionx,int motiony,int mode,bool shift)2856 int selectMouse (int x, int y, int motionx, int motiony, int mode, bool shift)
2857 {
2858 //  glutSwapBuffers ();
2859 	GLuint selectBuff [20 * 4];
2860 	GLint hits, viewport [4];
2861 
2862 	// Select buffer parameters
2863 	glSelectBuffer (20 * 4, selectBuff);
2864 	glGetIntegerv (GL_VIEWPORT, viewport);
2865 
2866 	// Enter to selection mode
2867 	glEnable (GL_DEPTH_TEST);
2868 	glDisable (GL_LIGHTING);
2869 	glMatrixMode (GL_PROJECTION);
2870 	glPushMatrix ();
2871 	glLoadIdentity ();
2872 
2873 	// Set-up pick matrix
2874   gluPickMatrix (x, viewport [3] - y, 5, 5, viewport);
2875 
2876 	// Set our perpective transformation matrix
2877   gluPerspective (visibleangle, 1.0, nearclippingplane * GLOBALSCALE, view * GLOBALSCALE);
2878 //  gluPerspective (60.0, 1.0, 0.2, 200.0);
2879 
2880 	glMatrixMode (GL_MODELVIEW);
2881 
2882 	// Render all scene and fill selection buffer
2883 	glRenderMode (GL_SELECT);
2884   menu_display ();
2885 
2886 	// Get hits and go back to normal rendering
2887 	hits = glRenderMode (GL_RENDER);
2888 
2889 	// Get first model in selection buffer stack
2890   GLuint *ptr = selectBuff;
2891   int mypicks = 0;
2892   int pickz2 = -1;
2893   int pick [100];
2894 	if (hits > 0)
2895   {
2896     int i;
2897     GLuint z = 0xFFFFFFFF;
2898     for (i = 0; i < hits; i ++)
2899     {
2900       int names = *ptr;
2901       ptr ++;
2902       GLuint z1 = *ptr;
2903       ptr ++;
2904       ptr ++;
2905       if (motionx < 0 && motiony < 0)
2906       {
2907         if (z1 < z)
2908         {
2909           z = z1; pickz2 = *ptr; mypicks = 1;
2910         }
2911       }
2912       else
2913       {
2914         pick [mypicks] = *ptr; mypicks ++;
2915       }
2916       ptr += names;
2917       if (mypicks >= 20) break;
2918     }
2919   }
2920 
2921 	glMatrixMode (GL_PROJECTION);
2922 
2923 	glPopMatrix ();
2924 	glMatrixMode (GL_MODELVIEW);
2925 
2926   char buf [STDSIZE];
2927   sprintf (buf, "selectMouse: picks=%d, pickz=%d, shift=%d", mypicks, pickz2, shift);
2928   display (buf, LOG_ALL);
2929   return pickz2;
2930 }
2931 
pause_display()2932 void pause_display ()
2933 {
2934   glMatrixMode (GL_MODELVIEW);
2935   glLoadIdentity ();
2936   glPushMatrix ();
2937 
2938   font1->drawText (-3, -1, -1, "PAUSED", &colorwhite);
2939 
2940   glPopMatrix ();
2941 }
2942 
credits_mouse(int button,int state,int x,int y)2943 void credits_mouse (int button, int state, int x, int y)
2944 {
2945   switch_menu ();
2946 }
2947 
credits_display()2948 void credits_display ()
2949 {
2950 #ifdef SHOW_SOFTWARE_PATENTS
2951   float xt = -22, yt = 12, zf = -2.4, ydist = 0.7;
2952   glPushMatrix ();
2953 //  glTranslatef (0, -3.5 + 0.014 * (float) creditstimer / timestep, 0);
2954   glTranslatef (0, -3.4 + 0.004 * (float) creditstimer / timestep, 0);
2955   CColor *col = &colorwhite;
2956   CColor *col2 = &coloryellow;
2957   float fontzoom = 1.0;
2958   font1->zoom = 0.1;
2959   font2->zoom = 0.1;
2960   font1->drawTextCentered (0, (yt -= 2 * ydist) / fontzoom, zf, "MONEY VERSUS DEMOCRACY", col2);
2961   font1->drawTextCentered (0, (yt -= 3 * ydist) / fontzoom, zf, "PATENTS ON SOFTWARE", col2);
2962   fontzoom = 0.8;
2963   font1->zoom = 0.08;
2964   font2->zoom = 0.08;
2965 
2966   font1->drawText (xt, (yt -= 5 * ydist) / fontzoom, zf, "WHAT ARE PATENTS?", col2);
2967   font2->drawText (xt, (yt -= 2 * ydist) / fontzoom, zf, "PATENTS IN EUROPE COST ABOUT 30000-50000 EURO (= US$).", col);
2968   font2->drawText (xt, (yt -= 1.5 * ydist) / fontzoom, zf, "THEY GRANT PROPERTY FOR SOMETHING, THAT NOONE CAN PUBLISH", col);
2969   font2->drawText (xt, (yt -= 1.5 * ydist) / fontzoom, zf, "EXCEPT THE PATENT OWNER.", col);
2970 
2971   font1->drawText (xt, (yt -= 4 * ydist) / fontzoom, zf, "WHO CAN AFFORD PATENTS?", col2);
2972   font2->drawText (xt, (yt -= 2 * ydist) / fontzoom, zf, "ONLY HUGE COMPANIES.", col);
2973 
2974   font1->drawText (xt, (yt -= 4 * ydist) / fontzoom, zf, "WHAT CAN BE PATENTED?", col2);
2975   font2->drawText (xt, (yt -= 2 * ydist) / fontzoom, zf, "CURRENTLY EVERYTHING. AMAZON HAS A PATENT TO SELL PRODUCTS", col);
2976   font2->drawText (xt, (yt -= 1.5 * ydist) / fontzoom, zf, "WITH ONE MOUSE CLICK. THERE ARE EUROPEAN PATENTS ON THE", col);
2977   font2->drawText (xt, (yt -= 1.5 * ydist) / fontzoom, zf, "PROGRESS BAR, ON THE UNDO FUNCTION, ETC.", col);
2978   font2->drawText (xt, (yt -= 1.5 * ydist) / fontzoom, zf, "CURRENTLY EURO SOFTWARE PATENTS ARE STOPPED UNTIL THE END", col);
2979   font2->drawText (xt, (yt -= 1.5 * ydist) / fontzoom, zf, "OF SUMMER 2004.", col);
2980 
2981   font1->drawText (xt, (yt -= 4 * ydist) / fontzoom, zf, "AN EXAMPLE FOR PATENTS ON COURT?", col2);
2982   font2->drawText (xt, (yt -= 2 * ydist) / fontzoom, zf, "IN 2001 MICROSOFT HAD TO PAY 500000000 US$, BECAUSE ANOTHER", col);
2983   font2->drawText (xt, (yt -= 1.5 * ydist) / fontzoom, zf, "COMPANY HAD A PATENT ON BROWSER PLUGINS (US).", col);
2984 
2985   font1->drawText (xt, (yt -= 4 * ydist) / fontzoom, zf, "WHAT IS SOFTWARE?", col2);
2986   font2->drawText (xt, (yt -= 2 * ydist) / fontzoom, zf, "SOFTWARE IS BASED ON ABSTRACT DESCRIPTIONS, WHICH EVERYONE", col);
2987   font2->drawText (xt, (yt -= 1.5 * ydist) / fontzoom, zf, "CAN FORMULATE IN PROSE LANGUAGE. CODE IS JUST A MIRROR", col);
2988   font2->drawText (xt, (yt -= 1.5 * ydist) / fontzoom, zf, "IMAGE OF THE DESCRIPTION.", col);
2989 
2990   font1->drawText (xt, (yt -= 4 * ydist) / fontzoom, zf, "WHY DOES MICROSOFT WANT PATENTS?", col2);
2991   font2->drawText (xt, (yt -= 2 * ydist) / fontzoom, zf, "TO PATENT CONCEPTS, AND DICTATE WHICH SYSTEMS MAY USE THEM.", col);
2992   font2->drawText (xt, (yt -= 1.5 * ydist) / fontzoom, zf, "EVENTUALLY TO ELIMINATE LINUX AND OPEN SOURCE.", col);
2993 
2994   font1->drawText (xt, (yt -= 4 * ydist) / fontzoom, zf, "WHY CAN EVERYTHING BE PATENTED?", col2);
2995   font2->drawText (xt, (yt -= 2 * ydist) / fontzoom, zf, "HUGE COMPANIES ARE PUSHING FOR EXECUTIVE POWERS.", col);
2996   font2->drawText (xt, (yt -= 1.5 * ydist) / fontzoom, zf, "PATENT LAWYERS ARE TAKING THE MONEY.", col);
2997 
2998   font1->drawText (xt, (yt -= 4 * ydist) / fontzoom, zf, "WHAT IS DEMOCRACY?", col2);
2999   font2->drawText (xt, (yt -= 2 * ydist) / fontzoom, zf, "YOUR POWER TO STOP THIS ABUSE.", col);
3000   font2->drawText (xt, (yt -= 1.5 * ydist) / fontzoom, zf, "VOTE AGAINST SOFTWARE PATENTS ON HTTP://PETITION.EUROLINUX.ORG.", col);
3001   font2->drawText (xt, (yt -= 1.5 * ydist) / fontzoom, zf, "TELL YOUR FRIENDS AND SEARCH THE INTERNET FOR MORE INSANITY.", col);
3002 #else
3003   float yt = 12, zf = -2.4, ydist = 0.7;
3004   glPushMatrix ();
3005   glTranslatef (0, -3.5 + 0.014 * (float) creditstimer / timestep, 0);
3006   CColor *col = &colorwhite;
3007   CColor *col2 = &coloryellow;
3008   float fontzoom = 1;
3009   font2->drawTextCentered (0, (yt -= 2 * ydist) / fontzoom, zf, "GAME PROGRAMMING,", col);
3010   font2->drawTextCentered (0, (yt -= 2 * ydist) / fontzoom, zf, "GRAPHICS, MODELS, SOUND & MUSIC", col);
3011   font1->drawTextCentered (0, (yt -= 2 * ydist) / fontzoom, zf, "THOMAS A. DREXL", col2);
3012   font1->zoom = 0.08;
3013   font2->zoom = 0.08;
3014   fontzoom = 0.8;
3015   font2->drawTextCentered (0, (yt -= 4 * ydist) / fontzoom, zf, "SPECIAL THANKS TO...", col);
3016   font2->drawTextCentered (0, (yt -= 4 * ydist) / fontzoom, zf, "LENS FLARES & FURTHER DEBUGGING", col);
3017   font1->drawTextCentered (0, (yt -= 2 * ydist) / fontzoom, zf, "PIOTR PAWLOW", col2);
3018   font2->drawTextCentered (0, (yt -= 4 * ydist) / fontzoom, zf, "MOUSE INTERFACE & LANDSCAPE IMPROVEMENTS", col);
3019   font1->drawTextCentered (0, (yt -= 2 * ydist) / fontzoom, zf, "LOURENS VEEN", col2);
3020   font2->drawTextCentered (0, (yt -= 4 * ydist) / fontzoom, zf, "PUBLISHING & FURTHER GAME IDEAS", col);
3021   font1->drawTextCentered (0, (yt -= 2 * ydist) / fontzoom, zf, "BERNHARD KAINDL", col2);
3022   font2->drawTextCentered (0, (yt -= 4 * ydist) / fontzoom, zf, "MOON TERRAIN", col);
3023   font1->drawTextCentered (0, (yt -= 2 * ydist) / fontzoom, zf, "NORBERT DREXL", col2);
3024   font2->drawTextCentered (0, (yt -= 4 * ydist) / fontzoom, zf, "PHYSICAL MODEL (ACTION) & COCKPIT IMPROVEMENTS", col);
3025   font1->drawTextCentered (0, (yt -= 2 * ydist) / fontzoom, zf, "ARNE REINERS", col2);
3026   font2->drawTextCentered (0, (yt -= 4 * ydist) / fontzoom, zf, "...AND THANKS TO ALL PEOPLE GIVING FEEDBACK AND ADVICE", col);
3027   float xf = -10;
3028   font1->zoom = 0.1;
3029   font2->zoom = 0.1;
3030   fontzoom = 1;
3031   font1->drawTextCentered (0, (yt -= 10 * ydist) / fontzoom, zf, "***********************", col);
3032   font1->drawTextCentered (0, (yt -= 10 * ydist) / fontzoom, zf, "DO YOU WANT TO CONTRIBUTE?", col);
3033   font1->zoom = 0.08;
3034   font2->zoom = 0.08;
3035   fontzoom = 0.8;
3036   font2->drawText (xf / fontzoom, (yt -= 4 * ydist) / fontzoom, zf, "LOTS OF THINGS ARE STILL NEEDED:", col);
3037   font2->drawText (xf / fontzoom, (yt -= 2 * ydist) / fontzoom, zf, "- DRAW TEXTURES OF TREES, BUILDINGS, ETC", col);
3038   font2->drawText (xf / fontzoom, (yt -= 2 * ydist) / fontzoom, zf, "- DESIGN 3D MODELS", col);
3039   font2->drawText (xf / fontzoom, (yt -= 2 * ydist) / fontzoom, zf, "- CREATE SOUNDTRACKS", col);
3040   font2->drawText (xf / fontzoom, (yt -= 2 * ydist) / fontzoom, zf, "- MAKE MISSION SUGGESTIONS", col);
3041   font2->drawText (xf / fontzoom, (yt -= 2 * ydist) / fontzoom, zf, "- GIVE FEEDBACK AND ADVICE", col);
3042   font1->zoom = 0.1;
3043   font2->zoom = 0.1;
3044   glPopMatrix ();
3045 #endif
3046 }
3047 
finish_display()3048 void finish_display ()
3049 {
3050   glTranslatef (0, -3.5 + 0.01 * (float) finishtimer / timestep, 0);
3051   CColor *col = &colorwhite;
3052   font1->drawTextCentered (0, 12, -3, "CONGRATULATIONS!", col);
3053   font1->drawTextCentered (0, 10, -3, "THE WORLD HAS BEEN SAVED YET AGAIN.", col);
3054   font1->drawTextCentered (0, 6, -3, "HOPE YOU HAD FUN PLAYING GL-117!", col);
3055   font1->drawTextCentered (0, 4, -3, "THIS GAME HAS ORIGINALLY BEEN DEVELOPED AS PART", col);
3056   font1->drawTextCentered (0, 2, -3, "OF THE COURSE \"APPLICATIONS OF COMPUTER GRAPHICS\"", col);
3057   font1->drawTextCentered (0, 0, -3, "AT THE TECHNICAL UNIVERSITY OF MUNICH, GERMANY.", col);
3058   font1->drawTextCentered (0, -2, -3, "IN FEBRUARY 2002 THE WORK WAS DONE AND I", col);
3059   font1->drawTextCentered (0, -4, -3, "PRESENTED THE PROTOTYPE OF A FLIGHT SIM,", col);
3060   font1->drawTextCentered (0, -6, -3, "YET WITHOUT TEXTURES, JOYSTICK, SOUNDS, MUSIC,", col);
3061   font1->drawTextCentered (0, -8, -3, "NO CAMPAIGN!", col);
3062   font1->drawTextCentered (0, -10, -3, "TWO MONTHS LATER THE FIRST RELEASE OF GL-117 WAS READY.", col);
3063   font1->drawTextCentered (0, -12, -3, "FURTHER RELEASES FOLLOWED, FEEDBACK ARRIVED, AND", col);
3064   font1->drawTextCentered (0, -14, -3, "PROGRAMMERS JOINED (LISTED IN THE CREDITS SECTION).", col);
3065   font1->drawTextCentered (0, -16, -3, "SPECIAL THANKS TO JOSEF DREXL FOR THE MODELING IDEAS,", col);
3066   font1->drawTextCentered (0, -18, -3, "AND THE UNIX AWARD GOES TO WOLFGANG HOMMEL ;-)", col);
3067 }
3068 
quit_display()3069 void quit_display ()
3070 {
3071   allmenus.setVisible (false);
3072   quitmenu.setVisible (true);
3073   quitmenu.draw ();
3074 
3075   font1->drawTextCentered (0, 0, -2, "REALLY QUIT?", &menu_colwhite);
3076 
3077   drawMouseCursor ();
3078 }
3079 
3080 
3081 
3082 /****************************************************************************
3083   IN-GAME DISPLAY EVENT
3084 ****************************************************************************/
3085 
3086 int vibration = 0;
3087 int starttime;
3088 
game_display()3089 void game_display ()
3090 {
3091   int i;
3092   double sunx = 0, suny = 0, sunz;
3093 
3094   if (dithering) glEnable (GL_DITHER);
3095   else glDisable (GL_DITHER);
3096 
3097   bool sunvisible = false;
3098   float pseudoview = getView ();
3099 
3100   float mycamtheta = camtheta, mycamphi = camphi + view_x , mycamgamma = camgamma + view_y;
3101 
3102   if (vibration > 0)
3103   {
3104     if (camera == 0)
3105     {
3106       float sinvib = sin ((float) vibration / timestep);
3107       mycamphi += 0.2 * vibration * sinvib / timestep;
3108       mycamgamma += 0.2 * vibration * sinvib / timestep;
3109     }
3110   }
3111 
3112 
3113   // calculate light factor
3114   if (camera == 0 && sunblinding && day && weather == WEATHER_SUNNY)
3115   {
3116     float np = fplayer->phi - 180;
3117     if (np >= 180) np -= 360;
3118     float sunfactor = fabs (np) + fabs (fplayer->gamma - 180 - sungamma);
3119     if (sunfactor < 50)
3120     {
3121       sunfactor = (50 - sunfactor) / 10;
3122       if (sunfactor < 1.0) sunfactor = 1.0;
3123     }
3124     else sunfactor = 1.0;
3125     sunlight_dest = sunfactor;
3126     if (game == GAME_PLAY)
3127       pseudoview /= sunfactor;
3128   }
3129   else
3130   {
3131     if (day) sunlight_dest = 1.0;
3132     else sunlight_dest = 0.75;
3133     if (flash > 0)
3134     {
3135       sunlight_dest = (float) flash / timestep;
3136     }
3137   }
3138 
3139   // show a short flash when an object explodes
3140   if (dynamiclighting)
3141   {
3142     for (i = 0; i < maxfighter; i ++)
3143     {
3144       if (fighter [i]->draw)
3145         if (fighter [i]->explode > 0)
3146           if (fighter [i] != fplayer)
3147           {
3148             float dgamma = fabs (fplayer->getAngleH (fighter [i]));
3149             float dphi = fabs (fplayer->getAngle (fighter [i]));
3150             if (dphi < 45 && dgamma < 45)
3151             {
3152               float ddist = fplayer->distance (fighter [i]);
3153               if (ddist < 40)
3154               {
3155                 ddist /= 15;
3156                 ddist ++;
3157                 dphi /= 25;
3158                 dphi ++;
3159                 dgamma /= 25;
3160                 dgamma ++;
3161                 if (fighter [i]->explode < 8 * timestep)
3162                   sunlight_dest = (float) fighter [i]->explode / timestep * 4 / ddist / dphi / dgamma;
3163                 else if (fighter [i]->explode < 16 * timestep)
3164                   sunlight_dest = (16.0 - fighter [i]->explode / timestep) * 4 / ddist / dphi / dgamma;
3165               }
3166             }
3167           }
3168     }
3169   }
3170 
3171   // sunlight for glittering does not look good
3172 /* if (camera == 0 && l->glittering > 1.0F)
3173   {
3174     sunlight += l->glittering * 1.0F - 1.0F;
3175   }*/
3176   l->glittering = 0;
3177 
3178   // turn down global sunlight when menu is showing
3179   if (game != GAME_PLAY && sunlight > 0.9F) sunlight = 0.9F;
3180 
3181   // start rendering
3182 
3183   glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
3184   glMatrixMode (GL_MODELVIEW);
3185   glLoadIdentity ();
3186 
3187   glScalef (GLOBALSCALE, GLOBALSCALE, GLOBALSCALE);
3188 
3189   glShadeModel (GL_SMOOTH);
3190 
3191   glPushMatrix ();
3192 
3193   if (camera != 1 && camera != 5)
3194     glRotatef (-mycamtheta, 0.0, 0.0, 1.0);
3195   glRotatef (mycamgamma, 1.0, 0.0, 0.0);
3196   glRotatef (-mycamphi, 0.0, 1.0, 0.0);
3197 
3198   // draw sky
3199 
3200   glDisable (GL_FOG);
3201   glDisable (GL_DEPTH_TEST);
3202 
3203   float mylight = sunlight;
3204   if (!day) mylight /= 0.75;
3205   if (mylight > 1.0 && day)
3206     mylight = mylight / 5.0 + 0.8;
3207   else if (mylight > 1.0 && !day)
3208     mylight = mylight / 5.0 + 0.8;
3209   gl->foglum = mylight;
3210   sphere->drawGL (tlminf, tlinf, tlnull, space->alpha, mylight, true, false);
3211 
3212   if (weather == WEATHER_SUNNY || weather == WEATHER_CLOUDY)
3213   {
3214     if (!day)
3215     {
3216       glPointSize (LINEWIDTH(1.0F));
3217       int stars = maxstar;
3218       if (weather != WEATHER_CLOUDY) stars = maxstar / 2;
3219       for (i = 0; i < stars; i ++)
3220       {
3221         glPushMatrix ();
3222         glRotatef (star [i]->phi, 0.0, 1.0, 0.0);
3223         glRotatef (star [i]->gamma, 1.0, 0.0, 0.0);
3224         glTranslatef (0, 0, -10);
3225         star [i]->draw ();
3226         glPopMatrix ();
3227       }
3228     }
3229   }
3230 
3231   glEnable (GL_DEPTH_TEST);
3232   glEnable (GL_FOG);
3233 
3234   if (quality >= 1 && clouds > 0)
3235   {
3236     float cloudfog = pseudoview;
3237     if (cloudfog > 110) cloudfog = 110;
3238     gl->enableFog (cloudfog);
3239 
3240     highclouds->zoom = 400;
3241     float ch2 = -382 - fplayer->tl->y / 10.0;
3242     CVector3 tlsphere2 (0, ch2, 0);
3243     highclouds->drawGL (&tlsphere2, fplayer->tl);
3244 
3245     glDisable (GL_FOG);
3246   }
3247 
3248 // draw sun or moon (or earth)
3249   float fac = view, zfac = view * 0.2;
3250   if (weather == WEATHER_SUNNY || weather == WEATHER_CLOUDY)
3251   {
3252     glRotatef (180, 0.0, 1.0, 0.0);
3253     if (camera == 0)
3254       glRotatef (sungamma, 1.0, 0.0, 0.0);
3255     else
3256       glRotatef (mycamgamma + sungamma, 1.0, 0.0, 0.0);
3257     float zf = -11;
3258     if (day)
3259       zf = -10;
3260     if (l->type == LAND_MOON && !day)
3261       zf = -8; // diplay bigger earth
3262     glTranslatef (0, 0, zf);
3263     gl->extractFrustum ();
3264     if (gl->isPointInFrustum (-1, 1, 0) || gl->isPointInFrustum (-1, -1, 0) ||
3265         gl->isPointInFrustum (1, -1, 0) || gl->isPointInFrustum (1, 1, 0))
3266     {
3267       glDisable (GL_DEPTH_TEST);
3268       if (day) gl->enableTextures (texsun->textureID);
3269       else if (l->type != LAND_MOON) gl->enableTextures (texmoon->textureID);
3270       else gl->enableTextures (texearth->textureID);
3271       if (day && l->type != 1)
3272         glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
3273       gl->enableAlphaBlending ();
3274       glEnable (GL_ALPHA_TEST);
3275       float alphamax = 0.1;
3276       if (day) alphamax = 0.1;
3277       glAlphaFunc (GL_GEQUAL, alphamax);
3278       glBegin (GL_QUADS);
3279       fac = view; zfac = view * 3.5;
3280       if (day && l->type != LAND_MOON)
3281       {
3282         float gm = (40.0 - sungamma) / 80.0;
3283         if (gm < 0) gm = 0;
3284         if (gm > 0.5) gm = 0.5;
3285         glColor4f (1.0, 1.0 - gm, 0.8 - gm, 1.0);
3286       }
3287       else
3288         glColor4f (1.0, 1.0, 1.0, 1.0);
3289       glTexCoord2d (0, 1);
3290       glVertex3f (-1, 1, 0);
3291       glTexCoord2d (1, 1);
3292       glVertex3f (1, 1, 0);
3293       glTexCoord2d (1, 0);
3294       glVertex3f (1, -1, 0);
3295       glTexCoord2d (0, 0);
3296       glVertex3f (-1, -1, 0);
3297       glEnd ();
3298 
3299       // Where is the sun?
3300       double proj[16];
3301       double modl[16];
3302       int vp[4];
3303       glGetDoublev( GL_PROJECTION_MATRIX, proj );
3304       glGetDoublev( GL_MODELVIEW_MATRIX, modl );
3305       glGetIntegerv( GL_VIEWPORT, vp );
3306       gluProject (0, 0, 0, modl, proj, vp, &sunx, &suny, &sunz);
3307       if ((sunx>=vp[0])&&(suny>=vp[1])&&(sunx<(vp[0]+vp[2]))&&(suny<(vp[1]+vp[3]))) sunvisible = true;
3308 
3309       glDisable (GL_ALPHA_TEST);
3310       glEnable (GL_DEPTH_TEST);
3311       glDisable (GL_TEXTURE_2D);
3312       gl->disableAlphaBlending ();
3313     }
3314   }
3315 
3316   glPopMatrix ();
3317 
3318   glPushMatrix ();
3319 
3320   if (camera != 1 && camera != 5)
3321     glRotatef (-mycamtheta, 0.0, 0.0, 1.0);
3322 
3323   glRotatef (mycamgamma, 1.0, 0.0, 0.0);
3324 
3325   glDisable (GL_FOG);
3326 
3327   glRotatef (-mycamphi, 0.0, 1.0, 0.0);
3328   glScalef (1, 1, 1);
3329 
3330   glTranslatef (-camx, -camy, -camz);
3331 
3332   if (camera != 50)
3333   {
3334     gl->enableFog (pseudoview);
3335   }
3336 
3337   // draw terrain
3338   l->calcDynamicLight (explosion, laser, (DynamicObj **) missile, flare);
3339   glEnable (GL_CULL_FACE);
3340   glCullFace (GL_FRONT);
3341   l->draw ((int) mycamphi, (int) (-mycamgamma + 180.0));
3342   glDisable (GL_CULL_FACE);
3343 
3344   // draw objects
3345   gl->extractFrustum ();
3346   if (camera != 50)
3347   {
3348     space->lum = sunlight;
3349     float dayfac = 1.0;
3350     if (!day) dayfac = 0.5;
3351     if (weather == WEATHER_SUNNY || weather == WEATHER_CLOUDY)
3352     {
3353       for (i = 0; i < space->no; i ++)
3354       {
3355         if (space->o [i]->tl->y < l->getExactRayHeight (space->o [i]->tl->x, space->o [i]->tl->z))
3356           space->o [i]->lum = 0.5 * dayfac;
3357         else
3358           space->o [i]->lum = 1.0 * dayfac;
3359       }
3360     }
3361     else
3362     {
3363       for (i = 0; i < space->no; i ++)
3364         space->o [i]->lum = dayfac;
3365     }
3366 //    printf ("%2.1f*%2.1f ", fplayer->lum, sunlight);
3367     if (flash > 7 * timestep)
3368     {
3369       if (antialiasing)
3370         flash1->draw ();
3371       else
3372         flash1->drawHQ ();
3373     }
3374     if (lighting)
3375     {
3376       glEnable( GL_LIGHTING);
3377       glEnable( GL_LIGHT0 );
3378       glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
3379       space->drawGL (); // draw all objects
3380       glDisable (GL_LIGHTING);
3381       glDepthMask (GL_FALSE);
3382       for (i = 0; i < space->no; i ++)
3383       {
3384         AIObj *dobj = (AIObj *) space->o [i];
3385         if (dobj->id >= MISSILE1)
3386           if (dobj->draw && dobj->drawlight && dobj->active)
3387           {
3388             if (dobj->smoke)
3389               if ((dobj->id >= MISSILE1 && dobj->id <= MISSILE2) || (dobj->id >= FIGHTER1 && dobj->id <= FIGHTER2))
3390                 if (!(dobj->ttl == 0 && dobj->id >= MISSILE1 && dobj->id <= MISSILE2))
3391                 {
3392                   dobj->smoke->draw ();
3393                 }
3394           }
3395       }
3396       glDepthMask (GL_TRUE);
3397     }
3398     else
3399     {
3400       space->drawGL ();
3401     }
3402   }
3403   glDisable (GL_TEXTURE_2D);
3404 
3405   glDisable (GL_LIGHTING);
3406 
3407   if (camera == 0)
3408   {
3409     glDisable (GL_DEPTH_TEST);
3410     if (antialiasing)
3411       glEnable (GL_LINE_SMOOTH);
3412     cockpit->drawTargeter ();
3413     if (antialiasing)
3414       glDisable (GL_LINE_SMOOTH);
3415     glEnable (GL_DEPTH_TEST);
3416   }
3417 
3418   glPopMatrix ();
3419 
3420 // draw flares
3421   if (specialeffects)
3422     if (sunvisible && /*camera == 0 &&*/ sunblinding && day)
3423     {
3424       CTexture* fl_texture[]= {texflare1,texflare3,texflare2,texflare4,texflare2,texflare4,texflare3,0};
3425       double fl_position[]=   {0.2,      1.6,      3.2,      8.1,      -1.4,     -2.2,     -3.5,     0};
3426       double fl_size[]=       {0.8,      0.6,      0.5,      0.4,      0.8,      0.4,      0.5,      0};
3427       double proj[16];
3428       double modl[16];
3429       double dr[2];
3430       int vp[4];
3431       double objx,objy,objz;
3432 
3433       glGetDoublev( GL_PROJECTION_MATRIX, proj );
3434       glGetDoublev( GL_MODELVIEW_MATRIX, modl );
3435       glGetIntegerv( GL_VIEWPORT, vp );
3436       glGetDoublev( GL_DEPTH_RANGE, dr );
3437 
3438       double cx=vp[2]/2+vp[0];
3439       double cy=vp[3]/2+vp[1];
3440 
3441       glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
3442       int i=0;
3443       double flarez_eye=4;
3444       double flarez_win=(-proj[10]+proj[14]/flarez_eye)*(dr[1]-dr[0])/2+(dr[1]+dr[0])/2;
3445       while (CTexture *tex=fl_texture[i])
3446       {
3447         double position=fl_position[i];
3448         double flarex,flarey,size=fl_size[i]/GLOBALSCALE;
3449 
3450         i++;
3451 
3452         flarex=(cx-sunx)*position+sunx;
3453         flarey=(cy-suny)*position+suny;
3454 
3455         if (gluUnProject (flarex, flarey, flarez_win, modl, proj, vp, &objx, &objy, &objz)==GL_TRUE)
3456         {
3457           gl->enableTextures (tex->textureID);
3458           gl->enableAlphaBlending ();
3459           glDisable (GL_ALPHA_TEST);
3460           glDisable (GL_DEPTH_TEST);
3461           glDisable (GL_FOG);
3462 
3463           glBegin (GL_QUADS);
3464           glColor4f (1.0, 1.0, 1.0, 1.0);
3465           glTexCoord2d (0, 1);
3466           glVertex3f (-size+objx, size+objy, objz);
3467           glTexCoord2d (1, 1);
3468           glVertex3f (size+objx, size+objy, objz);
3469           glTexCoord2d (1, 0);
3470           glVertex3f (size+objx, -size+objy, objz);
3471           glTexCoord2d (0, 0);
3472           glVertex3f (-size+objx, -size+objy, objz);
3473           glEnd ();
3474         }
3475       }
3476       glEnable (GL_DEPTH_TEST);
3477       glDisable (GL_TEXTURE_2D);
3478       gl->disableAlphaBlending ();
3479       glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
3480     }
3481 
3482 // sunblinding test
3483 
3484   if (sunvisible)
3485   {
3486     GLfloat zbuf[1];
3487     glReadPixels((int)sunx,(int)suny,1,1,GL_DEPTH_COMPONENT,GL_FLOAT,zbuf);
3488     sunblinding=(zbuf[0]<1)?false:true;
3489   }
3490   else
3491   {
3492     sunblinding=false;
3493   }
3494 
3495   // draw cockpit
3496   if (camera == 0)
3497   {
3498     if (antialiasing)
3499       glEnable (GL_LINE_SMOOTH);
3500     glPushMatrix ();
3501     glRotatef (view_y, 1, 0, 0);
3502     glRotatef (-view_x, 0, 1, 0);
3503     cockpit->drawCross ();
3504     cockpit->drawHeading ();
3505     glPopMatrix ();
3506     if (antialiasing)
3507       glDisable (GL_LINE_SMOOTH);
3508     cockpit->drawRadar ();
3509     cockpit->drawTargetedElement ();
3510     cockpit->drawWeapon ();
3511     cockpit->drawCounter ();
3512     cockpit->drawThrustBar ();
3513     cockpit->drawRelativeHeightBar ();
3514    }
3515 
3516   // draw blackout/redout (blending)
3517   if (camera == 0)
3518   {
3519     int black = (int) blackout;
3520     if (black > 255) black = 255;
3521     int red = (int) redout;
3522     if (red > 255) red = 255;
3523     float xf = 2.0, yf = 1.5, zf = 1.0;
3524     if (black > 0)
3525     {
3526       glColor4ub (0, 0, 0, black);
3527     }
3528     else if (red > 0)
3529     {
3530       glColor4ub (255, 0, 0, red);
3531     }
3532     if (black > 0 || red > 0)
3533     {
3534       glDisable (GL_DEPTH_TEST);
3535       glEnable (GL_BLEND);
3536       glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3537       glBegin (GL_QUADS);
3538       glVertex3f (-xf, -yf, -zf);
3539       glVertex3f (-xf, yf, -zf);
3540       glVertex3f (xf, yf, -zf);
3541       glVertex3f (xf, -yf, -zf);
3542       glEnd ();
3543       gl->disableAlphaBlending ();
3544       glDisable (GL_BLEND);
3545       glEnable (GL_DEPTH_TEST);
3546     }
3547   }
3548 
3549   if (brightness)
3550   {
3551     adjustBrightness ();
3552     glEnable (GL_DEPTH_TEST);
3553   }
3554 
3555   // draw mission dependant informations
3556   mission->draw ();
3557 
3558   glPushMatrix ();
3559   glDisable (GL_DEPTH_TEST);
3560 
3561   glPopMatrix ();
3562   char buf [25];
3563   sprintf (buf, "FPS: %d", (int) fps);
3564   font1->drawText (-25, 25, -3.5, buf, &colorwhite);
3565 
3566   bool write = false;
3567   if (firststart)
3568   {
3569     int akttime;
3570 #ifndef USE_GLUT
3571     akttime = SDL_GetTicks ();
3572 #else
3573     akttime = glutGet (GLUT_ELAPSED_TIME);
3574 #endif
3575     if (akttime - starttime < 20000)
3576       if ((akttime - starttime) / 300 % 3)
3577       {
3578         font1->drawTextCentered (0, 0, -1.8, "PLEASE WAIT WHILE", &colorred);
3579         font1->drawTextCentered (0, -1, -1.8, "ADJUSTING QUALITY", &colorred);
3580         write = true;
3581       }
3582   }
3583   if (fps >= 5 && fps <= 20 && !write)
3584   {
3585     font1->drawTextCentered (0, -8, -2, "FPS TOO LOW", &colorred);
3586     font1->drawTextCentered (0, -9, -2, "TURN DOWN VIEW OR QUALITY", &colorred);
3587   }
3588 
3589   if (fps < 5 && !write)
3590   {
3591     font1->drawTextCentered (0, -8, -2, "FPS FAR TOO LOW", &colorred);
3592     font1->drawTextCentered (0, -9, -2, "SEE \"README\" OR \"FAQ\" FILES", &colorred);
3593     font1->drawTextCentered (0, -10, -2, "HIT \"ESC\" AND 'Y' TO EXIT THE GAME", &colorred);
3594   }
3595 
3596   if (controls == CONTROLS_MOUSE && !mouse_relative)
3597     drawMouseCursor ();
3598 }
3599 
3600 
3601 
3602 /****************************************************************************
3603   TIMER EVENTS
3604 ****************************************************************************/
3605 
3606 float lastthrust;
3607 int gametimer;
3608 
game_timer(int dt)3609 void game_timer (int dt)
3610 {
3611 //  if (multiplayer) return;
3612   int i, i2;
3613 
3614   sunlight += (sunlight_dest - sunlight) / 10 * dt / timestep;
3615 
3616   gametimer += dt;
3617   cockpit->dt = dt;
3618   l->lsticker += dt;
3619   if (l->lsticker >= 36000000)
3620     l->lsticker = 0;
3621 
3622   if (vibration > 0)
3623   {
3624     vibration -= dt;
3625   }
3626 
3627   if (fplayer->autofire && fplayer->active)
3628   {
3629     if (fplayer->ammo != 0)
3630     {
3631       fplayer->fireCannon (laser);
3632 #ifdef HAVE_SDL_MIXER
3633       if (!startcannon)
3634       {
3635         sound->playLoop (SOUND_CANNON1);
3636         startcannon = true;
3637       }
3638 #else
3639       sound->play (SOUND_CANNON1, 1);
3640 #endif
3641     }
3642   }
3643 #ifdef HAVE_SDL_MIXER
3644   else
3645   {
3646     if (startcannon)
3647     {
3648       startcannon = false;
3649       sound->stop (SOUND_CANNON1);
3650     }
3651   }
3652 #endif
3653 
3654   if (lastshield > fplayer->shield && !fplayer->ai)
3655   {
3656     sound->play (SOUND_HIT1, false);
3657     lastshield = (int) fplayer->shield;
3658     vibration = 25 * timestep;
3659   }
3660 
3661   // create flash during thunderstorm
3662   if (weather == WEATHER_THUNDERSTORM && flash <= 0 && !myrandom (2000 / dt))
3663   {
3664     flash = 18 * timestep;
3665     int fphi = (int) camphi + myrandom (50) - 25;
3666     if (fphi < 0) fphi += 360;
3667     else if (fphi >= 360) fphi -= 360;
3668     float pseudoview = getView ();
3669     float fdist = myrandom ((int) pseudoview - 20) + 10;
3670     float fx = fplayer->tl->x - sine [fphi] * fdist;
3671     float fz = fplayer->tl->z - cosi [fphi] * fdist;
3672     flash1->set (fx, l->getHeight (fx, fz), fz, (int) camphi);
3673     int lev = (int) (128.0 - 80.0 * fdist / (pseudoview - 10));
3674     sound->setVolume (SOUND_THUNDER1, lev);
3675     sound->play (SOUND_THUNDER1, false);
3676   }
3677 
3678   if (initing) return;
3679 
3680   if (flash > 0)
3681     flash -= dt;
3682   if (flash <= 7 * timestep && flash > 0)
3683     flash -= dt;
3684 
3685   if (!fplayer->ai)
3686     if (sound->engine != (int) ((fplayer->thrust / fplayer->maxthrust * 20) - 10))
3687     {
3688       setPlaneVolume ();
3689       lastthrust = fplayer->thrust;
3690     }
3691 
3692   // collision tests
3693   for (i = 0; i < maxfighter; i ++)
3694   {
3695     for (i2 = 0; i2 < maxlaser; i2 ++)
3696       if (laser [i2]->active)
3697         fighter [i]->collide (laser [i2], dt);
3698     for (i2 = 0; i2 < maxmissile; i2 ++)
3699       if (missile [i2]->active)
3700         fighter [i]->collide (missile [i2], dt);
3701     for (i2 = 0; i2 < i; i2 ++)
3702       if (fighter [i2]->active)
3703         if (i != i2)
3704           fighter [i]->collide (fighter [i2], dt);
3705   }
3706 
3707   for (i = 0; i < maxflare; i ++)
3708   {
3709     for (i2 = 0; i2 < maxmissile; i2 ++)
3710       if (missile [i2]->active)
3711         flare [i]->collide (missile [i2], dt);
3712   }
3713 
3714   for (i = 0; i < maxchaff; i ++)
3715   {
3716     for (i2 = 0; i2 < maxmissile; i2 ++)
3717       if (missile [i2]->active)
3718         chaff [i]->collide (missile [i2], dt);
3719   }
3720 
3721   // move objects
3722   for (i = 0; i < maxfighter; i ++)
3723   {
3724     fighter [i]->aiAction (dt, (AIObj **) fighter, missile, laser, flare, chaff);
3725     float lev;
3726     if (fighter [i]->explode == 1 && (lev = fplayer->distance (fighter [i])) < 32)
3727     {
3728       sound->setVolume (SOUND_EXPLOSION1, 128);
3729       float angle = fplayer->getAngle (fighter [i]);
3730       angle = 180 - angle;
3731       sound->setPosition (SOUND_EXPLOSION1, (int) angle, (int) (lev * 4.0));
3732       sound->play (SOUND_EXPLOSION1, false);
3733     }
3734   }
3735   for (i = 0; i < maxlaser; i ++)
3736   {
3737     laser [i]->move (dt);
3738   }
3739   for (i = 0; i < maxmissile; i ++)
3740   {
3741     missile [i]->aiAction (dt, (AIObj **) fighter, missile, laser, flare, chaff);
3742   }
3743   for (i = 0; i < maxflare; i ++)
3744   {
3745     flare [i]->move (dt);
3746   }
3747   for (i = 0; i < maxchaff; i ++)
3748   {
3749     chaff [i]->move (dt);
3750   }
3751 
3752   for (i = 0; i < maxexplosion; i ++)
3753     explosion [i]->move (dt);
3754   for (i = 0; i < maxblacksmoke; i ++)
3755     blacksmoke [i]->move (dt);
3756 
3757   // show blackout/redout
3758   if (blackout > 0) blackout -= 3.0F * dt / timestep;
3759   if (blackout < 0) blackout = 0;
3760   if (redout > 0) redout -= 3.0F * dt / timestep;
3761   if (redout < 0) redout = 0;
3762   if (blackout > 400) blackout = 400;
3763   if (redout > 400) redout = 400;
3764   float testout;
3765   if (redout < 1)
3766   {
3767     testout = (fplayer->realspeed * fplayer->elevatoreffect - 0.13F) * 40.0F;
3768     if (testout > 0) blackout += testout * dt / timestep;
3769   }
3770   if (blackout < 1)
3771   {
3772     testout = (fplayer->realspeed * fplayer->elevatoreffect + 0.065F) * 80.0F;
3773     if (testout < 0) redout -= testout * dt / timestep;
3774   }
3775 
3776   // show own explosion from chase cam
3777   if (fplayer->shield <= 0)
3778     camera = 1;
3779 
3780   float cf = -fplayer->zoom / 2;
3781   camtheta = fplayer->theta;
3782   if (camera == 0)  // cockpit
3783   {
3784     float cgamma = fplayer->gamma + 25.0F * COS(fplayer->theta);
3785     float cphi = fplayer->phi + 25.0F * SIN(fplayer->theta);
3786     float fac = fplayer->zoom / 2;
3787     camx = fplayer->tl->x + COS(cgamma) * SIN(cphi) * fac;
3788     camy = fplayer->tl->y - SIN(cgamma) * fac;
3789     camz = fplayer->tl->z + COS(cgamma) * COS(cphi) * fac;
3790     camphi = fplayer->phi;
3791     camgamma = -fplayer->gamma + 180;
3792     fplayer->draw = 0;
3793   }
3794   if (camera == 1) // chase
3795   {
3796     cf = fplayer->zoom * 3;
3797     camx = fplayer->tl->x + cf * SIN(fplayer->phi);
3798     camy = fplayer->tl->y + fplayer->zoom;
3799     camz = fplayer->tl->z + cf * COS(fplayer->phi);
3800     camphi = fplayer->phi;
3801     fplayer->draw = 1;
3802     camgamma = 20;
3803   }
3804   else if (camera == 2) // backwards
3805   {
3806     cf = -fplayer->zoom * 3;
3807     camx = fplayer->tl->x + cf * SIN(fplayer->phi);
3808     camy = fplayer->tl->y + fplayer->zoom;
3809     camz = fplayer->tl->z + cf * COS(fplayer->phi);
3810     camphi = fplayer->phi + 180.0;
3811     fplayer->draw = 1;
3812     camgamma = 20;
3813   }
3814   else if (camera == 3) // other players
3815   {
3816     cf = fighter [aktcam]->zoom * 3;
3817     camx = fighter [aktcam]->tl->x + cf * SIN(fighter [aktcam]->phi);
3818     camy = fighter [aktcam]->tl->y + fighter [aktcam]->zoom;
3819     camz = fighter [aktcam]->tl->z + cf * COS(fighter [aktcam]->phi);
3820     camphi = fighter [aktcam]->phi;
3821     camgamma = 20;
3822     camtheta = fighter [aktcam]->theta;
3823     fplayer->draw = 1;
3824   }
3825   else if (camera == 4) // missile
3826   {
3827     cf = missile [0]->zoom * 10;
3828     camx = missile [0]->tl->x + cf * SIN(missile [0]->phi);
3829     camy = missile [0]->tl->y + fplayer->zoom * 2;
3830     camz = missile [0]->tl->z + cf * COS(missile [0]->phi);
3831     camphi = missile [0]->phi;
3832     fplayer->draw = 1;
3833   }
3834   else if (camera == 5) // top
3835   {
3836     cf = fplayer->zoom * 15;
3837     camx = fplayer->tl->x + cf * SIN(fplayer->phi);
3838     camy = fplayer->tl->y + 5.5;
3839     camz = fplayer->tl->z + cf * COS(fplayer->phi);
3840     camphi = fplayer->phi;
3841     fplayer->draw = 1;
3842     camgamma = 50;
3843   }
3844   else if (camera == 6) // left
3845   {
3846     cf = fplayer->zoom * 2;
3847     camphi = fplayer->phi + 90.0;
3848     if (camphi >= 360) camphi -= 360;
3849     else if (camphi < 0) camphi += 360;
3850     camx = fplayer->tl->x + cf * SIN(camphi);
3851     camy = fplayer->tl->y + fplayer->zoom;
3852     camz = fplayer->tl->z + cf * COS(camphi);
3853     fplayer->draw = 1;
3854     camgamma = 20;
3855   }
3856   else if (camera == 7) // right
3857   {
3858     cf = fplayer->zoom * 2;
3859     camphi = fplayer->phi + 270.0;
3860     if (camphi >= 360) camphi -= 360;
3861     else if (camphi < 0) camphi += 360;
3862     camx = fplayer->tl->x + cf * SIN(camphi);
3863     camy = fplayer->tl->y + fplayer->zoom;
3864     camz = fplayer->tl->z + cf * COS(camphi);
3865     fplayer->draw = 1;
3866     camgamma = 20;
3867   }
3868   else if (camera == 8) // top near
3869   {
3870     cf = fplayer->zoom * 5;
3871     camx = fplayer->tl->x + cf * SIN(fplayer->phi);
3872     camy = fplayer->tl->y + 2.5;
3873     camz = fplayer->tl->z + cf * COS(fplayer->phi);
3874     camphi = fplayer->phi;
3875     fplayer->draw = 1;
3876     camgamma = 50;
3877   }
3878   else if (camera == 9) // top very near
3879   {
3880     cf = fplayer->zoom * 2;
3881     camx = fplayer->tl->x + cf * SIN(fplayer->phi);
3882     camy = fplayer->tl->y + 1.0;
3883     camz = fplayer->tl->z + cf * COS(fplayer->phi);
3884     camphi = fplayer->phi;
3885     fplayer->draw = 1;
3886     camgamma = 50;
3887   }
3888   else if (camera == 50)
3889   {
3890     camx = 20;
3891     camz = 80;
3892     camy = 250;
3893     camphi = 20;
3894     camgamma = 75;
3895     game = GAME_PAUSE;
3896   }
3897   if (camphi >= 360.0) camphi -= 360.0;
3898 #ifdef USE_GLUT
3899   glutPostRedisplay();
3900 #else
3901   sdldisplay = true;
3902 #endif
3903 
3904   fplayer->rectheta -= dtheta;
3905   fplayer->recgamma += dgamma;
3906 
3907   missionstate = mission->processtimer (dt);
3908 
3909   if (missionstate == 2)
3910   {
3911     missionending ++;
3912     if (missionending >= 25)
3913     {
3914       missionending = 0;
3915       fplayer->score = mission->getScore (missionstate);
3916       if (!mission->id == MISSION_DEMO)
3917       {
3918         switch_stats ();
3919       }
3920       else
3921       {
3922         pleaseWait ();
3923         createMission (MISSION_DEMO);
3924         game_levelInit ();
3925       }
3926     }
3927   }
3928 
3929   if (missionstate == 1)
3930   {
3931     missionending ++;
3932     if (missionending >= 25)
3933     {
3934       missionending = 0;
3935       fplayer->score = mission->getScore (missionstate);
3936       if (mission->id != MISSION_DEMO)
3937       {
3938         if (mission->id != MISSION_MOON3)
3939           switch_stats ();
3940         else
3941           switch_finish ();
3942       }
3943       else
3944       {
3945         pleaseWait ();
3946         createMission (MISSION_DEMO);
3947         game_levelInit ();
3948       }
3949     }
3950   }
3951 
3952   if (controls == CONTROLS_KEYBOARD)
3953   {
3954     float fac = 0.005;
3955     if (keyb_elev == 0) fplayer->elevatoreffect = 0;
3956     else fplayer->elevatoreffect += (float) dt * keyb_elev * fac;
3957     if (keyb_roll == 0) fplayer->rolleffect = 0;
3958     else fplayer->rolleffect += (float) dt * keyb_roll * fac;
3959     if (keyb_rudder == 0) fplayer->ruddereffect = 0;
3960     else fplayer->ruddereffect += (float) dt * keyb_rudder * fac;
3961     if (fplayer->elevatoreffect > 1.0) fplayer->elevatoreffect = 1.0;
3962     if (fplayer->elevatoreffect < -0.5) fplayer->elevatoreffect = -0.5;
3963     if (fplayer->rolleffect > 1.0) fplayer->rolleffect = 1.0;
3964     if (fplayer->rolleffect < -1.0) fplayer->rolleffect = -1.0;
3965     if (fplayer->ruddereffect > 1.0) fplayer->ruddereffect = 1.0;
3966     if (fplayer->ruddereffect < -1.0) fplayer->ruddereffect = -1.0;
3967   }
3968 }
3969 
3970 float lastfps = -1;
3971 int newcamera = 0;
3972 
menu_timer(Uint32 dt)3973 void menu_timer (Uint32 dt)
3974 {
3975   char buf [256];
3976   menutimer += dt;
3977   int cycle = (menutimer / timestep) % 256;
3978   if (cycle == 0)
3979   {
3980     newcamera = 0;
3981   }
3982   if (cycle == 200 && !newcamera)
3983   {
3984     newcamera = 1;
3985     if (camera == 5)
3986     {
3987       camera = 1;
3988       if (missile [0]->active)
3989         camera = 4;
3990     }
3991     else if (camera == 1 || camera == 4) camera = 2;
3992     else if (camera == 2) camera = 5;
3993   }
3994 
3995   int akttime;
3996 #ifndef USE_GLUT
3997   akttime = SDL_GetTicks ();
3998 #else
3999   akttime = glutGet (GLUT_ELAPSED_TIME);
4000 #endif
4001   if (firststart)
4002     if (akttime - starttime < 20000)
4003     {
4004       if (lastfps != fps)
4005       {
4006         lastfps = fps;
4007         if (fps > 40)
4008         {
4009           if (view < quality * 20 + 60 && view < 100)
4010             view += 20;
4011           else if (quality < 5)
4012           {
4013             quality ++;
4014             view = quality * 20 + 30;
4015             if (quality >= 1)
4016             { antialiasing = 1; specialeffects = 1; dithering = 1; dynamiclighting = 0; }
4017           }
4018           sprintf (buf, "%d", (int) quality);
4019           ((Label *) optmenu [0]->components [1])->setText (buf);
4020           sprintf (buf, "%d", (int) view);
4021           ((Label *) optmenu [0]->components [3])->setText (buf);
4022         }
4023         else if (fps < 30)
4024         {
4025           if (view > quality * 20 + 30 && view > 20)
4026             view -= 20;
4027           else if (quality > 0)
4028           {
4029             quality --;
4030             view = quality * 20 + 60;
4031             if (quality < 1)
4032             { antialiasing = 0; specialeffects = 0; dithering = 0; dynamiclighting = 0; }
4033           }
4034           sprintf (buf, "%d", (int) quality);
4035           ((Label *) optmenu [0]->components [1])->setText (buf);
4036           sprintf (buf, "%d", (int) view);
4037           ((Label *) optmenu [0]->components [3])->setText (buf);
4038         }
4039         menu_reshape ();
4040       }
4041     }
4042 #ifdef USE_GLUT
4043   glutPostRedisplay();
4044 #else
4045   sdldisplay = true;
4046 #endif
4047 }
4048 
stats_timer(Uint32 dt)4049 void stats_timer (Uint32 dt)
4050 {
4051   menutimer += dt;
4052 #ifdef USE_GLUT
4053   glutPostRedisplay();
4054 #else
4055   sdldisplay = true;
4056 #endif
4057 }
4058 
mission_timer(Uint32 dt)4059 void mission_timer (Uint32 dt)
4060 {
4061   missionmenutimer += dt;
4062 #ifdef USE_GLUT
4063   glutPostRedisplay();
4064 #else
4065   sdldisplay = true;
4066 #endif
4067 }
4068 
credits_timer(Uint32 dt)4069 void credits_timer (Uint32 dt)
4070 {
4071   creditstimer += dt;
4072 #ifdef SHOW_SOFTWARE_PATENTS
4073   if (creditstimer > 2500 * timestep)
4074     creditstimer = 0;
4075 #else
4076   if (creditstimer > 700 * timestep)
4077     creditstimer = 0;
4078 #endif
4079 
4080 #ifdef USE_GLUT
4081   glutPostRedisplay();
4082 #else
4083   sdldisplay = true;
4084 #endif
4085 }
4086 
finish_timer(Uint32 dt)4087 void finish_timer (Uint32 dt)
4088 {
4089   finishtimer += dt;
4090   if (finishtimer > 800 * timestep)
4091     finishtimer = 0;
4092 #ifdef USE_GLUT
4093   glutPostRedisplay();
4094 #else
4095   sdldisplay = true;
4096 #endif
4097 }
4098 
create_timer(Uint32 dt)4099 void create_timer (Uint32 dt)
4100 {
4101 #ifndef USE_GLUT
4102 //  server->createSocketSet ();
4103   server->getClient ();
4104   SDL_Delay (100);
4105   mission_timer (dt);
4106 #endif
4107 }
4108 
join_timer(Uint32 dt)4109 void join_timer (Uint32 dt)
4110 {
4111 #ifdef HAVE_SDL_NET
4112 #ifndef USE_GLUT
4113   char buf [STDSIZE];
4114   if (client->sock == NULL) client->getServer ("127.0.0.1", "client1");
4115   else
4116   {
4117     SDL_Delay (100);
4118     mission_timer (dt);
4119     client->getMessage (buf);
4120 
4121     if (buf [0] == 's')
4122     {
4123       createMission (MISSION_MULTIPLAYER_DOGFIGHT);
4124       game_levelInit ();
4125       switch_game ();
4126       missionactive = true;
4127     }
4128   }
4129 #endif
4130 #endif
4131 }
4132 
4133 
4134 
4135 /****************************************************************************
4136   GAME DATA INITIALIZATION
4137 ****************************************************************************/
4138 
4139 // calculate missile rack positions for a fighter
setMissiles(CModel * model)4140 void setMissiles (CModel *model)
4141 {
4142   int i;
4143   CVector3 tlmissile (0, 0.3, 0.3);
4144   for (i = 0; i < model->numObjects; i ++)
4145   {
4146     if (model->object [i]->numVertices == 4)
4147     {
4148       CObject *o = model->object [i];
4149       float sumx = 0, sumz = 0;
4150       float maxy = 2;
4151       int i2;
4152       for (i2 = 0; i2 < o->numVertices; i2 ++)
4153       {
4154         sumx += o->vertex [i2].vector.x;
4155         if (o->vertex [i2].vector.y < maxy)
4156           maxy = o->vertex [i2].vector.y;
4157         sumz += o->vertex [i2].vector.z;
4158       }
4159       tlmissile.x = sumx / 4.0F;
4160       tlmissile.y = maxy;
4161       tlmissile.z = sumz / 4.0F;
4162 
4163       tlmissile.y = maxy;
4164       model->addRefPoint (&tlmissile);
4165     }
4166   }
4167 }
4168 
4169 // initialize game data
myInit()4170 void myInit ()
4171 {
4172   int i, i2;
4173 
4174   // useful global variables/constants
4175   tlinf = new CVector3 (1E10, 1E10, 1E10);
4176   tlminf = new CVector3 (-1E10, -1E10, -1E10);
4177   tlnull = new CVector3 (0, 0, 0);
4178   rotnull = new CRotation ();
4179   rotmissile = new CRotation ();
4180   rotmissile->a = 90;
4181   rotmissile->c = 270;
4182 
4183   // initialize all global variables
4184 
4185   for (i = 0; i < maxgroundobj; i ++)
4186   {
4187     groundobj [i] = new DynamicObj (space, &model_tent1, 3);
4188   }
4189 
4190   explsphere = new CSphere ();
4191   ((CSphere *) explsphere)->init (1, 9);
4192   CColor explcolor (255, 255, 1);
4193   explsphere->setColor (&explcolor);
4194   explsphere->alpha = true;
4195   for (i = 0; i < explsphere->object [0]->numVertices; i ++)
4196   {
4197     explsphere->object [0]->vertex [i].color.setColor (myrandom (100) + 155, myrandom (100) + 100, 0, myrandom (3) / 2 * 255);
4198   }
4199   for (i = 0; i < maxexplosion; i ++)
4200   {
4201     explosion [i] = new CExplosion (space, explsphere);
4202   }
4203 
4204   for (i = 0; i < maxblacksmoke; i ++)
4205   {
4206     blacksmoke [i] = new CBlackSmoke (space);
4207   }
4208 
4209   for (i = 0; i < maxfighter; i ++)
4210   {
4211     fighter [i] = new AIObj (space, &model_fig, 0.4);
4212     for (i2 = 0; i2 < 12; i2 ++)
4213       fighter [i]->addRefModel (&model_missile1, tlnull, rotmissile, 0.2);
4214   }
4215 
4216   highclouds = new HighClouds (25);
4217   highclouds->setTexture (texclouds3);
4218 
4219   highclouds2 = new HighClouds (25);
4220   highclouds2->setTexture (texclouds3);
4221 
4222   objsphere = new CSphere (1, 9, 1, 1, 1);
4223   sphere = new CSpaceObj (objsphere, 10.0);
4224   sphere->rot->a = 90;
4225   sphere->rot->b = 90;
4226   sphere->rot->c = 270;
4227   sphere->draw = 2;
4228   sphere->drawlight = false;
4229 
4230   flash1 = new Flash ();
4231 
4232   for (i = 0; i < maxlaser; i ++)
4233   {
4234     laser [i] = new DynamicObj (space, &model_cannon1, 0.07);
4235   }
4236 
4237   for (i = 0; i < maxmissile; i ++)
4238   {
4239     missile [i] = new AIObj (space, &model_missile1, 0.1);
4240   }
4241 
4242   for (i = 0; i < maxflare; i ++)
4243   {
4244     flare [i] = new DynamicObj (space, &model_flare1, 0.1);
4245   }
4246 
4247   for (i = 0; i < maxchaff; i ++)
4248   {
4249     chaff [i] = new DynamicObj (space, &model_chaff1, 0.1);
4250   }
4251 
4252   for (i = 0; i < maxstar; i ++)
4253   {
4254     star [i] = new Star (myrandom (360), myrandom (85), 0.4 + 0.1 * myrandom (8));
4255   }
4256 
4257   cockpit = new Cockpit ();
4258 
4259   pleaseWait ();
4260   createMission (MISSION_DEMO);
4261   game_levelInit ();
4262 
4263   menu_reshape ();
4264 }
4265 
4266 
4267 
4268 /****************************************************************************
4269   INTRO
4270 ****************************************************************************/
4271 
4272 CRotation rot;
4273 CRotation rot2;
4274 CVector3 tl;
4275 CVector3 tl2;
4276 int initexplode = 0;
4277 int initexplode1 = 0;
4278 int i;
4279 int inittimer = 0;
4280 int inittimer_gl117 = 0;
4281 
init_reshape()4282 void init_reshape ()
4283 {
4284   // use whole window
4285   glViewport (0, 0, (GLint) width, (GLint) height);
4286 
4287   glMatrixMode (GL_PROJECTION);
4288   glLoadIdentity ();
4289 
4290   // angle, aspectratio, nearclip, farclip
4291   gluPerspective (visibleangle, 1.0, nearclippingplane, 80);
4292   glPolygonMode (GL_FRONT_AND_BACK, polygonMode);
4293 }
4294 
4295 // load game data (this method does not really belong to the intro itself)
myFirstInit()4296 void myFirstInit ()
4297 {
4298   display ("Creating calculation tables", LOG_ALL);
4299   mathtab_init ();
4300 
4301   display ("Creating advanced OpenGL methods", LOG_ALL);
4302   gl = new GL ();
4303 
4304   // create textures (OpenGL)
4305   display ("Loading textures", LOG_ALL);
4306   texgrass = gl->genTextureTGA (dirs->getTextures ("grass1.tga"), 0, 0, 1, false);
4307   texrocks = gl->genTextureTGA (dirs->getTextures ("rocks1.tga"), 0, 0, 1, false);
4308   texwater = gl->genTextureTGA (dirs->getTextures ("water1.tga"), 0, 0, 1, false);
4309   texsand = gl->genTextureTGA (dirs->getTextures ("sand1.tga"), 0, 0, 1, false);
4310   texredsand = gl->genTextureTGA (dirs->getTextures ("redsand1.tga"), 0, 0, 1, false);
4311   texredstone = gl->genTextureTGA (dirs->getTextures ("redstone2.tga"), 0, 0, 1, false);
4312   texgravel1 = gl->genTextureTGA (dirs->getTextures ("gravel1.tga"), 0, 0, 1, false);
4313   texglitter1 = gl->genTextureTGA (dirs->getTextures ("glitter.tga"), 0, -1, 0, true);
4314   textree = gl->genTextureTGA (dirs->getTextures ("tree1.tga"), 0, -1, 1, true);
4315   textreeu = gl->genTextureTGA (dirs->getTextures ("treeu1.tga"), 0, -1, 1, true);
4316   textree2 = gl->genTextureTGA (dirs->getTextures ("tree2.tga"), 0, -1, 1, true);
4317   textreeu2 = gl->genTextureTGA (dirs->getTextures ("treeu2.tga"), 0, -1, 1, true);
4318   textree3 = gl->genTextureTGA (dirs->getTextures ("tree3.tga"), 0, 3, 1, true);
4319   textreeu3 = gl->genTextureTGA (dirs->getTextures ("treeu3.tga"), 0, 3, 1, true);
4320   textree4 = gl->genTextureTGA (dirs->getTextures ("tree4.tga"), 0, 3, 1, true);
4321   textreeu4 = gl->genTextureTGA (dirs->getTextures ("treeu4.tga"), 0, 3, 1, true);
4322   textree5 = gl->genTextureTGA (dirs->getTextures ("tree5.tga"), 0, -1, 1, true);
4323   textreeu5 = gl->genTextureTGA (dirs->getTextures ("treeu5.tga"), 0, -1, 1, true);
4324   texcactus1 = gl->genTextureTGA (dirs->getTextures ("cactus1.tga"), 0, 3, 1, true);
4325   texcactusu1 = gl->genTextureTGA (dirs->getTextures ("cactusu1.tga"), 0, 3, 1, true);
4326   texsmoke = gl->genTextureTGA (dirs->getTextures ("smoke1.tga"), 0, -1, 1, true);
4327   texsmoke2 = gl->genTextureTGA (dirs->getTextures ("smoke2.tga"), 0, -1, 1, true);
4328   texsmoke3 = gl->genTextureTGA (dirs->getTextures ("smoke3.tga"), 0, 5, 1, true);
4329   texsun = gl->genTextureTGA (dirs->getTextures ("sun2.tga"), 1, -1, 0, true);
4330   texmoon = gl->genTextureTGA (dirs->getTextures ("moon1.tga"), 1, 2, 0, true);
4331   texearth = gl->genTextureTGA (dirs->getTextures ("earth.tga"), 1, 0, 0, true);
4332   texflare1 = gl->genTextureTGA (dirs->getTextures ("flare1.tga"), 1, -1, 0, true);
4333   texflare2 = gl->genTextureTGA (dirs->getTextures ("flare2.tga"), 1, -1, 0, true);
4334   texflare3 = gl->genTextureTGA (dirs->getTextures ("flare3.tga"), 1, -1, 0, true);
4335   texflare4 = gl->genTextureTGA (dirs->getTextures ("flare4.tga"), 1, -1, 0, true);
4336   texcross = gl->genTextureTGA (dirs->getTextures ("cross.tga"), 0, -1, 1, true);
4337   texcross2 = gl->genTextureTGA (dirs->getTextures ("cross2.tga"), 0, -1, 1, true);
4338   texranks = gl->genTextureTGA (dirs->getTextures ("ranks.tga"), 0, 0, 0, true);
4339   texmedals = gl->genTextureTGA (dirs->getTextures ("medals.tga"), 0, 0, 0, true);
4340   texclouds1 = gl->genTextureTGA (dirs->getTextures ("clouds1.tga"), 0, -1, 1, true);
4341   texclouds2 = gl->genTextureTGA (dirs->getTextures ("clouds2.tga"), 0, 4, 1, true);
4342   texclouds3 = gl->genTextureTGA (dirs->getTextures ("clouds3.tga"), 0, 6, 1, true);
4343   texradar1 = gl->genTextureTGA (dirs->getTextures ("radar2.tga"), 0, -1, 0, true);
4344   texradar2 = gl->genTextureTGA (dirs->getTextures ("radar1.tga"), 0, -1, 0, true);
4345   texarrow = gl->genTextureTGA (dirs->getTextures ("arrow.tga"), 0, -1, 0, true);
4346 
4347   display ("Loading Fonts", LOG_ALL);
4348   font1 = new Font (dirs->getTextures ("font1.tga"), 32, '!', 64);
4349 //  font1 = new Font (dirs->getTextures ("font3.tga"), 37, '!', 100);
4350   font2 = new Font (dirs->getTextures ("font2.tga"), 32, '!', 64);
4351 
4352   display ("Loading 3ds models:", LOG_ALL);
4353   display (" * gl-16.3ds", LOG_ALL);
4354   g_Load3ds.Import3DS (&model_fig, dirs->getModels ("gl-16.3ds"));
4355   model_fig.setName ("FALCON");
4356   display (" * gl-15.3ds", LOG_ALL);
4357   g_Load3ds.Import3DS (&model_figa, dirs->getModels ("gl-15.3ds"));
4358   model_figa.setName ("SWALLOW");
4359   display (" * gl-14c.3ds", LOG_ALL);
4360   g_Load3ds.Import3DS (&model_figb, dirs->getModels ("gl-14c.3ds"));
4361   model_figb.setName ("HAWK");
4362   display (" * gl-14d.3ds", LOG_ALL);
4363   g_Load3ds.Import3DS (&model_figc, dirs->getModels ("gl-14d.3ds"));
4364   model_figc.setName ("HAWK II");
4365   display (" * gl-21b.3ds", LOG_ALL);
4366   g_Load3ds.Import3DS (&model_figd, dirs->getModels ("gl-21b.3ds"));
4367   model_figd.setName ("BUZZARD");
4368   display (" * gl-21.3ds", LOG_ALL);
4369   g_Load3ds.Import3DS (&model_fige, dirs->getModels ("gl-21.3ds"));
4370   model_fige.setName ("CROW");
4371   display (" * gl-14b.3ds", LOG_ALL);
4372   g_Load3ds.Import3DS (&model_figf, dirs->getModels ("gl-14b.3ds"));
4373   model_figf.setName ("PHOENIX");
4374   display (" * gl-14.3ds", LOG_ALL);
4375   g_Load3ds.Import3DS (&model_figg, dirs->getModels ("gl-14.3ds"));
4376   model_figg.setName ("RED ARROW");
4377   display (" * gl-29.3ds", LOG_ALL);
4378   g_Load3ds.Import3DS (&model_figh, dirs->getModels ("gl-29.3ds"));
4379   model_figh.setName ("BLACKBIRD");
4380   model_figh.scaleTexture (0.3, 0.3);
4381   display (" * gl-50.3ds", LOG_ALL);
4382   g_Load3ds.Import3DS (&model_figi, dirs->getModels ("gl-50.3ds"));
4383   model_figi.setName ("STORM");
4384   display (" * transp2.3ds", LOG_ALL);
4385   g_Load3ds.Import3DS (&model_figt, dirs->getModels ("transp2.3ds"));
4386   model_figt.setName ("TRANSPORT");
4387   display (" * transp4.3ds", LOG_ALL);
4388   g_Load3ds.Import3DS (&model_figu, dirs->getModels ("transp4.3ds"));
4389   model_figu.setName ("TRANSPORT");
4390 
4391   // cannon at daylight
4392   float cannoncube = 0.025;
4393   display (" * cannon1.3ds", LOG_ALL);
4394   g_Load3ds.Import3DS (&model_cannon1, dirs->getModels ("cannon1.3ds"));
4395   model_cannon1.cubex = cannoncube; model_cannon1.cubey = cannoncube; model_cannon1.cubez = cannoncube;
4396   display (" * cannon1b.3ds", LOG_ALL);
4397   g_Load3ds.Import3DS (&model_cannon1b, dirs->getModels ("cannon1b.3ds"));
4398   model_cannon1b.cubex = cannoncube; model_cannon1b.cubey = cannoncube; model_cannon1b.cubez = cannoncube;
4399 
4400   // cannon at night
4401   display (" * cannon2.3ds", LOG_ALL);
4402   g_Load3ds.Import3DS (&model_cannon2, dirs->getModels ("cannon2.3ds"));
4403   model_cannon2.nolight = true;
4404   model_cannon2.alpha = true;
4405   for (i = 0; i < 4; i ++)
4406   {
4407     model_cannon2.object [0]->vertex [i].color.c [0] = 255;
4408     model_cannon2.object [0]->vertex [i].color.c [1] = 255;
4409     model_cannon2.object [0]->vertex [i].color.c [2] = 0;
4410     model_cannon2.object [0]->vertex [i].color.c [3] = 255;
4411   }
4412   model_cannon2.object [0]->vertex [1].color.c [3] = 50;
4413   model_cannon2.object [0]->vertex [2].color.c [3] = 50;
4414   model_cannon2.cubex = cannoncube; model_cannon2.cubey = cannoncube; model_cannon2.cubez = cannoncube;
4415 
4416   display (" * cannon2b.3ds", LOG_ALL);
4417   g_Load3ds.Import3DS (&model_cannon2b, dirs->getModels ("cannon2b.3ds"));
4418   model_cannon2b.nolight = true;
4419   model_cannon2b.alpha = true;
4420   for (int i2 = 0; i2 < 2; i2 ++)
4421   {
4422     for (i = 0; i < 4; i ++)
4423     {
4424       model_cannon2b.object [i2]->vertex [i].color.c [0] = 255;
4425       model_cannon2b.object [i2]->vertex [i].color.c [1] = 255;
4426       model_cannon2b.object [i2]->vertex [i].color.c [2] = 0;
4427       model_cannon2b.object [i2]->vertex [i].color.c [3] = 255;
4428     }
4429     model_cannon2b.object [i2]->vertex [1].color.c [3] = 50;
4430     model_cannon2b.object [i2]->vertex [2].color.c [3] = 50;
4431   }
4432   model_cannon2b.cubex = cannoncube; model_cannon2b.cubey = cannoncube; model_cannon2b.cubez = cannoncube;
4433 
4434   display (" * flare1.3ds", LOG_ALL);
4435   g_Load3ds.Import3DS (&model_flare1, dirs->getModels ("flare1.3ds"));
4436   model_flare1.setName ("FLARE");
4437   model_flare1.alpha = true;
4438   model_flare1.nolight = true;
4439   display (" * chaff1.3ds", LOG_ALL);
4440   g_Load3ds.Import3DS (&model_chaff1, dirs->getModels ("chaff1.3ds"));
4441   model_chaff1.setName ("CHAFF");
4442   model_chaff1.alpha = true;
4443   model_chaff1.nolight = true;
4444   display (" * missile1.3ds", LOG_ALL);
4445   g_Load3ds.Import3DS (&model_missile1, dirs->getModels ("missile1.3ds"));
4446   model_missile1.setName ("AAM HS MK1");
4447   display (" * missile2.3ds", LOG_ALL);
4448   g_Load3ds.Import3DS (&model_missile2, dirs->getModels ("missile2.3ds"));
4449   model_missile2.setName ("AAM HS MK2");
4450   display (" * missile3.3ds", LOG_ALL);
4451   g_Load3ds.Import3DS (&model_missile3, dirs->getModels ("missile3.3ds"));
4452   model_missile3.setName ("AAM HS MK3");
4453   display (" * missile4.3ds", LOG_ALL);
4454   g_Load3ds.Import3DS (&model_missile4, dirs->getModels ("missile4.3ds"));
4455   model_missile4.setName ("AGM MK1");
4456   display (" * missile5.3ds", LOG_ALL);
4457   g_Load3ds.Import3DS (&model_missile5, dirs->getModels ("missile5.3ds"));
4458   model_missile5.setName ("AGM MK2");
4459   display (" * missile6.3ds", LOG_ALL);
4460   g_Load3ds.Import3DS (&model_missile6, dirs->getModels ("missile6.3ds"));
4461   model_missile6.setName ("DFM");
4462   display (" * missile7.3ds", LOG_ALL);
4463   g_Load3ds.Import3DS (&model_missile7, dirs->getModels ("missile7.3ds"));
4464   model_missile7.setName ("AAM FF MK1");
4465   display (" * missile8.3ds", LOG_ALL);
4466   g_Load3ds.Import3DS (&model_missile8, dirs->getModels ("missile8.3ds"));
4467   model_missile8.setName ("AAM FF MK2");
4468   display (" * flak2.3ds", LOG_ALL);
4469   g_Load3ds.Import3DS (&model_flak1, dirs->getModels ("flak2.3ds"));
4470   model_flak1.setName ("SA CANNON");
4471   display (" * flarak1.3ds", LOG_ALL);
4472   g_Load3ds.Import3DS (&model_flarak1, dirs->getModels ("flarak1.3ds"));
4473   model_flarak1.setName ("SAM");
4474   display (" * ship1.3ds", LOG_ALL);
4475   g_Load3ds.Import3DS (&model_ship1, dirs->getModels ("ship1.3ds"));
4476   model_ship1.setName ("CRUISER");
4477   display (" * tent1.3ds", LOG_ALL);
4478   g_Load3ds.Import3DS (&model_tent1, dirs->getModels ("tent1.3ds"));
4479   model_tent1.setName ("TENT");
4480   display (" * gl-117.3ds", LOG_ALL);
4481   g_Load3ds.Import3DS (&model_gl117, dirs->getModels ("gl-117.3ds"));
4482   model_gl117.displaylist = false;
4483   display (" * tank1.3ds", LOG_ALL);
4484   g_Load3ds.Import3DS (&model_tank1, dirs->getModels ("tank1.3ds"));
4485   model_tank1.setName ("WIESEL");
4486   model_tank1.scaleTexture (0.5, 0.5);
4487   display (" * container1.3ds", LOG_ALL);
4488   g_Load3ds.Import3DS (&model_container1, dirs->getModels ("container1.3ds"));
4489   model_container1.setName ("CONTAINER");
4490   display (" * ship2.3ds", LOG_ALL);
4491   g_Load3ds.Import3DS (&model_ship2, dirs->getModels ("ship2.3ds"));
4492   model_ship2.setName ("LIGHT DESTROYER");
4493   display (" * truck1.3ds", LOG_ALL);
4494   g_Load3ds.Import3DS (&model_truck1, dirs->getModels ("truck1.3ds"));
4495   model_truck1.setName ("TRUCK");
4496   display (" * truck2.3ds", LOG_ALL);
4497   g_Load3ds.Import3DS (&model_truck2, dirs->getModels ("truck2.3ds"));
4498   model_truck2.setName ("TRUCK");
4499   display (" * trsam.3ds", LOG_ALL);
4500   g_Load3ds.Import3DS (&model_trsam, dirs->getModels ("trsam.3ds"));
4501   model_trsam.setName ("MOBILE SAM");
4502   display (" * pickup1.3ds", LOG_ALL);
4503   g_Load3ds.Import3DS (&model_pickup1, dirs->getModels ("pickup1.3ds"));
4504   model_pickup1.setName ("PICKUP");
4505   display (" * pickup2.3ds", LOG_ALL);
4506   g_Load3ds.Import3DS (&model_pickup2, dirs->getModels ("pickup2.3ds"));
4507   model_pickup2.setName ("PICKUP");
4508   display (" * tank2.3ds", LOG_ALL);
4509   g_Load3ds.Import3DS (&model_tank2, dirs->getModels ("tank2.3ds"));
4510   model_tank2.setName ("PANTHER");
4511   model_tank2.scaleTexture (0.5, 0.5);
4512   display (" * tent4.3ds", LOG_ALL);
4513   g_Load3ds.Import3DS (&model_tent4, dirs->getModels ("tent4.3ds"));
4514   model_tent4.setName ("BIG TENT");
4515   display (" * hall1.3ds", LOG_ALL);
4516   g_Load3ds.Import3DS (&model_hall1, dirs->getModels ("hall1.3ds"));
4517   model_hall1.setName ("HALL");
4518   display (" * hall2.3ds", LOG_ALL);
4519   g_Load3ds.Import3DS (&model_hall2, dirs->getModels ("hall2.3ds"));
4520   model_hall2.setName ("HALL");
4521   display (" * oilrig.3ds", LOG_ALL);
4522   g_Load3ds.Import3DS (&model_oilrig, dirs->getModels ("oilrig.3ds"));
4523   model_oilrig.setName ("OILRIG");
4524   model_oilrig.alpha = true;
4525   display (" * egg.3ds", LOG_ALL);
4526   g_Load3ds.Import3DS (&model_egg, dirs->getModels ("egg.3ds"));
4527   model_egg.scaleTexture (0.08, 0.08);
4528   model_egg.setName ("COMPLEX");
4529   display (" * radar.3ds", LOG_ALL);
4530   g_Load3ds.Import3DS (&model_radar, dirs->getModels ("radar.3ds"));
4531   model_radar.setName ("RADAR");
4532   display (" * mine1.3ds", LOG_ALL);
4533   g_Load3ds.Import3DS (&model_mine1, dirs->getModels ("mine1.3ds"));
4534   model_mine1.setName ("MINE");
4535   display (" * aster1.3ds", LOG_ALL);
4536   g_Load3ds.Import3DS (&model_aster1, dirs->getModels ("aster1.3ds"));
4537   model_aster1.setName ("ASTEROID");
4538   display (" * base1.3ds", LOG_ALL);
4539   g_Load3ds.Import3DS (&model_base1, dirs->getModels ("base1.3ds"));
4540   model_base1.setName ("MOON BASE");
4541   display (" * barrier.3ds", LOG_ALL);
4542   g_Load3ds.Import3DS (&model_barrier1, dirs->getModels ("barrier.3ds"));
4543   model_barrier1.setName ("MOON BASE");
4544   model_barrier1.scaleTexture (10, 10);
4545   model_barrier1.alpha = true;
4546   display (" * rubble.3ds", LOG_ALL);
4547   g_Load3ds.Import3DS (&model_rubble1, dirs->getModels ("rubble.3ds"));
4548   model_base1.setName ("RUBBLE");
4549   display (" * depot1.3ds", LOG_ALL);
4550   g_Load3ds.Import3DS (&model_depot1, dirs->getModels ("depot1.3ds"));
4551   model_depot1.setName ("DEPOT");
4552   model_depot1.scaleTexture (2, 2);
4553   g_Load3ds.Import3DS (&model_house1, dirs->getModels ("house1.3ds"));
4554   model_house1.setName ("HOUSE");
4555 
4556   setMissiles (&model_fig);
4557   setMissiles (&model_figa);
4558   setMissiles (&model_figb);
4559   setMissiles (&model_figc);
4560   setMissiles (&model_figd);
4561   setMissiles (&model_fige);
4562   setMissiles (&model_figf);
4563   setMissiles (&model_figg);
4564   setMissiles (&model_figh);
4565   setMissiles (&model_figi);
4566 
4567   // enable Z-Buffer
4568   glEnable (GL_DEPTH_TEST);
4569 
4570   // fill polygons (GL_LINE for wireframe models)
4571   glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
4572 
4573   display ("Setting up world geometry", LOG_ALL);
4574   space = new Space ();
4575   space->drawlight = true;
4576   clip1 = space->z1;
4577   clip2 = space->z2;
4578   clip1->x = -ZOOM;
4579   clip1->y = -ZOOM;
4580   clip1->z = -ZOOM;
4581   clip2->x = ZOOM;
4582   clip2->y = ZOOM;
4583   clip2->z = ZOOM;
4584 
4585   // prepare intro
4586   init_reshape ();
4587 
4588   tl.x = 0.0;
4589   tl.y = 0.0;
4590   tl.z = -5.0;
4591   tl2.x = 0.0;
4592   tl2.y = 0.0;
4593   tl2.z = -5.0;
4594   rot.a = 270;
4595   rot2.c = 90;
4596   rot2.a = 270;
4597   rot2.b = 270;
4598   initexplode = 0;
4599   initexplode1 = 0;
4600 
4601   textitle = new CTexture ();
4602   textitle = gl->genTextureTGA (dirs->getTextures ("patents.tga"), 0, 0, 0, true);
4603 
4604   sungamma = 60;
4605   setLightSource (60);
4606 
4607   event_setAntialiasing ();
4608 
4609   glLightModeli (GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
4610 //  glLightModeli (GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
4611   glEnable (GL_LIGHT0);
4612   glEnable (GL_LIGHTING);
4613   glEnable (GL_COLOR_MATERIAL);
4614 
4615   glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
4616 }
4617 
init_key(int key,int x,int y)4618 void init_key (int key, int x, int y)
4619 {
4620   gl->clearScreen (); // exit intro
4621   myInit ();
4622   switch_menu ();
4623   fplayer->ai = true;
4624   camera = 5;
4625 #ifndef USE_GLUT
4626   starttime = SDL_GetTicks ();
4627 #else
4628   starttime = glutGet (GLUT_ELAPSED_TIME);
4629 #endif
4630 }
4631 
init_mouse(int button,int state,int x,int y)4632 void init_mouse (int button, int state, int x, int y)
4633 {
4634   init_key (32, x, y);
4635 }
4636 
4637 const int maxfx = 256;
4638 const int maxfy = 64;
4639 
4640 int heat [maxfy] [maxfx];
4641 int heat2 [maxfy] [maxfx];
4642 
init_display()4643 void init_display ()
4644 {
4645   CVector3 vec;
4646   CColor color (200, 200, 200, 255);
4647 
4648   glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
4649   glMatrixMode (GL_MODELVIEW);
4650   glLoadIdentity ();
4651 
4652   glPushMatrix ();
4653 
4654   glEnable (GL_DEPTH_TEST);
4655   glEnable (GL_LIGHTING);
4656 
4657   // draw fighter
4658   glPushMatrix ();
4659   glTranslatef (0, 0, -5);
4660   model_fig.draw (&vec, &tl, &rot, 1.0, 2.0, initexplode1);
4661   glPopMatrix ();
4662 
4663   glDisable (GL_DEPTH_TEST);
4664   glEnable (GL_BLEND);
4665 
4666   if (inittimer_gl117 > 2000)
4667   {
4668     float xf = 1.3F, yf = 0.65F, zf = 2.0F;
4669     int col = (inittimer_gl117 - 2000) / 2;
4670     if (col < 0 || col > 255) col = 255;
4671     glColor3ub (col, col, col);
4672     glPushMatrix ();
4673     glTranslatef (0, 0.5F, 0);
4674     gl->enableTextures (textitle->textureID);
4675     if (antialiasing)
4676       gl->enableLinearTexture (textitle->textureID);
4677     else
4678       gl->disableLinearTexture (textitle->textureID);
4679     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
4680     glBegin (GL_QUADS);
4681     glTexCoord2d (0, 1);
4682     glVertex3f (-xf, yf, -zf);
4683     glTexCoord2d (1, 1);
4684     glVertex3f (xf, yf, -zf);
4685     glTexCoord2d (1, 0);
4686     glVertex3f (xf, -yf, -zf);
4687     glTexCoord2d (0, 0);
4688     glVertex3f (-xf, -yf, -zf);
4689     glEnd ();
4690     glPopMatrix ();
4691     glDisable (GL_BLEND);
4692   }
4693 
4694   glDisable (GL_LIGHTING);
4695   glPopMatrix ();
4696 
4697   // draw fire (heat array)
4698   glDisable (GL_DEPTH_TEST);
4699   glEnable (GL_BLEND);
4700 
4701   float xf = 1.75F, yf = 1.78F, zf = 2.0F;
4702   glPushMatrix ();
4703   gl->enableTextures (5000);
4704   glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
4705   glBegin (GL_QUADS);
4706   glTexCoord2d (0, 1);
4707   glVertex3f (-xf, -yf, -zf);
4708   glTexCoord2d (1, 1);
4709   glVertex3f (xf, -yf, -zf);
4710   glTexCoord2d (1, 0);
4711   glVertex3f (xf, yf, -zf);
4712   glTexCoord2d (0, 0);
4713   glVertex3f (-xf, yf, -zf);
4714   glEnd ();
4715   glPopMatrix ();
4716   glDisable (GL_BLEND);
4717 
4718   font2->drawText (20, -20, -3, VERSIONSTRING, &color);
4719 }
4720 
genFireLine()4721 void genFireLine ()
4722 {
4723   int i, i2;
4724   for (i = 0; i < maxfx; i ++)
4725   {
4726     heat [maxfy - 1] [i] = myrandom (400);
4727   }
4728   for (i = 0; i < 5; i ++)
4729   {
4730     int r = myrandom (maxfx - 7) + 3;
4731     for (i2 = -3; i2 <= 3; i2 ++)
4732     {
4733       heat [maxfy - 1] [r + i2] = 1200; // insert hot spots at the bottom line
4734     }
4735   }
4736 }
4737 
4738 unsigned char firetex [maxfx * maxfy * 4];
4739 
proceedFire()4740 void proceedFire ()
4741 {
4742   int i, i2;
4743   for (i = maxfy - 2; i >= 1; i --)
4744     for (i2 = 2; i2 < maxfx - 2; i2 ++)
4745     {
4746       heat2 [i] [i2] = 0 * heat [i + 1] [i2 - 2] + 4 * heat [i + 1] [i2 - 1] + 16 * heat [i + 1] [i2] + 4 * heat [i + 1] [i2 + 1] + 0 * heat [i + 1] [i2 + 2]; // heat diffusion
4747       heat2 [i] [i2] += 0 * heat [i] [i2 - 2] + 4 * heat [i] [i2 - 1] + 16 * heat [i] [i2] + 4 * heat [i] [i2 + 1] + 0 * heat [i] [i2 + 2]; // heat diffusion
4748 	  heat2 [i] [i2] /= 48;
4749       heat2 [i] [i2] -= (int) (300.0F / maxfy); // heat sink
4750       if (heat2 [i] [i2] < 0) heat2 [i] [i2] = 0;
4751     }
4752   memcpy (heat, heat2, maxfx * maxfy * sizeof (int)); // copy back buffer to heat array
4753 
4754 
4755   for (i = 0; i < maxfy; i ++)
4756   {
4757     for (i2 = 0; i2 < maxfx + 1; i2 ++)
4758     {
4759       // rotate through fire colors (white-yellow-red-black-blue-black)
4760       // col in [0...512]
4761       int yind = i;
4762 	    int h = heat [yind] [i2];
4763 	    int b = h * 5;
4764 	    if (h > 30) b = (60 - h) * 5;
4765 	    if (h >= 60) b = 0;
4766 	    h -= 50;
4767       int r = h * 2; // blend out late for red->black
4768       if (r > 255) r = 255;
4769 	    else if (r < 0) r = 0;
4770 	    h -= 127;
4771       int g = h * 2; // blend out for yellow->red
4772       if (g > 255) g = 255;
4773       else if (g < 0) g = 0;
4774 	    h -= 127;
4775       if (h > 0)
4776       {
4777         b = h - 256; // blend out early to get white->yellow
4778         if (b > 255) b = 255;
4779       }
4780       else if (b < 0) b = 0;
4781       int a = r >= b ? r : b; // alpha value: transparent after yellow-red phase
4782       glColor4ub (r, g, b, a);
4783 	    firetex [(i * maxfx + i2) * 4] = r;
4784 	    firetex [(i * maxfx + i2) * 4 + 1] = g;
4785 	    firetex [(i * maxfx + i2) * 4 + 2] = b;
4786 	    firetex [(i * maxfx + i2) * 4 + 3] = a;
4787     }
4788     glEnd ();
4789   }
4790   glPopMatrix ();
4791   glBindTexture (GL_TEXTURE_2D, 5000);
4792   glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4793   glTexImage2D (GL_TEXTURE_2D, 0, 4, maxfx, maxfy, 0, GL_RGBA, GL_UNSIGNED_BYTE, firetex);
4794 }
4795 
4796 int initsynchrotimer = 0;
4797 
init_timer(Uint32 dt)4798 void init_timer (Uint32 dt)
4799 {
4800   inittimer_gl117 += dt;
4801   initsynchrotimer += dt;
4802   if (initsynchrotimer > 20)
4803   {
4804     initsynchrotimer -= 20;
4805     dt = 20;
4806   }
4807   else return;
4808 
4809   int r = myrandom (100);
4810   if (r == 50) r = myrandom (100); // do not optimize this: random number generator initialization
4811 
4812   tl.x = 6.0 * pow (1.5, -(5 + tl.z));
4813   tl.y = (tl.z + 3) * (tl.z + 3) * 0.02 - 0.8; //0.9 * tl.x;
4814   tl.z += 0.14;
4815 
4816   tl2.y = 0.3F;
4817   if (initexplode1 == -1 && tl2.z < 3)
4818   {
4819     tl2.z += 0.25;
4820   }
4821   if (tl2.z < 3)
4822   {
4823     rot2.b -= 20;
4824     if (rot2.b < 0) rot2.b += 360;
4825   }
4826   if (tl.z > -4.0)
4827   {
4828     rot.b ++;
4829   }
4830 
4831   if (inittimer == 0)
4832   {
4833     memset (heat, 0, maxfx * maxfy * sizeof (int));
4834     memset (heat2, 0, maxfx * maxfy * sizeof (int));
4835   }
4836 
4837   genFireLine ();
4838   proceedFire ();
4839 
4840   if (inittimer >= 75)
4841   {
4842     initexplode1 = -1;
4843   }
4844 
4845   if (inittimer >= 350)
4846   {
4847     initexplode += dt;
4848   }
4849 
4850   if (inittimer >= 400)
4851   {
4852     init_key (27, 0, 0); // switch to menu
4853   }
4854 
4855   inittimer ++;
4856 
4857 #ifdef USE_GLUT
4858   glutPostRedisplay();
4859 #else
4860   sdldisplay = true;
4861 #endif
4862 }
4863 
4864 
4865 
4866 /****************************************************************************
4867   ABSTRACT EVENT BRANCHES
4868 ****************************************************************************/
4869 
myKeyboardFunc(unsigned char uckey,int x,int y)4870 static void myKeyboardFunc (unsigned char uckey, int x, int y)
4871 {
4872   int key = (int) uckey;
4873   if (key >= 'a' && key <= 'z') key = toupper (key);
4874   if (game == GAME_PLAY || game == GAME_PAUSE)
4875     game_key (key, x, y);
4876   else if (game == GAME_INIT)
4877     init_key (key, x, y);
4878   else if (game == GAME_MENU)
4879   {
4880     allmenus.eventKey (key);
4881     menu_key (key, x, y);
4882   }
4883   else if (game == GAME_CREDITS)
4884     credits_key (key, x, y);
4885   else if (game == GAME_CREATE)
4886     create_key (key, x, y);
4887   else if (game == GAME_JOIN)
4888     join_key (key, x, y);
4889   else if (game == GAME_MISSION)
4890     mission_key (key, x, y);
4891   else if (game == GAME_STATS)
4892     stats_key (key, x, y);
4893   else if (game == GAME_FAME)
4894     fame_key (key, x, y);
4895   else if (game == GAME_FIGHTER)
4896     fighter_key (key, x, y);
4897   else if (game == GAME_FINISH)
4898     finish_key (key, x, y);
4899   else if (game == GAME_QUIT)
4900     quit_key (key, x, y);
4901 }
4902 
myKeyboardFuncUp(unsigned char key,int x,int y)4903 static void myKeyboardFuncUp (unsigned char key, int x, int y)
4904 {
4905   if (game == GAME_PLAY || game == GAME_PAUSE)
4906     game_keyup ((int) key, x, y);
4907 }
4908 
mySpecialFunc(int key,int x,int y)4909 static void mySpecialFunc (int key, int x, int y)
4910 {
4911   if (game == GAME_PLAY || game == GAME_PAUSE)
4912     game_key (key + 256, x, y);
4913   else if (game == GAME_MENU)
4914   {
4915     allmenus.eventSpecial (key);
4916   }
4917 }
4918 
mySpecialFuncUp(int key,int x,int y)4919 static void mySpecialFuncUp (int key, int x, int y)
4920 {
4921   if (game == GAME_PLAY || game == GAME_PAUSE)
4922     game_keyup (key + 256, x, y);
4923 }
4924 
myPassiveRelMotionFunc(int xrel,int yrel)4925 static void myPassiveRelMotionFunc (int xrel, int yrel)
4926 {
4927   if (game == GAME_PLAY)
4928     if (controls == CONTROLS_MOUSE)
4929       game_mouserelmotion (xrel, yrel);
4930 }
4931 
myPassiveMotionFunc(int x,int y)4932 static void myPassiveMotionFunc (int x, int y)
4933 {
4934   mousex = x; mousey = y;
4935   if (game == GAME_PLAY)
4936     game_mousemotion (x, y);
4937   else if (game == GAME_MENU)
4938   {
4939     allmenus.eventMouse (x, y, 0);
4940     menu_mouse (-1, -1, x, y);
4941   }
4942   else if (game == GAME_STATS)
4943   {
4944     statsmenu.eventMouse (x, y, 0);
4945     stats_mouse (-1, -1, x, y);
4946   }
4947   else if (game == GAME_MISSION)
4948   {
4949     missionmenu.eventMouse (x, y, 0);
4950     mission_mouse (-1, -1, x, y);
4951   }
4952   else if (game == GAME_FAME)
4953   {
4954     famemenu.eventMouse (x, y, 0);
4955     fame_mouse (-1, -1, x, y);
4956   }
4957   else if (game == GAME_FIGHTER)
4958   {
4959     fightermenu.eventMouse (x, y, 0);
4960     fighter_mouse (-1, -1, x, y);
4961   }
4962   else if (game == GAME_CREATE)
4963     create_mouse (-1, -1, x, y);
4964   else if (game == GAME_JOIN)
4965     join_mouse (-1, -1, x, y);
4966   else if (game == GAME_QUIT)
4967   {
4968     quitmenu.eventMouse (x, y, 0);
4969     quit_mouse (-1, -1, x, y);
4970   }
4971 }
4972 
myMouseFunc(int button,int state,int x,int y)4973 static void myMouseFunc (int button, int state, int x, int y)
4974 {
4975 #ifdef USE_GLUT
4976   button ++;
4977 #endif
4978   if (game == GAME_PLAY)
4979   {
4980     if (controls == CONTROLS_MOUSE)
4981       game_mouse (button, state, x, y);
4982   }
4983   else if (game == GAME_INIT)
4984   {
4985     init_mouse (button, state, x, y);
4986   }
4987   else if (game == GAME_MENU)
4988   {
4989 #ifdef USE_GLUT
4990     if (state == 0)
4991 #endif
4992     allmenus.eventMouse (x, y, button);
4993     menu_mouse (button, state, x, y);
4994   }
4995   else if (game == GAME_MISSION)
4996   {
4997 #ifdef USE_GLUT
4998     if (state == 0)
4999 #endif
5000     missionmenu.eventMouse (x, y, button);
5001     mission_mouse (button, state, x, y);
5002   }
5003   else if (game == GAME_STATS)
5004   {
5005 #ifdef USE_GLUT
5006     if (state == 0)
5007 #endif
5008     statsmenu.eventMouse (x, y, button);
5009     stats_mouse (button, state, x, y);
5010   }
5011   else if (game == GAME_FAME)
5012   {
5013 #ifdef USE_GLUT
5014     if (state == 0)
5015 #endif
5016     famemenu.eventMouse (x, y, button);
5017     fame_mouse (button, state, x, y);
5018   }
5019   else if (game == GAME_FIGHTER)
5020   {
5021 #ifdef USE_GLUT
5022     if (state == 0)
5023 #endif
5024     fightermenu.eventMouse (x, y, button);
5025     fighter_mouse (button, state, x, y);
5026   }
5027   else if (game == GAME_CREATE)
5028   {
5029     create_mouse (button, state, x, y);
5030   }
5031   else if (game == GAME_JOIN)
5032   {
5033     join_mouse (button, state, x, y);
5034   }
5035   else if (game == GAME_QUIT)
5036   {
5037 #ifdef USE_GLUT
5038     if (state == 0)
5039 #endif
5040     quitmenu.eventMouse (x, y, button);
5041     quit_mouse (button, state, x, y);
5042   }
5043   else if (game == GAME_CREDITS)
5044   {
5045 #ifdef USE_GLUT
5046     if (state == 0)
5047 #endif
5048     credits_mouse (button, state, x, y);
5049   }
5050 }
5051 
myReshapeFunc(int width,int height)5052 static void myReshapeFunc (int width, int height)
5053 {
5054   ::width = width;
5055   ::height = height;
5056   ::wantwidth = width;
5057   ::wantheight = height;
5058   if (game == GAME_PLAY || game == GAME_PAUSE)
5059     game_reshape ();
5060   else if (game == GAME_MENU || game == GAME_MISSION || game == GAME_QUIT)
5061     menu_reshape ();
5062   else if (game == GAME_INIT)
5063     init_reshape ();
5064   else if (game == GAME_CREDITS || game == GAME_FINISH)
5065     credits_reshape ();
5066   else if (game == GAME_STATS)
5067     stats_reshape ();
5068 }
5069 
myDisplayFunc()5070 static void myDisplayFunc ()
5071 {
5072   if (game == GAME_INIT)
5073   {
5074     init_display ();
5075     game_view ();
5076   }
5077   else if (game == GAME_PLAY)
5078   {
5079     game_display ();
5080     game_view ();
5081   }
5082   else if (game == GAME_PAUSE)
5083   {
5084     game_display ();
5085     pause_display ();
5086     game_view ();
5087   }
5088   else if (game == GAME_MENU)
5089   {
5090     if (camera == 50) camera = 0;
5091     game_display ();
5092     menu_display ();
5093     game_view ();
5094   }
5095   else if (game == GAME_CREDITS)
5096   {
5097     if (camera == 50) camera = 0;
5098     game_display ();
5099     credits_display ();
5100     game_view ();
5101   }
5102   else if (game == GAME_MISSION)
5103   {
5104     if (camera == 50) camera = 0;
5105     game_display ();
5106     mission_display ();
5107     game_view ();
5108   }
5109   else if (game == GAME_STATS)
5110   {
5111     if (camera == 50) camera = 0;
5112     game_display ();
5113     stats_display ();
5114     game_view ();
5115   }
5116   else if (game == GAME_FAME)
5117   {
5118     game_display ();
5119     fame_display ();
5120     game_view ();
5121   }
5122   else if (game == GAME_FIGHTER)
5123   {
5124     game_display ();
5125     fighter_display ();
5126     game_view ();
5127   }
5128   else if (game == GAME_CREATE)
5129   {
5130     create_display ();
5131     game_view ();
5132   }
5133   else if (game == GAME_JOIN)
5134   {
5135     join_display ();
5136     game_view ();
5137   }
5138   else if (game == GAME_FINISH)
5139   {
5140     if (camera == 50) camera = 0;
5141     game_display ();
5142     finish_display ();
5143     game_view ();
5144   }
5145   else if (game == GAME_QUIT)
5146   {
5147     game_display ();
5148     quit_display ();
5149     game_view ();
5150   }
5151 }
5152 
myIdleFunc()5153 static void myIdleFunc ()
5154 {
5155 #ifdef USE_GLUT
5156   glutPostRedisplay ();
5157 #endif
5158 }
5159 
myJoystickAxisFunc(int x,int y,int t,int r)5160 static void myJoystickAxisFunc (int x, int y, int t, int r)
5161 {
5162   if (game == GAME_PLAY)
5163   {
5164     if (controls == CONTROLS_JOYSTICK)
5165       game_joystickaxis (x, y, t, r);
5166   }
5167 }
5168 
myJoystickButtonFunc(int button)5169 static void myJoystickButtonFunc (int button)
5170 {
5171   if (game == GAME_PLAY)
5172   {
5173     if (controls == CONTROLS_JOYSTICK)
5174       game_joystickbutton (button);
5175   }
5176   else if (game == GAME_MENU)
5177   {
5178     allmenus.eventJoystick (button);
5179   }
5180 }
5181 
myJoystickHatFunc(int hat)5182 static void myJoystickHatFunc (int hat)
5183 {
5184   int normhat = hat;
5185 #ifndef USE_GLUT
5186   if (hat % 1000 == SDL_HAT_RIGHT) normhat = 100;
5187   if (hat % 1000 == SDL_HAT_UP) normhat = 101;
5188   if (hat % 1000 == SDL_HAT_LEFT) normhat = 102;
5189   if (hat % 1000 == SDL_HAT_DOWN) normhat = 103;
5190   normhat += (hat / 1000) * 1000;
5191 #endif
5192   if (game == GAME_PLAY)
5193   {
5194     if (controls == CONTROLS_JOYSTICK)
5195       game_joystickhat (normhat);
5196   }
5197   else if (game == GAME_MENU)
5198   {
5199     allmenus.eventJoystick (normhat);
5200   }
5201 }
5202 
myTimerFunc(int value)5203 static void myTimerFunc (int value)
5204 {
5205   Uint32 akttime, dt;
5206 #ifndef USE_GLUT
5207     akttime = SDL_GetTicks ();
5208 #else
5209     akttime = glutGet (GLUT_ELAPSED_TIME);
5210 #endif
5211   if (lasttime == 0) dt = 1;
5212   else dt = akttime - lasttime;
5213   lasttime = akttime;
5214 
5215   if (dt > 1000)
5216   {
5217     dt = 1;
5218     if (game == GAME_PLAY && multiplayer)
5219     {
5220       display ("Out of sync", LOG_ERROR);
5221       switch_menu ();
5222     }
5223   }
5224 
5225   if (game == GAME_PLAY)
5226     game_timer (dt);
5227   else if (game == GAME_INIT)
5228     init_timer (dt);
5229   else if (game == GAME_MENU)
5230   {
5231     if (!missionactive)
5232       game_timer (dt);
5233     menu_timer (dt);
5234   }
5235   else if (game == GAME_CREDITS)
5236   {
5237     if (!missionactive)
5238       game_timer (dt);
5239     credits_timer (dt);
5240   }
5241   else if (game == GAME_CREATE)
5242     create_timer (dt);
5243   else if (game == GAME_JOIN)
5244     join_timer (dt);
5245   else if (game == GAME_MISSION)
5246   {
5247     if (!missionactive)
5248       game_timer (dt);
5249     mission_timer (dt);
5250   }
5251   else if (game == GAME_STATS)
5252     stats_timer (dt);
5253   else if (game == GAME_FAME)
5254   {
5255     if (!missionactive)
5256       game_timer (dt);
5257     mission_timer (dt);
5258   }
5259   else if (game == GAME_FIGHTER)
5260   {
5261     if (!missionactive)
5262       game_timer (dt);
5263     mission_timer (dt);
5264   }
5265   else if (game == GAME_FINISH)
5266     finish_timer (dt);
5267   else if (game == GAME_QUIT)
5268   {
5269     if (!missionactive)
5270       game_timer (dt);
5271     mission_timer (dt);
5272   }
5273 
5274 #ifdef USE_GLUT
5275   glutTimerFunc (1, myTimerFunc, 0); // do as many timer calls as possible
5276 #endif
5277 }
5278 
5279 #ifndef USE_GLUT
5280 
5281 Uint32 nexttime = 0;
5282 
5283 int joystickbutton = -1;
5284 bool joystickfirebutton = false;
5285 
5286 // This loop emulates the glutMainLoop() of GLUT using SDL!!!
sdlMainLoop()5287 void sdlMainLoop ()
5288 {
5289   int sym = 0;
5290   SDL_Event event;
5291 
5292   while (true)
5293   {
5294     while (SDL_PollEvent (&event)) // process events
5295     {
5296       switch (event.type)
5297       {
5298         case SDL_MOUSEMOTION:
5299           myPassiveMotionFunc (event.motion.x, event.motion.y);
5300           if (game == GAME_PLAY && controls == CONTROLS_MOUSE && mouse_relative)
5301           {
5302             fplayer->rolleffect = 0;
5303             fplayer->elevatoreffect = 0;
5304             fplayer->ruddereffect = 0;
5305           }
5306           myPassiveRelMotionFunc (event.motion.xrel, event.motion.yrel);
5307           break;
5308 
5309         case SDL_MOUSEBUTTONDOWN:
5310           myMouseFunc (event.button.button, event.button.state, event.button.x, event.button.y);
5311           break;
5312 
5313         case SDL_KEYDOWN:
5314           if (!event.key.keysym.unicode)
5315             mySpecialFunc (event.key.keysym.sym, 0, 0);
5316           else
5317             myKeyboardFunc (event.key.keysym.sym, 0, 0);
5318           break;
5319 
5320         case SDL_KEYUP:
5321           sym = event.key.keysym.sym;
5322           if (sym == 8 || sym == 9 || sym == 13 || (sym >= 32 && sym <= 'z'))
5323             myKeyboardFuncUp (event.key.keysym.sym, 0, 0);
5324           else
5325             mySpecialFuncUp (event.key.keysym.sym, 0, 0);
5326           break;
5327 
5328         case SDL_JOYAXISMOTION:
5329           if (abs (event.jaxis.value) < 2000)
5330           {
5331             jaxis [event.jaxis.axis + event.jaxis.which * 10] = 0;
5332           }
5333           else
5334           {
5335             if (event.jaxis.value < 0)
5336               event.jaxis.value += 2500;
5337             else
5338               event.jaxis.value -= 2500;
5339             jaxis [event.jaxis.axis + event.jaxis.which * 10] = (int) event.jaxis.value * 32768 / 30268;
5340           }
5341           break;
5342 
5343         case SDL_JOYBUTTONDOWN:
5344           joystickbutton = event.jbutton.button + event.jbutton.which * 1000;
5345           if (joystickbutton == (int) joystick_firecannon)
5346             joystickfirebutton = true;
5347           myJoystickButtonFunc (joystickbutton);
5348           joystickbutton = -1;
5349           break;
5350 
5351         case SDL_JOYBUTTONUP:
5352           joystickbutton = event.jbutton.button + event.jbutton.which * 1000;
5353           if (joystickbutton == (int) joystick_firecannon)
5354             joystickfirebutton = false;
5355           joystickbutton = -1;
5356           break;
5357 
5358         case SDL_JOYHATMOTION:
5359           myJoystickHatFunc (event.jhat.value + event.jhat.which * 1000);
5360           break;
5361 
5362         case SDL_ACTIVEEVENT:
5363           sdlreshape = true;
5364           sdldisplay = true;
5365           break;
5366       }
5367     }
5368 
5369     if (controls == CONTROLS_JOYSTICK)
5370     {
5371       int x = jaxis [getJoystickAxisIndex (joystick_aileron)];
5372       int y = jaxis [getJoystickAxisIndex (joystick_elevator)];
5373       int rudder = jaxis [getJoystickAxisIndex (joystick_rudder)];
5374       int throttle = jaxis [getJoystickAxisIndex (joystick_throttle)];
5375       myJoystickAxisFunc (x, y, rudder, throttle);
5376       view_x = (float) jaxis [getJoystickAxisIndex (joystick_view_x)]/(-328.0);
5377       view_y = (float) jaxis [getJoystickAxisIndex (joystick_view_y)]/(-328.0);
5378       if (joystickfirebutton)
5379         myJoystickButtonFunc (joystick_firecannon);
5380     }
5381 
5382     if (sdldisplay) myDisplayFunc ();
5383     sdldisplay = false;
5384     if (sdlreshape) myReshapeFunc (width, height);
5385     sdlreshape = false;
5386     myTimerFunc (1); // dummy value
5387   }
5388 }
5389 #endif
5390 
5391 
5392 
5393 /****************************************************************************
5394   STARTUP METHODS
5395 ****************************************************************************/
5396 
5397 // common GLUT screen init code, return 0 on error
setGlutScreen(int w,int h,int b,int f)5398 int setGlutScreen (int w, int h, int b, int f)
5399 {
5400   char gamestr [256];
5401   sprintf (gamestr, "%dx%d:%d", w, h, b);
5402   glutGameModeString (gamestr);
5403   if (f)
5404   {
5405     if (glutGameModeGet (GLUT_GAME_MODE_POSSIBLE))
5406     {
5407       glutEnterGameMode ();
5408     }
5409     else
5410     {
5411       return 0;
5412     }
5413   }
5414   else
5415   {
5416     glutInitWindowPosition (0, 0);
5417     glutInitWindowSize (w, h);
5418     glutwindow = glutCreateWindow ("GL-117");
5419     if (glutwindow == GL_FALSE)
5420       return 0;
5421   }
5422   return 1;
5423 }
5424 
5425 // set screen to (width, height, bpp, fullscreen), return 0 on error
setScreen(int w,int h,int b,int f)5426 int setScreen (int w, int h, int b, int f)
5427 {
5428 
5429 #ifdef USE_GLUT
5430 
5431   if (!setGlutScreen (w, h, b, f))
5432   {
5433     b = 16;
5434     if (!setGlutScreen (w, h, b, f))
5435     {
5436       b = 8;
5437       if (!setGlutScreen (w, h, b, f))
5438       {
5439         b = 2;
5440         if (!setGlutScreen (w, h, b, f))
5441         {
5442           return 0;
5443         }
5444       }
5445     }
5446   }
5447 
5448 #else
5449 
5450   Uint32 video_flags;
5451   if (f)
5452   {
5453     video_flags = SDL_OPENGL | SDL_FULLSCREEN;
5454   }
5455   else
5456   {
5457     video_flags = SDL_OPENGL;
5458   }
5459   int rgb_size [3];
5460   switch (b)
5461   {
5462     case 8:
5463       rgb_size [0] = 2;
5464       rgb_size [1] = 3;
5465       rgb_size [2] = 3;
5466       break;
5467     case 15:
5468     case 16:
5469       rgb_size [0] = 5;
5470       rgb_size [1] = 5;
5471       rgb_size [2] = 5;
5472       break;
5473     default:
5474       rgb_size [0] = 8;
5475       rgb_size [1] = 8;
5476       rgb_size [2] = 8;
5477       break;
5478   }
5479   SDL_GL_SetAttribute (SDL_GL_RED_SIZE, rgb_size [0]);
5480   SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, rgb_size [1]);
5481   SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, rgb_size [2]);
5482   SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 16);
5483   SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
5484   if (SDL_SetVideoMode (w, h, b, video_flags) == NULL)
5485   {
5486     if ((b = SDL_VideoModeOK (w, h, b, video_flags)) != 0)
5487     {
5488       b = 16;
5489       SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 5);
5490       SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 5);
5491       SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 5);
5492       if (SDL_SetVideoMode (w, h, b, video_flags) == NULL)
5493       {
5494         b = 8;
5495         SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 2);
5496         SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 3);
5497         SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 3);
5498         if (SDL_SetVideoMode (w, h, b, video_flags) == NULL)
5499         {
5500           return 0;
5501         }
5502       }
5503     }
5504   }
5505 
5506 #endif
5507 
5508   glViewport (0, 0, (GLint) w, (GLint) h);
5509 
5510   // take over results in global variables
5511   width = w;
5512   height = h;
5513   bpp = b;
5514   fullscreen = f;
5515   wantwidth = w; // requested values for next restart
5516   wantheight = h;
5517   wantfullscreen = f;
5518   return 1;
5519 }
5520 
5521 // get approximate speed by drawing polygons (obsolete)
speedTest()5522 int speedTest ()
5523 {
5524   int frames = 0, time2 = 0, time1 = 0;
5525 
5526   glMatrixMode (GL_PROJECTION);
5527   glLoadIdentity ();
5528   gluPerspective (visibleangle, 1.0, nearclippingplane, 20.0); // should be sqrt(2) or 1.5
5529   glPolygonMode (GL_FRONT_AND_BACK, polygonMode);
5530   glMatrixMode (GL_MODELVIEW);
5531   glLoadIdentity ();
5532 
5533   #ifndef USE_GLUT
5534     time1 = SDL_GetTicks ();
5535   #else
5536     time1 = glutGet (GLUT_ELAPSED_TIME);
5537   #endif
5538 
5539   while (time2 - time1 < 1000)
5540   {
5541     frames ++;
5542   #ifndef USE_GLUT
5543     time2 = SDL_GetTicks ();
5544   #else
5545     time2 = glutGet (GLUT_ELAPSED_TIME);
5546   #endif
5547 
5548     glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
5549 
5550     glRotatef (1, 0, 0, 1);
5551     for (float zf = -13; zf <= -3; zf += 0.05)
5552     {
5553       glBegin (GL_QUADS);
5554       glColor4d (255, 0, 0, 255);
5555       glVertex3f (-1, -1, zf);
5556       glVertex3f (-1, 1, zf);
5557       glVertex3f (1, 1, zf);
5558       glVertex3f (1, -1, zf);
5559       glEnd ();
5560     }
5561 
5562 #ifdef USE_GLUT
5563   glutSwapBuffers();
5564 #else
5565   SDL_GL_SwapBuffers ();
5566 #endif
5567 
5568   }
5569   return frames;
5570 }
5571 
5572 bool configinit = false; // has GLUT/SDL already been inited?
5573 
5574 // test screen settings automatically
config_test(int argc,char ** argv)5575 void config_test (int argc, char **argv)
5576 {
5577   display ("No configuration file found. Testing...", LOG_MOST);
5578   int bppi [4];
5579 
5580 #ifdef USE_GLUT // GLUT ONLY
5581   display ("Using GLUT only", LOG_MOST);
5582   glutInit (&argc, argv);
5583   glutInitDisplayMode (GLUT_DEPTH | GLUT_RGB | GLUT_DOUBLE);
5584   configinit = true;
5585 #else // SDL
5586   char buf [STDSIZE];
5587   display ("Using SDL and GLUT", LOG_MOST);
5588   if (SDL_Init (SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0)
5589   {
5590     sprintf (buf, "Couldn't initialize SDL: %s", SDL_GetError ());
5591     display (buf, LOG_FATAL);
5592     exit (EXIT_INIT);
5593   }
5594   configinit = true;
5595 #endif
5596 
5597   int valids = -1; // valid screen mode? (-1 = no mode)
5598   int n = 0;
5599   while (n < 4)
5600   {
5601     if (setScreen (resolution [n] [0], resolution [n] [1], resolution [n] [2], resolution [n] [3]))
5602     {
5603       bppi [n] = bpp; // store bpp setting
5604       valids = n;
5605       break; // first mode found => exit loop
5606     }
5607     else
5608     {
5609       bppi [n] = -1;
5610     }
5611     n ++;
5612   }
5613 
5614   if (valids == -1)
5615   {
5616     display ("No working display modes found! Try editing the file conf yourself. You may not be able to play this game.", LOG_FATAL);
5617     exit (EXIT_INIT);
5618   }
5619 
5620   // start with lowest quality/view settings
5621   quality = 0;
5622   view = 20;
5623   width = resolution [valids] [0];
5624   height = resolution [valids] [1];
5625   bpp = bppi [valids];
5626   fullscreen = resolution [valids] [3];
5627   wantwidth = width; // requested values for next restart
5628   wantheight = height;
5629   wantfullscreen = fullscreen;
5630 }
5631 
5632 // get startup help screen
viewParameters()5633 void viewParameters ()
5634 {
5635   display (" ", LOG_NONE);
5636   display ("Usage: gl-117 [-h -v -dLEVEL]", LOG_NONE);
5637   display (" ", LOG_NONE);
5638   display ("-h: Display this help screen and quit", LOG_NONE);
5639   display ("-v: Display version string and quit", LOG_NONE);
5640   display ("-dLEVEL: Set debug LEVEL to 0=silent...5=log all", LOG_NONE);
5641   display (" ", LOG_NONE);
5642 }
5643 
checkargs(int argc,char ** argv)5644 void checkargs (int argc, char **argv)
5645 {
5646   char buf [STDSIZE]; // temp buffer
5647   int i; // temp counter
5648 
5649   for (i = 1; i < argc; i ++) // for each arg (argument/parameter)
5650   {
5651     if (argv [i] [1] == 'd') // change log/debug level
5652     {
5653       char *ptr = &argv [i] [2];
5654       debuglevel = atoi (ptr);
5655       if (debuglevel < LOG_NONE || debuglevel > LOG_ALL) // look at common.h for the constants
5656       {
5657         display ("Invalid debug level", LOG_FATAL);
5658         viewParameters ();
5659         exit (EXIT_COMMAND);
5660       }
5661       else
5662       {
5663         sprintf (buf, "Entering debug level %d", debuglevel);
5664         display (buf, LOG_MOST);
5665       }
5666     }
5667     else if (argv [i] [1] == 'v') // display version string
5668     {
5669       display (VERSIONSTRING, LOG_NONE);
5670       exit (EXIT_NORMAL);
5671     }
5672     else if (argv [i] [1] == 'h') // display startup help screen
5673     {
5674       viewParameters ();
5675       exit (EXIT_NORMAL);
5676     }
5677     else
5678     {
5679       display ("Invalid command line parameter", LOG_FATAL);
5680       viewParameters ();
5681       exit (EXIT_COMMAND);
5682     }
5683   }
5684 }
5685 
textMouseButton(char * buf,int button)5686 void textMouseButton (char *buf, int button)
5687 {
5688   if (button == 0) strcpy (buf, "NONE");
5689   else sprintf (buf, "BUTTON%d", button);
5690 }
5691 
5692 int campaignstartid;
5693 int trainingstartid;
5694 
callbackReturn(Component * comp,int key)5695 void callbackReturn (Component *comp, int key)
5696 {
5697   switch_game ();
5698 }
5699 
callbackStats(Component * comp,int key)5700 void callbackStats (Component *comp, int key)
5701 {
5702   stats_key (27, 0, 0);
5703 }
5704 
callbackQuitNow(Component * comp,int key)5705 void callbackQuitNow (Component *comp, int key)
5706 {
5707   game_quit ();
5708 }
5709 
callbackSwitchMainMenu(Component * comp,int key)5710 void callbackSwitchMainMenu (Component *comp, int key)
5711 {
5712   switch_menu ();
5713 }
5714 
callbackQuit(Component * comp,int key)5715 void callbackQuit (Component *comp, int key)
5716 {
5717   switch_quit ();
5718 }
5719 
callbackCredits(Component * comp,int key)5720 void callbackCredits (Component *comp, int key)
5721 {
5722   switch_credits ();
5723 }
5724 
callbackPilots(Component * comp,int key)5725 void callbackPilots (Component *comp, int key)
5726 {
5727   switch_fame ();
5728 }
5729 
5730 int currentaxis = 0;
5731 
5732 #ifndef USE_GLUT
callbackJoystickAxis(Component * comp,int key)5733 void callbackJoystickAxis (Component *comp, int key)
5734 {
5735   int i;
5736   int buttonnum = -1;
5737 
5738   // get clicked button's number
5739   for (i = 0; i < 12; i ++)
5740   {
5741     if (comp == controlsmenu [2]->components [i])
5742     {
5743       buttonnum = i;
5744     }
5745   }
5746   if (buttonnum == -1) return;
5747 
5748   // read text from label of button
5749   Label *la = (Label *) controlsmenu [2]->components [buttonnum + 1];
5750 
5751   int joynum = 0;
5752   int joyaxis = 0;
5753   if (la->text [1] == '/') joynum = -1;
5754   else
5755   {
5756     joynum = la->text [0] - 'A';
5757     joyaxis = la->text [2] - '0';
5758   }
5759 
5760   if (key == MOUSE_BUTTON_LEFT)
5761   {
5762     if (joynum == -1)
5763     {
5764       joynum = 0;
5765       joyaxis = 0;
5766     }
5767     else if (joynum >= joysticks) joynum = -1;
5768     else
5769     {
5770       joyaxis ++;
5771       if (joyaxis >= sdljoystickaxes [joynum])
5772       {
5773         joyaxis = 0;
5774         joynum ++;
5775         if (joynum >= joysticks) joynum = -1;
5776       }
5777     }
5778   }
5779   else
5780   {
5781     if (joynum == -1)
5782     {
5783       joynum = joysticks - 1;
5784       joyaxis = sdljoystickaxes [joynum] - 1;
5785     }
5786     else if (joynum >= joysticks) joynum = -1;
5787     else
5788     {
5789       joyaxis --;
5790       if (joyaxis < 0)
5791       {
5792         joynum --;
5793         if (joynum < 0)
5794         {
5795           joynum = -1;
5796           joyaxis = 0;
5797         }
5798         else
5799           joyaxis = sdljoystickaxes [joynum] - 1;
5800       }
5801     }
5802   }
5803 
5804   int *joysetting = NULL;
5805   if (buttonnum == 0) joysetting = &joystick_aileron;
5806   else if (buttonnum == 2) joysetting = &joystick_elevator;
5807   else if (buttonnum == 4) joysetting = &joystick_throttle;
5808   else if (buttonnum == 6) joysetting = &joystick_rudder;
5809   else if (buttonnum == 8) joysetting = &joystick_view_x;
5810   else if (buttonnum == 10) joysetting = &joystick_view_y;
5811 
5812   *joysetting = joynum * 1000 + joyaxis;
5813   char latext [4];
5814   if (joynum >= 0)
5815   {
5816     latext [0] = 'A' + joynum;
5817     latext [1] = 32;
5818     latext [2] = '0' + joyaxis;
5819     latext [3] = 0;
5820     la->setText (latext);
5821   }
5822   else
5823   {
5824     la->setText ("N/A");
5825   }
5826 }
5827 #endif
5828 
callbackSwitchStartMission(Component * comp,int key)5829 void callbackSwitchStartMission (Component *comp, int key)
5830 {
5831   pleaseWait ();
5832   if (!game_levelInit ())
5833   {
5834     switch_menu ();
5835     return;
5836   }
5837   switch_game ();
5838   missionactive = true;
5839 }
5840 
callbackFighterPrev(Component * comp,int key)5841 void callbackFighterPrev (Component *comp, int key)
5842 {
5843   int maxfighter = 6;
5844   Pilot *p = pilots->pilot [pilots->aktpilot];
5845   if (p->mission_state [MISSION_DEPOT] == 1) maxfighter ++;
5846   if (p->mission_state [MISSION_SHIP1] == 1) maxfighter ++;
5847   if (p->mission_state [MISSION_CANYON3] == 1) maxfighter ++;
5848   if (p->mission_state [MISSION_MOON1] == 1) maxfighter ++;
5849   if (key == MOUSE_BUTTON_LEFT)
5850   {
5851     aktfighter --;
5852     if (aktfighter < 0) aktfighter = maxfighter - 1;
5853   }
5854 }
5855 
callbackFighterNext(Component * comp,int key)5856 void callbackFighterNext (Component *comp, int key)
5857 {
5858   int maxfighter = 6;
5859   Pilot *p = pilots->pilot [pilots->aktpilot];
5860   if (p->mission_state [MISSION_DEPOT] == 1) maxfighter ++;
5861   if (p->mission_state [MISSION_SHIP1] == 1) maxfighter ++;
5862   if (p->mission_state [MISSION_CANYON3] == 1) maxfighter ++;
5863   if (p->mission_state [MISSION_MOON1] == 1) maxfighter ++;
5864   if (key == MOUSE_BUTTON_LEFT)
5865   {
5866     aktfighter ++;
5867     if (aktfighter >= maxfighter) aktfighter = 0;
5868   }
5869 }
5870 
callbackFighter(Component * comp,int key)5871 void callbackFighter (Component *comp, int key)
5872 {
5873   switch_fighter ();
5874 }
5875 
setpilotstext()5876 void setpilotstext ()
5877 {
5878   char buf [64];
5879   int i;
5880   sprintf (buf, "     %s %s", pilots->pilot [pilots->aktpilot]->getShortRank (), pilots->pilot [pilots->aktpilot]->name);
5881   ((Label *) submenu [0]->components [1])->setText (buf);
5882   for (i = 0; i < pilots->aktpilots; i ++)
5883   {
5884     sprintf (buf, "     %s %s", pilots->pilot [i]->getShortRank (), pilots->pilot [i]->name);
5885     ((Label *) submenu [0]->components [i + 2])->setText (buf);
5886   }
5887   for (; i < 5; i ++)
5888   {
5889     ((Label *) submenu [0]->components [i + 2])->setText ("N/A");
5890   }
5891 }
5892 
callbackPilotsAdd(Component * comp,int key)5893 void callbackPilotsAdd (Component *comp, int key)
5894 {
5895   char buf [64];
5896   if (key == MOUSE_BUTTON_LEFT)
5897   {
5898     strcpy (buf, ((EditField *) submenu [0]->components [9])->text);
5899     if (strlen (buf) > 0 && pilots->aktpilots < 5)
5900     {
5901       pilots->add (buf);
5902       ((EditField *) submenu [0]->components [9])->setText ("");
5903       setpilotstext ();
5904     }
5905   }
5906 }
5907 
callbackPilotsDelete(Component * comp,int key)5908 void callbackPilotsDelete (Component *comp, int key)
5909 {
5910   if (key == MOUSE_BUTTON_RIGHT)
5911   {
5912     pilots->rm ();
5913     setpilotstext ();
5914   }
5915 }
5916 
callbackPilotsList(Component * comp,int key)5917 void callbackPilotsList (Component *comp, int key)
5918 {
5919   int i;
5920   for (i = 0; i < 5; i ++)
5921   {
5922     if (comp == submenu [0]->components [i + 2])
5923     {
5924       if (i < pilots->aktpilots)
5925       {
5926         pilots->aktpilot = i;
5927         setpilotstext ();
5928       }
5929     }
5930   }
5931 }
5932 
callbackJoystick(Component * comp,int key)5933 void callbackJoystick (Component *comp, int key)
5934 {
5935   int i;
5936   for (i = 12; i < 23; i ++)
5937     if (comp == controlsmenu [0]->components [i])
5938     {
5939       int z = 12;
5940       if (i == z ++) joystick_firecannon = key;
5941       else if (i == z ++) joystick_firemissile = key;
5942       else if (i == z ++) joystick_dropflare = key;
5943       else if (i == z ++) joystick_dropchaff = key;
5944       else if (i == z ++) joystick_selectmissile = key;
5945       else if (i == z ++) joystick_targetnearest = key;
5946       else if (i == z ++) joystick_targetlocking = key;
5947       else if (i == z ++) joystick_targetnext = key;
5948       else if (i == z ++) joystick_targetprevious = key;
5949       else if (i == z ++) joystick_thrustup = key;
5950       else if (i == z ++) joystick_thrustdown = key;
5951     }
5952 }
5953 
callbackMouseDefaults(Component * comp,int key)5954 void callbackMouseDefaults (Component *comp, int key)
5955 {
5956   char buf [256];
5957   mouse_sensitivity = 100;
5958   mouse_reverse = false;
5959   mouse_relative = false;
5960   mouse_autorudder = 30;
5961 
5962   sprintf (buf, "%d%%", mouse_autorudder);
5963   ((Label *) controlsmenu [1]->components [7])->setText (buf);
5964   if (mouse_relative) sprintf (buf, "ON");
5965   else sprintf (buf, "OFF");
5966   ((Label *) controlsmenu [1]->components [5])->setText (buf);
5967   if (mouse_reverse) sprintf (buf, "ON");
5968   else sprintf (buf, "OFF");
5969   ((Label *) controlsmenu [1]->components [3])->setText (buf);
5970   sprintf (buf, "%d%%", mouse_sensitivity);
5971   ((Label *) controlsmenu [1]->components [1])->setText (buf);
5972 }
5973 
callbackMouseAutorudder(Component * comp,int key)5974 void callbackMouseAutorudder (Component *comp, int key)
5975 {
5976   char buf [256];
5977   if (key == MOUSE_BUTTON_LEFT)
5978   {
5979     mouse_autorudder += 10;
5980     if (mouse_autorudder > 100) mouse_autorudder = 0;
5981   }
5982   else
5983   {
5984     mouse_autorudder -= 10;
5985     if (mouse_autorudder < 0) mouse_autorudder = 100;
5986   }
5987   sprintf (buf, "%d%%", mouse_autorudder);
5988   ((Label *) controlsmenu [1]->components [7])->setText (buf);
5989 }
5990 
callbackMouseRelative(Component * comp,int key)5991 void callbackMouseRelative (Component *comp, int key)
5992 {
5993   char buf [256];
5994   mouse_relative = !mouse_relative;
5995   if (mouse_relative) sprintf (buf, "ON");
5996   else sprintf (buf, "OFF");
5997   ((Label *) controlsmenu [1]->components [5])->setText (buf);
5998 }
5999 
callbackMouseReverse(Component * comp,int key)6000 void callbackMouseReverse (Component *comp, int key)
6001 {
6002   char buf [256];
6003   mouse_reverse = !mouse_reverse;
6004   if (mouse_reverse) sprintf (buf, "ON");
6005   else sprintf (buf, "OFF");
6006   ((Label *) controlsmenu [1]->components [3])->setText (buf);
6007 }
6008 
callbackMouseSensitivity(Component * comp,int key)6009 void callbackMouseSensitivity (Component *comp, int key)
6010 {
6011   char buf [256];
6012   if (key == MOUSE_BUTTON_LEFT)
6013   {
6014     mouse_sensitivity += 10;
6015     if (mouse_sensitivity > 200) mouse_sensitivity = 70;
6016   }
6017   else
6018   {
6019     mouse_sensitivity -= 10;
6020     if (mouse_sensitivity < 70) mouse_sensitivity = 200;
6021   }
6022   sprintf (buf, "%d%%", mouse_sensitivity);
6023   ((Label *) controlsmenu [1]->components [1])->setText (buf);
6024 }
6025 
callbackDefaultsJoystick(Component * comp,int key)6026 void callbackDefaultsJoystick (Component *comp, int key)
6027 {
6028   joystick_aileron = 0;
6029   joystick_elevator = 1;
6030   joystick_throttle = 2;
6031   joystick_rudder = 3;
6032   joystick_view_x = 4;
6033   joystick_view_y = 5;
6034 
6035   int z = 1;
6036   ((Label *) controlsmenu [2]->components [z])->setText ("A 0");
6037   z += 2;
6038   ((Label *) controlsmenu [2]->components [z])->setText ("A 1");
6039   z += 2;
6040   ((Label *) controlsmenu [2]->components [z])->setText ("A 2");
6041   z += 2;
6042   ((Label *) controlsmenu [2]->components [z])->setText ("A 3");
6043   z += 2;
6044   ((Label *) controlsmenu [2]->components [z])->setText ("A 4");
6045   z += 2;
6046   ((Label *) controlsmenu [2]->components [z])->setText ("A 5");
6047 
6048   joystick_firecannon = 0;
6049   joystick_firemissile = 2;
6050   joystick_dropflare = 3;
6051   joystick_dropchaff = 3;
6052   joystick_selectmissile = 1;
6053   joystick_targetnearest = 101;
6054   joystick_targetlocking = 103;
6055   joystick_targetnext = 100;
6056   joystick_targetprevious = 102;
6057   joystick_thrustup = 4;
6058   joystick_thrustdown = 5;
6059 
6060   z = 12;
6061   ((EditJoystick *) controlsmenu [2]->components [z ++])->setButton (joystick_firecannon);
6062   ((EditJoystick *) controlsmenu [2]->components [z ++])->setButton (joystick_firemissile);
6063   ((EditJoystick *) controlsmenu [2]->components [z ++])->setButton (joystick_dropflare);
6064   ((EditJoystick *) controlsmenu [2]->components [z ++])->setButton (joystick_dropchaff);
6065   ((EditJoystick *) controlsmenu [2]->components [z ++])->setButton (joystick_selectmissile);
6066   ((EditJoystick *) controlsmenu [2]->components [z ++])->setButton (joystick_targetnearest);
6067   ((EditJoystick *) controlsmenu [2]->components [z ++])->setButton (joystick_targetlocking);
6068   ((EditJoystick *) controlsmenu [2]->components [z ++])->setButton (joystick_targetnext);
6069   ((EditJoystick *) controlsmenu [2]->components [z ++])->setButton (joystick_targetprevious);
6070   ((EditJoystick *) controlsmenu [2]->components [z ++])->setButton (joystick_thrustup);
6071   ((EditJoystick *) controlsmenu [2]->components [z ++])->setButton (joystick_thrustdown);
6072 }
6073 
callbackDefaults(Component * comp,int key)6074 void callbackDefaults (Component *comp, int key)
6075 {
6076   key_firecannon = 32;
6077   key_firemissile = 13;
6078   key_dropflare = 'F';
6079   key_dropchaff = 'C';
6080   key_selectmissile = 'M';
6081   key_targetnearest = 'E';
6082   key_targetlocking = 'L';
6083   key_targetnext = 'N';
6084   key_targetprevious = 'P';
6085   key_thrustup = 'S';
6086   key_thrustdown = 'X';
6087 
6088   int z = 5;
6089   ((EditKey *) controlsmenu [0]->components [z ++])->setKey (key_firecannon);
6090   ((EditKey *) controlsmenu [0]->components [z ++])->setKey (key_firemissile);
6091   ((EditKey *) controlsmenu [0]->components [z ++])->setKey (key_dropflare);
6092   ((EditKey *) controlsmenu [0]->components [z ++])->setKey (key_dropchaff);
6093   ((EditKey *) controlsmenu [0]->components [z ++])->setKey (key_selectmissile);
6094   ((EditKey *) controlsmenu [0]->components [z ++])->setKey (key_targetnearest);
6095   ((EditKey *) controlsmenu [0]->components [z ++])->setKey (key_targetlocking);
6096   ((EditKey *) controlsmenu [0]->components [z ++])->setKey (key_targetnext);
6097   ((EditKey *) controlsmenu [0]->components [z ++])->setKey (key_targetprevious);
6098   ((EditKey *) controlsmenu [0]->components [z ++])->setKey (key_thrustup);
6099   ((EditKey *) controlsmenu [0]->components [z ++])->setKey (key_thrustdown);
6100 }
6101 
callbackKeyboard(Component * comp,int key)6102 void callbackKeyboard (Component *comp, int key)
6103 {
6104   int i;
6105   for (i = 5; i < 16; i ++)
6106     if (comp == controlsmenu [0]->components [i])
6107     {
6108       int z = 5;
6109       if (i == z ++) key_firecannon = key;
6110       else if (i == z ++) key_firemissile = key;
6111       else if (i == z ++) key_dropflare = key;
6112       else if (i == z ++) key_dropchaff = key;
6113       else if (i == z ++) key_selectmissile = key;
6114       else if (i == z ++) key_targetnearest = key;
6115       else if (i == z ++) key_targetlocking = key;
6116       else if (i == z ++) key_targetnext = key;
6117       else if (i == z ++) key_targetprevious = key;
6118       else if (i == z ++) key_thrustup = key;
6119       else if (i == z ++) key_thrustdown = key;
6120     }
6121 }
6122 
textControls(char * buf)6123 void textControls (char *buf)
6124 {
6125   if (controls == CONTROLS_KEYBOARD) sprintf (buf, "%s", "KEYBOARD");
6126   else if (controls == CONTROLS_MOUSE) sprintf (buf, "%s", "MOUSE");
6127   else if (controls == CONTROLS_JOYSTICK) sprintf (buf, "%s", "JOYSTICK");
6128 }
6129 
callbackControls(Component * comp,int key)6130 void callbackControls (Component *comp, int key)
6131 {
6132   char buf [256];
6133   if (key == MOUSE_BUTTON_LEFT)
6134   {
6135     fplayer->rolleffect = 0;
6136     fplayer->ruddereffect = 0;
6137     fplayer->elevatoreffect = 0;
6138     keyb_elev = 0;
6139     keyb_roll = 0;
6140     keyb_rudder = 0;
6141     controls ++;
6142     if (controls > 2) controls = 0;
6143     if (controls == CONTROLS_JOYSTICK && !joysticks) controls = CONTROLS_KEYBOARD;
6144 #ifdef USE_GLUT
6145     if (controls == CONTROLS_KEYBOARD) controls = CONTROLS_MOUSE;
6146 #endif
6147   }
6148   textControls (buf);
6149   ((Label *) optmenu [2]->components [5])->setText (buf);
6150   allmenus.components [11]->setVisible (false);
6151   allmenus.components [12]->setVisible (false);
6152   allmenus.components [13]->setVisible (false);
6153   if (controls == CONTROLS_KEYBOARD) allmenus.components [11]->setVisible (true);
6154   else if (controls == CONTROLS_JOYSTICK) allmenus.components [13]->setVisible (true);
6155   else allmenus.components [12]->setVisible (true);
6156 }
6157 
callbackPhysics(Component * comp,int key)6158 void callbackPhysics (Component *comp, int key)
6159 {
6160   char buf [256];
6161   physics = !physics;
6162   if (!physics) sprintf (buf, "%s", "ACTION");
6163   else sprintf (buf, "%s", "SIMULATION");
6164   ((Label *) optmenu [2]->components [3])->setText (buf);
6165 }
6166 
callbackDifficulty(Component * comp,int key)6167 void callbackDifficulty (Component *comp, int key)
6168 {
6169   char buf [256];
6170   if (key == MOUSE_BUTTON_LEFT)
6171   {
6172     difficulty ++;
6173     if (difficulty > 2) difficulty = 0;
6174   }
6175   else
6176   {
6177     difficulty --;
6178     if (difficulty < 0) difficulty = 2;
6179   }
6180   if (difficulty == 0) sprintf (buf, "%s", "EASY");
6181   else if (difficulty == 1) sprintf (buf, "%s", "NORMAL");
6182   else if (difficulty == 2) sprintf (buf, "%s", "HARD");
6183   ((Label *) optmenu [2]->components [1])->setText (buf);
6184 }
6185 
callbackSound(Component * comp,int key)6186 void callbackSound (Component *comp, int key)
6187 {
6188   char buf [256];
6189   if (sound->audio)
6190   {
6191     if (key == MOUSE_BUTTON_LEFT)
6192     {
6193       sound->volumesound += 10;
6194       if (sound->volumesound > 100)
6195         sound->volumesound = 0;
6196       volumesound = sound->volumesound;
6197       sound->setVolume ();
6198       setPlaneVolume ();
6199       sound->play (SOUND_CLICK1, false);
6200       menu_reshape ();
6201     }
6202     else
6203     {
6204       sound->volumesound -= 10;
6205       if (sound->volumesound < 0)
6206         sound->volumesound = 100;
6207       volumesound = sound->volumesound;
6208       sound->setVolume ();
6209       setPlaneVolume ();
6210       sound->play (SOUND_CLICK1, false);
6211       menu_reshape ();
6212     }
6213     sprintf (buf, "%d%%", volumesound);
6214     ((Label *) optmenu [1]->components [1])->setText (buf);
6215   }
6216 }
6217 
callbackMusic(Component * comp,int key)6218 void callbackMusic (Component *comp, int key)
6219 {
6220   char buf [256];
6221   if (sound->audio)
6222   {
6223     if (key == MOUSE_BUTTON_LEFT)
6224     {
6225       sound->volumemusic += 10;
6226       if (sound->volumemusic > 100)
6227       {
6228         sound->volumemusic = 0;
6229         sound->haltMusic ();
6230       }
6231       volumemusic = sound->volumemusic;
6232       sound->setVolumeMusic ();
6233       menu_reshape ();
6234     }
6235     else
6236     {
6237       sound->volumemusic -= 10;
6238       if (sound->volumemusic < 0)
6239         sound->volumemusic = 100;
6240       volumemusic = sound->volumemusic;
6241       sound->setVolumeMusic ();
6242       menu_reshape ();
6243     }
6244     if (sound->volumemusic != 0 && !sound->musicplaying)
6245       playRandomMusic ();
6246     sprintf (buf, "%d%%", volumemusic);
6247     ((Label *) optmenu [1]->components [3])->setText (buf);
6248   }
6249 }
6250 
callbackBrightness(Component * comp,int key)6251 void callbackBrightness (Component *comp, int key)
6252 {
6253   char buf [256];
6254   if (key == MOUSE_BUTTON_LEFT)
6255   {
6256     brightness += 10;
6257     if (brightness > 50) brightness = -50;
6258   }
6259   else
6260   {
6261     brightness -= 10;
6262     if (brightness < -50) brightness = 50;
6263   }
6264   sprintf (buf, "%d%%", brightness);
6265   ((Label *) optmenu [0]->components [13])->setText (buf);
6266 }
6267 
callbackResolution(Component * comp,int key)6268 void callbackResolution (Component *comp, int key)
6269 {
6270   const int numres = 4;
6271   int resx [numres] = { 640, 800, 1024, 1280 };
6272   int resy [numres] = { 480, 600, 800, 1024 };
6273   int found = 0;
6274   char buf [256];
6275 
6276   if (key == MOUSE_BUTTON_LEFT)
6277   {
6278     for (int i = 0; i < numres; i ++)
6279       if (wantwidth == resx [i])
6280       {
6281         found = i + 1;
6282       }
6283   }
6284   else
6285   {
6286     for (int i = 0; i < numres; i ++)
6287       if (wantwidth == resx [i])
6288       {
6289         found = i - 1;
6290       }
6291   }
6292 
6293   if (found < 0) found = numres - 1;
6294   else if (found >= numres) found = 0;
6295 
6296   wantwidth = resx [found];
6297   wantheight = resy [found];
6298 
6299   sprintf (buf, "%d*%d", wantwidth, wantheight);
6300   ((Label *) optmenu [0]->components [16])->setText (buf);
6301 }
6302 
callbackFullscreen(Component * comp,int key)6303 void callbackFullscreen (Component *comp, int key)
6304 {
6305   if (wantfullscreen) wantfullscreen = 0;
6306   else wantfullscreen = 1;
6307 
6308   if (wantfullscreen) ((Label *) optmenu [0]->components [18])->setText ("YES");
6309   else ((Label *) optmenu [0]->components [18])->setText ("NO");
6310 }
6311 
callbackDynamicLighting(Component * comp,int key)6312 void callbackDynamicLighting (Component *comp, int key)
6313 {
6314   char buf [256];
6315   dynamiclighting = (dynamiclighting == 0 ? 1 : 0);
6316   if (dynamiclighting) strcpy (buf, "ON");
6317   else strcpy (buf, "OFF");
6318   ((Label *) optmenu [0]->components [11])->setText (buf);
6319 }
6320 
callbackSpecialEffects(Component * comp,int key)6321 void callbackSpecialEffects (Component *comp, int key)
6322 {
6323   char buf [256];
6324   specialeffects = (specialeffects == 0 ? 1 : 0);
6325   if (specialeffects) strcpy (buf, "ON");
6326   else strcpy (buf, "OFF");
6327   ((Label *) optmenu [0]->components [9])->setText (buf);
6328 }
6329 
callbackAntialiasing(Component * comp,int key)6330 void callbackAntialiasing (Component *comp, int key)
6331 {
6332   char buf [256];
6333   antialiasing = (antialiasing == 0 ? 1 : 0);
6334   if (antialiasing) strcpy (buf, "ON");
6335   else strcpy (buf, "OFF");
6336   ((Label *) optmenu [0]->components [7])->setText (buf);
6337   event_setAntialiasing ();
6338 }
6339 
callbackDithering(Component * comp,int key)6340 void callbackDithering (Component *comp, int key)
6341 {
6342   char buf [256];
6343   dithering = (dithering == 0 ? 1 : 0);
6344   if (dithering) strcpy (buf, "ON");
6345   else strcpy (buf, "OFF");
6346   ((Label *) optmenu [0]->components [5])->setText (buf);
6347 }
6348 
callbackView(Component * comp,int key)6349 void callbackView (Component *comp, int key)
6350 {
6351   char buf [256];
6352   if (key == MOUSE_BUTTON_LEFT)
6353   {
6354     view += 10;
6355     if (view > VIEW_MAX) view = VIEW_MIN;
6356     menu_reshape ();
6357   }
6358   else
6359   {
6360     view -= 10;
6361     if (view < VIEW_MIN) view = VIEW_MAX;
6362     menu_reshape ();
6363   }
6364   sprintf (buf, "%d", (int) view);
6365   ((Label *) optmenu [0]->components [3])->setText (buf); // this is also set by autoconfig in menu_timer
6366 }
6367 
callbackQuality(Component * comp,int key)6368 void callbackQuality (Component *comp, int key)
6369 {
6370   char buf [256];
6371   if (key == MOUSE_BUTTON_LEFT)
6372   {
6373     quality ++;
6374     if (quality > 5) quality = 0;
6375   }
6376   else
6377   {
6378     quality --;
6379     if (quality < 0) quality = 5;
6380   }
6381   sprintf (buf, "%d", quality);
6382   ((Label *) optmenu [0]->components [1])->setText (buf); // this is also set by autoconfig in menu_timer
6383 }
6384 
callbackTraining(Component * comp,int key)6385 void callbackTraining (Component *comp, int key)
6386 {
6387   allmenus.setVisible (false);
6388 
6389   switch_mission (getTrainingIdFromValue (comp->id - trainingstartid));
6390 }
6391 
callbackCampaign(Component * comp,int key)6392 void callbackCampaign (Component *comp, int key)
6393 {
6394   allmenus.setVisible (false);
6395   switch_mission (getCampaignIdFromValue (comp->id - campaignstartid));
6396 }
6397 
callbackMainMenu(Component * comp,int key)6398 void callbackMainMenu (Component *comp, int key)
6399 {
6400   for (i = 0; i < 6; i ++)
6401     if (comp == mainbutton [i])
6402     {
6403       allmenus.setVisible (false);
6404       allmenus.visible = true;
6405       allmenus.components [0]->setVisible (true);
6406       allmenus.components [i + 1]->setVisible (true);
6407       currentsubmenu = allmenus.components [i + 1];
6408       if (missionactive)
6409         mainbutton [6]->setVisible (true);
6410       else
6411         mainbutton [6]->setVisible (false);
6412       if (i == 3)
6413       {
6414         if (currentoptmenu) currentoptmenu->setVisible (true);
6415         if (currentoptmenu == allmenus.components [10])
6416         {
6417           if (controls == CONTROLS_KEYBOARD) allmenus.components [11]->setVisible (true);
6418           else if (controls == CONTROLS_JOYSTICK) allmenus.components [13]->setVisible (true);
6419           else allmenus.components [12]->setVisible (true);
6420         }
6421       }
6422       return;
6423     }
6424   for (i = 0; i < 3; i ++)
6425     if (comp == optbutton [i])
6426     {
6427       allmenus.components [8]->setVisible (false);
6428       allmenus.components [9]->setVisible (false);
6429       allmenus.components [10]->setVisible (false);
6430       allmenus.components [i + 1 + 7]->setVisible (true);
6431       if (i + 1 + 7 == 10)
6432       {
6433         if (controls == CONTROLS_KEYBOARD) allmenus.components [11]->setVisible (true);
6434         else if (controls == CONTROLS_JOYSTICK) allmenus.components [13]->setVisible (true);
6435         else allmenus.components [12]->setVisible (true);
6436       }
6437       else
6438       {
6439         allmenus.components [11]->setVisible (false);
6440         allmenus.components [12]->setVisible (false);
6441         allmenus.components [13]->setVisible (false);
6442       }
6443       currentoptmenu = allmenus.components [i + 1 + 7];
6444       return;
6445     }
6446 }
6447 
setJoystickAxisString(int joysetting,char * joystr)6448 void setJoystickAxisString (int joysetting, char *joystr)
6449 {
6450   joystr [3] = 0;
6451   if (joysetting < 0)
6452   {
6453     strcpy (joystr, "N/A");
6454   }
6455   else
6456   {
6457     joystr [0] = 'A' + (joysetting / 1000);
6458     joystr [1] = 32;
6459     joystr [2] = '0' + (joysetting % 1000);
6460   }
6461 }
6462 
6463 char mainmenunames [10] [25];
6464 char submenu1names [20] [25];
6465 char submenu2names [30] [25];
6466 char optmenunames [5] [25];
6467 char controlsmenu0names [15] [25];
6468 
createMenu()6469 void createMenu ()
6470 {
6471   char buf [256];
6472   char buf2 [256];
6473   int i;
6474   int z = 0;
6475   float xf = -2;
6476   float xfstep = 4;
6477   float yf = 12;
6478   float yfstep = 1.0;
6479   float xsubmenu = -1;
6480   float ysubmenu = 12;
6481   Button *button;
6482   Label *label;
6483   TextField *textfield;
6484   EditKey *editkey;
6485   EditField *editfield;
6486 #ifndef USE_GLUT
6487   EditJoystick *editjoystick;
6488 #endif
6489 
6490 /*
6491 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6492  Register main menu
6493 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6494 */
6495 
6496   strcpy (mainmenunames [0], "PILOTS");
6497   strcpy (mainmenunames [1], "TRAINING");
6498   strcpy (mainmenunames [2], "CAMPAIGN");
6499   strcpy (mainmenunames [3], "OPTIONS");
6500 #ifdef SHOW_SOFTWARE_PATENTS
6501   strcpy (mainmenunames [4], "SOFTWARE PATENTS");
6502 #else
6503   strcpy (mainmenunames [4], "CREDITS");
6504 #endif
6505   strcpy (mainmenunames [5], "QUIT");
6506   strcpy (mainmenunames [6], "RETURN");
6507 
6508   mainmenu = new Container ();
6509 //  mainmenu->setBounds (-14.3, 12.2, 10.6, 7.4);
6510   allmenus.add (mainmenu);
6511 
6512   for (i = 0; i < 7; i ++)
6513   {
6514     submenu [i] = new Container ();
6515     allmenus.add (submenu [i]);
6516   }
6517 
6518 /*  submenu [0]->setBounds (-1.3, 12.2, 14.1, 12.4);
6519   submenu [1]->setBounds (-1.3, 12.2, 12.6, 7.4);
6520   submenu [2]->setBounds (-1.3, 12.2, 12.6, 1.4);
6521   submenu [3]->setBounds (-1.3, 12.2, 14.1, 1.4);*/
6522 
6523   for (i = 0; i < 7; i ++)
6524   {
6525     mainbutton [i] = new Button (mainmenunames [i]);
6526     mainbutton [i]->setBounds (-14, yf, 10, yfstep - 0.1);
6527     yf -= yfstep;
6528     mainbutton [i]->setFunction (callbackMainMenu);
6529     mainmenu->add (mainbutton [i]);
6530   }
6531 
6532   currentsubmenu = submenu [0];
6533   mainbutton [4]->setFunction (callbackCredits);
6534   mainbutton [5]->setFunction (callbackQuit);
6535   mainbutton [6]->setVisible (false);
6536   mainbutton [6]->setFunction (callbackReturn);
6537 
6538 /*
6539 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6540  Register pilots submenu
6541 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6542 */
6543 
6544   xf = xsubmenu; yf = ysubmenu; xfstep = 13.5; yfstep = 1;
6545   sprintf (buf, "ACTIVE:");
6546   label = new Label (buf);
6547   label->setBounds (xf, yf, xfstep, yfstep - 0.1);
6548   submenu [0]->add (label);
6549   yf -= yfstep;
6550 
6551   sprintf (buf, "     %s %s", pilots->pilot [pilots->aktpilot]->getShortRank (), pilots->pilot [pilots->aktpilot]->name);
6552   label = new Label (buf);
6553   label->setBounds (xf, yf, xfstep, yfstep - 0.1);
6554   submenu [0]->add (label);
6555 
6556   yf -= 2;
6557   for (i = 0; i < 5; i ++)
6558   {
6559     if (i < pilots->aktpilots)
6560       sprintf (buf, "     %s %s", pilots->pilot [i]->getShortRank (), pilots->pilot [i]->name);
6561     else
6562       sprintf (buf, "N/A");
6563     button = new Button (buf);
6564     button->setFunction (callbackPilotsList);
6565     button->setBounds (xf, yf, xfstep, yfstep - 0.1);
6566     submenu [0]->add (button);
6567     yf -= yfstep;
6568   }
6569 
6570   yf -= 0.5;
6571   button = new Button ("DELETE (RIGHT MB)");
6572   button->setFunction (callbackPilotsDelete);
6573   button->setBounds (xf, yf, xfstep, yfstep - 0.1);
6574   submenu [0]->add (button);
6575   yf -= yfstep;
6576 
6577   yf -= 0.5;
6578   button = new Button ("ADD");
6579   button->setFunction (callbackPilotsAdd);
6580   button->setBounds (xf, yf, xfstep, yfstep - 0.1);
6581   submenu [0]->add (button);
6582   yf -= yfstep;
6583 
6584   editfield = new EditField (15);
6585   editfield->setBounds (xf, yf, xfstep, yfstep - 0.1);
6586   submenu [0]->add (editfield);
6587   yf -= yfstep;
6588 
6589 /*
6590 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6591  Register training submenu
6592 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6593 */
6594 
6595   z = 0;
6596   strcpy (submenu1names [z ++], "TUTORIAL: PILOTING");
6597   strcpy (submenu1names [z ++], "TUTORIAL: BOMBER");
6598   strcpy (submenu1names [z ++], "TUTORIAL: FIGHTER");
6599   strcpy (submenu1names [z ++], "TUTORIAL: AERODYNAMICS");
6600   strcpy (submenu1names [z ++], "FREE FLIGHT");
6601   strcpy (submenu1names [z ++], "DEATHMATCH");
6602   strcpy (submenu1names [z ++], "TEAM DEATHMATCH");
6603   strcpy (submenu1names [z ++], "CANNON DEATHMATCH");
6604   strcpy (submenu1names [z ++], "TEAM BASE");
6605   strcpy (submenu1names [z ++], "WAVES");
6606 
6607   xf = xsubmenu; yf = ysubmenu - 2; xfstep = 12; yfstep = 0.8;
6608   for (i = 0; i < 10; i ++)
6609   {
6610     button = new Button (submenu1names [i]);
6611     button->setBounds (xf, yf, xfstep, yfstep - 0.1);
6612     button->setFunction (callbackTraining);
6613     yf -= yfstep;
6614     if (i == 3) yf -= yfstep;
6615     submenu [1]->add (button);
6616   }
6617 
6618   trainingstartid = submenu [1]->components [0]->id;
6619 
6620   yf -= yfstep;
6621   for (i = 0; i < maploader->getMapNumber (); i ++)
6622   {
6623     char str [256];
6624     strcpy (str, maploader->getNextMap ());
6625     maploader->toUpper (str);
6626     button = new Button (str);
6627     button->setBounds (xf, yf, xfstep, yfstep - 0.1);
6628     button->setFunction (callbackTraining);
6629     yf -= yfstep;
6630     submenu [1]->add (button);
6631   }
6632 
6633   xf = xsubmenu; yf = ysubmenu; yfstep = 1;
6634   button = new Button ("FIGHTER INFO");
6635   button->setFunction (callbackFighter);
6636   button->setBounds (xf, yf, xfstep - 0.2, yfstep - 0.1);
6637   submenu [1]->add (button);
6638   xf += xfstep;
6639 
6640 /*
6641 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6642  Register campaign submenu
6643 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6644 */
6645 
6646   z = 0;
6647   strcpy (submenu2names [z ++], "FIRST TEST");
6648   strcpy (submenu2names [z ++], "SECOND TEST");
6649   strcpy (submenu2names [z ++], "TRANSPORT");
6650   strcpy (submenu2names [z ++], "CONVOY");
6651   strcpy (submenu2names [z ++], "DOGFIGHT");
6652   strcpy (submenu2names [z ++], "AIR BATTLE");
6653   strcpy (submenu2names [z ++], "SURFACE-AIR DEFENSE");
6654   strcpy (submenu2names [z ++], "VETERAN DOGFIGHT");
6655   strcpy (submenu2names [z ++], "BASE ATTACK");
6656   strcpy (submenu2names [z ++], "DEPOTS");
6657   strcpy (submenu2names [z ++], "DEFEND SAM");
6658   strcpy (submenu2names [z ++], "DESERT DOGFIGHT");
6659   strcpy (submenu2names [z ++], "TANK ASSAUT");
6660   strcpy (submenu2names [z ++], "SAM CONVOY");
6661   strcpy (submenu2names [z ++], "DESTROYERS");
6662   strcpy (submenu2names [z ++], "OILRIG");
6663   strcpy (submenu2names [z ++], "CRUISER");
6664   strcpy (submenu2names [z ++], "RADAR BASE");
6665   strcpy (submenu2names [z ++], "CANYON BATTLE");
6666   strcpy (submenu2names [z ++], "TUNNEL");
6667   strcpy (submenu2names [z ++], "MAIN BASE");
6668   strcpy (submenu2names [z ++], "TURRETS");
6669   strcpy (submenu2names [z ++], "MOON BATTLE");
6670   strcpy (submenu2names [z ++], "ELITE DOGFIGHT");
6671   strcpy (submenu2names [z ++], "SNEAKING");
6672 
6673   xf = xsubmenu; yf = ysubmenu - 2; xfstep = 12; yfstep = 0.8;
6674   for (i = 0; i < z; i ++)
6675   {
6676     button = new Button (submenu2names [i]);
6677     button->setFunction (callbackCampaign);
6678     button->setBounds (xf, yf, xfstep, yfstep - 0.1);
6679     yf -= yfstep;
6680     submenu [2]->add (button);
6681   }
6682 
6683   campaignstartid = submenu [2]->components [0]->id;
6684 
6685   xf = xsubmenu; yf = ysubmenu; yfstep = 1;
6686   button = new Button ("PILOTS RANKING");
6687   button->setFunction (callbackPilots);
6688   button->setBounds (xf, yf, xfstep - 0.2, yfstep - 0.1);
6689   submenu [2]->add (button);
6690   xf += xfstep;
6691 
6692 /*
6693 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6694  Register options submenu
6695 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6696 */
6697 
6698   xf = xsubmenu; yf = 12; xfstep = 4.6;
6699   strcpy (optmenunames [0], "VIDEO");
6700   strcpy (optmenunames [1], "AUDIO");
6701   strcpy (optmenunames [2], "GAME");
6702 
6703   for (i = 0; i < 3; i ++)
6704   {
6705     optmenu [i] = new Container ();
6706     allmenus.add (optmenu [i]);
6707   }
6708 
6709   for (i = 0; i < 3; i ++)
6710   {
6711     optbutton [i] = new Button (optmenunames [i]);
6712     optbutton [i]->setBounds (xf, yf, xfstep - 0.2, 1);
6713     xf += xfstep;
6714     optbutton [i]->setFunction (callbackMainMenu);
6715     submenu [3]->add (optbutton [i]);
6716   }
6717 
6718   currentoptmenu = optmenu [0];
6719 
6720 /*
6721 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6722  Register video options submenu
6723 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6724 */
6725 
6726   float xftab = 3;
6727   xf = xsubmenu; yf = 10; xfstep = 13.6; yfstep = 1;
6728   button = new Button ("QUALITY");
6729   button->setFunction (callbackQuality);
6730   button->setBounds (xf, yf, xfstep, yfstep - 0.1);
6731   optmenu [0]->add (button);
6732 
6733   sprintf (buf, "%d", quality);
6734   label = new Label (buf);
6735   label->setTransparent (true);
6736   label->setBounds (xf + xfstep - xftab, yf, 2, yfstep - 0.1);
6737   optmenu [0]->add (label);
6738   yf -= yfstep;
6739 
6740   button = new Button ("VIEW");
6741   button->setFunction (callbackView);
6742   button->setBounds (xf, yf, xfstep, yfstep - 0.1);
6743   optmenu [0]->add (button);
6744 
6745   sprintf (buf, "%d", (int) view);
6746   label = new Label (buf);
6747   label->setTransparent (true);
6748   label->setBounds (xf + xfstep - xftab, yf, 2, yfstep - 0.1);
6749   optmenu [0]->add (label);
6750   yf -= yfstep;
6751 
6752   button = new Button ("DITHERING");
6753   button->setFunction (callbackDithering);
6754   button->setBounds (xf, yf, xfstep, yfstep - 0.1);
6755   optmenu [0]->add (button);
6756 
6757   if (dithering) strcpy (buf, "ON");
6758   else strcpy (buf, "OFF");
6759   label = new Label (buf);
6760   label->setTransparent (true);
6761   label->setBounds (xf + xfstep - xftab, yf, 2, yfstep - 0.1);
6762   optmenu [0]->add (label);
6763   yf -= yfstep;
6764 
6765   button = new Button ("ANTIALIASING");
6766   button->setFunction (callbackAntialiasing);
6767   button->setBounds (xf, yf, xfstep, yfstep - 0.1);
6768   optmenu [0]->add (button);
6769 
6770   if (antialiasing) strcpy (buf, "ON");
6771   else strcpy (buf, "OFF");
6772   label = new Label (buf);
6773   label->setTransparent (true);
6774   label->setBounds (xf + xfstep - xftab, yf, 2, yfstep - 0.1);
6775   optmenu [0]->add (label);
6776   yf -= yfstep;
6777 
6778   button = new Button ("SPECIAL EFFECTS");
6779   button->setFunction (callbackSpecialEffects);
6780   button->setBounds (xf, yf, xfstep, yfstep - 0.1);
6781   optmenu [0]->add (button);
6782 
6783   if (specialeffects) strcpy (buf, "ON");
6784   else strcpy (buf, "OFF");
6785   label = new Label (buf);
6786   label->setTransparent (true);
6787   label->setBounds (xf + xfstep - xftab, yf, 2, yfstep - 0.1);
6788   optmenu [0]->add (label);
6789   yf -= yfstep;
6790 
6791   button = new Button ("DYN LIGHTING");
6792   button->setFunction (callbackDynamicLighting);
6793   button->setBounds (xf, yf, xfstep, yfstep - 0.1);
6794   optmenu [0]->add (button);
6795 
6796   if (dynamiclighting) strcpy (buf, "ON");
6797   else strcpy (buf, "OFF");
6798   label = new Label (buf);
6799   label->setTransparent (true);
6800   label->setBounds (xf + xfstep - xftab, yf, 2, yfstep - 0.1);
6801   optmenu [0]->add (label);
6802   yf -= yfstep;
6803 
6804   button = new Button ("BRIGHTNESS");
6805   button->setFunction (callbackBrightness);
6806   button->setBounds (xf, yf, xfstep, yfstep - 0.1);
6807   optmenu [0]->add (button);
6808 
6809   sprintf (buf, "%d%%", brightness);
6810   label = new Label (buf);
6811   label->setTransparent (true);
6812   label->setBounds (xf + xfstep - xftab, yf, 2, yfstep - 0.1);
6813   optmenu [0]->add (label);
6814   yf -= yfstep;
6815 
6816   yf -= yfstep / 2;
6817   sprintf (buf, "NEED RESTART:");
6818   label = new Label (buf);
6819   label->setTransparent (true);
6820   label->setBounds (xf, yf, 2, yfstep - 0.3);
6821   optmenu [0]->add (label);
6822   yf -= yfstep;
6823 
6824   button = new Button ("RESOLUTION");
6825   button->setFunction (callbackResolution);
6826   button->setBounds (xf, yf, xfstep, yfstep - 0.1);
6827   optmenu [0]->add (button);
6828 
6829   sprintf (buf, "%d*%d", wantwidth, wantheight);
6830   label = new Label (buf);
6831   label->setTransparent (true);
6832   label->setBounds (xf + xfstep - xftab * 2, yf, 2, yfstep - 0.1);
6833   optmenu [0]->add (label);
6834   yf -= yfstep;
6835 
6836   button = new Button ("FULLSCREEN");
6837   button->setFunction (callbackFullscreen);
6838   button->setBounds (xf, yf, xfstep, yfstep - 0.1);
6839   optmenu [0]->add (button);
6840 
6841   if (wantfullscreen) sprintf (buf, "YES");
6842   else sprintf (buf, "NO");
6843   label = new Label (buf);
6844   label->setTransparent (true);
6845   label->setBounds (xf + xfstep - xftab, yf, 2, yfstep - 0.1);
6846   optmenu [0]->add (label);
6847   yf -= yfstep;
6848 
6849 /*
6850 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6851  Register sound options submenu
6852 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6853 */
6854 
6855   yf = 10; xfstep = 13.6; yfstep = 1;
6856 #ifdef USE_GLUT
6857   textfield = new TextField ("PLEASE INSTALL SDL AND\nSDLMIXER AND RECOMIPLE\nGL-117 TO ENABLE SOUND\nAND MUSIC", 0.6);
6858   textfield->setBounds (xf, yf, xfstep, 0.6 * 4);
6859   optmenu [1]->add (textfield);
6860   yf -= 0.6 * 4;
6861 #else
6862   button = new Button ("SOUND VOLUME");
6863   button->setFunction (callbackSound);
6864   button->setBounds (xf, yf, xfstep, yfstep - 0.1);
6865   optmenu [1]->add (button);
6866 
6867   if (sound->audio) sprintf (buf, "%d%%", volumesound);
6868   else sprintf (buf, "N/A");
6869   label = new Label (buf);
6870   label->setTransparent (true);
6871   label->setBounds (xf + xfstep - xftab, yf, 2, yfstep - 0.1);
6872   optmenu [1]->add (label);
6873   yf -= yfstep;
6874 
6875   button = new Button ("MUSIC VOLUME");
6876   button->setFunction (callbackMusic);
6877   button->setBounds (xf, yf, xfstep, yfstep - 0.1);
6878   optmenu [1]->add (button);
6879 
6880   if (sound->audio) sprintf (buf, "%d%%", volumemusic);
6881   else sprintf (buf, "N/A");
6882   label = new Label (buf);
6883   label->setTransparent (true);
6884   label->setBounds (xf + xfstep - xftab, yf, 2, yfstep - 0.1);
6885   optmenu [1]->add (label);
6886   yf -= yfstep;
6887 
6888   if (!sound->audio)
6889   {
6890     optmenu [1]->components [0]->setActive (false);
6891     optmenu [1]->components [1]->setActive (false);
6892     optmenu [1]->components [2]->setActive (false);
6893     optmenu [1]->components [3]->setActive (false);
6894   }
6895 #endif
6896 
6897 /*
6898 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6899  Register controls options submenu
6900 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6901 */
6902 
6903   xftab = 6.8;
6904   xf = xsubmenu; yf = 10; xfstep = 13.5; yfstep = 1;
6905   button = new Button ("DIFFICULTY");
6906   button->setFunction (callbackDifficulty);
6907   button->setBounds (xf, yf, xfstep, yfstep - 0.1);
6908   optmenu [2]->add (button);
6909 
6910   if (difficulty == 0) sprintf (buf, "%s", "EASY");
6911   else if (difficulty == 1) sprintf (buf, "%s", "NORMAL");
6912   else if (difficulty == 2) sprintf (buf, "%s", "HARD");
6913   label = new Label (buf);
6914   label->setTransparent (true);
6915   label->setBounds (xf + xfstep - xftab, yf, 2, yfstep - 0.1);
6916   optmenu [2]->add (label);
6917   yf -= yfstep;
6918 
6919   button = new Button ("PHYSICS");
6920   button->setFunction (callbackPhysics);
6921   button->setBounds (xf, yf, xfstep, yfstep - 0.1);
6922   optmenu [2]->add (button);
6923 
6924   if (!physics) sprintf (buf, "%s", "ACTION");
6925   else sprintf (buf, "%s", "SIMULATION");
6926   label = new Label (buf);
6927   label->setTransparent (true);
6928   label->setBounds (xf + xfstep - xftab, yf, 2, yfstep - 0.1);
6929   optmenu [2]->add (label);
6930   yf -= yfstep;
6931 
6932   button = new Button ("CONTROLS");
6933   button->setFunction (callbackControls);
6934   button->setBounds (xf, yf, xfstep, yfstep - 0.1);
6935   optmenu [2]->add (button);
6936 
6937   textControls (buf);
6938   label = new Label (buf);
6939   label->setTransparent (true);
6940   label->setBounds (xf + xfstep - xftab, yf, 2, yfstep - 0.1);
6941   optmenu [2]->add (label);
6942   yf -= yfstep;
6943 
6944 /*
6945 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6946  Register keyboard control submenu
6947 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6948 */
6949 
6950   xf = xsubmenu + 1; yf = ysubmenu - 6; xfstep = 12.5; yfstep = 0.8;
6951   for (i = 0; i < 3; i ++)
6952   {
6953     controlsmenu [i] = new Container ();
6954     allmenus.add (controlsmenu [i]);
6955   }
6956 
6957   label = new Label ("ROLL:       \t   LEFT, RIGHT");
6958   label->setBounds (xf, yf, xfstep, yfstep - 0.1);
6959   controlsmenu [0]->add (label);
6960   yf -= yfstep;
6961 
6962   label = new Label ("ELEVATOR: \t   UP, DOWN");
6963   label->setBounds (xf, yf, xfstep, yfstep - 0.1);
6964   controlsmenu [0]->add (label);
6965   yf -= yfstep;
6966 
6967   label = new Label ("RUDDER:  \t   LSHIFT+ROLL");
6968   label->setBounds (xf, yf, xfstep, yfstep - 0.1);
6969   controlsmenu [0]->add (label);
6970   yf -= yfstep;
6971 
6972   label = new Label ("THROTTLE: \t   1...9");
6973   label->setBounds (xf, yf, xfstep, yfstep - 0.1);
6974   controlsmenu [0]->add (label);
6975   yf -= yfstep;
6976 
6977   label = new Label ("CAMERA:  \t   F1...F8");
6978   label->setBounds (xf, yf, xfstep, yfstep - 0.1);
6979   controlsmenu [0]->add (label);
6980   yf -= yfstep;
6981 
6982   z = 0;
6983   strcpy (controlsmenu0names [z ++], "FIRE CANNON");
6984   strcpy (controlsmenu0names [z ++], "FIRE MISSILE");
6985   strcpy (controlsmenu0names [z ++], "DROP FLARE");
6986   strcpy (controlsmenu0names [z ++], "DROP CHAFF");
6987   strcpy (controlsmenu0names [z ++], "SELECT MISSILE");
6988   strcpy (controlsmenu0names [z ++], "TARGET NEAREST");
6989   strcpy (controlsmenu0names [z ++], "TARGET LOCKING");
6990   strcpy (controlsmenu0names [z ++], "TARGET NEXT");
6991   strcpy (controlsmenu0names [z ++], "TARGET PREVIOUS");
6992   strcpy (controlsmenu0names [z ++], "INC THRUST");
6993   strcpy (controlsmenu0names [z ++], "DEC THRUST");
6994 
6995   int keys [11];
6996   keys [0] = key_firecannon;
6997   keys [1] = key_firemissile;
6998   keys [2] = key_dropflare;
6999   keys [3] = key_dropchaff;
7000   keys [4] = key_selectmissile;
7001   keys [5] = key_targetnearest;
7002   keys [6] = key_targetlocking;
7003   keys [7] = key_targetnext;
7004   keys [8] = key_targetprevious;
7005   keys [9] = key_thrustup;
7006   keys [10] = key_thrustdown;
7007 
7008   yf -= 0.5;
7009   for (i = 0; i < 11; i ++)
7010   {
7011     editkey = new EditKey (controlsmenu0names [i]);
7012     editkey->setKey (keys [i]);
7013     editkey->setFunction (callbackKeyboard);
7014     editkey->setBounds (xf, yf, xfstep, yfstep - 0.1);
7015     controlsmenu [0]->add (editkey);
7016     yf -= yfstep;
7017   }
7018 
7019   yf -= 1; yfstep = 1.0;
7020   button = new Button ("LOAD DEFAULTS");
7021   button->setFunction (callbackDefaults);
7022   button->setBounds (xf, yf, xfstep, yfstep - 0.1);
7023   controlsmenu [0]->add (button);
7024 
7025 /*
7026 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7027  Register mouse control submenu
7028 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7029 */
7030 
7031   xftab = 3.5;
7032   xf = xsubmenu + 1; yf = ysubmenu - 6; xfstep = 12.5; yfstep = 0.8;
7033   button = new Button ("SENSITIVITY");
7034   button->setFunction (callbackMouseSensitivity);
7035   button->setBounds (xf, yf, xfstep, yfstep - 0.1);
7036   controlsmenu [1]->add (button);
7037 
7038   sprintf (buf, "%d%%", (int) mouse_sensitivity);
7039   label = new Label (buf);
7040   label->setTransparent (true);
7041   label->setBounds (xf + xfstep - xftab, yf, 2, yfstep - 0.1);
7042   controlsmenu [1]->add (label);
7043   yf -= yfstep;
7044 
7045   button = new Button ("REVERSE");
7046   button->setFunction (callbackMouseReverse);
7047   button->setBounds (xf, yf, xfstep, yfstep - 0.1);
7048   controlsmenu [1]->add (button);
7049 
7050   if (mouse_reverse) sprintf (buf, "ON");
7051   else sprintf (buf, "OFF");
7052   label = new Label (buf);
7053   label->setTransparent (true);
7054   label->setBounds (xf + xfstep - xftab, yf, 2, yfstep - 0.1);
7055   controlsmenu [1]->add (label);
7056   yf -= yfstep;
7057 
7058   button = new Button ("RELATIVE");
7059   button->setFunction (callbackMouseRelative);
7060   button->setBounds (xf, yf, xfstep, yfstep - 0.1);
7061   controlsmenu [1]->add (button);
7062 
7063   if (mouse_relative) sprintf (buf, "ON");
7064   else sprintf (buf, "OFF");
7065   label = new Label (buf);
7066   label->setTransparent (true);
7067   label->setBounds (xf + xfstep - xftab, yf, 2, yfstep - 0.1);
7068   controlsmenu [1]->add (label);
7069   yf -= yfstep;
7070 
7071   button = new Button ("AUTORUDDER");
7072   button->setFunction (callbackMouseAutorudder);
7073   button->setBounds (xf, yf, xfstep, yfstep - 0.1);
7074   controlsmenu [1]->add (button);
7075 
7076   sprintf (buf, "%d%%", mouse_autorudder);
7077   label = new Label (buf);
7078   label->setTransparent (true);
7079   label->setBounds (xf + xfstep - xftab, yf, 2, yfstep - 0.1);
7080   controlsmenu [1]->add (label);
7081   yf -= yfstep;
7082 
7083   yf -= 0.5;
7084   textMouseButton (buf2, mouse_firecannon);
7085   sprintf (buf, "FIRE CANNON:            \t %s", buf2);
7086   label = new Label (buf);
7087   label->setBounds (xf, yf, xfstep, yfstep - 0.1);
7088   controlsmenu [1]->add (label);
7089   yf -= yfstep;
7090 
7091   textMouseButton (buf2, mouse_firemissile);
7092   sprintf (buf, "FIRE MISSILE:            \t %s", buf2);
7093   label = new Label (buf);
7094   label->setBounds (xf, yf, xfstep, yfstep - 0.1);
7095   controlsmenu [1]->add (label);
7096   yf -= yfstep;
7097 
7098   textMouseButton (buf2, mouse_selectmissile);
7099   sprintf (buf, "SELECT MISSILE:      \t %s", buf2);
7100   label = new Label (buf);
7101   label->setBounds (xf, yf, xfstep, yfstep - 0.1);
7102   controlsmenu [1]->add (label);
7103   yf -= yfstep;
7104 
7105   yf -= 1; yfstep = 1.0;
7106   button = new Button ("LOAD DEFAULTS");
7107   button->setFunction (callbackMouseDefaults);
7108   button->setBounds (xf, yf, xfstep, yfstep - 0.1);
7109   controlsmenu [1]->add (button);
7110 
7111 /*
7112 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7113  Register joystick control submenu
7114 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7115 */
7116 
7117 #ifndef USE_GLUT
7118   char joystr [4];
7119 
7120   xf = xsubmenu + 1; yf = ysubmenu - 6; xfstep = 12.5; yfstep = 0.8;
7121   button = new Button ("AILERON");
7122   button->setFunction (callbackJoystickAxis);
7123   button->setBounds (xf, yf, xfstep, yfstep - 0.1);
7124   controlsmenu [2]->add (button);
7125   setJoystickAxisString (joystick_aileron, joystr);
7126   label = new Label (joystr);
7127   label->setBounds (xf + xfstep - xftab, yf, xftab, yfstep - 0.1);
7128   label->setTransparent (true);
7129   controlsmenu [2]->add (label);
7130   yf -= yfstep;
7131 
7132   button = new Button ("ELEVATOR");
7133   button->setFunction (callbackJoystickAxis);
7134   button->setBounds (xf, yf, xfstep, yfstep - 0.1);
7135   controlsmenu [2]->add (button);
7136   setJoystickAxisString (joystick_elevator, joystr);
7137   label = new Label (joystr);
7138   label->setBounds (xf + xfstep - xftab, yf, xftab, yfstep - 0.1);
7139   label->setTransparent (true);
7140   controlsmenu [2]->add (label);
7141   yf -= yfstep;
7142 
7143   button = new Button ("THROTTLE");
7144   button->setFunction (callbackJoystickAxis);
7145   button->setBounds (xf, yf, xfstep, yfstep - 0.1);
7146   controlsmenu [2]->add (button);
7147   setJoystickAxisString (joystick_throttle, joystr);
7148   label = new Label (joystr);
7149   label->setBounds (xf + xfstep - xftab, yf, xftab, yfstep - 0.1);
7150   label->setTransparent (true);
7151   controlsmenu [2]->add (label);
7152   yf -= yfstep;
7153 
7154   button = new Button ("RUDDER");
7155   button->setFunction (callbackJoystickAxis);
7156   button->setBounds (xf, yf, xfstep, yfstep - 0.1);
7157   controlsmenu [2]->add (button);
7158   setJoystickAxisString (joystick_rudder, joystr);
7159   label = new Label (joystr);
7160   label->setBounds (xf + xfstep - xftab, yf, xftab, yfstep - 0.1);
7161   label->setTransparent (true);
7162   controlsmenu [2]->add (label);
7163   yf -= yfstep;
7164 
7165   button = new Button ("VIEW X");
7166   button->setFunction (callbackJoystickAxis);
7167   button->setBounds (xf, yf, xfstep, yfstep - 0.1);
7168   controlsmenu [2]->add (button);
7169   setJoystickAxisString (joystick_view_x, joystr);
7170   label = new Label (joystr);
7171   label->setBounds (xf + xfstep - xftab, yf, xftab, yfstep - 0.1);
7172   label->setTransparent (true);
7173   controlsmenu [2]->add (label);
7174   yf -= yfstep;
7175 
7176   button = new Button ("VIEW Y");
7177   button->setFunction (callbackJoystickAxis);
7178   button->setBounds (xf, yf, xfstep, yfstep - 0.1);
7179   controlsmenu [2]->add (button);
7180   setJoystickAxisString (joystick_view_y, joystr);
7181   label = new Label (joystr);
7182   label->setBounds (xf + xfstep - xftab, yf, xftab, yfstep - 0.1);
7183   label->setTransparent (true);
7184   controlsmenu [2]->add (label);
7185   yf -= yfstep;
7186 
7187   int buttons [11];
7188   buttons [0] = joystick_firecannon;
7189   buttons [1] = joystick_firemissile;
7190   buttons [2] = joystick_dropflare;
7191   buttons [3] = joystick_dropchaff;
7192   buttons [4] = joystick_selectmissile;
7193   buttons [5] = joystick_targetnearest;
7194   buttons [6] = joystick_targetlocking;
7195   buttons [7] = joystick_targetnext;
7196   buttons [8] = joystick_targetprevious;
7197   buttons [9] = joystick_thrustup;
7198   buttons [10] = joystick_thrustdown;
7199 
7200   yf -= 0.5;
7201   for (i = 0; i < 11; i ++)
7202   {
7203     editjoystick = new EditJoystick (controlsmenu0names [i]);
7204     editjoystick->setButton (buttons [i]);
7205     editjoystick->setFunction (callbackJoystick);
7206     editjoystick->setBounds (xf, yf, xfstep, yfstep - 0.1);
7207     controlsmenu [2]->add (editjoystick);
7208     yf -= yfstep;
7209   }
7210 
7211   yf -= 1; yfstep = 1.0;
7212   button = new Button ("LOAD DEFAULTS");
7213   button->setFunction (callbackDefaultsJoystick);
7214   button->setBounds (xf, yf, xfstep, yfstep - 0.1);
7215   controlsmenu [2]->add (button);
7216 #endif
7217 
7218 /*
7219 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7220  Register top pilots menu
7221 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7222 */
7223 
7224   xf = -10; yf = 9; xfstep = 20; yfstep = 1.2;
7225   sprintf (buf, "         PILOTS RANKING");
7226   label = new Label (buf);
7227   label->setBounds (xf, yf, xfstep, yfstep - 0.1);
7228   famemenu.add (label);
7229   yf -= yfstep + 0.25;
7230 
7231   yfstep = 1.0;
7232   textfield = new TextField ("", yfstep - 0.1);
7233   textfield->setBounds (xf, yf, xfstep, (yfstep - 0.1) * 13);
7234   famemenu.add (textfield);
7235   yf -= yfstep * 13;
7236 
7237   yfstep = 1.1;
7238   sprintf (buf, "         BACK TO MAIN MENU");
7239   button = new Button (buf);
7240   button->setBounds (xf, yf, xfstep, yfstep - 0.1);
7241   button->setFunction (callbackSwitchMainMenu);
7242   famemenu.add (button);
7243   yf -= yfstep + 0.25;
7244 
7245 /*
7246 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7247  Register fighter menu
7248 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7249 */
7250 
7251   xf = -10; yf = 12; xfstep = 20; yfstep = 1.2;
7252   sprintf (buf, "          FIGHTER INFO");
7253   label = new Label (buf);
7254   label->setBounds (xf, yf, xfstep, yfstep - 0.1);
7255   fightermenu.add (label);
7256   yf -= yfstep + 0.25;
7257 
7258   yfstep = 1.0;
7259   buf [0] = 0;
7260   label = new Label (buf);
7261   label->setBounds (xf, yf, xfstep, yfstep - 0.1);
7262   fightermenu.add (label);
7263   yf -= yfstep + 0.25;
7264 
7265   yfstep = 1.1;
7266   textfield = new TextField ("", yfstep - 0.1);
7267   textfield->setBounds (xf, yf, xfstep, (yfstep - 0.1) * 5 + 0.15);
7268   fightermenu.add (textfield);
7269   yf -= yfstep * 5 + 0.05;
7270 
7271   button = new Button ("<");
7272   button->setBounds (xf, yf, 1.5, 1.5);
7273   button->setFunction (callbackFighterPrev);
7274   fightermenu.add (button);
7275   button = new Button (">");
7276   button->setBounds (-xf -1.5, yf, 1.5, 1.5);
7277   button->setFunction (callbackFighterNext);
7278   fightermenu.add (button);
7279   textfield = new TextField ("", yfstep - 0.1);
7280   textfield->setBounds (xf + 1.5, yf, 17, 12.5);
7281   fightermenu.add (textfield);
7282   yf -= 13;
7283 
7284   sprintf (buf, "         BACK TO MAIN MENU");
7285   button = new Button (buf);
7286   button->setBounds (xf, yf, xfstep, yfstep - 0.1);
7287   button->setFunction (callbackSwitchMainMenu);
7288   fightermenu.add (button);
7289   yf -= yfstep + 0.25;
7290 
7291 /*
7292 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7293  Register mission menu
7294 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7295 */
7296 
7297   xf = -12.5; yf = 11; xfstep = 25; yfstep = 1.3;
7298   buf [0] = 0;
7299   label = new Label (buf);
7300   label->setBounds (xf, yf, xfstep, yfstep - 0.1);
7301   missionmenu.add (label);
7302   yf -= yfstep + 0.15;
7303 
7304   yfstep = 1.0;
7305   buf [0] = 0;
7306   label = new Label (buf);
7307   label->setBounds (xf, yf, xfstep, 3.5);
7308   missionmenu.add (label);
7309   yf -= 3.75;
7310 
7311   buf [0] = 0;
7312   label = new Label (buf);
7313   label->setBounds (xf, yf, xfstep / 2 - 0.1, 5.7);
7314   missionmenu.add (label);
7315 
7316   buf [0] = 0;
7317   label = new Label (buf);
7318   label->setBounds (xf + xfstep / 2 + 0.1, yf, xfstep / 2 - 0.1, 5.7);
7319   missionmenu.add (label);
7320   yf -= 5.95;
7321 
7322   buf [0] = 0;
7323   label = new Label (buf);
7324   label->setBounds (xf, yf, xfstep / 2 - 0.1, 6.8);
7325   missionmenu.add (label);
7326 
7327   buf [0] = 0;
7328   label = new Label (buf);
7329   label->setBounds (xf + xfstep / 2 + 0.1, yf, xfstep / 2 - 0.1, 6.8);
7330   missionmenu.add (label);
7331   yf -= 7.15;
7332 
7333   yfstep = 1.0;
7334   button = new Button (" BACK TO MAIN MENU");
7335   button->setBounds (xf, yf, xfstep / 2 - 0.1, yfstep - 0.1);
7336   button->setFunction (callbackSwitchMainMenu);
7337   missionmenu.add (button);
7338 
7339   button = new Button ("    START MISSION");
7340   button->setBounds (xf + xfstep / 2 + 0.1, yf, xfstep / 2 - 0.1, yfstep - 0.1);
7341   button->setFunction (callbackSwitchStartMission);
7342   missionmenu.add (button);
7343 
7344 /*
7345 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7346  Register quit dialog
7347 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7348 */
7349 
7350   xf = -6; yf = 2; xfstep = 12; yfstep = 1.2;
7351   buf [0] = 0;
7352   label = new Label (buf);
7353   label->setBounds (xf, yf, xfstep, 3);
7354   quitmenu.add (label);
7355   yf -= 3.25;
7356 
7357   yfstep = 1.0; xfstep = 12;
7358   button = new Button ("    YES");
7359   button->setBounds (xf, yf, xfstep / 2 - 0.1, yfstep - 0.1);
7360   button->setFunction (callbackQuitNow);
7361   quitmenu.add (button);
7362 
7363   button = new Button ("     NO");
7364   button->setBounds (xf + xfstep / 2 + 0.1, yf, xfstep / 2 - 0.1, yfstep - 0.1);
7365   button->setFunction (callbackSwitchMainMenu);
7366   quitmenu.add (button);
7367 
7368 /*
7369 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7370  Register stats dialog
7371 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7372 */
7373 
7374   xf = -10; yf = 9; xfstep = 20; yfstep = 1.2;
7375   buf [0] = 0;
7376   textfield = new TextField (buf, 1);
7377   textfield->setBounds (xf, yf, xfstep, 15.8);
7378   statsmenu.add (textfield);
7379   yf -= 16;
7380 
7381   yfstep = 1.0; xfstep = 20;
7382   button = new Button ("                  CONTINUE");
7383   button->setBounds (xf, yf, xfstep, yfstep - 0.1);
7384   button->setFunction (callbackStats);
7385   statsmenu.add (button);
7386 
7387 
7388 
7389   famemenu.setVisible (false);
7390   fightermenu.setVisible (false);
7391   missionmenu.setVisible (false);
7392   quitmenu.setVisible (false);
7393   statsmenu.setVisible (false);
7394   allmenus.setVisible (false);
7395   allmenus.visible = true;
7396   allmenus.components [0]->setVisible (true);
7397 }
7398 
7399 
7400 
7401 /****************************************************************************
7402   GL-117 ENTRY POINT
7403 ****************************************************************************/
7404 
main(int argc,char ** argv)7405 int main (int argc, char **argv)
7406 {
7407   char buf [STDSIZE]; // temp buffer
7408 
7409   checkargs (argc, argv); // process command line parameters
7410 
7411   dirs = new Dirs (argv [0]); // get data directory (DATADIR, defined via autoconf)
7412 
7413 
7414   sprintf (buf, "Startup %s, %s ... ", argv [0], VERSIONSTRING);
7415   display (buf, LOG_MOST);
7416 
7417 #ifdef _MSC_VER
7418   display ("Windows detected ", LOG_MOST);
7419 #endif
7420 
7421   display ("Getting directory locations", LOG_ALL);
7422 
7423   if (!load_config ()) // try to load conf file (conf.cpp) and validate settings
7424   {
7425     // no conf file found => create new one
7426     display ("Creating new configuration", LOG_ALL);
7427     config_test (argc, argv); // do screen test
7428     firststart = true; // enable adjusting quality/view/graphics automatically by the game
7429   }
7430 
7431   save_config (); // save conf file (validated)
7432 
7433   load_configInterface (); // load interface settings from conf.interface and validate
7434   save_configInterface (); // save interface settings
7435 
7436   maploader = new MapLoader ();
7437 
7438 // here srand should be called to initialize the random number generator
7439 // this is currently done by grabbing random numbers via the init methods (not very elegant)
7440 
7441   server = NULL;
7442   client = NULL;
7443 
7444   display ("Creating/Loading pilots list", LOG_ALL);
7445   pilots = new PilotList (dirs->getSaves ("pilots")); // look at pilots.h
7446 
7447 // NO SDL FOUND => USE GLUT ONLY
7448 #ifdef USE_GLUT
7449 
7450   display ("Using GLUT only", LOG_MOST);
7451   if (!configinit)
7452   {
7453     glutInit (&argc, argv);
7454     glutInitDisplayMode (GLUT_DEPTH | GLUT_RGB | GLUT_DOUBLE);
7455     if (!setScreen (width, height, bpp, fullscreen))
7456     {
7457       load_saveconfig ();
7458       if (!setScreen (width, height, bpp, fullscreen))
7459       {
7460         sprintf (buf, "No working display mode %dx%d found", width, height);
7461         display (buf, LOG_FATAL);
7462         exit (EXIT_INIT);
7463       }
7464     }
7465   }
7466 
7467   display ("Calling main initialization method", LOG_ALL);
7468   myFirstInit ();
7469 
7470   display ("Creating dummy sound system, install SDL to enable sound", LOG_ALL);
7471   sound = new SoundSystem ();
7472 
7473   createMenu ();
7474 
7475   display ("Registering GLUT callbacks", LOG_ALL);
7476   glutReshapeFunc (myReshapeFunc);
7477   glutDisplayFunc (myDisplayFunc);
7478   glutKeyboardFunc (myKeyboardFunc);
7479   glutSpecialFunc (mySpecialFunc);
7480   glutPassiveMotionFunc (myPassiveMotionFunc);
7481   glutMouseFunc (myMouseFunc);
7482   glutIdleFunc (myIdleFunc);
7483   glutTimerFunc (20, myTimerFunc, 0);
7484 
7485   // parameters: visible angle, aspectracio, z-nearclip, z-farclip
7486   gluPerspective (visibleangle, (float) width / height, nearclippingplane * GLOBALSCALE, 50.0 * GLOBALSCALE);
7487 
7488   // no keyboard available with GLUT, as there are no KEY_DOWN/UP events
7489   if (controls <= 0)
7490     controls = CONTROLS_MOUSE;
7491 
7492   display ("Entering GLUT main loop", LOG_ALL);
7493   glutMainLoop(); // give controls to GLUT
7494 
7495 // SDL FOUND
7496 #else
7497 
7498   display ("Using SDL and GLUT", LOG_MOST);
7499   if (!configinit)
7500     if (SDL_Init (SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0)
7501     {
7502       sprintf (buf, "Couldn't initialize SDL: %s", SDL_GetError ());
7503       display (buf, LOG_FATAL);
7504       exit (EXIT_INIT);
7505     }
7506   atexit (SDL_Quit);
7507 
7508 // SDL_NET INSTALLED?
7509 #ifdef HAVE_SDL_NET
7510   if (SDLNet_Init () == -1) // initialize SDL_net
7511   {
7512     sprintf (buf, "SDLNet_Init: %s", SDLNet_GetError ());
7513     display (buf, LOG_FATAL);
7514     exit (EXIT_INIT);
7515   }
7516   display ("Using SDL_net", LOG_MOST);
7517 #endif
7518 
7519   if (!configinit)
7520   {
7521     if (!setScreen (width, height, bpp, fullscreen))
7522     {
7523       load_saveconfig ();
7524       if (!setScreen (width, height, bpp, fullscreen))
7525       {
7526         sprintf (buf, "No working display mode %dx%d found.", width, height);
7527         display (buf, LOG_FATAL);
7528         exit (EXIT_INIT);
7529       }
7530     }
7531   }
7532 
7533   display ("Setting SDL caption", LOG_ALL);
7534   SDL_WM_SetCaption ("GL-117", "GL-117"); // window name
7535 
7536   SDL_ShowCursor (0);
7537 
7538   display ("Creating sound system", LOG_ALL);
7539   sound = new SoundSystem (); // look at audio.cpp
7540   sound->volumesound = volumesound;
7541   sound->volumemusic = volumemusic;
7542   sound->setVolume (); // set all sound volumes
7543   sound->setVolumeMusic (); // set all music volumes
7544 
7545   display ("Playing startup music", LOG_ALL);
7546   sound->playMusic (1);
7547 #ifdef HAVE_SDL_MIXER
7548   Mix_HookMusicFinished (playRandomMusic);
7549 #endif
7550 
7551   display ("Calling main initialization method", LOG_ALL);
7552   myFirstInit ();
7553   myReshapeFunc (width, height);
7554 
7555   display ("Querying joystick", LOG_ALL);
7556   joysticks = SDL_NumJoysticks ();
7557   memset (jaxis, 0, maxjaxis * maxjoysticks * sizeof (int));
7558   if (joysticks > 0)
7559   {
7560     for (i = 0; i < joysticks; i ++)
7561     {
7562       SDL_JoystickEventState (SDL_ENABLE);
7563       sdljoystick [i] = SDL_JoystickOpen (i);
7564       sdljoystickaxes [i] = SDL_JoystickNumAxes (sdljoystick [i]);
7565       sprintf (buf, "Joystick \"%s\" detected", SDL_JoystickName (i));
7566       display (buf, LOG_MOST);
7567     }
7568   }
7569   else
7570   {
7571     display ("No joystick found", LOG_MOST);
7572 //    sdljoystick [0] = NULL;
7573     if (controls == CONTROLS_JOYSTICK) // no joystick available, so switch to mouse controls
7574       controls = CONTROLS_MOUSE;
7575   }
7576 
7577 // disable joystick manually
7578 //  joysticks = 0;
7579 
7580 /*  joysticks = 2;
7581   sdljoystickaxes [0] = 4;
7582   sdljoystickaxes [1] = 2;*/
7583 
7584   SDL_EnableUNICODE (1);
7585   SDL_EnableKeyRepeat (SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
7586 
7587 // Restrict mouse to SDL window
7588 //  SDL_WM_GrabInput (SDL_GRAB_ON);
7589 
7590   createMenu ();
7591 
7592   display ("Entering SDL main loop (GLUT emulation)", LOG_ALL);
7593   sdlMainLoop (); // simulate GLUT's main loop (above)
7594 
7595 #endif
7596 
7597   return 0; // exit without signaling errors
7598 }
7599 
7600 #endif
7601