team.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  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/team.cpp $*
  25. * *
  26. * $Author:: Tom_s $*
  27. * *
  28. * $Modtime:: 2/05/02 11:22a $*
  29. * *
  30. * $Revision:: 58 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "team.h"
  36. #include <stdio.h>
  37. #include "teammanager.h"
  38. #include "miscutil.h"
  39. #include "cnetwork.h"
  40. #include "playermanager.h"
  41. #include "gamedata.h"
  42. #include "wwdebug.h"
  43. #include "useroptions.h"
  44. #include "playertype.h"
  45. #include "colors.h"
  46. #include "networkobjectfactory.h"
  47. #include "netclassids.h"
  48. #include "gameobjmanager.h"
  49. #include "translatedb.h"
  50. #include "string_ids.h"
  51. #include "multihud.h"
  52. #include "apppackettypes.h"
  53. #include "devoptions.h"
  54. #include "gamespyadmin.h"
  55. DECLARE_NETWORKOBJECT_FACTORY(cTeam, NETCLASSID_TEAM);
  56. //------------------------------------------------------------------------------------
  57. cTeam::cTeam(void)
  58. {
  59. Reset();
  60. Set_App_Packet_Type(APPPACKETTYPE_TEAM);
  61. cTeamManager::Add(this);
  62. }
  63. //------------------------------------------------------------------------------------
  64. cTeam::~cTeam(void)
  65. {
  66. //WWDEBUG_SAY(("* Destroying team object %d (%s)\n", TeamNumber, Name));
  67. }
  68. //------------------------------------------------------------------------------------
  69. void cTeam::Init(int team_number)//, WideStringClass & name)
  70. {
  71. WWASSERT(team_number >= 0 && team_number < MAX_TEAMS);
  72. WWASSERT(cNetwork::I_Am_Server());
  73. //WWDEBUG_SAY(("* Adding team object %d (%s)\n", team_number, name));
  74. Set_Object_Dirty_Bit(NetworkObjectClass::BIT_CREATION, true);
  75. /*
  76. //
  77. // This doesn't work because at this point we are not yet a client
  78. //
  79. if (cNetwork::I_Am_Client()) {
  80. //
  81. // Turn off for self
  82. //
  83. Set_Object_Dirty_Bit(cNetwork::Get_My_Id(), NetworkObjectClass::BIT_CREATION, false);
  84. }
  85. /**/
  86. TeamNumber = team_number;
  87. Init_Team_Name();
  88. //
  89. // Special-case the IDs because this code is executed before loading,
  90. // and in loading the dynamic range is reset.
  91. //
  92. if (TeamNumber == PLAYERTYPE_NOD) {
  93. Set_Network_ID(NETID_NOD_TEAM);
  94. } else {
  95. WWASSERT(TeamNumber == PLAYERTYPE_GDI);
  96. Set_Network_ID(NETID_GDI_TEAM);
  97. }
  98. }
  99. //------------------------------------------------------------------------------------
  100. void cTeam::Init_Team_Name(void)
  101. {
  102. if (TeamNumber == PLAYERTYPE_NOD) {
  103. Name = TRANSLATION(IDS_MP_TEAMNAME_MISSIONS_TEAM_0);
  104. } else {
  105. WWASSERT(TeamNumber == PLAYERTYPE_GDI);
  106. Name = TRANSLATION(IDS_MP_TEAMNAME_MISSIONS_TEAM_1);
  107. }
  108. }
  109. //------------------------------------------------------------------------------------
  110. void cTeam::Reset(void)
  111. {
  112. Kills = 0;
  113. Deaths = 0;
  114. Score = 0;
  115. Money = 0;
  116. Set_Object_Dirty_Bit(NetworkObjectClass::BIT_RARE, true);
  117. }
  118. //------------------------------------------------------------------------------------
  119. void cTeam::Set_Kills(int new_kills)
  120. {
  121. WWASSERT(cNetwork::I_Am_Only_Client());
  122. WWASSERT(new_kills >= 0);
  123. Kills = new_kills;
  124. Set_Object_Dirty_Bit(NetworkObjectClass::BIT_RARE, true);
  125. }
  126. //------------------------------------------------------------------------------------
  127. void cTeam::Set_Deaths(int new_deaths)
  128. {
  129. WWASSERT(cNetwork::I_Am_Only_Client());
  130. WWASSERT(new_deaths >= 0);
  131. Deaths = new_deaths;
  132. Set_Object_Dirty_Bit(NetworkObjectClass::BIT_RARE, true);
  133. }
  134. //------------------------------------------------------------------------------------
  135. void cTeam::Set_Score(float new_score)
  136. {
  137. //WWASSERT(cNetwork::I_Am_Only_Client());
  138. Score = new_score;
  139. Set_Object_Dirty_Bit(NetworkObjectClass::BIT_OCCASIONAL, true);
  140. }
  141. //------------------------------------------------------------------------------------
  142. int cTeam::Tally_Size(void) const
  143. {
  144. //
  145. // For the sake of simplicity/at the cost of efficiency, we calculate
  146. // team size, rather than storing and maintaining it.
  147. // To remind you of this I use "tally" instead of "get".
  148. //
  149. return cPlayerManager::Tally_Team_Size(TeamNumber);
  150. }
  151. //------------------------------------------------------------------------------------
  152. void cTeam::Increment_Kills(void)
  153. {
  154. if (!CombatManager::Is_Gameplay_Permitted()) {
  155. return;
  156. }
  157. WWASSERT(cNetwork::I_Am_Server());
  158. Kills++;
  159. Set_Object_Dirty_Bit(NetworkObjectClass::BIT_RARE, true);
  160. }
  161. //------------------------------------------------------------------------------------
  162. void cTeam::Increment_Deaths(void)
  163. {
  164. if (!CombatManager::Is_Gameplay_Permitted()) {
  165. return;
  166. }
  167. WWASSERT(cNetwork::I_Am_Server());
  168. Deaths++;
  169. Set_Object_Dirty_Bit(NetworkObjectClass::BIT_RARE, true);
  170. }
  171. //------------------------------------------------------------------------------------
  172. void cTeam::Increment_Score(float increment)
  173. {
  174. if (!CombatManager::Is_Gameplay_Permitted()) {
  175. return;
  176. }
  177. WWASSERT(cNetwork::I_Am_Server());
  178. Score += increment;
  179. Set_Object_Dirty_Bit(NetworkObjectClass::BIT_OCCASIONAL, true);
  180. }
  181. //------------------------------------------------------------------------------------
  182. float cTeam::Get_Kill_To_Death_Ratio(void) const
  183. {
  184. //
  185. // If Deaths = 0, return -1;
  186. //
  187. float ktd = -1;
  188. if (Deaths > 0) {
  189. ktd = Kills / (float) Deaths;
  190. }
  191. return ktd;
  192. }
  193. //------------------------------------------------------------------------------------
  194. void cTeam::Get_Team_String(int rank, WideStringClass & string) const
  195. {
  196. //
  197. // Compose a string description of a team's stats for display
  198. //
  199. string.Format(L"");
  200. WWASSERT(PTheGameData != NULL);
  201. //bool is_verbose = The_Game()->IsIntermission.Get() || MultiHUDClass::Get_Verbose_Lists();
  202. bool is_verbose = //force_verbose ||
  203. The_Game()->IsIntermission.Is_True() ||
  204. //MultiHUDClass::Get_Verbose_Lists();
  205. (MultiHUDClass::Get_Playerlist_Format() == PLAYERLIST_FORMAT_FULL);
  206. WideStringClass substring;
  207. //
  208. // Num Players
  209. //
  210. substring.Format(L"%-2d ", Tally_Size());
  211. string += substring;
  212. /*
  213. //
  214. // Standing
  215. //
  216. if (is_verbose) {
  217. substring.Format(L" %2d. ", rank);
  218. string += substring;
  219. }
  220. */
  221. //
  222. // Name
  223. //
  224. //GAMESPY
  225. //substring.Format(L"%-11s", Name);
  226. if (cGameSpyAdmin::Is_Gamespy_Game()) {
  227. substring.Format(L"%-36s", Name);
  228. } else {
  229. substring.Format(L"%-11s", Name);
  230. }
  231. string += substring;
  232. //
  233. // Kills
  234. //
  235. if (is_verbose) {
  236. substring.Format(L"%-8d", Kills);
  237. string += substring;
  238. }
  239. //
  240. // Deaths
  241. //
  242. if (is_verbose) {
  243. substring.Format(L"%-8d", Deaths);
  244. string += substring;
  245. }
  246. //
  247. // Kill to Death ratio
  248. //
  249. if (is_verbose) {
  250. float ktd = Get_Kill_To_Death_Ratio();
  251. if (ktd >= 0) {
  252. substring.Format(L"%-8.1f", ktd);
  253. } else {
  254. substring.Format(L"%-8s", "-");
  255. }
  256. string += substring;
  257. }
  258. /**/
  259. //
  260. // Money
  261. //
  262. WWASSERT(PTheGameData != NULL);
  263. if ((The_Game()->Is_Cnc() || The_Game()->Is_Skirmish()) && is_verbose) {
  264. #ifdef WWDEBUG
  265. bool show = cDevOptions::ShowMoney.Is_True() ||
  266. #else
  267. bool show =
  268. #endif // WWDEBUG
  269. cNetwork::I_Am_Only_Server() ||
  270. (cNetwork::I_Am_Client() &&
  271. cNetwork::Get_My_Player_Object() != NULL &&
  272. (cNetwork::Get_My_Team_Number() == TeamNumber));
  273. if (show) {
  274. substring.Format(L"%-8d", Tally_Money());
  275. } else {
  276. substring.Format(L"%-8s", "-");
  277. }
  278. string += substring;
  279. }
  280. /**/
  281. //
  282. // Score
  283. //
  284. substring.Format(L"%-8d", (int) Score);
  285. string += substring;
  286. }
  287. //------------------------------------------------------------------------------------
  288. Vector3 cTeam::Get_Color(void) const
  289. {
  290. return Get_Color_For_Team(TeamNumber);
  291. }
  292. //------------------------------------------------------------------------------------
  293. int cTeam::Tally_Money(void) const
  294. {
  295. int tally = 0;
  296. for ( SLNode<cPlayer> * player_node = cPlayerManager::Get_Player_Object_List()->Head();
  297. player_node != NULL;
  298. player_node = player_node->Next ())
  299. {
  300. cPlayer * p_player = player_node->Data();
  301. WWASSERT(p_player != NULL);
  302. if (p_player->Get_Is_Active().Is_True() &&
  303. p_player->Get_Player_Type() == TeamNumber)
  304. {
  305. tally += (int) p_player->Get_Money();
  306. }
  307. }
  308. return tally;
  309. }
  310. //------------------------------------------------------------------------------------
  311. void cTeam::Export_Creation(BitStreamClass &packet)
  312. {
  313. NetworkObjectClass::Export_Creation (packet);
  314. packet.Add(TeamNumber);
  315. //packet.Add_Wide_Terminated_String(Name);//XXX
  316. }
  317. //------------------------------------------------------------------------------------
  318. void cTeam::Import_Creation(BitStreamClass &packet)
  319. {
  320. NetworkObjectClass::Import_Creation(packet);
  321. packet.Get(TeamNumber);
  322. //packet.Get_Wide_Terminated_String(Name, sizeof(Name));
  323. //packet.Get_Wide_Terminated_String(Name.Get_Buffer(256), 256);
  324. Init_Team_Name();
  325. WWASSERT(cNetwork::I_Am_Only_Client());
  326. }
  327. //------------------------------------------------------------------------------------
  328. void cTeam::Export_Rare(BitStreamClass &packet)
  329. {
  330. packet.Add(Kills);
  331. packet.Add(Deaths);
  332. //packet.Add(Score);
  333. ////packet.Add(Money);
  334. }
  335. //------------------------------------------------------------------------------------
  336. void cTeam::Import_Rare(BitStreamClass &packet)
  337. {
  338. int placeholder = 0;
  339. //float float_placeholder = 0;
  340. Set_Kills( packet.Get(placeholder));
  341. Set_Deaths( packet.Get(placeholder));
  342. //Set_Score( packet.Get(float_placeholder));
  343. ////Set_Money( packet.Get(placeholder));
  344. }
  345. //------------------------------------------------------------------------------------
  346. void cTeam::Export_Occasional(BitStreamClass &packet)
  347. {
  348. packet.Add(Score);
  349. //packet.Add(Money);
  350. }
  351. //------------------------------------------------------------------------------------
  352. void cTeam::Import_Occasional(BitStreamClass &packet)
  353. {
  354. //int placeholder = 0;
  355. float float_placeholder = 0;
  356. Set_Score( packet.Get(float_placeholder));
  357. //Set_Money( packet.Get(placeholder));
  358. }
  359. //------------------------------------------------------------------------------------
  360. void cTeam::Export_Frequent(BitStreamClass &packet)
  361. {
  362. }
  363. //------------------------------------------------------------------------------------
  364. void cTeam::Import_Frequent(BitStreamClass &packet)
  365. {
  366. }
  367. //FlagCaps = 0;
  368. //FlagLosses = 0;