1#include "radar.qh"
2
3#include <common/ent_cs.qh>
4#include <common/mapinfo.qh>
5#include <client/mapvoting.qh>
6#include <client/teamradar.qh>
7#include <common/mutators/mutator/waypoints/all.qh>
8
9// Radar (#6)
10
11bool HUD_Radar_Clickable()
12{
13	return hud_panel_radar_mouse && !hud_panel_radar_temp_hidden;
14}
15
16void HUD_Radar_Show_Maximized(bool doshow, bool clickable)
17{
18    TC(bool, doshow);
19	hud_panel_radar_maximized = doshow;
20	hud_panel_radar_temp_hidden = 0;
21
22	if ( doshow )
23	{
24		if (clickable)
25		{
26			if(autocvar_hud_cursormode)
27				setcursormode(1);
28			hud_panel_radar_mouse = 1;
29
30			// we must unset the player's buttons, as they aren't released elsewhere
31			localcmd("-fire\n");
32			localcmd("-fire2\n");
33			localcmd("-use\n");
34			localcmd("-hook\n");
35			localcmd("-jump\n");
36		}
37	}
38	else if ( hud_panel_radar_mouse )
39	{
40		hud_panel_radar_mouse = 0;
41		mouseClicked = 0;
42		if(autocvar_hud_cursormode)
43		if(!mv_active)
44			setcursormode(0);
45	}
46}
47void HUD_Radar_Hide_Maximized()
48{
49	HUD_Radar_Show_Maximized(false,false);
50}
51
52
53float HUD_Radar_InputEvent(int bInputType, float nPrimary, float nSecondary)
54{
55    TC(int, bInputType);
56	if(!hud_panel_radar_maximized || !hud_panel_radar_mouse ||
57		autocvar__hud_configure || mv_active)
58		return false;
59
60	if(bInputType == 3)
61	{
62		mousepos_x = nPrimary;
63		mousepos_y = nSecondary;
64		return true;
65	}
66
67	if(nPrimary == K_MOUSE1)
68	{
69		if(bInputType == 0) // key pressed
70			mouseClicked |= S_MOUSE1;
71		else if(bInputType == 1) // key released
72			mouseClicked -= (mouseClicked & S_MOUSE1);
73	}
74	else if(nPrimary == K_MOUSE2)
75	{
76		if(bInputType == 0) // key pressed
77			mouseClicked |= S_MOUSE2;
78		else if(bInputType == 1) // key released
79			mouseClicked -= (mouseClicked & S_MOUSE2);
80	}
81	else if ( nPrimary == K_ESCAPE && bInputType == 0 )
82	{
83		HUD_Radar_Hide_Maximized();
84	}
85	else
86	{
87		// allow console/use binds to work without hiding the map
88		string con_keys = strcat(findkeysforcommand("toggleconsole", 0), " ", findkeysforcommand("+use", 0)) ;
89		int keys = tokenize(con_keys); // findkeysforcommand returns data for this
90		int i;
91		for (i = 0; i < keys; ++i)
92		{
93			if(nPrimary == stof(argv(i)))
94				return false;
95		}
96
97		if ( STAT(HEALTH) <= 0 )
98		{
99			// Show scoreboard
100			if ( bInputType < 2 )
101			{
102				con_keys = findkeysforcommand("+showscores", 0);
103				keys = tokenize(con_keys);
104				for (i = 0; i < keys; ++i)
105				{
106					if ( nPrimary == stof(argv(i)) )
107					{
108						hud_panel_radar_temp_hidden = bInputType == 0;
109						return false;
110					}
111				}
112			}
113		}
114		else if ( bInputType == 0 )
115			HUD_Radar_Hide_Maximized();
116
117		return false;
118	}
119
120	return true;
121}
122
123void HUD_Radar_Mouse()
124{
125	if ( !hud_panel_radar_mouse ) return;
126	if(mv_active) return;
127
128	if ( intermission )
129	{
130		HUD_Radar_Hide_Maximized();
131		return;
132	}
133
134	if(mouseClicked & S_MOUSE2)
135	{
136		HUD_Radar_Hide_Maximized();
137		return;
138	}
139
140	if (!autocvar_hud_cursormode)
141		update_mousepos();
142
143	panel = HUD_PANEL(RADAR);
144	HUD_Panel_LoadCvars();
145
146
147	panel_size = autocvar_hud_panel_radar_maximized_size;
148	panel_size_x = bound(0.2, panel_size_x, 1) * vid_conwidth;
149	panel_size_y = bound(0.2, panel_size_y, 1) * vid_conheight;
150	panel_pos_x = (vid_conwidth - panel_size_x) / 2;
151	panel_pos_y = (vid_conheight - panel_size_y) / 2;
152
153	if(mouseClicked & S_MOUSE1)
154	{
155		// click outside
156		if ( mousepos_x < panel_pos_x || mousepos_x > panel_pos_x + panel_size_x ||
157			 mousepos_y < panel_pos_y || mousepos_y > panel_pos_y + panel_size_y )
158		{
159			HUD_Radar_Hide_Maximized();
160			return;
161		}
162		vector pos = teamradar_texcoord_to_3dcoord(teamradar_2dcoord_to_texcoord(mousepos),view_origin_z);
163		localcmd(sprintf("cmd ons_spawn %f %f %f",pos_x,pos_y,pos_z));
164
165		HUD_Radar_Hide_Maximized();
166		return;
167	}
168
169
170	draw_cursor_normal(mousepos, '1 1 1', 0.8);
171}
172
173void HUD_Radar()
174{
175	if (!autocvar__hud_configure)
176	{
177		if (hud_panel_radar_maximized)
178		{
179			if (!hud_draw_maximized) return;
180		}
181		else
182		{
183			if (autocvar_hud_panel_radar == 0) return;
184			if (autocvar_hud_panel_radar != 2 && !teamplay) return;
185			if(radar_panel_modified)
186			{
187				panel.update_time = time; // forces reload of panel attributes
188				radar_panel_modified = false;
189			}
190		}
191	}
192
193	if ( hud_panel_radar_temp_hidden )
194		return;
195
196	HUD_Panel_LoadCvars();
197
198	float f = 0;
199
200	if (hud_panel_radar_maximized && !autocvar__hud_configure)
201	{
202		panel_size = autocvar_hud_panel_radar_maximized_size;
203		panel_size.x = bound(0.2, panel_size.x, 1) * vid_conwidth;
204		panel_size.y = bound(0.2, panel_size.y, 1) * vid_conheight;
205		panel_pos.x = (vid_conwidth - panel_size.x) / 2;
206		panel_pos.y = (vid_conheight - panel_size.y) / 2;
207
208		string panel_bg;
209		panel_bg = strcat(hud_skin_path, "/border_default"); // always use the default border when maximized
210		if(precache_pic(panel_bg) == "")
211			panel_bg = "gfx/hud/default/border_default"; // fallback
212		if(!radar_panel_modified && panel_bg != panel.current_panel_bg)
213			radar_panel_modified = true;
214		if(panel.current_panel_bg)
215			strunzone(panel.current_panel_bg);
216		panel.current_panel_bg = strzone(panel_bg);
217
218		switch(hud_panel_radar_maximized_zoommode)
219		{
220			default:
221			case 0:
222				f = current_zoomfraction;
223				break;
224			case 1:
225				f = 1 - current_zoomfraction;
226				break;
227			case 2:
228				f = 0;
229				break;
230			case 3:
231				f = 1;
232				break;
233		}
234
235		switch(hud_panel_radar_maximized_rotation)
236		{
237			case 0:
238				teamradar_angle = view_angles.y - 90;
239				break;
240			default:
241				teamradar_angle = 90 * hud_panel_radar_maximized_rotation;
242				break;
243		}
244	}
245	if (!hud_panel_radar_maximized && !autocvar__hud_configure)
246	{
247		switch(hud_panel_radar_zoommode)
248		{
249			default:
250			case 0:
251				f = current_zoomfraction;
252				break;
253			case 1:
254				f = 1 - current_zoomfraction;
255				break;
256			case 2:
257				f = 0;
258				break;
259			case 3:
260				f = 1;
261				break;
262		}
263
264		switch(hud_panel_radar_rotation)
265		{
266			case 0:
267				teamradar_angle = view_angles.y - 90;
268				break;
269			default:
270				teamradar_angle = 90 * hud_panel_radar_rotation;
271				break;
272		}
273	}
274
275	vector pos, mySize;
276	pos = panel_pos;
277	mySize = panel_size;
278
279	if (autocvar_hud_panel_radar_dynamichud)
280		HUD_Scale_Enable();
281	else
282		HUD_Scale_Disable();
283	HUD_Panel_DrawBg();
284	if(panel_bg_padding)
285	{
286		pos += '1 1 0' * panel_bg_padding;
287		mySize -= '2 2 0' * panel_bg_padding;
288	}
289
290	int color2;
291	float scale2d, normalsize, bigsize;
292
293	teamradar_origin2d = HUD_Shift(pos + 0.5 * mySize);
294	teamradar_size2d = mySize;
295
296	if(minimapname == "")
297		return;
298
299	teamradar_loadcvars();
300
301	scale2d = vlen_maxnorm2d(mi_picmax - mi_picmin);
302	teamradar_size2d = HUD_Scale(mySize);
303
304	teamradar_extraclip_mins = teamradar_extraclip_maxs = '0 0 0'; // we always center
305
306	// pixels per world qu to match the teamradar_size2d_x range in the longest dimension
307	if((hud_panel_radar_rotation == 0 && !hud_panel_radar_maximized) || (hud_panel_radar_maximized_rotation == 0 && hud_panel_radar_maximized))
308	{
309		// max-min distance must fit the radar in any rotation
310		bigsize = vlen_minnorm2d(teamradar_size2d) * scale2d / (1.05 * vlen(vec2(mi_scale)));
311	}
312	else
313	{
314		vector c0, c1, c2, c3, span;
315		c0 = Rotate(mi_min, teamradar_angle * DEG2RAD);
316		c1 = Rotate(mi_max, teamradar_angle * DEG2RAD);
317		c2 = Rotate('1 0 0' * mi_min.x + '0 1 0' * mi_max.y, teamradar_angle * DEG2RAD);
318		c3 = Rotate('1 0 0' * mi_max.x + '0 1 0' * mi_min.y, teamradar_angle * DEG2RAD);
319		span = '0 0 0';
320		span.x = max(c0_x, c1_x, c2_x, c3_x) - min(c0_x, c1_x, c2_x, c3_x);
321		span.y = max(c0_y, c1_y, c2_y, c3_y) - min(c0_y, c1_y, c2_y, c3_y);
322
323		// max-min distance must fit the radar in x=x, y=y
324		bigsize = min(
325			teamradar_size2d.x * scale2d / (1.05 * span.x),
326			teamradar_size2d.y * scale2d / (1.05 * span.y)
327		);
328	}
329
330	normalsize = vlen_maxnorm2d(teamradar_size2d) * scale2d / hud_panel_radar_scale;
331	if(bigsize > normalsize)
332		normalsize = bigsize;
333
334	teamradar_size =
335		  f * bigsize
336		+ (1 - f) * normalsize;
337	teamradar_origin3d_in_texcoord = teamradar_3dcoord_to_texcoord(
338		  f * mi_center
339		+ (1 - f) * view_origin);
340
341	drawsetcliparea(
342		pos.x,
343		pos.y,
344		mySize.x,
345		mySize.y
346	);
347
348	draw_teamradar_background(hud_panel_radar_foreground_alpha);
349
350	IL_EACH(g_radarlinks, true, draw_teamradar_link(it.origin, it.velocity, it.team));
351
352	IL_EACH(g_radaricons, it.teamradar_icon, {
353		if ( hud_panel_radar_mouse )
354		if ( it.health >= 0 )
355		if ( it.team == myteam + 1 || gametype == MAPINFO_TYPE_RACE || !teamplay )
356		{
357			vector coord = teamradar_texcoord_to_2dcoord(teamradar_3dcoord_to_texcoord(it.origin));
358			if(vdist((mousepos - coord), <, 8))
359			{
360				vector brightcolor;
361				brightcolor_x = min(1,it.teamradar_color_x*1.5);
362				brightcolor_y = min(1,it.teamradar_color_y*1.5);
363				brightcolor_z = min(1,it.teamradar_color_z*1.5);
364				drawpic(coord - '8 8 0', "gfx/teamradar_icon_glow", '16 16 0', brightcolor, panel_fg_alpha, 0);
365			}
366		}
367		entity icon = RadarIcons_from(it.teamradar_icon);
368		draw_teamradar_icon(it.origin, icon, it, spritelookupcolor(it, icon.netname, it.teamradar_color), panel_fg_alpha);
369	});
370	AL_EACH(_entcs, e, it != NULL, {
371		if (!it.m_entcs_private) continue;
372		if (it.sv_entnum == current_player) continue;
373		color2 = entcs_GetTeam(it.sv_entnum);
374		draw_teamradar_player(it.origin, it.angles, Team_ColorRGB(color2));
375	});
376	draw_teamradar_player(entcs_receiver(current_player).origin, view_angles, '1 1 1');
377
378	drawresetcliparea();
379
380	if ( hud_panel_radar_mouse )
381	{
382		string message = "Click to select teleport destination";
383
384		if ( STAT(HEALTH) <= 0 )
385		{
386			message = "Click to select spawn location";
387		}
388
389		drawcolorcodedstring(pos + '0.5 0 0' * (mySize_x - stringwidth(message, true, hud_fontsize)) - '0 1 0' * hud_fontsize_y * 2,
390							 message, hud_fontsize, hud_panel_radar_foreground_alpha, DRAWFLAG_NORMAL);
391
392		hud_panel_radar_bottom = pos_y + mySize_y + hud_fontsize_y;
393	}
394}
395