HELP.CPP 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  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. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
  9. // in the hope that it will be useful, but with permitted additional restrictions
  10. // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
  11. // distributed with this program. You should have received a copy of the
  12. // GNU General Public License along with permitted additional restrictions
  13. // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
  14. /* $Header: F:\projects\c&c\vcs\code\help.cpv 2.18 16 Oct 1995 16:51:02 JOE_BOSTIC $ */
  15. /***********************************************************************************************
  16. *** 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 ***
  17. ***********************************************************************************************
  18. * *
  19. * Project Name : Command & Conquer *
  20. * *
  21. * File Name : HELP.CPP *
  22. * *
  23. * Programmer : Joe L. Bostic *
  24. * *
  25. * Start Date : 11/18/94 *
  26. * *
  27. * Last Update : July 16, 1995 [JLB] *
  28. * *
  29. *---------------------------------------------------------------------------------------------*
  30. * Functions: *
  31. * HelpClass::Draw_Help -- Display the help message (if necessary). *
  32. * HelpClass::HelpClass -- Default constructor for the help processor. *
  33. * HelpClass::Help_AI -- Handles the help text logic. *
  34. * HelpClass::Help_Text -- Assigns text as the current help text. *
  35. * HelpClass::Init_Clear -- Sets help system to a known state. *
  36. * HelpClass::Overlap_List -- Returns with offset list for cells under help text. *
  37. * HelpClass::Scroll_Map -- Makes sure scrolling doesn't leave text shards. *
  38. * HelpClass::Set_Cost -- Initiates the second line of help text showing item cost. *
  39. * HelpClass::Set_Tactical_Position -- Sets the tactial map position. *
  40. * HelpClass::Set_Tactical_Position -- Sets the tactical map position. *
  41. * HelpClass::Set_Text -- Determines the overlap list and draw coordinates. *
  42. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  43. #include "function.h"
  44. /*
  45. ** This is the holding buffer for the text overlap list. This buffer must be in the near
  46. ** data segment. It will be filled in by the Set_Text() function.
  47. */
  48. //short const HelpClass::OverlapList[30] = { // Can't be const - it's expected to be written to. ST - 2/7/2019 5:16PM
  49. short HelpClass::OverlapList[30] = {
  50. REFRESH_EOL
  51. };
  52. char const * HelpClass::HelpText;
  53. CountDownTimerClass HelpClass::CountDownTimer;
  54. /***********************************************************************************************
  55. * HelpClass::HelpClass -- Default constructor for the help processor. *
  56. * *
  57. * The help processor is initialized by this routine. It merely sets up the help engine *
  58. * to the default state. The default state will not display any help text. Call the *
  59. * Help_Text() function to enable help processing. *
  60. * *
  61. * INPUT: none *
  62. * *
  63. * OUTPUT: none *
  64. * *
  65. * WARNINGS: none *
  66. * *
  67. * HISTORY: *
  68. * 11/18/1994 JLB : Created. *
  69. *=============================================================================================*/
  70. HelpClass::HelpClass(void)
  71. {
  72. X = 0;
  73. Y = 0;
  74. Width = 0;
  75. Text = TXT_NONE;
  76. Color = LTGREY;
  77. CountDownTimer.Set(0);
  78. IsRight = false;
  79. Cost = 0;
  80. }
  81. /***********************************************************************************************
  82. * HelpClass::Init_Clear -- Sets help system to a known state. *
  83. * *
  84. * INPUT: none *
  85. * *
  86. * OUTPUT: none *
  87. * *
  88. * WARNINGS: none *
  89. * *
  90. * HISTORY: *
  91. * 12/24/1994 JLB : Created. *
  92. *=============================================================================================*/
  93. void HelpClass::Init_Clear(void)
  94. {
  95. TabClass::Init_Clear();
  96. Set_Text(TXT_NONE);
  97. }
  98. /***********************************************************************************************
  99. * HelpClass::Overlap_List -- Returns with offset list for cells under help text. *
  100. * *
  101. * Use this routine to fetch an offset list for the cells under the text displayed. If *
  102. * there is no text displayed, then the list will consist of just the terminator code. *
  103. * *
  104. * INPUT: none *
  105. * *
  106. * OUTPUT: Returns with a pointer to the offset list for the help text overlap. The offset *
  107. * list is based on the tactical map upper left corner cell. *
  108. * *
  109. * WARNINGS: none *
  110. * *
  111. * HISTORY: *
  112. * 11/18/1994 JLB : Created. *
  113. *=============================================================================================*/
  114. short const * HelpClass::Overlap_List(void) const
  115. {
  116. if (Text == TXT_NONE || CountDownTimer.Time()) {
  117. ((short &)(OverlapList[0])) = REFRESH_EOL;
  118. }
  119. return(OverlapList);
  120. }
  121. /***********************************************************************************************
  122. * HelpClass::Help_AI -- Handles the help text logic. *
  123. * *
  124. * This routine handles tracking the mouse position to see if the mouse remains stationary *
  125. * for the required amount of time. If the time requirement has been met, then it flags *
  126. * the help system to display the help text the next time the Draw_Help() function is *
  127. * called. *
  128. * *
  129. * INPUT: key -- Keyboard input code. *
  130. * *
  131. * x,y -- Mouse coordinates. *
  132. * *
  133. * OUTPUT: none *
  134. * *
  135. * WARNINGS: This routine must be called once and only once per game frame (15 times per *
  136. * second). *
  137. * *
  138. * HISTORY: *
  139. * 11/18/1994 JLB : Created. *
  140. * 12/31/1994 JLB : Uses mouse coordinates as passed in. *
  141. *=============================================================================================*/
  142. void HelpClass::AI(KeyNumType &key, int x, int y)
  143. {
  144. /*
  145. ** If there is any keyboard input, then the help text goes away.
  146. */
  147. // if (key) {
  148. // Help_Text(TXT_NONE);
  149. // }
  150. if (!CountDownTimer.Time() && !IsRight && (x != X || y != Y)) {
  151. Help_Text(TXT_NONE);
  152. }
  153. /*
  154. ** Process the countdown timer only if it hasn't already expired and there is
  155. ** a real help text message to display.
  156. */
  157. if (CountDownTimer.Time() && !HelpText && Text != TXT_NONE) {
  158. /*
  159. ** If the mouse has moved, then reset the timer since a moving mouse is not
  160. ** supposed to bring up the help text.
  161. */
  162. if (!IsRight && (X != x || Y != y)) {
  163. X = x;
  164. Y = y;
  165. CountDownTimer.Start();
  166. CountDownTimer.Set(HELP_DELAY);
  167. Set_Text(TXT_NONE);
  168. } else {
  169. /*
  170. ** If the delay has expired, then the text must be drawn. Build the help text
  171. ** overlay list at this time. Better to do it now, when we KNOW it is needed, then
  172. ** to do it earlier when it might not be needed.
  173. */
  174. Set_Text(Text);
  175. }
  176. }
  177. TabClass::AI(key, x, y);
  178. }
  179. /***********************************************************************************************
  180. * HelpClass::Help_Text -- Assigns text as the current help text. *
  181. * *
  182. * Use this routine to change the help text that will pop up if the cursor isn't moved *
  183. * for the help delay duration. Call this routine as often as desired. *
  184. * *
  185. * INPUT: text -- The text number for the help text to use. *
  186. * *
  187. * OUTPUT: none *
  188. * *
  189. * WARNINGS: none *
  190. * *
  191. * HISTORY: *
  192. * 11/18/1994 JLB : Created. *
  193. *=============================================================================================*/
  194. void HelpClass::Help_Text(int text, int x, int y, int color, bool quick, int cost)
  195. {
  196. if (text != Text) {
  197. /*
  198. ** If there is an existing text message, then flag the map to redraw the underlying
  199. ** icons so that the text message is erased.
  200. */
  201. if (Text != TXT_NONE) {
  202. Refresh_Cells(Coord_Cell(TacticalCoord), &OverlapList[0]);
  203. }
  204. /*
  205. ** Record the position of the mouse. This recorded position will be used to determine
  206. ** if the mouse has moved. A moving mouse prevents the help text from popping up.
  207. */
  208. X = x;
  209. if (x == -1) X = Get_Mouse_X();
  210. Y = y;
  211. if (y == -1) Y = Get_Mouse_Y();
  212. IsRight = (y != -1) || (x != -1);
  213. if (quick) {
  214. CountDownTimer.Set(1);
  215. } else {
  216. CountDownTimer.Set(HELP_DELAY);
  217. }
  218. Color = color;
  219. Text = text;
  220. Cost = cost;
  221. }
  222. }
  223. /***********************************************************************************************
  224. * HelpClass::Draw_Help -- Display the help message (if necessary). *
  225. * *
  226. * This function will print the help text if it thinks it should. The timer and text *
  227. * message can control whether this occurs. If there is no help text or the countdown timer *
  228. * has not expired, then no text will be printed. *
  229. * *
  230. * INPUT: none *
  231. * *
  232. * OUTPUT: none *
  233. * *
  234. * WARNINGS: none *
  235. * *
  236. * HISTORY: *
  237. * 11/18/1994 JLB : Created. *
  238. *=============================================================================================*/
  239. void HelpClass::Draw_It(bool forced)
  240. {
  241. TabClass::Draw_It(forced);
  242. if (Text != TXT_NONE && (forced || !CountDownTimer.Time())) {
  243. if (LogicPage->Lock()){
  244. // Fancy_Text_Print(Text, DrawX, DrawY, Color, BLACK, TPF_6POINT|TPF_NOSHADOW);
  245. Fancy_Text_Print(Text, DrawX, DrawY, Color, BLACK, TPF_MAP|TPF_NOSHADOW);
  246. LogicPage->Draw_Rect(DrawX-1, DrawY-1, DrawX+Width+1, DrawY+FontHeight, Color);
  247. if (Cost) {
  248. char buffer[15];
  249. sprintf(buffer, "$%d", Cost);
  250. int width = String_Pixel_Width(buffer);
  251. // Fancy_Text_Print(buffer, DrawX, DrawY+FontHeight, Color, BLACK, TPF_6POINT|TPF_NOSHADOW);
  252. Fancy_Text_Print(buffer, DrawX, DrawY+FontHeight, Color, BLACK, TPF_MAP|TPF_NOSHADOW);
  253. LogicPage->Draw_Rect(DrawX-1, DrawY+FontHeight, DrawX+width+1, DrawY+FontHeight+FontHeight-1, Color);
  254. LogicPage->Draw_Line(DrawX, DrawY+FontHeight, DrawX+MIN(width+1, Width) - 1, DrawY+FontHeight, BLACK);
  255. }
  256. LogicPage->Unlock();
  257. }
  258. }
  259. // if (!In_Debugger) HidPage.Unlock();
  260. }
  261. /***********************************************************************************************
  262. * HelpClass::Set_Text -- Determines the overlap list and draw coordinates. *
  263. * *
  264. * This routine is used to build the overlap list -- used for icon refreshing. It also *
  265. * determines if the text can fit on the screen and makes adjustments so that it will. *
  266. * *
  267. * INPUT: text -- The text number to set the help system to use. *
  268. * *
  269. * OUTPUT: none *
  270. * *
  271. * WARNINGS: none *
  272. * *
  273. * HISTORY: *
  274. * 11/18/1994 JLB : Created. *
  275. * 12/11/1994 JLB : Won't draw past tactical map edges. *
  276. *=============================================================================================*/
  277. void HelpClass::Set_Text(int text)
  278. {
  279. if (text != TXT_NONE) {
  280. Text = text;
  281. // Fancy_Text_Print(TXT_NONE, 0, 0, 0, 0, TPF_6POINT|TPF_NOSHADOW);
  282. Fancy_Text_Print(TXT_NONE, 0, 0, 0, 0, TPF_MAP|TPF_NOSHADOW);
  283. Width = String_Pixel_Width(Text_String(Text));
  284. if (IsRight) {
  285. DrawX = X - Width;
  286. DrawY = Y;
  287. } else {
  288. int right = TacPixelX + Lepton_To_Pixel(TacLeptonWidth) - 3;
  289. int bottom = TacPixelY + Lepton_To_Pixel(TacLeptonHeight) - 1;
  290. DrawX = X+X_OFFSET;
  291. DrawY = Y+Y_OFFSET;
  292. if (DrawX + Width > right) {
  293. DrawX -= (DrawX+Width) - right;
  294. }
  295. if (DrawY + FontHeight > bottom) {
  296. DrawY -= (DrawY+FontHeight) - bottom;
  297. }
  298. if (DrawX < TacPixelX+1) DrawX = TacPixelX+1;
  299. if (DrawY < TacPixelY+1) DrawY = TacPixelY+1;
  300. }
  301. int lines = (Cost) ? 2 : 1;
  302. memcpy((void*)OverlapList, Text_Overlap_List(Text_String(Text), DrawX-1, DrawY, lines), sizeof(OverlapList));
  303. }
  304. }
  305. /***********************************************************************************************
  306. * HelpClass::Scroll_Map -- Makes sure scrolling doesn't leave text shards. *
  307. * *
  308. * This routine intercepts the map scrolling request and then makes sure that if, in fact, *
  309. * the map is going to scroll, then reset and erase the help text so that it doesn't *
  310. * mess up the display. *
  311. * *
  312. * INPUT: facing -- The direction to scroll (unused by this routine). *
  313. * *
  314. * really -- If the scroll is actually going to occur, rather than just be examined *
  315. * for legality, then this parameter will be true. If this parameter is *
  316. * true, then the help text is reset. *
  317. * *
  318. * OUTPUT: Returns if it can, or did, scroll in the requested direction. *
  319. * *
  320. * WARNINGS: none *
  321. * *
  322. * HISTORY: *
  323. * 12/15/1994 JLB : Created. *
  324. *=============================================================================================*/
  325. bool HelpClass::Scroll_Map(DirType facing, int & distance, bool really)
  326. {
  327. if (really) {
  328. Help_Text(TXT_NONE);
  329. }
  330. return(TabClass::Scroll_Map(facing, distance, really));
  331. }
  332. /***********************************************************************************************
  333. * HelpClass::Set_Cost -- Initiates the second line of help text showing item cost. *
  334. * *
  335. * Use this routine after the Help_Text() function to activate the second line. The second *
  336. * line displays a cost. Typically, this is used by the sidebar to display the cost of the *
  337. * specified item. *
  338. * *
  339. * INPUT: cost -- The cost to associate with this help text. If this value is zero, then *
  340. * no second line is displayed, so don't pass in zero. *
  341. * *
  342. * OUTPUT: none *
  343. * *
  344. * WARNINGS: none *
  345. * *
  346. * HISTORY: *
  347. * 01/09/1995 JLB : Created. *
  348. *=============================================================================================*/
  349. void HelpClass::Set_Cost(int cost)
  350. {
  351. Cost = cost;
  352. }
  353. void HelpClass::Set_Tactical_Position(COORDINATE coord)
  354. {
  355. if (TacticalCoord != coord) {
  356. Help_Text(TXT_NONE);
  357. }
  358. TabClass::Set_Tactical_Position(coord);
  359. }