radiocommanddisplay.cpp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. /*
  2. ** Command & Conquer Renegade(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. /***********************************************************************************************
  19. *** 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 ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : commando *
  23. * *
  24. * $Archive:: /Commando/Code/Commando/radiocommanddisplay.cpp $*
  25. * *
  26. * Author:: Patrick Smith *
  27. * *
  28. * $Modtime:: 3/15/02 3:26p $*
  29. * *
  30. * $Revision:: 5 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "radiocommanddisplay.h"
  36. #include "assetmgr.h"
  37. #include "texture.h"
  38. #include "font3d.h"
  39. #include "objectives.h"
  40. #include "translatedb.h"
  41. #include "wwaudio.h"
  42. #include "globalsettings.h"
  43. #include "scene.h"
  44. #include "evasettings.h"
  45. #include "cncmodesettings.h"
  46. #include "string_ids.h"
  47. #include "rendobj.h"
  48. #include "input.h"
  49. #include "dinput.h"
  50. #include "timemgr.h"
  51. #include "gametype.h"
  52. #include "combat.h"
  53. #include "vehicle.h"
  54. #include "soldier.h"
  55. ////////////////////////////////////////////////////////////////
  56. // Static member initialization
  57. ////////////////////////////////////////////////////////////////
  58. float RadioCommandDisplayClass::DisplayTimer = 0.0F;
  59. bool RadioCommandDisplayClass::IsDisplayed = false;
  60. TextWindowClass * RadioCommandDisplayClass::TextWindow = NULL;
  61. ////////////////////////////////////////////////////////////////
  62. //
  63. // Shutdown
  64. //
  65. ////////////////////////////////////////////////////////////////
  66. void
  67. RadioCommandDisplayClass::Shutdown (void)
  68. {
  69. if (TextWindow != NULL) {
  70. delete TextWindow;
  71. TextWindow = NULL;
  72. }
  73. IsDisplayed = false;
  74. DisplayTimer = 0.0F;
  75. return ;
  76. }
  77. ////////////////////////////////////////////////////////////////
  78. //
  79. // Initialize
  80. //
  81. ////////////////////////////////////////////////////////////////
  82. void
  83. RadioCommandDisplayClass::Initialize (void)
  84. {
  85. //
  86. // Start fresh
  87. //
  88. if (TextWindow != NULL) {
  89. delete TextWindow;
  90. TextWindow = NULL;
  91. }
  92. //
  93. // Allocate the new text window
  94. //
  95. TextWindow = new TextWindowClass;
  96. //
  97. // Use the same dimensions as the mission objectives in single player
  98. //
  99. EvaSettingsDefClass *settings = EvaSettingsDefClass::Get_Instance ();
  100. //
  101. // Local constants
  102. //
  103. const char *BACKDROP_TGA = "hud_6x4_Messages.tga";
  104. //
  105. // Configure the backdrop for the text window
  106. //
  107. TextWindow->Set_Backdrop (BACKDROP_TGA, settings->Get_Objectives_Screen_Rect (),
  108. settings->Get_Objectives_Texture_Size (), settings->Get_Objectives_Endcap_Rect (),
  109. settings->Get_Objectives_Fadeout_Rect (), settings->Get_Objectives_Background_Rect ());
  110. //
  111. // Configure the area where text can be displayed in the window
  112. //
  113. TextWindow->Set_Text_Area (settings->Get_Objectives_Text_Rect ());
  114. //
  115. // Configure the columns
  116. //
  117. TextWindow->Add_Column (TRANSLATE (IDS_MENU_RADIO_KEY), 0.3F, Vector3 (0.75F, 1.0F, 0.75F));
  118. TextWindow->Add_Column (TRANSLATE (IDS_MENU_RADIO_KEY_MESSAGE), 0.7F, Vector3 (0.75F, 1.0F, 0.75F));
  119. TextWindow->Display_Columns (true);
  120. DisplayTimer = 0.0F;
  121. return ;
  122. }
  123. ////////////////////////////////////////////////////////////////
  124. //
  125. // Update
  126. //
  127. ////////////////////////////////////////////////////////////////
  128. void
  129. RadioCommandDisplayClass::Update (DISPLAY_TYPE type)
  130. {
  131. CNCModeSettingsDef *cnc_def = CNCModeSettingsDef::Get_Instance ();
  132. if (TextWindow == NULL || cnc_def == NULL) {
  133. return ;
  134. }
  135. //
  136. // Start fresh
  137. //
  138. TextWindow->Delete_All_Items ();
  139. //
  140. // Local constants
  141. //
  142. const int COMMAND_COUNT = 10;
  143. //
  144. // Determine what the access key to display these radio commands is.
  145. //
  146. int range_start_index = 0;
  147. WideStringClass access_key;
  148. if (type == DISPLAY_CMDS_01) {
  149. access_key = TRANSLATE (IDS_MENU_TEXT892);
  150. } else if (type == DISPLAY_CMDS_02) {
  151. access_key = TRANSLATE (IDS_MENU_TEXT893);
  152. range_start_index = 10;
  153. } else {
  154. access_key.Format (L"%s + %s", TRANSLATE (IDS_MENU_TEXT892), TRANSLATE (IDS_MENU_TEXT893));
  155. range_start_index = 20;
  156. }
  157. //
  158. // Add all the radio commands to the text window
  159. //
  160. for (int index = 0; index < COMMAND_COUNT; index ++){
  161. int key_id = index + 1;
  162. if (key_id >= 10) {
  163. key_id -= 10;
  164. }
  165. WideStringClass command_key (0, true);
  166. command_key.Format (L"%s + %d", access_key, key_id);
  167. //
  168. // Insert an item for this radio command
  169. //
  170. int item_index = TextWindow->Insert_Item (index, command_key);
  171. if (item_index >= 0) {
  172. //
  173. // Lookup the message that this command displays
  174. //
  175. int cmd_index = range_start_index + index;
  176. int text_id = cnc_def->Get_Radio_Command (cmd_index);
  177. //
  178. // Display the message
  179. //
  180. TextWindow->Set_Item_Text (item_index, 1, TRANSLATE (text_id));
  181. }
  182. }
  183. return ;
  184. }
  185. ////////////////////////////////////////////////////////////////
  186. //
  187. // Display
  188. //
  189. ////////////////////////////////////////////////////////////////
  190. void
  191. RadioCommandDisplayClass::Display (bool onoff, DISPLAY_TYPE type)
  192. {
  193. //
  194. // Display or hide the window
  195. //
  196. IsDisplayed = onoff;
  197. TextWindow->Display (onoff);
  198. //
  199. // Update the data in the window as necessary
  200. //
  201. if (onoff) {
  202. Update (type);
  203. }
  204. //
  205. // Play the 'EVA displayed' sound effect
  206. //
  207. if (IsDisplayed) {
  208. int sound_id = GlobalSettingsDef::Get_Global_Settings ()->Get_EVA_Objectives_Sound_ID ();
  209. if (sound_id != 0) {
  210. WWAudioClass::Get_Instance ()->Create_Instant_Sound (sound_id, Matrix3D (1));
  211. }
  212. }
  213. return ;
  214. }
  215. ////////////////////////////////////////////////////////////////
  216. //
  217. // Render
  218. //
  219. ////////////////////////////////////////////////////////////////
  220. void
  221. RadioCommandDisplayClass::Render (void)
  222. {
  223. //
  224. // Don't do this for true single player
  225. //
  226. if (IS_MISSION) {
  227. return ;
  228. }
  229. Check_Keys ();
  230. //
  231. // Only render if the window is being displayed
  232. //
  233. if (IsDisplayed) {
  234. TextWindow->Render ();
  235. }
  236. return ;
  237. }
  238. ////////////////////////////////////////////////////////////////
  239. //
  240. // Check_Keys
  241. //
  242. ////////////////////////////////////////////////////////////////
  243. void
  244. RadioCommandDisplayClass::Check_Keys (void)
  245. {
  246. //
  247. // Local constants
  248. //
  249. const float TIMER_DURATION = 2.0F;
  250. // ignore left control if star is in a flying vehicle
  251. bool ignore_lctrl = ( COMBAT_STAR && COMBAT_STAR->As_SoldierGameObj() && COMBAT_STAR->As_SoldierGameObj()->Get_Vehicle() && COMBAT_STAR->As_SoldierGameObj()->Get_Vehicle()->Is_Aircraft() );
  252. //
  253. // Determine which keys (if any) are down
  254. //
  255. bool is_key_down[DISPLAY_MAX] = { 0 };
  256. if ( ignore_lctrl ) {
  257. is_key_down[DISPLAY_CMDS_01] = Input::Is_Button_Down (DIK_RCONTROL);
  258. is_key_down[DISPLAY_CMDS_02] = Input::Is_Button_Down (DIK_RMENU);
  259. } else {
  260. is_key_down[DISPLAY_CMDS_01] = Input::Is_Button_Down (DIK_LCONTROL) || Input::Is_Button_Down (DIK_RCONTROL);
  261. is_key_down[DISPLAY_CMDS_02] = Input::Is_Button_Down (DIK_LMENU) || Input::Is_Button_Down (DIK_RMENU);
  262. }
  263. is_key_down[DISPLAY_CMDS_03] = is_key_down[DISPLAY_CMDS_01] && is_key_down[DISPLAY_CMDS_02];
  264. //
  265. // Are any of the buttons being held?
  266. //
  267. bool is_any_key_down = is_key_down[DISPLAY_CMDS_01] || is_key_down[DISPLAY_CMDS_02];
  268. if (is_any_key_down) {
  269. //
  270. // Do we need to display the UI or trigger the timer?
  271. //
  272. if (IsDisplayed == false) {
  273. if (DisplayTimer == 0.0F) {
  274. DisplayTimer = TIMER_DURATION;
  275. } else {
  276. //
  277. // Is it time to display the UI yet?
  278. //
  279. DisplayTimer -= TimeManager::Get_Frame_Seconds ();
  280. if (DisplayTimer <= 0.0F) {
  281. //
  282. // Determine which page to display
  283. //
  284. for (int index = DISPLAY_MAX - 1; index >= 0; index --) {
  285. if (is_key_down[index]) {
  286. Display (true, (DISPLAY_TYPE)index);
  287. DisplayTimer = 0.0F;
  288. break;
  289. }
  290. }
  291. }
  292. }
  293. }
  294. } else {
  295. //
  296. // Turn off the UI if the key is no longer being held
  297. //
  298. if (IsDisplayed) {
  299. Display (false);
  300. }
  301. DisplayTimer = 0.0F;
  302. }
  303. return ;
  304. }