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