FS2_Open
Open source remastering of the Freespace 2 engine
popupdead.cpp
Go to the documentation of this file.
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 
14 #define POPUPDEAD_NUM_CHOICES 3 // normal
15 #define POPUPDEAD_NUM_CHOICES_RA 4 // red alert
16 #define POPUPDEAD_NUM_CHOICES_SKIP 3 // skip mission menu
17 
18 #define POPUPDEAD_NUM_CHOICES_MAX 4
19 
20 #include "freespace2/freespace.h"
22 #include "gamesnd/gamesnd.h"
23 #include "globalincs/alphacolors.h"
24 #include "hud/hudmessage.h"
25 #include "io/key.h"
26 #include "io/timer.h"
28 #include "network/multi.h"
29 #include "network/multiutil.h"
30 #include "playerman/player.h"
31 #include "popup/popup.h"
32 #include "popup/popupdead.h"
33 #include "ui/ui.h"
34 
35 
38 UI_BUTTON Popupdead_button_regions[POPUPDEAD_NUM_CHOICES_MAX]; // fake buttons used for mouse detection over text
39 
41 {
42  { // GR_640
43  {464, 389, 497, 403}, // upper right pixel of text, lower right pixel of button (for tiny popup)
44  {464, 413, 497, 427},
45  {464, 435, 497, 446},
46  {464, 457, 497, 466},
47  },
48  { // GR_1024
49  {745, 627, 809, 664},
50  {745, 663, 809, 700}, // upper right pixel of text, lower right pixel of button (for tiny popup)
51  {745, 699, 809, 736},
52  {745, 735, 809, 772},
53  },
54 };
55 
57 {
58  { // GR_640
59  {478, 387}, // upper left pixel (tiny popup)
60  {478, 410},
61  {478, 432},
62  {478, 455},
63  },
64  { // GR_1024
65  {760, 620}, // upper left pixel (tiny popup)
66  {760, 656},
67  {760, 692},
68  {760, 728},
69  }
70 };
71 
73  "PopDeath", // GR_640
74  "2_PopDeath" // GR-1024
75 };
76 
78 {
79  { // GR_640
80  131, 363
81  },
82  { // GR_1024
83  205, 581
84  }
85 };
86 
88 {
89  { // GR_640
90  "PopD_00", // first choice
91  "PopD_01", // second choice
92  "PopD_02", // third choice
93  "PopD_03", // fourth choice
94  },
95  { // GR_1024
96  "2_PopD_00", // first choice
97  "2_PopD_01", // second choice
98  "2_PopD_02", // third choice
99  "2_PopD_03", // fourth choice
100  }
101 };
102 
104  96, // GR_640
105  160
106 };
107 
108 
109 static const char *Popupdead_button_text[POPUPDEAD_NUM_CHOICES_MAX];
110 
111 // multiplayer specifics to help with return values since they can vary
112 #define POPUPDEAD_OBS_ONLY 1
113 #define POPUPDEAD_OBS_QUIT 2
114 #define POPUPDEAD_RESPAWN_ONLY 3
115 #define POPUPDEAD_RESPAWN_QUIT 4
116 
117 int Popupdead_default_choice; // What the default choice is (ie activated when Enter pressed)
118 int Popupdead_active = 0; // A dead popup is active
119 int Popupdead_choice; // Index for choice picked (-1 if none picked)
120 int Popupdead_num_choices; // number of buttons
121 int Popupdead_multi_type; // what kind of popup is active for muliplayer
122 int Popupdead_skip_active = 0; // The skip-misison popup is active
124 
126 
127 extern int Cmdline_mpnoreturn;
128 // Initialize the dead popup data
130 {
131  int i;
132  UI_BUTTON *b;
133 
134  if ( Popupdead_active ) {
135  return;
136  }
137 
138  // increment number of deaths
140 
141 
142  // create base window
145 
148 
151  if (Game_mode & GM_MULTIPLAYER) {
154  HUD_printf("Player will automatically respawn in %d seconds", The_mission.max_respawn_delay);
155  }
156  else {
157  HUD_printf("Player will automatically respawn now");
158  }
159  }
160  }
161  }
162 
163  if ( Game_mode & GM_NORMAL ) {
164  // also do a campaign check here?
165  if (0) { //((Player->show_skip_popup) && (!Popupdead_skip_already_shown) && (Game_mode & GM_CAMPAIGN_MODE) && (Game_mode & GM_NORMAL) && (Player->failures_this_session >= PLAYER_MISSION_FAILURE_LIMIT)) {
166  // init the special preliminary death popup that gives the skip option
167  Popupdead_button_text[0] = XSTR( "Do Not Skip This Mission", 1473);
168  Popupdead_button_text[1] = XSTR( "Advance To The Next Mission", 1474);
169  Popupdead_button_text[2] = XSTR( "Don't Show Me This Again", 1475);
173  // We can't staticly declare these because they are externalized
174  Popupdead_button_text[0] = XSTR( "Quick Start Mission", 105);
175  Popupdead_button_text[1] = XSTR( "Return To Flight Deck", 106);
176  Popupdead_button_text[2] = XSTR( "Return To Briefing", 107);
177  Popupdead_button_text[3] = XSTR( "Replay previous mission", 1432);
179  } else {
180  Popupdead_button_text[0] = XSTR( "Quick Start Mission", 105);
181  Popupdead_button_text[1] = XSTR( "Return To Flight Deck", 106);
182  Popupdead_button_text[2] = XSTR( "Return To Briefing", 107);
184  }
185  } else {
186  // in multiplayer, we have different choices depending on respawn mode, etc.
187 
188  // if the player has run out of respawns and must either quit and become an observer
190 
191  // the master should not be able to quit the game
193  Popupdead_button_text[0] = XSTR( "Observer Mode", 108);
196  } else {
197  Popupdead_button_text[0] = XSTR( "Observer Mode", 108);
198  Popupdead_button_text[1] = XSTR( "Return To Flight Deck", 106);
201  }
202  } else {
203  // the master of the game should not be allowed to quit
205  Popupdead_button_text[0] = XSTR( "Respawn", 109);
208  } else {
209  Popupdead_button_text[0] = XSTR( "Respawn", 109);
210  if(!Cmdline_mpnoreturn)
211  {
212  Popupdead_button_text[1] = XSTR( "Return To Flight Deck", 106);
214  }
215  else
216  {
218  }
220  }
221  }
222  }
223 
224  // create buttons
225  for (i=0; i < Popupdead_num_choices; i++) {
226  b = &Popupdead_buttons[i];
227  b->create(&Popupdead_window, "", Popupdead_button_coords[gr_screen.res][i][0], Popupdead_button_coords[gr_screen.res][i][1], 30, 20, 0, 1);
230 
231  // create invisible buttons to detect mouse presses... can't use mask since button region is dynamically sized
232  int lx, w, h;
233  gr_get_string_size(&w, &h, Popupdead_button_text[i]);
235  b = &Popupdead_button_regions[i];
237  b->hide();
238  }
239 
241  Popupdead_choice = -1;
242  Popupdead_active = 1;
243 }
244 
245 // maybe play a sound when key up/down is pressed to switch default choice
247 {
248  int i, mouse_over=0;
249  UI_BUTTON *br, *b;
250 
251  // only play if mouse not currently highlighting a choice
252  for ( i = 0; i < Popupdead_num_choices; i++ ) {
253  br = &Popupdead_button_regions[i];
254  b = &Popupdead_buttons[i];
255  if ( br->button_down() ) {
256  mouse_over=1;
257  break;
258  }
259 
260  if ( br->button_hilighted() && !b->button_down() ) {
261  mouse_over=1;
262  break;
263  }
264 
265  if ( b->button_hilighted() ) {
266  mouse_over=1;
267  }
268  }
269 
270  if (!mouse_over) {
272  }
273 }
274 
275 // do any key processing here
276 // exit: -1 => nothing was done
277 // >=0 => a choice was selected
279 {
280  int masked_k;
281 
282  if ( k <= 0 ) {
283  return -1;
284  }
285 
286  switch(k) {
287 
288  case KEY_ENTER:
289  return Popupdead_default_choice; // select the current default choice
290  break;
291 
292  case KEY_ESC:
293  if (Popupdead_skip_active) {
294  return 0; // 0 mimics a "do not skip"
295  } else {
296  return 1; // do nothing here for now - 1 mimics a "return to flight deck"
297  }
298  break;
299 
300  case KEY_DOWN:
301  case KEY_PAD2:
302  case KEY_TAB:
307  }
308  break;
309 
310  case KEY_UP:
311  case KEY_PAD8:
312  case KEY_SHIFTED+KEY_TAB:
315  if ( Popupdead_default_choice < 0 ) {
317  }
318  break;
319 
320  case KEY_PAUSE:
322  break;
323 
324  default:
325  break;
326  } // end switch
327 
328  // read the dead key set
329  masked_k = k & ~KEY_CTRLED; // take out CTRL modifier only
331  button_info_do(&Player->bi); // call functions based on status of button_info bit vectors
332 
333  return -1;
334 }
335 
336 
337 // see if any popup buttons have been pressed
338 // exit: -1 => no buttons pressed
339 // >=0 => button index that was pressed
341 {
342  int i;
343  UI_BUTTON *b;
344 
345  for ( i = 0; i < Popupdead_num_choices; i++ ) {
346  b = &Popupdead_button_regions[i];
347  if ( b->pressed() ) {
348  return i;
349  }
350 
351  b = &Popupdead_buttons[i];
352  if ( b->pressed() ) {
353  return i;
354  }
355  }
356 
357  return -1;
358 }
359 
360 // See if any of the button should change appearance based on mouse position
362 {
363  int i,mouse_is_highlighting=0;
364  UI_BUTTON *br, *b;
365 
366  for ( i = 0; i < Popupdead_num_choices; i++ ) {
367  br = &Popupdead_button_regions[i];
368  b = &Popupdead_buttons[i];
369  if ( br->button_down() ) {
370  b->draw_forced(2);
371  mouse_is_highlighting=1;
372  continue;
373  }
374 
375  if ( (b->button_hilighted()) || (br->button_hilighted() && !b->button_down()) ) {
377  mouse_is_highlighting=1;
378  b->draw_forced(1);
379  }
380  }
381 
382  // Only if mouse is not highlighting an option, let the default choice be drawn highlighted
383  if ( (!mouse_is_highlighting) && (Popupdead_num_choices>1) ) {
384  for ( i = 0; i < Popupdead_num_choices; i++ ) {
385  b = &Popupdead_buttons[i];
386  // highlight the default choice
387  if ( i == Popupdead_default_choice ) {
388  b->draw_forced(1);
389  }
390  }
391  }
392 }
393 
394 // Draw the button text nicely formatted in the popup
396 {
397  int w,h,i,sx,sy;
398 
400 
401  for ( i=0; i < Popupdead_num_choices; i++ ) {
402  gr_get_string_size(&w, &h, Popupdead_button_text[i]);
405  gr_string(sx, sy, Popupdead_button_text[i], GR_RESIZE_MENU);
406  }
407 }
408 
409 // Called once per frame to run the dead popup
410 int popupdead_do_frame(float frametime)
411 {
412  int k, choice;
413 
414  if ( !Popupdead_active ) {
415  return -1;
416  }
417 
418  // maybe show skip mission popup
420  int popup_choice = popup(0, 3, XSTR("Do Not Skip This Mission", 1473),
421  XSTR("Advance To The Next Mission", 1474),
422  XSTR("Don't Show Me This Again", 1475),
423  XSTR("You have failed this mission five times. If you like, you may advance to the next mission.", 1472) );
424  switch (popup_choice) {
425  case 0:
426  // stay on this mission, so proceed to normal death popup
427  // in other words, do nothing.
428  break;
429  case 1:
430  // skip this mission
431  Popupdead_active = 0;
434  return -1;
435  case 2:
436  // don't show this again
437  Player->show_skip_popup = 0;
438  break;
439  }
440 
442  }
443 
444 
445  k = Popupdead_window.process();
446 
447  choice = popupdead_process_keys(k);
448  if ( choice >= 0 ) {
449  // do something different for single/multiplayer
450  if ( Game_mode & GM_NORMAL ) {
451  Popupdead_choice=choice;
452  } else {
453  Assert( Popupdead_multi_type != -1 );
454  switch ( Popupdead_multi_type ) {
455 
456  case POPUPDEAD_OBS_ONLY:
457  case POPUPDEAD_OBS_QUIT:
459  if ( (Popupdead_multi_type == POPUPDEAD_OBS_QUIT) && (choice == 1) )
461  break;
462 
466  if ( (Popupdead_multi_type == POPUPDEAD_RESPAWN_QUIT) && (choice == 1) )
468  break;
469 
470  default:
471  Int3();
472  break;
473  }
474  }
475  }
476 
477  choice = popupdead_check_buttons();
478  if ( choice >= 0 ) {
479  // do something different for single/multiplayer
480  if ( Game_mode & GM_NORMAL ) {
481  Popupdead_choice=choice;
482  } else {
483  Assert( Popupdead_multi_type != -1 );
484  switch ( Popupdead_multi_type ) {
485 
486  case POPUPDEAD_OBS_ONLY:
487  case POPUPDEAD_OBS_QUIT:
489  if ( (Popupdead_multi_type == POPUPDEAD_OBS_QUIT) && (choice == 1) )
491  break;
492 
496  if ( (Popupdead_multi_type == POPUPDEAD_RESPAWN_QUIT) && (choice == 1) )
498  break;
499 
500  default:
501  Int3();
502  break;
503  }
504  }
505  }
506 
507  Popupdead_window.draw();
510 
511  // maybe force the player to respawn if they've taken too long to choose
512  if (( Game_mode & GM_MULTIPLAYER ) && (The_mission.max_respawn_delay >= 0) && (timestamp_elapsed(Popupdead_timer)) && (choice < 0)) {
515  }
516  }
517 
518  return Popupdead_choice;
519 }
520 
521 // Close down the dead popup
523 {
524  if ( !Popupdead_active ) {
525  return;
526  }
527 
529  Popupdead_window.destroy();
530  game_flush();
531 
532  Popupdead_active = 0;
535 }
536 
537 // Is there a dead popup active?
539 {
540  return Popupdead_active;
541 }
void game_flush()
Definition: fredstubs.cpp:83
int Popupdead_timer
Definition: popupdead.cpp:125
void set_highlight_action(void(*_user_function)(void))
Definition: button.cpp:375
int timestamp(int delta_ms)
Definition: timer.cpp:226
int i
Definition: multi_pxo.cpp:466
#define POPUPDEAD_NUM_CHOICES_MAX
Definition: popupdead.cpp:18
int button_hilighted()
Definition: button.cpp:387
int Popupdead_region_coords[GR_NUM_RESOLUTIONS][POPUPDEAD_NUM_CHOICES_MAX][4]
Definition: popupdead.cpp:40
#define KEY_DOWN
Definition: key.h:180
#define POPUPDEAD_OBS_QUIT
Definition: popupdead.cpp:113
int Game_mode
Definition: systemvars.cpp:24
GLfloat GLfloat GLfloat GLfloat h
Definition: Glext.h:7280
int popupdead_process_keys(int k)
Definition: popupdead.cpp:278
#define GR_RESIZE_MENU
Definition: 2d.h:684
net_player * Net_player
Definition: multi.cpp:94
void popupdead_start()
Definition: popupdead.cpp:129
#define POPUPDEAD_DO_RESPAWN
Definition: popupdead.h:16
#define KEY_PAD8
Definition: key.h:164
void set_foreground_bmap(char *fname)
Definition: window.cpp:127
Assert(pm!=NULL)
#define GR_NUM_RESOLUTIONS
Definition: 2d.h:651
__inline void gr_string(int x, int y, const char *string, int resize_mode=GR_RESIZE_FULL)
Definition: 2d.h:769
int res
Definition: 2d.h:370
char * Popupdead_background_filename[GR_NUM_RESOLUTIONS]
Definition: popupdead.cpp:72
int Dead_key_set_size
Definition: keycontrol.cpp:475
int max_respawn_delay
Definition: missionparse.h:142
int Popupdead_skip_message_y[GR_NUM_RESOLUTIONS]
Definition: popupdead.cpp:103
virtual void hide(int n)
Definition: gadget.cpp:207
void gr_set_color_fast(color *dst)
Definition: 2d.cpp:1197
int popupdead_check_buttons()
Definition: popupdead.cpp:340
void popupdead_play_default_change_sound()
Definition: popupdead.cpp:246
Definition: ui.h:195
int flags
Definition: multi.h:463
#define Int3()
Definition: pstypes.h:292
#define PLAYER_MISSION_FAILURE_LIMIT
Definition: player.h:77
void mission_campaign_skip_to_next(int start_game)
void draw_forced(int frame_num)
Definition: button.cpp:104
void destroy()
Definition: window.cpp:189
int multi_num_players()
Definition: multiutil.cpp:1799
int Popupdead_multi_type
Definition: popupdead.cpp:121
int set_bmaps(char *ani_filename, int nframes=3, int start_frame=1)
Definition: gadget.cpp:71
#define POPUPDEAD_DO_OBSERVER
Definition: popupdead.h:17
UI_BUTTON Popupdead_buttons[POPUPDEAD_NUM_CHOICES_MAX]
Definition: popupdead.cpp:37
#define NETINFO_FLAG_AM_MASTER
Definition: multi.h:599
int Popupdead_default_choice
Definition: popupdead.cpp:117
#define POPUPDEAD_NUM_CHOICES_RA
Definition: popupdead.cpp:15
#define POPUPDEAD_RESPAWN_QUIT
Definition: popupdead.cpp:115
#define GM_MULTIPLAYER
Definition: systemvars.h:18
#define POPUPDEAD_DO_MAIN_HALL
Definition: popupdead.h:18
#define MISSION_FLAG_RED_ALERT
Definition: missionparse.h:84
int pressed()
Definition: button.cpp:325
#define KEY_SHIFTED
Definition: key.h:62
void process_set_of_keys(int key, int count, int *list)
#define w(p)
Definition: modelsinc.h:68
#define KEY_ENTER
Definition: key.h:125
int Dead_key_set[]
Definition: keycontrol.cpp:336
int Popupdead_skip_active
Definition: popupdead.cpp:122
#define KEY_PAUSE
Definition: key.h:185
#define POPUPDEAD_NUM_CHOICES_SKIP
Definition: popupdead.cpp:16
#define NETINFO_FLAG_TEAM_CAPTAIN
Definition: multi.h:612
int failures_this_session
Definition: player.h:202
ubyte show_skip_popup
Definition: player.h:203
int Popupdead_background_coords[GR_NUM_RESOLUTIONS][2]
Definition: popupdead.cpp:77
UI_BUTTON Popupdead_button_regions[POPUPDEAD_NUM_CHOICES_MAX]
Definition: popupdead.cpp:38
const char * XSTR(const char *str, int index)
Definition: localize.cpp:851
#define NETINFO_FLAG_LIMBO
Definition: multi.h:607
user_click (mouse selects a control)
Definition: gamesnd.h:305
void popupdead_force_draw_buttons()
Definition: popupdead.cpp:361
popup dialog box goes away
Definition: gamesnd.h:316
void button_info_do(button_info *bi)
void game_process_pause_key()
GLboolean GLboolean GLboolean b
Definition: Glext.h:5781
#define POPUPDEAD_RESPAWN_ONLY
Definition: popupdead.cpp:114
void popupdead_close()
Definition: popupdead.cpp:522
int Cmdline_mpnoreturn
Definition: cmdline.cpp:409
void create(UI_WINDOW *wnd, char *_text, int _x, int _y, int _w, int _h, int do_repeat=0, int ignore_focus=0)
Definition: button.cpp:26
#define KEY_ESC
Definition: key.h:124
#define POPUPDEAD_NUM_CHOICES
Definition: popupdead.cpp:14
int button_down()
Definition: button.cpp:363
#define POPUPDEAD_OBS_ONLY
Definition: popupdead.cpp:112
int Popupdead_skip_already_shown
Definition: popupdead.cpp:123
void create(int _x, int _y, int _w, int _h, int _flags, int _f_id=-1)
Definition: window.cpp:140
player * Player
Definition: ui.h:584
screen gr_screen
Definition: 2d.cpp:46
void gr_get_string_size(int *w, int *h, const char *text, int len=9999)
Definition: font.cpp:196
int Popupdead_choice
Definition: popupdead.cpp:119
void common_play_highlight_sound()
Definition: gamesnd.cpp:1151
void popupdead_draw_button_text()
Definition: popupdead.cpp:395
int Popupdead_button_coords[GR_NUM_RESOLUTIONS][POPUPDEAD_NUM_CHOICES_MAX][2]
Definition: popupdead.cpp:56
#define timestamp_elapsed(stamp)
Definition: timer.h:102
#define KEY_CTRLED
Definition: key.h:64
#define KEY_TAB
Definition: key.h:127
int Popupdead_active
Definition: popupdead.cpp:118
#define KEY_UP
Definition: key.h:179
void HUD_printf(const char *format,...)
Definition: hudmessage.cpp:527
#define GM_NORMAL
Definition: systemvars.h:19
color Color_bright_blue
Definition: alphacolors.cpp:31
void gamesnd_play_iface(int n)
Definition: gamesnd.cpp:260
mission The_mission
#define KEY_PAD2
Definition: key.h:158
void draw()
Definition: window.cpp:220
int Popupdead_num_choices
Definition: popupdead.cpp:120
int process(int key_in=-1, int process_mouse=1)
Definition: window.cpp:401
void gameseq_post_event(int event)
#define GM_CAMPAIGN_MODE
Definition: systemvars.h:29
button_info bi
Definition: player.h:125
int popupdead_do_frame(float frametime)
Definition: popupdead.cpp:410
int popupdead_is_active()
Definition: popupdead.cpp:538
UI_WINDOW Popupdead_window
Definition: popupdead.cpp:36
char * Popupdead_button_filenames[GR_NUM_RESOLUTIONS][POPUPDEAD_NUM_CHOICES_MAX]
Definition: popupdead.cpp:87