2003-07-09 03:10:01 +00:00
|
|
|
/*
|
|
|
|
|
-----------------------------------------------------------------------------
|
|
|
|
|
Class: UnlockSystem
|
|
|
|
|
|
|
|
|
|
Desc: See header.
|
|
|
|
|
|
|
|
|
|
Copyright (c) 2001-2003 by the person(s) listed below. All rights reserved.
|
|
|
|
|
Kevin Slaughter
|
|
|
|
|
curewater
|
|
|
|
|
-----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "global.h"
|
|
|
|
|
#include "PrefsManager.h"
|
|
|
|
|
#include "RageLog.h"
|
2003-07-09 05:57:09 +00:00
|
|
|
#include "song.h"
|
2003-07-09 03:10:01 +00:00
|
|
|
#include "RageException.h"
|
|
|
|
|
#include "RageUtil.h"
|
|
|
|
|
#include "UnlockSystem.h"
|
2003-07-09 05:01:37 +00:00
|
|
|
#include "SongManager.h"
|
2003-07-09 03:10:01 +00:00
|
|
|
|
|
|
|
|
#include <fstream>
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
|
|
#include "stdio.h"
|
|
|
|
|
|
|
|
|
|
UnlockSystem::UnlockSystem()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2003-07-09 04:46:24 +00:00
|
|
|
bool UnlockSystem::SongIsLocked( const Song *song )
|
|
|
|
|
{
|
2003-07-09 05:01:37 +00:00
|
|
|
SongEntry *p = FindSong( song );
|
|
|
|
|
return p && p->isLocked;
|
2003-07-09 04:46:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool UnlockSystem::SongIsRoulette( const Song *song )
|
|
|
|
|
{
|
2003-07-09 05:01:37 +00:00
|
|
|
SongEntry *p = FindSong( song );
|
|
|
|
|
return p && p->m_iRouletteSeed != 0;
|
2003-07-09 04:46:24 +00:00
|
|
|
}
|
|
|
|
|
|
2003-07-09 05:01:37 +00:00
|
|
|
SongEntry *UnlockSystem::FindSong( const Song *pSong )
|
2003-07-09 03:10:01 +00:00
|
|
|
{
|
|
|
|
|
for(unsigned i = 0; i < m_SongEntries.size(); i++)
|
2003-07-09 05:01:37 +00:00
|
|
|
if (m_SongEntries[i].GetSong() == pSong )
|
|
|
|
|
return &m_SongEntries[i];
|
|
|
|
|
|
|
|
|
|
return NULL;
|
2003-07-09 03:10:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SongEntry::SongEntry()
|
|
|
|
|
{
|
|
|
|
|
m_fDancePointsRequired = 0;
|
|
|
|
|
m_fArcadePointsRequired = 0;
|
|
|
|
|
m_fSongPointsRequired = 0;
|
|
|
|
|
m_fExtraStagesCleared = 0;
|
|
|
|
|
m_fExtraStagesFailed = 0;
|
|
|
|
|
m_fStagesCleared = 0;
|
|
|
|
|
m_fToastysSeen = 0;
|
|
|
|
|
m_iRouletteSeed = 0;
|
|
|
|
|
|
|
|
|
|
isLocked = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2003-07-09 04:47:51 +00:00
|
|
|
static bool CompareSongEntries(const SongEntry &se1, const SongEntry &se2)
|
2003-07-09 03:10:01 +00:00
|
|
|
{
|
|
|
|
|
return se1.m_sSongName < se2.m_sSongName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool UnlockSystem::ParseRow(CString text, CString &type, float &qty,
|
|
|
|
|
CString &songname)
|
|
|
|
|
{
|
|
|
|
|
int pos = -1;
|
|
|
|
|
int end = text.GetLength(); // sets a value in case | does not exist
|
|
|
|
|
char unlock_type[4];
|
|
|
|
|
char qty_text[20];
|
|
|
|
|
|
|
|
|
|
while (text[pos] != '|' && pos < text[pos] != '\0')
|
|
|
|
|
{
|
|
|
|
|
pos++;
|
|
|
|
|
if (text[pos] == '[') text[pos] = ' ';
|
|
|
|
|
if (text[pos] == ']') text[pos] = ' ';;
|
|
|
|
|
if (text[pos] == '|')
|
|
|
|
|
{
|
|
|
|
|
end = pos;
|
|
|
|
|
text[pos] = ' ';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* XXX: "local variable 'end' may be used without having been initialized";
|
|
|
|
|
* I havn't looked at this code to see if it's a problem, but I don't want
|
|
|
|
|
* to simply silence the warning without being sure. (Can this just be
|
|
|
|
|
* a standard INI--does it actually need to be another file format?) -glenn */
|
|
|
|
|
|
|
|
|
|
// glenn: ok, i set it at the beginning.
|
|
|
|
|
|
|
|
|
|
songname = text.Right(text.GetLength() - 1 - end);
|
|
|
|
|
|
|
|
|
|
sscanf(text, "%s %s|", unlock_type, qty_text);
|
|
|
|
|
|
|
|
|
|
type = unlock_type;
|
|
|
|
|
qty = (float) atof(qty_text);
|
|
|
|
|
|
|
|
|
|
LOG->Trace( "UnlockSystem Entry %s", text.c_str() );
|
|
|
|
|
LOG->Trace( " Title %s", songname.c_str() );
|
|
|
|
|
LOG->Trace( " Type %s", type.c_str() );
|
|
|
|
|
LOG->Trace( " Value %s", qty_text );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SongEntry::updateLocked()
|
|
|
|
|
{
|
|
|
|
|
if (!isLocked) return true; // if its already true
|
|
|
|
|
|
|
|
|
|
if (m_fArcadePointsRequired != 0)
|
|
|
|
|
isLocked = (PREFSMAN->m_fArcadePointsAccumulated < m_fArcadePointsRequired);
|
|
|
|
|
|
|
|
|
|
if (m_fDancePointsRequired != 0)
|
|
|
|
|
isLocked = (PREFSMAN->m_fDancePointsAccumulated < m_fDancePointsRequired);
|
|
|
|
|
|
|
|
|
|
if (m_fSongPointsRequired != 0)
|
|
|
|
|
isLocked = (PREFSMAN->m_fSongPointsAccumulated < m_fSongPointsRequired);
|
|
|
|
|
|
|
|
|
|
if (m_fExtraStagesCleared != 0)
|
|
|
|
|
isLocked = (PREFSMAN->m_fExtraStagesCleared < m_fExtraStagesCleared);
|
|
|
|
|
|
|
|
|
|
if (m_fExtraStagesFailed != 0)
|
|
|
|
|
isLocked = (PREFSMAN->m_fExtraStagesFailed < m_fExtraStagesFailed);
|
|
|
|
|
|
|
|
|
|
if (m_fStagesCleared != 0)
|
|
|
|
|
isLocked = (PREFSMAN->m_fTotalStagesCleared < m_fStagesCleared);
|
|
|
|
|
|
|
|
|
|
if (m_fToastysSeen != 0)
|
|
|
|
|
isLocked = (PREFSMAN->m_fTotalToastysSeen < m_fToastysSeen);
|
|
|
|
|
|
|
|
|
|
if (m_iRouletteSeed != 0)
|
|
|
|
|
isLocked = (PREFSMAN->m_RouletteSeeds[m_iRouletteSeed] == '0');
|
|
|
|
|
|
|
|
|
|
return !isLocked;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool UnlockSystem::LoadFromDATFile( CString sPath )
|
|
|
|
|
{
|
|
|
|
|
LOG->Trace( "UnlockSystem::LoadFromDATFile(%s)", sPath.c_str() );
|
|
|
|
|
|
|
|
|
|
ifstream input;
|
|
|
|
|
|
|
|
|
|
input.open(sPath);
|
|
|
|
|
if(input.fail())
|
|
|
|
|
{
|
|
|
|
|
LOG->Warn( "Error opening file '%s' for reading.", sPath.c_str() );
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char line[256];
|
|
|
|
|
CString unlock_type, song_title;
|
|
|
|
|
float datavalue;
|
|
|
|
|
|
|
|
|
|
// m_SongEntries.clear();
|
|
|
|
|
|
|
|
|
|
while(input.getline(line, 255))
|
|
|
|
|
{
|
|
|
|
|
if(line[0] == '/' && line[1] == '/') //Check for comments
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
/* "[data1] data2". Ignore whitespace at the beginning of the line. */
|
|
|
|
|
if (!ParseRow(line, unlock_type, datavalue, song_title))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
SongEntry current;
|
|
|
|
|
|
|
|
|
|
song_title.MakeUpper(); //Avoid case-sensitive problems
|
|
|
|
|
current.m_sSongName = song_title;
|
|
|
|
|
|
|
|
|
|
if (unlock_type == "AP")
|
|
|
|
|
{
|
|
|
|
|
current.m_fArcadePointsRequired = datavalue;
|
|
|
|
|
current.isLocked = (PREFSMAN->m_fArcadePointsAccumulated < datavalue);
|
|
|
|
|
}
|
|
|
|
|
if (unlock_type == "DP")
|
|
|
|
|
{
|
|
|
|
|
current.m_fDancePointsRequired = datavalue;
|
|
|
|
|
current.isLocked = (PREFSMAN->m_fDancePointsAccumulated < datavalue);
|
|
|
|
|
}
|
|
|
|
|
if (unlock_type == "SP")
|
|
|
|
|
{
|
|
|
|
|
current.m_fSongPointsRequired = datavalue;
|
|
|
|
|
current.isLocked = (PREFSMAN->m_fSongPointsAccumulated < datavalue);
|
|
|
|
|
}
|
|
|
|
|
if (unlock_type == "EC")
|
|
|
|
|
{
|
|
|
|
|
current.m_fExtraStagesCleared = datavalue;
|
|
|
|
|
current.isLocked = (PREFSMAN->m_fExtraStagesCleared < datavalue);
|
|
|
|
|
}
|
|
|
|
|
if (unlock_type == "EF")
|
|
|
|
|
{
|
|
|
|
|
current.m_fExtraStagesFailed = datavalue;
|
|
|
|
|
current.isLocked = (PREFSMAN->m_fExtraStagesFailed < datavalue);
|
|
|
|
|
}
|
|
|
|
|
if (unlock_type == "CS")
|
|
|
|
|
{
|
|
|
|
|
current.m_fStagesCleared = datavalue;
|
|
|
|
|
current.isLocked = (PREFSMAN->m_fTotalStagesCleared < datavalue);
|
|
|
|
|
}
|
|
|
|
|
if (unlock_type == "!!")
|
|
|
|
|
{
|
|
|
|
|
current.m_fToastysSeen = datavalue;
|
|
|
|
|
current.isLocked = (PREFSMAN->m_fTotalToastysSeen < datavalue);
|
|
|
|
|
}
|
|
|
|
|
if (unlock_type == "RO")
|
|
|
|
|
{
|
|
|
|
|
current.m_iRouletteSeed = (int)datavalue;
|
|
|
|
|
current.isLocked = (PREFSMAN->m_fArcadePointsAccumulated < datavalue);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_SongEntries.push_back(current);
|
|
|
|
|
}
|
|
|
|
|
// sort list so we can make use of binary searching
|
|
|
|
|
sort( m_SongEntries.begin(), m_SongEntries.end(), CompareSongEntries );
|
|
|
|
|
|
|
|
|
|
for(unsigned i=0; i < m_SongEntries.size(); i++)
|
|
|
|
|
LOG->Trace( "UnlockSystem entry: %s", m_SongEntries[i].m_sSongName.c_str() );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SongEntry::SelectableWheel()
|
|
|
|
|
{
|
|
|
|
|
return (!isLocked); // cached
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SongEntry::SelectableRoulette()
|
|
|
|
|
{
|
|
|
|
|
if (!isLocked) return true;
|
|
|
|
|
|
|
|
|
|
if (m_iRouletteSeed != 0) return true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float UnlockSystem::NumPointsUntilNextUnlock()
|
|
|
|
|
{
|
|
|
|
|
float fSmallestPoints = 400000000; // or an arbitrarily large value
|
|
|
|
|
for( unsigned a=0; a<m_SongEntries.size(); a++ )
|
|
|
|
|
{
|
|
|
|
|
// old line: if( m_SongEntries[a].m_fDancePointsRequired >= fSmallestPoints )
|
|
|
|
|
// new: it makes sure the number of points to the song is positive, AND it is less than
|
|
|
|
|
// the currently smallest one. (cure)
|
|
|
|
|
if( m_SongEntries[a].m_fDancePointsRequired > PREFSMAN->m_fDancePointsAccumulated)
|
|
|
|
|
fSmallestPoints = min(fSmallestPoints, m_SongEntries[a].m_fDancePointsRequired);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (fSmallestPoints == 400000000) return 0; // no match found
|
|
|
|
|
return fSmallestPoints - PREFSMAN->m_fDancePointsAccumulated;
|
|
|
|
|
}
|
2003-07-09 05:01:37 +00:00
|
|
|
|
|
|
|
|
Song *SongEntry::GetSong() const
|
|
|
|
|
{
|
|
|
|
|
return SONGMAN->FindSong( "", m_sSongName );
|
|
|
|
|
}
|