SPECIAL.CPP (22534B)
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: /CounterStrike/SPECIAL.CPP 1 3/03/97 10:25a 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 : SPECIAL.CPP * 24 * * 25 * Programmer : Joe L. Bostic * 26 * * 27 * Start Date : 05/27/95 * 28 * * 29 * Last Update : August 20, 1996 [JLB] * 30 * * 31 *---------------------------------------------------------------------------------------------* 32 * Functions: * 33 * Fetch_Difficulty -- Fetches the difficulty setting desired. * 34 * Fetch_Password -- Prompts for a password entry from client. * 35 * PWEditClass::Draw_Text -- Draws password style obscured text. * 36 * Special_Dialog -- Handles the special options dialog. * 37 * SpecialClass::Init -- Initialize the special class of options. * 38 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 39 40 #include "function.h" 41 42 #ifdef WIN32 43 #define OPTION_WIDTH 236*2 44 #define OPTION_HEIGHT 162*2 45 #define OPTION_X ((640 - OPTION_WIDTH) / 2) 46 #define OPTION_Y (400 - OPTION_HEIGHT) / 2 47 #else 48 #define OPTION_WIDTH 236 49 #define OPTION_HEIGHT 162 50 #define OPTION_X ((320 - OPTION_WIDTH) / 2) 51 #define OPTION_Y (200 - OPTION_HEIGHT) / 2 52 #endif 53 54 55 /*********************************************************************************************** 56 * SpecialClass::Init -- Initialize the special class of options. * 57 * * 58 * This initialization function is required (as opposed to using a constructor) because * 59 * the SpecialClass is declared as part of a union. A union cannot have a member with a * 60 * constructor. Other than this anomoly, the function serves the same purpose as a * 61 * normal constructor. * 62 * * 63 * INPUT: none * 64 * * 65 * OUTPUT: none * 66 * * 67 * WARNINGS: none * 68 * * 69 * HISTORY: * 70 * 08/20/1996 JLB : Created. * 71 *=============================================================================================*/ 72 void SpecialClass::Init(void) 73 { 74 IsShadowGrow = false; 75 IsSpeedBuild = false; 76 IsFromInstall = false; 77 IsCaptureTheFlag = false; 78 IsInert = false; 79 IsThreePoint = false; 80 IsTGrowth = true; 81 IsTSpread = true; 82 UseMCVDeploy = false; 83 IsMCVDeploy = false; 84 IsEarlyWin = false; 85 ModernBalance = false; 86 } 87 88 89 /*********************************************************************************************** 90 * Special_Dialog -- Handles the special options dialog. * 91 * * 92 * This dialog is used when setting the special game options. It does not appear in the * 93 * final version of the game. * 94 * * 95 * INPUT: none * 96 * * 97 * OUTPUT: none * 98 * * 99 * WARNINGS: none * 100 * * 101 * HISTORY: * 102 * 09/21/1995 JLB : Created. * 103 *=============================================================================================*/ 104 void Special_Dialog(bool simple) 105 { 106 simple; 107 #if (0)//PG 108 SpecialClass oldspecial = Special; 109 GadgetClass * buttons = NULL; 110 static struct { 111 int Description; 112 int Setting; 113 CheckBoxClass * Button; 114 } _options[] = { 115 {TXT_THREE_POINT, 0, 0}, 116 {TXT_SPEED_BUILD, 0, 0}, 117 }; 118 119 TextButtonClass ok(200, TXT_OK, TPF_BUTTON, OPTION_X+15*RESFACTOR, OPTION_Y+OPTION_HEIGHT-15*RESFACTOR); 120 TextButtonClass cancel(201, TXT_CANCEL, TPF_BUTTON, OPTION_X+OPTION_WIDTH-60*RESFACTOR, OPTION_Y+OPTION_HEIGHT-15*RESFACTOR); 121 buttons = &ok; 122 cancel.Add(*buttons); 123 124 for (int index = 0; index < sizeof(_options)/sizeof(_options[0]); index++) { 125 _options[index].Button = new CheckBoxClass(100+index, OPTION_X+17*RESFACTOR, OPTION_Y+20*RESFACTOR+(index*10*RESFACTOR)); 126 if (_options[index].Button) { 127 _options[index].Button->Add(*buttons); 128 129 bool value = false; 130 switch (_options[index].Description) { 131 case TXT_THREE_POINT: 132 value = Special.IsThreePoint; 133 break; 134 135 case TXT_SPEED_BUILD: 136 value = Special.IsSpeedBuild; 137 break; 138 } 139 140 _options[index].Setting = value; 141 if (value) { 142 _options[index].Button->Turn_On(); 143 } else { 144 _options[index].Button->Turn_Off(); 145 } 146 } 147 } 148 149 Map.Override_Mouse_Shape(MOUSE_NORMAL); 150 Set_Logic_Page(SeenBuff); 151 bool recalc = true; 152 bool display = true; 153 bool process = true; 154 while (process) { 155 156 if (Session.Type == GAME_NORMAL) { 157 Call_Back(); 158 } else { 159 if (Main_Loop()) { 160 process = false; 161 } 162 } 163 164 if (display) { 165 display = false; 166 167 Hide_Mouse(); 168 Dialog_Box(OPTION_X, OPTION_Y, OPTION_WIDTH, OPTION_HEIGHT); 169 Draw_Caption(TXT_SPECIAL_OPTIONS, OPTION_X, OPTION_Y, OPTION_WIDTH); 170 171 for (index = 0; index < sizeof(_options)/sizeof(_options[0]); index++) { 172 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); 173 } 174 buttons->Draw_All(); 175 Show_Mouse(); 176 } 177 178 KeyNumType input = buttons->Input(); 179 switch (input) { 180 case KN_ESC: 181 case 200|KN_BUTTON: 182 process = false; 183 for (index = 0; index < sizeof(_options)/sizeof(_options[0]); index++) { 184 bool setting = _options[index].Setting; 185 switch (_options[index].Description) { 186 case TXT_THREE_POINT: 187 oldspecial.IsThreePoint = setting; 188 break; 189 190 case TXT_SPEED_BUILD: 191 oldspecial.IsSpeedBuild = setting; 192 break; 193 } 194 } 195 if (!simple) { 196 OutList.Add(EventClass(oldspecial)); 197 } else { 198 Special = oldspecial; 199 } 200 break; 201 202 case 201|KN_BUTTON: 203 process = false; 204 break; 205 206 case KN_NONE: 207 break; 208 209 default: 210 index = (input & ~KN_BUTTON) - 100; 211 if ((unsigned)index < sizeof(_options)/sizeof(_options[0])) { 212 _options[index].Setting = _options[index].Button->IsOn; 213 } 214 break; 215 } 216 } 217 218 if (!simple) { 219 Map.Revert_Mouse_Shape(); 220 HidPage.Clear(); 221 Map.Flag_To_Redraw(true); 222 Map.Render(); 223 } 224 #endif 225 } 226 227 228 /* 229 ** Derived from the edit class, this class allows entry of passwords style text 230 ** as an edit box. This style is characterized by "*" being displayed for every 231 ** real character entered. 232 */ 233 class PWEditClass : public EditClass 234 { 235 public: 236 PWEditClass(int id, char * text, int max_len, TextPrintType flags, int x, int y, int w=-1, int h=-1) : 237 EditClass(id, text, max_len, flags, x, y, w, h, ALPHANUMERIC) {}; 238 239 protected: 240 virtual void Draw_Text(char const * text); 241 }; 242 243 244 /*********************************************************************************************** 245 * PWEditClass::Draw_Text -- Draws password style obscured text. * 246 * * 247 * This routine is used by the password style edit box in order to display the entered * 248 * text. The text will be displayed as asterisks instead of the actual characters the * 249 * edit box may contain. This is necessary to obscure the password entry from glancing * 250 * eyes. * 251 * * 252 * INPUT: text -- Pointer to the text that is to be rendered. * 253 * * 254 * OUTPUT: none * 255 * * 256 * WARNINGS: none * 257 * * 258 * HISTORY: * 259 * 10/27/1995 JLB : Created. * 260 *=============================================================================================*/ 261 void PWEditClass::Draw_Text(char const * text) 262 { 263 char buffer[80]; 264 265 memset(buffer, '\0', sizeof(buffer)); 266 memset(buffer, '*', strlen(text)); 267 268 if (FontPtr == GradFont6Ptr) { 269 TextPrintType flags; 270 271 if (Has_Focus()) { 272 flags = TPF_BRIGHT_COLOR; 273 } else { 274 flags = (TextPrintType)0; 275 } 276 277 Conquer_Clip_Text_Print(buffer, X+1, Y+1, Color, TBLACK, TextFlags | flags, Width-2); 278 279 if (Has_Focus() && (int)strlen(buffer) < MaxLength) { 280 Conquer_Clip_Text_Print( "_", X+1+String_Pixel_Width(buffer), Y+1, Color, TBLACK, TextFlags | flags); 281 } 282 } else { 283 Conquer_Clip_Text_Print(buffer, X+1, Y+1, Has_Focus() ? 284 &ColorRemaps[PCOLOR_DIALOG_BLUE] : &ColorRemaps[PCOLOR_GREY], 285 TBLACK, TextFlags, Width-2); 286 287 if (Has_Focus() && (int)strlen(buffer) < MaxLength) { 288 Conquer_Clip_Text_Print("_", X+1+String_Pixel_Width(buffer), Y+1, 289 &ColorRemaps[PCOLOR_DIALOG_BLUE], TBLACK, TextFlags); 290 } 291 } 292 } 293 294 295 /*********************************************************************************************** 296 * Fetch_Password -- Prompts for a password entry from client. * 297 * * 298 * This routine will prompt for and return a password entry from the player. * 299 * * 300 * INPUT: caption -- The caption to use for the top of the prompt dialog. * 301 * * 302 * message -- The body of the message to display in the dialog. * 303 * * 304 * btext -- The button text to use to finish the dialog box entry. * 305 * * 306 * OUTPUT: Returns with a pointer to the password text entered. This pointer is valid * 307 * only until the next time that this routine is called. * 308 * * 309 * WARNINGS: none * 310 * * 311 * HISTORY: * 312 * 10/27/1995 JLB : Created. * 313 *=============================================================================================*/ 314 #define BUFFSIZE (511) 315 char const * Fetch_Password(int caption, int message, int btext) 316 { 317 char buffer[BUFFSIZE]; 318 bool process; // loop while true 319 KeyNumType input; // user input 320 bool pressed; 321 int curbutton; 322 TextButtonClass ok; 323 324 if (btext == TXT_NONE) btext = TXT_OK; 325 326 //PG_TO_FIX 327 //Fancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_6PT_GRAD|TPF_NOSHADOW); 328 329 /* 330 ** Examine the optional button parameters. Fetch the width and starting 331 ** characters for each. 332 */ 333 int bwidth, bheight; // button width and height 334 335 /* 336 ** Build the button list. 337 */ 338 bheight = FontHeight + FontYSpacing + 2*RESFACTOR; 339 bwidth = max((String_Pixel_Width(Text_String(btext)) + 8*RESFACTOR), 30*RESFACTOR); 340 341 /* 342 ** Determine the dimensions of the text to be used for the dialog box. 343 ** These dimensions will control how the dialog box looks. 344 */ 345 buffer[BUFFSIZE-1] = 0; 346 strncpy(buffer, Text_String(message), BUFFSIZE-1); 347 //PG_TO_FIX 348 //Fancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_6PT_GRAD|TPF_NOSHADOW); 349 int width; 350 int height; 351 Format_Window_String(buffer, 255, width, height); 352 353 width = max(width, 50*RESFACTOR); 354 width += 40*RESFACTOR; 355 height += (60+25)*RESFACTOR; 356 357 int x = (SeenBuff.Get_Width() - width) / 2; 358 int y = (SeenBuff.Get_Height() - height) / 2; 359 360 /* 361 ** Create the "ok" and password edit buttons. 362 */ 363 TextButtonClass button1(1, btext, TPF_BUTTON, 364 x + ((width - bwidth) >> 1), y + height - (bheight + 5*RESFACTOR), bwidth); 365 366 static char pbuffer[45]; 367 memset(pbuffer, '\0', sizeof(pbuffer)); 368 int editx = x+26*RESFACTOR; 369 int editwidth = (SeenBuff.Get_Width()/2 - editx) * 2; 370 PWEditClass button2(2, &pbuffer[0], sizeof(pbuffer), TPF_6PT_GRAD|TPF_NOSHADOW, editx, (y+height)-35*RESFACTOR, editwidth, 10*RESFACTOR); 371 372 TextButtonClass * buttonlist = 0; 373 curbutton = 0; 374 375 /* 376 ** Add and initialize the buttons to the button list. 377 */ 378 buttonlist = &button1; 379 button2.Add(*buttonlist); 380 381 /* 382 ** Draw the background of the dialog. 383 */ 384 Hide_Mouse(); 385 Set_Logic_Page(SeenBuff); 386 Dialog_Box(x, y, width, height); 387 Draw_Caption(caption, x, y, width); 388 389 /* 390 ** Draw the body of the message box. 391 */ 392 Fancy_Text_Print(buffer, x + 20*RESFACTOR, y + 25*RESFACTOR, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW); 393 394 /* 395 ** Redraw the buttons. 396 */ 397 if (buttonlist) { 398 buttonlist->Draw_All(); 399 } 400 Show_Mouse(); 401 402 /* 403 ** Main Processing Loop. 404 */ 405 process = true; 406 pressed = false; 407 bool first = true; 408 while (process) { 409 410 /* 411 ** Invoke game callback. 412 */ 413 Call_Back(); 414 415 #ifdef WIN32 416 /* 417 ** Handle possible surface loss due to a focus switch 418 */ 419 if (AllSurfaces.SurfacesRestored) { 420 AllSurfaces.SurfacesRestored=FALSE; 421 process = false; 422 break; 423 } 424 #endif //WIN32 425 426 /* 427 ** Fetch and process input. 428 */ 429 input = buttonlist->Input(); 430 if (first) { 431 button2.Set_Focus(); 432 button2.Flag_To_Redraw(); 433 first = false; 434 } 435 switch (input) { 436 case (1|BUTTON_FLAG): 437 process = false; 438 break; 439 440 case (KN_ESC): 441 case (2|BUTTON_FLAG): 442 process = false; 443 break; 444 445 case (KN_RETURN): 446 process = false; 447 break; 448 449 default: 450 break; 451 } 452 } 453 454 return(pbuffer); 455 } 456 457 458 /*********************************************************************************************** 459 * Fetch_Difficulty -- Fetches the difficulty setting desired. * 460 * * 461 * This will display a dialog box that requests the player to specify a difficulty * 462 * setting. * 463 * * 464 * INPUT: none * 465 * * 466 * OUTPUT: Returns with a difficulty setting of 0 for easiest and 4 for hardest. * 467 * * 468 * WARNINGS: none * 469 * * 470 * HISTORY: * 471 * 08/13/1996 JLB : Created. * 472 *=============================================================================================*/ 473 #ifdef FIXIT_CSII // checked - ajw 9/28/98 474 int Fetch_Difficulty(bool amath) 475 #else 476 int Fetch_Difficulty(void) 477 #endif 478 { 479 int const w = 250 * RESFACTOR; 480 int const h = 80 * RESFACTOR; 481 int const x = ((320 * RESFACTOR)/2) - w/2; 482 int const y = ((200 * RESFACTOR)/2) - h/2; 483 int const bwidth = 30 * RESFACTOR; 484 485 /* 486 ** Fill the description buffer with the description text. Break 487 ** the text into appropriate spacing. 488 */ 489 char buffer[512]; 490 strncpy(buffer, Text_String(TXT_DIFFICULTY), sizeof(buffer)-1); 491 buffer[sizeof(buffer)-1] = '\0'; 492 #ifdef FIXIT_CSII // checked - ajw 9/28/98 493 // If it's an aftermath mission, trim the sentence to get rid of the campaign stuff. 494 if (amath) { 495 int index=0; 496 while (buffer[index] && buffer[index]!='.') index++; 497 if (buffer[index]=='.') { 498 buffer[index+1]=0; 499 } 500 } 501 #endif 502 //PG_TO_FIX 503 //Fancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_6PT_GRAD|TPF_NOSHADOW); 504 int width; 505 int height; 506 Format_Window_String(buffer, w-60*RESFACTOR, width, height); 507 508 /* 509 ** Create the OK button. 510 */ 511 TextButtonClass okbutton(1, TXT_OK, TPF_BUTTON, (x+w) - (bwidth+20*RESFACTOR) , (y+h) - (18*RESFACTOR), bwidth); 512 GadgetClass * buttonlist = &okbutton; 513 514 /* 515 ** Create the slider button. 516 */ 517 SliderClass slider(2, x+20*RESFACTOR, y+h - 29*RESFACTOR, w - 40*RESFACTOR, 8*RESFACTOR, true); 518 if (Rule.IsFineDifficulty) { 519 slider.Set_Maximum(5); 520 slider.Set_Value(2); 521 } else { 522 slider.Set_Maximum(3); 523 slider.Set_Value(1); 524 } 525 slider.Add(*buttonlist); 526 527 /* 528 ** Main Processing Loop. 529 */ 530 Set_Logic_Page(SeenBuff); 531 bool redraw = true; 532 bool process = true; 533 while (process) { 534 535 if (redraw) { 536 redraw = false; 537 538 /* 539 ** Draw the background of the dialog. 540 */ 541 Hide_Mouse(); 542 Dialog_Box(x, y, w, h); 543 544 /* 545 ** Draw the body of the message. 546 */ 547 // Fancy_Text_Print(buffer, x + 20*RESFACTOR, y + 15*RESFACTOR, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW); 548 Fancy_Text_Print(buffer, x + 20*RESFACTOR, y + 15*RESFACTOR, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_6PT_GRAD|TPF_NOSHADOW); 549 550 /* 551 ** Display the descripton of the slider range. 552 */ 553 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); 554 Fancy_Text_Print(TXT_EASY, slider.X, slider.Y-9*RESFACTOR, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_6PT_GRAD|TPF_DROPSHADOW); 555 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); 556 557 /* 558 ** Redraw the buttons. 559 */ 560 if (buttonlist) { 561 buttonlist->Draw_All(); 562 } 563 Show_Mouse(); 564 } 565 566 /* 567 ** Invoke game callback. 568 */ 569 Call_Back(); 570 571 #ifdef WIN32 572 /* 573 ** Handle possible surface loss due to a focus switch 574 */ 575 if (AllSurfaces.SurfacesRestored) { 576 AllSurfaces.SurfacesRestored=FALSE; 577 redraw = true; 578 continue; 579 } 580 #endif //WIN32 581 582 /* 583 ** Fetch and process input. 584 */ 585 KeyNumType input = buttonlist->Input(); 586 587 switch (input) { 588 case KN_RETURN: 589 case (1|BUTTON_FLAG): 590 process = false; 591 break; 592 593 default: 594 break; 595 } 596 } 597 598 return(slider.Get_Value() * (Rule.IsFineDifficulty ? 1 : 2)); 599 }