PlayerProfile.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code 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. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #pragma hdrstop
  21. #include "../idlib/precompiled.h"
  22. #pragma hdrstop
  23. #include "PlayerProfile.h"
  24. // After releasing a version to the market, here are limitations for compatibility:
  25. // - the major version should not ever change
  26. // - always add new items to the bottom of the save/load routine
  27. // - never remove or change the size of items, just stop using them or add new items to the end
  28. //
  29. // The biggest reason these limitations exist is because if a newer profile is created and then loaded with a GMC
  30. // version, we have to support it.
  31. const int16 PROFILE_TAG = ( 'D' << 8 ) | '3';
  32. const int8 PROFILE_VER_MAJOR = 10; // If this is changed, you should reset the minor version and remove all backward compatible code
  33. const int8 PROFILE_VER_MINOR = 0; // Within each major version, minor versions can be supported for backward compatibility
  34. class idPlayerProfileLocal : public idPlayerProfile {
  35. };
  36. idPlayerProfileLocal playerProfiles[MAX_INPUT_DEVICES];
  37. /*
  38. ========================
  39. Contains data that needs to be saved out on a per player profile basis, global for the lifetime of the player so
  40. the data can be shared across computers.
  41. - HUD tint colors
  42. - key bindings
  43. - etc...
  44. ========================
  45. */
  46. /*
  47. ========================
  48. idPlayerProfile * CreatePlayerProfile
  49. ========================
  50. */
  51. idPlayerProfile * idPlayerProfile::CreatePlayerProfile( int deviceIndex ) {
  52. playerProfiles[deviceIndex].SetDefaults();
  53. playerProfiles[deviceIndex].deviceNum = deviceIndex;
  54. return &playerProfiles[deviceIndex];
  55. }
  56. /*
  57. ========================
  58. idPlayerProfile::idPlayerProfile
  59. ========================
  60. */
  61. idPlayerProfile::idPlayerProfile() {
  62. SetDefaults();
  63. // Don't have these in SetDefaults because they're used for state management and SetDefaults is called when
  64. // loading the profile
  65. state = IDLE;
  66. requestedState = IDLE;
  67. deviceNum = -1;
  68. dirty = false;
  69. }
  70. /*
  71. ========================
  72. idPlayerProfile::SetDefaults
  73. ========================
  74. */
  75. void idPlayerProfile::SetDefaults() {
  76. achievementBits = 0;
  77. achievementBits2 = 0;
  78. dlcReleaseVersion = 0;
  79. stats.SetNum( MAX_PLAYER_PROFILE_STATS );
  80. for ( int i = 0; i < MAX_PLAYER_PROFILE_STATS; ++i ) {
  81. stats[i].i = 0;
  82. }
  83. leftyFlip = false;
  84. customConfig = false;
  85. configSet = 0;
  86. }
  87. /*
  88. ========================
  89. idPlayerProfile::~idPlayerProfile
  90. ========================
  91. */
  92. idPlayerProfile::~idPlayerProfile() {
  93. }
  94. /*
  95. ========================
  96. idPlayerProfile::Serialize
  97. ========================
  98. */
  99. bool idPlayerProfile::Serialize( idSerializer & ser ) {
  100. // NOTE:
  101. // See comments at top of file on versioning rules
  102. // Default to current tag/version
  103. int32 magicNumber = 0;
  104. magicNumber += PROFILE_TAG << 16;
  105. magicNumber += PROFILE_VER_MAJOR << 8;
  106. magicNumber += PROFILE_VER_MINOR;
  107. // Serialize version
  108. ser.SerializePacked( magicNumber );
  109. int16 tag = ( magicNumber >> 16 ) & 0xffff;
  110. int8 majorVersion = ( magicNumber >> 8 ) & 0xff;
  111. int8 minorVersion = magicNumber & 0xff; minorVersion;
  112. if ( tag != PROFILE_TAG ) {
  113. return false;
  114. }
  115. if ( majorVersion != PROFILE_VER_MAJOR ) {
  116. return false;
  117. }
  118. // Archived cvars (all the menu settings for Doom3 are archived cvars)
  119. idDict cvarDict;
  120. cvarSystem->MoveCVarsToDict( CVAR_ARCHIVE, cvarDict );
  121. cvarDict.Serialize( ser );
  122. if ( ser.IsReading() ) {
  123. // Never sync these cvars with Steam because they require an engine or video restart
  124. cvarDict.Delete( "r_fullscreen" );
  125. cvarDict.Delete( "r_vidMode" );
  126. cvarDict.Delete( "r_multisamples" );
  127. cvarDict.Delete( "com_engineHz" );
  128. cvarSystem->SetCVarsFromDict( cvarDict );
  129. common->StartupVariable( NULL );
  130. }
  131. // The dlcReleaseVersion is used to determine that new content is available
  132. ser.SerializePacked( dlcReleaseVersion );
  133. // New setting to save to make sure that we have or haven't seen this achievement before used to pass TRC R149d
  134. ser.Serialize( achievementBits );
  135. ser.Serialize( achievementBits2 );
  136. // Check to map sure we are on a valid map before we save, this helps prevent someone from creating a test map and
  137. // gaining a bunch of achievements from it
  138. int numStats = stats.Num();
  139. ser.SerializePacked( numStats );
  140. stats.SetNum( numStats );
  141. for ( int i = 0; i < numStats; ++i ) {
  142. ser.SerializePacked( stats[i].i );
  143. }
  144. ser.Serialize( leftyFlip );
  145. ser.Serialize( configSet );
  146. if ( ser.IsReading() ) {
  147. // Which binding is used on the console?
  148. ser.Serialize( customConfig );
  149. ExecConfig( false );
  150. if ( customConfig ) {
  151. for ( int i = 0; i < K_LAST_KEY; ++i ) {
  152. idStr bind;
  153. ser.SerializeString( bind );
  154. idKeyInput::SetBinding( i, bind.c_str() );
  155. }
  156. }
  157. } else {
  158. if ( !customConfig ) {
  159. ExecConfig( false );
  160. }
  161. customConfig = true;
  162. ser.Serialize( customConfig );
  163. for ( int i = 0; i < K_LAST_KEY; ++i ) {
  164. idStr bind = idKeyInput::GetBinding( i );
  165. ser.SerializeString( bind );
  166. }
  167. }
  168. return true;
  169. }
  170. /*
  171. ========================
  172. idPlayerProfile::StatSetInt
  173. ========================
  174. */
  175. void idPlayerProfile::StatSetInt( int s, int v ) {
  176. stats[s].i = v;
  177. MarkDirty( true );
  178. }
  179. /*
  180. ========================
  181. idPlayerProfile::StatSetFloat
  182. ========================
  183. */
  184. void idPlayerProfile::StatSetFloat( int s, float v ) {
  185. stats[s].f = v;
  186. MarkDirty( true );
  187. }
  188. /*
  189. ========================
  190. idPlayerProfile::StatGetInt
  191. ========================
  192. */
  193. int idPlayerProfile::StatGetInt( int s ) const {
  194. return stats[s].i;
  195. }
  196. /*
  197. ========================
  198. idPlayerProfile::StatGetFloat
  199. ========================
  200. */
  201. float idPlayerProfile::StatGetFloat( int s ) const {
  202. return stats[s].f;
  203. }
  204. /*
  205. ========================
  206. idPlayerProfile::SaveSettings
  207. ========================
  208. */
  209. void idPlayerProfile::SaveSettings( bool forceDirty ) {
  210. if ( state != SAVING ) {
  211. if ( forceDirty ) {
  212. MarkDirty( true );
  213. }
  214. if ( GetRequestedState() == IDLE && IsDirty() ) {
  215. SetRequestedState( SAVE_REQUESTED );
  216. }
  217. }
  218. }
  219. /*
  220. ========================
  221. idPlayerProfile::SaveSettings
  222. ========================
  223. */
  224. void idPlayerProfile::LoadSettings() {
  225. if ( state != LOADING ) {
  226. if ( verify( GetRequestedState() == IDLE ) ) {
  227. SetRequestedState( LOAD_REQUESTED );
  228. }
  229. }
  230. }
  231. /*
  232. ========================
  233. idPlayerProfile::SetAchievement
  234. ========================
  235. */
  236. void idPlayerProfile::SetAchievement( const int id ) {
  237. if ( id >= idAchievementSystem::MAX_ACHIEVEMENTS ) {
  238. assert( false ); // FIXME: add another set of achievement bit flags
  239. return;
  240. }
  241. uint64 mask = 0;
  242. if ( id < 64 ) {
  243. mask = achievementBits;
  244. achievementBits |= (int64)1 << id;
  245. mask = ~mask & achievementBits;
  246. } else {
  247. mask = achievementBits2;
  248. achievementBits2 |= (int64)1 << ( id - 64 );
  249. mask = ~mask & achievementBits2;
  250. }
  251. // Mark the profile dirty if achievement bits changed
  252. if ( mask != 0 ) {
  253. MarkDirty( true );
  254. }
  255. }
  256. /*
  257. ========================
  258. idPlayerProfile::ClearAchievement
  259. ========================
  260. */
  261. void idPlayerProfile::ClearAchievement( const int id ) {
  262. if ( id >= idAchievementSystem::MAX_ACHIEVEMENTS ) {
  263. assert( false ); // FIXME: add another set of achievement bit flags
  264. return;
  265. }
  266. if ( id < 64 ) {
  267. achievementBits &= ~( (int64)1 << id );
  268. } else {
  269. achievementBits2 &= ~( (int64)1 << ( id - 64 ) );
  270. }
  271. MarkDirty( true );
  272. }
  273. /*
  274. ========================
  275. idPlayerProfile::GetAchievement
  276. ========================
  277. */
  278. bool idPlayerProfile::GetAchievement( const int id ) const {
  279. if ( id >= idAchievementSystem::MAX_ACHIEVEMENTS ) {
  280. assert( false ); // FIXME: add another set of achievement bit flags
  281. return false;
  282. }
  283. if ( id < 64 ) {
  284. return ( achievementBits & (int64)1 << id ) != 0;
  285. } else {
  286. return ( achievementBits2 & (int64)1 << ( id - 64 ) ) != 0;
  287. }
  288. }
  289. /*
  290. ========================
  291. idPlayerProfile::SetConfig
  292. ========================
  293. */
  294. void idPlayerProfile::SetConfig( int config, bool save ) {
  295. configSet = config;
  296. ExecConfig( save );
  297. }
  298. /*
  299. ========================
  300. idPlayerProfile::SetConfig
  301. ========================
  302. */
  303. void idPlayerProfile::RestoreDefault() {
  304. ExecConfig( true, true );
  305. }
  306. /*
  307. ========================
  308. idPlayerProfile::SetLeftyFlip
  309. ========================
  310. */
  311. void idPlayerProfile::SetLeftyFlip( bool lf ) {
  312. leftyFlip = lf;
  313. ExecConfig( true );
  314. }
  315. /*
  316. ========================
  317. idPlayerProfile::ExecConfig
  318. ========================
  319. */
  320. void idPlayerProfile::ExecConfig( bool save, bool forceDefault ) {
  321. int flags = 0;
  322. if ( !save ) {
  323. flags = cvarSystem->GetModifiedFlags();
  324. }
  325. if ( !customConfig || forceDefault ) {
  326. cmdSystem->AppendCommandText( "exec default.cfg\n" );
  327. cmdSystem->AppendCommandText( "exec joy_360_0.cfg\n" );
  328. }
  329. if ( leftyFlip ) {
  330. cmdSystem->AppendCommandText( "exec joy_lefty.cfg" );
  331. } else {
  332. cmdSystem->AppendCommandText( "exec joy_righty.cfg" );
  333. }
  334. cmdSystem->ExecuteCommandBuffer();
  335. if ( !save ) {
  336. cvarSystem->ClearModifiedFlags( CVAR_ARCHIVE );
  337. cvarSystem->SetModifiedFlags( flags );
  338. }
  339. }
  340. CONSOLE_COMMAND( setProfileDefaults, "sets profile settings to default and saves", 0 ) {
  341. if ( session->GetSignInManager().GetMasterLocalUser() == NULL ) {
  342. return;
  343. }
  344. idPlayerProfile * profile = session->GetSignInManager().GetMasterLocalUser()->GetProfile();
  345. if ( verify( profile != NULL ) ) {
  346. profile->SetDefaults();
  347. profile->SaveSettings( true );
  348. }
  349. }