// // Copyright 2020 Electronic Arts Inc. // // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free // software: you can redistribute it and/or modify it under the terms of // the GNU General Public License as published by the Free Software Foundation, // either version 3 of the License, or (at your option) any later version. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed // in the hope that it will be useful, but with permitted additional restrictions // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT // distributed with this program. You should have received a copy of the // GNU General Public License along with permitted additional restrictions // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection /* $Header: /CounterStrike/SPECIAL.CPP 1 3/03/97 10:25a Joe_bostic $ */ /*********************************************************************************************** *** 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 *** *********************************************************************************************** * * * Project Name : Command & Conquer * * * * File Name : SPECIAL.CPP * * * * Programmer : Joe L. Bostic * * * * Start Date : 05/27/95 * * * * Last Update : August 20, 1996 [JLB] * * * *---------------------------------------------------------------------------------------------* * Functions: * * Fetch_Difficulty -- Fetches the difficulty setting desired. * * Fetch_Password -- Prompts for a password entry from client. * * PWEditClass::Draw_Text -- Draws password style obscured text. * * Special_Dialog -- Handles the special options dialog. * * SpecialClass::Init -- Initialize the special class of options. * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #include "function.h" #ifdef WIN32 #define OPTION_WIDTH 236*2 #define OPTION_HEIGHT 162*2 #define OPTION_X ((640 - OPTION_WIDTH) / 2) #define OPTION_Y (400 - OPTION_HEIGHT) / 2 #else #define OPTION_WIDTH 236 #define OPTION_HEIGHT 162 #define OPTION_X ((320 - OPTION_WIDTH) / 2) #define OPTION_Y (200 - OPTION_HEIGHT) / 2 #endif /*********************************************************************************************** * SpecialClass::Init -- Initialize the special class of options. * * * * This initialization function is required (as opposed to using a constructor) because * * the SpecialClass is declared as part of a union. A union cannot have a member with a * * constructor. Other than this anomoly, the function serves the same purpose as a * * normal constructor. * * * * INPUT: none * * * * OUTPUT: none * * * * WARNINGS: none * * * * HISTORY: * * 08/20/1996 JLB : Created. * *=============================================================================================*/ void SpecialClass::Init(void) { IsShadowGrow = false; IsSpeedBuild = false; IsFromInstall = false; IsCaptureTheFlag = false; IsInert = false; IsThreePoint = false; IsTGrowth = true; IsTSpread = true; UseMCVDeploy = false; IsMCVDeploy = false; IsEarlyWin = false; ModernBalance = false; } /*********************************************************************************************** * Special_Dialog -- Handles the special options dialog. * * * * This dialog is used when setting the special game options. It does not appear in the * * final version of the game. * * * * INPUT: none * * * * OUTPUT: none * * * * WARNINGS: none * * * * HISTORY: * * 09/21/1995 JLB : Created. * *=============================================================================================*/ void Special_Dialog(bool simple) { simple; #if (0)//PG SpecialClass oldspecial = Special; GadgetClass * buttons = NULL; static struct { int Description; int Setting; CheckBoxClass * Button; } _options[] = { {TXT_THREE_POINT, 0, 0}, {TXT_SPEED_BUILD, 0, 0}, }; TextButtonClass ok(200, TXT_OK, TPF_BUTTON, OPTION_X+15*RESFACTOR, OPTION_Y+OPTION_HEIGHT-15*RESFACTOR); TextButtonClass cancel(201, TXT_CANCEL, TPF_BUTTON, OPTION_X+OPTION_WIDTH-60*RESFACTOR, OPTION_Y+OPTION_HEIGHT-15*RESFACTOR); buttons = &ok; cancel.Add(*buttons); for (int index = 0; index < sizeof(_options)/sizeof(_options[0]); index++) { _options[index].Button = new CheckBoxClass(100+index, OPTION_X+17*RESFACTOR, OPTION_Y+20*RESFACTOR+(index*10*RESFACTOR)); if (_options[index].Button) { _options[index].Button->Add(*buttons); bool value = false; switch (_options[index].Description) { case TXT_THREE_POINT: value = Special.IsThreePoint; break; case TXT_SPEED_BUILD: value = Special.IsSpeedBuild; break; } _options[index].Setting = value; if (value) { _options[index].Button->Turn_On(); } else { _options[index].Button->Turn_Off(); } } } Map.Override_Mouse_Shape(MOUSE_NORMAL); Set_Logic_Page(SeenBuff); bool recalc = true; bool display = true; bool process = true; while (process) { if (Session.Type == GAME_NORMAL) { Call_Back(); } else { if (Main_Loop()) { process = false; } } if (display) { display = false; Hide_Mouse(); Dialog_Box(OPTION_X, OPTION_Y, OPTION_WIDTH, OPTION_HEIGHT); Draw_Caption(TXT_SPECIAL_OPTIONS, OPTION_X, OPTION_Y, OPTION_WIDTH); for (index = 0; index < sizeof(_options)/sizeof(_options[0]); index++) { Fancy_Text_Print(_options[index].Description, _options[index].Button->X+10*RESFACTOR, _options[index].Button->Y, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW); } buttons->Draw_All(); Show_Mouse(); } KeyNumType input = buttons->Input(); switch (input) { case KN_ESC: case 200|KN_BUTTON: process = false; for (index = 0; index < sizeof(_options)/sizeof(_options[0]); index++) { bool setting = _options[index].Setting; switch (_options[index].Description) { case TXT_THREE_POINT: oldspecial.IsThreePoint = setting; break; case TXT_SPEED_BUILD: oldspecial.IsSpeedBuild = setting; break; } } if (!simple) { OutList.Add(EventClass(oldspecial)); } else { Special = oldspecial; } break; case 201|KN_BUTTON: process = false; break; case KN_NONE: break; default: index = (input & ~KN_BUTTON) - 100; if ((unsigned)index < sizeof(_options)/sizeof(_options[0])) { _options[index].Setting = _options[index].Button->IsOn; } break; } } if (!simple) { Map.Revert_Mouse_Shape(); HidPage.Clear(); Map.Flag_To_Redraw(true); Map.Render(); } #endif } /* ** Derived from the edit class, this class allows entry of passwords style text ** as an edit box. This style is characterized by "*" being displayed for every ** real character entered. */ class PWEditClass : public EditClass { public: PWEditClass(int id, char * text, int max_len, TextPrintType flags, int x, int y, int w=-1, int h=-1) : EditClass(id, text, max_len, flags, x, y, w, h, ALPHANUMERIC) {}; protected: virtual void Draw_Text(char const * text); }; /*********************************************************************************************** * PWEditClass::Draw_Text -- Draws password style obscured text. * * * * This routine is used by the password style edit box in order to display the entered * * text. The text will be displayed as asterisks instead of the actual characters the * * edit box may contain. This is necessary to obscure the password entry from glancing * * eyes. * * * * INPUT: text -- Pointer to the text that is to be rendered. * * * * OUTPUT: none * * * * WARNINGS: none * * * * HISTORY: * * 10/27/1995 JLB : Created. * *=============================================================================================*/ void PWEditClass::Draw_Text(char const * text) { char buffer[80]; memset(buffer, '\0', sizeof(buffer)); memset(buffer, '*', strlen(text)); if (FontPtr == GradFont6Ptr) { TextPrintType flags; if (Has_Focus()) { flags = TPF_BRIGHT_COLOR; } else { flags = (TextPrintType)0; } Conquer_Clip_Text_Print(buffer, X+1, Y+1, Color, TBLACK, TextFlags | flags, Width-2); if (Has_Focus() && (int)strlen(buffer) < MaxLength) { Conquer_Clip_Text_Print( "_", X+1+String_Pixel_Width(buffer), Y+1, Color, TBLACK, TextFlags | flags); } } else { Conquer_Clip_Text_Print(buffer, X+1, Y+1, Has_Focus() ? &ColorRemaps[PCOLOR_DIALOG_BLUE] : &ColorRemaps[PCOLOR_GREY], TBLACK, TextFlags, Width-2); if (Has_Focus() && (int)strlen(buffer) < MaxLength) { Conquer_Clip_Text_Print("_", X+1+String_Pixel_Width(buffer), Y+1, &ColorRemaps[PCOLOR_DIALOG_BLUE], TBLACK, TextFlags); } } } /*********************************************************************************************** * Fetch_Password -- Prompts for a password entry from client. * * * * This routine will prompt for and return a password entry from the player. * * * * INPUT: caption -- The caption to use for the top of the prompt dialog. * * * * message -- The body of the message to display in the dialog. * * * * btext -- The button text to use to finish the dialog box entry. * * * * OUTPUT: Returns with a pointer to the password text entered. This pointer is valid * * only until the next time that this routine is called. * * * * WARNINGS: none * * * * HISTORY: * * 10/27/1995 JLB : Created. * *=============================================================================================*/ #define BUFFSIZE (511) char const * Fetch_Password(int caption, int message, int btext) { char buffer[BUFFSIZE]; bool process; // loop while true KeyNumType input; // user input bool pressed; int curbutton; TextButtonClass ok; if (btext == TXT_NONE) btext = TXT_OK; //PG_TO_FIX //Fancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_6PT_GRAD|TPF_NOSHADOW); /* ** Examine the optional button parameters. Fetch the width and starting ** characters for each. */ int bwidth, bheight; // button width and height /* ** Build the button list. */ bheight = FontHeight + FontYSpacing + 2*RESFACTOR; bwidth = max((String_Pixel_Width(Text_String(btext)) + 8*RESFACTOR), 30*RESFACTOR); /* ** Determine the dimensions of the text to be used for the dialog box. ** These dimensions will control how the dialog box looks. */ buffer[BUFFSIZE-1] = 0; strncpy(buffer, Text_String(message), BUFFSIZE-1); //PG_TO_FIX //Fancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_6PT_GRAD|TPF_NOSHADOW); int width; int height; Format_Window_String(buffer, 255, width, height); width = max(width, 50*RESFACTOR); width += 40*RESFACTOR; height += (60+25)*RESFACTOR; int x = (SeenBuff.Get_Width() - width) / 2; int y = (SeenBuff.Get_Height() - height) / 2; /* ** Create the "ok" and password edit buttons. */ TextButtonClass button1(1, btext, TPF_BUTTON, x + ((width - bwidth) >> 1), y + height - (bheight + 5*RESFACTOR), bwidth); static char pbuffer[45]; memset(pbuffer, '\0', sizeof(pbuffer)); int editx = x+26*RESFACTOR; int editwidth = (SeenBuff.Get_Width()/2 - editx) * 2; PWEditClass button2(2, &pbuffer[0], sizeof(pbuffer), TPF_6PT_GRAD|TPF_NOSHADOW, editx, (y+height)-35*RESFACTOR, editwidth, 10*RESFACTOR); TextButtonClass * buttonlist = 0; curbutton = 0; /* ** Add and initialize the buttons to the button list. */ buttonlist = &button1; button2.Add(*buttonlist); /* ** Draw the background of the dialog. */ Hide_Mouse(); Set_Logic_Page(SeenBuff); Dialog_Box(x, y, width, height); Draw_Caption(caption, x, y, width); /* ** Draw the body of the message box. */ Fancy_Text_Print(buffer, x + 20*RESFACTOR, y + 25*RESFACTOR, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW); /* ** Redraw the buttons. */ if (buttonlist) { buttonlist->Draw_All(); } Show_Mouse(); /* ** Main Processing Loop. */ process = true; pressed = false; bool first = true; while (process) { /* ** Invoke game callback. */ Call_Back(); #ifdef WIN32 /* ** Handle possible surface loss due to a focus switch */ if (AllSurfaces.SurfacesRestored) { AllSurfaces.SurfacesRestored=FALSE; process = false; break; } #endif //WIN32 /* ** Fetch and process input. */ input = buttonlist->Input(); if (first) { button2.Set_Focus(); button2.Flag_To_Redraw(); first = false; } switch (input) { case (1|BUTTON_FLAG): process = false; break; case (KN_ESC): case (2|BUTTON_FLAG): process = false; break; case (KN_RETURN): process = false; break; default: break; } } return(pbuffer); } /*********************************************************************************************** * Fetch_Difficulty -- Fetches the difficulty setting desired. * * * * This will display a dialog box that requests the player to specify a difficulty * * setting. * * * * INPUT: none * * * * OUTPUT: Returns with a difficulty setting of 0 for easiest and 4 for hardest. * * * * WARNINGS: none * * * * HISTORY: * * 08/13/1996 JLB : Created. * *=============================================================================================*/ #ifdef FIXIT_CSII // checked - ajw 9/28/98 int Fetch_Difficulty(bool amath) #else int Fetch_Difficulty(void) #endif { int const w = 250 * RESFACTOR; int const h = 80 * RESFACTOR; int const x = ((320 * RESFACTOR)/2) - w/2; int const y = ((200 * RESFACTOR)/2) - h/2; int const bwidth = 30 * RESFACTOR; /* ** Fill the description buffer with the description text. Break ** the text into appropriate spacing. */ char buffer[512]; strncpy(buffer, Text_String(TXT_DIFFICULTY), sizeof(buffer)-1); buffer[sizeof(buffer)-1] = '\0'; #ifdef FIXIT_CSII // checked - ajw 9/28/98 // If it's an aftermath mission, trim the sentence to get rid of the campaign stuff. if (amath) { int index=0; while (buffer[index] && buffer[index]!='.') index++; if (buffer[index]=='.') { buffer[index+1]=0; } } #endif //PG_TO_FIX //Fancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_6PT_GRAD|TPF_NOSHADOW); int width; int height; Format_Window_String(buffer, w-60*RESFACTOR, width, height); /* ** Create the OK button. */ TextButtonClass okbutton(1, TXT_OK, TPF_BUTTON, (x+w) - (bwidth+20*RESFACTOR) , (y+h) - (18*RESFACTOR), bwidth); GadgetClass * buttonlist = &okbutton; /* ** Create the slider button. */ SliderClass slider(2, x+20*RESFACTOR, y+h - 29*RESFACTOR, w - 40*RESFACTOR, 8*RESFACTOR, true); if (Rule.IsFineDifficulty) { slider.Set_Maximum(5); slider.Set_Value(2); } else { slider.Set_Maximum(3); slider.Set_Value(1); } slider.Add(*buttonlist); /* ** Main Processing Loop. */ Set_Logic_Page(SeenBuff); bool redraw = true; bool process = true; while (process) { if (redraw) { redraw = false; /* ** Draw the background of the dialog. */ Hide_Mouse(); Dialog_Box(x, y, w, h); /* ** Draw the body of the message. */ // Fancy_Text_Print(buffer, x + 20*RESFACTOR, y + 15*RESFACTOR, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW); Fancy_Text_Print(buffer, x + 20*RESFACTOR, y + 15*RESFACTOR, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_6PT_GRAD|TPF_NOSHADOW); /* ** Display the descripton of the slider range. */ Fancy_Text_Print(TXT_HARD, slider.X+slider.Width, slider.Y-9*RESFACTOR, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_RIGHT|TPF_6PT_GRAD|TPF_DROPSHADOW); Fancy_Text_Print(TXT_EASY, slider.X, slider.Y-9*RESFACTOR, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_6PT_GRAD|TPF_DROPSHADOW); Fancy_Text_Print(TXT_NORMAL, slider.X + (slider.Width/2), slider.Y-9*RESFACTOR, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_CENTER|TPF_6PT_GRAD|TPF_DROPSHADOW); /* ** Redraw the buttons. */ if (buttonlist) { buttonlist->Draw_All(); } Show_Mouse(); } /* ** Invoke game callback. */ Call_Back(); #ifdef WIN32 /* ** Handle possible surface loss due to a focus switch */ if (AllSurfaces.SurfacesRestored) { AllSurfaces.SurfacesRestored=FALSE; redraw = true; continue; } #endif //WIN32 /* ** Fetch and process input. */ KeyNumType input = buttonlist->Input(); switch (input) { case KN_RETURN: case (1|BUTTON_FLAG): process = false; break; default: break; } } return(slider.Get_Value() * (Rule.IsFineDifficulty ? 1 : 2)); }