doom3-bfg/neo/framework/PlayerProfile.cpp

467 lines
11 KiB
C++

/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
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.
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.
===========================================================================
*/
#pragma hdrstop
#include "precompiled.h"
#pragma hdrstop
#include "PlayerProfile.h"
// After releasing a version to the market, here are limitations for compatibility:
// - the major version should not ever change
// - always add new items to the bottom of the save/load routine
// - never remove or change the size of items, just stop using them or add new items to the end
//
// The biggest reason these limitations exist is because if a newer profile is created and then loaded with a GMC
// version, we have to support it.
const int16 PROFILE_TAG = ( 'D' << 8 ) | '3';
const int8 PROFILE_VER_MAJOR = 10; // If this is changed, you should reset the minor version and remove all backward compatible code
const int8 PROFILE_VER_MINOR = 0; // Within each major version, minor versions can be supported for backward compatibility
class idPlayerProfileLocal : public idPlayerProfile
{
};
idPlayerProfileLocal playerProfiles[MAX_INPUT_DEVICES];
/*
========================
Contains data that needs to be saved out on a per player profile basis, global for the lifetime of the player so
the data can be shared across computers.
- HUD tint colors
- key bindings
- etc...
========================
*/
/*
========================
idPlayerProfile * CreatePlayerProfile
========================
*/
idPlayerProfile* idPlayerProfile::CreatePlayerProfile( int deviceIndex )
{
playerProfiles[deviceIndex].SetDefaults();
playerProfiles[deviceIndex].deviceNum = deviceIndex;
return &playerProfiles[deviceIndex];
}
/*
========================
idPlayerProfile::idPlayerProfile
========================
*/
idPlayerProfile::idPlayerProfile()
{
SetDefaults();
// Don't have these in SetDefaults because they're used for state management and SetDefaults is called when
// loading the profile
state = IDLE;
requestedState = IDLE;
deviceNum = -1;
dirty = false;
}
/*
========================
idPlayerProfile::SetDefaults
========================
*/
void idPlayerProfile::SetDefaults()
{
achievementBits = 0;
achievementBits2 = 0;
dlcReleaseVersion = 0;
stats.SetNum( MAX_PLAYER_PROFILE_STATS );
for( int i = 0; i < MAX_PLAYER_PROFILE_STATS; ++i )
{
stats[i].i = 0;
}
leftyFlip = false;
customConfig = false;
configSet = 0;
}
/*
========================
idPlayerProfile::~idPlayerProfile
========================
*/
idPlayerProfile::~idPlayerProfile()
{
}
/*
========================
idPlayerProfile::Serialize
========================
*/
bool idPlayerProfile::Serialize( idSerializer& ser )
{
// NOTE:
// See comments at top of file on versioning rules
// Default to current tag/version
int32 magicNumber = 0;
magicNumber += PROFILE_TAG << 16;
magicNumber += PROFILE_VER_MAJOR << 8;
magicNumber += PROFILE_VER_MINOR;
// Serialize version
ser.SerializePacked( magicNumber );
int16 tag = ( magicNumber >> 16 ) & 0xffff;
int8 majorVersion = ( magicNumber >> 8 ) & 0xff;
int8 minorVersion = magicNumber & 0xff;
minorVersion;
if( tag != PROFILE_TAG )
{
return false;
}
if( majorVersion != PROFILE_VER_MAJOR )
{
return false;
}
// Archived cvars (all the menu settings for Doom3 are archived cvars)
idDict cvarDict;
cvarSystem->MoveCVarsToDict( CVAR_ARCHIVE, cvarDict );
cvarDict.Serialize( ser );
if( ser.IsReading() )
{
// Never sync these cvars with Steam because they require an engine or video restart
cvarDict.Delete( "r_fullscreen" );
cvarDict.Delete( "r_vidMode" );
cvarDict.Delete( "r_multisamples" );
cvarDict.Delete( "com_engineHz" );
cvarSystem->SetCVarsFromDict( cvarDict );
common->StartupVariable( NULL );
}
// The dlcReleaseVersion is used to determine that new content is available
ser.SerializePacked( dlcReleaseVersion );
// New setting to save to make sure that we have or haven't seen this achievement before used to pass TRC R149d
ser.Serialize( achievementBits );
ser.Serialize( achievementBits2 );
// Check to map sure we are on a valid map before we save, this helps prevent someone from creating a test map and
// gaining a bunch of achievements from it
int numStats = stats.Num();
ser.SerializePacked( numStats );
stats.SetNum( numStats );
for( int i = 0; i < numStats; ++i )
{
ser.SerializePacked( stats[i].i );
}
ser.Serialize( leftyFlip );
ser.Serialize( configSet );
if( ser.IsReading() )
{
// Which binding is used on the console?
ser.Serialize( customConfig );
ExecConfig( false );
if( customConfig )
{
for( int i = 0; i < K_LAST_KEY; ++i )
{
idStr bind;
ser.SerializeString( bind );
idKeyInput::SetBinding( i, bind.c_str() );
}
}
}
else
{
if( !customConfig )
{
ExecConfig( false );
}
customConfig = true;
ser.Serialize( customConfig );
for( int i = 0; i < K_LAST_KEY; ++i )
{
idStr bind = idKeyInput::GetBinding( i );
ser.SerializeString( bind );
}
}
return true;
}
/*
========================
idPlayerProfile::StatSetInt
========================
*/
void idPlayerProfile::StatSetInt( int s, int v )
{
stats[s].i = v;
MarkDirty( true );
}
/*
========================
idPlayerProfile::StatSetFloat
========================
*/
void idPlayerProfile::StatSetFloat( int s, float v )
{
stats[s].f = v;
MarkDirty( true );
}
/*
========================
idPlayerProfile::StatGetInt
========================
*/
int idPlayerProfile::StatGetInt( int s ) const
{
return stats[s].i;
}
/*
========================
idPlayerProfile::StatGetFloat
========================
*/
float idPlayerProfile::StatGetFloat( int s ) const
{
return stats[s].f;
}
/*
========================
idPlayerProfile::SaveSettings
========================
*/
void idPlayerProfile::SaveSettings( bool forceDirty )
{
if( state != SAVING )
{
if( forceDirty )
{
MarkDirty( true );
}
if( GetRequestedState() == IDLE && IsDirty() )
{
SetRequestedState( SAVE_REQUESTED );
}
}
}
/*
========================
idPlayerProfile::SaveSettings
========================
*/
void idPlayerProfile::LoadSettings()
{
if( state != LOADING )
{
if( verify( GetRequestedState() == IDLE ) )
{
SetRequestedState( LOAD_REQUESTED );
}
}
}
/*
========================
idPlayerProfile::SetAchievement
========================
*/
void idPlayerProfile::SetAchievement( const int id )
{
if( id >= idAchievementSystem::MAX_ACHIEVEMENTS )
{
assert( false ); // FIXME: add another set of achievement bit flags
return;
}
uint64 mask = 0;
if( id < 64 )
{
mask = achievementBits;
achievementBits |= ( int64 )1 << id;
mask = ~mask & achievementBits;
}
else
{
mask = achievementBits2;
achievementBits2 |= ( int64 )1 << ( id - 64 );
mask = ~mask & achievementBits2;
}
// Mark the profile dirty if achievement bits changed
if( mask != 0 )
{
MarkDirty( true );
}
}
/*
========================
idPlayerProfile::ClearAchievement
========================
*/
void idPlayerProfile::ClearAchievement( const int id )
{
if( id >= idAchievementSystem::MAX_ACHIEVEMENTS )
{
assert( false ); // FIXME: add another set of achievement bit flags
return;
}
if( id < 64 )
{
achievementBits &= ~( ( int64 )1 << id );
}
else
{
achievementBits2 &= ~( ( int64 )1 << ( id - 64 ) );
}
MarkDirty( true );
}
/*
========================
idPlayerProfile::GetAchievement
========================
*/
bool idPlayerProfile::GetAchievement( const int id ) const
{
if( id >= idAchievementSystem::MAX_ACHIEVEMENTS )
{
assert( false ); // FIXME: add another set of achievement bit flags
return false;
}
if( id < 64 )
{
return ( achievementBits & ( int64 )1 << id ) != 0;
}
else
{
return ( achievementBits2 & ( int64 )1 << ( id - 64 ) ) != 0;
}
}
/*
========================
idPlayerProfile::SetConfig
========================
*/
void idPlayerProfile::SetConfig( int config, bool save )
{
configSet = config;
ExecConfig( save );
}
/*
========================
idPlayerProfile::SetConfig
========================
*/
void idPlayerProfile::RestoreDefault()
{
ExecConfig( true, true );
}
/*
========================
idPlayerProfile::SetLeftyFlip
========================
*/
void idPlayerProfile::SetLeftyFlip( bool lf )
{
leftyFlip = lf;
ExecConfig( true );
}
/*
========================
idPlayerProfile::ExecConfig
========================
*/
void idPlayerProfile::ExecConfig( bool save, bool forceDefault )
{
int flags = 0;
if( !save )
{
flags = cvarSystem->GetModifiedFlags();
}
if( !customConfig || forceDefault )
{
cmdSystem->AppendCommandText( "exec default.cfg\n" );
cmdSystem->AppendCommandText( "exec joy_360_0.cfg\n" );
}
if( leftyFlip )
{
cmdSystem->AppendCommandText( "exec joy_lefty.cfg" );
}
else
{
cmdSystem->AppendCommandText( "exec joy_righty.cfg" );
}
cmdSystem->ExecuteCommandBuffer();
if( !save )
{
cvarSystem->ClearModifiedFlags( CVAR_ARCHIVE );
cvarSystem->SetModifiedFlags( flags );
}
}
CONSOLE_COMMAND( setProfileDefaults, "sets profile settings to default and saves", 0 )
{
if( session->GetSignInManager().GetMasterLocalUser() == NULL )
{
return;
}
idPlayerProfile* profile = session->GetSignInManager().GetMasterLocalUser()->GetProfile();
if( verify( profile != NULL ) )
{
profile->SetDefaults();
profile->SaveSettings( true );
}
}