1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell
5  * or otherwise commercially exploit the source or things you created based on the
6  * source.
7  *
8 */
9 
10 
11 
12 
13 #include "controlconfig/controlsconfig.h"
14 #include "freespace.h"
15 #include "gamesequence/gamesequence.h"
16 #include "globalincs/alphacolors.h"
17 #include "graphics/font.h"
18 #include "hud/hud.h"
19 #include "hud/hudmessage.h"
20 #include "io/key.h"
21 #include "missionui/missionpause.h"
22 #include "network/multi_pause.h"
23 #include "object/object.h"
24 #include "popup/popup.h"
25 #include "sound/audiostr.h"
26 #include "ui/ui.h"
27 #include "weapon/weapon.h"
28 
29 
30 
31 
32 // ----------------------------------------------------------------------------------------------------------------
33 // PAUSE DEFINES/VARS
34 //
35 
36 // pause bitmap name
37 const char *Pause_bmp_name[GR_NUM_RESOLUTIONS] = {
38 	"PleaseWait",
39 	"2_PleaseWait"
40 };
41 
42 // pause bitmap display stuff
43 int Please_wait_coords[GR_NUM_RESOLUTIONS][4] = {
44 	{ // GR_640
45 		152, 217, 316, 26
46 	},
47 	{ // GR_1024
48 		247, 346, 510, 36
49 	}
50 };
51 
52 // pause window objects
53 UI_WINDOW Pause_win;
54 UI_CHECKBOX Pause_single_step;
55 UI_CHECKBOX Pause_physics;
56 UI_CHECKBOX Pause_ai;
57 UI_CHECKBOX Pause_ai_render;
58 UI_CHECKBOX Pause_firing;
59 UI_CHECKBOX Pause_external_view_mode_check;
60 UI_BUTTON Pause_continue;
61 int Pause_type = PAUSE_TYPE_NORMAL;
62 
63 // if we're already paused
64 int Paused = 0;
65 
66 // background screen (for the chatbox)
67 int Pause_background_bitmap = -1;
68 
69 // saved background screen
70 int Pause_saved_screen = -1;
71 
72 // if we're in external vie wmode
73 int Pause_external_view_mode = 0;
74 
75 // externs
76 extern int Ai_render_debug_flag;
77 extern int Ai_firing_enabled;
78 extern int physics_paused;
79 extern int ai_paused;
80 extern int last_single_step;
81 extern int game_single_step;
82 
83 // ----------------------------------------------------------------------------------------------------------------
84 // PAUSE FUNCTIONS
85 //
86 
pause_get_type()87 int pause_get_type()
88 {
89 	return Pause_type;
90 }
91 
pause_set_type(int type)92 void pause_set_type(int type)
93 {
94 	Pause_type = type;
95 }
96 
97 // initialize the pause screen
pause_init()98 void pause_init()
99 {
100 	// if we're already paused. do nothing
101 	if ( Paused ) {
102 		return;
103 	}
104 
105 	Assert( !(Game_mode & GM_MULTIPLAYER) );
106 
107 	// pause all weapon sounds
108 	weapon_pause_sounds();
109 
110 	if (Pause_type == PAUSE_TYPE_NORMAL)	{
111 		Pause_saved_screen = gr_save_screen();
112 	}
113 
114 	// pause all game music
115 	audiostream_pause_all();
116 
117 	Pause_win.create(0, 0, gr_screen.max_w_unscaled, gr_screen.max_h_unscaled, 0);
118 
119 	Pause_background_bitmap = bm_load(Pause_bmp_name[gr_screen.res]);
120 
121 	io::mouse::CursorManager::get()->pushStatus();
122 	io::mouse::CursorManager::get()->showCursor(true);
123 
124 	Paused = 1;
125 }
126 
127 extern int button_function_demo_valid(int n);
128 extern int button_function(int n);
129 
130 // pause do frame - will handle running multiplayer operations if necessary
pause_do()131 void pause_do()
132 {
133 	int k;
134 	const char *pause_str = XSTR("Paused", 767);
135 	int str_w, str_h;
136 	// next two are for view resetting
137 	static int previous_Viewer_mode = -1;
138 	static int previous_hud_state = -1;
139 
140 	Assert( !(Game_mode & GM_MULTIPLAYER) );
141 
142 	//	RENDER A GAME FRAME HERE AS THE BACKGROUND (if normal pause)
143 
144 	if(Pause_type == PAUSE_TYPE_NORMAL)	{
145 		// Fall back to viewer just incase saved screen is invalid
146 		if(Pause_saved_screen == -1){
147 			Pause_type = PAUSE_TYPE_VIEWER;
148 		}
149 		else if(Pause_type == PAUSE_TYPE_NORMAL)	{
150 			gr_restore_screen(Pause_saved_screen);
151 		}
152 	}
153 
154 	if(Pause_type == PAUSE_TYPE_NORMAL){
155 		if (Pause_background_bitmap >= 0) {
156 			gr_set_bitmap(Pause_background_bitmap);
157 
158 			// draw the bitmap
159 			gr_bitmap(Please_wait_coords[gr_screen.res][0], Please_wait_coords[gr_screen.res][1], GR_RESIZE_MENU);
160 
161 			// draw "Paused" on it
162 			gr_set_color_fast(&Color_normal);
163 			font::set_font(font::FONT2);
164 			gr_get_string_size(&str_w, &str_h, pause_str);
165 			gr_string((gr_screen.max_w_unscaled - str_w) / 2, (gr_screen.max_h_unscaled - str_h) / 2, pause_str, GR_RESIZE_MENU);
166 			font::set_font(font::FONT1);
167 		}
168 	}
169 
170 	if (Pause_type == PAUSE_TYPE_VIEWER) {
171 		if (previous_Viewer_mode < 0)
172 			previous_Viewer_mode = Viewer_mode;
173 
174 		if (previous_hud_state < 0)
175 			previous_hud_state = hud_disabled();
176 	}
177 
178 	// process the ui window here
179 	k = Pause_win.process() & ~KEY_DEBUGGED;
180 	switch (k)
181 	{
182 		case KEY_TAB:
183 			hud_toggle_draw();
184 			break;
185 
186 		// view from outside of the ship
187 	   	case KEY_ENTER:
188 			if (Pause_type == PAUSE_TYPE_VIEWER) {
189 				button_function_demo_valid(VIEW_EXTERNAL);
190 			}
191 			break;
192 
193 		// view from target
194 		case KEY_PADDIVIDE:
195 			if (Pause_type == PAUSE_TYPE_VIEWER) {
196 				button_function_demo_valid(VIEW_OTHER_SHIP);
197 			}
198 			break;
199 
200 		// change target
201 		case KEY_PADMULTIPLY:
202 			if (Pause_type == PAUSE_TYPE_VIEWER) {
203 				button_function(TARGET_NEXT);
204 			}
205 			break;
206 
207 		case KEY_ESC:
208 		case KEY_ALTED + KEY_PAUSE:
209 		case KEY_PAUSE:
210 			// reset previous view if we happened to be playing around with it during pause
211 			if (Pause_type == PAUSE_TYPE_VIEWER) {
212 				if (previous_Viewer_mode >= 0) {
213 					Viewer_mode = previous_Viewer_mode;
214 				}
215 
216 				// NOTE remember that hud state is reversed here (0 == on, 1 == off)
217 				if ( (previous_hud_state >= 0) && (hud_disabled() != previous_hud_state) ) {
218 					hud_set_draw( !previous_hud_state );
219 				}
220 			}
221 
222 			gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
223 			break;
224 	}	// end switch
225 
226 	// draw the background window
227 	Pause_win.draw();
228 
229 	// a very unique case where we shouldn't be doing the page flip because we're inside of popup code
230 	if(!popup_active()){
231 		if(Pause_type == PAUSE_TYPE_NORMAL) {
232 			gr_flip();
233 		}
234 	} else {
235 		// this should only be happening in a very unique multiplayer case
236 		Int3();
237 	}
238 }
239 
240 // close the pause screen
pause_close()241 void pause_close()
242 {
243 	// if we're not paused - do nothing
244 	if ( !Paused ) {
245 		return;
246 	}
247 
248 	Assert( !(Game_mode & GM_MULTIPLAYER) );
249 
250 	// unpause all weapon sounds
251 	weapon_unpause_sounds();
252 
253 	// deinit stuff
254 	if(Pause_saved_screen != -1) {
255 		gr_free_screen(Pause_saved_screen);
256 		Pause_saved_screen = -1;
257 	}
258 
259 	if (Pause_background_bitmap != -1){
260 		bm_release(Pause_background_bitmap);
261 		Pause_background_bitmap = -1;
262 	}
263 
264 	Pause_win.destroy();
265 	game_flush();
266 
267 	io::mouse::CursorManager::get()->popStatus();
268 
269 	// unpause all the music
270 	audiostream_unpause_all();
271 
272 	Paused = 0;
273 }
274 
275 // debug pause init
pause_debug_init()276 void pause_debug_init()
277 {
278 	Pause_win.create( 100,100,400,300, WIN_DIALOG );
279 
280 	Pause_physics.create( &Pause_win, NOX("Physics Pause <P>"), 200, 150, physics_paused );
281 	Pause_ai.create( &Pause_win, NOX("AI Pause <A>"), 200, 175, ai_paused );
282 	#ifndef NDEBUG
283 	Pause_ai_render.create( &Pause_win, NOX("AI Render Stuff <R>"), 200, 200, Ai_render_debug_flag);
284 	#endif
285 	Pause_firing.create( &Pause_win, NOX("AI firing <F>"), 200, 225, Ai_firing_enabled);
286 	Pause_external_view_mode_check.create( &Pause_win, NOX("External View <E>"), 200, 250, Pause_external_view_mode);
287 	Pause_single_step.create( &Pause_win, NOX("Single Step <S>"), 200, 290, game_single_step );
288 	Pause_continue.create( &Pause_win, NOX("Leave Pause"), 200, 350, 200, 40 );
289 
290 	Pause_single_step.set_hotkey( KEY_S );
291 	Pause_physics.set_hotkey( KEY_P );
292 	Pause_ai.set_hotkey( KEY_A );
293 	Pause_ai_render.set_hotkey( KEY_R );
294 	Pause_firing.set_hotkey( KEY_F );
295 	Pause_external_view_mode_check.set_hotkey( KEY_E );
296 	Pause_continue.set_hotkey( KEY_ESC );
297 
298 	Pause_continue.set_focus();
299 }
300 
301 // debug pause do frame
pause_debug_do()302 void pause_debug_do()
303 {
304 	int key;
305 
306 	key = Pause_win.process();
307 	if ( Pause_single_step.changed())	{
308 		game_single_step = Pause_single_step.checked();
309 	}
310 
311 	if ( Pause_physics.changed())	{
312 		physics_paused = Pause_physics.checked();
313 	}
314 
315 	if ( Pause_ai.changed())	{
316 		ai_paused = Pause_ai.checked();
317 		if (ai_paused){
318 			obj_init_all_ships_physics();
319 		}
320 	}
321 
322 	if ( Pause_ai_render.changed())	{
323 		Ai_render_debug_flag = Pause_ai_render.checked();
324 	}
325 
326 	if ( Pause_firing.changed())	{
327 		Ai_firing_enabled = Pause_firing.checked();
328 	}
329 
330 	if ( Pause_external_view_mode_check.changed())	{
331 		Pause_external_view_mode = Pause_external_view_mode_check.checked();
332 		if (Pause_external_view_mode){
333 			HUD_sourced_printf(HUD_SOURCE_HIDDEN, "%s", XSTR( "External view of player ship.", 182));
334 		} else {
335 			HUD_sourced_printf(HUD_SOURCE_HIDDEN, "%s", XSTR( "View from inside player ship.", 183));
336 		}
337 	}
338 
339 	if ( Pause_continue.pressed() || (key == KEY_PAUSE) )	{	//	Changed, MK, 11/9/97, only Pause break pause.
340 		gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
341 	}
342 
343 	gr_clear();
344 	Pause_win.draw();
345 
346 	gr_flip();
347 }
348 
349 // debug pause close
pause_debug_close()350 void pause_debug_close()
351 {
352 	last_single_step = 0;	// Make so single step waits a frame before stepping
353 	Pause_win.destroy();
354 	game_flush();
355 }
356