gdcnc.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  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. *** Confidential - Westwood Studios ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : Commando *
  23. * *
  24. * $Archive:: /Commando/Code/Commando/gdcnc.cpp $*
  25. * *
  26. * $Author:: Bhayes $*
  27. * *
  28. * $Modtime:: 4/15/02 4:12p $*
  29. * *
  30. * $Revision:: 47 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "gdcnc.h"
  36. #include "specialbuilds.h"
  37. #include "cnetwork.h"
  38. #include "translatedb.h"
  39. #include "string_ids.h"
  40. #include "assets.h"
  41. #include "multihud.h"
  42. #include "playerdata.h"
  43. #include "player.h"
  44. #include "playertype.h"
  45. #include "consolemode.h"
  46. //-----------------------------------------------------------------------------
  47. cGameDataCnc::cGameDataCnc(void) :
  48. IsPlaying (false),
  49. cGameData()
  50. {
  51. //WWDEBUG_SAY(("cGameDataCnc::cGameDataCnc\n"));
  52. Set_Time_Limit_Minutes(25);
  53. Set_Ini_Filename("svrcfg_cnc.ini");
  54. Set_Ip_And_Port();
  55. BaseDestructionEndsGame.Set(true);
  56. BeaconPlacementEndsGame.Set(true);
  57. StartingCredits = 0;
  58. IsTeamChangingAllowed.Set(false);
  59. RemixTeams.Set(true);
  60. Set_Radar_Mode(RADAR_TEAMMATES);
  61. }
  62. //-----------------------------------------------------------------------------
  63. cGameDataCnc::~cGameDataCnc(void)
  64. {
  65. //WWDEBUG_SAY(("cGameDataCnc::~cGameDataCnc\n"));
  66. }
  67. //-----------------------------------------------------------------------------
  68. cGameDataCnc& cGameDataCnc::operator=(const cGameDataCnc& rhs)
  69. {
  70. //
  71. // Call the base class
  72. //
  73. cGameData::operator=(rhs);
  74. BaseDestructionEndsGame = rhs.BaseDestructionEndsGame;
  75. BeaconPlacementEndsGame = rhs.BeaconPlacementEndsGame;
  76. StartingCredits = rhs.StartingCredits;
  77. return (*this);
  78. }
  79. //-----------------------------------------------------------------------------
  80. const WCHAR* cGameDataCnc::Get_Static_Game_Name(void)
  81. {
  82. return TRANSLATION(IDS_MP_GAME_TYPE_CNC);
  83. }
  84. //-----------------------------------------------------------------------------
  85. void cGameDataCnc::Reset_Game(bool is_reloaded)
  86. {
  87. WWDEBUG_SAY(("cGameDataCnc::Reset_Game\n"));
  88. cGameData::Reset_Game(is_reloaded);
  89. //
  90. // TSS091201 - hack - On_Game_End not called in correct places
  91. //
  92. if (IsPlaying) {
  93. BaseGDI.Shutdown ();
  94. BaseNOD.Shutdown ();
  95. IsPlaying = false;
  96. }
  97. //
  98. // Initialize the base controllers
  99. //
  100. BaseGDI.Initialize ( PLAYERTYPE_GDI );
  101. BaseNOD.Initialize ( PLAYERTYPE_NOD );
  102. return ;
  103. }
  104. //-----------------------------------------------------------------------------
  105. void
  106. cGameDataCnc::On_Game_Begin (void)
  107. {
  108. WWDEBUG_SAY(("cGameDataCnc::On_Game_Begin\n"));
  109. cGameData::On_Game_Begin();
  110. CombatManager::Set_Beacon_Placement_Ends_Game(BeaconPlacementEndsGame.Get());
  111. //
  112. // Initialize the bases
  113. //
  114. IsPlaying = true;
  115. return ;
  116. }
  117. //-----------------------------------------------------------------------------
  118. void
  119. cGameDataCnc::On_Game_End (void)
  120. {
  121. WWDEBUG_SAY(("cGameDataCnc::On_Game_End\n"));
  122. //
  123. // Close the bases
  124. //
  125. BaseGDI.Shutdown ();
  126. BaseNOD.Shutdown ();
  127. IsPlaying = false;
  128. cGameData::On_Game_End();
  129. return ;
  130. }
  131. //-----------------------------------------------------------------------------
  132. void
  133. cGameDataCnc::Soldier_Added (SoldierGameObj *soldier)
  134. {
  135. cGameData::Soldier_Added (soldier);
  136. //
  137. // Give the soldier some starting credits
  138. //
  139. if ( soldier != NULL &&
  140. soldier->Get_Player_Data() != NULL &&
  141. soldier->Get_Player_Data()->Get_Game_Time () == 0)
  142. {
  143. soldier->Get_Player_Data ()->Set_Money (StartingCredits);
  144. }
  145. return ;
  146. }
  147. //-----------------------------------------------------------------------------
  148. void cGameDataCnc::Think(void)
  149. {
  150. cGameData::Think();
  151. if (!cNetwork::I_Am_Server()) {
  152. return;
  153. }
  154. //
  155. // Let the bases think
  156. //
  157. if (IsPlaying) {
  158. BaseGDI.Think ();
  159. BaseNOD.Think ();
  160. }
  161. return ;
  162. }
  163. //-----------------------------------------------------------------------------
  164. void cGameDataCnc::Set_Starting_Credits(int credits)
  165. {
  166. Set_Generic_Num(credits, 0, MAX_CREDITS, StartingCredits);
  167. }
  168. //-----------------------------------------------------------------------------
  169. void cGameDataCnc::Export_Tier_2_Data(cPacket & packet)
  170. {
  171. cGameData::Export_Tier_2_Data(packet);
  172. packet.Add(BaseDestructionEndsGame.Get());
  173. packet.Add(BeaconPlacementEndsGame.Get());
  174. packet.Add(StartingCredits);
  175. }
  176. //-----------------------------------------------------------------------------
  177. void cGameDataCnc::Import_Tier_2_Data(cPacket & packet)
  178. {
  179. cGameData::Import_Tier_2_Data(packet);
  180. bool b_placeholder;
  181. int i_placeholder;
  182. BaseDestructionEndsGame.Set( packet.Get(b_placeholder));
  183. BeaconPlacementEndsGame.Set( packet.Get(b_placeholder));
  184. Set_Starting_Credits( packet.Get(i_placeholder));
  185. }
  186. //-----------------------------------------------------------------------------
  187. void cGameDataCnc::Base_Destruction_Score_Tweaking(void)
  188. {
  189. WWASSERT(cNetwork::I_Am_Server());
  190. cTeam * p_nod = cTeamManager::Find_Team(PLAYERTYPE_NOD);
  191. WWASSERT(p_nod != NULL);
  192. cTeam * p_gdi = cTeamManager::Find_Team(PLAYERTYPE_GDI);
  193. WWASSERT(p_gdi != NULL);
  194. float nod_score = p_nod->Get_Score();
  195. float gdi_score = p_gdi->Get_Score();
  196. const int BASE_DESTRUCTION_POINTS_REWARD = 5000;
  197. //
  198. // Base destroyer gets a points reward.
  199. // If this isn't enough to beat other team, nudge score ahead by 1 point.
  200. //
  201. if (BaseGDI.Is_Base_Destroyed()) {
  202. nod_score += BASE_DESTRUCTION_POINTS_REWARD;
  203. if (nod_score <= gdi_score) {
  204. nod_score = gdi_score + 1;
  205. }
  206. p_nod->Set_Score(nod_score);
  207. } else {
  208. WWASSERT(BaseNOD.Is_Base_Destroyed());
  209. gdi_score += BASE_DESTRUCTION_POINTS_REWARD;
  210. if (gdi_score <= nod_score) {
  211. gdi_score = nod_score + 1;
  212. }
  213. p_gdi->Set_Score(gdi_score);
  214. }
  215. }
  216. //-----------------------------------------------------------------------------
  217. bool cGameDataCnc::Is_Game_Over(void)
  218. {
  219. WWASSERT(cNetwork::I_Am_Server());
  220. bool is_game_over = cGameData::Is_Game_Over();
  221. if (!is_game_over && BaseDestructionEndsGame.Is_True())
  222. {
  223. //
  224. // If a base is destroyed then the game is over and the other team wins.
  225. // To ensure this we may need to tweak the base-destroyer's score.
  226. //
  227. if (BaseGDI.Is_Base_Destroyed() || BaseNOD.Is_Base_Destroyed()) {
  228. is_game_over = true;
  229. Base_Destruction_Score_Tweaking();
  230. if (BaseGDI.Did_Beacon_Destroy_Base() || BaseNOD.Did_Beacon_Destroy_Base()) {
  231. Set_Win_Type(WIN_TYPE_BEACON);
  232. } else {
  233. Set_Win_Type(WIN_TYPE_BASE_DESTRUCTION);
  234. }
  235. }
  236. }
  237. //
  238. // Beacon placement end game works via above base destruction method.
  239. //
  240. return is_game_over;
  241. }
  242. //-----------------------------------------------------------------------------
  243. void cGameDataCnc::Load_From_Server_Config(void)
  244. {
  245. cGameData::Load_From_Server_Config(Get_Ini_Filename());
  246. INIClass * p_ini = Get_INI(Get_Ini_Filename());
  247. WWASSERT(p_ini != NULL);
  248. bool b;
  249. int i;
  250. //float f;
  251. i = p_ini->Get_Int( INI_SECTION_NAME, "MaxPlayers", Get_Max_Players());
  252. Set_Max_Players(i);
  253. b = p_ini->Get_Bool( INI_SECTION_NAME, "IsFriendlyFirePermitted", IsFriendlyFirePermitted.Get());
  254. IsFriendlyFirePermitted.Set(b);
  255. b = p_ini->Get_Bool( INI_SECTION_NAME, "DoMapsLoop", DoMapsLoop);
  256. DoMapsLoop = b;
  257. b = p_ini->Get_Bool( INI_SECTION_NAME, "IsTeamChangingAllowed", IsTeamChangingAllowed.Get());
  258. IsTeamChangingAllowed.Set(b);
  259. b = p_ini->Get_Bool( INI_SECTION_NAME, "IsClanGame", IsClanGame.Get());
  260. IsClanGame.Set(b);
  261. b = p_ini->Get_Bool( INI_SECTION_NAME, "BaseDestructionEndsGame", BaseDestructionEndsGame.Get());
  262. BaseDestructionEndsGame.Set(b);
  263. b = p_ini->Get_Bool( INI_SECTION_NAME, "BeaconPlacementEndsGame", BeaconPlacementEndsGame.Get());
  264. BeaconPlacementEndsGame.Set(b);
  265. i = p_ini->Get_Int( INI_SECTION_NAME, "StartingCredits", Get_Starting_Credits());
  266. Set_Starting_Credits(i);
  267. Release_INI(p_ini);
  268. return ;
  269. }
  270. //-----------------------------------------------------------------------------
  271. void cGameDataCnc::Save_To_Server_Config(void)
  272. {
  273. cGameData::Save_To_Server_Config(Get_Ini_Filename());
  274. INIClass * p_ini = Get_INI(Get_Ini_Filename());
  275. WWASSERT(p_ini != NULL);
  276. p_ini->Put_Bool( INI_SECTION_NAME, "IsFriendlyFirePermitted", IsFriendlyFirePermitted.Get());
  277. p_ini->Put_Bool( INI_SECTION_NAME, "DoMapsLoop", DoMapsLoop);
  278. p_ini->Put_Bool( INI_SECTION_NAME, "IsTeamChangingAllowed", IsTeamChangingAllowed.Get());
  279. p_ini->Put_Bool( INI_SECTION_NAME, "IsClanGame", IsClanGame.Get());
  280. p_ini->Put_Int( INI_SECTION_NAME, "MaxPlayers", Get_Max_Players());
  281. p_ini->Put_Bool( INI_SECTION_NAME, "BaseDestructionEndsGame", BaseDestructionEndsGame.Get());
  282. p_ini->Put_Bool( INI_SECTION_NAME, "BeaconPlacementEndsGame", BeaconPlacementEndsGame.Get());
  283. p_ini->Put_Int( INI_SECTION_NAME, "StartingCredits", Get_Starting_Credits());
  284. Save_INI(p_ini, Get_Ini_Filename());
  285. Release_INI(p_ini);
  286. }
  287. //-----------------------------------------------------------------------------
  288. void cGameDataCnc::Show_My_Money(void)
  289. {
  290. if (cNetwork::I_Am_Client()) {
  291. cPlayer * p_player = cNetwork::Get_My_Player_Object();
  292. if (p_player != NULL) {
  293. WideStringClass text(0,true);
  294. text.Format(L"%s: %d",
  295. TRANSLATION(IDS_MP_MONEY), (int) p_player->Get_Money());
  296. Add_Bottom_Text(text);
  297. }
  298. }
  299. }
  300. //-----------------------------------------------------------------------------
  301. void cGameDataCnc::Show_Game_Settings_Limits(void)
  302. {
  303. /*
  304. if (IsIntermission.Is_True()) {
  305. return;
  306. }
  307. */
  308. Show_My_Money();
  309. cGameData::Show_Game_Settings_Limits();
  310. }
  311. //-----------------------------------------------------------------------------
  312. bool cGameDataCnc::Is_Limited(void) const
  313. {
  314. return Is_Time_Limit() || BaseDestructionEndsGame.Is_True();
  315. }
  316. //-----------------------------------------------------------------------------
  317. void cGameDataCnc::Get_Description(WideStringClass & description)
  318. {
  319. //
  320. // Call base class
  321. //
  322. cGameData::Get_Description(description);
  323. const WideStringClass delimiter = L"\t";
  324. const WideStringClass newline = L"\n";
  325. const WideStringClass yes = TRANSLATE(IDS_YES);
  326. const WideStringClass no = TRANSLATE(IDS_NO);
  327. WideStringClass attribute(0, true);
  328. WideStringClass value(0, true);
  329. //
  330. // Starting Credits
  331. //
  332. attribute = TRANSLATE(IDS_MENU_TEXT349);
  333. value.Format(L"%d", StartingCredits);
  334. description += (attribute + delimiter + value + newline);
  335. //
  336. // Base Destruction Ends Game
  337. //
  338. attribute = TRANSLATE(IDS_MENU_TEXT314);
  339. value = (BaseDestructionEndsGame.Get() ? yes : no);
  340. description += (attribute + delimiter + value + newline);
  341. //
  342. // Beacon Placement Ends Game
  343. //
  344. attribute = TRANSLATE(IDS_MENU_TEXT315);
  345. value = (BeaconPlacementEndsGame.Get() ? yes : no);
  346. description += (attribute + delimiter + value + newline);
  347. }
  348. #define PRINT_CONFIG_ERROR ConsoleBox.Print("File %s - Error:\r\n\t ", Get_Ini_Filename());
  349. //-----------------------------------------------------------------------------
  350. bool cGameDataCnc::Is_Valid_Settings(WideStringClass& outMsg, bool check_as_server)
  351. {
  352. /*
  353. ** Check the base settings first.
  354. */
  355. if (!cGameData::Is_Valid_Settings(outMsg, check_as_server)) {
  356. return(false);
  357. }
  358. #ifdef FREEDEDICATEDSERVER
  359. if (BaseDestructionEndsGame.Is_False() && BeaconPlacementEndsGame.Is_True()) {
  360. //cHelpText::Set(TRANSLATION(IDS_MP_GAMEMODE_NEEDS_LIMIT));
  361. PRINT_CONFIG_ERROR;
  362. ConsoleBox.Print("Cannot allow beacons to end game without base destruction ending game.\n\n");
  363. outMsg = TRANSLATE(IDS_HOPTERR_NO_GAMEEND);
  364. return false;
  365. }
  366. #endif
  367. return(true);
  368. }
  369. //-----------------------------------------------------------------------------
  370. bool cGameDataCnc::Is_Gameplay_Permitted(void)
  371. {
  372. bool permitted = cGameData::Is_Gameplay_Permitted();
  373. if (permitted && Get_Max_Players() > 1)
  374. {
  375. //
  376. // If your maxplayers is set to more than 1 then you must have an opponent.
  377. //
  378. permitted =
  379. cPlayerManager::Tally_Team_Size(PLAYERTYPE_NOD) > 0 &&
  380. cPlayerManager::Tally_Team_Size(PLAYERTYPE_GDI) > 0;
  381. }
  382. return permitted;
  383. }
  384. /*
  385. void cGameDataCnc::Get_Description(WideStringClass & description)
  386. {
  387. //
  388. // Call base class
  389. //
  390. cGameData::Get_Description(description);
  391. const WideStringClass newline = L"\n";
  392. const WideStringClass yes = L"yes";
  393. const WideStringClass no = L"no";
  394. WideStringClass line(0, true);
  395. line.Format(L"Starting Credits\t%d", StartingCredits);
  396. IDS_MENU_TEXT349
  397. description += line;
  398. description += newline;
  399. line.Format(L"Base Destruction Ends Game\t%s", BaseDestructionEndsGame.Get() ? yes : no);
  400. IDS_MENU_TEXT314
  401. description += line;
  402. description += newline;
  403. line.Format(L"Beacon Placement Ends Game\t%s", BeaconPlacementEndsGame.Get() ? yes : no);
  404. IDS_MENU_TEXT315
  405. description += line;
  406. description += newline;
  407. }
  408. */
  409. //-----------------------------------------------------------------------------