1 #ifdef _WIN32
2 #include "windows.h"
3 #endif
4
5 #include "string.h"
6 #include "stdio.h"
7 #include "stdlib.h"
8 #include "math.h"
9
10 #include "GL/gl.h"
11 #include "GL/glu.h"
12 #include "GL/glut.h"
13 #include "SDL/SDL.h"
14 #include "SDL/SDL_mixer.h"
15
16 #include "list.h"
17 #include "vector.h"
18 #include "cmc.h"
19 #include "3dobject.h"
20 #include "shadow3dobject.h"
21 #include "piece3dobject.h"
22 #include "myglutaux.h"
23 #include "nether.h"
24
25 #include "glprintf.h"
26
27 extern int frames_per_sec;
28 extern bool fullscreen;
29 extern int shadows;
30 extern bool sound;
31 extern int up_key,down_key,left_key,right_key,fire_key,pause_key;
32 extern int level;
33 extern float MINY,MAXY,MINX,MAXX;
34 extern bool show_radar;
35
36 #ifdef _WRITE_REPORT_
37 FILE *debug_fp=0;
38 #endif
39
40
NETHER(char * mapname)41 NETHER::NETHER(char *mapname)
42 {
43
44 #ifdef _WRITE_REPORT_
45 debug_fp=fopen("report.txt","w");
46 fprintf(debug_fp,"Creating game...\n");
47 fflush(debug_fp);
48 #endif
49
50 if (shadows==1) {
51 lightpos[0]=-1000;
52 lightpos[1]=-3000;
53 lightpos[2]=5000;
54 lightpos[3]=1;
55 lightposv.x=lightpos[0];
56 lightposv.y=lightpos[1];
57 lightposv.z=lightpos[2];
58 } else {
59 lightpos[0]=0;
60 lightpos[1]=0;
61 lightpos[2]=5000;
62 lightpos[3]=1;
63 lightposv.x=lightpos[0];
64 lightposv.y=lightpos[1];
65 lightposv.z=lightpos[2];
66 } /* if */
67
68 #ifdef _WRITE_REPORT_
69 fprintf(debug_fp,"loading objects...\n");
70 fflush(debug_fp);
71 #endif
72
73 loadobjects();
74
75 #ifdef _WRITE_REPORT_
76 fprintf(debug_fp,"loading map...\n");
77 fflush(debug_fp);
78 #endif
79
80 /* Load map: */
81 if (!loadmap(mapname)) {
82 map_w=map_h=0;
83 map=0;
84 } /* if */
85
86 #ifdef _WRITE_REPORT_
87 fprintf(debug_fp,"Initializing game variables...\n");
88 fflush(debug_fp);
89 #endif
90
91 /* Set camera: */
92 viewp.x=map_w/2;
93 viewp.y=0;
94 camera.x=6;
95 camera.y=-6;
96 camera.z=11;
97 zoom=1;
98
99 /* Init game: */
100 day=0;
101 hour=0;
102 minute=0;
103 second=0;
104 shipp.x=4.0;
105 shipp.y=2.0;
106 shipp.z=3.0;
107 ship_op=OP_NONE;
108 ship_op2=OP_NONE;
109 ship_timemoving=0;
110
111 resources[0][0]=20;
112 resources[0][1]=0;
113 resources[0][2]=0;
114 resources[0][3]=0;
115 resources[0][4]=0;
116 resources[0][5]=0;
117 resources[0][6]=0;
118 resources[1][0]=20;
119 resources[1][1]=0;
120 resources[1][2]=0;
121 resources[1][3]=0;
122 resources[1][4]=0;
123 resources[1][5]=0;
124 resources[1][6]=0;
125 statistics[0][0]=0;
126 statistics[0][1]=0;
127 statistics[0][2]=0;
128 statistics[0][3]=0;
129 statistics[0][4]=0;
130 statistics[0][5]=0;
131 statistics[0][6]=0;
132 statistics[0][7]=0;
133 statistics[1][0]=0;
134 statistics[1][1]=0;
135 statistics[1][2]=0;
136 statistics[1][3]=0;
137 statistics[1][4]=0;
138 statistics[1][5]=0;
139 statistics[1][6]=0;
140 statistics[1][7]=0;
141 recomputestatistics=true;
142
143 game_state=STATE_PLAYING;
144 animation_timer=0;
145 construction_pointer=0;
146 controlled=0;
147 game_finished=0;
148 game_started=INTRO_TIME;
149
150 #ifdef _WRITE_REPORT_
151 fprintf(debug_fp,"Creating menus...\n");
152 fflush(debug_fp);
153 #endif
154
155 /* Init status: */
156 newmenu(GENERAL_MENU);
157 redrawmenu=2;
158 redrawradar=1;
159
160 #ifdef _WRITE_REPORT_
161 fprintf(debug_fp,"Initializing AI...\n");
162 fflush(debug_fp);
163 #endif
164
165 /* Init AI: */
166 AI_precomputations();
167
168 #ifdef _WRITE_REPORT_
169 fprintf(debug_fp,"Loading sounds...\n");
170 fflush(debug_fp);
171 #endif
172
173 /* Load sounds: */
174 S_shot=Mix_LoadWAV("/usr/local/share/netherearth/sound/shot.wav");
175 S_explosion=Mix_LoadWAV("/usr/local/share/netherearth/sound/explosion.wav");
176 S_select=Mix_LoadWAV("/usr/local/share/netherearth/sound/select.wav");
177 S_wrong=Mix_LoadWAV("/usr/local/share/netherearth/sound/wrong.wav");
178 S_construction=Mix_LoadWAV("/usr/local/share/netherearth/sound/construction.wav");
179
180 #ifdef _WRITE_REPORT_
181 fprintf(debug_fp,"Game created.\n");
182 fflush(debug_fp);
183 #endif
184
185 } /* NETHER::NETHER */
186
187
~NETHER()188 NETHER::~NETHER()
189 {
190
191 #ifdef _WRITE_REPORT_
192 fprintf(debug_fp,"Destroying Game...\n");
193 fflush(debug_fp);
194 #endif
195
196 #ifdef _WRITE_REPORT_
197 fprintf(debug_fp,"Deleting sounds...\n");
198 fflush(debug_fp);
199 #endif
200
201 Mix_FreeChunk(S_shot);
202 Mix_FreeChunk(S_explosion);
203 Mix_FreeChunk(S_select);
204 Mix_FreeChunk(S_wrong);
205 Mix_FreeChunk(S_construction);
206 S_shot=0;
207 S_explosion=0;
208 S_select=0;
209 S_wrong=0;
210 S_construction=0;
211
212 #ifdef _WRITE_REPORT_
213 fprintf(debug_fp,"Deleting objects...\n");
214 fflush(debug_fp);
215 #endif
216
217 deleteobjects();
218
219 #ifdef _WRITE_REPORT_
220 fprintf(debug_fp,"Deleting AI...\n");
221 fflush(debug_fp);
222 #endif
223
224 AI_deleteprecomputations();
225
226 #ifdef _WRITE_REPORT_
227 fprintf(debug_fp,"Deleting map...\n");
228 fflush(debug_fp);
229 #endif
230
231 /* Delete map: */
232 if (map!=0) delete map;
233 map=0;
234 map_w=map_h=0;
235
236 #ifdef _WRITE_REPORT_
237 fprintf(debug_fp,"Game destroyed.\n");
238 fclose(debug_fp);
239 #endif
240
241 } /* NETHER::~NETHER */
242
243
loadobjects(void)244 void NETHER::loadobjects(void)
245 {
246 /* Load 3D objects: */
247 char *tnames[12]={"/usr/local/share/netherearth/models/grass1.ase","/usr/local/share/netherearth/models/rough.ase","/usr/local/share/netherearth/models/rocks.ase","/usr/local/share/netherearth/models/heavyrocks.ase",
248 "/usr/local/share/netherearth/models/hole1.asc","/usr/local/share/netherearth/models/hole2.asc","/usr/local/share/netherearth/models/hole3.asc",
249 "/usr/local/share/netherearth/models/hole4.asc","/usr/local/share/netherearth/models/hole5.asc","/usr/local/share/netherearth/models/hole6.asc",
250 "/usr/local/share/netherearth/models/grass2.ase","/usr/local/share/netherearth/models/grass3.ase"};
251 char *bnames[9]={"/usr/local/share/netherearth/models/lowwall1.ase","/usr/local/share/netherearth/models/lowwall2.ase","/usr/local/share/netherearth/models/lowwall3.ase",
252 "/usr/local/share/netherearth/models/highwall1.ase","/usr/local/share/netherearth/models/factory.ase","/usr/local/share/netherearth/models/fence.asc",
253 "/usr/local/share/netherearth/models/flag.asc","/usr/local/share/netherearth/models/highwall2.ase","/usr/local/share/netherearth/models/warbase.ase"};
254 char *pnames[11]={"/usr/local/share/netherearth/models/h-bipod.ase","/usr/local/share/netherearth/models/h-tracks.ase","/usr/local/share/netherearth/models/h-antigrav.ase",
255 "/usr/local/share/netherearth/models/h-cannon.ase","/usr/local/share/netherearth/models/h-missiles.ase","/usr/local/share/netherearth/models/h-phasers.ase",
256 "/usr/local/share/netherearth/models/h-nuclear.ase","/usr/local/share/netherearth/models/h-electronics.ase",
257 "/usr/local/share/netherearth/models/h-bipod-base.ase","/usr/local/share/netherearth/models/h-bipod-rleg.ase","/usr/local/share/netherearth/models/h-bipod-lleg.ase"};
258 char *pnames2[11]={"/usr/local/share/netherearth/models/e-bipod.ase","/usr/local/share/netherearth/models/e-tracks.ase","/usr/local/share/netherearth/models/e-antigrav.ase",
259 "/usr/local/share/netherearth/models/e-cannon.ase","/usr/local/share/netherearth/models/e-missiles.ase","/usr/local/share/netherearth/models/e-phasers.ase",
260 "/usr/local/share/netherearth/models/nuclear.asc","/usr/local/share/netherearth/models/e-electronics.ase",
261 "/usr/local/share/netherearth/models/e-bipod-base.ase","/usr/local/share/netherearth/models/e-bipod-rleg.ase","/usr/local/share/netherearth/models/e-bipod-lleg.ase"};
262 char *bullnames[3]={"/usr/local/share/netherearth/models/bullet1.asc","/usr/local/share/netherearth/models/bullet2.asc","/usr/local/share/netherearth/models/bullet3.asc"};
263 float pscale[11]={0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.45,0.375,0.375};
264 float bscale[9]={0.5,0.5,0.5,
265 0.5,0.5,1.0,
266 0.25,0.5,0.5};
267 float bullscale[3]={0.05,0.3,0.4};
268
269 float r[12]={0.0 ,0.7f ,0.6f ,0.5f ,0.0 ,0.0 ,0.0 ,0.0 ,0.0 ,0.0 ,0.0 ,0.0};
270 float g[12]={0.733f ,0.5f ,0.45f ,0.4f ,0.733f ,0.733f ,0.733f ,0.733f ,0.733f ,0.733f ,0.733f ,0.733f};
271 float b[12]={0.0 ,0.0 ,0.0 ,0.0 ,0.0 ,0.0 ,0.0 ,0.0 ,0.0 ,0.0 ,0.0 ,0.0};
272 int i;
273
274 n_objs=12;
275 tile=new C3DObject *[n_objs];
276 tile_r=new float[n_objs];
277 tile_g=new float[n_objs];
278 tile_b=new float[n_objs];
279 for(i=0;i<n_objs;i++) {
280 tile[i]=new C3DObject(tnames[i],"/usr/local/share/netherearth/textures/");
281 tile[i]->normalize(0.50f);
282 tile[i]->makepositive();
283 tile_r[i]=r[i];
284 tile_g[i]=g[i];
285 tile_b[i]=b[i];
286 } /* for */
287
288 tile[4]->moveobject(0,0,-0.05);
289 tile[5]->moveobject(0,0,-0.05);
290 tile[6]->moveobject(0,0,-0.05);
291 tile[7]->moveobject(0,0,-0.05);
292 tile[8]->moveobject(0,0,-0.05);
293 tile[9]->moveobject(0,0,-0.05);
294
295 n_buildings=9;
296 building_tile=new Shadow3DObject *[n_buildings];
297 for(i=0;i<n_buildings;i++) {
298 building_tile[i]=new Shadow3DObject(bnames[i],"/usr/local/share/netherearth/textures/");
299 building_tile[i]->normalize(bscale[i]);
300 building_tile[i]->makepositive();
301 } /* for */
302 building_tile[5]->moveobject(0,0,0.01);
303 building_tile[6]->moveobject(0.4,0.4,0.0);
304
305 n_pieces=11;
306 piece_tile[0]=new Piece3DObject *[n_pieces];
307 piece_tile[1]=new Piece3DObject *[n_pieces];
308 for(i=0;i<n_pieces;i++) {
309 piece_tile[0][i]=new Piece3DObject(pnames[i],"/usr/local/share/netherearth/textures/");
310 piece_tile[0][i]->normalize(pscale[i]);
311 piece_tile[0][i]->makepositive();
312 piece_tile[1][i]=new Piece3DObject(pnames2[i],"/usr/local/share/netherearth/textures/");
313 piece_tile[1][i]->normalize(pscale[i]);
314 piece_tile[1][i]->makepositive();
315 } /* for */
316 piece_tile[0][0]->moveobject(-0.5,-0.5,0.0);
317 piece_tile[0][1]->moveobject(-0.5,-0.5,0.0);
318 piece_tile[0][2]->moveobject(-0.5,-0.5,0.2);
319 piece_tile[0][3]->moveobject(-0.5,-0.5,0.0);
320 piece_tile[0][4]->moveobject(-0.5,-0.45,0.0);
321 piece_tile[0][5]->moveobject(-0.5,-0.5,0.0);
322 piece_tile[0][6]->moveobject(-0.5,-0.5,0.0);
323 piece_tile[0][7]->moveobject(-0.32,-0.3,0.0);
324 piece_tile[0][8]->moveobject(-0.45,-0.45,0.6);
325 piece_tile[0][9]->moveobject(-0.4,-0.5,0.0);
326 piece_tile[0][10]->moveobject(-0.4,0.2,0.0);
327
328 piece_tile[1][0]->moveobject(-0.5,-0.5,0.0);
329 piece_tile[1][1]->moveobject(-0.5,-0.5,0.0);
330 piece_tile[1][2]->moveobject(-0.5,-0.5,0.2);
331 piece_tile[1][3]->moveobject(-0.5,-0.5,0.0);
332 piece_tile[1][4]->moveobject(-0.5,-0.45,0.0);
333 piece_tile[1][5]->moveobject(-0.5,-0.5,0.0);
334 piece_tile[1][6]->moveobject(-0.5,-0.5,0.0);
335 piece_tile[1][7]->moveobject(-0.32,-0.3,0.0);
336 piece_tile[1][8]->moveobject(-0.45,-0.45,0.6);
337 piece_tile[1][9]->moveobject(-0.4,-0.5,0.0);
338 piece_tile[1][10]->moveobject(-0.4,0.2,0.0);
339
340 ship=new Shadow3DObject("/usr/local/share/netherearth/models/ship.asc","/usr/local/share/netherearth/textures/");
341 ship->normalize(0.5f);
342 ship->makepositive();
343
344 n_bullets=3;
345 bullet_tile=new Piece3DObject *[n_bullets];
346 for(i=0;i<n_bullets;i++) {
347 bullet_tile[i]=new Piece3DObject(bullnames[i],"/usr/local/share/netherearth/textures/");
348 bullet_tile[i]->normalize(bullscale[i]);
349 } /* for */
350
351 ship->ComputeShadow(lightposv);
352 for(i=0;i<n_buildings;i++) building_tile[i]->ComputeShadow(lightposv);
353 for(i=0;i<n_pieces;i++) piece_tile[0][i]->ComputeFixedShadows(lightposv);
354 for(i=0;i<n_pieces;i++) piece_tile[1][i]->ComputeFixedShadows(lightposv);
355 for(i=0;i<n_bullets;i++) bullet_tile[i]->ComputeFixedShadows(lightposv);
356
357 construction_tile[0]=new C3DObject("/usr/local/share/netherearth/models/construction1.asc","/usr/local/share/netherearth/textures/");
358 construction_tile[1]=new C3DObject("/usr/local/share/netherearth/models/construction2.asc","/usr/local/share/netherearth/textures/");
359 construction_tile[2]=new C3DObject("/usr/local/share/netherearth/models/construction3.asc","/usr/local/share/netherearth/textures/");
360 construction_tile[0]->normalize(10.0);
361 construction_tile[1]->normalize(9.0);
362 construction_tile[2]->normalize(7.0);
363
364 message_tile[0]=new C3DObject("/usr/local/share/netherearth/models/go.ase","/usr/local/share/netherearth/textures/");
365 message_tile[1]=new C3DObject("/usr/local/share/netherearth/models/youwin.ase","/usr/local/share/netherearth/textures/");
366 message_tile[2]=new C3DObject("/usr/local/share/netherearth/models/gameover.ase","/usr/local/share/netherearth/textures/");
367 message_tile[0]->normalize(4.0);
368 message_tile[1]->normalize(4.0);
369 message_tile[2]->normalize(4.0);
370 } /* NETHER::loadobjects */
371
372
deleteobjects(void)373 void NETHER::deleteobjects(void)
374 {
375 int i;
376
377 /* Delete objects: */
378 for(i=0;i<n_objs;i++) delete tile[i];
379 delete tile;
380 tile=0;
381 delete tile_r;
382 tile_r=0;
383 delete tile_g;
384 tile_g=0;
385 delete tile_b;
386 tile_b=0;
387 delete ship;
388 ship=0;
389 for(i=0;i<n_buildings;i++) delete building_tile[i];
390 delete building_tile;
391 building_tile=0;
392 for(i=0;i<n_pieces;i++) delete piece_tile[0][i];
393 for(i=0;i<n_pieces;i++) delete piece_tile[1][i];
394 delete piece_tile[0];
395 delete piece_tile[1];
396 piece_tile[0]=0;
397 piece_tile[1]=0;
398 delete construction_tile[0];
399 delete construction_tile[1];
400 delete construction_tile[2];
401 construction_tile[0]=0;
402 construction_tile[1]=0;
403 construction_tile[2]=0;
404 delete message_tile[0];
405 delete message_tile[1];
406 delete message_tile[2];
407 for(i=0;i<n_bullets;i++) delete bullet_tile[i];
408 delete bullet_tile;
409 bullet_tile=0;
410 } /* NETHER::deleteobjects */
411
412
refresh_display_lists(void)413 void NETHER::refresh_display_lists(void)
414 {
415 int i;
416
417 for(i=0;i<n_objs;i++) {
418 tile[i]->refresh_display_lists();
419 } /* for */
420
421 ship->refresh_display_lists();
422
423 for(i=0;i<n_buildings;i++) {
424 building_tile[i]->refresh_display_lists();
425 } /* for */
426
427 for(i=0;i<n_pieces;i++) {
428 piece_tile[0][i]->refresh_display_lists();
429 piece_tile[1][i]->refresh_display_lists();
430 } /* for */
431
432 for(i=0;i<3;i++) {
433 construction_tile[i]->refresh_display_lists();
434 } /* for */
435 } /* NETHER::refresh_display_lists */
436
437
438
gamecycle(int w,int h)439 bool NETHER::gamecycle(int w,int h)
440 {
441 int i;
442 bool retval=true;
443 unsigned char *keyboard;
444
445 SDL_PumpEvents();
446 keyboard = SDL_GetKeyState(NULL);
447
448 #ifdef _WRITE_REPORT_
449 fprintf(debug_fp,"Cycle start.\n");
450 fprintf(debug_fp,"game_state: %i\n",game_state);
451 fflush(debug_fp);
452 #endif
453
454 switch(game_state) {
455 case STATE_PLAYING:
456 retval=cycle(keyboard);
457 break;
458 case STATE_CONSTRUCTION:
459 retval=construction_cycle(keyboard);
460 break;
461 case STATE_PAUSE:
462 case STATE_SAVINGGAME:
463 case STATE_LOADINGGAME:
464 retval=option_cycle(keyboard);
465 break;
466 } /* switch */
467
468 for(i=0;i<SDLK_LAST;i++) old_keyboard[i]=keyboard[i];
469
470 #ifdef _WRITE_REPORT_
471 fprintf(debug_fp,"Cycle end: %i\n",retval);
472 fflush(debug_fp);
473 #endif
474
475 return retval;
476 } /* NETHER::gamecycle */
477
478
gameredraw(int w,int h)479 void NETHER::gameredraw(int w,int h)
480 {
481
482 #ifdef _WRITE_REPORT_
483 fprintf(debug_fp,"Redraw start.\n");
484 fprintf(debug_fp,"game_state: %i\n",game_state);
485 fflush(debug_fp);
486 #endif
487
488 switch(game_state) {
489 case STATE_PLAYING:
490 draw(w,h);
491 break;
492 case STATE_CONSTRUCTION:
493 construction_draw(w,h);
494 break;
495 case STATE_PAUSE:
496 case STATE_SAVINGGAME:
497 case STATE_LOADINGGAME:
498 draw(w,h);
499 options_draw(w,h);
500 break;
501 } /* switch */
502
503 SDL_GL_SwapBuffers();
504
505 #ifdef _WRITE_REPORT_
506 fprintf(debug_fp,"Redraw end.");
507 fflush(debug_fp);
508 #endif
509
510 } /* gameredraw */
511
512
draw(int width,int height)513 void NETHER::draw(int width,int height)
514 {
515 float lightpos2[4]={0,0,1000,0};
516 float tmpls[4]={1.0F,1.0F,1.0F,1.0};
517 float tmpld[4]={0.6F,0.6F,0.6F,1.0};
518 float tmpla[4]={0.2F,0.2F,0.2F,1.0};
519 float ratio;
520 int split = int((width*25.0F)/32.0F);
521 int splity = 0;
522
523 if (show_radar) splity = int((height*2.0F)/15.0F)+1;
524 else splity = 0;
525
526 /* Enable Lights, etc.: */
527 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
528 glEnable(GL_LIGHT0);
529 glLightfv(GL_LIGHT0,GL_AMBIENT,tmpla);
530 glLightfv(GL_LIGHT0,GL_DIFFUSE,tmpld);
531 glLightfv(GL_LIGHT0,GL_SPECULAR,tmpls);
532 glEnable(GL_LIGHTING);
533 glEnable(GL_COLOR_MATERIAL);
534 glShadeModel( GL_SMOOTH );
535 glCullFace( GL_BACK );
536 glFrontFace( GL_CCW );
537 glEnable( GL_CULL_FACE );
538 glEnable( GL_SCISSOR_TEST );
539 glEnable( GL_DEPTH_TEST );
540 glDepthFunc( GL_LEQUAL );
541 glClearStencil(0);
542
543 /* Draw the GAME screen: */
544 glLightfv(GL_LIGHT0,GL_POSITION,lightpos);
545 glClearColor(0,0,0,0.0);
546 glViewport(0,splity,split,height-splity);
547 ratio=float(split)/float(height-splity);
548 glMatrixMode( GL_PROJECTION );
549 glLoadIdentity( );
550 gluPerspective( 30.0, ratio, 1.0, 1024.0 );
551 glScissor(0,splity,split,height-splity);
552 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
553 draw_game(false);
554 if (shadows) {
555 /* Set STENCIL Buffer: */
556 glStencilMask(1);
557 glEnable(GL_STENCIL_TEST);
558 glDepthMask(GL_FALSE);
559 glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);
560 glStencilFunc(GL_ALWAYS,1,1);
561 glStencilOp(GL_KEEP,GL_KEEP,GL_REPLACE);
562 draw_game(true);
563 glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
564
565 /* Draw shadow poligon: */
566 glDepthFunc(GL_ALWAYS);
567 glDisable(GL_CULL_FACE);
568
569 glColor4f(0.0,0.0,0.0,0.4f);
570 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
571 glEnable(GL_BLEND);
572
573 glStencilFunc(GL_NOTEQUAL,0,1);
574 glStencilOp(GL_KEEP,GL_KEEP,GL_KEEP);
575 glMatrixMode(GL_PROJECTION);
576 glPushMatrix();
577 glLoadIdentity();
578 glBegin(GL_TRIANGLE_STRIP);
579 glVertex3f(-1.0, 1.0,0.0);
580 glVertex3f(-1.0,-1.0,0.0);
581 glVertex3f( 1.0, 1.0,0.0);
582 glVertex3f( 1.0,-1.0,0.0);
583 glEnd();
584 glPopMatrix();
585
586 glDisable(GL_BLEND);
587
588 glDepthMask(GL_TRUE);
589 glDepthFunc(GL_LEQUAL);
590 glEnable(GL_CULL_FACE);
591 glDisable(GL_STENCIL_TEST);
592 } /* if */
593
594 if (game_started>0) {
595 glMatrixMode( GL_PROJECTION );
596 glLoadIdentity( );
597 gluPerspective( 30.0, ratio, 1.0, 1024.0 );
598 gluLookAt(0,0,30,0,0,0,0,1,0);
599 glClear(GL_DEPTH_BUFFER_BIT);
600 glMatrixMode(GL_MODELVIEW);
601 glLoadIdentity();
602
603 if (game_started>40) glTranslatef(0,0,(game_started-40)*2);
604 if (game_started<20) glTranslatef(0,0,(20-game_started)*2);
605 message_tile[0]->draw(1.0,1.0,1.0);
606 } /* if */
607
608 if (game_finished>100) {
609 glMatrixMode( GL_PROJECTION );
610 glLoadIdentity( );
611 gluPerspective( 30.0, ratio, 1.0, 1024.0 );
612 gluLookAt(0,0,30,0,0,0,0,1,0);
613 glClear(GL_DEPTH_BUFFER_BIT);
614 glMatrixMode(GL_MODELVIEW);
615 glLoadIdentity();
616
617 if (game_finished<120) glTranslatef(0,0,(120-game_finished)*2);
618 if (game_finished>240) glTranslatef(0,0,(game_finished-240)*2);
619 if (statistics[0][0]==0) message_tile[2]->draw(1.0,1.0,1.0);
620 else message_tile[1]->draw(1.0,1.0,1.0);
621 } /* if */
622
623 /* Draw the RADAR screen: */
624 if (show_radar && redrawradar<=1) {
625
626 glLightfv(GL_LIGHT0,GL_POSITION,lightpos2);
627 glClearColor(0.0,0.0,0,0);
628 glViewport(0,0,split,splity);
629 glMatrixMode( GL_PROJECTION );
630 glLoadIdentity( );
631 glOrtho(0,float(split),0,float(splity),-100,100);
632 glScissor(0,0,split,splity);
633 glScalef(width/640.0,height/480.0,1);
634 draw_radar();
635 } /* if */
636 redrawradar--;
637 if (redrawradar<0) redrawradar=3;
638
639 /* Draw the STATUS screen: */
640 if (redrawmenu!=0) {
641 redrawmenu--;
642
643 glLightfv(GL_LIGHT0,GL_POSITION,lightpos2);
644 glClearColor(0,0,0.2,0);
645 glViewport(split,0,width-split,height);
646 glMatrixMode( GL_PROJECTION );
647 glLoadIdentity( );
648 glOrtho(0,float(width-split),0,height,-100,100);
649 glScissor(split,0,width-split,height);
650 glScalef(width/640.0,height/480.0,1);
651 draw_status();
652
653 /*
654 glMatrixMode(GL_MODELVIEW);
655 glPushMatrix();
656 glLoadIdentity();
657 glTranslatef(70.0,10.0,0);
658 glColor3f(1.0f,1.0f,1.0f);
659 scaledglprintf(0.1f,0.1f,"FPS: %i",frames_per_sec);
660 glPopMatrix();
661 */
662
663 } /* if */
664 } /* NETHER::draw */
665
666
667
draw_game(bool shadows)668 void NETHER::draw_game(bool shadows)
669 {
670 {
671 MINY=-8*zoom;
672 MINX=-(10+viewp.z*4)*zoom;
673 MAXY=(9+viewp.z*4)*zoom;
674 MAXX=8*zoom;
675 }
676
677 if (!explosions.EmptyP()) {
678 int minstep=128;
679 List<EXPLOSION> l;
680 EXPLOSION *n;
681 float offs=0.0,r;
682
683 l.Instance(explosions);
684 l.Rewind();
685 while(l.Iterate(n)) {
686 if (n->size==2 && n->step<minstep) minstep=n->step;
687 } /* while */
688
689 r=(128-minstep)/256.0;
690 offs=sin(minstep)*r;
691
692 gluLookAt(viewp.x+camera.x*zoom+offs,viewp.y+camera.y*zoom+offs,viewp.z+camera.z*zoom,viewp.x+offs,viewp.y+offs,viewp.z,0,0,1);
693 } else {
694 gluLookAt(viewp.x+camera.x*zoom,viewp.y+camera.y*zoom,viewp.z+camera.z*zoom,viewp.x,viewp.y,viewp.z,0,0,1);
695 } /* if */
696
697 glMatrixMode(GL_MODELVIEW);
698 glLoadIdentity();
699
700 /* Draw: */
701
702 /* Draw the map: */
703 drawmap(shadows);
704
705 /* Draw the robots and bullets: */
706 {
707 int i;
708 List<ROBOT> l;
709 List<BULLET> l2;
710 ROBOT *r;
711 BULLET *b;
712
713 for(i=0;i<2;i++) {
714 l.Instance(robots[i]);
715 l.Rewind();
716 while(l.Iterate(r)) {
717 if (r->pos.y>=(viewp.y+MINY) &&
718 r->pos.y<=(viewp.y+MAXY) &&
719 r->pos.x>=(viewp.x+MINX) &&
720 r->pos.x<=(viewp.x+MAXX)) {
721 glPushMatrix();
722 glTranslatef(r->pos.x,r->pos.y,r->pos.z);
723 DrawRobot(r,i,shadows);
724 glPopMatrix();
725 } /* if */
726 } /* while */
727 } /* for */
728
729 l2.Instance(bullets);
730 l2.Rewind();
731 while(l2.Iterate(b)) {
732 if (b->pos.y>=(viewp.y+MINY) &&
733 b->pos.y<=(viewp.y+MAXY) &&
734 b->pos.x>=(viewp.x+MINX) &&
735 b->pos.x<=(viewp.x+MAXX)) {
736 glPushMatrix();
737 glTranslatef(b->pos.x,b->pos.y,b->pos.z);
738 DrawBullet(b,shadows);
739 glPopMatrix();
740 } /* if */
741 } /* while */
742 }
743
744 /* Draw the ship: */
745 glPushMatrix();
746 glTranslatef(shipp.x,shipp.y,shipp.z);
747 if (!shadows) ship->draw(0.7,0.7,0.7);
748 glPopMatrix();
749
750 if (shadows) {
751 float sx,sy;
752 float x[2],y[2];
753 float minz;
754 Vector light;
755
756 light=lightposv;
757 light=light/light.z;
758
759 sx=shipp.x-light.x*shipp.z;
760 sy=shipp.y-light.y*shipp.z;
761
762 if (controlled==0) {
763 x[0]=sx+ship->shdw_cmc.x[0];
764 x[1]=sx+ship->shdw_cmc.x[1];
765 y[0]=sy+ship->shdw_cmc.y[0];
766 y[1]=sy+ship->shdw_cmc.y[1];
767 minz=MapMaxZ(x,y);
768 } else {
769 minz=controlled->pos.z;
770 } /* if */
771
772 glPushMatrix();
773 glTranslatef(sx,sy,minz+0.05);
774 if (shadows) ship->DrawShadow(0,0,0,0.5);
775 glPopMatrix();
776 }
777
778 /* Draw the extras: */
779
780 /* Draw nuclear explosions: */
781 if (!shadows) {
782 List<EXPLOSION> l;
783 EXPLOSION *n;
784 float a,r;
785
786 l.Instance(explosions);
787 l.Rewind();
788 while(l.Iterate(n)) {
789 a=(128.0f-n->step)/80.0f;
790 r=1.0;
791 if (n->size==0) {
792 r=(float(n->step)/512.0f)+0.1;
793 } /* if */
794 if (n->size==1) {
795 r=(float(n->step)/96.0f)+0.5;
796 } /* if */
797 if (n->size==2) {
798 r=(float(n->step)/48.0f)+1.0;
799 } /* if */
800 if (a<0) a=0;
801 if (a>1) a=1;
802
803 glPushMatrix();
804 glTranslatef(n->pos.x,n->pos.y,n->pos.z);
805 glColor4f(1.0f,0.5f,0.0,a);
806 glDepthMask(GL_FALSE);
807 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
808 glEnable(GL_BLEND);
809 glutSolidSphere(r,8,8);
810 glDisable(GL_BLEND);
811 glDepthMask(GL_TRUE);
812 glPopMatrix();
813 } /* while */
814 }
815
816 /* Draw the particles: */
817 if (!shadows) {
818 List<PARTICLE> l;
819 PARTICLE *p;
820
821 l.Instance(particles);
822 l.Rewind();
823 while(l.Iterate(p)) {
824 if (p->pos.y>=(viewp.y+MINY) &&
825 p->pos.y<=(viewp.y+MAXY) &&
826 p->pos.x>=(viewp.x+MINX) &&
827 p->pos.x<=(viewp.x+MAXX)) DrawParticle(p);
828 } /* if */
829
830 } /* if */
831
832 } /* NETHER::draw_screen */
833
834
draw_status(void)835 void NETHER::draw_status(void)
836 {
837 /* Clear the color and depth buffers. */
838 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
839
840 glMatrixMode(GL_MODELVIEW);
841 glLoadIdentity();
842
843 /* Draw buttons: */
844 {
845 List<STATUSBUTTON> l;
846 STATUSBUTTON *b;
847 float angle,cf;
848
849 l.Instance(buttons);
850 l.Rewind();
851 while(l.Iterate(b)) {
852 if (b->status>=-16) {
853 angle=(float(b->status)*90.0)/16.0;
854 cf=float((16-abs(b->status)))/16.0;
855 glPushMatrix();
856 glTranslatef(b->x,b->y,0);
857 glRotatef(angle,0,1,0);
858
859 /* Draw button: */
860 glColor3f(b->r*cf,b->g*cf,b->b*cf);
861 glutSolidBox(b->sx/2,b->sy/2,10.0);
862 glTranslatef(0,0,11);
863
864 glColor3f(1.0,1.0,1.0);
865 if (b->text1[0]!=0) {
866 if (b->text2[0]!=0) {
867 glTranslatef(0,-12,0);
868 scaledglprintf(0.1f,0.1f,b->text2);
869 glTranslatef(0,17,0);
870 scaledglprintf(0.1f,0.1f,b->text1);
871 } else {
872 glTranslatef(0,-3,0);
873 scaledglprintf(0.1f,0.1f,b->text1);
874 } /* if */
875 } /* if */
876
877 glPopMatrix();
878 } /* if */
879 } /* while */
880 }
881
882 glPushMatrix();
883 switch(act_menu) {
884 case GENERAL_MENU:
885 {
886 STATUSBUTTON *b;
887 b=getbutton(STATUS_BUTTON);
888 if (b!=0 && b->status==0) {
889 statistics[0][7]=robots[0].Length();
890 statistics[1][7]=robots[1].Length();
891
892 glColor3f(0.5f,0.5f,1.0f);
893 glTranslatef(70,356,0);
894 scaledglprintf(0.1f,0.1f,"%i WARBASES %i",statistics[1][0],statistics[0][0]);
895 glTranslatef(0,-18,0);
896 scaledglprintf(0.1f,0.1f,"%i ELECTR'S %i",statistics[1][1],statistics[0][1]);
897 glTranslatef(0,-18,0);
898 scaledglprintf(0.1f,0.1f,"%i NUCLEAR %i",statistics[1][2],statistics[0][2]);
899 glTranslatef(0,-18,0);
900 scaledglprintf(0.1f,0.1f,"%i PHASERS %i",statistics[1][3],statistics[0][3]);
901 glTranslatef(0,-18,0);
902 scaledglprintf(0.1f,0.1f,"%i MISSILES %i",statistics[1][4],statistics[0][4]);
903 glTranslatef(0,-18,0);
904 scaledglprintf(0.1f,0.1f,"%i CANNON %i",statistics[1][5],statistics[0][5]);
905 glTranslatef(0,-18,0);
906 scaledglprintf(0.1f,0.1f,"%i CHASSIS %i",statistics[1][6],statistics[0][6]);
907 glTranslatef(0,-18,0);
908 scaledglprintf(0.1f,0.1f,"%.2i ROBOTS %.2i",statistics[1][7],statistics[0][7]);
909
910 glColor3f(0.0f,0.8f,0.0f);
911 glTranslatef(0,-65,0);
912 scaledglprintf(0.1f,0.1f,"GENERAL %.2i",resources[0][0]);
913 glTranslatef(0,-18,0);
914 scaledglprintf(0.1f,0.1f,"ELECTR' %.2i",resources[0][1]);
915 glTranslatef(0,-18,0);
916 scaledglprintf(0.1f,0.1f,"NUCLEAR %.2i",resources[0][2]);
917 glTranslatef(0,-18,0);
918 scaledglprintf(0.1f,0.1f,"PHASERS %.2i",resources[0][3]);
919 glTranslatef(0,-18,0);
920 scaledglprintf(0.1f,0.1f,"MISSILE %.2i",resources[0][4]);
921 glTranslatef(0,-18,0);
922 scaledglprintf(0.1f,0.1f,"CANNON %.2i",resources[0][5]);
923 glTranslatef(0,-18,0);
924 scaledglprintf(0.1f,0.1f,"CHASSIS %.2i",resources[0][6]);
925 } /* if */
926 }
927 break;
928 case ROBOT_MENU:
929 case DIRECTCONTROL_MENU:
930 {
931 STATUSBUTTON *b;
932
933 b=getbutton(ROBOT1_BUTTON);
934 if (b!=0 && b->status==0) {
935
936 glTranslatef(70,140,0);
937 glColor3f(1.0f,1.0f,0.0);
938 scaledglprintf(0.1f,0.1f,"-ORDERS-");
939 glColor3f(0.5f,0.5f,1.0f);
940 switch(controlled->program) {
941 case PROGRAM_STOPDEFEND:
942 glTranslatef(0,-20,0);
943 scaledglprintf(0.1f,0.1f,"STOP");
944 glTranslatef(0,-18,0);
945 scaledglprintf(0.1f,0.1f,"AND");
946 glTranslatef(0,-18,0);
947 scaledglprintf(0.1f,0.1f,"DEFEND");
948 break;
949 case PROGRAM_ADVANCE:
950 glTranslatef(0,-20,0);
951 scaledglprintf(0.1f,0.1f,"ADVANCE");
952 glTranslatef(0,-18,0);
953 scaledglprintf(0.1f,0.1f,"%.2i",controlled->program_parameter/2);
954 glTranslatef(0,-18,0);
955 scaledglprintf(0.1f,0.1f,"MILES");
956 break;
957 case PROGRAM_RETREAT:
958 glTranslatef(0,-20,0);
959 scaledglprintf(0.1f,0.1f,"RETREAT");
960 glTranslatef(0,-18,0);
961 scaledglprintf(0.1f,0.1f,"%.2i",controlled->program_parameter/2);
962 glTranslatef(0,-18,0);
963 scaledglprintf(0.1f,0.1f,"MILES");
964 break;
965 case PROGRAM_DESTROY:
966 glTranslatef(0,-20,0);
967 scaledglprintf(0.1f,0.1f,"DESTROY");
968 switch(controlled->program_parameter) {
969 case P_PARAM_ROBOTS:
970 glTranslatef(0,-18,0);
971 scaledglprintf(0.1f,0.1f,"ENEMY");
972 glTranslatef(0,-18,0);
973 scaledglprintf(0.1f,0.1f,"ROBOTS");
974 break;
975 case P_PARAM_WARBASES:
976 glTranslatef(0,-18,0);
977 scaledglprintf(0.1f,0.1f,"ENEMY");
978 glTranslatef(0,-18,0);
979 scaledglprintf(0.1f,0.1f,"WARBASES");
980 break;
981 case P_PARAM_NFACTORIES:
982 glTranslatef(0,-18,0);
983 scaledglprintf(0.1f,0.1f,"NEUTRAL");
984 glTranslatef(0,-18,0);
985 scaledglprintf(0.1f,0.1f,"FACTORIES");
986 break;
987 case P_PARAM_EFACTORIES:
988 glTranslatef(0,-18,0);
989 scaledglprintf(0.1f,0.1f,"ENEMY");
990 glTranslatef(0,-18,0);
991 scaledglprintf(0.1f,0.1f,"FACTORIES");
992 break;
993 } /* switch */
994 break;
995 case PROGRAM_CAPTURE:
996 glTranslatef(0,-20,0);
997 scaledglprintf(0.1f,0.1f,"CAPTURE");
998 switch(controlled->program_parameter) {
999 case P_PARAM_ROBOTS:
1000 glTranslatef(0,-18,0);
1001 scaledglprintf(0.1f,0.1f,"ENEMY");
1002 glTranslatef(0,-18,0);
1003 scaledglprintf(0.1f,0.1f,"ROBOTS");
1004 break;
1005 case P_PARAM_WARBASES:
1006 glTranslatef(0,-18,0);
1007 scaledglprintf(0.1f,0.1f,"ENEMY");
1008 glTranslatef(0,-18,0);
1009 scaledglprintf(0.1f,0.1f,"WARBASES");
1010 break;
1011 case P_PARAM_NFACTORIES:
1012 glTranslatef(0,-18,0);
1013 scaledglprintf(0.1f,0.1f,"NEUTRAL");
1014 glTranslatef(0,-18,0);
1015 scaledglprintf(0.1f,0.1f,"FACTORIES");
1016 break;
1017 case P_PARAM_EFACTORIES:
1018 glTranslatef(0,-18,0);
1019 scaledglprintf(0.1f,0.1f,"ENEMY");
1020 glTranslatef(0,-18,0);
1021 scaledglprintf(0.1f,0.1f,"FACTORIES");
1022 break;
1023 } /* switch */
1024 break;
1025 } /* switch */
1026
1027 glTranslatef(0,-44,0);
1028 glColor3f(1.0f,1.0f,0.0);
1029 scaledglprintf(0.1f,0.1f,"STRENGTH");
1030 glTranslatef(0,-18,0);
1031 glColor3f(1.0f,1.0f,1.0f);
1032 scaledglprintf(0.1f,0.1f,"%.3i%c",controlled->strength,'%');
1033 } /* if */
1034 }
1035 break;
1036
1037 case COMBATMODE_MENU:
1038 case DIRECTCONTROL2_MENU:
1039
1040 glTranslatef(70,40,0);
1041 glColor3f(1.0f,1.0f,0.0);
1042 scaledglprintf(0.1f,0.1f,"STRENGTH");
1043 glTranslatef(0,-18,0);
1044 glColor3f(1.0f,1.0f,1.0f);
1045 scaledglprintf(0.1f,0.1f,"%.3i%c",controlled->strength,'%');
1046 break;
1047
1048 case ORDERS_MENU:
1049 {
1050 STATUSBUTTON *b;
1051
1052 b=getbutton(ORDERS1_BUTTON);
1053 if (b!=0 && b->status==0) {
1054 glTranslatef(70,400,0);
1055 glColor3f(1.0f,1.0f,1.0f);
1056 scaledglprintf(0.1f,0.1f,"SELECT");
1057 glTranslatef(0,-20,0);
1058 scaledglprintf(0.1f,0.1f,"ORDERS");
1059
1060 glTranslatef(0,-340,0);
1061 glColor3f(1.0f,1.0f,0.0);
1062 scaledglprintf(0.1f,0.1f,"STRENGTH");
1063 glTranslatef(0,-18,0);
1064 glColor3f(1.0f,1.0f,1.0f);
1065 scaledglprintf(0.1f,0.1f,"%.3i%c",controlled->strength,'%');
1066 } /* if */
1067 }
1068 break;
1069
1070 case SELECTDISTANCE_MENU:
1071 {
1072 STATUSBUTTON *b;
1073
1074 b=getbutton(ORDERS_BUTTON);
1075 if (b!=0 && b->status==0) {
1076 glTranslatef(70,300,0);
1077 glColor3f(0.5f,0.5f,1.0f);
1078 scaledglprintf(0.1f,0.1f,"SELECT");
1079 glTranslatef(0,-20,0);
1080 scaledglprintf(0.1f,0.1f,"DISTANCE");
1081
1082 glColor3f(1.0f,1.0f,0.0);
1083 glTranslatef(0,-40,0);
1084 scaledglprintf(0.1f,0.1f,"%.2i MILES",controlled->program_parameter/2);
1085
1086 glTranslatef(0,-200,0);
1087 glColor3f(1.0f,1.0f,0.0);
1088 scaledglprintf(0.1f,0.1f,"STRENGTH");
1089 glTranslatef(0,-18,0);
1090 glColor3f(1.0f,1.0f,1.0f);
1091 scaledglprintf(0.1f,0.1f,"%.3i%c",controlled->strength,'%');
1092 } /* if */
1093 }
1094 break;
1095
1096 case TARGETD_MENU:
1097 case TARGETC_MENU:
1098 {
1099 STATUSBUTTON *b;
1100
1101 b=getbutton(ORDERS_BUTTON);
1102 if (b!=0 && b->status==0) {
1103 glTranslatef(70,350,0);
1104 glColor3f(0.5f,0.5f,1.0f);
1105 scaledglprintf(0.1f,0.1f,"SELECT");
1106 glTranslatef(0,-20,0);
1107 scaledglprintf(0.1f,0.1f,"TARGET");
1108
1109 glTranslatef(0,-290,0);
1110 glColor3f(1.0f,1.0f,0.0);
1111 scaledglprintf(0.1f,0.1f,"STRENGTH");
1112 glTranslatef(0,-18,0);
1113 glColor3f(1.0f,1.0f,1.0f);
1114 scaledglprintf(0.1f,0.1f,"%.3i%c",controlled->strength,'%');
1115 } /* if */
1116 }
1117 break;
1118
1119 } /* switch */
1120 glPopMatrix();
1121
1122 } /* NETHER::draw_status */
1123
1124
options_draw(int w,int h)1125 void NETHER::options_draw(int w,int h)
1126 {
1127 float lightpos2[4]={0,0,1000,0};
1128 float tmpls[4]={1.0F,1.0F,1.0F,1.0};
1129 float tmpld[4]={0.6F,0.6F,0.6F,1.0};
1130 float tmpla[4]={0.2F,0.2F,0.2F,1.0};
1131 float ratio;
1132 int splitx[2]={int(w*0.3),int(w*0.7)};
1133 int splity[2]={int(h*0.3),int(h*0.7)};
1134
1135 /* Enable Lights, etc.: */
1136 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
1137 glEnable(GL_LIGHT0);
1138 glLightfv(GL_LIGHT0,GL_AMBIENT,tmpla);
1139 glLightfv(GL_LIGHT0,GL_DIFFUSE,tmpld);
1140 glLightfv(GL_LIGHT0,GL_SPECULAR,tmpls);
1141 glEnable(GL_LIGHTING);
1142 glEnable(GL_COLOR_MATERIAL);
1143 glShadeModel( GL_SMOOTH );
1144 glCullFace( GL_BACK );
1145 glFrontFace( GL_CCW );
1146 glEnable( GL_CULL_FACE );
1147 glEnable( GL_SCISSOR_TEST );
1148 glEnable( GL_DEPTH_TEST );
1149
1150 /* Draw the MENU: */
1151 glLightfv(GL_LIGHT0,GL_POSITION,lightpos);
1152 glClearColor(0,0,0,0.0);
1153 glViewport(splitx[0],splity[0],splitx[1]-splitx[0],splity[1]-splity[0]);
1154 ratio=float(splitx[1]-splitx[0])/float(splity[1]-splity[0]);
1155 glMatrixMode( GL_PROJECTION );
1156 glLoadIdentity( );
1157 gluPerspective( 30.0, ratio, 1.0, 1024.0 );
1158 glScissor(splitx[0],splity[0],splitx[1]-splitx[0],splity[1]-splity[0]);
1159 gluLookAt(0,0,30,0,0,0,0,1,0);
1160
1161 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
1162
1163 glMatrixMode(GL_MODELVIEW);
1164 glLoadIdentity();
1165
1166 if (game_state==STATE_PAUSE) {
1167 if (option_menu==0) glColor3f(1.0,0.0,0.0);
1168 else glColor3f(0.5,0.5,1.0);
1169 glTranslatef(0,5,0);
1170 scaledglprintf(0.01,0.01,"RETURN TO GAME");
1171
1172 if (option_menu==1) glColor3f(1.0,0.0,0.0);
1173 else glColor3f(0.5,0.5,1.0);
1174 glTranslatef(0,-5,0);
1175 scaledglprintf(0.01,0.01,"LOAD GAME");
1176
1177 if (option_menu==2) glColor3f(1.0,0.0,0.0);
1178 else glColor3f(0.5,0.5,1.0);
1179 glTranslatef(0,-3,0);
1180 scaledglprintf(0.01,0.01,"SAVE GAME");
1181
1182 if (option_menu==3) glColor3f(1.0,0.0,0.0);
1183 else glColor3f(0.5,0.5,1.0);
1184 glTranslatef(0,-3,0);
1185 scaledglprintf(0.01,0.01,"QUIT GAME");
1186 } /* if */
1187
1188 if (game_state==STATE_SAVINGGAME) {
1189 int i;
1190 FILE *fp;
1191 char filename[80];
1192
1193 glColor3f(0.5,0.5,1.0);
1194 glTranslatef(0,6,0);
1195 scaledglprintf(0.01,0.01,"CHOOSE SLOT TO SAVE");
1196
1197 if (option_menu==0) glColor3f(1.0,0.0,0.0);
1198 else glColor3f(0.5,0.5,1.0);
1199 glTranslatef(0,-4,0);
1200 scaledglprintf(0.01,0.01,"CANCEL");
1201
1202 for(i=0;i<4;i++) {
1203 if (option_menu==(i+1)) glColor3f(1.0,0.0,0.0);
1204 else glColor3f(0.5,0.5,1.0);
1205 glTranslatef(0,-2,0);
1206 sprintf(filename,"savedgame%i.txt",i);
1207 fp=fopen(filename,"r");
1208 if (fp==0) {
1209 scaledglprintf(0.01,0.01,"SLOT%i - EMPTY",i+1);
1210 } else {
1211 scaledglprintf(0.01,0.01,"SLOT%i - GAME SAVED",i+1);
1212 fclose(fp);
1213 } /* if */
1214 } /* for */
1215 } /* if */
1216
1217 if (game_state==STATE_LOADINGGAME) {
1218 int i;
1219 FILE *fp;
1220 char filename[80];
1221
1222 glColor3f(0.5,0.5,1.0);
1223 glTranslatef(0,6,0);
1224 scaledglprintf(0.01,0.01,"CHOOSE SLOT TO LOAD");
1225
1226 if (option_menu==0) glColor3f(1.0,0.0,0.0);
1227 else glColor3f(0.5,0.5,1.0);
1228 glTranslatef(0,-4,0);
1229 scaledglprintf(0.01,0.01,"CANCEL");
1230
1231 for(i=0;i<4;i++) {
1232 if (option_menu==(i+1)) glColor3f(1.0,0.0,0.0);
1233 else glColor3f(0.5,0.5,1.0);
1234 glTranslatef(0,-2,0);
1235 sprintf(filename,"savedgame%i.txt",i);
1236 fp=fopen(filename,"r");
1237 if (fp==0) {
1238 scaledglprintf(0.01,0.01,"SLOT%i - EMPTY",i+1);
1239 } else {
1240 scaledglprintf(0.01,0.01,"SLOT%i - GAME SAVED",i+1);
1241 fclose(fp);
1242 } /* if */
1243 } /* for */
1244 } /* if */
1245
1246
1247 } /* NETHER::options_draw */
1248
1249
option_cycle(unsigned char * keyboard)1250 bool NETHER::option_cycle(unsigned char *keyboard)
1251 {
1252 switch(game_state) {
1253 case STATE_PAUSE:
1254 if (keyboard[fire_key] && !old_keyboard[fire_key]) {
1255 switch(option_menu) {
1256 case 0:
1257 game_state=STATE_PLAYING;
1258 break;
1259 case 1: game_state=STATE_LOADINGGAME;
1260 option_menu=0;
1261 break;
1262 case 2: game_state=STATE_SAVINGGAME;
1263 option_menu=0;
1264 break;
1265 case 3: return false;
1266 break;
1267 } /* if */
1268 } /* if */
1269
1270 if (keyboard[down_key] && !old_keyboard[down_key]) {
1271 option_menu++;
1272 if (option_menu>=4) option_menu=0;
1273 } /* if */
1274
1275 if (keyboard[up_key] && !old_keyboard[up_key]) {
1276 option_menu--;
1277 if (option_menu<0) option_menu=3;
1278 } /* if */
1279 break;
1280
1281 case STATE_SAVINGGAME:
1282 if (keyboard[fire_key] && !old_keyboard[fire_key]) {
1283 switch(option_menu) {
1284 case 0:
1285 game_state=STATE_PAUSE;
1286 option_menu=2;
1287 break;
1288 case 1:
1289 case 2:
1290 case 3:
1291 case 4:
1292 {
1293 char filename[80];
1294 sprintf(filename,"savedgame%i.txt",option_menu-1);
1295 save_game(filename);
1296 //save_debug_report("debugreport.txt");
1297 game_state=STATE_PAUSE;
1298 option_menu=2;
1299 redrawmenu=2;
1300 redrawradar=1;
1301 }
1302 } /* if */
1303 } /* if */
1304
1305 if (keyboard[down_key] && !old_keyboard[down_key]) {
1306 option_menu++;
1307 if (option_menu>=5) option_menu=0;
1308 } /* if */
1309
1310 if (keyboard[up_key] && !old_keyboard[up_key]) {
1311 option_menu--;
1312 if (option_menu<0) option_menu=4;
1313 } /* if */
1314 break;
1315
1316 case STATE_LOADINGGAME:
1317 if (keyboard[fire_key] && !old_keyboard[fire_key]) {
1318 switch(option_menu) {
1319 case 0:
1320 game_state=STATE_PAUSE;
1321 option_menu=1;
1322 break;
1323 case 1:
1324 case 2:
1325 case 3:
1326 case 4:
1327 {
1328 char filename[80];
1329 sprintf(filename,"savedgame%i.txt",option_menu-1);
1330 killmenu(act_menu);
1331 load_game(filename);
1332 newmenu(act_menu);
1333 redrawmenu=2;
1334 recomputestatistics=true;
1335 game_finished=0;
1336 game_started=INTRO_TIME;
1337 game_state=STATE_PAUSE;
1338 option_menu=2;
1339 }
1340 } /* switch */
1341 } /* if */
1342
1343 if (keyboard[down_key] && !old_keyboard[down_key]) {
1344 option_menu++;
1345 if (option_menu>=5) option_menu=0;
1346 } /* if */
1347
1348 if (keyboard[up_key] && !old_keyboard[up_key]) {
1349 option_menu--;
1350 if (option_menu<0) option_menu=4;
1351 } /* if */
1352 break;
1353 } /* switch */
1354
1355 return true;
1356 } /* NETHER::option_cycle */
1357
1358
ShipCollision(C3DObject * obj,float x,float y,float z)1359 bool NETHER::ShipCollision(C3DObject *obj,float x,float y,float z)
1360 {
1361 int i;
1362 List<BUILDING> l;
1363 BUILDING *b;
1364 List<ROBOT> l2;
1365 ROBOT *r;
1366 float m1[16]={1,0,0,0,
1367 0,1,0,0,
1368 0,0,1,0,
1369 x,y,z,1};
1370 float m2[16]={1,0,0,0,
1371 0,1,0,0,
1372 0,0,1,0,
1373 0,0,0,1};
1374
1375 /* Collision with buildings: */
1376 l.Instance(buildings);
1377 l.Rewind();
1378 while(l.Iterate(b)) {
1379 if (((b->pos.x-x)*(b->pos.x-x)+
1380 (b->pos.y-y)*(b->pos.y-y)+
1381 (b->pos.z-z)*(b->pos.z-z))<COLISION_TEST_THRESHOLD) {
1382
1383 m2[12]=b->pos.x;
1384 m2[13]=b->pos.y;
1385 m2[14]=b->pos.z;
1386
1387 switch(b->type) {
1388 case B_FENCE:
1389 if (obj->cmc.collision_simple(m1,&(building_tile[5]->cmc),m2)) return true;
1390 break;
1391 case B_WALL1:
1392 if (obj->cmc.collision_simple(m1,&(building_tile[0]->cmc),m2)) return true;
1393 break;
1394 case B_WALL2:
1395 if (obj->cmc.collision_simple(m1,&(building_tile[1]->cmc),m2)) return true;
1396 break;
1397 case B_WALL3:
1398 if (obj->cmc.collision_simple(m1,&(building_tile[2]->cmc),m2)) return true;
1399 break;
1400 case B_WALL4:
1401 if (obj->cmc.collision_simple(m1,&(building_tile[3]->cmc),m2)) return true;
1402 break;
1403 case B_WALL5:
1404 if (obj->cmc.collision_simple(m1,&(building_tile[4]->cmc),m2)) return true;
1405 break;
1406 case B_WALL6:
1407 if (obj->cmc.collision_simple(m1,&(building_tile[7]->cmc),m2)) return true;
1408 break;
1409 case B_WARBASE:
1410 if (obj->cmc.collision_simple(m1,&(building_tile[8]->cmc),m2)) return true;
1411 //m2[13]=b->pos.y-2;
1412 //m2[14]=b->pos.z+1;
1413 //if (b->owner!=0) if (obj->cmc.collision_simple(m1,&(building_tile[6]->cmc),m2)) return true;
1414 break;
1415 case B_FACTORY_ELECTRONICS:
1416 if (obj->cmc.collision_simple(m1,&(building_tile[4]->cmc),m2)) return true;
1417 m2[12]=b->pos.x+0.5;
1418 m2[13]=b->pos.y+0.5;
1419 m2[14]=b->pos.z+1;
1420 if (obj->cmc.collision_simple(m1,&(piece_tile[0][7]->cmc),m2)) return true;
1421 //m2[12]=b->pos.x;
1422 //m2[13]=b->pos.y-1;
1423 //if (b->owner!=0) if (obj->cmc.collision_simple(m1,&(building_tile[6]->cmc),m2)) return true;
1424 break;
1425 case B_FACTORY_NUCLEAR:
1426 if (obj->cmc.collision_simple(m1,&(building_tile[4]->cmc),m2)) return true;
1427 m2[12]=b->pos.x+0.5;
1428 m2[13]=b->pos.y+0.5;
1429 m2[14]=b->pos.z+1;
1430 if (obj->cmc.collision_simple(m1,&(piece_tile[0][6]->cmc),m2)) return true;
1431 //m2[12]=b->pos.x;
1432 //m2[13]=b->pos.y-1;
1433 //if (b->owner!=0) if (obj->cmc.collision_simple(m1,&(building_tile[6]->cmc),m2)) return true;
1434 break;
1435 case B_FACTORY_PHASERS:
1436 if (obj->cmc.collision_simple(m1,&(building_tile[4]->cmc),m2)) return true;
1437 m2[12]=b->pos.x+0.5;
1438 m2[13]=b->pos.y+0.5;
1439 m2[14]=b->pos.z+1;
1440 if (obj->cmc.collision_simple(m1,&(piece_tile[0][5]->cmc),m2)) return true;
1441 //m2[12]=b->pos.x;
1442 //m2[13]=b->pos.y-1;
1443 //if (b->owner!=0) if (obj->cmc.collision_simple(m1,&(building_tile[6]->cmc),m2)) return true;
1444 break;
1445 case B_FACTORY_MISSILES:
1446 if (obj->cmc.collision_simple(m1,&(building_tile[4]->cmc),m2)) return true;
1447 m2[12]=b->pos.x+0.5;
1448 m2[13]=b->pos.y+0.5;
1449 m2[14]=b->pos.z+1;
1450 if (obj->cmc.collision_simple(m1,&(piece_tile[0][4]->cmc),m2)) return true;
1451 //m2[12]=b->pos.x;
1452 //m2[13]=b->pos.y-1;
1453 //if (b->owner!=0) if (obj->cmc.collision_simple(m1,&(building_tile[6]->cmc),m2)) return true;
1454 break;
1455 case B_FACTORY_CANNONS:
1456 if (obj->cmc.collision_simple(m1,&(building_tile[4]->cmc),m2)) return true;
1457 m2[12]=b->pos.x+0.5;
1458 m2[13]=b->pos.y+0.5;
1459 m2[14]=b->pos.z+1;
1460 if (obj->cmc.collision_simple(m1,&(piece_tile[0][3]->cmc),m2)) return true;
1461 //m2[12]=b->pos.x;
1462 //m2[13]=b->pos.y-1;
1463 //if (b->owner!=0) if (obj->cmc.collision_simple(m1,&(building_tile[6]->cmc),m2)) return true;
1464 break;
1465 case B_FACTORY_CHASSIS:
1466 if (obj->cmc.collision_simple(m1,&(building_tile[4]->cmc),m2)) return true;
1467 m2[12]=b->pos.x+0.5;
1468 m2[13]=b->pos.y+0.5;
1469 m2[14]=b->pos.z+1;
1470 if (obj->cmc.collision_simple(m1,&(piece_tile[0][1]->cmc),m2)) return true;
1471 //m2[12]=b->pos.x;
1472 //m2[13]=b->pos.y-1;
1473 //if (b->owner!=0) if (obj->cmc.collision_simple(m1,&(building_tile[6]->cmc),m2)) return true;
1474 break;
1475 } /* switch */
1476 } /* if */
1477 } /* while */
1478
1479 /* Collision with the robots: */
1480 for(i=0;i<2;i++) {
1481 l2.Instance(robots[i]);
1482 l2.Rewind();
1483 while(l2.Iterate(r)) {
1484 if (((r->pos.x-x)*(r->pos.x-x)+
1485 (r->pos.y-y)*(r->pos.y-y))<COLISION_TEST_THRESHOLD) {
1486 m2[12]=r->pos.x;
1487 m2[13]=r->pos.y;
1488 m2[14]=r->pos.z;
1489 if (obj->cmc.collision_simple(m1,&(r->cmc),m2)) return true;
1490 } /* if */
1491 } /* while */
1492 } /* while */
1493
1494 return false;
1495 } /* NETHER::ShipCollision */
1496
1497
1498
SFX_volume(Vector pos)1499 int NETHER::SFX_volume(Vector pos)
1500 {
1501 float distance=(pos-shipp).norma();
1502
1503 distance=(distance-8)/8;
1504 if (distance<1) distance=1;
1505
1506
1507 return int(128/distance);
1508 } /* SFX_volume */
1509