Files
itgmania212121/stepmania/src/UnlockSystem.cpp
T

509 lines
13 KiB
C++
Raw Normal View History

/*
-----------------------------------------------------------------------------
Class: UnlockSystem
Desc: See header.
Copyright (c) 2001-2003 by the person(s) listed below. All rights reserved.
Kevin Slaughter
Andrew Wong
-----------------------------------------------------------------------------
*/
#include "global.h"
#include "PrefsManager.h"
#include "RageLog.h"
2003-07-09 05:57:09 +00:00
#include "song.h"
2003-07-11 18:08:57 +00:00
#include "Course.h"
#include "RageException.h"
#include "RageUtil.h"
#include "UnlockSystem.h"
2003-07-09 05:01:37 +00:00
#include "SongManager.h"
2003-07-11 18:08:57 +00:00
#include "GameState.h"
#include "IniFile.h"
#include "MsdFile.h"
#include <fstream>
using namespace std;
#include "stdio.h"
UnlockSystem::UnlockSystem()
{
ArcadePoints = 0;
DancePoints = 0;
SongPoints = 0;
ExtraClearPoints = 0;
ExtraFailPoints = 0;
ToastyPoints = 0;
StagesCleared = 0;
RouletteSeeds = "1";
2003-07-16 12:58:02 +00:00
2003-08-04 00:04:53 +00:00
ReadValues("Data" SLASH "MemCard.ini"); // in case its ever accessed,
// we want the values to be available
2003-08-04 00:04:53 +00:00
WriteValues("Data" SLASH "MemCard.ini"); // create if it does not exist
}
2003-07-18 08:04:47 +00:00
void UnlockSystem::RouletteUnlock( const Song *song )
{
2003-08-07 10:15:16 +00:00
// if its an extra stage, don't count it
if (GAMESTATE->IsExtraStage() || GAMESTATE->IsExtraStage2())
return;
2003-08-11 20:57:57 +00:00
UnlockEntry *p = FindSong( song );
2003-07-18 08:04:47 +00:00
if (!p)
return; // does not exist
if (p->m_iRouletteSeed == 0)
return; // already unlocked
RouletteSeeds[p->m_iRouletteSeed] = '1';
2003-08-04 00:04:53 +00:00
WriteValues("Data" SLASH "MemCard.ini");
}
bool UnlockSystem::CourseIsLocked( const Course *course )
{
2003-07-18 08:04:47 +00:00
if( !PREFSMAN->m_bUseUnlockSystem )
return false;
// I know, its not a song, but for purposes of title
// comparison, its the same thing.
2003-08-11 20:57:57 +00:00
UnlockEntry *p = FindCourse( course );
if (p)
2003-07-18 06:38:05 +00:00
p->UpdateLocked();
2003-07-18 06:38:05 +00:00
return p != NULL && p->isLocked;
}
2003-07-09 04:46:24 +00:00
bool UnlockSystem::SongIsLocked( const Song *song )
{
2003-07-18 08:04:47 +00:00
if( !PREFSMAN->m_bUseUnlockSystem )
return false;
2003-08-11 20:57:57 +00:00
UnlockEntry *p = FindSong( song );
2003-07-12 20:16:07 +00:00
if( p == NULL )
return false;
2003-07-18 06:38:05 +00:00
p->UpdateLocked();
2003-07-12 20:16:07 +00:00
LOG->Trace( "current status: %slocked", p->isLocked? "":"un" );
2003-07-12 20:16:07 +00:00
return p->isLocked;
2003-07-09 04:46:24 +00:00
}
bool UnlockSystem::SongIsRoulette( const Song *song )
{
2003-08-11 20:57:57 +00:00
UnlockEntry *p = FindSong( song );
return p && (p->m_iRouletteSeed != 0) ;
2003-07-09 04:46:24 +00:00
}
2003-08-11 20:57:57 +00:00
UnlockEntry *UnlockSystem::FindLockEntry( CString songname )
{
2003-07-12 20:16:07 +00:00
for(unsigned i = 0; i < m_SongEntries.size(); i++)
if (!songname.CompareNoCase(m_SongEntries[i].m_sSongName))
return &m_SongEntries[i];
return NULL;
}
2003-08-11 20:57:57 +00:00
UnlockEntry *UnlockSystem::FindSong( const Song *pSong )
{
for(unsigned i = 0; i < m_SongEntries.size(); i++)
2003-07-18 06:38:05 +00:00
if (m_SongEntries[i].m_pSong == pSong )
return &m_SongEntries[i];
return NULL;
}
2003-08-11 20:57:57 +00:00
UnlockEntry *UnlockSystem::FindCourse( const Course *pCourse )
{
for(unsigned i = 0; i < m_SongEntries.size(); i++)
2003-07-18 06:38:05 +00:00
if (m_SongEntries[i].m_pCourse== pCourse )
2003-07-09 05:01:37 +00:00
return &m_SongEntries[i];
2003-07-09 05:01:37 +00:00
return NULL;
}
2003-08-11 20:57:57 +00:00
UnlockEntry::UnlockEntry()
{
m_fDancePointsRequired = 0;
m_fArcadePointsRequired = 0;
m_fSongPointsRequired = 0;
m_fExtraStagesCleared = 0;
m_fExtraStagesFailed = 0;
m_fStagesCleared = 0;
m_fToastysSeen = 0;
m_iRouletteSeed = 0;
2003-07-18 06:38:05 +00:00
m_pSong = NULL;
m_pCourse = NULL;
2003-07-16 12:58:02 +00:00
isLocked = true;
}
2003-08-11 20:57:57 +00:00
void UnlockEntry::UpdateLocked()
{
2003-07-18 06:38:05 +00:00
if (!isLocked)
return;
2003-07-18 06:38:05 +00:00
const UnlockSystem *UNLOCKS = GAMESTATE->m_pUnlockingSys;
2003-07-18 06:38:05 +00:00
isLocked = true;
if ( m_fArcadePointsRequired && UNLOCKS->ArcadePoints >= m_fArcadePointsRequired )
2003-07-18 06:38:05 +00:00
isLocked = false;
if ( m_fDancePointsRequired && UNLOCKS->DancePoints >= m_fDancePointsRequired )
2003-07-18 06:38:05 +00:00
isLocked = false;
if ( m_fSongPointsRequired && UNLOCKS->SongPoints >= m_fSongPointsRequired )
2003-07-18 06:38:05 +00:00
isLocked = false;
if ( m_fExtraStagesCleared && UNLOCKS->ExtraClearPoints >= m_fExtraStagesCleared )
2003-07-18 06:38:05 +00:00
isLocked = false;
if ( m_fExtraStagesFailed && UNLOCKS->ExtraFailPoints >= m_fExtraStagesFailed )
2003-07-18 06:38:05 +00:00
isLocked = false;
if ( m_fStagesCleared && UNLOCKS->StagesCleared >= m_fStagesCleared )
2003-07-18 06:38:05 +00:00
isLocked = false;
if ( m_fToastysSeen && UNLOCKS->ToastyPoints >= m_fToastysSeen )
2003-07-18 06:38:05 +00:00
isLocked = false;
2003-07-18 06:38:05 +00:00
if ( m_iRouletteSeed )
{
2003-07-18 06:38:05 +00:00
const CString &tmp = UNLOCKS->RouletteSeeds;
2003-07-18 06:38:05 +00:00
LOG->Trace("Seed in question: %d Roulette seeds: %s", m_iRouletteSeed, tmp.c_str() );
if( tmp[m_iRouletteSeed] == '1' )
2003-07-18 06:38:05 +00:00
isLocked = false;
}
}
bool UnlockSystem::LoadFromDATFile( CString sPath )
{
LOG->Trace( "UnlockSystem::LoadFromDATFile(%s)", sPath.c_str() );
MsdFile msd;
if( !msd.ReadFile( sPath ) )
{
LOG->Warn( "Error opening file '%s' for reading: %s.", sPath.c_str(), msd.GetError().c_str() );
return false;
}
int MaxRouletteSlot = 0;
2003-07-16 12:58:02 +00:00
unsigned i, j;
for( i=0; i<msd.GetNumValues(); i++ )
{
int iNumParams = msd.GetNumParams(i);
const MsdFile::value_t &sParams = msd.GetValue(i);
CString sValueName = sParams[0];
if(iNumParams < 1)
{
LOG->Warn("Got \"%s\" tag with no parameters", sValueName.c_str());
continue;
}
if( stricmp(sParams[0],"UNLOCK") )
{
2003-07-15 10:11:22 +00:00
LOG->Warn("Unrecognized unlock tag \"%s\", ignored.", sValueName.c_str());
continue;
}
2003-08-11 20:57:57 +00:00
UnlockEntry current;
current.m_sSongName = sParams[1];
LOG->Trace("Song entry: %s", current.m_sSongName.c_str() );
CStringArray UnlockTypes;
split(sParams[2], ",", UnlockTypes);
2003-07-16 12:58:02 +00:00
for( j=0; j<UnlockTypes.size(); ++j )
{
CStringArray readparam;
split(UnlockTypes[j], "=", readparam);
CString unlock_type = readparam[0];
float datavalue = (float) atof(readparam[1]);
LOG->Trace("UnlockTypes line: %s", UnlockTypes[j].c_str() );
LOG->Trace("Unlock info: %s %f", unlock_type.c_str(), datavalue);
if (unlock_type == "AP")
current.m_fArcadePointsRequired = datavalue;
if (unlock_type == "DP")
current.m_fDancePointsRequired = datavalue;
if (unlock_type == "SP")
current.m_fSongPointsRequired = datavalue;
if (unlock_type == "EC")
current.m_fExtraStagesCleared = datavalue;
if (unlock_type == "EF")
current.m_fExtraStagesFailed = datavalue;
if (unlock_type == "CS")
current.m_fStagesCleared = datavalue;
if (unlock_type == "!!")
current.m_fToastysSeen = datavalue;
if (unlock_type == "RO")
{
current.m_iRouletteSeed = (int)datavalue;
MaxRouletteSlot = max( MaxRouletteSlot, (int) datavalue );
}
}
2003-07-18 06:38:05 +00:00
current.UpdateLocked();
2003-07-16 12:58:02 +00:00
m_SongEntries.push_back(current);
}
InitRouletteSeeds(MaxRouletteSlot); // resize roulette seeds
// for more efficient use of file
2003-07-18 06:38:05 +00:00
UpdateSongs();
for(i=0; i < m_SongEntries.size(); i++)
{
CString tmp = " ";
if (!m_SongEntries[i].isLocked) tmp = "un";
LOG->Trace( "UnlockSystem Entry %s", m_SongEntries[i].m_sSongName.c_str() );
2003-07-18 06:38:05 +00:00
if (m_SongEntries[i].m_pSong != NULL)
LOG->Trace( " Translit %s", m_SongEntries[i].m_pSong->GetTranslitMainTitle().c_str() );
LOG->Trace( " AP %f", m_SongEntries[i].m_fArcadePointsRequired );
LOG->Trace( " DP %f", m_SongEntries[i].m_fDancePointsRequired );
LOG->Trace( " SP %f", m_SongEntries[i].m_fSongPointsRequired );
LOG->Trace( " CS %f", m_SongEntries[i].m_fStagesCleared );
LOG->Trace( " RO %i", m_SongEntries[i].m_iRouletteSeed );
LOG->Trace( " Status %slocked", tmp.c_str() );
2003-07-24 14:04:13 +00:00
if (m_SongEntries[i].m_pSong)
LOG->Trace( " Found matching song entry" );
if (m_SongEntries[i].m_pCourse)
LOG->Trace( " Found matching course entry" );
}
return true;
}
2003-08-11 20:57:57 +00:00
bool UnlockEntry::SelectableWheel()
{
return (!isLocked); // cached
}
2003-08-11 20:57:57 +00:00
bool UnlockEntry::SelectableRoulette()
{
if (!isLocked) return true;
if (m_iRouletteSeed != 0) return true;
return false;
}
float UnlockSystem::DancePointsUntilNextUnlock()
{
float fSmallestPoints = 400000000; // or an arbitrarily large value
for( unsigned a=0; a<m_SongEntries.size(); a++ )
if( m_SongEntries[a].m_fDancePointsRequired > DancePoints)
fSmallestPoints = min(fSmallestPoints, m_SongEntries[a].m_fDancePointsRequired);
if (fSmallestPoints == 400000000) return 0; // no match found
return fSmallestPoints - DancePoints;
}
2003-07-09 05:01:37 +00:00
float UnlockSystem::ArcadePointsUntilNextUnlock()
{
float fSmallestPoints = 400000000; // or an arbitrarily large value
for( unsigned a=0; a<m_SongEntries.size(); a++ )
if( m_SongEntries[a].m_fArcadePointsRequired > ArcadePoints)
fSmallestPoints = min(fSmallestPoints, m_SongEntries[a].m_fArcadePointsRequired);
if (fSmallestPoints == 400000000) return 0; // no match found
return fSmallestPoints - ArcadePoints;
}
float UnlockSystem::SongPointsUntilNextUnlock()
{
float fSmallestPoints = 400000000; // or an arbitrarily large value
for( unsigned a=0; a<m_SongEntries.size(); a++ )
if( m_SongEntries[a].m_fSongPointsRequired > SongPoints )
fSmallestPoints = min(fSmallestPoints, m_SongEntries[a].m_fSongPointsRequired);
if (fSmallestPoints == 400000000) return 0; // no match found
return fSmallestPoints - SongPoints;
}
2003-07-18 06:38:05 +00:00
/* Update the song pointer. Only call this when it's likely to have changed,
* such as on load, or when a song title changes in the editor. */
void UnlockSystem::UpdateSongs()
2003-07-09 05:01:37 +00:00
{
2003-07-18 06:38:05 +00:00
for( unsigned i = 0; i < m_SongEntries.size(); ++i )
{
m_SongEntries[i].m_pSong = NULL;
m_SongEntries[i].m_pCourse = NULL;
m_SongEntries[i].m_pSong = SONGMAN->FindSong( m_SongEntries[i].m_sSongName );
2003-07-18 06:38:05 +00:00
if( m_SongEntries[i].m_pSong == NULL )
m_SongEntries[i].m_pCourse = SONGMAN->FindCourse( m_SongEntries[i].m_sSongName );
}
2003-07-09 05:01:37 +00:00
}
// This is mainly to streamline the INI for unnecessary values.
void UnlockSystem::InitRouletteSeeds(int MaxRouletteSlot)
{
CString seeds = RouletteSeeds;
MaxRouletteSlot++; // we actually need one more
// have exactly the needed number of slots
if (seeds.GetLength() == MaxRouletteSlot) return;
if (seeds.GetLength() > MaxRouletteSlot) // truncate value
{
// too many seeds
seeds = seeds.Left(MaxRouletteSlot);
RouletteSeeds = seeds;
return;
}
// if we get here, the value isn't long enough
while (seeds.GetLength() != MaxRouletteSlot)
seeds += "0";
RouletteSeeds = seeds;
}
bool UnlockSystem::ReadValues( CString filename)
{
IniFile data;
data.SetPath(filename);
if (!data.ReadFile())
return false;
data.GetValueF( "Unlock", "ArcadePointsAccumulated", ArcadePoints );
data.GetValueF( "Unlock", "DancePointsAccumulated", DancePoints );
data.GetValueF( "Unlock", "SongPointsAccumulated", SongPoints );
data.GetValueF( "Unlock", "ExtraStagesCleared", ExtraClearPoints );
data.GetValueF( "Unlock", "ExtraStagesFailed", ExtraFailPoints );
data.GetValueF( "Unlock", "TotalStagesCleared", StagesCleared );
data.GetValueF( "Unlock", "TotalToastysSeen", ToastyPoints );
data.GetValue ( "Unlock", "RouletteSeeds", RouletteSeeds );
return true;
}
bool UnlockSystem::WriteValues( CString filename)
{
IniFile data;
data.SetPath(filename);
data.SetValueF( "Unlock", "ArcadePointsAccumulated", ArcadePoints );
data.SetValueF( "Unlock", "DancePointsAccumulated", DancePoints );
data.SetValueF( "Unlock", "SongPointsAccumulated", SongPoints );
data.SetValueF( "Unlock", "ExtraStagesCleared", ExtraClearPoints );
data.SetValueF( "Unlock", "ExtraStagesFailed", ExtraFailPoints );
data.SetValueF( "Unlock", "TotalStagesCleared", StagesCleared );
data.SetValueF( "Unlock", "TotalToastysSeen", ToastyPoints );
data.SetValue ( "Unlock", "RouletteSeeds", RouletteSeeds );
data.WriteFile();
return true;
}
float UnlockSystem::UnlockAddAP(float credit)
{
2003-08-04 00:04:53 +00:00
ReadValues("Data" SLASH "MemCard.ini");
ArcadePoints += credit;
2003-08-04 00:04:53 +00:00
WriteValues("Data" SLASH "MemCard.ini");
return ArcadePoints;
}
float UnlockSystem::UnlockAddAP(Grade credit)
{
2003-08-04 00:04:53 +00:00
ReadValues("Data" SLASH "MemCard.ini");
if (credit != GRADE_E && credit != GRADE_D)
ArcadePoints += 1;
if (credit == GRADE_AAA)
ArcadePoints += 9;
2003-08-04 00:04:53 +00:00
WriteValues("Data" SLASH "MemCard.ini");
return ArcadePoints;
}
float UnlockSystem::UnlockAddDP(float credit)
{
2003-08-04 00:04:53 +00:00
ReadValues("Data" SLASH "MemCard.ini");
// we don't want to ever take away dance points
if (credit > 0) DancePoints += credit;
2003-08-04 00:04:53 +00:00
WriteValues("Data" SLASH "MemCard.ini");
return DancePoints;
}
float UnlockSystem::UnlockAddSP(float credit)
{
2003-08-04 00:04:53 +00:00
ReadValues("Data" SLASH "MemCard.ini");
SongPoints += credit;
2003-08-04 00:04:53 +00:00
WriteValues("Data" SLASH "MemCard.ini");
return SongPoints;
}
float UnlockSystem::UnlockAddSP(Grade credit)
{
2003-08-04 00:04:53 +00:00
ReadValues("Data" SLASH "MemCard.ini");
2003-07-12 21:41:12 +00:00
const float SongPointsVals[NUM_GRADES] = { -1 /* unused */, 0, 1, 2, 3, 4, 5, 10, 20 };
SongPoints += SongPointsVals[credit];
2003-08-04 00:04:53 +00:00
WriteValues("Data" SLASH "MemCard.ini");
return SongPoints;
}
float UnlockSystem::UnlockClearExtraStage()
{
2003-08-04 00:04:53 +00:00
ReadValues("Data" SLASH "MemCard.ini");
ExtraClearPoints++;
2003-08-04 00:04:53 +00:00
WriteValues("Data" SLASH "MemCard.ini");
return ExtraClearPoints;
}
float UnlockSystem::UnlockFailExtraStage()
{
2003-08-04 00:04:53 +00:00
ReadValues("Data" SLASH "MemCard.ini");
ExtraFailPoints++;
2003-08-04 00:04:53 +00:00
WriteValues("Data" SLASH "MemCard.ini");
return ExtraFailPoints;
}
float UnlockSystem::UnlockClearStage()
{
2003-08-04 00:04:53 +00:00
ReadValues("Data" SLASH "MemCard.ini");
StagesCleared++;
2003-08-04 00:04:53 +00:00
WriteValues("Data" SLASH "MemCard.ini");
return StagesCleared;
}
float UnlockSystem::UnlockToasty()
{
2003-08-04 00:04:53 +00:00
ReadValues("Data" SLASH "MemCard.ini");
ToastyPoints++;
2003-08-04 00:04:53 +00:00
WriteValues("Data" SLASH "MemCard.ini");
return ToastyPoints;
2003-07-11 18:08:57 +00:00
}
int UnlockSystem::GetNumUnlocks() const
{
return m_SongEntries.size();
2003-08-10 03:23:17 +00:00
}