CnC_Remastered_Collection/REDALERT/SPECIAL.CPP
PG-SteveT ae72fce5dd August 6th Patch Update
Accumulated DLL source code changes since June 22nd patch
2020-08-06 09:44:54 -07:00

600 lines
22 KiB
C++

//
// 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));
}