DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

PlayerProfile.cpp (10794B)


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