player.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104
  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/player.cpp $*
  25. * *
  26. * $Author:: Steve_t $*
  27. * *
  28. * $Modtime:: 10/17/02 11:04a $*
  29. * *
  30. * $Revision:: 146 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "player.h"
  36. #include <string.h>
  37. #include <stdio.h>
  38. #include "playermanager.h"
  39. #include "teammanager.h"
  40. #include "wwdebug.h"
  41. #include "miscutil.h"
  42. #include "cnetwork.h"
  43. #include "textdisplay.h"
  44. #include "WWAudio.H"
  45. #include "gamedata.h"
  46. #include "wwdebug.h"
  47. #include "chunkio.h"
  48. #include "useroptions.h"
  49. #include "smartgameobj.h"
  50. #include "playertype.h"
  51. #include "translatedb.h"
  52. #include "string_ids.h"
  53. #include "devoptions.h"
  54. #include "colors.h"
  55. #include "persistfactory.h"
  56. #include "combatchunkid.h"
  57. #include "networkobjectfactory.h"
  58. #include "gameobjmanager.h"
  59. #include "gametype.h"
  60. #include "multihud.h"
  61. #include "apppackettypes.h"
  62. #include "messagewindow.h"
  63. #include "playerkill.h"
  64. #include "consolemode.h"
  65. #include "gamespyadmin.h"
  66. DECLARE_NETWORKOBJECT_FACTORY(cPlayer, NETCLASSID_PLAYER);
  67. //
  68. // Class statics
  69. //
  70. const int cPlayer::INVALID_ID = -1000;
  71. //------------------------------------------------------------------------------------
  72. cPlayer::cPlayer(void) :
  73. ClanID(0),
  74. WOLPoints(0)
  75. {
  76. //WWDEBUG_SAY(("cPlayer::cPlayer\n"));
  77. Id = INVALID_ID;
  78. LadderPoints = 0;
  79. Kills = 0;
  80. Deaths = 0;
  81. Rung = 0;
  82. WolRank = -1;
  83. IpAddress = 0;
  84. Fps = 0;
  85. LastUpdateTimeMs = 0;
  86. DamageScaleFactor = 100;
  87. Ping = -1;
  88. FastSortKey = 0;
  89. NumWolGames = 0;
  90. Reset_Join_Time();
  91. Reset_Total_Time();
  92. Set_Is_In_Game(true);
  93. Set_Is_Waiting_For_Intermission(false);
  94. Set_App_Packet_Type(APPPACKETTYPE_PLAYER);
  95. Set_GameSpy_Auth_State(GAMESPY_AUTH_STATE_INITIAL);
  96. Set_GameSpy_Kick_State(GAMESPY_KICK_STATE_INITIAL);
  97. cPlayerManager::Add(this);
  98. }
  99. //------------------------------------------------------------------------------------
  100. cPlayer::~cPlayer(void)
  101. {
  102. //WWDEBUG_SAY(("* Destroying player object for client %d (%s)\n", Id, Name));
  103. //WWDEBUG_SAY(("cPlayer::~cPlayer\n"));
  104. cPlayerManager::Remove(this);
  105. }
  106. //------------------------------------------------------------------------------------
  107. void cPlayer::Delete(void)
  108. {
  109. delete this;
  110. }
  111. //------------------------------------------------------------------------------------
  112. void cPlayer::Init(void)
  113. {
  114. WWASSERT(cNetwork::I_Am_Server());
  115. Set_Object_Dirty_Bit(NetworkObjectClass::BIT_CREATION, true);
  116. }
  117. //-----------------------------------------------------------------------------
  118. enum {
  119. CHUNKID_VARIABLES = 12374,
  120. CHUNKID_PARENT,
  121. MICROCHUNK_ID = 1,
  122. MICROCHUNK_NAME,
  123. MICROCHUNK_PLAYERTYPE,
  124. MICROCHUNK_KILLS,
  125. MICROCHUNK_DEATHS,
  126. XXXMICROCHUNK_SCORE,
  127. MICROCHUNK_NUMLIVES,
  128. MICROCHUNK_TEAMNUMBER,
  129. MICROCHUNK_REMAP_POINTER,
  130. };
  131. //-----------------------------------------------------------------------------
  132. bool cPlayer::Save(ChunkSaveClass & csave)
  133. {
  134. csave.Begin_Chunk(CHUNKID_PARENT);
  135. PlayerDataClass::Save( csave );
  136. csave.End_Chunk();
  137. csave.Begin_Chunk(CHUNKID_VARIABLES);
  138. WRITE_MICRO_CHUNK(csave, MICROCHUNK_ID, Id);
  139. WRITE_MICRO_CHUNK_WIDESTRING(csave, MICROCHUNK_NAME, Name);
  140. WRITE_MICRO_CHUNK(csave, MICROCHUNK_KILLS, Kills());
  141. WRITE_MICRO_CHUNK(csave, MICROCHUNK_DEATHS, Deaths());
  142. WRITE_MICRO_CHUNK(csave, MICROCHUNK_TEAMNUMBER, PlayerType());
  143. void * old_ptr = this;
  144. WRITE_MICRO_CHUNK(csave, MICROCHUNK_REMAP_POINTER, old_ptr);
  145. csave.End_Chunk();
  146. return true;
  147. }
  148. //-----------------------------------------------------------------------------
  149. bool cPlayer::Load(ChunkLoadClass &cload)
  150. {
  151. void * old_ptr = NULL;
  152. while (cload.Open_Chunk()) {
  153. switch(cload.Cur_Chunk_ID()) {
  154. case CHUNKID_PARENT:
  155. PlayerDataClass::Load( cload );
  156. break;
  157. case CHUNKID_VARIABLES:
  158. while (cload.Open_Micro_Chunk()) {
  159. switch(cload.Cur_Micro_Chunk_ID()) {
  160. READ_MICRO_CHUNK(cload, MICROCHUNK_ID, Id);
  161. READ_MICRO_CHUNK_WIDESTRING(cload, MICROCHUNK_NAME, Name);
  162. READ_SAFE_MICRO_CHUNK(cload, MICROCHUNK_KILLS, Kills,int);
  163. READ_SAFE_MICRO_CHUNK(cload, MICROCHUNK_DEATHS, Deaths, int);
  164. READ_SAFE_MICRO_CHUNK(cload, MICROCHUNK_TEAMNUMBER, PlayerType, int);
  165. READ_MICRO_CHUNK(cload, MICROCHUNK_REMAP_POINTER, old_ptr);
  166. default:
  167. Debug_Say(( "Unrecognized cPlayer Variable chunkID\n" ));
  168. break;
  169. }
  170. cload.Close_Micro_Chunk();
  171. }
  172. break;
  173. default:
  174. Debug_Say(( "Unrecognized cPlayer chunkID\n" ));
  175. break;
  176. }
  177. cload.Close_Chunk();
  178. }
  179. if ( old_ptr != NULL ) {
  180. SaveLoadSystemClass::Register_Pointer(old_ptr, this);
  181. }
  182. return true;
  183. }
  184. //------------------------------------------------------------------------------------
  185. void cPlayer::On_Create(void)
  186. {
  187. WWASSERT(cNetwork::I_Am_Client());
  188. //
  189. // Don't show a join message unless:
  190. // - It's MP
  191. // - I am rendering
  192. // - It's not about me
  193. // - His join came after my join (the server will send you existing
  194. // players before your own).
  195. //
  196. if (!IS_MISSION && cPlayerManager::Is_Player_Present(cNetwork::Get_My_Id())) {
  197. WWASSERT(CombatManager::Get_Message_Window() != NULL);
  198. if (cNetwork::Show_Welcome_Message(Name)) {
  199. switch (PlayerType()) {
  200. case PLAYERTYPE_RENEGADE:
  201. {
  202. WideStringClass widestring;
  203. widestring.Format(
  204. L"%s, %s.\n",
  205. TRANSLATION(IDS_MP_WELCOME_RENEGADE),
  206. Name);
  207. //
  208. // Display the message...
  209. //
  210. CombatManager::Get_Message_Window ()->Add_Message (widestring, Vector3 (0.7F, 0.7F, 0.7F));
  211. break;
  212. }
  213. case PLAYERTYPE_NOD:
  214. case PLAYERTYPE_GDI:
  215. {
  216. WideStringClass widestring;
  217. WWASSERT(PTheGameData != NULL);
  218. if (The_Game()->IsTeamChangingAllowed.Is_True()) {
  219. widestring.Format(
  220. L"%s, %s.\n",
  221. TRANSLATION(IDS_MP_WELCOME_RENEGADE),
  222. Name);
  223. } else {
  224. widestring.Format(
  225. L"%s, %s, %s %s %s.\n",
  226. TRANSLATION(IDS_MP_WELCOME_RENEGADE),
  227. Name,
  228. TRANSLATION(IDS_MP_TO),
  229. The_Game()->Get_Team_Word(),
  230. cTeamManager::Get_Team_Name(PlayerType));
  231. }
  232. //
  233. // Display the message...
  234. //
  235. CombatManager::Get_Message_Window ()->Add_Message (widestring, Vector3 (0.7F, 0.7F, 0.7F));
  236. break;
  237. }
  238. default:
  239. DIE;
  240. }
  241. } else {
  242. switch (PlayerType()) {
  243. case PLAYERTYPE_MUTANT:
  244. case PLAYERTYPE_NEUTRAL:
  245. break;
  246. case PLAYERTYPE_RENEGADE:
  247. {
  248. WideStringClass widestring;
  249. widestring.Format(
  250. L"%s %s\n",
  251. Name,
  252. TRANSLATION(IDS_MP_RENEGADE_JOINS));
  253. //
  254. // Display the message...
  255. //
  256. CombatManager::Get_Message_Window ()->Add_Message (widestring, Vector3 (0.7F, 0.7F, 0.7F));
  257. break;
  258. }
  259. case PLAYERTYPE_NOD:
  260. case PLAYERTYPE_GDI:
  261. {
  262. WideStringClass widestring;
  263. WWASSERT(PTheGameData != NULL);
  264. if (The_Game()->IsTeamChangingAllowed.Is_True()) {
  265. widestring.Format(
  266. L"%s %s\n",
  267. Name,
  268. TRANSLATION(IDS_MP_RENEGADE_JOINS));
  269. } else {
  270. widestring.Format(
  271. L"%s %s %s %s\n",
  272. Name,
  273. TRANSLATION(IDS_MP_TEAMPLAYER_JOINS),
  274. The_Game()->Get_Team_Word(),
  275. cTeamManager::Get_Team_Name(PlayerType));
  276. }
  277. //
  278. // Display the message...
  279. //
  280. Vector3 color(0.7F, 0.7F, 0.7F);
  281. CombatManager::Get_Message_Window ()->Add_Message (widestring, color);
  282. break;
  283. }
  284. default:
  285. DIE;
  286. }
  287. }
  288. }
  289. }
  290. //------------------------------------------------------------------------------------
  291. void cPlayer::On_Destroy(void)
  292. {
  293. if (cNetwork::I_Am_Client() &&
  294. GameModeManager::Find("Combat")->Is_Active() &&
  295. The_Game() != NULL &&
  296. The_Game()->Is_Cnc()) {
  297. WideStringClass message;
  298. message.Format(
  299. L"%s %s\n",
  300. Name, TRANSLATION(IDS_MP_PLAYER_LEFT_GAME));
  301. //
  302. // Display the message...
  303. //
  304. CombatManager::Get_Message_Window ()->Add_Message (message, Vector3 (0.7F, 0.7F, 0.7F));
  305. }
  306. }
  307. //------------------------------------------------------------------------------------
  308. void cPlayer::Mark_As_Modified(void)
  309. {
  310. Set_Object_Dirty_Bit(NetworkObjectClass::BIT_RARE, true);
  311. }
  312. //------------------------------------------------------------------------------------
  313. void cPlayer::Set_Id(int id)
  314. {
  315. Id = id;
  316. Set_Object_Dirty_Bit(NetworkObjectClass::BIT_RARE, true);
  317. }
  318. //------------------------------------------------------------------------------------
  319. void cPlayer::Set_Name(const WideStringClass & name)
  320. {
  321. Name = name;
  322. Set_Object_Dirty_Bit(NetworkObjectClass::BIT_RARE, true);
  323. }
  324. //------------------------------------------------------------------------------------
  325. void cPlayer::Set_Player_Type(int type)
  326. {
  327. WWASSERT(type >= PLAYERTYPE_FIRST && type <= PLAYERTYPE_LAST);
  328. PlayerType = type;
  329. Set_Object_Dirty_Bit(NetworkObjectClass::BIT_RARE, true);
  330. }
  331. //-----------------------------------------------------------------------------
  332. bool cPlayer::Is_Team_Player(void)
  333. {
  334. return PlayerType == PLAYERTYPE_NOD || PlayerType == PLAYERTYPE_GDI;
  335. }
  336. //------------------------------------------------------------------------------------
  337. void cPlayer::Reset_Player(void)
  338. {
  339. //
  340. // Call base class
  341. //
  342. PlayerDataClass::Reset_Player();
  343. Set_Ladder_Points(0);
  344. Set_Kills(0);
  345. Set_Deaths(0);
  346. Reset_Join_Time();
  347. Reset_Total_Time();
  348. Set_Object_Dirty_Bit(NetworkObjectClass::BIT_RARE, true);
  349. }
  350. //------------------------------------------------------------------------------------
  351. Vector3 cPlayer::Get_Color(void) const
  352. {
  353. switch (PlayerType()) {
  354. case PLAYERTYPE_NEUTRAL:
  355. return COLOR_NEUTRAL;
  356. break;
  357. case PLAYERTYPE_RENEGADE:
  358. return COLOR_RENEGADE;
  359. break;
  360. case PLAYERTYPE_NOD:
  361. return Get_Color_For_Team(PLAYERTYPE_NOD);
  362. break;
  363. case PLAYERTYPE_GDI:
  364. return Get_Color_For_Team(PLAYERTYPE_GDI);
  365. break;
  366. default:
  367. //
  368. //TSS110101
  369. //This crashed the server in the beta test.
  370. //I don't know how we got here.
  371. //Try making it non-fatal.
  372. //
  373. //DIE;
  374. return COLOR_NEUTRAL; // avoid compiler warning
  375. }
  376. }
  377. //------------------------------------------------------------------------------------
  378. void cPlayer::Get_Player_String(int rank, WideStringClass & string, bool force_verbose)
  379. {
  380. //
  381. // Compose a string description of a player's stats for display
  382. //
  383. #pragma message("TODO: (TSS) Examine all wide string %s formatting for errors...")
  384. string.Format(L"");
  385. WWASSERT(The_Game() != NULL);
  386. bool is_verbose = force_verbose ||
  387. The_Game()->IsIntermission.Is_True() ||
  388. //MultiHUDClass::Get_Verbose_Lists();
  389. (MultiHUDClass::Get_Playerlist_Format() == PLAYERLIST_FORMAT_FULL);
  390. WideStringClass substring(0, true);
  391. //
  392. // Standing
  393. //
  394. //XXX substring.Format(L" %2d. ", rank);
  395. substring.Format(L" %2d. ", (int) Get_Rung());
  396. string += substring;
  397. //
  398. // Name
  399. //
  400. // GAMESPY
  401. /*
  402. if (IsActive.Is_True()) {
  403. substring.Format(L"%-11s", Name);
  404. } else {
  405. substring.Format(L"%-9s##", Name);
  406. }
  407. */
  408. if (cGameSpyAdmin::Is_Gamespy_Game()) {
  409. substring.Format(L"%-34s", Name);
  410. } else {
  411. substring.Format(L"%-9s", Name);
  412. }
  413. if (IsActive.Is_True()) {
  414. substring += L" ";
  415. } else {
  416. substring += L"##";
  417. }
  418. string += substring;
  419. if (IsInGame.Is_False()) {
  420. //
  421. // Don't show all the other details, just show "RELOADING"
  422. //
  423. substring.Format(L"%s", TRANSLATION(IDS_MP_LOADING));
  424. string += substring;
  425. return;
  426. }
  427. //
  428. // Kills
  429. //
  430. if (is_verbose) {
  431. substring.Format(L"%-8d", Get_Kills());
  432. string += substring;
  433. }
  434. //
  435. // Deaths
  436. //
  437. if (is_verbose) {
  438. substring.Format(L"%-8d", Get_Deaths());
  439. string += substring;
  440. }
  441. //
  442. // Kill to Death ratio
  443. //
  444. if (is_verbose) {
  445. float ktd = Get_Kill_To_Death_Ratio();
  446. if (ktd >= 0) {
  447. substring.Format(L"%-8.1f", ktd);
  448. } else {
  449. substring.Format(L"%-8s", "-");
  450. }
  451. string += substring;
  452. }
  453. //
  454. // Money.
  455. // Do not show other team's money.
  456. //
  457. WWASSERT(PTheGameData != NULL);
  458. if ((The_Game()->Is_Cnc() || The_Game()->Is_Skirmish()) && is_verbose) {
  459. #ifdef WWDEBUG
  460. bool show = cDevOptions::ShowMoney.Is_True() ||
  461. #else
  462. bool show =
  463. #endif // WWDEBUG
  464. cNetwork::I_Am_Only_Server() ||
  465. (cNetwork::I_Am_Client() &&
  466. cNetwork::Get_My_Player_Object() != NULL &&
  467. (cNetwork::Get_My_Team_Number() == (int) PlayerType));
  468. if (show) {
  469. substring.Format(L"%-8d", (int) Get_Money());
  470. } else {
  471. substring.Format(L"%-8s", "-");
  472. }
  473. string += substring;
  474. }
  475. //
  476. // Score
  477. //
  478. substring.Format(L"%-8d", (int) Get_Score());
  479. string += substring;
  480. //
  481. // Ladder Points
  482. //
  483. if (force_verbose && The_Game()->IsLaddered.Is_True()) {
  484. substring.Format(L"%-8d", Get_Ladder_Points());
  485. string += substring;
  486. }
  487. //
  488. // WOL rank
  489. //
  490. if (GameModeManager::Find("WOL")->Is_Active() && is_verbose) {
  491. if ((int)WolRank == -1) {
  492. substring.Format(L"%-8s", L" -");
  493. } else {
  494. substring.Format(L"%-8d", (int)WolRank);
  495. }
  496. string += substring;
  497. }
  498. #ifdef WWDEBUG
  499. //
  500. // Ping
  501. //
  502. if (cDevOptions::ShowPing.Is_True()) {
  503. /*
  504. int ping = Get_Avg_Ping();
  505. if (ping >= 0) {
  506. substring.Format(L"%-8d", ping);
  507. } else {
  508. substring.Format(L"%-8s", L"");
  509. }
  510. */
  511. int ping = Get_Ping();
  512. if (ping >= 0) {
  513. substring.Format(L"%-8d", ping);
  514. } else {
  515. substring.Format(L"%-8s", L"");
  516. }
  517. string += substring;
  518. }
  519. //
  520. // Player Id
  521. //
  522. if (cDevOptions::ShowId.Is_True()) {
  523. substring.Format(L"%-8d", Id);
  524. string += substring;
  525. }
  526. //
  527. // Fps
  528. //
  529. if (cNetwork::I_Am_Server() && cDevOptions::ShowClientFps.Is_True()) {
  530. substring.Format(L"%-8d", Fps);
  531. string += substring;
  532. }
  533. //
  534. // GameSpy auth. state
  535. //
  536. if (cNetwork::I_Am_Server() && cGameSpyAdmin::Is_Gamespy_Game() &&
  537. cDevOptions::ShowGameSpyAuthState.Is_True()) {
  538. WideStringClass wide_string;
  539. wide_string.Convert_From(cGameSpyAuthMgr::Describe_Auth_State(GameSpyAuthState));
  540. substring.Format(L"%-12s", wide_string);
  541. string += substring;
  542. }
  543. //
  544. // IP Address
  545. //
  546. if (cNetwork::I_Am_Server() && cDevOptions::ShowIpAddresses.Is_True()) {
  547. WideStringClass wide_ip;
  548. wide_ip.Convert_From(cNetUtil::Address_To_String(IpAddress));
  549. substring.Format(L"%-30s", wide_ip);
  550. string += substring;
  551. }
  552. #endif // WWDEBUG
  553. if (force_verbose) {
  554. //
  555. // Logged player list has no color so we need to show Nod/GDI
  556. //
  557. //substring.Format(L" T%d", (int) PlayerType);
  558. if (PlayerType == PLAYERTYPE_NOD) {
  559. substring.Format(L" %s", TRANSLATION(IDS_MP_TEAMNAME_MISSIONS_TEAM_0));
  560. } else {
  561. substring.Format(L" %s", TRANSLATION(IDS_MP_TEAMNAME_MISSIONS_TEAM_1));
  562. }
  563. string += substring;
  564. }
  565. }
  566. //------------------------------------------------------------------------------------
  567. void cPlayer::Set_Score(float score)
  568. {
  569. //
  570. // Call base class
  571. //
  572. PlayerDataClass::Set_Score(score);
  573. Set_Object_Dirty_Bit(NetworkObjectClass::BIT_OCCASIONAL, true);
  574. }
  575. //------------------------------------------------------------------------------------
  576. void cPlayer::Increment_Score(float add)
  577. {
  578. if (!CombatManager::Is_Gameplay_Permitted()) {
  579. return;
  580. }
  581. //
  582. // Call base class
  583. //
  584. PlayerDataClass::Increment_Score(add);
  585. //
  586. // If this player is on a team, increment the team score
  587. //
  588. if (Is_Team_Player()) {
  589. cTeam * p_team = cTeamManager::Find_Team(Get_Player_Type());
  590. WWASSERT(p_team != NULL);
  591. p_team->Increment_Score(add);
  592. }
  593. Set_Object_Dirty_Bit(NetworkObjectClass::BIT_OCCASIONAL, true);
  594. }
  595. //------------------------------------------------------------------------------------
  596. void cPlayer::Set_Money(float money)
  597. {
  598. //
  599. // Call base class
  600. //
  601. PlayerDataClass::Set_Money(money);
  602. Set_Object_Dirty_Bit(NetworkObjectClass::BIT_OCCASIONAL, true);
  603. }
  604. //------------------------------------------------------------------------------------
  605. void cPlayer::Increment_Money(float add)
  606. {
  607. if (!CombatManager::Is_Gameplay_Permitted()) {
  608. return;
  609. }
  610. //
  611. // Call base class
  612. //
  613. PlayerDataClass::Increment_Money(add);
  614. /*
  615. //
  616. // If this player is on a team, increment the team money
  617. //
  618. if (Is_Team_Player()) {
  619. cTeam * p_team = cTeamManager::Find_Team(Get_Player_Type());
  620. WWASSERT(p_team != NULL);
  621. p_team->Increment_Money(add);
  622. }
  623. */
  624. Set_Object_Dirty_Bit(NetworkObjectClass::BIT_OCCASIONAL, true);
  625. }
  626. //------------------------------------------------------------------------------------
  627. void cPlayer::Set_Ladder_Points(int points)
  628. {
  629. LadderPoints = points;
  630. Set_Object_Dirty_Bit(NetworkObjectClass::BIT_RARE, true);
  631. }
  632. //------------------------------------------------------------------------------------
  633. void cPlayer::Set_Kills(int new_kills)
  634. {
  635. WWASSERT(new_kills >= 0);
  636. Kills = new_kills;
  637. Set_Object_Dirty_Bit(NetworkObjectClass::BIT_OCCASIONAL, true);
  638. }
  639. //------------------------------------------------------------------------------------
  640. void cPlayer::Set_Deaths(int new_deaths)
  641. {
  642. WWASSERT(new_deaths >= 0);
  643. Deaths = new_deaths;
  644. Set_Object_Dirty_Bit(NetworkObjectClass::BIT_OCCASIONAL, true);
  645. }
  646. //------------------------------------------------------------------------------------
  647. void cPlayer::Set_Wol_Rank(int wol_rank)
  648. {
  649. WWASSERT(wol_rank >= -1);
  650. WolRank = wol_rank;
  651. Set_Object_Dirty_Bit(NetworkObjectClass::BIT_RARE, true);
  652. }
  653. //------------------------------------------------------------------------------------
  654. void cPlayer::Set_Rung(int rung)
  655. {
  656. WWASSERT(rung >= 0);
  657. Rung = rung;
  658. }
  659. //------------------------------------------------------------------------------------
  660. void cPlayer::Set_Damage_Scale_Factor(int factor)
  661. {
  662. WWASSERT(factor >= 0 && factor <= 100);
  663. DamageScaleFactor = factor;
  664. Set_Object_Dirty_Bit(NetworkObjectClass::BIT_RARE, true);
  665. }
  666. //------------------------------------------------------------------------------------
  667. void cPlayer::Reset_Join_Time(void)
  668. {
  669. JoinTimeMs = TIMEGETTIME();
  670. }
  671. //------------------------------------------------------------------------------------
  672. void cPlayer::Increment_Total_Time(void)
  673. {
  674. TotalTimeMs += (TIMEGETTIME() - JoinTimeMs);
  675. }
  676. //------------------------------------------------------------------------------------
  677. void cPlayer::Reset_Total_Time(void)
  678. {
  679. TotalTimeMs = 0;
  680. }
  681. //------------------------------------------------------------------------------------
  682. void cPlayer::Set_Ip_Address(ULONG ip_address)
  683. {
  684. WWASSERT(ip_address != 0);
  685. WWDEBUG_SAY(("cPlayer::Set_Ip_Address to %s\n",
  686. cNetUtil::Address_To_String(ip_address)));
  687. IpAddress = ip_address;
  688. }
  689. //------------------------------------------------------------------------------------
  690. void cPlayer::Set_Fps(int fps)
  691. {
  692. WWASSERT(fps >= 0);
  693. Fps = fps;
  694. }
  695. //------------------------------------------------------------------------------------
  696. void cPlayer::Set_Last_Update_Time_Ms(DWORD time_ms)
  697. {
  698. LastUpdateTimeMs = time_ms;
  699. }
  700. //------------------------------------------------------------------------------------
  701. float cPlayer::Get_Kill_To_Death_Ratio(void) const
  702. {
  703. //
  704. // If Deaths = 0, return -1;
  705. //
  706. float ktd = -1;
  707. if ((int) Deaths > 0) {
  708. ktd = ((int) Kills) / (float) ((int)Deaths);
  709. }
  710. return ktd;
  711. }
  712. //------------------------------------------------------------------------------------
  713. void cPlayer::Increment_Kills(void)
  714. {
  715. if (!CombatManager::Is_Gameplay_Permitted()) {
  716. return;
  717. }
  718. WWASSERT(cNetwork::I_Am_Server());
  719. Set_Kills((int)Kills + 1);
  720. }
  721. //------------------------------------------------------------------------------------
  722. void cPlayer::Increment_Deaths(void)
  723. {
  724. if (!CombatManager::Is_Gameplay_Permitted()) {
  725. return;
  726. }
  727. WWASSERT(cNetwork::I_Am_Server());
  728. Set_Deaths((int)Deaths + 1);
  729. }
  730. /*
  731. //------------------------------------------------------------------------------------
  732. int cPlayer::Get_Avg_Ping(void) const
  733. {
  734. //
  735. // If you are a server this method will return the player's S->C ping.
  736. // If you are a client this method will return your own C->S ping, and
  737. // -1 for anyone else.
  738. //
  739. int ping = -1;
  740. if (cNetwork::I_Am_Server()) {
  741. if (Id > 0) {
  742. cRemoteHost * p_rhost = cNetwork::Get_Server_Rhost(Id);
  743. WWASSERT(p_rhost != NULL);
  744. ping = p_rhost->Get_Average_Internal_Pingtime_Ms();
  745. }
  746. } else if (Id == cNetwork::Get_My_Id()) {
  747. WWASSERT(cNetwork::I_Am_Only_Client());
  748. cRemoteHost * p_rhost = cNetwork::Get_Client_Rhost();
  749. if (p_rhost != NULL) {
  750. //
  751. // It can be NULL as you are quitting
  752. //
  753. ping = p_rhost->Get_Average_Internal_Pingtime_Ms();
  754. }
  755. }
  756. return ping;
  757. }
  758. */
  759. //------------------------------------------------------------------------------------
  760. int cPlayer::Get_Ping(void)
  761. {
  762. //
  763. // Update the ping if we are the server.
  764. //
  765. if (cNetwork::I_Am_Server() && Id > 0) {
  766. cRemoteHost * p_rhost = cNetwork::Get_Server_Rhost(Id);
  767. if (p_rhost != NULL) {
  768. Ping = p_rhost->Get_Average_Internal_Pingtime_Ms();
  769. }
  770. }
  771. return Ping;
  772. }
  773. //------------------------------------------------------------------------------------
  774. void cPlayer::Export_Creation(BitStreamClass &packet)
  775. {
  776. NetworkObjectClass::Export_Creation(packet);
  777. packet.Add_Wide_Terminated_String(Name);
  778. }
  779. //------------------------------------------------------------------------------------
  780. void cPlayer::Import_Creation(BitStreamClass &packet)
  781. {
  782. NetworkObjectClass::Import_Creation(packet);
  783. WWASSERT(cNetwork::I_Am_Only_Client());
  784. packet.Get_Wide_Terminated_String(Name.Get_Buffer(256), 256);
  785. }
  786. //------------------------------------------------------------------------------------
  787. void cPlayer::Export_Rare(BitStreamClass &packet)
  788. {
  789. packet.Add(Id);
  790. packet.Add((int)LadderPoints);
  791. packet.Add((int)PlayerType);
  792. packet.Add(DamageScaleFactor);
  793. packet.Add(Get_Ping());
  794. packet.Add(IsInGame.Get());
  795. packet.Add(Invulnerable.Get());
  796. packet.Add(IsActive.Get());
  797. packet.Add((int)WolRank);
  798. packet.Add(NumWolGames);
  799. //WWDEBUG_SAY(("cPlayer::Export_Rare NumWolGames = %d\n", NumWolGames));
  800. }
  801. //------------------------------------------------------------------------------------
  802. void cPlayer::Import_Rare(BitStreamClass &packet)
  803. {
  804. int int_placeholder = 0;
  805. Set_Id( packet.Get(int_placeholder));
  806. Set_Ladder_Points( packet.Get(int_placeholder));
  807. Set_Player_Type( packet.Get(int_placeholder));
  808. Set_Damage_Scale_Factor( packet.Get(int_placeholder));
  809. Set_Ping( packet.Get(int_placeholder));
  810. bool bool_placeholder = false;
  811. Set_Is_In_Game( packet.Get(bool_placeholder));
  812. Invulnerable.Set( packet.Get(bool_placeholder));
  813. Set_Is_Active( packet.Get(bool_placeholder));
  814. WolRank = packet.Get(int_placeholder);
  815. NumWolGames = packet.Get(int_placeholder);
  816. }
  817. //------------------------------------------------------------------------------------
  818. void cPlayer::Export_Occasional(BitStreamClass &packet)
  819. {
  820. //
  821. // Call the base class
  822. //
  823. PlayerDataClass::Export_Occasional(packet);
  824. packet.Add((int)Kills);
  825. packet.Add((int)Deaths);
  826. }
  827. //------------------------------------------------------------------------------------
  828. void cPlayer::Import_Occasional(BitStreamClass &packet)
  829. {
  830. //
  831. // Call the base class
  832. //
  833. PlayerDataClass::Import_Occasional(packet);
  834. int int_placeholder = 0;
  835. Set_Kills( packet.Get(int_placeholder));
  836. Set_Deaths( packet.Get(int_placeholder));
  837. }
  838. //------------------------------------------------------------------------------------
  839. void cPlayer::Set_Is_In_Game(bool state)
  840. {
  841. IsInGame.Set(state);
  842. Set_Object_Dirty_Bit(NetworkObjectClass::BIT_RARE, true);
  843. }
  844. //------------------------------------------------------------------------------------
  845. void cPlayer::Set_Is_Waiting_For_Intermission(bool state)
  846. {
  847. IsWaitingForIntermission.Set(state);
  848. }
  849. //------------------------------------------------------------------------------------
  850. void cPlayer::Set_Is_Active(bool flag)
  851. {
  852. if (flag != IsActive.Get()) {
  853. if (cNetwork::I_Am_Client()) {
  854. if (flag == true) {
  855. On_Create();
  856. cPlayerManager::Activated(this);
  857. } else {
  858. On_Destroy();
  859. cPlayerManager::Deactivated(this);
  860. }
  861. }
  862. if (IsActive.Is_False()) {
  863. //
  864. // Anyone who leaves will need to be reauthenticated next tim ethey attempt
  865. // to join.
  866. //
  867. Set_GameSpy_Auth_State(GAMESPY_AUTH_STATE_INITIAL);
  868. Set_GameSpy_Kick_State(GAMESPY_KICK_STATE_INITIAL);
  869. }
  870. IsActive.Set(flag);
  871. Set_Object_Dirty_Bit(NetworkObjectClass::BIT_RARE, true);
  872. }
  873. }
  874. //------------------------------------------------------------------------------------
  875. bool cPlayer::Is_Alive_And_Kicking(void) const
  876. {
  877. //
  878. // Abbreviates those players who are human, loaded, and active.
  879. //
  880. return Is_Human() && IsInGame.Is_True() && IsActive.Is_True();
  881. }
  882. //------------------------------------------------------------------------------------
  883. void cPlayer::Set_Num_Wol_Games(int num_games)
  884. {
  885. NumWolGames = num_games;
  886. //WWDEBUG_SAY(("Set_Num_Wol_Games NumWolGames = %d\n", NumWolGames));
  887. Set_Object_Dirty_Bit(NetworkObjectClass::BIT_RARE, true);
  888. }
  889. //------------------------------------------------------------------------------------
  890. void cPlayer::Set_GameSpy_Auth_State(GAMESPY_AUTH_STATE_ENUM state)
  891. {
  892. if (state != GameSpyAuthState)
  893. {
  894. GameSpyAuthState = state;
  895. GameSpyAuthStateEntryTimeMs = TIMEGETTIME();
  896. }
  897. }
  898. //------------------------------------------------------------------------------------
  899. void cPlayer::Set_GameSpy_Auth_State_Entry_Time_Ms(DWORD time_ms)
  900. {
  901. GameSpyAuthStateEntryTimeMs = time_ms;
  902. }
  903. //------------------------------------------------------------------------------------
  904. void cPlayer::Set_GameSpy_Challenge_String(StringClass & challenge_string)
  905. {
  906. WWASSERT(!challenge_string.Is_Empty());
  907. GameSpyChallengeString = challenge_string;
  908. }
  909. //------------------------------------------------------------------------------------
  910. void cPlayer::Set_GameSpy_Hash_Id(StringClass & hash_id)
  911. {
  912. WWASSERT(!hash_id.Is_Empty());
  913. GameSpyHashId = hash_id;
  914. }
  915. //------------------------------------------------------------------------------------
  916. void cPlayer::Set_GameSpy_Kick_State(GAMESPY_KICK_STATE_ENUM state)
  917. {
  918. if (state != GameSpyKickState)
  919. {
  920. GameSpyKickState = state;
  921. GameSpyKickStateEntryTimeMs = TIMEGETTIME();
  922. }
  923. }
  924. //------------------------------------------------------------------------------------
  925. void cPlayer::Set_GameSpy_Kick_State_Entry_Time_Ms(DWORD time_ms)
  926. {
  927. GameSpyKickStateEntryTimeMs = time_ms;
  928. }