SPECIAL.CPP 22 KB

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