1 /*
2  * Created by Olivier "LuaPineapple" Hamel for the Freespace 2 Source Code Project.
3  * You may not sell or otherwise commercially exploit the source or things you
4  * create based on the source.
5  *
6  */
7 
8 #include "bmpman/bmpman.h"
9 #include "freespace.h"
10 #include "gamesnd/gamesnd.h"
11 #include "globalincs/linklist.h"
12 #include "globalincs/alphacolors.h"
13 #include "globalincs/systemvars.h"
14 #include "graphics/font.h"
15 #include "graphics/matrix.h"
16 #include "hud/hudwingmanstatus.h"
17 #include "iff_defs/iff_defs.h"
18 #include "io/timer.h"
19 #include "jumpnode/jumpnode.h"
20 #include "localization/localize.h"
21 #include "math/staticrand.h"
22 #include "network/multi.h"
23 #include "object/object.h"
24 #include "playerman/player.h"
25 #include "radar/radardradis.h"
26 #include "radar/radarorb.h"
27 #include "render/3d.h"
28 #include "ship/awacs.h"
29 #include "ship/ship.h"
30 #include "ship/subsysdamage.h"
31 #include "weapon/emp.h"
32 #include "weapon/weapon.h"
33 
34 #define RADIANS_PER_DEGREE (PI / 180.0f)
35 
HudGaugeRadarDradis()36 HudGaugeRadarDradis::HudGaugeRadarDradis():
37 HudGaugeRadar(HUD_OBJECT_RADAR_BSG, 255, 255, 255),
38 xy_plane(-1), xz_yz_plane(-1), sweep_plane(-1), target_brackets(-1), unknown_contact_icon(-1), sweep_duration(6.0), sweep_percent(0.0), scale(1.20f), sub_y_clip(false)
39 {
40 	vm_vec_copy_scale(&sweep_normal_x, &vmd_zero_vector, 1.0f);
41 	vm_vec_copy_scale(&sweep_normal_y, &vmd_zero_vector, 1.0f);
42 	vm_vec_copy_scale(&sweep_normal_z, &vmd_zero_vector, 1.0f);
43 
44 	// init the view perturb matrix
45 	view_perturb.a2d[0][0] = 1.0f;
46 	view_perturb.a2d[0][1] = 0.0f;
47 	view_perturb.a2d[0][2] = 0.0f;
48 	view_perturb.a2d[1][0] = 0.0f;
49 	view_perturb.a2d[1][1] = -1.0f;
50 	view_perturb.a2d[1][2] = 0.0f;
51 	view_perturb.a2d[2][0] = 0.0f;
52 	view_perturb.a2d[2][1] = 0.0f;
53 	view_perturb.a2d[2][2] = 1.0f;
54 
55 	// init the orb eye position
56 	Orb_eye_position.a1d[0] = 0.0f;
57 	Orb_eye_position.a1d[1] = 0.0f;
58 	Orb_eye_position.a1d[2] = -2.5f;
59 
60 	fx_guides0_0.a1d[0] = -1.0f;
61 	fx_guides0_0.a1d[1] = 0.0f;
62 	fx_guides0_0.a1d[2] = 0.0f;
63 
64 	fx_guides0_1.a1d[0] = 1.0f;
65 	fx_guides0_1.a1d[1] = 0.0f;
66 	fx_guides0_1.a1d[2] = 0.0f;
67 
68 	fx_guides1_0.a1d[0] = 0.0f;
69 	fx_guides1_0.a1d[1] = -1.0f;
70 	fx_guides1_0.a1d[2] = 0.0f;
71 
72 	fx_guides1_1.a1d[0] = 0.0f;
73 	fx_guides1_1.a1d[1] = 1.0f;
74 	fx_guides1_1.a1d[2] = 0.0f;
75 
76 	fx_guides2_0.a1d[0] = 0.0f;
77 	fx_guides2_0.a1d[1] = 0.0f;
78 	fx_guides2_0.a1d[2] = -1.0f;
79 
80 	fx_guides2_1.a1d[0] = 0.0f;
81 	fx_guides2_1.a1d[1] = 0.0f;
82 	fx_guides2_1.a1d[2] = 1.0f;
83 
84 	this->loop_sound_handle = sound_handle::invalid();
85 }
86 
initBitmaps(char * fname_xy,char * fname_xz_yz,char * fname_sweep,char * fname_target_brackets,char * fname_unknown)87 void HudGaugeRadarDradis::initBitmaps(char* fname_xy, char* fname_xz_yz, char* fname_sweep, char* fname_target_brackets, char* fname_unknown)
88 {
89 	xy_plane = bm_load(fname_xy); // Base
90 	if ( xy_plane < 0 ) {
91 		Warning(LOCATION,"Cannot load hud bitmap: %s\n", fname_xy);
92 	}
93 
94 	xz_yz_plane = bm_load(fname_xz_yz); // Two vertical cross rings
95 	if ( xz_yz_plane < 0 ) {
96 		Warning(LOCATION,"Cannot load hud bitmap: %s\n", fname_xz_yz);
97 	}
98 
99 	sweep_plane = bm_load(fname_sweep); // Sweep lines
100 	if ( sweep_plane < 0 ) {
101 		Warning(LOCATION,"Cannot load hud bitmap: %s\n", fname_sweep);
102 	}
103 
104 	target_brackets = bm_load(fname_target_brackets);
105 	if ( target_brackets < 0 ) {
106 		Warning(LOCATION,"Cannot load hud bitmap: %s\n", fname_target_brackets);
107 	}
108 
109 	unknown_contact_icon = bm_load(fname_unknown);
110 	if ( unknown_contact_icon < 0 ) {
111 		Warning(LOCATION,"Cannot load hud bitmap: %s\n", fname_unknown);
112 	}
113 }
114 
plotBlip(blip * b,vec3d * pos,float * alpha)115 void HudGaugeRadarDradis::plotBlip(blip* b, vec3d *pos, float *alpha)
116 {
117 	*pos = b->position;
118 	vm_vec_normalize(pos);
119 
120 	if (ship_is_tagged(b->objp)) {
121 		*alpha = 1.0f;
122 		return;
123 	}
124 
125 	float fade_multi = 1.5f;
126 
127 	if (b->objp->type == OBJ_SHIP) {
128 		if (Ships[b->objp->instance].flags[Ship::Ship_Flags::Stealth]) {
129 			fade_multi *= 2.0f;
130 		}
131 	}
132 
133 	b->time_since_update += flFrametime;
134 	// If the blip has been pinged by the local x-axis sweep, update
135 	if (std::abs(vm_vec_dot(&sweep_normal_x, pos)) < 0.01f) {
136 		b->time_since_update = 0.0f;
137 	}
138 
139 	*alpha = ((sweep_duration - b->time_since_update)/sweep_duration)*fade_multi/2.0f;
140 
141 	if (*alpha < 0.0f) {
142 		*alpha = 0.0f;
143 	}
144 }
145 
drawContact(vec3d * pnt,int idx,int clr_idx,float,float alpha,float scale_factor)146 void HudGaugeRadarDradis::drawContact(vec3d *pnt, int idx, int clr_idx, float  /*dist*/, float alpha, float scale_factor)
147 {
148 	vec3d  p;
149 	int h, w;
150 	vertex vert;
151 	float aspect_mp;
152 
153 	if ((sub_y_clip && (pnt->xyz.y > 0)) || ((!sub_y_clip) && (pnt->xyz.y <= 0)))
154 		return;
155 
156     memset(&vert, 0, sizeof(vert));
157 
158 	vm_vec_rotate(&p, pnt,  &vmd_identity_matrix);
159 	g3_transfer_vertex(&vert, &p);
160 
161 	float sizef = fl_sqrt(vm_vec_dist(&Orb_eye_position, pnt) * 8.0f) * scale_factor;
162 
163     if ( clr_idx >= 0 ) {
164         bm_get_info(clr_idx, &w, &h);
165 
166         if (h == w) {
167             aspect_mp = 1.0f;
168         } else {
169             aspect_mp = (((float) h) / ((float) w));
170         }
171 
172         //gr_set_bitmap(clr_idx, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, alpha);
173         //g3_draw_polygon(&p, &vmd_identity_matrix, sizef/35.0f, aspect_mp*sizef/35.0f, TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT);
174 		material mat_params;
175 		material_set_unlit_color(&mat_params, clr_idx, &Color_bright_white, alpha, true, false);
176 		g3_render_rect_oriented(&mat_params, &p, &vmd_identity_matrix, sizef/35.0f, aspect_mp*sizef/35.0f);
177     }
178 
179     if ( idx >= 0 ) {
180         bm_get_info(idx, &w, &h);
181 
182         if (h == w) {
183             aspect_mp = 1.0f;
184         } else {
185             aspect_mp = (((float) h) / ((float) w));
186         }
187 
188         //gr_set_bitmap(idx, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, alpha);
189         //g3_draw_polygon(&p, &vmd_identity_matrix, sizef/35.0f, aspect_mp*sizef/35.0f, TMAP_FLAG_TEXTURED | TMAP_FLAG_BW_TEXTURE | TMAP_HTL_3D_UNLIT);
190 		material mat_params;
191 		material_set_unlit_color(&mat_params, idx, &gr_screen.current_color, alpha, true, false);
192 		g3_render_rect_oriented(&mat_params, &p, &vmd_identity_matrix, sizef/35.0f, aspect_mp*sizef/35.0f);
193     }
194 }
195 
196 // radar is damaged, so make blips dance around
blipDrawDistorted(blip * b,vec3d * pos,float alpha)197 void HudGaugeRadarDradis::blipDrawDistorted(blip *b, vec3d *pos, float alpha)
198 {
199 	float temp_scale;
200 	float dist = vm_vec_normalize(pos);
201 	vec3d out;
202 	float distortion_angle=20;
203 
204 	// maybe alter the effect if EMP is active
205 	if (emp_active_local())
206 	{
207 		temp_scale = emp_current_intensity();
208 		dist *= frand_range(MAX(0.75f, 0.75f*temp_scale), MIN(1.25f, 1.25f*temp_scale));
209 		distortion_angle *= frand_range(-3.0f,3.0f)*frand_range(0.0f, temp_scale);
210 
211 		if (dist > 1.0f) dist = 1.0f;
212 		if (dist < 0.1f) dist = 0.1f;
213 	}
214 
215 	vm_vec_random_cone(&out, pos, distortion_angle);
216 	vm_vec_scale(&out, dist);
217 
218 	drawContact(&out, -1, unknown_contact_icon, b->dist, alpha, 1.0f);
219 }
220 
221 // blip is for a target immune to sensors, so cause to flicker in/out with mild distortion
blipDrawFlicker(blip * b,vec3d * pos,float alpha)222 void HudGaugeRadarDradis::blipDrawFlicker(blip *b, vec3d *pos, float alpha)
223 {
224 	int flicker_index;
225 
226 	float dist=vm_vec_normalize(pos);
227 	vec3d out;
228 	float distortion_angle=10;
229 
230 	if ((b-Blips) & 1)
231 		flicker_index=0;
232 	else
233 		flicker_index=1;
234 
235 
236 	if (timestamp_elapsed(Radar_flicker_timer[flicker_index])) {
237 		Radar_flicker_timer[flicker_index] = timestamp_rand(50,1000);
238 		Radar_flicker_on[flicker_index] ^= 1;
239 	}
240 
241 	if (!Radar_flicker_on[flicker_index])
242 		return;
243 
244 	if (Random::flip_coin())
245 	{
246 		distortion_angle *= frand_range(0.1f,2.0f);
247 		dist *= frand_range(0.75f, 1.25f);
248 
249 		if (dist > 1.0f) dist = 1.0f;
250 		if (dist < 0.1f) dist = 0.1f;
251 	}
252 
253 	vm_vec_random_cone(&out,pos,distortion_angle);
254 	vm_vec_scale(&out,dist);
255 
256 	drawContact(&out, -1, unknown_contact_icon, b->dist, alpha, 1.0f);
257 }
258 
259 // Draw all the active radar blips
drawBlips(int blip_type,int bright,int distort)260 void HudGaugeRadarDradis::drawBlips(int blip_type, int bright, int distort)
261 {
262 	blip *b = NULL;
263 	blip *blip_head;
264 	vec3d pos;
265 	float alpha;
266 
267 	Assert((blip_type >= 0) && (blip_type < MAX_BLIP_TYPES));
268 
269 	//long frametime = timer_get_approx_seconds();
270 	// Need to set font.
271 	font::set_font(font::FONT1);
272 
273 	if(bright) {
274 		blip_head = &Blip_bright_list[blip_type];
275 	} else {
276 		blip_head = &Blip_dim_list[blip_type];
277 	}
278 
279 	float scale_factor = 1.0f;
280 
281 	// draw all blips of this type
282 	for (b = GET_FIRST(blip_head); b != END_OF_LIST(blip_head); b = GET_NEXT(b))
283 	{
284 		plotBlip(b, &pos, &alpha);
285 
286 		gr_set_color_fast(b->blip_color);
287 
288 		scale_factor = 1.0f;
289 
290 		// maybe draw cool blip to indicate current target
291 		if (b->flags & BLIP_CURRENT_TARGET)
292 		{
293 			if (radar_target_id_flags & RTIF_PULSATE) {
294 				scale_factor *= 1.3f + (sinf(10 * f2fl(Missiontime)) * 0.3f);
295 			}
296 			if (radar_target_id_flags & RTIF_BLINK) {
297 				if (Missiontime & 8192)
298 					continue;
299 			}
300 			if (radar_target_id_flags & RTIF_ENLARGE) {
301 				scale_factor *= 1.3f;
302 			}
303 
304 			alpha = 1.0;
305 			b->rad = Radar_blip_radius_target;
306 			drawContact(&pos, -1, target_brackets, b->dist, alpha, scale_factor);
307 		}
308 		else {
309 			b->rad = Radar_blip_radius_normal;
310 		}
311 
312 		// maybe distort blip
313 		if (distort) {
314 			blipDrawDistorted(b, &pos, alpha);
315 		} else {
316 			if (b->flags & BLIP_DRAW_DISTORTED) {
317 				blipDrawFlicker(b, &pos, alpha);
318 			} else if (b->radar_image_2d >= 0 || b->radar_color_image_2d >= 0) {
319 				drawContact(&pos, b->radar_image_2d, b->radar_color_image_2d, b->dist, alpha, scale_factor);
320 			} else {
321 				drawContact(&pos, -1, unknown_contact_icon, b->dist, alpha, scale_factor);
322 			}
323 		}
324 	}
325 }
326 
setupViewHtl()327 void HudGaugeRadarDradis::setupViewHtl()
328 {
329 	setClip(position[0], position[1], Radar_radius[0], Radar_radius[1]);
330 	gr_set_proj_matrix(.625f * PI_2, i2fl(Radar_radius[0])/i2fl(Radar_radius[1]), 0.001f, 5.0f);
331 	gr_set_view_matrix(&Orb_eye_position, &vmd_identity_matrix);
332 
333 	gr_zbuffer_set(GR_ZBUFF_NONE);
334 }
335 
doneDrawingHtl()336 void HudGaugeRadarDradis::doneDrawingHtl()
337 {
338 	gr_end_view_matrix();
339 	gr_end_proj_matrix();
340 
341 	//hud_save_restore_camera_data(0);
342 
343 	gr_zbuffer_set(GR_ZBUFF_FULL);
344 }
345 
drawOutlinesHtl()346 void HudGaugeRadarDradis::drawOutlinesHtl()
347 {
348 	matrix base_tilt = vmd_identity_matrix;
349 	vec3d base_tilt_norm;
350 
351 	if ((xy_plane == -1) || (xz_yz_plane == -1))
352 		return;
353 
354 	g3_start_instance_matrix(&vmd_zero_vector, /*&Player_obj->orient*/&vmd_identity_matrix, true);
355 
356 		// Tilt the base disc component of DRADIS-style radar 30 degrees down
357 		vm_angle_2_matrix(&base_tilt, PI/6, 0);
358 		vm_vec_rotate(&base_tilt_norm, &vmd_y_vector, &base_tilt);
359 
360 		//gr_set_bitmap(xy_plane, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 1.0f); // base
361 		//g3_draw_polygon(&vmd_zero_vector, &base_tilt_norm, scale, scale, TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT);
362 		material mat_params;
363 		material_set_unlit(&mat_params, xy_plane, 1.0f, true, false);
364 		g3_render_rect_oriented(&mat_params, &vmd_zero_vector, &base_tilt_norm, scale, scale);
365 
366 		//gr_set_bitmap(xz_yz_plane, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 1.0f);
367 
368 		//g3_draw_polygon(&vmd_zero_vector, &vmd_x_vector, scale, scale, TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT); // forward facing ring
369 		//g3_draw_polygon(&vmd_zero_vector, &vmd_z_vector, scale, scale, TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT); // side facing ring
370 
371 		material_set_unlit(&mat_params, xz_yz_plane, 1.0f, true, false);
372 		g3_render_rect_oriented(&mat_params, &vmd_zero_vector, &vmd_x_vector, scale, scale); // forward facing ring
373 		g3_render_rect_oriented(&mat_params, &vmd_zero_vector, &vmd_z_vector, scale, scale); // side facing ring
374 	g3_done_instance(true);
375 }
376 
drawSweeps()377 void HudGaugeRadarDradis::drawSweeps()
378 {
379 	if (sweep_plane == -1)
380 		return;
381 
382 	sweep_percent = (fmod(((float)game_get_overall_frametime() / (float)65536), sweep_duration) /  sweep_duration) * PI * 2; // convert to radians from 0 <-> 1
383 	float sweep_perc_z = sweep_percent * -0.5f;
384 
385 	vec3d sweep_a;
386 	vec3d sweep_b;
387 	vec3d sweep_c;
388 
389 	vm_rot_point_around_line(&sweep_a, &vmd_y_vector, sweep_percent, &vmd_zero_vector, &vmd_z_vector); // Sweep line: XZ
390 	vm_rot_point_around_line(&sweep_b, &vmd_y_vector, sweep_percent, &vmd_zero_vector, &vmd_x_vector); // Sweep line: YZ
391 	vm_rot_point_around_line(&sweep_c, &vmd_x_vector, sweep_perc_z, &vmd_zero_vector, &vmd_y_vector); // Sweep line: XY
392 
393 	vm_vec_copy_scale(&sweep_normal_x, &sweep_a, 1.0f);
394 	vm_vec_copy_scale(&sweep_normal_y, &sweep_b, 1.0f);
395 
396 	g3_start_instance_matrix(&vmd_zero_vector, /*&Player_obj->orient*/&vmd_identity_matrix, true);
397 //		gr_set_bitmap(sweep_plane, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 1.0f);
398 
399 // 		g3_draw_polygon(&vmd_zero_vector, &sweep_a, scale, scale, TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT);
400 // 		g3_draw_polygon(&vmd_zero_vector, &sweep_b, scale, scale, TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT);
401 // 		g3_draw_polygon(&vmd_zero_vector, &sweep_c, scale, scale, TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT);
402 
403 		material mat_params;
404 		material_set_unlit(&mat_params, sweep_plane, 1.0f, true, false);
405 		g3_render_rect_oriented(&mat_params, &vmd_zero_vector, &sweep_a, scale, scale);
406 		g3_render_rect_oriented(&mat_params, &vmd_zero_vector, &sweep_b, scale, scale);
407 		g3_render_rect_oriented(&mat_params, &vmd_zero_vector, &sweep_c, scale, scale);
408 
409 		float rotation = sweep_percent;
410 
411 		vm_rot_point_around_line(&sweep_a, &vmd_y_vector, rotation, &vmd_zero_vector, &vmd_z_vector); // Sweep line: XZ
412 		vm_rot_point_around_line(&sweep_b, &vmd_y_vector, rotation, &vmd_zero_vector, &vmd_x_vector); // Sweep line: YZ
413 		vm_rot_point_around_line(&sweep_c, &vmd_x_vector,sweep_perc_z, &vmd_zero_vector, &vmd_y_vector); // Sweep line: YZ
414 
415 		//gr_set_bitmap(sweep_plane, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL);
416 
417 // 		g3_draw_polygon(&vmd_zero_vector, &sweep_a, scale, scale, TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT); // Sweep line: XZ
418 // 		g3_draw_polygon(&vmd_zero_vector, &sweep_b, scale, scale, TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT); // Sweep line: YZ
419 // 		g3_draw_polygon(&vmd_zero_vector, &sweep_c, scale, scale, TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT);
420 
421 		g3_render_rect_oriented(&mat_params, &vmd_zero_vector, &sweep_a, scale, scale); // Sweep line: XZ
422 		g3_render_rect_oriented(&mat_params, &vmd_zero_vector, &sweep_b, scale, scale); // Sweep line: YZ
423 		g3_render_rect_oriented(&mat_params, &vmd_zero_vector, &sweep_c, scale, scale);
424 
425 		/*int dist = 90;
426 
427 		for(int i = 1; i < dist; i++)
428 		{
429 			float rotation = sweep_percent - (i * RADIANS_PER_DEGREE);
430 			float alpha	= (1.0f - (float)((float)i / (float)dist)) * 0.25f;
431 
432 			//if (i < 2)
433 				//alpha = 1.0f;
434 
435 			gr_set_bitmap(sweep_plane, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, alpha);
436 
437 			vm_rot_point_around_line(&sweep_a, &vmd_y_vector, rotation, &vmd_zero_vector, &vmd_z_vector); // Sweep line: XZ
438 			vm_rot_point_around_line(&sweep_b, &vmd_y_vector, rotation, &vmd_zero_vector, &vmd_x_vector); // Sweep line: YZ
439 
440 			g3_draw_polygon(&vmd_zero_vector, &sweep_a, scale, scale, TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT); // Sweep line: XZ
441 			g3_draw_polygon(&vmd_zero_vector, &sweep_b, scale, scale, TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT); // Sweep line: YZ
442 
443 			if (i < (dist * 0.5f))
444 			{
445 				vm_rot_point_around_line(&sweep_c, &vmd_x_vector,sweep_perc_z + (i * RADIANS_PER_DEGREE), &vmd_zero_vector, &vmd_y_vector); // Sweep line: YZ
446 				g3_draw_polygon(&vmd_zero_vector, &sweep_c, scale, scale, TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT);
447 			}
448 		}*/
449 
450 	g3_done_instance(true);
451 }
452 
drawBlipsSorted(int distort)453 void HudGaugeRadarDradis::drawBlipsSorted(int distort)
454 {
455 	GR_DEBUG_SCOPE("Draw Dradis blips");
456 
457 	matrix base_tilt = vmd_identity_matrix;
458 
459 	vm_angle_2_matrix(&base_tilt, -PI/6, 0);
460 
461 	for(int is_bright = 0; is_bright < 2; is_bright++) {
462 		sub_y_clip = true;
463 		g3_start_instance_matrix(&vmd_zero_vector, /*&Player_obj->orient*/&base_tilt, true);
464 			drawBlips(BLIP_TYPE_BOMB, is_bright, distort);
465 			drawBlips(BLIP_TYPE_JUMP_NODE, is_bright, distort);
466 			drawBlips(BLIP_TYPE_NORMAL_SHIP, is_bright, distort);
467 			drawBlips(BLIP_TYPE_TAGGED_SHIP, is_bright, distort);
468 			drawBlips(BLIP_TYPE_WARPING_SHIP, is_bright, distort);
469 			drawBlips(BLIP_TYPE_NAVBUOY_CARGO, is_bright, distort);
470 		g3_done_instance(true);
471 
472 		drawOutlinesHtl();
473 
474 		sub_y_clip = false;
475 		g3_start_instance_matrix(&vmd_zero_vector, /*&Player_obj->orient*/&base_tilt, true);
476 			drawBlips(BLIP_TYPE_BOMB, is_bright, distort);
477 			drawBlips(BLIP_TYPE_JUMP_NODE, is_bright, distort);
478 			drawBlips(BLIP_TYPE_NORMAL_SHIP, is_bright, distort);
479 			drawBlips(BLIP_TYPE_TAGGED_SHIP, is_bright, distort);
480 			drawBlips(BLIP_TYPE_WARPING_SHIP, is_bright, distort);
481 			drawBlips(BLIP_TYPE_NAVBUOY_CARGO, is_bright, distort);
482 		g3_done_instance(true);
483 	}
484 }
485 
486 
render(float)487 void HudGaugeRadarDradis::render(float  /*frametime*/)
488 {
489 	float sensors_str;
490 	int   ok_to_blit_radar;
491 
492 	ok_to_blit_radar = 1;
493 
494 	sensors_str = ship_get_subsystem_strength(Player_ship, SUBSYSTEM_SENSORS);
495 
496 	if (ship_subsys_disrupted(Player_ship, SUBSYSTEM_SENSORS))
497 		sensors_str = MIN_SENSOR_STR_TO_RADAR - 1;
498 
499 	// note that on lowest skill level, there is no radar effects due to sensors damage
500 	if ((Game_skill_level == 0) || (sensors_str > SENSOR_STR_RADAR_NO_EFFECTS))
501 	{
502 		Radar_static_playing = 0;
503 		Radar_static_next = 0;
504 		Radar_death_timer = 0;
505 		Radar_avail_prev_frame = 1;
506 	}
507 	else
508 		if (sensors_str < MIN_SENSOR_STR_TO_RADAR)
509 		{
510 			if (Radar_avail_prev_frame)
511 			{
512 				Radar_death_timer = timestamp(2000);
513 				Radar_static_next = 1;
514 			}
515 
516 			Radar_avail_prev_frame = 0;
517 		}
518 		else
519 		{
520 			Radar_death_timer = 0;
521 
522 			if (Radar_static_next == 0)
523 				Radar_static_next = 1;
524 		}
525 
526 	if (timestamp_elapsed(Radar_death_timer))
527 		ok_to_blit_radar = 0;
528 
529 	setupViewHtl();
530 
531 	//WMC - This strikes me as a bit hackish
532 	bool g3_yourself = !g3_in_frame();
533 	if(g3_yourself)
534 		g3_start_frame(1);
535 
536 	drawSweeps();
537 
538 	if (timestamp_elapsed(Radar_static_next))
539 	{
540 		Radar_static_playing ^= 1;
541 		Radar_static_next = timestamp_rand(50, 750);
542 	}
543 
544 	// if the emp effect is active, always draw the radar wackily
545 	if (emp_active_local())
546 		Radar_static_playing = 1;
547 
548 	if (ok_to_blit_radar)
549 	{
550 		if (Radar_static_playing)
551 		{
552 			drawBlipsSorted(1);	// passing 1 means to draw distorted
553 
554 			if (!Radar_static_looping.isValid())
555 				Radar_static_looping = snd_play_looping(gamesnd_get_game_sound(GameSounds::STATIC));
556 		}
557 		else
558 		{
559 			drawBlipsSorted(0);
560 
561 			if (Radar_static_looping.isValid()) {
562 				snd_stop(Radar_static_looping);
563 				Radar_static_looping = sound_handle::invalid();
564 			}
565 		}
566 	}
567 	else
568 	{
569 		if (Radar_static_looping.isValid()) {
570 			snd_stop(Radar_static_looping);
571 			Radar_static_looping = sound_handle::invalid();
572 		}
573 	}
574 
575 	if(g3_yourself)
576 		g3_end_frame();
577 
578 	doneDrawingHtl();
579 }
580 
pageIn()581 void HudGaugeRadarDradis::pageIn()
582 {
583 	bm_page_in_texture(xy_plane);
584 	bm_page_in_texture(xz_yz_plane);
585 	bm_page_in_texture(sweep_plane);
586 	bm_page_in_texture(target_brackets);
587 	bm_page_in_texture(unknown_contact_icon);
588 }
589 
doLoopSnd()590 void HudGaugeRadarDradis::doLoopSnd()
591 {
592 	if (!this->m_loop_snd.isValid())
593 	{
594 		return;
595 	}
596 
597 	if (!this->shouldDoSounds())
598 	{
599 		if (loop_sound_handle.isValid() && snd_is_playing(loop_sound_handle)) {
600 			snd_stop(loop_sound_handle);
601 			loop_sound_handle = sound_handle::invalid();
602 		}
603 	} else if (!this->loop_sound_handle.isValid() || !snd_is_playing(this->loop_sound_handle)) {
604 		loop_sound_handle = snd_play(gamesnd_get_game_sound(m_loop_snd), 0.0f, loop_sound_volume);
605 	}
606 }
607 
doBeeps()608 void HudGaugeRadarDradis::doBeeps()
609 {
610 	if (!this->shouldDoSounds())
611 	{
612 		return;
613 	}
614 
615 	if (Missiontime == 0 || Missiontime == Frametime)
616 	{
617 		// don't play sounds in first frame
618 		return;
619 	}
620 
621 	if (!arrival_beep_snd.isValid() &&
622 		!departure_beep_snd.isValid() &&
623 		!m_stealth_arrival_snd.isValid() &&
624 		!stealth_departure_snd.isValid())
625 	{
626 		return;
627 	}
628 
629 	bool departure_happened = false;
630 	bool stealth_departure_happened = false;
631 
632 	bool arrival_happened = false;
633 	bool stealth_arrival_happened = false;
634 
635 	for (int i = 0; i < MAX_SHIPS; i++)
636 	{
637 		ship * shipp = &Ships[i];
638 
639 		if (shipp->objnum >= 0)
640 		{
641 			if (shipp->radar_visible_since >= 0 || shipp->radar_last_contact >= 0)
642 			{
643 				if (shipp->radar_visible_since == Missiontime)
644 				{
645 					if (shipp->radar_current_status == DISTORTED)
646 					{
647 						stealth_arrival_happened = true;
648 					}
649 					else
650 					{
651 						arrival_happened = true;
652 					}
653 				}
654 				else if (shipp->radar_visible_since < 0 && shipp->radar_last_contact == Missiontime)
655 				{
656 					if (shipp->radar_last_status == DISTORTED)
657 					{
658 						stealth_departure_happened = true;
659 					}
660 					else
661 					{
662 						departure_happened = true;
663 					}
664 				}
665 			}
666 		}
667 	}
668 
669 	if (timestamp_elapsed(arrival_beep_next_check))
670 	{
671 		if (arrival_beep_snd.isValid() && arrival_happened)
672 		{
673 			snd_play(gamesnd_get_game_sound(arrival_beep_snd));
674 
675 			arrival_beep_next_check = timestamp(arrival_beep_delay);
676 		}
677 		else if (m_stealth_arrival_snd.isValid() && stealth_arrival_happened)
678 		{
679 			snd_play(gamesnd_get_game_sound(m_stealth_arrival_snd));
680 
681 			arrival_beep_next_check = timestamp(arrival_beep_delay);
682 		}
683 
684 	}
685 
686 	if (timestamp_elapsed(departure_beep_next_check))
687 	{
688 		if (departure_beep_snd.isValid() && departure_happened)
689 		{
690 			snd_play(gamesnd_get_game_sound(departure_beep_snd));
691 
692 			departure_beep_next_check = timestamp(departure_beep_delay);
693 		}
694 		else if (stealth_departure_snd.isValid() && stealth_departure_happened)
695 		{
696 			snd_play(gamesnd_get_game_sound(stealth_departure_snd));
697 
698 			departure_beep_next_check = timestamp(departure_beep_delay);
699 		}
700 	}
701 }
702 
initSound(gamesnd_id loop_snd,float _loop_snd_volume,gamesnd_id arrival_snd,gamesnd_id departure_snd,gamesnd_id stealth_arrival_snd,gamesnd_id stealth_departue_snd,float arrival_delay,float departure_delay)703 void HudGaugeRadarDradis::initSound(gamesnd_id loop_snd, float _loop_snd_volume, gamesnd_id arrival_snd, gamesnd_id departure_snd, gamesnd_id stealth_arrival_snd, gamesnd_id stealth_departue_snd, float arrival_delay, float departure_delay)
704 {
705 	this->m_loop_snd = loop_snd;
706 	this->loop_sound_handle = sound_handle::invalid();
707 	this->loop_sound_volume = _loop_snd_volume;
708 
709 	this->arrival_beep_snd = arrival_snd;
710 	this->departure_beep_snd = departure_snd;
711 
712 	this->m_stealth_arrival_snd = stealth_arrival_snd;
713 	this->stealth_departure_snd = stealth_departue_snd;
714 
715 	this->arrival_beep_delay = fl2i(arrival_delay * 1000.0f);
716 	this->departure_beep_delay = fl2i(departure_delay * 1000.0f);
717 }
718 
onFrame(float)719 void HudGaugeRadarDradis::onFrame(float  /*frametime*/)
720 {
721 	// Play the specified radar sound
722 	this->doLoopSnd();
723 
724 	// Play beeps for ship arrival and departure
725 	this->doBeeps();
726 }
727 
initialize()728 void HudGaugeRadarDradis::initialize()
729 {
730 	HudGaugeRadar::initialize();
731 
732 	this->arrival_beep_next_check = timestamp();
733 	this->departure_beep_next_check = timestamp();
734 }
735 
shouldDoSounds()736 bool HudGaugeRadarDradis::shouldDoSounds()
737 {
738 	if (hud_disabled())
739 		return false;
740 
741 	if (Viewer_mode & (VM_EXTERNAL | VM_CHASE | VM_DEAD_VIEW | VM_OTHER_SHIP))
742 		return false;
743 
744 	return true;
745 }
746