CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

GOPTIONS.CPP (18509B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 
     16 /* $Header:   F:\projects\c&c\vcs\code\goptions.cpv   2.17   16 Oct 1995 16:50:26   JOE_BOSTIC  $ */
     17 /***********************************************************************************************
     18  ***             C O N F I D E N T I A L  ---  W E S T W O O D   S T U D I O S               ***
     19  ***********************************************************************************************
     20  *                                                                                             *
     21  *                 Project Name : Command & Conquer                                            *
     22  *                                                                                             *
     23  *                    File Name : OPTIONS.CPP                                                  *
     24  *                                                                                             *
     25  *                   Programmer : Joe L. Bostic                                                *
     26  *                                                                                             *
     27  *                   Start Date : June 8, 1994                                                 *
     28  *                                                                                             *
     29  *                  Last Update : July 27, 1995 [JLB]                                          *
     30  *                                                                                             *
     31  *---------------------------------------------------------------------------------------------*
     32  * Functions:                                                                                  *
     33  *   OptionsClass::Process -- Handles all the options graphic interface.                       *
     34  *   Draw_Caption -- Draws a caption on a dialog box.                                          *
     35  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     36 
     37 #include "function.h"
     38 
     39 #include "goptions.h"
     40 #include "loaddlg.h"
     41 #include "sounddlg.h"
     42 #include "visudlg.h"
     43 #include "gamedlg.h"
     44 #include "textbtn.h"
     45 #include "confdlg.h"
     46 #include "descdlg.h"
     47 
     48 void GameOptionsClass::Adjust_Variables_For_Resolution(void)
     49 {
     50 	int factor = (SeenBuff.Get_Width() == 320) ? 1 : 2;
     51 
     52 	OptionWidth		=	(216+8) * factor;
     53 	OptionHeight	=	100 * factor;
     54 	OptionX			=	((SeenBuff.Get_Width() - OptionWidth) / 2);
     55 	OptionY			=	((SeenBuff.Get_Height() - OptionHeight) / 2);
     56 	ButtonWidth		=	130 * factor;
     57 	OButtonHeight	=	9 * factor;
     58 	CaptionYPos		=	5 * factor;
     59 	ButtonY			=	21 * factor;
     60 	Border1Len		=	72 * factor;
     61 	Border2Len		=	16 * factor;
     62 	ButtonResumeY	=	(OptionHeight - (15 * factor));
     63 }
     64 /***********************************************************************************************
     65  * OptionsClass::Process -- Handles all the options graphic interface.                         *
     66  *                                                                                             *
     67  *    This routine is the main control for the visual representation of the options            *
     68  *    screen. It handles the visual overlay and the player input.                              *
     69  *                                                                                             *
     70  * INPUT:      none                                                                            *
     71  *                                                                                             *
     72  * OUTPUT:     none                                                                            *
     73  *                                                                                             *
     74  * WARNINGS:      none                                                                         *
     75  *                                                                                             *
     76  * HISTORY:     12/31/1994 MML : Created.                                                      *
     77  *   06/23/1995 JLB : Handles restating the mission objective.                                 *
     78  *   07/27/1995 JLB : Adjusts menu for multiplay mode.                                         *
     79  *=============================================================================================*/
     80 void GameOptionsClass::Process(void)
     81 {
     82 	static struct {
     83 		int ID;				// Button ID to use.
     84 		int Text;			// Text number to use for this button.
     85 		bool Multiplay;	// Allowed in multiplayer version?
     86 	} _constants[] = {
     87 		{BUTTON_LOAD,  	TXT_LOAD_MISSION,    	false},
     88 		{BUTTON_SAVE,  	TXT_SAVE_MISSION,    	false},
     89 		{BUTTON_DELETE,	TXT_DELETE_MISSION,  	true},
     90 		{BUTTON_GAME,  	TXT_GAME_CONTROLS,   	true},
     91 		{BUTTON_QUIT,  	TXT_QUIT_MISSION,    	true},
     92 		{BUTTON_RESUME,	TXT_RESUME_MISSION,  	true},
     93 		{BUTTON_RESTATE,	TXT_RESTATE_MISSION,		false},
     94 	};
     95 
     96 	/*
     97 	**	Variables.
     98 	*/
     99 	TextButtonClass * buttons = 0;
    100 	int selection;
    101 	bool pressed;
    102 	int curbutton = 6;
    103 	int y;
    104 	TextButtonClass *buttonsel[sizeof(_constants)/sizeof(_constants[0])];
    105 
    106 	Set_Logic_Page(SeenBuff);
    107 
    108 	/*
    109 	**	Build the button list for all of the buttons for this dialog.
    110 	*/
    111 	int maxwidth = 0;
    112 	int resfactor = (SeenBuff.Get_Width() == 320) ? 1 : 2;
    113 
    114 	for (int index = 0; index < sizeof(_constants)/sizeof(_constants[0]); index++ ) {
    115 		int text = _constants[index].Text;
    116 		buttonsel[index] = NULL;
    117 
    118 		if (GameToPlay != GAME_NORMAL && !_constants[index].Multiplay) {
    119 			buttonsel[index] = 0;
    120 			continue;
    121 		}
    122 
    123 		if (GameToPlay != GAME_NORMAL && text == TXT_DELETE_MISSION) {
    124 			text = TXT_RESIGN;
    125 		}
    126 
    127 		if (index < 5) {
    128 			y = (SeenBuff.Get_Height() - OptionHeight)/2 + ButtonY + ((OButtonHeight+2) * index);
    129 		} else {
    130 			y = OptionY + ButtonResumeY;
    131 		}
    132 
    133 		TextButtonClass * g = new TextButtonClass(_constants[index].ID,
    134 			text, TPF_6PT_GRAD|TPF_NOSHADOW, 0, y);
    135 
    136 		if (g->Width > maxwidth) {
    137 			maxwidth = g->Width;
    138 		}
    139 		if (!buttons) {
    140 			buttons = g;
    141 		} else {
    142 			g->Add_Tail(*buttons);
    143 		}
    144 
    145 		buttonsel[index] = g;
    146 	}
    147 
    148 	buttonsel[curbutton-1]->Turn_On();
    149 
    150 	/*
    151 	**	Force all button lengths to match the maximum length of the widest button.
    152 	*/
    153 	GadgetClass * g = buttons;
    154 	while (g) {
    155 		g->Width = MAX(maxwidth, 90 * resfactor);
    156 		g->X = OptionX+(OptionWidth-g->Width)/2;
    157 		g = g->Get_Next();
    158 	}
    159 #ifdef FRENCH
    160 	buttonsel[BUTTON_RESUME-1]->Width = 104 *resfactor;
    161 #else
    162 	buttonsel[BUTTON_RESUME-1]->Width = 90 *resfactor;
    163 #endif
    164 	buttonsel[BUTTON_RESUME-1]->X = OptionX+(5 * resfactor);
    165 
    166 	if (GameToPlay == GAME_NORMAL) {
    167 		buttonsel[BUTTON_RESTATE-1]->Width = 90 * resfactor;
    168 		buttonsel[BUTTON_RESTATE-1]->X = OptionX+OptionWidth-(buttonsel[BUTTON_RESTATE-1]->Width+(5 * resfactor));
    169 	}
    170 
    171 	/*
    172 	**	This causes left mouse button clicking within the confines of the dialog to
    173 	**	be ignored if it wasn't recognized by any other button or slider.
    174 	*/
    175 	(new GadgetClass(OptionX, OptionY, OptionWidth, OptionHeight, GadgetClass::LEFTPRESS))->Add_Tail(*buttons);
    176 
    177 	/*
    178 	**	This cause a right click anywhere or a left click outside the dialog region
    179 	**	to be equivalent to clicking on the return to game button.
    180 	*/
    181 	(new ControlClass(BUTTON_RESUME, 0, 0, SeenBuff.Get_Width(), SeenBuff.Get_Height(), GadgetClass::LEFTPRESS|GadgetClass::RIGHTPRESS))->Add_Tail(*buttons);
    182 
    183 	Keyboard::Clear();
    184 
    185 	Fancy_Text_Print(TXT_NONE, 0, 0, CC_GREEN, TBLACK, TPF_CENTER|TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW);
    186 
    187 	/*
    188 	**	Main Processing Loop.
    189 	*/
    190 	bool display = true;
    191 	bool process = true;
    192 	pressed = false;
    193 	while (process) {
    194 
    195 		/*
    196 		** If we have just received input focus again after running in the background then
    197 		** we need to redraw.
    198 		*/
    199 		if (AllSurfaces.SurfacesRestored){
    200 			AllSurfaces.SurfacesRestored=FALSE;
    201 			display=TRUE;
    202 		}
    203 
    204 		/*
    205 		**	Invoke game callback.
    206 		*/
    207 		if (GameToPlay == GAME_NORMAL) {
    208 			Call_Back();
    209 		} else {
    210 			if (Main_Loop()) {
    211 				process = false;
    212 			}
    213 		}
    214 
    215 		/*
    216 		**	Refresh display if needed.
    217 		*/
    218 		if (display) {
    219 
    220 			/*
    221 			**	Redraw the map.
    222 			*/
    223 			HiddenPage.Clear();
    224 			Map.Flag_To_Redraw(true);
    225 			Map.Render();
    226 
    227 			/*
    228 			**	Reset up the window.  Window x-coords are in bytes not pixels.
    229 			*/
    230 			Set_Window(WINDOW_EDITOR, OptionX, OptionY, OptionWidth, OptionHeight);
    231 			Hide_Mouse();
    232 
    233 			/*
    234 			**	Draw the background.
    235 			*/
    236 			Window_Box (WINDOW_EDITOR, BOXSTYLE_GREEN_BORDER); // has border, raised up
    237 
    238 			/*
    239 			**	Draw the arrows border if requested.
    240 			*/
    241 			Draw_Caption(TXT_OPTIONS, OptionX, OptionY, OptionWidth);
    242 
    243 			/*
    244 			**	Display the version number at the bottom of the dialog box.
    245 			*/
    246 #ifdef DEMO
    247 			Version_Number();
    248 			Fancy_Text_Print("DEMO%s",
    249 					((WindowList[WINDOW_EDITOR][WINDOWX]+WindowList[WINDOW_EDITOR][WINDOWWIDTH])<<3)-3*resfactor,
    250 					WindowList[WINDOW_EDITOR][WINDOWY]+WindowList[WINDOW_EDITOR][WINDOWHEIGHT]-((GameToPlay == GAME_NORMAL) ? (32*resfactor) : (24*resfactor)),
    251 					DKGREY, TBLACK,
    252 					TPF_6POINT|TPF_NOSHADOW|TPF_RIGHT,
    253 					ScenarioName,
    254 					VersionText);
    255 #else
    256 			Fancy_Text_Print("%s\rV.%d%s",
    257 					((WindowList[WINDOW_EDITOR][WINDOWX]+WindowList[WINDOW_EDITOR][WINDOWWIDTH])<<3)-3*resfactor,
    258 					WindowList[WINDOW_EDITOR][WINDOWY]+WindowList[WINDOW_EDITOR][WINDOWHEIGHT]-((GameToPlay == GAME_NORMAL) ? (32*resfactor) : (24*resfactor)),
    259 					DKGREY, TBLACK,
    260 					TPF_6POINT|TPF_NOSHADOW|TPF_RIGHT,
    261 					ScenarioName,
    262 					Version_Number(),
    263 					VersionText);
    264 #endif
    265 
    266 			buttons->Draw_All();
    267 			TabClass::Hilite_Tab(0);
    268 			Show_Mouse();
    269 			display = false;
    270 		}
    271 
    272 		/*
    273 		**	Get user input.
    274 		*/
    275 		KeyNumType input = buttons->Input();
    276 
    277 		/*
    278 		**	Process Input.
    279 		*/
    280 		switch (input) {
    281 			case (BUTTON_RESTATE | KN_BUTTON):
    282 				selection = BUTTON_RESTATE;
    283 				pressed = true;
    284 				break;
    285 
    286 			case (BUTTON_LOAD | KN_BUTTON):
    287 				selection = BUTTON_LOAD;
    288 				pressed = true;
    289 				break;
    290 
    291 			case (BUTTON_SAVE | KN_BUTTON):
    292 				selection = BUTTON_SAVE;
    293 				pressed = true;
    294 				break;
    295 
    296 			case (BUTTON_DELETE | KN_BUTTON):
    297 				selection = BUTTON_DELETE;
    298 				pressed = true;
    299 				break;
    300 
    301 			case (BUTTON_QUIT | KN_BUTTON):
    302 				selection = BUTTON_QUIT;
    303 				pressed = true;
    304 				break;
    305 
    306 			case (BUTTON_GAME | KN_BUTTON):
    307 				selection = BUTTON_GAME;
    308 				pressed = true;
    309 				break;
    310 
    311 			case (KN_ESC):
    312 			case (BUTTON_RESUME | KN_BUTTON):
    313 				selection = BUTTON_RESUME;
    314 				pressed = true;
    315 				break;
    316 
    317 			case (KN_UP):
    318 				buttonsel[curbutton-1]->Turn_Off();
    319 				buttonsel[curbutton-1]->Flag_To_Redraw();
    320 				curbutton--;
    321 				if (GameToPlay == GAME_NORMAL) {
    322 					if (curbutton < BUTTON_LOAD) {
    323 						curbutton = (BUTTON_COUNT - 1);
    324 					}
    325 				} else {
    326 					if (curbutton < BUTTON_DELETE) {
    327 						curbutton = BUTTON_RESUME;
    328 //						curbutton = (BUTTON_COUNT-1);
    329 					}
    330 				}
    331 				buttonsel[curbutton-1]->Turn_On();
    332 				buttonsel[curbutton-1]->Flag_To_Redraw();
    333 				break;
    334 
    335 			case (KN_DOWN):
    336 				buttonsel[curbutton-1]->Turn_Off();
    337 				buttonsel[curbutton-1]->Flag_To_Redraw();
    338 				curbutton++;
    339 				if (GameToPlay == GAME_NORMAL) {
    340 					if (curbutton >= BUTTON_COUNT) {
    341 						curbutton = BUTTON_LOAD;
    342 					}
    343 				} else {
    344 					if (curbutton > BUTTON_RESUME) {
    345 						curbutton = BUTTON_DELETE;
    346 					}
    347 				}
    348 				buttonsel[curbutton-1]->Turn_On();
    349 				buttonsel[curbutton-1]->Flag_To_Redraw();
    350 				break;
    351 
    352 			case (KN_RETURN):
    353 				buttonsel[curbutton-1]->IsPressed = true;
    354 				buttonsel[curbutton-1]->Draw_Me(true);
    355 				selection = curbutton;
    356 				pressed = true;
    357 				break;
    358 
    359 			default:
    360 				break;
    361 		}
    362 
    363 		if (pressed) {
    364 			buttonsel[curbutton-1]->Turn_Off();
    365 			buttonsel[curbutton-1]->Flag_To_Redraw();
    366 			curbutton = selection;
    367 			buttonsel[curbutton-1]->Turn_On();
    368 			buttonsel[curbutton-1]->Flag_To_Redraw();
    369 
    370 			switch (selection) {
    371 				case BUTTON_RESTATE:
    372 					display = true;
    373 #ifdef JAPANESE
    374 					if (!Restate_Mission(ScenarioName, TXT_VIDEO, TXT_TAB_BUTTON_CONTROLS)) {
    375 #else
    376 					if (!Restate_Mission(ScenarioName, TXT_VIDEO, TXT_OPTIONS)) {
    377 #endif
    378 						BreakoutAllowed = true;
    379 						char buffer[25];
    380 						sprintf(buffer, "%s.VQA", BriefMovie);
    381 						if (CCFileClass(buffer).Is_Available()) {
    382 							Play_Movie(BriefMovie);
    383 						} else {
    384 							Play_Movie(ActionMovie);
    385 						}
    386 						//BreakoutAllowed = false;
    387 						memset(BlackPalette, 0x01, 768);
    388 						Set_Palette(BlackPalette);
    389 						memset(BlackPalette, 0x00, 768);
    390 						Set_Palette(BlackPalette);
    391 						Map.Flag_To_Redraw(true);
    392 						Theme.Queue_Song(THEME_PICK_ANOTHER);
    393 						process = false;
    394 					}
    395 					break;
    396 
    397 				case (BUTTON_LOAD):
    398 					display = true;
    399 					if (LoadOptionsClass(LoadOptionsClass::LOAD).Process()) {
    400 						process = false;
    401 					}
    402 					break;
    403 
    404 				case (BUTTON_SAVE):
    405 					display = true;
    406 					LoadOptionsClass(LoadOptionsClass::SAVE).Process();
    407 					break;
    408 
    409 				case (BUTTON_DELETE):
    410 					display = true;
    411 					if (GameToPlay != GAME_NORMAL) {
    412 						if (Surrender_Dialog()) {
    413 							OutList.Add(EventClass(EventClass::DESTRUCT));
    414 						}
    415 						process = false;
    416 					} else {
    417 						LoadOptionsClass(LoadOptionsClass::WWDELETE).Process();
    418 					}
    419 					break;
    420 
    421 				case (BUTTON_QUIT):
    422 					if (GameToPlay == GAME_NORMAL) {
    423 #ifdef JAPANESE
    424 						switch (CCMessageBox().Process(TXT_CONFIRM_EXIT, TXT_YES, TXT_NO, TXT_RESTART)) {
    425 #else
    426 						switch (CCMessageBox().Process(TXT_CONFIRM_EXIT, TXT_ABORT, TXT_CANCEL, TXT_RESTART)) {
    427 #endif
    428 							case 2:
    429 								display = true;
    430 								break;
    431 
    432 							case 0:
    433 								process = false;
    434 								Queue_Exit();
    435 								break;
    436 
    437 							case 1:
    438 								PlayerRestarts = true;
    439 								process = false;
    440 								break;
    441 						}
    442 					} else {
    443 						if (ConfirmationClass().Process(TXT_CONFIRM_EXIT)) {
    444 							process = false;
    445 							Queue_Exit();
    446 						} else {
    447 							display = true;
    448 						}
    449 					}
    450 					break;
    451 
    452 				case (BUTTON_GAME):
    453 					display = true;
    454 					GameControlsClass().Process();
    455 					break;
    456 
    457 				case (BUTTON_RESUME):
    458 					//Save_Settings();
    459 					process = false;
    460 					display = true;
    461 					break;
    462 			}
    463 
    464 			pressed = false;
    465 			buttonsel[curbutton-1]->IsPressed = false;
    466 			//buttonsel[curbutton-1]->Turn_Off();
    467 			buttonsel[curbutton-1]->Turn_On();
    468 			buttonsel[curbutton-1]->Flag_To_Redraw();
    469 		}
    470 	}
    471 
    472 	/*
    473 	**	Clean up and re-enter the game.
    474 	*/
    475 	buttons->Delete_List();
    476 
    477 	/*
    478 	**	Redraw the map.
    479 	*/
    480 	Keyboard::Clear();
    481 	Call_Back();
    482 	HiddenPage.Clear();
    483 	Call_Back();
    484 	Map.Flag_To_Redraw(true);
    485 	Map.Render();
    486 }
    487 
    488 
    489 /***********************************************************************************************
    490  * Draw_Caption -- Draws a caption on a dialog box.                                            *
    491  *                                                                                             *
    492  *    This routine draws the caption text and any fancy filigree that the dialog may require.  *
    493  *                                                                                             *
    494  * INPUT:   text  -- The text of the caption. This is the text number.                         *
    495  *                                                                                             *
    496  *          x,y   -- The dialog box X and Y pixel coordinate of the upper left corner.         *
    497  *                                                                                             *
    498  *          w     -- The width of the dialog box (in pixels).                                  *
    499  *                                                                                             *
    500  * OUTPUT:  none                                                                               *
    501  *                                                                                             *
    502  * WARNINGS:   none                                                                            *
    503  *                                                                                             *
    504  * HISTORY:                                                                                    *
    505  *   06/23/1995 JLB : Created.                                                                 *
    506  *=============================================================================================*/
    507 void Draw_Caption(int text, int x, int y, int w)
    508 {
    509 	OptionControlType option = OPTION_NONE;
    510 	int factor			= (SeenBuff.Get_Width() == 320) ? 1 : 2;
    511 
    512 
    513 	/*
    514 	**	Determine the filigree to use depending on the text of the caption.
    515 	*/
    516 	switch (text) {
    517 		case TXT_GAME_CONTROLS:
    518 		case TXT_OPTIONS:
    519 			option = OPTION_CONTROLS;
    520 			break;
    521 
    522 		case TXT_LOAD_MISSION:
    523 		case TXT_SAVE_MISSION:
    524 		case TXT_DELETE_MISSION:
    525 			option = OPTION_DELETE;
    526 			break;
    527 
    528 		case TXT_NONE:
    529 		case TXT_MODEM_SERIAL:
    530 		case TXT_SELECT_MPLAYER_GAME:
    531 		case TXT_SELECT_SERIAL_GAME:
    532 			option = OPTION_DIALOG;
    533 			break;
    534 
    535 		case TXT_HOST_SERIAL_GAME:
    536 		case TXT_JOIN_SERIAL_GAME:
    537 			option = OPTION_SERIAL;
    538 			break;
    539 
    540 		case TXT_SETTINGS:
    541 		case TXT_PHONE_LIST:
    542 		case TXT_PHONE_LISTING:
    543 			option = OPTION_PHONE;
    544 			break;
    545 
    546 		case TXT_JOIN_NETWORK_GAME:
    547 			option = OPTION_JOIN_NETWORK;
    548 			break;
    549 
    550 		case TXT_NETGAME_SETUP:
    551 			option = OPTION_NETWORK;
    552 			break;
    553 
    554 		case TXT_VISUAL_CONTROLS:
    555 			option = OPTION_VISUAL;
    556 			break;
    557 
    558 		case TXT_SOUND_CONTROLS:
    559 			option = OPTION_SOUND;
    560 			break;
    561 
    562 		default:
    563 			option = OPTION_DIALOG;
    564 			break;
    565 	}
    566 
    567 	/*
    568 	**	Draw the filigree at the corners of the dialog.
    569 	*/
    570 	if (option != OPTION_NONE) {
    571 		CC_Draw_Shape(MixFileClass::Retrieve("OPTIONS.SHP"), (int)option, x+12, y+11, WINDOW_MAIN, SHAPE_CENTER);
    572 		CC_Draw_Shape(MixFileClass::Retrieve("OPTIONS.SHP"), (int)option+1, x+w-14, y+11, WINDOW_MAIN, SHAPE_CENTER);
    573 	}
    574 
    575 	/*
    576 	**	Draw the caption.
    577 	*/
    578 	if (text != TXT_NONE) {
    579 		Fancy_Text_Print(text, w/2 + x, 5*factor + y, CC_GREEN, TBLACK, TPF_CENTER|TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW);
    580 
    581 		int length = String_Pixel_Width(Text_String(text));
    582 		LogicPage->Draw_Line((x+(w/2))-(length/2), y+FontHeight+FontYSpacing + 5*factor, (x+(w/2))+(length/2), y+FontHeight+FontYSpacing + 5*factor, CC_GREEN);
    583 	}
    584 }