2011-03-17 01:47:30 -04:00
|
|
|
#include "global.h"
|
|
|
|
|
#include "UnlockManager.h"
|
|
|
|
|
#include "PrefsManager.h"
|
|
|
|
|
#include "RageLog.h"
|
|
|
|
|
#include "Song.h"
|
|
|
|
|
#include "Course.h"
|
|
|
|
|
#include "RageUtil.h"
|
|
|
|
|
#include "SongManager.h"
|
|
|
|
|
#include "GameState.h"
|
2011-06-24 00:28:57 -04:00
|
|
|
#include "GameConstantsAndTypes.h" // StepsTypeToString
|
2011-03-17 01:47:30 -04:00
|
|
|
#include "ProfileManager.h"
|
|
|
|
|
#include "Profile.h"
|
|
|
|
|
#include "ThemeManager.h"
|
|
|
|
|
#include "Foreach.h"
|
|
|
|
|
#include "Steps.h"
|
|
|
|
|
#include <float.h>
|
|
|
|
|
#include "CommonMetrics.h"
|
|
|
|
|
#include "LuaManager.h"
|
|
|
|
|
#include "GameManager.h"
|
|
|
|
|
#include "Style.h"
|
|
|
|
|
|
|
|
|
|
UnlockManager* UNLOCKMAN = NULL; // global and accessable from anywhere in our program
|
|
|
|
|
|
|
|
|
|
#define UNLOCK_NAMES THEME->GetMetric ("UnlockManager","UnlockNames")
|
|
|
|
|
#define UNLOCK(x) THEME->GetMetricR("UnlockManager", ssprintf("Unlock%sCommand",x.c_str()));
|
|
|
|
|
|
|
|
|
|
static ThemeMetric<bool> AUTO_LOCK_CHALLENGE_STEPS( "UnlockManager", "AutoLockChallengeSteps" );
|
2011-06-26 16:10:24 -07:00
|
|
|
static ThemeMetric<bool> AUTO_LOCK_EDIT_STEPS( "UnlockManager", "AutoLockEditSteps" );
|
2011-06-26 16:14:50 -07:00
|
|
|
static ThemeMetric<bool> SONGS_NOT_ADDITIONAL( "UnlockManager", "SongsNotAdditional" );
|
2011-03-17 01:47:30 -04:00
|
|
|
|
|
|
|
|
static const char *UnlockRequirementNames[] =
|
|
|
|
|
{
|
|
|
|
|
"ArcadePoints",
|
|
|
|
|
"DancePoints",
|
|
|
|
|
"SongPoints",
|
|
|
|
|
"ExtraCleared",
|
|
|
|
|
"ExtraFailed",
|
|
|
|
|
"Toasties",
|
2011-04-30 18:41:14 -05:00
|
|
|
"StagesCleared",
|
|
|
|
|
"NumberUnlocked"
|
2011-03-17 01:47:30 -04:00
|
|
|
};
|
|
|
|
|
XToString( UnlockRequirement );
|
|
|
|
|
StringToX( UnlockRequirement );
|
|
|
|
|
LuaXType( UnlockRequirement );
|
|
|
|
|
|
|
|
|
|
static const char *UnlockRewardTypeNames[] =
|
|
|
|
|
{
|
|
|
|
|
"Song",
|
|
|
|
|
"Steps",
|
2011-06-24 00:28:57 -04:00
|
|
|
"StepsType",
|
2011-03-17 01:47:30 -04:00
|
|
|
"Course",
|
|
|
|
|
"Modifier",
|
|
|
|
|
};
|
|
|
|
|
XToString( UnlockRewardType );
|
|
|
|
|
XToLocalizedString( UnlockRewardType );
|
|
|
|
|
LuaXType( UnlockRewardType );
|
|
|
|
|
LuaFunction( UnlockRewardTypeToLocalizedString, UnlockRewardTypeToLocalizedString(Enum::Check<UnlockRewardType>(L, 1)) );
|
|
|
|
|
|
|
|
|
|
UnlockManager::UnlockManager()
|
|
|
|
|
{
|
|
|
|
|
// Register with Lua.
|
|
|
|
|
{
|
|
|
|
|
Lua *L = LUA->Get();
|
|
|
|
|
lua_pushstring( L, "UNLOCKMAN" );
|
|
|
|
|
this->PushSelf( L );
|
|
|
|
|
lua_settable( L, LUA_GLOBALSINDEX );
|
|
|
|
|
LUA->Release( L );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UNLOCKMAN = this;
|
|
|
|
|
|
|
|
|
|
Load();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UnlockManager::~UnlockManager()
|
|
|
|
|
{
|
|
|
|
|
// Unregister with Lua.
|
|
|
|
|
LUA->UnsetGlobal( "UNLOCKMAN" );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UnlockManager::UnlockSong( const Song *song )
|
|
|
|
|
{
|
|
|
|
|
const UnlockEntry *p = FindSong( song );
|
|
|
|
|
if( !p )
|
|
|
|
|
return; // does not exist
|
|
|
|
|
if( p->m_sEntryID.empty() )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
UnlockEntryID( p->m_sEntryID );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RString UnlockManager::FindEntryID( const RString &sName ) const
|
|
|
|
|
{
|
|
|
|
|
const UnlockEntry *pEntry = NULL;
|
|
|
|
|
|
|
|
|
|
const Song *pSong = SONGMAN->FindSong( sName );
|
|
|
|
|
if( pSong != NULL )
|
|
|
|
|
pEntry = FindSong( pSong );
|
|
|
|
|
|
|
|
|
|
const Course *pCourse = SONGMAN->FindCourse( sName );
|
|
|
|
|
if( pCourse != NULL )
|
|
|
|
|
pEntry = FindCourse( pCourse );
|
|
|
|
|
|
|
|
|
|
if( pEntry == NULL )
|
|
|
|
|
pEntry = FindModifier( sName );
|
|
|
|
|
|
|
|
|
|
if( pEntry == NULL )
|
|
|
|
|
{
|
|
|
|
|
LOG->Warn( "Couldn't find locked entry \"%s\"", sName.c_str() );
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return pEntry->m_sEntryID;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int UnlockManager::CourseIsLocked( const Course *pCourse ) const
|
|
|
|
|
{
|
|
|
|
|
int iRet = 0;
|
|
|
|
|
|
|
|
|
|
if( PREFSMAN->m_bUseUnlockSystem )
|
|
|
|
|
{
|
|
|
|
|
const UnlockEntry *p = FindCourse( pCourse );
|
|
|
|
|
if( p == NULL )
|
|
|
|
|
return false;
|
|
|
|
|
if( p->IsLocked() )
|
|
|
|
|
iRet |= LOCKED_LOCK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If a course uses a song that is disabled, disable the course too. */
|
|
|
|
|
FOREACH_CONST( CourseEntry, pCourse->m_vEntries, e )
|
|
|
|
|
{
|
|
|
|
|
const CourseEntry &ce = *e;
|
|
|
|
|
const Song *pSong = ce.songID.ToSong();
|
|
|
|
|
if( pSong == NULL )
|
|
|
|
|
continue;
|
|
|
|
|
int iSongLock = SongIsLocked( pSong );
|
|
|
|
|
if( iSongLock & LOCKED_DISABLED )
|
|
|
|
|
iRet |= LOCKED_DISABLED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return iRet;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int UnlockManager::SongIsLocked( const Song *pSong ) const
|
|
|
|
|
{
|
|
|
|
|
int iRet = 0;
|
|
|
|
|
if( PREFSMAN->m_bUseUnlockSystem )
|
|
|
|
|
{
|
|
|
|
|
const UnlockEntry *p = FindSong( pSong );
|
|
|
|
|
if( p != NULL && p->IsLocked() )
|
|
|
|
|
{
|
|
|
|
|
iRet |= LOCKED_LOCK;
|
|
|
|
|
if( !p->m_sEntryID.empty() && m_RouletteCodes.find( p->m_sEntryID ) != m_RouletteCodes.end() )
|
|
|
|
|
iRet |= LOCKED_ROULETTE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if( PREFSMAN->m_bHiddenSongs && pSong->m_SelectionDisplay == Song::SHOW_NEVER )
|
|
|
|
|
iRet |= LOCKED_SELECTABLE;
|
|
|
|
|
|
|
|
|
|
if( !pSong->m_bEnabled )
|
|
|
|
|
iRet |= LOCKED_DISABLED;
|
|
|
|
|
|
|
|
|
|
return iRet;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool UnlockManager::StepsIsLocked( const Song *pSong, const Steps *pSteps ) const
|
|
|
|
|
{
|
|
|
|
|
if( !PREFSMAN->m_bUseUnlockSystem )
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
const UnlockEntry *p = FindSteps( pSong, pSteps );
|
|
|
|
|
if( p == NULL )
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
return p->IsLocked();
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-24 00:28:57 -04:00
|
|
|
bool UnlockManager::StepsTypeIsLocked(const Song *pSong, const Steps *pSteps, const StepsType *pSType) const
|
|
|
|
|
{
|
|
|
|
|
if( !PREFSMAN->m_bUseUnlockSystem )
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
const UnlockEntry *p = FindStepsType( pSong, pSteps, pSType );
|
|
|
|
|
if( p == NULL )
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
return p->IsLocked();
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-17 01:47:30 -04:00
|
|
|
bool UnlockManager::ModifierIsLocked( const RString &sOneMod ) const
|
|
|
|
|
{
|
|
|
|
|
if( !PREFSMAN->m_bUseUnlockSystem )
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
const UnlockEntry *p = FindModifier( sOneMod );
|
|
|
|
|
if( p == NULL )
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
return p->IsLocked();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const UnlockEntry *UnlockManager::FindSong( const Song *pSong ) const
|
|
|
|
|
{
|
|
|
|
|
FOREACH_CONST( UnlockEntry, m_UnlockEntries, e )
|
|
|
|
|
if( e->m_Song.ToSong() == pSong && e->m_dc == Difficulty_Invalid )
|
|
|
|
|
return &(*e);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const UnlockEntry *UnlockManager::FindSteps( const Song *pSong, const Steps *pSteps ) const
|
|
|
|
|
{
|
|
|
|
|
ASSERT( pSong && pSteps );
|
|
|
|
|
FOREACH_CONST( UnlockEntry, m_UnlockEntries, e )
|
|
|
|
|
if( e->m_Song.ToSong() == pSong && e->m_dc == pSteps->GetDifficulty() )
|
|
|
|
|
return &(*e);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-24 00:28:57 -04:00
|
|
|
const UnlockEntry *UnlockManager::FindStepsType(const Song *pSong,
|
|
|
|
|
const Steps *pSteps,
|
|
|
|
|
const StepsType *pSType ) const
|
|
|
|
|
{
|
|
|
|
|
ASSERT( pSong && pSteps && pSType );
|
|
|
|
|
FOREACH_CONST( UnlockEntry, m_UnlockEntries, e )
|
|
|
|
|
if(e->m_Song.ToSong() == pSong &&
|
|
|
|
|
e->m_dc == pSteps->GetDifficulty() &&
|
|
|
|
|
e->m_StepsType == pSteps->m_StepsType)
|
|
|
|
|
return &(*e);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-17 01:47:30 -04:00
|
|
|
const UnlockEntry *UnlockManager::FindCourse( const Course *pCourse ) const
|
|
|
|
|
{
|
|
|
|
|
FOREACH_CONST( UnlockEntry, m_UnlockEntries, e )
|
|
|
|
|
if( e->m_Course.ToCourse() == pCourse )
|
|
|
|
|
return &(*e);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const UnlockEntry *UnlockManager::FindModifier( const RString &sOneMod ) const
|
|
|
|
|
{
|
|
|
|
|
FOREACH_CONST( UnlockEntry, m_UnlockEntries, e )
|
|
|
|
|
if( e->GetModifier().CompareNoCase(sOneMod) == 0 )
|
|
|
|
|
return &(*e);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static float GetArcadePoints( const Profile *pProfile )
|
|
|
|
|
{
|
|
|
|
|
float fAP = 0;
|
|
|
|
|
|
|
|
|
|
FOREACH_ENUM( Grade, g )
|
|
|
|
|
{
|
|
|
|
|
switch(g)
|
|
|
|
|
{
|
|
|
|
|
case Grade_Tier01:
|
|
|
|
|
case Grade_Tier02: fAP += 9 * pProfile->m_iNumStagesPassedByGrade[g]; break;
|
|
|
|
|
default: fAP += 1 * pProfile->m_iNumStagesPassedByGrade[g]; break;
|
|
|
|
|
|
|
|
|
|
case Grade_Failed:
|
|
|
|
|
case Grade_NoData:
|
|
|
|
|
; // no points
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FOREACH_ENUM( PlayMode, pm )
|
|
|
|
|
{
|
|
|
|
|
switch(pm)
|
|
|
|
|
{
|
2011-07-20 11:11:04 -04:00
|
|
|
case PLAY_MODE_NONSTOP:
|
|
|
|
|
case PLAY_MODE_ONI:
|
|
|
|
|
case PLAY_MODE_ENDLESS:
|
|
|
|
|
{
|
|
|
|
|
fAP += pProfile->m_iNumSongsPlayedByPlayMode[pm];
|
|
|
|
|
}
|
|
|
|
|
default: break;
|
2011-03-17 01:47:30 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return fAP;
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-20 11:11:04 -04:00
|
|
|
// TODO: Make this more flexible for games with many grade tiers. Lua-ize it? -Wolfman2000
|
2011-03-17 01:47:30 -04:00
|
|
|
static float GetSongPoints( const Profile *pProfile )
|
|
|
|
|
{
|
|
|
|
|
float fSP = 0;
|
|
|
|
|
|
|
|
|
|
FOREACH_ENUM( Grade, g )
|
|
|
|
|
{
|
|
|
|
|
switch( g )
|
|
|
|
|
{
|
|
|
|
|
case Grade_Tier01:/*AAAA*/ fSP += 20 * pProfile->m_iNumStagesPassedByGrade[g]; break;
|
|
|
|
|
case Grade_Tier02:/*AAA*/ fSP += 10* pProfile->m_iNumStagesPassedByGrade[g]; break;
|
|
|
|
|
case Grade_Tier03:/*AA*/ fSP += 5* pProfile->m_iNumStagesPassedByGrade[g]; break;
|
|
|
|
|
case Grade_Tier04:/*A*/ fSP += 4* pProfile->m_iNumStagesPassedByGrade[g]; break;
|
|
|
|
|
case Grade_Tier05:/*B*/ fSP += 3* pProfile->m_iNumStagesPassedByGrade[g]; break;
|
|
|
|
|
case Grade_Tier06:/*C*/ fSP += 2* pProfile->m_iNumStagesPassedByGrade[g]; break;
|
|
|
|
|
case Grade_Tier07:/*D*/ fSP += 1* pProfile->m_iNumStagesPassedByGrade[g]; break;
|
|
|
|
|
case Grade_Failed:
|
|
|
|
|
case Grade_NoData:
|
2011-07-20 11:11:04 -04:00
|
|
|
default:
|
2011-03-17 01:47:30 -04:00
|
|
|
; // no points
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FOREACH_ENUM( PlayMode, pm )
|
|
|
|
|
{
|
|
|
|
|
switch(pm)
|
|
|
|
|
{
|
2011-07-20 11:11:04 -04:00
|
|
|
case PLAY_MODE_NONSTOP:
|
|
|
|
|
case PLAY_MODE_ONI:
|
|
|
|
|
case PLAY_MODE_ENDLESS:
|
|
|
|
|
{
|
2011-03-17 01:47:30 -04:00
|
|
|
fSP += pProfile->m_iNumSongsPlayedByPlayMode[pm];
|
2011-07-20 11:11:04 -04:00
|
|
|
}
|
|
|
|
|
default: break;
|
2011-03-17 01:47:30 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return fSP;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UnlockManager::GetPoints( const Profile *pProfile, float fScores[NUM_UnlockRequirement] ) const
|
|
|
|
|
{
|
|
|
|
|
fScores[UnlockRequirement_ArcadePoints] = GetArcadePoints( pProfile );
|
|
|
|
|
fScores[UnlockRequirement_SongPoints] = GetSongPoints( pProfile );
|
|
|
|
|
fScores[UnlockRequirement_DancePoints] = (float) pProfile->m_iTotalDancePoints;
|
|
|
|
|
fScores[UnlockRequirement_StagesCleared] = (float) pProfile->GetTotalNumSongsPassed();
|
2011-06-15 21:50:43 -05:00
|
|
|
//fScores[UnlockRequirement_NumUnlocked] = (float) GetNumUnlocked();
|
2011-03-17 01:47:30 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return true if all songs and/or courses referenced by an unlock are available. */
|
|
|
|
|
bool UnlockEntry::IsValid() const
|
|
|
|
|
{
|
|
|
|
|
switch( m_Type )
|
|
|
|
|
{
|
|
|
|
|
case UnlockRewardType_Song:
|
|
|
|
|
return m_Song.IsValid();
|
|
|
|
|
|
|
|
|
|
case UnlockRewardType_Steps:
|
|
|
|
|
return m_Song.IsValid() && m_dc != Difficulty_Invalid;
|
|
|
|
|
|
2011-06-24 00:28:57 -04:00
|
|
|
case UnlockRewardType_Steps_Type:
|
|
|
|
|
{
|
|
|
|
|
return m_Song.IsValid() && m_dc != Difficulty_Invalid && m_StepsType != StepsType_Invalid;
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-17 01:47:30 -04:00
|
|
|
case UnlockRewardType_Course:
|
|
|
|
|
return m_Course.IsValid();
|
|
|
|
|
|
|
|
|
|
case UnlockRewardType_Modifier:
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
WARN( ssprintf("%i", m_Type) );
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UnlockEntryStatus UnlockEntry::GetUnlockEntryStatus() const
|
|
|
|
|
{
|
2011-06-24 00:28:57 -04:00
|
|
|
set<RString> &ids = PROFILEMAN->GetMachineProfile()->m_UnlockedEntryIDs;
|
|
|
|
|
if(!m_sEntryID.empty() &&
|
|
|
|
|
ids.find(m_sEntryID) != ids.end() )
|
2011-03-17 01:47:30 -04:00
|
|
|
return UnlockEntryStatus_Unlocked;
|
|
|
|
|
|
|
|
|
|
float fScores[NUM_UnlockRequirement];
|
|
|
|
|
UNLOCKMAN->GetPoints( PROFILEMAN->GetMachineProfile(), fScores );
|
|
|
|
|
|
|
|
|
|
for( int i = 0; i < NUM_UnlockRequirement; ++i )
|
2011-06-15 21:50:43 -05:00
|
|
|
{
|
|
|
|
|
if( i == UnlockRequirement_NumUnlocked )
|
|
|
|
|
continue;
|
|
|
|
|
|
2011-03-17 01:47:30 -04:00
|
|
|
if( m_fRequirement[i] && fScores[i] >= m_fRequirement[i] )
|
|
|
|
|
return UnlockEntryStatus_RequirementsMet;
|
2011-06-15 21:50:43 -05:00
|
|
|
}
|
2011-03-17 01:47:30 -04:00
|
|
|
|
|
|
|
|
if( m_bRequirePassHardSteps && m_Song.IsValid() )
|
|
|
|
|
{
|
|
|
|
|
Song *pSong = m_Song.ToSong();
|
|
|
|
|
vector<Steps*> vp;
|
|
|
|
|
SongUtil::GetSteps(
|
|
|
|
|
pSong,
|
|
|
|
|
vp,
|
|
|
|
|
StepsType_Invalid,
|
|
|
|
|
Difficulty_Hard
|
|
|
|
|
);
|
|
|
|
|
FOREACH_CONST( Steps*, vp, s )
|
|
|
|
|
if( PROFILEMAN->GetMachineProfile()->HasPassedSteps(pSong, *s) )
|
|
|
|
|
return UnlockEntryStatus_RequirementsMet;
|
|
|
|
|
}
|
2011-06-26 16:10:24 -07:00
|
|
|
|
|
|
|
|
if (m_bRequirePassChallengeSteps && m_Song.IsValid())
|
|
|
|
|
{
|
|
|
|
|
Song *pSong = m_Song.ToSong();
|
|
|
|
|
vector<Steps*> vp;
|
|
|
|
|
SongUtil::GetSteps(pSong,
|
|
|
|
|
vp,
|
|
|
|
|
StepsType_Invalid,
|
|
|
|
|
Difficulty_Challenge);
|
|
|
|
|
FOREACH_CONST(Steps*, vp, s)
|
|
|
|
|
{
|
|
|
|
|
if (PROFILEMAN->GetMachineProfile()->HasPassedSteps(pSong, *s))
|
|
|
|
|
return UnlockEntryStatus_RequirementsMet;
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-03-17 01:47:30 -04:00
|
|
|
|
|
|
|
|
return UnlockEntryStatus_RequrementsNotMet;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RString UnlockEntry::GetDescription() const
|
|
|
|
|
{
|
|
|
|
|
Song *pSong = m_Song.ToSong();
|
|
|
|
|
switch( m_Type )
|
|
|
|
|
{
|
|
|
|
|
default:
|
|
|
|
|
ASSERT(0);
|
|
|
|
|
return "";
|
|
|
|
|
case UnlockRewardType_Song:
|
|
|
|
|
return pSong ? pSong->GetDisplayFullTitle() : "";
|
|
|
|
|
case UnlockRewardType_Steps:
|
2011-06-24 00:28:57 -04:00
|
|
|
{
|
|
|
|
|
StepsType st = GAMEMAN->GetHowToPlayStyleForGame( GAMESTATE->m_pCurGame )->m_StepsType; // TODO: Is this the best thing we can do here?
|
|
|
|
|
return (pSong ? pSong->GetDisplayFullTitle() : "") + ", " + CustomDifficultyToLocalizedString( GetCustomDifficulty(st, m_dc, CourseType_Invalid) );
|
|
|
|
|
}
|
|
|
|
|
case UnlockRewardType_Steps_Type:
|
|
|
|
|
{
|
|
|
|
|
RString ret = (pSong ? pSong->GetDisplayFullTitle() : "");
|
|
|
|
|
ret += "," + CustomDifficultyToLocalizedString( GetCustomDifficulty(m_StepsType, m_dc, CourseType_Invalid) );
|
|
|
|
|
return ret + "," + StringConversion::ToString(m_StepsType); // yeah, bit strange.
|
|
|
|
|
}
|
2011-03-17 01:47:30 -04:00
|
|
|
case UnlockRewardType_Course:
|
|
|
|
|
return m_Course.IsValid() ? m_Course.ToCourse()->GetDisplayFullTitle() : "";
|
|
|
|
|
case UnlockRewardType_Modifier:
|
|
|
|
|
return CommonMetrics::LocalizeOptionItem( GetModifier(), false );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RString UnlockEntry::GetBannerFile() const
|
|
|
|
|
{
|
|
|
|
|
Song *pSong = m_Song.ToSong();
|
|
|
|
|
switch( m_Type )
|
|
|
|
|
{
|
|
|
|
|
default:
|
|
|
|
|
ASSERT(0);
|
|
|
|
|
return "";
|
|
|
|
|
case UnlockRewardType_Song:
|
|
|
|
|
case UnlockRewardType_Steps:
|
2011-06-24 00:28:57 -04:00
|
|
|
case UnlockRewardType_Steps_Type:
|
2011-03-17 01:47:30 -04:00
|
|
|
return pSong ? pSong->GetBannerPath() : "";
|
|
|
|
|
case UnlockRewardType_Course:
|
|
|
|
|
return m_Course.ToCourse() ? m_Course.ToCourse()->GetBannerPath() : "";
|
|
|
|
|
case UnlockRewardType_Modifier:
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RString UnlockEntry::GetBackgroundFile() const
|
|
|
|
|
{
|
|
|
|
|
Song *pSong = m_Song.ToSong();
|
|
|
|
|
switch( m_Type )
|
|
|
|
|
{
|
|
|
|
|
default:
|
|
|
|
|
ASSERT(0);
|
|
|
|
|
return "";
|
|
|
|
|
case UnlockRewardType_Song:
|
|
|
|
|
case UnlockRewardType_Steps:
|
2011-06-24 00:28:57 -04:00
|
|
|
case UnlockRewardType_Steps_Type:
|
2011-03-17 01:47:30 -04:00
|
|
|
return pSong ? pSong->GetBackgroundPath() : "";
|
|
|
|
|
case UnlockRewardType_Course:
|
|
|
|
|
return "";
|
|
|
|
|
case UnlockRewardType_Modifier:
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
void UnlockManager::Load()
|
|
|
|
|
{
|
|
|
|
|
LOG->Trace( "UnlockManager::Load()" );
|
|
|
|
|
|
|
|
|
|
vector<RString> asUnlockNames;
|
|
|
|
|
split( UNLOCK_NAMES, ",", asUnlockNames );
|
|
|
|
|
|
|
|
|
|
Lua *L = LUA->Get();
|
|
|
|
|
for( unsigned i = 0; i < asUnlockNames.size(); ++i )
|
|
|
|
|
{
|
|
|
|
|
const RString &sUnlockName = asUnlockNames[i];
|
|
|
|
|
|
|
|
|
|
LuaReference cmds = UNLOCK( sUnlockName );
|
|
|
|
|
|
|
|
|
|
UnlockEntry current;
|
|
|
|
|
current.m_sEntryID = sUnlockName; // default
|
|
|
|
|
|
|
|
|
|
// function
|
|
|
|
|
cmds.PushSelf( L );
|
|
|
|
|
ASSERT( !lua_isnil(L, -1) );
|
|
|
|
|
|
|
|
|
|
// 1st parameter
|
|
|
|
|
current.PushSelf( L );
|
|
|
|
|
|
|
|
|
|
// call function with 1 argument and 0 results
|
|
|
|
|
lua_call( L, 1, 0 );
|
|
|
|
|
|
|
|
|
|
if( current.m_bRoulette )
|
|
|
|
|
m_RouletteCodes.insert( current.m_sEntryID );
|
|
|
|
|
|
|
|
|
|
m_UnlockEntries.push_back( current );
|
|
|
|
|
}
|
|
|
|
|
LUA->Release(L);
|
|
|
|
|
|
|
|
|
|
if( AUTO_LOCK_CHALLENGE_STEPS )
|
|
|
|
|
{
|
|
|
|
|
FOREACH_CONST( Song*, SONGMAN->GetAllSongs(), s )
|
|
|
|
|
{
|
|
|
|
|
// If no hard steps to play to unlock, skip
|
|
|
|
|
if( SongUtil::GetOneSteps(*s, StepsType_Invalid, Difficulty_Hard) == NULL )
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
// If no challenge steps to unlock, skip
|
|
|
|
|
if( SongUtil::GetOneSteps(*s, StepsType_Invalid, Difficulty_Challenge) == NULL )
|
|
|
|
|
continue;
|
|
|
|
|
|
2011-06-26 16:14:50 -07:00
|
|
|
if( SONGS_NOT_ADDITIONAL && SONGMAN->WasLoadedFromAdditionalSongs(*s) )
|
2011-03-17 01:47:30 -04:00
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
UnlockEntry ue;
|
|
|
|
|
ue.m_sEntryID = "_challenge_" + (*s)->GetSongDir();
|
|
|
|
|
ue.m_Type = UnlockRewardType_Steps;
|
|
|
|
|
ue.m_cmd.Load( (*s)->m_sGroupName+"/"+(*s)->GetTranslitFullTitle()+",expert" );
|
|
|
|
|
ue.m_bRequirePassHardSteps = true;
|
|
|
|
|
|
|
|
|
|
m_UnlockEntries.push_back( ue );
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-06-26 16:10:24 -07:00
|
|
|
|
|
|
|
|
if (AUTO_LOCK_EDIT_STEPS)
|
|
|
|
|
{
|
|
|
|
|
FOREACH_CONST( Song*, SONGMAN->GetAllSongs(), s )
|
|
|
|
|
{
|
|
|
|
|
// no challenge steps to play: skip.
|
|
|
|
|
if (SongUtil::GetOneSteps(*s, StepsType_Invalid, Difficulty_Challenge) == NULL)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
// no edit steps to unlock: skip.
|
|
|
|
|
if (SongUtil::GetOneSteps(*s, StepsType_Invalid, Difficulty_Edit) == NULL)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
// don't add additional songs.
|
2011-06-26 16:14:50 -07:00
|
|
|
if (SONGS_NOT_ADDITIONAL && SONGMAN->WasLoadedFromAdditionalSongs(*s))
|
2011-06-26 16:10:24 -07:00
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
UnlockEntry ue;
|
|
|
|
|
ue.m_sEntryID = "_edit_" + (*s)->GetSongDir();
|
|
|
|
|
ue.m_Type = UnlockRewardType_Steps;
|
|
|
|
|
ue.m_cmd.Load( (*s)->m_sGroupName+"/"+(*s)->GetTranslitFullTitle()+",edit" );
|
|
|
|
|
ue.m_bRequirePassChallengeSteps = true;
|
|
|
|
|
|
|
|
|
|
m_UnlockEntries.push_back(ue);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-03-17 01:47:30 -04:00
|
|
|
|
2011-04-30 18:41:14 -05:00
|
|
|
// Make sure that we don't have duplicate unlock IDs. This can cause problems
|
2011-03-17 01:47:30 -04:00
|
|
|
// with UnlockCelebrate and with codes.
|
|
|
|
|
FOREACH_CONST( UnlockEntry, m_UnlockEntries, ue )
|
|
|
|
|
FOREACH_CONST( UnlockEntry, m_UnlockEntries, ue2 )
|
|
|
|
|
if( ue != ue2 )
|
|
|
|
|
ASSERT_M( ue->m_sEntryID != ue2->m_sEntryID, ssprintf("duplicate unlock entry id %s",ue->m_sEntryID.c_str()) );
|
|
|
|
|
|
|
|
|
|
FOREACH( UnlockEntry, m_UnlockEntries, e )
|
|
|
|
|
{
|
|
|
|
|
switch( e->m_Type )
|
|
|
|
|
{
|
|
|
|
|
case UnlockRewardType_Song:
|
|
|
|
|
e->m_Song.FromSong( SONGMAN->FindSong( e->m_cmd.GetArg(0).s ) );
|
|
|
|
|
if( !e->m_Song.IsValid() )
|
|
|
|
|
LOG->Warn( "Unlock: Cannot find song matching \"%s\"", e->m_cmd.GetArg(0).s.c_str() );
|
|
|
|
|
break;
|
|
|
|
|
case UnlockRewardType_Steps:
|
|
|
|
|
e->m_Song.FromSong( SONGMAN->FindSong( e->m_cmd.GetArg(0).s ) );
|
|
|
|
|
if( !e->m_Song.IsValid() )
|
|
|
|
|
{
|
|
|
|
|
LOG->Warn( "Unlock: Cannot find song matching \"%s\"", e->m_cmd.GetArg(0).s.c_str() );
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
e->m_dc = StringToDifficulty( e->m_cmd.GetArg(1).s );
|
|
|
|
|
if( e->m_dc == Difficulty_Invalid )
|
|
|
|
|
{
|
|
|
|
|
LOG->Warn( "Unlock: Invalid difficulty \"%s\"", e->m_cmd.GetArg(1).s.c_str() );
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
2011-06-24 00:28:57 -04:00
|
|
|
case UnlockRewardType_Steps_Type:
|
|
|
|
|
{
|
|
|
|
|
e->m_Song.FromSong( SONGMAN->FindSong( e->m_cmd.GetArg(0).s ) );
|
|
|
|
|
if( !e->m_Song.IsValid() )
|
|
|
|
|
{
|
|
|
|
|
LOG->Warn( "Unlock: Cannot find song matching \"%s\"", e->m_cmd.GetArg(0).s.c_str() );
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
e->m_dc = StringToDifficulty( e->m_cmd.GetArg(1).s );
|
|
|
|
|
if( e->m_dc == Difficulty_Invalid )
|
|
|
|
|
{
|
|
|
|
|
LOG->Warn( "Unlock: Invalid difficulty \"%s\"", e->m_cmd.GetArg(1).s.c_str() );
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
e->m_StepsType = GAMEMAN->StringToStepsType(e->m_cmd.GetArg(2).s);
|
|
|
|
|
if (e->m_StepsType == StepsType_Invalid)
|
|
|
|
|
{
|
|
|
|
|
LOG->Warn( "Unlock: Invalid steps type \"%s\"", e->m_cmd.GetArg(2).s.c_str() );
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2011-03-17 01:47:30 -04:00
|
|
|
case UnlockRewardType_Course:
|
|
|
|
|
e->m_Course.FromCourse( SONGMAN->FindCourse(e->m_cmd.GetArg(0).s) );
|
|
|
|
|
if( !e->m_Course.IsValid() )
|
|
|
|
|
LOG->Warn( "Unlock: Cannot find course matching \"%s\"", e->m_cmd.GetArg(0).s.c_str() );
|
|
|
|
|
break;
|
|
|
|
|
case UnlockRewardType_Modifier:
|
|
|
|
|
// nothing to cache
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
ASSERT(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Log unlocks
|
|
|
|
|
FOREACH_CONST( UnlockEntry, m_UnlockEntries, e )
|
|
|
|
|
{
|
|
|
|
|
RString str = ssprintf( "Unlock: %s; ", join("\n",e->m_cmd.m_vsArgs).c_str() );
|
|
|
|
|
FOREACH_ENUM( UnlockRequirement, j )
|
|
|
|
|
if( e->m_fRequirement[j] )
|
|
|
|
|
str += ssprintf( "%s = %f; ", UnlockRequirementToString(j).c_str(), e->m_fRequirement[j] );
|
|
|
|
|
if( e->m_bRequirePassHardSteps )
|
|
|
|
|
str += "RequirePassHardSteps; ";
|
2011-06-26 16:10:24 -07:00
|
|
|
if (e->m_bRequirePassChallengeSteps)
|
|
|
|
|
str += "RequirePassChallengeSteps; ";
|
2011-03-17 01:47:30 -04:00
|
|
|
|
|
|
|
|
str += ssprintf( "entryID = %s ", e->m_sEntryID.c_str() );
|
|
|
|
|
str += e->IsLocked()? "locked":"unlocked";
|
|
|
|
|
if( e->m_Song.IsValid() )
|
|
|
|
|
str += ( " (found song)" );
|
|
|
|
|
if( e->m_Course.IsValid() )
|
|
|
|
|
str += ( " (found course)" );
|
|
|
|
|
LOG->Trace( "%s", str.c_str() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void UnlockManager::Reload()
|
|
|
|
|
{
|
|
|
|
|
// clear old data, if any
|
|
|
|
|
m_UnlockEntries.clear();
|
|
|
|
|
m_RouletteCodes.clear();
|
|
|
|
|
|
|
|
|
|
Load();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float UnlockManager::PointsUntilNextUnlock( UnlockRequirement t ) const
|
|
|
|
|
{
|
|
|
|
|
float fScores[NUM_UnlockRequirement];
|
|
|
|
|
ZERO( fScores );
|
|
|
|
|
GetPoints( PROFILEMAN->GetMachineProfile(), fScores );
|
|
|
|
|
|
|
|
|
|
float fSmallestPoints = FLT_MAX; // or an arbitrarily large value
|
|
|
|
|
for( unsigned a=0; a<m_UnlockEntries.size(); a++ )
|
|
|
|
|
if( m_UnlockEntries[a].m_fRequirement[t] > fScores[t] )
|
|
|
|
|
fSmallestPoints = min( fSmallestPoints, m_UnlockEntries[a].m_fRequirement[t] );
|
2011-04-30 18:41:14 -05:00
|
|
|
|
2011-03-17 01:47:30 -04:00
|
|
|
if( fSmallestPoints == FLT_MAX )
|
|
|
|
|
return 0; // no match found
|
|
|
|
|
return fSmallestPoints - fScores[t];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UnlockManager::UnlockEntryID( RString sEntryID )
|
|
|
|
|
{
|
|
|
|
|
PROFILEMAN->GetMachineProfile()->m_UnlockedEntryIDs.insert( sEntryID );
|
|
|
|
|
SONGMAN->InvalidateCachedTrails();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UnlockManager::UnlockEntryIndex( int iEntryIndex )
|
|
|
|
|
{
|
|
|
|
|
RString sEntryID = m_UnlockEntries[iEntryIndex].m_sEntryID;
|
|
|
|
|
UnlockEntryID( sEntryID );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UnlockManager::PreferUnlockEntryID( RString sUnlockEntryID )
|
|
|
|
|
{
|
|
|
|
|
for( unsigned i = 0; i < m_UnlockEntries.size(); ++i )
|
|
|
|
|
{
|
|
|
|
|
UnlockEntry &pEntry = m_UnlockEntries[i];
|
|
|
|
|
if( pEntry.m_sEntryID != sUnlockEntryID )
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if( pEntry.m_Song.ToSong() != NULL )
|
|
|
|
|
GAMESTATE->m_pPreferredSong = pEntry.m_Song.ToSong();
|
|
|
|
|
if( pEntry.m_Course.ToCourse() )
|
|
|
|
|
GAMESTATE->m_pPreferredCourse = pEntry.m_Course.ToCourse();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int UnlockManager::GetNumUnlocks() const
|
|
|
|
|
{
|
|
|
|
|
return m_UnlockEntries.size();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int UnlockManager::GetNumUnlocked() const
|
|
|
|
|
{
|
|
|
|
|
int count = 0;
|
|
|
|
|
FOREACH_CONST( UnlockEntry, m_UnlockEntries, ue )
|
|
|
|
|
{
|
2011-06-15 21:50:43 -05:00
|
|
|
if( !ue->IsLocked() )
|
2011-03-17 01:47:30 -04:00
|
|
|
count++;
|
|
|
|
|
}
|
|
|
|
|
return count;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int UnlockManager::GetUnlockEntryIndexToCelebrate() const
|
|
|
|
|
{
|
|
|
|
|
FOREACH_CONST( UnlockEntry, m_UnlockEntries, ue )
|
|
|
|
|
{
|
|
|
|
|
if( ue->GetUnlockEntryStatus() == UnlockEntryStatus_RequirementsMet )
|
|
|
|
|
return ue - m_UnlockEntries.begin();
|
|
|
|
|
}
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool UnlockManager::AnyUnlocksToCelebrate() const
|
|
|
|
|
{
|
|
|
|
|
return GetUnlockEntryIndexToCelebrate() != -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UnlockManager::GetUnlocksByType( UnlockRewardType t, vector<UnlockEntry *> &apEntries )
|
|
|
|
|
{
|
|
|
|
|
for( unsigned i = 0; i < m_UnlockEntries.size(); ++i )
|
|
|
|
|
if( m_UnlockEntries[i].IsValid() && m_UnlockEntries[i].m_Type == t )
|
|
|
|
|
apEntries.push_back( &m_UnlockEntries[i] );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UnlockManager::GetSongsUnlockedByEntryID( vector<Song *> &apSongsOut, RString sUnlockEntryID )
|
|
|
|
|
{
|
|
|
|
|
vector<UnlockEntry *> apEntries;
|
|
|
|
|
GetUnlocksByType( UnlockRewardType_Song, apEntries );
|
|
|
|
|
|
|
|
|
|
for( unsigned i = 0; i < apEntries.size(); ++i )
|
|
|
|
|
if( apEntries[i]->m_sEntryID == sUnlockEntryID )
|
|
|
|
|
apSongsOut.push_back( apEntries[i]->m_Song.ToSong() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UnlockManager::GetStepsUnlockedByEntryID( vector<Song *> &apSongsOut, vector<Difficulty> &apDifficultyOut, RString sUnlockEntryID )
|
|
|
|
|
{
|
|
|
|
|
vector<UnlockEntry *> apEntries;
|
|
|
|
|
GetUnlocksByType( UnlockRewardType_Steps, apEntries );
|
|
|
|
|
|
|
|
|
|
for( unsigned i = 0; i < apEntries.size(); ++i )
|
|
|
|
|
{
|
|
|
|
|
if( apEntries[i]->m_sEntryID == sUnlockEntryID )
|
|
|
|
|
{
|
|
|
|
|
apSongsOut.push_back( apEntries[i]->m_Song.ToSong() );
|
|
|
|
|
apDifficultyOut.push_back( apEntries[i]->m_dc );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// lua start
|
|
|
|
|
#include "LuaBinding.h"
|
|
|
|
|
|
|
|
|
|
/** @brief Allow Lua to have access to the UnlockEntry. */
|
|
|
|
|
class LunaUnlockEntry: public Luna<UnlockEntry>
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
static int IsLocked( T* p, lua_State *L ) { lua_pushboolean(L, p->IsLocked() ); return 1; }
|
|
|
|
|
static int GetDescription( T* p, lua_State *L ) { lua_pushstring(L, p->GetDescription() ); return 1; }
|
|
|
|
|
static int GetUnlockRewardType( T* p, lua_State *L ) { lua_pushnumber(L, p->m_Type ); return 1; }
|
|
|
|
|
static int GetRequirement( T* p, lua_State *L ) { UnlockRequirement i = Enum::Check<UnlockRequirement>( L, 1 ); lua_pushnumber(L, p->m_fRequirement[i] ); return 1; }
|
|
|
|
|
static int GetRequirePassHardSteps( T* p, lua_State *L ){ lua_pushboolean(L, p->m_bRequirePassHardSteps); return 1; }
|
2011-06-26 16:10:24 -07:00
|
|
|
static int GetRequirePassChallengeSteps( T* p, lua_State *L )
|
|
|
|
|
{
|
|
|
|
|
lua_pushboolean(L, p->m_bRequirePassChallengeSteps);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2011-03-17 01:47:30 -04:00
|
|
|
static int GetSong( T* p, lua_State *L )
|
|
|
|
|
{
|
|
|
|
|
Song *pSong = p->m_Song.ToSong();
|
|
|
|
|
if( pSong ) { pSong->PushSelf(L); return 1; }
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2011-08-22 22:54:21 -04:00
|
|
|
// Get all of the steps locked based on difficulty (similar to In The Groove 2).
|
|
|
|
|
static int GetStepOfAllTypes( T* p, lua_State *L )
|
|
|
|
|
{
|
|
|
|
|
Song *pSong = p->m_Song.ToSong();
|
|
|
|
|
if (pSong)
|
|
|
|
|
{
|
|
|
|
|
const vector<Steps*>& allSteps = pSong->GetAllSteps();
|
|
|
|
|
vector<Steps*> toRet;
|
|
|
|
|
FOREACH_CONST(Steps*, allSteps, step)
|
|
|
|
|
{
|
|
|
|
|
if ((*step)->GetDifficulty() == p->m_dc)
|
|
|
|
|
{
|
|
|
|
|
toRet.push_back(*step);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
LuaHelpers::CreateTableFromArray<Steps*>( toRet, L );
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2011-08-12 23:55:36 -04:00
|
|
|
// TODO: Add a function to just get all steps.
|
|
|
|
|
static int GetStepByStepsType( T* p, lua_State *L )
|
|
|
|
|
{
|
|
|
|
|
Song *pSong = p->m_Song.ToSong();
|
|
|
|
|
if (pSong)
|
|
|
|
|
{
|
|
|
|
|
const vector<Steps*>& allStepsType = pSong->GetStepsByStepsType(p->m_StepsType);
|
|
|
|
|
FOREACH_CONST(Steps*, allStepsType, step)
|
|
|
|
|
{
|
|
|
|
|
if ((*step)->GetDifficulty() == p->m_dc)
|
|
|
|
|
{
|
|
|
|
|
(*step)->PushSelf(L); return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-30 18:41:14 -05:00
|
|
|
static int GetCourse( T* p, lua_State *L )
|
|
|
|
|
{
|
|
|
|
|
Course *pCourse = p->m_Course.ToCourse();
|
|
|
|
|
if( pCourse ) { pCourse->PushSelf(L); return 1; }
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
static int GetCode( T* p, lua_State *L )
|
|
|
|
|
{
|
|
|
|
|
lua_pushstring( L, p->m_sEntryID );
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2011-03-17 01:47:30 -04:00
|
|
|
|
2011-04-30 19:35:51 -05:00
|
|
|
// internal
|
2011-03-17 01:47:30 -04:00
|
|
|
static int GetArgs( T* p, lua_State *L )
|
|
|
|
|
{
|
|
|
|
|
Command cmd;
|
|
|
|
|
for( int i = 1; i <= lua_gettop(L); ++i )
|
|
|
|
|
cmd.m_vsArgs.push_back( SArg(i) );
|
|
|
|
|
p->m_cmd = cmd;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int song( T* p, lua_State *L ) { GetArgs( p, L ); p->m_Type = UnlockRewardType_Song; return 0; }
|
|
|
|
|
static int steps( T* p, lua_State *L ) { GetArgs( p, L ); p->m_Type = UnlockRewardType_Steps; return 0; }
|
2011-06-24 00:28:57 -04:00
|
|
|
static int steps_type(T* p, lua_State *L) { GetArgs(p, L); p->m_Type = UnlockRewardType_Steps_Type; return 0; }
|
2011-03-17 01:47:30 -04:00
|
|
|
static int course( T* p, lua_State *L ) { GetArgs( p, L ); p->m_Type = UnlockRewardType_Course; return 0; }
|
|
|
|
|
static int mod( T* p, lua_State *L ) { GetArgs( p, L ); p->m_Type = UnlockRewardType_Modifier; return 0; }
|
|
|
|
|
static int code( T* p, lua_State *L ) { p->m_sEntryID = SArg(1); return 0; }
|
|
|
|
|
static int roulette( T* p, lua_State *L ) { p->m_bRoulette = true; return 0; }
|
|
|
|
|
static int requirepasshardsteps( T* p, lua_State *L ) { p->m_bRequirePassHardSteps = true; return 0; }
|
2011-08-22 22:56:13 -04:00
|
|
|
static int requirepasschallengesteps( T* p, lua_State *L ) { p->m_bRequirePassChallengeSteps = true; return 0; }
|
2011-03-17 01:47:30 -04:00
|
|
|
static int require( T* p, lua_State *L )
|
|
|
|
|
{
|
|
|
|
|
const UnlockRequirement ut = Enum::Check<UnlockRequirement>( L, 1 );
|
|
|
|
|
if( ut != UnlockRequirement_Invalid )
|
|
|
|
|
p->m_fRequirement[ut] = FArg(2);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LunaUnlockEntry()
|
|
|
|
|
{
|
|
|
|
|
ADD_METHOD( IsLocked );
|
2011-04-30 18:41:14 -05:00
|
|
|
ADD_METHOD( GetCode );
|
2011-03-17 01:47:30 -04:00
|
|
|
ADD_METHOD( GetDescription );
|
|
|
|
|
ADD_METHOD( GetUnlockRewardType );
|
|
|
|
|
ADD_METHOD( GetRequirement );
|
|
|
|
|
ADD_METHOD( GetRequirePassHardSteps );
|
2011-06-26 16:10:24 -07:00
|
|
|
ADD_METHOD( GetRequirePassChallengeSteps );
|
2011-03-17 01:47:30 -04:00
|
|
|
ADD_METHOD( GetSong );
|
2011-04-30 18:41:14 -05:00
|
|
|
ADD_METHOD( GetCourse );
|
2011-08-22 22:54:21 -04:00
|
|
|
ADD_METHOD( GetStepOfAllTypes );
|
2011-08-12 23:55:36 -04:00
|
|
|
ADD_METHOD( GetStepByStepsType );
|
2011-03-17 01:47:30 -04:00
|
|
|
ADD_METHOD( song );
|
|
|
|
|
ADD_METHOD( steps );
|
2011-06-24 00:28:57 -04:00
|
|
|
ADD_METHOD( steps_type );
|
2011-03-17 01:47:30 -04:00
|
|
|
ADD_METHOD( course );
|
|
|
|
|
ADD_METHOD( mod );
|
|
|
|
|
ADD_METHOD( code );
|
|
|
|
|
ADD_METHOD( roulette );
|
|
|
|
|
ADD_METHOD( requirepasshardsteps );
|
2011-08-22 22:56:13 -04:00
|
|
|
ADD_METHOD( requirepasschallengesteps );
|
2011-03-17 01:47:30 -04:00
|
|
|
ADD_METHOD( require );
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
LUA_REGISTER_CLASS( UnlockEntry )
|
|
|
|
|
|
|
|
|
|
/** @brief Allow Lua to have access to the UnlockManager. */
|
|
|
|
|
class LunaUnlockManager: public Luna<UnlockManager>
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
static int GetPointsUntilNextUnlock( T* p, lua_State *L )
|
|
|
|
|
{
|
|
|
|
|
const UnlockRequirement ut = Enum::Check<UnlockRequirement>( L, 1 );
|
|
|
|
|
lua_pushnumber( L, p->PointsUntilNextUnlock(ut) );
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
static int FindEntryID( T* p, lua_State *L ) { RString sName = SArg(1); RString s = p->FindEntryID(sName); if( s.empty() ) lua_pushnil(L); else lua_pushstring(L, s); return 1; }
|
|
|
|
|
static int UnlockEntryID( T* p, lua_State *L ) { RString sUnlockEntryID = SArg(1); p->UnlockEntryID(sUnlockEntryID); return 0; }
|
|
|
|
|
static int UnlockEntryIndex( T* p, lua_State *L ) { int iUnlockEntryID = IArg(1); p->UnlockEntryIndex(iUnlockEntryID); return 0; }
|
|
|
|
|
static int PreferUnlockEntryID( T* p, lua_State *L ) { RString sUnlockEntryID = SArg(1); p->PreferUnlockEntryID(sUnlockEntryID); return 0; }
|
|
|
|
|
static int GetNumUnlocks( T* p, lua_State *L ) { lua_pushnumber( L, p->GetNumUnlocks() ); return 1; }
|
|
|
|
|
static int GetNumUnlocked( T* p, lua_State *L ) { lua_pushnumber( L, p->GetNumUnlocked() ); return 1; }
|
|
|
|
|
static int GetUnlockEntryIndexToCelebrate( T* p, lua_State *L ) { lua_pushnumber( L, p->GetUnlockEntryIndexToCelebrate() ); return 1; }
|
|
|
|
|
static int AnyUnlocksToCelebrate( T* p, lua_State *L ) { lua_pushboolean( L, p->AnyUnlocksToCelebrate() ); return 1; }
|
|
|
|
|
static int GetUnlockEntry( T* p, lua_State *L ) { unsigned iIndex = IArg(1); if( iIndex >= p->m_UnlockEntries.size() ) return 0; p->m_UnlockEntries[iIndex].PushSelf(L); return 1; }
|
|
|
|
|
static int GetSongsUnlockedByEntryID( T* p, lua_State *L )
|
|
|
|
|
{
|
|
|
|
|
vector<Song *> apSongs;
|
|
|
|
|
UNLOCKMAN->GetSongsUnlockedByEntryID( apSongs, SArg(1) );
|
|
|
|
|
LuaHelpers::CreateTableFromArray( apSongs, L );
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int GetStepsUnlockedByEntryID( T* p, lua_State *L )
|
|
|
|
|
{
|
2011-04-30 19:35:51 -05:00
|
|
|
// Return the Song each Steps are associated with, too.
|
2011-03-17 01:47:30 -04:00
|
|
|
vector<Song *> apSongs;
|
|
|
|
|
vector<Difficulty> apDifficulty;
|
|
|
|
|
UNLOCKMAN->GetStepsUnlockedByEntryID( apSongs, apDifficulty, SArg(1) );
|
|
|
|
|
LuaHelpers::CreateTableFromArray( apSongs, L );
|
|
|
|
|
LuaHelpers::CreateTableFromArray( apDifficulty, L );
|
|
|
|
|
return 2;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-30 19:35:51 -05:00
|
|
|
static int GetPoints( T* p, lua_State *L ) {
|
|
|
|
|
float fScores[NUM_UnlockRequirement];
|
|
|
|
|
UNLOCKMAN->GetPoints( PROFILEMAN->GetMachineProfile(), fScores );
|
2011-04-30 19:40:43 -05:00
|
|
|
lua_pushnumber( L, fScores[Enum::Check<UnlockRequirement>(L, 1)] );
|
2011-04-30 19:35:51 -05:00
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int GetPointsForProfile( T* p, lua_State *L ) {
|
|
|
|
|
float fScores[NUM_UnlockRequirement];
|
|
|
|
|
UNLOCKMAN->GetPoints( Luna<Profile>::check(L,1), fScores );
|
2011-04-30 19:40:43 -05:00
|
|
|
lua_pushnumber( L, fScores[Enum::Check<UnlockRequirement>(L, 2)] );
|
2011-04-30 19:35:51 -05:00
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-17 01:47:30 -04:00
|
|
|
LunaUnlockManager()
|
|
|
|
|
{
|
2011-04-30 19:35:51 -05:00
|
|
|
ADD_METHOD( AnyUnlocksToCelebrate );
|
2011-03-17 01:47:30 -04:00
|
|
|
ADD_METHOD( FindEntryID );
|
|
|
|
|
ADD_METHOD( GetNumUnlocks );
|
|
|
|
|
ADD_METHOD( GetNumUnlocked );
|
2011-04-30 19:35:51 -05:00
|
|
|
ADD_METHOD( GetPoints );
|
|
|
|
|
ADD_METHOD( GetPointsForProfile );
|
|
|
|
|
ADD_METHOD( GetPointsUntilNextUnlock );
|
2011-03-17 01:47:30 -04:00
|
|
|
ADD_METHOD( GetSongsUnlockedByEntryID );
|
|
|
|
|
ADD_METHOD( GetStepsUnlockedByEntryID );
|
2011-04-30 19:35:51 -05:00
|
|
|
ADD_METHOD( GetUnlockEntry );
|
|
|
|
|
ADD_METHOD( GetUnlockEntryIndexToCelebrate );
|
|
|
|
|
ADD_METHOD( PreferUnlockEntryID );
|
|
|
|
|
ADD_METHOD( UnlockEntryID );
|
|
|
|
|
ADD_METHOD( UnlockEntryIndex );
|
2011-08-27 15:50:45 -05:00
|
|
|
//ADD_METHOD( UnlockSong );
|
|
|
|
|
//ADD_METHOD( GetUnlocksByType );
|
2011-03-17 01:47:30 -04:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
LUA_REGISTER_CLASS( UnlockManager )
|
|
|
|
|
// lua end
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* (c) 2001-2004 Kevin Slaughter, Andrew Wong, Glenn Maynard
|
|
|
|
|
* All rights reserved.
|
|
|
|
|
*
|
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
|
* copy of this software and associated documentation files (the
|
|
|
|
|
* "Software"), to deal in the Software without restriction, including
|
|
|
|
|
* without limitation the rights to use, copy, modify, merge, publish,
|
|
|
|
|
* distribute, and/or sell copies of the Software, and to permit persons to
|
|
|
|
|
* whom the Software is furnished to do so, provided that the above
|
|
|
|
|
* copyright notice(s) and this permission notice appear in all copies of
|
|
|
|
|
* the Software and that both the above copyright notice(s) and this
|
|
|
|
|
* permission notice appear in supporting documentation.
|
|
|
|
|
*
|
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
|
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
|
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
|
|
|
|
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
|
|
|
|
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
|
|
|
|
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
|
|
|
|
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
|
|
|
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
|
|
|
* PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
|
*/
|