dlgcncbattleinfo.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  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/dlgcncbattleinfo.cpp $*
  25. * *
  26. * Author:: Patrick Smith *
  27. * *
  28. * $Modtime:: 2/24/02 2:06p $*
  29. * *
  30. * $Revision:: 11 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "dlgcncbattleinfo.h"
  36. #include "resource.h"
  37. #include "listctrl.h"
  38. #include "imagectrl.h"
  39. #include "playertype.h"
  40. #include "combat.h"
  41. #include "playermanager.h"
  42. #include "player.h"
  43. #include "soldier.h"
  44. #include "gameinitmgr.h"
  45. #include "gamemode.h"
  46. #include "input.h"
  47. #include "healthbarctrl.h"
  48. #include "basecontroller.h"
  49. #include "building.h"
  50. #include "damage.h"
  51. #include "vehicle.h"
  52. #include "resource.h"
  53. #include "WOLGMode.h"
  54. #include <WWOnline\WOLUser.h>
  55. #include "translatedb.h"
  56. #include "string_ids.h"
  57. #include "mousemgr.h"
  58. #include "directinput.h"
  59. ////////////////////////////////////////////////////////////////
  60. // Local constants
  61. ////////////////////////////////////////////////////////////////
  62. enum
  63. {
  64. COL_RANK,
  65. COL_NAME,
  66. COL_KD,
  67. COL_SCORE
  68. };
  69. static const BUILDING_COUNT = 5;
  70. static const BUILDING_SLOT_COUNT = 6;
  71. ////////////////////////////////////////////////////////////////
  72. // Local typedefs
  73. ////////////////////////////////////////////////////////////////
  74. typedef struct
  75. {
  76. const char * texture_name;
  77. BuildingConstants::BuildingType type;
  78. } BUILDING_INSTANCE_INFO;
  79. static const BUILDING_INSTANCE_INFO GDI_BUILDINGS[BUILDING_COUNT] =
  80. {
  81. { "HUD_C&C_G_GUARDTOW.TGA", BuildingConstants::TYPE_BASE_DEFENSE },
  82. { "HUD_C&C_G_REFINERY.TGA", BuildingConstants::TYPE_REFINERY },
  83. { "HUD_C&C_G_POWER.TGA", BuildingConstants::TYPE_POWER_PLANT },
  84. { "HUD_C&C_G_BARRACKS.TGA", BuildingConstants::TYPE_SOLDIER_FACTORY },
  85. { "HUD_C&C_G_WARFACT.TGA", BuildingConstants::TYPE_VEHICLE_FACTORY },
  86. };
  87. static const BUILDING_INSTANCE_INFO NOD_BUILDINGS[BUILDING_COUNT] =
  88. {
  89. { "HUD_C&C_OBLISK.TGA", BuildingConstants::TYPE_BASE_DEFENSE },
  90. { "HUD_C&C_N_REFINERY.TGA", BuildingConstants::TYPE_REFINERY },
  91. { "HUD_C&C_N_POWER.TGA", BuildingConstants::TYPE_POWER_PLANT },
  92. { "HUD_C&C_N_HANDOF.TGA", BuildingConstants::TYPE_SOLDIER_FACTORY },
  93. { "HUD_C&C_N_AIRSTRIP.TGA", BuildingConstants::TYPE_VEHICLE_FACTORY },
  94. };
  95. typedef struct
  96. {
  97. int icon_ctrl_id;
  98. int health_ctrl_id;
  99. } BUILDING_INFO;
  100. static const BUILDING_INFO GDI_BUILDING_CTRLS[BUILDING_SLOT_COUNT] =
  101. {
  102. { IDC_GDI_BUILDING01_ICON, IDC_GDI_BUILDING01_HEALTHBAR },
  103. { IDC_GDI_BUILDING02_ICON, IDC_GDI_BUILDING02_HEALTHBAR },
  104. { IDC_GDI_BUILDING03_ICON, IDC_GDI_BUILDING03_HEALTHBAR },
  105. { IDC_GDI_BUILDING04_ICON, IDC_GDI_BUILDING04_HEALTHBAR },
  106. { IDC_GDI_BUILDING05_ICON, IDC_GDI_BUILDING05_HEALTHBAR },
  107. { IDC_GDI_BUILDING06_ICON, IDC_GDI_BUILDING06_HEALTHBAR },
  108. };
  109. static const BUILDING_INFO NOD_BUILDING_CTRLS[BUILDING_SLOT_COUNT] =
  110. {
  111. { IDC_NOD_BUILDING01_ICON, IDC_NOD_BUILDING01_HEALTHBAR },
  112. { IDC_NOD_BUILDING02_ICON, IDC_NOD_BUILDING02_HEALTHBAR },
  113. { IDC_NOD_BUILDING03_ICON, IDC_NOD_BUILDING03_HEALTHBAR },
  114. { IDC_NOD_BUILDING04_ICON, IDC_NOD_BUILDING04_HEALTHBAR },
  115. { IDC_NOD_BUILDING05_ICON, IDC_NOD_BUILDING05_HEALTHBAR },
  116. { IDC_NOD_BUILDING06_ICON, IDC_NOD_BUILDING06_HEALTHBAR },
  117. };
  118. ////////////////////////////////////////////////////////////////
  119. //
  120. // CNCBattleInfoDialogClass
  121. //
  122. ////////////////////////////////////////////////////////////////
  123. CNCBattleInfoDialogClass::CNCBattleInfoDialogClass (void) :
  124. MenuDialogClass (IDD_CNC_BATTLE_INFO)
  125. {
  126. return ;
  127. }
  128. ////////////////////////////////////////////////////////////////
  129. //
  130. // ~CNCBattleInfoDialogClass
  131. //
  132. ////////////////////////////////////////////////////////////////
  133. CNCBattleInfoDialogClass::~CNCBattleInfoDialogClass (void)
  134. {
  135. GameInitMgrClass::Continue_Game ();
  136. return ;
  137. }
  138. ////////////////////////////////////////////////////////////////
  139. //
  140. // On_Init_Dialog
  141. //
  142. ////////////////////////////////////////////////////////////////
  143. void
  144. CNCBattleInfoDialogClass::On_Init_Dialog (void)
  145. {
  146. MenuDialogClass::On_Init_Dialog ();
  147. MouseMgrClass::Show_Cursor (false);
  148. //
  149. // Get a pointer to the list control
  150. //
  151. ListCtrlClass *list_ctrl = (ListCtrlClass *)Get_Dlg_Item (IDC_GDI_LIST_CTRL);
  152. if (list_ctrl != NULL) {
  153. //
  154. // Configure the columns
  155. //
  156. list_ctrl->Add_Column (TRANSLATE (IDS_MENU_RANK), 0.175F, Vector3 (1, 1, 1));
  157. list_ctrl->Add_Column (TRANSLATE (IDS_MENU_NAME), 0.425F, Vector3 (1, 1, 1));
  158. list_ctrl->Add_Column (TRANSLATE (IDS_MENU_KD_RATIO), 0.2F, Vector3 (1, 1, 1));
  159. list_ctrl->Add_Column (TRANSLATE (IDS_MENU_SCORE), 0.2F, Vector3 (1, 1, 1));
  160. Populate_Player_List (list_ctrl, PLAYERTYPE_GDI);
  161. }
  162. //
  163. // Get a pointer to the list control
  164. //
  165. list_ctrl = (ListCtrlClass *)Get_Dlg_Item (IDC_NOD_LIST_CTRL);
  166. if (list_ctrl != NULL) {
  167. //
  168. // Configure the columns
  169. //
  170. list_ctrl->Add_Column (TRANSLATE (IDS_MENU_RANK), 0.175F, Vector3 (1, 1, 1));
  171. list_ctrl->Add_Column (TRANSLATE (IDS_MENU_NAME), 0.425F, Vector3 (1, 1, 1));
  172. list_ctrl->Add_Column (TRANSLATE (IDS_MENU_KD_RATIO), 0.2F, Vector3 (1, 1, 1));
  173. list_ctrl->Add_Column (TRANSLATE (IDS_MENU_SCORE), 0.2F, Vector3 (1, 1, 1));
  174. Populate_Player_List (list_ctrl, PLAYERTYPE_NOD);
  175. }
  176. //
  177. // Setup the team and building icons on the dialog
  178. //
  179. Configure_Icons ();
  180. //
  181. // Activate the menu game mode (if necessary)
  182. //
  183. GameModeClass *menu_game_mode = GameModeManager::Find ("Menu");
  184. if (menu_game_mode != NULL && menu_game_mode->Is_Active () == false) {
  185. menu_game_mode->Activate ();
  186. }
  187. return ;
  188. }
  189. ////////////////////////////////////////////////////////////////
  190. //
  191. // Configure_Icons
  192. //
  193. ////////////////////////////////////////////////////////////////
  194. void
  195. CNCBattleInfoDialogClass::Configure_Icons (void)
  196. {
  197. BaseControllerClass *base = BaseControllerClass::Find_Base_For_Star ();
  198. if (base == NULL) {
  199. return ;
  200. }
  201. //
  202. // Configure the team icons
  203. //
  204. ((ImageCtrlClass *)Get_Dlg_Item (IDC_GDI_TEAM_ICON))->Set_Texture ("HUD_C&C_GDILOGO.TGA");
  205. ((ImageCtrlClass *)Get_Dlg_Item (IDC_NOD_TEAM_ICON))->Set_Texture ("HUD_C&C_NODLOGO.TGA");
  206. //
  207. // Find the two base controllers
  208. //
  209. BaseControllerClass *gdi_base = BaseControllerClass::Find_Base ( PLAYERTYPE_GDI );
  210. BaseControllerClass *nod_base = BaseControllerClass::Find_Base ( PLAYERTYPE_NOD );
  211. int next_slot = 0;
  212. //
  213. // Fill in the GDI buildings
  214. //
  215. for (int index = 0; index < BUILDING_COUNT; index ++) {
  216. //
  217. // Find the building
  218. //
  219. BuildingGameObj *building = gdi_base->Find_Building (GDI_BUILDINGS[index].type);
  220. if (building != NULL) {
  221. //
  222. // Configure the controls for this building
  223. //
  224. float life = building->Get_Defense_Object ()->Get_Health () / building->Get_Defense_Object ()->Get_Health_Max ();
  225. ImageCtrlClass *image_ctrl = (ImageCtrlClass *)Get_Dlg_Item (GDI_BUILDING_CTRLS[next_slot].icon_ctrl_id);
  226. HealthBarCtrlClass *health_ctrl = (HealthBarCtrlClass *)Get_Dlg_Item (GDI_BUILDING_CTRLS[next_slot].health_ctrl_id);
  227. image_ctrl->Set_Texture (GDI_BUILDINGS[index].texture_name);
  228. health_ctrl->Set_Life (life);
  229. next_slot ++;
  230. }
  231. }
  232. //
  233. // Now fill in the harvester
  234. //
  235. VehicleGameObj *gdi_harvester = gdi_base->Get_Harvester_Vehicle ();
  236. if (gdi_harvester != NULL) {
  237. float life = gdi_harvester->Get_Defense_Object ()->Get_Health () / gdi_harvester->Get_Defense_Object ()->Get_Health_Max ();
  238. ((ImageCtrlClass *)Get_Dlg_Item (GDI_BUILDING_CTRLS[next_slot].icon_ctrl_id))->Set_Texture ("HUD_C&C_G_HARVISTER.TGA");
  239. ((HealthBarCtrlClass *)Get_Dlg_Item (GDI_BUILDING_CTRLS[next_slot].health_ctrl_id))->Set_Life (life);
  240. next_slot ++;
  241. }
  242. //
  243. // Hide the remaining (unused) controls
  244. //
  245. for (index = next_slot; index < BUILDING_SLOT_COUNT; index ++) {
  246. Get_Dlg_Item (GDI_BUILDING_CTRLS[index].icon_ctrl_id)->Show (false);
  247. Get_Dlg_Item (GDI_BUILDING_CTRLS[index].health_ctrl_id)->Show (false);
  248. }
  249. //
  250. // Fill in the NOD buildings
  251. //
  252. next_slot = 0;
  253. for (index = 0; index < BUILDING_COUNT; index ++) {
  254. //
  255. // Find the building
  256. //
  257. BuildingGameObj *building = nod_base->Find_Building (NOD_BUILDINGS[index].type);
  258. if (building != NULL) {
  259. //
  260. // Configure the controls for this building
  261. //
  262. float life = building->Get_Defense_Object ()->Get_Health () / building->Get_Defense_Object ()->Get_Health_Max ();
  263. ((ImageCtrlClass *)Get_Dlg_Item (NOD_BUILDING_CTRLS[next_slot].icon_ctrl_id))->Set_Texture (NOD_BUILDINGS[index].texture_name);
  264. ((HealthBarCtrlClass *)Get_Dlg_Item (NOD_BUILDING_CTRLS[next_slot].health_ctrl_id))->Set_Life (life);
  265. next_slot ++;
  266. }
  267. }
  268. //
  269. // Now fill in the harvester
  270. //
  271. VehicleGameObj *nod_harvester = nod_base->Get_Harvester_Vehicle ();
  272. if (nod_harvester != NULL) {
  273. float life = nod_harvester->Get_Defense_Object ()->Get_Health () / nod_harvester->Get_Defense_Object ()->Get_Health_Max ();
  274. ((ImageCtrlClass *)Get_Dlg_Item (NOD_BUILDING_CTRLS[next_slot].icon_ctrl_id))->Set_Texture ("HUD_C&C_N_HARVISTER.TGA");
  275. ((HealthBarCtrlClass *)Get_Dlg_Item (NOD_BUILDING_CTRLS[next_slot].health_ctrl_id))->Set_Life (life);
  276. next_slot ++;
  277. }
  278. //
  279. // Hide the remaining (unused) controls
  280. //
  281. for (index = next_slot; index < BUILDING_SLOT_COUNT; index ++) {
  282. Get_Dlg_Item (NOD_BUILDING_CTRLS[index].icon_ctrl_id)->Show (false);
  283. Get_Dlg_Item (NOD_BUILDING_CTRLS[index].health_ctrl_id)->Show (false);
  284. }
  285. return ;
  286. }
  287. ////////////////////////////////////////////////////////////////
  288. //
  289. // Populate_Player_List
  290. //
  291. ////////////////////////////////////////////////////////////////
  292. void
  293. CNCBattleInfoDialogClass::Populate_Player_List (ListCtrlClass *list_ctrl, int team_id)
  294. {
  295. //
  296. // Find the player's name that most closely matches the typed name
  297. //
  298. int index = 0;
  299. for ( SLNode<cPlayer> *player_node = cPlayerManager::Get_Player_Object_List ()->Head ();
  300. player_node != NULL;
  301. player_node = player_node->Next ())
  302. {
  303. cPlayer *player = player_node->Data ();
  304. WWASSERT (player != NULL);
  305. if (player->Get_Is_Active().Is_False()) {
  306. continue;
  307. }
  308. //
  309. // Does this player belong to the same team?
  310. //
  311. if (player->Get_Player_Type () == team_id) {
  312. //
  313. // Make a new entry for this player
  314. //
  315. int item_index = list_ctrl->Insert_Entry (index ++, L"");
  316. if (item_index >= 0) {
  317. WideStringClass displayName(0, true);
  318. Build_Player_Display_Name(player, displayName);
  319. list_ctrl->Set_Entry_Text(item_index, COL_NAME, (const WCHAR*)displayName);
  320. list_ctrl->Set_Entry_Int (item_index, COL_RANK, player->Get_Rung ());
  321. list_ctrl->Set_Entry_Int (item_index, COL_SCORE, player->Get_Score ());
  322. //
  323. // Put a star by the player's name if this is the local player
  324. //
  325. if (player->Get_GameObj () == COMBAT_STAR) {
  326. list_ctrl->Add_Icon (item_index, COL_NAME, "IF_LRGSTAR.TGA");
  327. list_ctrl->Set_Entry_Color (item_index, COL_RANK, Vector3 (1.0F, 1.0F, 1.0F));
  328. list_ctrl->Set_Entry_Color (item_index, COL_NAME, Vector3 (1.0F, 1.0F, 1.0F));
  329. list_ctrl->Set_Entry_Color (item_index, COL_KD, Vector3 (1.0F, 1.0F, 1.0F));
  330. list_ctrl->Set_Entry_Color (item_index, COL_SCORE, Vector3 (1.0F, 1.0F, 1.0F));
  331. }
  332. //
  333. // Convert the kill to death ratio to a string and put it into the right column
  334. //
  335. WideStringClass number_str;
  336. float ktd_ratio = player->Get_Kill_To_Death_Ratio ();
  337. if (ktd_ratio >= 0) {
  338. number_str.Format(L"%-8.1f", ktd_ratio);
  339. } else {
  340. number_str.Format(L"%-8s", L"-");
  341. }
  342. list_ctrl->Set_Entry_Text (item_index, COL_KD, number_str);
  343. //
  344. // Set the ranking as this entries user data so we can sort by it...
  345. //
  346. list_ctrl->Set_Entry_Data (item_index, COL_RANK, player->Get_Rung ());
  347. }
  348. }
  349. }
  350. //
  351. // Now, sort the players by rank
  352. //
  353. list_ctrl->Sort (ListSortCallback, 0);
  354. //list_ctrl->Auto_Size_Columns_Include_Contents (4.0F);
  355. return ;
  356. }
  357. ////////////////////////////////////////////////////////////////
  358. //
  359. // ListSortCallback
  360. //
  361. ////////////////////////////////////////////////////////////////
  362. int CALLBACK
  363. CNCBattleInfoDialogClass::ListSortCallback
  364. (
  365. ListCtrlClass * list_ctrl,
  366. int item_index1,
  367. int item_index2,
  368. uint32 user_param
  369. )
  370. {
  371. int rank1 = (int)list_ctrl->Get_Entry_Data (item_index1, COL_RANK);
  372. int rank2 = (int)list_ctrl->Get_Entry_Data (item_index2, COL_RANK);
  373. return (rank1 - rank2);
  374. }
  375. ////////////////////////////////////////////////////////////////
  376. //
  377. // On_Frame_Update
  378. //
  379. ////////////////////////////////////////////////////////////////
  380. void
  381. CNCBattleInfoDialogClass::On_Frame_Update (void)
  382. {
  383. //
  384. // End the dialog when the user releases the player list key
  385. //
  386. int dik_id = Input::Get_Primary_Key_For_Function (INPUT_FUNCTION_BATTLE_INFO_TOGGLE);
  387. if ((DirectInput::Get_Keyboard_Button (dik_id) & DirectInput::DI_BUTTON_HELD) == 0) {
  388. End_Dialog ();
  389. }
  390. return ;
  391. }
  392. void CNCBattleInfoDialogClass::Build_Player_Display_Name(const cPlayer* player, WideStringClass& outName)
  393. {
  394. // Denzil 02/24/02 Day 1 Patch - Do not show clan abbreviation for now because
  395. // it does not always fit in the space alloted. For now it is better not to
  396. // show it than to have it chopped off.
  397. #if(0)
  398. GameModeClass* gameMode = GameModeManager::Find("WOL");
  399. if (gameMode && gameMode->Is_Active()) {
  400. WolGameModeClass* wolGame = static_cast<WolGameModeClass*>(gameMode);
  401. WWASSERT(wolGame);
  402. RefPtr<WWOnline::UserData> user = wolGame->Get_WOL_User_Data(player->Get_Name());
  403. if (user.IsValid()) {
  404. // Set there clan information
  405. RefPtr<WWOnline::SquadData> clan = user->GetSquad();
  406. if (clan.IsValid()) {
  407. outName.Format(L"%s [%S]", player->Get_Name(), clan->GetAbbr());
  408. return;
  409. }
  410. }
  411. }
  412. #endif
  413. outName = player->Get_Name();
  414. }