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