Created SongOptions Lua interface with a similar design to the PlayerOptions interface. Moved enums that were inside SongOptions out and made them Lua accessible. Removed sAutosyncType and associated things from AdjustSync.cpp because it was unused. Added DefaultNilArgs and FArgGTEZero to LuaBinding as helpers. Moved INTERFACE defines from PlayerOptions.cpp to OptionsBinding.h.

This commit is contained in:
Kyzentun
2014-05-03 19:27:32 -06:00
parent b6b840187d
commit 0dfb131291
20 changed files with 384 additions and 258 deletions
+31
View File
@@ -780,6 +780,7 @@
<Function name='GetSongDelay'/> <Function name='GetSongDelay'/>
<Function name='GetSongFreeze'/> <Function name='GetSongFreeze'/>
<Function name='GetSongOptions'/> <Function name='GetSongOptions'/>
<Function name='GetSongOptionsObject'/>
<Function name='GetSongOptionsString'/> <Function name='GetSongOptionsString'/>
<Function name='GetSongPercent'/> <Function name='GetSongPercent'/>
<Function name='GetSongPosition'/> <Function name='GetSongPosition'/>
@@ -1453,6 +1454,20 @@
<Function name='WasLoadedFromAdditionalCourses'/> <Function name='WasLoadedFromAdditionalCourses'/>
<Function name='WasLoadedFromAdditionalSongs'/> <Function name='WasLoadedFromAdditionalSongs'/>
</Class> </Class>
<Class name='SongOptions'>
<Function name='LifeSetting'/>
<Function name='DrainSetting'/>
<Function name='AutosyncSetting'/>
<Function name='BatteryLives'/>
<Function name='AssistClap'/>
<Function name='AssistMetronome'/>
<Function name='StaticBackground'/>
<Function name='RandomBGOnly'/>
<Function name='SaveScore'/>
<Function name='SaveReplay'/>
<Function name='MusicRate'/>
<Function name='Haste'/>
</Class>
<Class name='SongPosition'> <Class name='SongPosition'>
<Function name='GetCurBPS'/> <Function name='GetCurBPS'/>
<Function name='GetDelay'/> <Function name='GetDelay'/>
@@ -1777,6 +1792,12 @@
<EnumValue name='&apos;AttractSoundFrequency_Every4Times&apos;' value='4'/> <EnumValue name='&apos;AttractSoundFrequency_Every4Times&apos;' value='4'/>
<EnumValue name='&apos;AttractSoundFrequency_Every5Times&apos;' value='5'/> <EnumValue name='&apos;AttractSoundFrequency_Every5Times&apos;' value='5'/>
</Enum> </Enum>
<Enum name='AutosyncType'>
<EnumValue name='&apos;AutosyncType_Off&apos;' value='0'/>
<EnumValue name='&apos;AutosyncType_Song&apos;' value='1'/>
<EnumValue name='&apos;AutosyncType_Machine&apos;' value='2'/>
<EnumValue name='&apos;AutosyncType_Tempo&apos;' value='3'/>
</Enum>
<Enum name='BannerCacheMode'> <Enum name='BannerCacheMode'>
<EnumValue name='&apos;BannerCacheMode_Off&apos;' value='0'/> <EnumValue name='&apos;BannerCacheMode_Off&apos;' value='0'/>
<EnumValue name='&apos;BannerCacheMode_LowResPreload&apos;' value='1'/> <EnumValue name='&apos;BannerCacheMode_LowResPreload&apos;' value='1'/>
@@ -1832,6 +1853,11 @@
<EnumValue name='&apos;DisplayBPM_Specified&apos;' value='1'/> <EnumValue name='&apos;DisplayBPM_Specified&apos;' value='1'/>
<EnumValue name='&apos;DisplayBPM_Random&apos;' value='2'/> <EnumValue name='&apos;DisplayBPM_Random&apos;' value='2'/>
</Enum> </Enum>
<Enum name='DrainType'>
<EnumValue name='&apos;DrainType_Normal&apos;' value='0'/>
<EnumValue name='&apos;DrainType_NoRecover&apos;' value='1'/>
<EnumValue name='&apos;DrainType_SuddenDeath&apos;' value='2'/>
</Enum>
<Enum name='DrawMode'> <Enum name='DrawMode'>
<EnumValue name='&apos;DrawMode_Quads&apos;' value='0'/> <EnumValue name='&apos;DrawMode_Quads&apos;' value='0'/>
<EnumValue name='&apos;DrawMode_QuadStrip&apos;' value='1'/> <EnumValue name='&apos;DrawMode_QuadStrip&apos;' value='1'/>
@@ -1951,6 +1977,11 @@
<EnumValue name='&apos;LayoutType_ShowAllInRow&apos;' value='0'/> <EnumValue name='&apos;LayoutType_ShowAllInRow&apos;' value='0'/>
<EnumValue name='&apos;LayoutType_ShowOneInRow&apos;' value='1'/> <EnumValue name='&apos;LayoutType_ShowOneInRow&apos;' value='1'/>
</Enum> </Enum>
<Enum name='LifeType'>
<EnumValue name='&apos;LifeType_Bar&apos;' value='0'/>
<EnumValue name='&apos;LifeType_Battery&apos;' value='1'/>
<EnumValue name='&apos;LifeType_Time&apos;' value='2'/>
</Enum>
<Enum name='LightsMode'> <Enum name='LightsMode'>
<EnumValue name='&apos;LightsMode_Attract&apos;' value='0'/> <EnumValue name='&apos;LightsMode_Attract&apos;' value='0'/>
<EnumValue name='&apos;LightsMode_Joining&apos;' value='1'/> <EnumValue name='&apos;LightsMode_Joining&apos;' value='1'/>
+36 -1
View File
@@ -2330,6 +2330,9 @@ save yourself some time, copy this for undocumented things:
<Function name='GetSongOptionsString' return='string' arguments=''> <Function name='GetSongOptionsString' return='string' arguments=''>
Returns the song options as a string. Returns the song options as a string.
</Function> </Function>
<Function name='GetSongOptionsObject' return='SongOptions' arguments='ModsLevel ml'>
Returns the song options for the specified ModsLevel as an object.
</Function>
<Function name='GetSongPercent' return='float' arguments='float fBeat'> <Function name='GetSongPercent' return='float' arguments='float fBeat'>
Returns how much of the song is through at beat <code>fBeat</code>. Returns how much of the song is through at beat <code>fBeat</code>.
</Function> </Function>
@@ -2825,7 +2828,7 @@ save yourself some time, copy this for undocumented things:
</Class> </Class>
<Class name='PlayerOptions'> <Class name='PlayerOptions'>
<Description> <Description>
Most options fall into one of two types: float or bool.<br /> Most options fall into one of four types: float, int, bool, or enum.<br />
Float type options have this interface:<br /> Float type options have this interface:<br />
Option(value, approach_speed)<br /> Option(value, approach_speed)<br />
If value is a float, sets the TimeSpacing modifier to value.<br /> If value is a float, sets the TimeSpacing modifier to value.<br />
@@ -2838,7 +2841,9 @@ save yourself some time, copy this for undocumented things:
a,b= options:Boost(5) -- Sets a and b to the previous values, NOT to 5 and .5. Sets the value to 5 and leaves the approach speed at whatever it was.<br /> a,b= options:Boost(5) -- Sets a and b to the previous values, NOT to 5 and .5. Sets the value to 5 and leaves the approach speed at whatever it was.<br />
<br /> <br />
Setting the approach speed only matters when modifying the PlayerOptions from ModsLevel_Song.<br /> Setting the approach speed only matters when modifying the PlayerOptions from ModsLevel_Song.<br />
Int type options are similar to float in that they return and take a number, but they do not have an approach speed.<br />
Bool type options have an almost identical interface, the difference is that they can not have an approach speed.<br /> Bool type options have an almost identical interface, the difference is that they can not have an approach speed.<br />
Enum type options are almost identical to bool type. They take and return an enum value.<br />
For brevity, the functions are only given a description if the option requires careful handling or does not follow the float or bool interfaces.<br /> For brevity, the functions are only given a description if the option requires careful handling or does not follow the float or bool interfaces.<br />
</Description> </Description>
<Function name='IsEasierForCourseAndTrail' return='bool' arguments='Course c, Trail t'> <Function name='IsEasierForCourseAndTrail' return='bool' arguments='Course c, Trail t'>
@@ -4039,6 +4044,36 @@ save yourself some time, copy this for undocumented things:
Returns <code>true</code> if the specified song was loaded from AdditionalSongs. Returns <code>true</code> if the specified song was loaded from AdditionalSongs.
</Function> </Function>
</Class> </Class>
<Class name='SongOptions'>
<Description>
See the description for PlayerOptions. The functions follow the same design.
</Description>
<Function name='LifeSetting' return='LifeType' arguments='LifeType type'>
</Function>
<Function name='DrainSetting' return= 'DrainType' arguments='DrainType type'>
</Function>
<Function name='AutosyncSetting' return='AutosyncType' arguments='AutosyncType type'>
</Function>
<Function name='BatteryLives' return='int' arguments='int num'>
</Function>
<Function name='AssistClap' return='bool' arguments='bool b'>
</Function>
<Function name='AssistMetronome' return='bool' arguments='bool b'>
</Function>
<Function name='StaticBackground' return='bool' arguments='bool b'>
</Function>
<Function name='RandomBGOnly' return='bool' arguments='bool b'>
</Function>
<Function name='SaveScore' return='bool' arguments='bool b'>
</Function>
<Function name='SaveReplay' return='bool' arguments='bool b'>
</Function>
<Function name='MusicRate' return='float' arguments='float rate'>
Limited to the range 0 &lt; rate &lt;= 3 because speeds greater than 3 are likely to crash.
</Function>
<Function name='Haste' return='float' arguments='float h'>
</Function>
</Class>
<Class name='SongPosition'> <Class name='SongPosition'>
<Function name='GetCurBPS' return='float' arguments=''> <Function name='GetCurBPS' return='float' arguments=''>
Returns the current beats per second. Returns the current beats per second.
+9 -24
View File
@@ -141,25 +141,22 @@ void AdjustSync::RevertSyncChanges()
static LocalizedString AUTOSYNC_CORRECTION_APPLIED ( "AdjustSync", "Autosync: Correction applied." ); static LocalizedString AUTOSYNC_CORRECTION_APPLIED ( "AdjustSync", "Autosync: Correction applied." );
static LocalizedString AUTOSYNC_CORRECTION_NOT_APPLIED ( "AdjustSync", "Autosync: Correction NOT applied. Deviation too high." ); static LocalizedString AUTOSYNC_CORRECTION_NOT_APPLIED ( "AdjustSync", "Autosync: Correction NOT applied. Deviation too high." );
static LocalizedString AUTOSYNC_SONG ( "AdjustSync", "Autosync Song" );
static LocalizedString AUTOSYNC_MACHINE ( "AdjustSync", "Autosync Machine" );
static LocalizedString AUTOSYNC_TEMPO ( "AdjustSync", "Autosync Tempo" );
void AdjustSync::HandleAutosync( float fNoteOffBySeconds, float fStepTime ) void AdjustSync::HandleAutosync( float fNoteOffBySeconds, float fStepTime )
{ {
if( GAMESTATE->IsCourseMode() ) if( GAMESTATE->IsCourseMode() )
return; return;
SongOptions::AutosyncType type = GAMESTATE->m_SongOptions.GetCurrent().m_AutosyncType; AutosyncType type = GAMESTATE->m_SongOptions.GetCurrent().m_AutosyncType;
switch( type ) { switch( type ) {
case SongOptions::AUTOSYNC_OFF: case AutosyncType_Off:
return; return;
case SongOptions::AUTOSYNC_TEMPO: case AutosyncType_Tempo:
{ {
// We collect all of the data and process it at the end // We collect all of the data and process it at the end
s_vAutosyncTempoData.push_back( make_pair(fStepTime, fNoteOffBySeconds) ); s_vAutosyncTempoData.push_back( make_pair(fStepTime, fNoteOffBySeconds) );
break; break;
} }
case SongOptions::AUTOSYNC_MACHINE: case AutosyncType_Machine:
case SongOptions::AUTOSYNC_SONG: case AutosyncType_Song:
{ {
s_fAutosyncOffset[s_iAutosyncOffsetSample] = fNoteOffBySeconds; s_fAutosyncOffset[s_iAutosyncOffsetSample] = fNoteOffBySeconds;
++s_iAutosyncOffsetSample; ++s_iAutosyncOffsetSample;
@@ -179,7 +176,7 @@ void AdjustSync::HandleSongEnd()
{ {
if( GAMESTATE->IsCourseMode() ) if( GAMESTATE->IsCourseMode() )
return; return;
if( GAMESTATE->m_SongOptions.GetCurrent().m_AutosyncType == SongOptions::AUTOSYNC_TEMPO ) if( GAMESTATE->m_SongOptions.GetCurrent().m_AutosyncType == AutosyncType_Tempo )
{ {
AutosyncTempo(); AutosyncTempo();
} }
@@ -192,25 +189,13 @@ void AdjustSync::AutosyncOffset()
const float mean = calc_mean( s_fAutosyncOffset, s_fAutosyncOffset+OFFSET_SAMPLE_COUNT ); const float mean = calc_mean( s_fAutosyncOffset, s_fAutosyncOffset+OFFSET_SAMPLE_COUNT );
const float stddev = calc_stddev( s_fAutosyncOffset, s_fAutosyncOffset+OFFSET_SAMPLE_COUNT ); const float stddev = calc_stddev( s_fAutosyncOffset, s_fAutosyncOffset+OFFSET_SAMPLE_COUNT );
RString sAutosyncType; AutosyncType type = GAMESTATE->m_SongOptions.GetCurrent().m_AutosyncType;
SongOptions::AutosyncType type = GAMESTATE->m_SongOptions.GetCurrent().m_AutosyncType;
switch( type )
{
case SongOptions::AUTOSYNC_SONG:
sAutosyncType = AUTOSYNC_SONG;
break;
case SongOptions::AUTOSYNC_MACHINE:
sAutosyncType = AUTOSYNC_MACHINE;
break;
default:
FAIL_M(ssprintf("Invalid autosync type: %i", type));
}
if( stddev < .03f ) // If they stepped with less than .03 error if( stddev < .03f ) // If they stepped with less than .03 error
{ {
switch( type ) switch( type )
{ {
case SongOptions::AUTOSYNC_SONG: case AutosyncType_Song:
{ {
GAMESTATE->m_pCurSong->m_SongTiming.m_fBeat0OffsetInSeconds += mean; GAMESTATE->m_pCurSong->m_SongTiming.m_fBeat0OffsetInSeconds += mean;
const vector<Steps *>& vpSteps = GAMESTATE->m_pCurSong->GetAllSteps(); const vector<Steps *>& vpSteps = GAMESTATE->m_pCurSong->GetAllSteps();
@@ -224,7 +209,7 @@ void AdjustSync::AutosyncOffset()
} }
break; break;
} }
case SongOptions::AUTOSYNC_MACHINE: case AutosyncType_Machine:
// Step timing is not needed for this operation. // Step timing is not needed for this operation.
PREFSMAN->m_fGlobalOffsetSeconds.Set( PREFSMAN->m_fGlobalOffsetSeconds + mean ); PREFSMAN->m_fGlobalOffsetSeconds.Set( PREFSMAN->m_fGlobalOffsetSeconds + mean );
break; break;
+2 -2
View File
@@ -805,9 +805,9 @@ void GameCommand::ApplySelf( const vector<PlayerNumber> &vpns ) const
// we don't override the user's changes if they back out. // we don't override the user's changes if they back out.
if( GAMESTATE->m_PlayMode == PLAY_MODE_ONI && if( GAMESTATE->m_PlayMode == PLAY_MODE_ONI &&
GAMESTATE->m_PlayMode != OldPlayMode && GAMESTATE->m_PlayMode != OldPlayMode &&
GAMESTATE->m_SongOptions.GetStage().m_LifeType == SongOptions::LIFE_BAR ) GAMESTATE->m_SongOptions.GetStage().m_LifeType == LifeType_Bar )
{ {
SO_GROUP_ASSIGN( GAMESTATE->m_SongOptions, ModsLevel_Stage, m_LifeType, SongOptions::LIFE_BATTERY ); SO_GROUP_ASSIGN( GAMESTATE->m_SongOptions, ModsLevel_Stage, m_LifeType, LifeType_Battery );
} }
} }
+7
View File
@@ -2366,6 +2366,12 @@ public:
LuaHelpers::Push( L, s ); LuaHelpers::Push( L, s );
return 1; return 1;
} }
static int GetSongOptionsObject( T* p, lua_State *L )
{
ModsLevel m = Enum::Check<ModsLevel>( L, 1 );
p->m_SongOptions.Get(m).PushSelf(L);
return 1;
}
static int GetDefaultSongOptions( T* p, lua_State *L ) static int GetDefaultSongOptions( T* p, lua_State *L )
{ {
SongOptions so; SongOptions so;
@@ -2643,6 +2649,7 @@ public:
ADD_METHOD( GetPremium ); ADD_METHOD( GetPremium );
ADD_METHOD( GetSongOptionsString ); ADD_METHOD( GetSongOptionsString );
ADD_METHOD( GetSongOptions ); ADD_METHOD( GetSongOptions );
ADD_METHOD( GetSongOptionsObject );
ADD_METHOD( GetDefaultSongOptions ); ADD_METHOD( GetDefaultSongOptions );
ADD_METHOD( ApplyPreferredModifiers ); ADD_METHOD( ApplyPreferredModifiers );
ADD_METHOD( ApplyStageModifiers ); ADD_METHOD( ApplyStageModifiers );
+4 -4
View File
@@ -4,13 +4,13 @@
#include "LifeMeterBattery.h" #include "LifeMeterBattery.h"
#include "LifeMeterTime.h" #include "LifeMeterTime.h"
LifeMeter *LifeMeter::MakeLifeMeter( SongOptions::LifeType t ) LifeMeter *LifeMeter::MakeLifeMeter( LifeType t )
{ {
switch( t ) switch( t )
{ {
case SongOptions::LIFE_BAR: return new LifeMeterBar; case LifeType_Bar: return new LifeMeterBar;
case SongOptions::LIFE_BATTERY: return new LifeMeterBattery; case LifeType_Battery: return new LifeMeterBattery;
case SongOptions::LIFE_TIME: return new LifeMeterTime; case LifeType_Time: return new LifeMeterTime;
default: default:
FAIL_M(ssprintf("Unrecognized LifeMeter type: %i", t)); FAIL_M(ssprintf("Unrecognized LifeMeter type: %i", t));
} }
+1 -1
View File
@@ -41,7 +41,7 @@ public:
virtual float GetLife() const { return 0; } // for cosmetic use only virtual float GetLife() const { return 0; } // for cosmetic use only
virtual void UpdateNonstopLifebar() { } virtual void UpdateNonstopLifebar() { }
static LifeMeter *MakeLifeMeter( SongOptions::LifeType t ); static LifeMeter *MakeLifeMeter( LifeType t );
// //
// Lua // Lua
+14 -14
View File
@@ -31,16 +31,16 @@ LifeMeterBar::LifeMeterBar()
m_pPlayerState = NULL; m_pPlayerState = NULL;
SongOptions::DrainType dtype = GAMESTATE->m_SongOptions.GetStage().m_DrainType; DrainType dtype = GAMESTATE->m_SongOptions.GetStage().m_DrainType;
switch( dtype ) switch( dtype )
{ {
case SongOptions::DRAIN_NORMAL: case DrainType_Normal:
m_fLifePercentage = INITIAL_VALUE; m_fLifePercentage = INITIAL_VALUE;
break; break;
/* These types only go down, so they always start at full. */ /* These types only go down, so they always start at full. */
case SongOptions::DRAIN_NO_RECOVER: case DrainType_NoRecover:
case SongOptions::DRAIN_SUDDEN_DEATH: case DrainType_SuddenDeath:
m_fLifePercentage = 1.0f; break; m_fLifePercentage = 1.0f; break;
default: default:
FAIL_M(ssprintf("Invalid DrainType: %i", dtype)); FAIL_M(ssprintf("Invalid DrainType: %i", dtype));
@@ -132,12 +132,12 @@ void LifeMeterBar::ChangeLife( TapNoteScore score )
switch( GAMESTATE->m_SongOptions.GetSong().m_DrainType ) switch( GAMESTATE->m_SongOptions.GetSong().m_DrainType )
{ {
DEFAULT_FAIL( GAMESTATE->m_SongOptions.GetSong().m_DrainType ); DEFAULT_FAIL( GAMESTATE->m_SongOptions.GetSong().m_DrainType );
case SongOptions::DRAIN_NORMAL: case DrainType_Normal:
break; break;
case SongOptions::DRAIN_NO_RECOVER: case DrainType_NoRecover:
fDeltaLife = min( fDeltaLife, 0 ); fDeltaLife = min( fDeltaLife, 0 );
break; break;
case SongOptions::DRAIN_SUDDEN_DEATH: case DrainType_SuddenDeath:
if( score < MIN_STAY_ALIVE ) if( score < MIN_STAY_ALIVE )
fDeltaLife = -1.0f; fDeltaLife = -1.0f;
else else
@@ -151,10 +151,10 @@ void LifeMeterBar::ChangeLife( TapNoteScore score )
void LifeMeterBar::ChangeLife( HoldNoteScore score, TapNoteScore tscore ) void LifeMeterBar::ChangeLife( HoldNoteScore score, TapNoteScore tscore )
{ {
float fDeltaLife=0.f; float fDeltaLife=0.f;
SongOptions::DrainType dtype = GAMESTATE->m_SongOptions.GetSong().m_DrainType; DrainType dtype = GAMESTATE->m_SongOptions.GetSong().m_DrainType;
switch( dtype ) switch( dtype )
{ {
case SongOptions::DRAIN_NORMAL: case DrainType_Normal:
switch( score ) switch( score )
{ {
case HNS_Held: fDeltaLife = m_fLifePercentChange.GetValue(SE_Held); break; case HNS_Held: fDeltaLife = m_fLifePercentChange.GetValue(SE_Held); break;
@@ -166,7 +166,7 @@ void LifeMeterBar::ChangeLife( HoldNoteScore score, TapNoteScore tscore )
if( IsHot() && score == HNS_LetGo ) if( IsHot() && score == HNS_LetGo )
fDeltaLife = -0.10f; // make it take a while to get back to "hot" fDeltaLife = -0.10f; // make it take a while to get back to "hot"
break; break;
case SongOptions::DRAIN_NO_RECOVER: case DrainType_NoRecover:
switch( score ) switch( score )
{ {
case HNS_Held: fDeltaLife = +0.000f; break; case HNS_Held: fDeltaLife = +0.000f; break;
@@ -176,7 +176,7 @@ void LifeMeterBar::ChangeLife( HoldNoteScore score, TapNoteScore tscore )
FAIL_M(ssprintf("Invalid HoldNoteScore: %i", score)); FAIL_M(ssprintf("Invalid HoldNoteScore: %i", score));
} }
break; break;
case SongOptions::DRAIN_SUDDEN_DEATH: case DrainType_SuddenDeath:
switch( score ) switch( score )
{ {
case HNS_Held: fDeltaLife = +0; break; case HNS_Held: fDeltaLife = +0; break;
@@ -221,14 +221,14 @@ void LifeMeterBar::ChangeLife( float fDeltaLife )
switch( GAMESTATE->m_SongOptions.GetSong().m_DrainType ) switch( GAMESTATE->m_SongOptions.GetSong().m_DrainType )
{ {
case SongOptions::DRAIN_NORMAL: case DrainType_Normal:
case SongOptions::DRAIN_NO_RECOVER: case DrainType_NoRecover:
if( fDeltaLife > 0 ) if( fDeltaLife > 0 )
fDeltaLife *= m_fLifeDifficulty; fDeltaLife *= m_fLifeDifficulty;
else else
fDeltaLife /= m_fLifeDifficulty; fDeltaLife /= m_fLifeDifficulty;
break; break;
case SongOptions::DRAIN_SUDDEN_DEATH: case DrainType_SuddenDeath:
// This should always -1.0f; // This should always -1.0f;
if( fDeltaLife < 0 ) if( fDeltaLife < 0 )
fDeltaLife = -1.0f; fDeltaLife = -1.0f;
+19
View File
@@ -376,6 +376,25 @@ LuaClass::~LuaClass()
LUA->Release( L ); LUA->Release( L );
} }
void DefaultNilArgs(lua_State* L, int n)
{
while(lua_gettop(L) < n)
{
lua_pushnil(L);
}
}
float FArgGTEZero(lua_State* L, int index)
{
float s= FArg(index);
if(s < 0)
{
luaL_error(L, "Arg must be greater than or equal to zero.");
}
return s;
}
/* /*
* (c) 2005 Glenn Maynard * (c) 2005 Glenn Maynard
* All rights reserved. * All rights reserved.
+5
View File
@@ -170,6 +170,11 @@ public:
#define LIST_METHOD( method_name ) \ #define LIST_METHOD( method_name ) \
{ #method_name, method_name } { #method_name, method_name }
// Explicitly separates the stack into args and return values.
// This way, the stack can safely be used to store the previous values.
void DefaultNilArgs(lua_State* L, int n);
float FArgGTEZero(lua_State* L, int index);
#endif #endif
/* /*
+2 -2
View File
@@ -628,7 +628,7 @@ void Player::Load()
// TODO: Remove use of PlayerNumber. // TODO: Remove use of PlayerNumber.
PlayerNumber pn = m_pPlayerState->m_PlayerNumber; PlayerNumber pn = m_pPlayerState->m_PlayerNumber;
bool bOniDead = GAMESTATE->m_SongOptions.GetStage().m_LifeType == SongOptions::LIFE_BATTERY && bool bOniDead = GAMESTATE->m_SongOptions.GetStage().m_LifeType == LifeType_Battery &&
(m_pPlayerStageStats == NULL || m_pPlayerStageStats->m_bFailed); (m_pPlayerStageStats == NULL || m_pPlayerStageStats->m_bFailed);
/* The editor reuses Players ... so we really need to make sure everything /* The editor reuses Players ... so we really need to make sure everything
@@ -1781,7 +1781,7 @@ int Player::GetClosestNonEmptyRow( int iNoteRow, int iMaxRowsAhead, int iMaxRows
bool Player::IsOniDead() const bool Player::IsOniDead() const
{ {
// If we're playing on oni and we've died, do nothing. // If we're playing on oni and we've died, do nothing.
return GAMESTATE->m_SongOptions.GetCurrent().m_LifeType == SongOptions::LIFE_BATTERY && m_pPlayerStageStats && m_pPlayerStageStats->m_bFailed; return GAMESTATE->m_SongOptions.GetCurrent().m_LifeType == LifeType_Battery && m_pPlayerStageStats && m_pPlayerStageStats->m_bFailed;
} }
void Player::Fret( int col, int row, const RageTimer &tm, bool bHeld, bool bRelease ) void Player::Fret( int col, int row, const RageTimer &tm, bool bHeld, bool bRelease )
+55 -121
View File
@@ -908,6 +908,7 @@ void PlayerOptions::ResetPrefs( ResetPrefsType type )
// lua start // lua start
#include "LuaBinding.h" #include "LuaBinding.h"
#include "OptionsBinding.h"
/** @brief Allow Lua to have access to PlayerOptions. */ /** @brief Allow Lua to have access to PlayerOptions. */
class LunaPlayerOptions: public Luna<PlayerOptions> class LunaPlayerOptions: public Luna<PlayerOptions>
@@ -930,107 +931,53 @@ public:
return 1; return 1;
} }
static float CheckedApproachSpeed(lua_State* L, float s)
{
if(s < 0)
{
luaL_error(L, "Approach speed must be greater than or equal to zero.");
}
return s;
}
// Explicitly separates the stack into args and return values.
// This way, the stack can safely be used to store the previous values.
static void DefaultNilArgs(lua_State* L, int n)
{
while(lua_gettop(L) < n)
{
lua_pushnil(L);
}
}
// Functions are designed to combine Get and Set into one, to be less clumsy to use. -Kyz
// If a valid arg is passed, the value is set.
// The previous value is returned.
#define FLOAT_INTERFACE(func_name, member) \
static int func_name(T* p, lua_State* L) \
{ \
DefaultNilArgs(L, 2); \
lua_pushnumber(L, p->m_f ## member); \
lua_pushnumber(L, p->m_Speedf ## member); \
if(lua_isnumber(L, 1)) \
{ \
p->m_f ## member = FArg(1); \
if(p->m_Speedf ## member <= 0.0f) \
{ \
p->m_Speedf ## member = 1.0f; \
} \
} \
if(lua_isnumber(L, 2)) \
{ \
p->m_Speedf ## member = CheckedApproachSpeed(L, FArg(2)); \
} \
return 2; \
}
#define BOOL_INTERFACE(func_name, member) \
static int func_name(T* p, lua_State* L) \
{ \
DefaultNilArgs(L, 1); \
lua_pushboolean(L, p->m_b ## member); \
if(lua_isboolean(L, 1)) \
{ \
p->m_b ## member = BArg(1); \
} \
return 1; \
}
// Direct control functions, for themes that can handle it. // Direct control functions, for themes that can handle it.
FLOAT_INTERFACE(TimeSpacing, TimeSpacing); FLOAT_INTERFACE(TimeSpacing, TimeSpacing, true);
FLOAT_INTERFACE(MaxScrollBPM, MaxScrollBPM); FLOAT_INTERFACE(MaxScrollBPM, MaxScrollBPM, true);
FLOAT_INTERFACE(ScrollSpeed, ScrollSpeed); FLOAT_INTERFACE(ScrollSpeed, ScrollSpeed, true);
FLOAT_INTERFACE(ScrollBPM, ScrollBPM); FLOAT_INTERFACE(ScrollBPM, ScrollBPM, true);
FLOAT_INTERFACE(Boost, Accels[PlayerOptions::ACCEL_BOOST]); FLOAT_INTERFACE(Boost, Accels[PlayerOptions::ACCEL_BOOST], true);
FLOAT_INTERFACE(Brake, Accels[PlayerOptions::ACCEL_BRAKE]); FLOAT_INTERFACE(Brake, Accels[PlayerOptions::ACCEL_BRAKE], true);
FLOAT_INTERFACE(Wave, Accels[PlayerOptions::ACCEL_WAVE]); FLOAT_INTERFACE(Wave, Accels[PlayerOptions::ACCEL_WAVE], true);
FLOAT_INTERFACE(Expand, Accels[PlayerOptions::ACCEL_EXPAND]); FLOAT_INTERFACE(Expand, Accels[PlayerOptions::ACCEL_EXPAND], true);
FLOAT_INTERFACE(Boomerang, Accels[PlayerOptions::ACCEL_BOOMERANG]); FLOAT_INTERFACE(Boomerang, Accels[PlayerOptions::ACCEL_BOOMERANG], true);
FLOAT_INTERFACE(Drunk, Effects[PlayerOptions::EFFECT_DRUNK]); FLOAT_INTERFACE(Drunk, Effects[PlayerOptions::EFFECT_DRUNK], true);
FLOAT_INTERFACE(Dizzy, Effects[PlayerOptions::EFFECT_DIZZY]); FLOAT_INTERFACE(Dizzy, Effects[PlayerOptions::EFFECT_DIZZY], true);
FLOAT_INTERFACE(Confusion, Effects[PlayerOptions::EFFECT_CONFUSION]); FLOAT_INTERFACE(Confusion, Effects[PlayerOptions::EFFECT_CONFUSION], true);
FLOAT_INTERFACE(Mini, Effects[PlayerOptions::EFFECT_MINI]); FLOAT_INTERFACE(Mini, Effects[PlayerOptions::EFFECT_MINI], true);
FLOAT_INTERFACE(Tiny, Effects[PlayerOptions::EFFECT_TINY]); FLOAT_INTERFACE(Tiny, Effects[PlayerOptions::EFFECT_TINY], true);
FLOAT_INTERFACE(Flip, Effects[PlayerOptions::EFFECT_FLIP]); FLOAT_INTERFACE(Flip, Effects[PlayerOptions::EFFECT_FLIP], true);
FLOAT_INTERFACE(Invert, Effects[PlayerOptions::EFFECT_INVERT]); FLOAT_INTERFACE(Invert, Effects[PlayerOptions::EFFECT_INVERT], true);
FLOAT_INTERFACE(Tornado, Effects[PlayerOptions::EFFECT_TORNADO]); FLOAT_INTERFACE(Tornado, Effects[PlayerOptions::EFFECT_TORNADO], true);
FLOAT_INTERFACE(Tipsy, Effects[PlayerOptions::EFFECT_TIPSY]); FLOAT_INTERFACE(Tipsy, Effects[PlayerOptions::EFFECT_TIPSY], true);
FLOAT_INTERFACE(Bumpy, Effects[PlayerOptions::EFFECT_BUMPY]); FLOAT_INTERFACE(Bumpy, Effects[PlayerOptions::EFFECT_BUMPY], true);
FLOAT_INTERFACE(Beat, Effects[PlayerOptions::EFFECT_BEAT]); FLOAT_INTERFACE(Beat, Effects[PlayerOptions::EFFECT_BEAT], true);
FLOAT_INTERFACE(Xmode, Effects[PlayerOptions::EFFECT_XMODE]); FLOAT_INTERFACE(Xmode, Effects[PlayerOptions::EFFECT_XMODE], true);
FLOAT_INTERFACE(Twirl, Effects[PlayerOptions::EFFECT_TWIRL]); FLOAT_INTERFACE(Twirl, Effects[PlayerOptions::EFFECT_TWIRL], true);
FLOAT_INTERFACE(Roll, Effects[PlayerOptions::EFFECT_ROLL]); FLOAT_INTERFACE(Roll, Effects[PlayerOptions::EFFECT_ROLL], true);
FLOAT_INTERFACE(Hidden, Appearances[PlayerOptions::APPEARANCE_HIDDEN]); FLOAT_INTERFACE(Hidden, Appearances[PlayerOptions::APPEARANCE_HIDDEN], true);
FLOAT_INTERFACE(HiddenOffset, Appearances[PlayerOptions::APPEARANCE_HIDDEN_OFFSET]); FLOAT_INTERFACE(HiddenOffset, Appearances[PlayerOptions::APPEARANCE_HIDDEN_OFFSET], true);
FLOAT_INTERFACE(Sudden, Appearances[PlayerOptions::APPEARANCE_SUDDEN]); FLOAT_INTERFACE(Sudden, Appearances[PlayerOptions::APPEARANCE_SUDDEN], true);
FLOAT_INTERFACE(SuddenOffset, Appearances[PlayerOptions::APPEARANCE_SUDDEN_OFFSET]); FLOAT_INTERFACE(SuddenOffset, Appearances[PlayerOptions::APPEARANCE_SUDDEN_OFFSET], true);
FLOAT_INTERFACE(Stealth, Appearances[PlayerOptions::APPEARANCE_STEALTH]); FLOAT_INTERFACE(Stealth, Appearances[PlayerOptions::APPEARANCE_STEALTH], true);
FLOAT_INTERFACE(Blink, Appearances[PlayerOptions::APPEARANCE_BLINK]); FLOAT_INTERFACE(Blink, Appearances[PlayerOptions::APPEARANCE_BLINK], true);
FLOAT_INTERFACE(RandomVanish, Appearances[PlayerOptions::APPEARANCE_RANDOMVANISH]); FLOAT_INTERFACE(RandomVanish, Appearances[PlayerOptions::APPEARANCE_RANDOMVANISH], true);
FLOAT_INTERFACE(Reverse, Scrolls[PlayerOptions::SCROLL_REVERSE]); FLOAT_INTERFACE(Reverse, Scrolls[PlayerOptions::SCROLL_REVERSE], true);
FLOAT_INTERFACE(Split, Scrolls[PlayerOptions::SCROLL_SPLIT]); FLOAT_INTERFACE(Split, Scrolls[PlayerOptions::SCROLL_SPLIT], true);
FLOAT_INTERFACE(Alternate, Scrolls[PlayerOptions::SCROLL_ALTERNATE]); FLOAT_INTERFACE(Alternate, Scrolls[PlayerOptions::SCROLL_ALTERNATE], true);
FLOAT_INTERFACE(Cross, Scrolls[PlayerOptions::SCROLL_CROSS]); FLOAT_INTERFACE(Cross, Scrolls[PlayerOptions::SCROLL_CROSS], true);
FLOAT_INTERFACE(Centered, Scrolls[PlayerOptions::SCROLL_CENTERED]); FLOAT_INTERFACE(Centered, Scrolls[PlayerOptions::SCROLL_CENTERED], true);
FLOAT_INTERFACE(Dark, Dark); FLOAT_INTERFACE(Dark, Dark, true);
FLOAT_INTERFACE(Blind, Blind); FLOAT_INTERFACE(Blind, Blind, true);
FLOAT_INTERFACE(Cover, Cover); FLOAT_INTERFACE(Cover, Cover, true);
FLOAT_INTERFACE(RandAttack, RandAttack); FLOAT_INTERFACE(RandAttack, RandAttack, true);
FLOAT_INTERFACE(NoAttack, NoAttack); FLOAT_INTERFACE(NoAttack, NoAttack, true);
FLOAT_INTERFACE(PlayerAutoPlay, PlayerAutoPlay); FLOAT_INTERFACE(PlayerAutoPlay, PlayerAutoPlay, true);
FLOAT_INTERFACE(Skew, Skew); FLOAT_INTERFACE(Skew, Skew, true);
FLOAT_INTERFACE(Tilt, PerspectiveTilt); FLOAT_INTERFACE(Tilt, PerspectiveTilt, true);
FLOAT_INTERFACE(Passmark, Passmark); // Passmark is not sanity checked to the [0, 1] range because LifeMeterBar::IsFailing is the only thing that uses it, and it's used in a <= test. Any theme passing a value outside the [0, 1] range probably expects the result they get. -Kyz FLOAT_INTERFACE(Passmark, Passmark, true); // Passmark is not sanity checked to the [0, 1] range because LifeMeterBar::IsFailing is the only thing that uses it, and it's used in a <= test. Any theme passing a value outside the [0, 1] range probably expects the result they get. -Kyz
FLOAT_INTERFACE(RandomSpeed, RandomSpeed); FLOAT_INTERFACE(RandomSpeed, RandomSpeed, true);
BOOL_INTERFACE(TurnNone, Turns[PlayerOptions::TURN_NONE]); BOOL_INTERFACE(TurnNone, Turns[PlayerOptions::TURN_NONE]);
BOOL_INTERFACE(Mirror, Turns[PlayerOptions::TURN_MIRROR]); BOOL_INTERFACE(Mirror, Turns[PlayerOptions::TURN_MIRROR]);
BOOL_INTERFACE(Backwards, Turns[PlayerOptions::TURN_BACKWARDS]); BOOL_INTERFACE(Backwards, Turns[PlayerOptions::TURN_BACKWARDS]);
@@ -1063,9 +1010,7 @@ public:
BOOL_INTERFACE(NoQuads, Transforms[PlayerOptions::TRANSFORM_NOQUADS]); BOOL_INTERFACE(NoQuads, Transforms[PlayerOptions::TRANSFORM_NOQUADS]);
BOOL_INTERFACE(NoStretch, Transforms[PlayerOptions::TRANSFORM_NOSTRETCH]); BOOL_INTERFACE(NoStretch, Transforms[PlayerOptions::TRANSFORM_NOSTRETCH]);
BOOL_INTERFACE(MuteOnError, MuteOnError); BOOL_INTERFACE(MuteOnError, MuteOnError);
ENUM_INTERFACE(FailSetting, FailType, FailType);
#undef FLOAT_INTERFACE
#undef BOOL_INTERFACE
// NoteSkins // NoteSkins
static int NoteSkin(T* p, lua_State* L) static int NoteSkin(T* p, lua_State* L)
@@ -1098,17 +1043,6 @@ public:
return 2; return 2;
} }
static int FailSetting(T* p, lua_State* L)
{
DefaultNilArgs(L, 1);
Enum::Push(L, p->m_FailType);
if(lua_isstring(L, 1))
{
p->m_FailType= Enum::Check<FailType>(L, 1);
}
return 1;
}
static void SetSpeedModApproaches(T* p, float speed) static void SetSpeedModApproaches(T* p, float speed)
{ {
p->m_SpeedfScrollBPM= speed; p->m_SpeedfScrollBPM= speed;
@@ -1147,7 +1081,7 @@ public:
} }
if(lua_isnumber(L, 2)) if(lua_isnumber(L, 2))
{ {
SetSpeedModApproaches(p, CheckedApproachSpeed(L, FArg(2))); SetSpeedModApproaches(p, FArgGTEZero(L, 2));
} }
return 2; return 2;
} }
@@ -1174,7 +1108,7 @@ public:
} }
if(lua_isnumber(L, 2)) if(lua_isnumber(L, 2))
{ {
SetSpeedModApproaches(p, CheckedApproachSpeed(L, FArg(2))); SetSpeedModApproaches(p, FArgGTEZero(L, 2));
} }
return 2; return 2;
} }
@@ -1206,7 +1140,7 @@ public:
} }
if(lua_isnumber(L, 2)) if(lua_isnumber(L, 2))
{ {
SetSpeedModApproaches(p, CheckedApproachSpeed(L, FArg(2))); SetSpeedModApproaches(p, FArgGTEZero(L, 2));
} }
return 2; return 2;
} }
@@ -1228,7 +1162,7 @@ public:
} }
if(lua_isnumber(L, 2)) if(lua_isnumber(L, 2))
{ {
SetPerspectiveApproach(p, L, CheckedApproachSpeed(L, FArg(2))); SetPerspectiveApproach(p, L, FArgGTEZero(L, 2));
} }
return 1; return 1;
} }
@@ -1255,7 +1189,7 @@ public:
} }
if(lua_isnumber(L, 2)) if(lua_isnumber(L, 2))
{ {
SetPerspectiveApproach(p, L, CheckedApproachSpeed(L, FArg(2))); SetPerspectiveApproach(p, L, FArgGTEZero(L, 2));
} }
return 2; return 2;
} }
@@ -1282,7 +1216,7 @@ public:
} }
if(lua_isnumber(L, 2)) if(lua_isnumber(L, 2))
{ {
SetPerspectiveApproach(p, L, CheckedApproachSpeed(L, FArg(2))); SetPerspectiveApproach(p, L, FArgGTEZero(L, 2));
} }
return 2; return 2;
} }
@@ -1307,7 +1241,7 @@ public:
} }
if(lua_isnumber(L, 2)) if(lua_isnumber(L, 2))
{ {
SetPerspectiveApproach(p, L, CheckedApproachSpeed(L, FArg(2))); SetPerspectiveApproach(p, L, FArgGTEZero(L, 2));
} }
return 2; return 2;
} }
@@ -1332,7 +1266,7 @@ public:
} }
if(lua_isnumber(L, 2)) if(lua_isnumber(L, 2))
{ {
SetPerspectiveApproach(p, L, CheckedApproachSpeed(L, FArg(2))); SetPerspectiveApproach(p, L, FArgGTEZero(L, 2));
} }
return 2; return 2;
} }
+10 -10
View File
@@ -647,28 +647,28 @@ class DebugLineAutosync : public IDebugLine
virtual RString GetDisplayTitle() { return AUTOSYNC.GetValue(); } virtual RString GetDisplayTitle() { return AUTOSYNC.GetValue(); }
virtual RString GetDisplayValue() virtual RString GetDisplayValue()
{ {
SongOptions::AutosyncType type = GAMESTATE->m_SongOptions.GetSong().m_AutosyncType; AutosyncType type = GAMESTATE->m_SongOptions.GetSong().m_AutosyncType;
switch( type ) switch( type )
{ {
case SongOptions::AUTOSYNC_OFF: return OFF.GetValue(); break; case AutosyncType_Off: return OFF.GetValue(); break;
case SongOptions::AUTOSYNC_SONG: return SONG.GetValue(); break; case AutosyncType_Song: return SONG.GetValue(); break;
case SongOptions::AUTOSYNC_MACHINE: return MACHINE.GetValue(); break; case AutosyncType_Machine: return MACHINE.GetValue(); break;
case SongOptions::AUTOSYNC_TEMPO: return SYNC_TEMPO.GetValue(); break; case AutosyncType_Tempo: return SYNC_TEMPO.GetValue(); break;
default: default:
FAIL_M(ssprintf("Invalid autosync type: %i", type)); FAIL_M(ssprintf("Invalid autosync type: %i", type));
} }
} }
virtual Type GetType() const { return IDebugLine::gameplay_only; } virtual Type GetType() const { return IDebugLine::gameplay_only; }
virtual bool IsEnabled() { return GAMESTATE->m_SongOptions.GetSong().m_AutosyncType!=SongOptions::AUTOSYNC_OFF; } virtual bool IsEnabled() { return GAMESTATE->m_SongOptions.GetSong().m_AutosyncType!=AutosyncType_Off; }
virtual void DoAndLog( RString &sMessageOut ) virtual void DoAndLog( RString &sMessageOut )
{ {
int as = GAMESTATE->m_SongOptions.GetSong().m_AutosyncType + 1; int as = GAMESTATE->m_SongOptions.GetSong().m_AutosyncType + 1;
bool bAllowSongAutosync = !GAMESTATE->IsCourseMode(); bool bAllowSongAutosync = !GAMESTATE->IsCourseMode();
if( !bAllowSongAutosync && if( !bAllowSongAutosync &&
( as == SongOptions::AUTOSYNC_SONG || as == SongOptions::AUTOSYNC_TEMPO ) ) ( as == AutosyncType_Song || as == AutosyncType_Tempo ) )
as = SongOptions::AUTOSYNC_MACHINE; as = AutosyncType_Machine;
wrap( as, SongOptions::NUM_AUTOSYNC_TYPES ); wrap( as, NUM_AutosyncType );
SO_GROUP_ASSIGN( GAMESTATE->m_SongOptions, ModsLevel_Song, m_AutosyncType, SongOptions::AutosyncType(as) ); SO_GROUP_ASSIGN( GAMESTATE->m_SongOptions, ModsLevel_Song, m_AutosyncType, AutosyncType(as) );
MESSAGEMAN->Broadcast( Message_AutosyncChanged ); MESSAGEMAN->Broadcast( Message_AutosyncChanged );
IDebugLine::DoAndLog( sMessageOut ); IDebugLine::DoAndLog( sMessageOut );
} }
+10 -10
View File
@@ -135,7 +135,7 @@ void PlayerInfo::Load( PlayerNumber pn, MultiPlayer mp, bool bShowNoteField, int
break; break;
case PLAY_MODE_ONI: case PLAY_MODE_ONI:
case PLAY_MODE_ENDLESS: case PLAY_MODE_ENDLESS:
if( GAMESTATE->m_SongOptions.GetStage().m_LifeType == SongOptions::LIFE_TIME ) if( GAMESTATE->m_SongOptions.GetStage().m_LifeType == LifeType_Time )
m_pPrimaryScoreDisplay = new ScoreDisplayLifeTime; m_pPrimaryScoreDisplay = new ScoreDisplayLifeTime;
else else
m_pPrimaryScoreDisplay = new ScoreDisplayOni; m_pPrimaryScoreDisplay = new ScoreDisplayOni;
@@ -570,7 +570,7 @@ void ScreenGameplay::Init()
// not 100% sure of that. -freem // not 100% sure of that. -freem
if( !GAMESTATE->IsPlayerEnabled(pi->m_pn) && SHOW_LIFE_METER_FOR_DISABLED_PLAYERS ) if( !GAMESTATE->IsPlayerEnabled(pi->m_pn) && SHOW_LIFE_METER_FOR_DISABLED_PLAYERS )
{ {
if(GAMESTATE->m_SongOptions.GetStage().m_LifeType == SongOptions::LIFE_BAR) if(GAMESTATE->m_SongOptions.GetStage().m_LifeType == LifeType_Bar)
static_cast<LifeMeterBar*>(pi->m_pLifeMeter)->ChangeLife(-1.0f); static_cast<LifeMeterBar*>(pi->m_pLifeMeter)->ChangeLife(-1.0f);
} }
} }
@@ -1017,9 +1017,9 @@ void ScreenGameplay::SetupSong( int iSongIndex )
RString sType; RString sType;
switch( GAMESTATE->m_SongOptions.GetCurrent().m_SoundEffectType ) switch( GAMESTATE->m_SongOptions.GetCurrent().m_SoundEffectType )
{ {
case SongOptions::SOUNDEFFECT_OFF: sType = "SoundEffectControl_Off"; break; case SoundEffectType_Off: sType = "SoundEffectControl_Off"; break;
case SongOptions::SOUNDEFFECT_SPEED: sType = "SoundEffectControl_Speed"; break; case SoundEffectType_Speed: sType = "SoundEffectControl_Speed"; break;
case SongOptions::SOUNDEFFECT_PITCH: sType = "SoundEffectControl_Pitch"; break; case SoundEffectType_Pitch: sType = "SoundEffectControl_Pitch"; break;
default: break; default: break;
} }
@@ -1082,7 +1082,7 @@ void ScreenGameplay::LoadNextSong()
/* If we're in battery mode, force FailImmediate. We assume in Player::Step /* If we're in battery mode, force FailImmediate. We assume in Player::Step
* that failed players can't step. */ * that failed players can't step. */
if( GAMESTATE->m_SongOptions.GetCurrent().m_LifeType == SongOptions::LIFE_BATTERY ) if( GAMESTATE->m_SongOptions.GetCurrent().m_LifeType == LifeType_Battery )
{ {
FOREACH_EnabledPlayerInfo( m_vPlayerInfo, pi ) FOREACH_EnabledPlayerInfo( m_vPlayerInfo, pi )
PO_GROUP_ASSIGN( pi->GetPlayerState()->m_PlayerOptions, ModsLevel_Song, m_FailType, FailType_Immediate ); PO_GROUP_ASSIGN( pi->GetPlayerState()->m_PlayerOptions, ModsLevel_Song, m_FailType, FailType_Immediate );
@@ -1118,10 +1118,10 @@ void ScreenGameplay::LoadNextSong()
// reset oni game over graphic // reset oni game over graphic
SET_XY_AND_ON_COMMAND( pi->m_sprOniGameOver ); SET_XY_AND_ON_COMMAND( pi->m_sprOniGameOver );
if( GAMESTATE->m_SongOptions.GetCurrent().m_LifeType==SongOptions::LIFE_BATTERY && pi->GetPlayerStageStats()->m_bFailed ) // already failed if( GAMESTATE->m_SongOptions.GetCurrent().m_LifeType==LifeType_Battery && pi->GetPlayerStageStats()->m_bFailed ) // already failed
pi->ShowOniGameOver(); pi->ShowOniGameOver();
if( GAMESTATE->m_SongOptions.GetCurrent().m_LifeType==SongOptions::LIFE_BAR && pi->m_pLifeMeter ) if( GAMESTATE->m_SongOptions.GetCurrent().m_LifeType==LifeType_Bar && pi->m_pLifeMeter )
pi->m_pLifeMeter->UpdateNonstopLifebar(); pi->m_pLifeMeter->UpdateNonstopLifebar();
if( pi->m_pStepsDisplay ) if( pi->m_pStepsDisplay )
@@ -1634,7 +1634,7 @@ void ScreenGameplay::Update( float fDeltaTime )
PlayerNumber pn = pi->GetStepsAndTrailIndex(); PlayerNumber pn = pi->GetStepsAndTrailIndex();
FailType ft = GAMESTATE->GetPlayerFailType( pi->GetPlayerState() ); FailType ft = GAMESTATE->GetPlayerFailType( pi->GetPlayerState() );
SongOptions::LifeType lt = GAMESTATE->m_SongOptions.GetCurrent().m_LifeType; LifeType lt = GAMESTATE->m_SongOptions.GetCurrent().m_LifeType;
if( ft == FailType_Off || ft == FailType_EndOfSong ) if( ft == FailType_Off || ft == FailType_EndOfSong )
continue; continue;
@@ -1658,7 +1658,7 @@ void ScreenGameplay::Update( float fDeltaTime )
bool bAllowOniDie = false; bool bAllowOniDie = false;
switch( lt ) switch( lt )
{ {
case SongOptions::LIFE_BATTERY: case LifeType_Battery:
bAllowOniDie = true; bAllowOniDie = true;
default: default:
break; break;
+1 -1
View File
@@ -45,7 +45,7 @@ void ScreenGameplaySyncMachine::Init()
ScreenGameplayNormal::Init(); ScreenGameplayNormal::Init();
SO_GROUP_ASSIGN( GAMESTATE->m_SongOptions, ModsLevel_Stage, m_AutosyncType, SongOptions::AUTOSYNC_MACHINE ); SO_GROUP_ASSIGN( GAMESTATE->m_SongOptions, ModsLevel_Stage, m_AutosyncType, AutosyncType_Machine );
ClearMessageQueue(); // remove all of the messages set in ScreenGameplay that animate "ready", "here we go", etc. ClearMessageQueue(); // remove all of the messages set in ScreenGameplay that animate "ready", "here we go", etc.
+1 -1
View File
@@ -198,7 +198,7 @@ void ScreenJukebox::Init()
PO_GROUP_ASSIGN( GAMESTATE->m_pPlayerState[p]->m_PlayerOptions, ModsLevel_Stage, m_fPerspectiveTilt, -1.0f ); PO_GROUP_ASSIGN( GAMESTATE->m_pPlayerState[p]->m_PlayerOptions, ModsLevel_Stage, m_fPerspectiveTilt, -1.0f );
PO_GROUP_ASSIGN_N( GAMESTATE->m_pPlayerState[p]->m_PlayerOptions, ModsLevel_Stage, m_fEffects, PlayerOptions::EFFECT_TINY, 1.0f ); PO_GROUP_ASSIGN_N( GAMESTATE->m_pPlayerState[p]->m_PlayerOptions, ModsLevel_Stage, m_fEffects, PlayerOptions::EFFECT_TINY, 1.0f );
} }
SO_GROUP_ASSIGN( GAMESTATE->m_SongOptions, ModsLevel_Stage, m_LifeType, SongOptions::LIFE_BATTERY ); SO_GROUP_ASSIGN( GAMESTATE->m_SongOptions, ModsLevel_Stage, m_LifeType, LifeType_Battery );
} }
FOREACH_EnabledPlayer( p ) FOREACH_EnabledPlayer( p )
+2 -2
View File
@@ -1247,11 +1247,11 @@ bool ScreenSelectMusic::MenuStart( const InputEventPlus &input )
// apply #LIVES // apply #LIVES
if( pCourse->m_iLives != -1 ) if( pCourse->m_iLives != -1 )
{ {
SO_GROUP_ASSIGN( GAMESTATE->m_SongOptions, ModsLevel_Stage, m_LifeType, SongOptions::LIFE_BATTERY ); SO_GROUP_ASSIGN( GAMESTATE->m_SongOptions, ModsLevel_Stage, m_LifeType, LifeType_Battery );
SO_GROUP_ASSIGN( GAMESTATE->m_SongOptions, ModsLevel_Stage, m_iBatteryLives, pCourse->m_iLives ); SO_GROUP_ASSIGN( GAMESTATE->m_SongOptions, ModsLevel_Stage, m_iBatteryLives, pCourse->m_iLives );
} }
if( pCourse->GetCourseType() == COURSE_TYPE_SURVIVAL) if( pCourse->GetCourseType() == COURSE_TYPE_SURVIVAL)
SO_GROUP_ASSIGN( GAMESTATE->m_SongOptions, ModsLevel_Stage, m_LifeType, SongOptions::LIFE_TIME ); SO_GROUP_ASSIGN( GAMESTATE->m_SongOptions, ModsLevel_Stage, m_LifeType, LifeType_Time );
} }
else else
{ {
+6 -6
View File
@@ -113,13 +113,13 @@ void ScreenSyncOverlay::UpdateText()
} }
} }
SongOptions::AutosyncType type = GAMESTATE->m_SongOptions.GetCurrent().m_AutosyncType; AutosyncType type = GAMESTATE->m_SongOptions.GetCurrent().m_AutosyncType;
switch( type ) switch( type )
{ {
case SongOptions::AUTOSYNC_OFF: break; case AutosyncType_Off: break;
case SongOptions::AUTOSYNC_SONG: vs.push_back(AUTO_SYNC_SONG); break; case AutosyncType_Song: vs.push_back(AUTO_SYNC_SONG); break;
case SongOptions::AUTOSYNC_MACHINE: vs.push_back(AUTO_SYNC_MACHINE); break; case AutosyncType_Machine: vs.push_back(AUTO_SYNC_MACHINE); break;
case SongOptions::AUTOSYNC_TEMPO: vs.push_back(AUTO_SYNC_TEMPO); break; case AutosyncType_Tempo: vs.push_back(AUTO_SYNC_TEMPO); break;
default: default:
FAIL_M(ssprintf("Invalid autosync type: %i", type)); FAIL_M(ssprintf("Invalid autosync type: %i", type));
} }
@@ -134,7 +134,7 @@ void ScreenSyncOverlay::UpdateText()
// Update SyncInfo // Update SyncInfo
bool bVisible = GAMESTATE->m_SongOptions.GetCurrent().m_AutosyncType != SongOptions::AUTOSYNC_OFF; bool bVisible = GAMESTATE->m_SongOptions.GetCurrent().m_AutosyncType != AutosyncType_Off;
m_textAdjustments.SetVisible( bVisible ); m_textAdjustments.SetVisible( bVisible );
if( bVisible ) if( bVisible )
{ {
+112 -30
View File
@@ -4,10 +4,47 @@
#include "GameState.h" #include "GameState.h"
#include "CommonMetrics.h" #include "CommonMetrics.h"
static const char *LifeTypeNames[] = {
"Bar",
"Battery",
"Time",
};
XToString( LifeType );
XToLocalizedString( LifeType );
LuaXType( LifeType );
static const char *DrainTypeNames[] = {
"Normal",
"NoRecover",
"SuddenDeath",
};
XToString( DrainType );
XToLocalizedString( DrainType );
LuaXType( DrainType );
static const char *AutosyncTypeNames[] = {
"Off",
"Song",
"Machine",
"Tempo",
};
XToString( AutosyncType );
XToLocalizedString( AutosyncType );
LuaXType( AutosyncType );
static const char *SoundEffectTypeNames[] = {
"Off",
"Speed",
"Pitch",
};
XToString( SoundEffectType );
XToLocalizedString( SoundEffectType );
LuaXType( SoundEffectType );
void SongOptions::Init() void SongOptions::Init()
{ {
m_LifeType = LIFE_BAR; m_LifeType = LifeType_Bar;
m_DrainType = DRAIN_NORMAL; m_DrainType = DrainType_Normal;
m_iBatteryLives = 4; m_iBatteryLives = 4;
m_bAssistClap = false; m_bAssistClap = false;
m_bAssistMetronome = false; m_bAssistMetronome = false;
@@ -15,8 +52,8 @@ void SongOptions::Init()
m_SpeedfMusicRate = 1.0f; m_SpeedfMusicRate = 1.0f;
m_fHaste = 0.0f; m_fHaste = 0.0f;
m_SpeedfHaste = 1.0f; m_SpeedfHaste = 1.0f;
m_AutosyncType = AUTOSYNC_OFF; m_AutosyncType = AutosyncType_Off;
m_SoundEffectType = SOUNDEFFECT_OFF; m_SoundEffectType = SoundEffectType_Off;
m_bStaticBackground = false; m_bStaticBackground = false;
m_bRandomBGOnly = false; m_bRandomBGOnly = false;
m_bSaveScore = true; m_bSaveScore = true;
@@ -61,18 +98,18 @@ void SongOptions::GetMods( vector<RString> &AddTo ) const
{ {
switch( m_LifeType ) switch( m_LifeType )
{ {
case LIFE_BAR: case LifeType_Bar:
switch( m_DrainType ) switch( m_DrainType )
{ {
case DRAIN_NORMAL: break; case DrainType_Normal: break;
case DRAIN_NO_RECOVER: AddTo.push_back("NoRecover"); break; case DrainType_NoRecover: AddTo.push_back("NoRecover"); break;
case DRAIN_SUDDEN_DEATH: AddTo.push_back("SuddenDeath"); break; case DrainType_SuddenDeath: AddTo.push_back("SuddenDeath"); break;
} }
break; break;
case LIFE_BATTERY: case LifeType_Battery:
AddTo.push_back( ssprintf( "%dLives", m_iBatteryLives ) ); AddTo.push_back( ssprintf( "%dLives", m_iBatteryLives ) );
break; break;
case LIFE_TIME: case LifeType_Time:
AddTo.push_back( "LifeTime" ); AddTo.push_back( "LifeTime" );
break; break;
default: default:
@@ -92,19 +129,19 @@ void SongOptions::GetMods( vector<RString> &AddTo ) const
switch( m_AutosyncType ) switch( m_AutosyncType )
{ {
case AUTOSYNC_OFF: break; case AutosyncType_Off: break;
case AUTOSYNC_SONG: AddTo.push_back("AutosyncSong"); break; case AutosyncType_Song: AddTo.push_back("AutosyncSong"); break;
case AUTOSYNC_MACHINE: AddTo.push_back("AutosyncMachine"); break; case AutosyncType_Machine: AddTo.push_back("AutosyncMachine"); break;
case AUTOSYNC_TEMPO: AddTo.push_back("AutosyncTempo"); break; case AutosyncType_Tempo: AddTo.push_back("AutosyncTempo"); break;
default: default:
FAIL_M(ssprintf("Invalid autosync type: %i", m_AutosyncType)); FAIL_M(ssprintf("Invalid autosync type: %i", m_AutosyncType));
} }
switch( m_SoundEffectType ) switch( m_SoundEffectType )
{ {
case SOUNDEFFECT_OFF: break; case SoundEffectType_Off: break;
case SOUNDEFFECT_SPEED: AddTo.push_back("EffectSpeed"); break; case SoundEffectType_Speed: AddTo.push_back("EffectSpeed"); break;
case SOUNDEFFECT_PITCH: AddTo.push_back("EffectPitch"); break; case SoundEffectType_Pitch: AddTo.push_back("EffectPitch"); break;
default: default:
FAIL_M(ssprintf("Invalid sound effect type: %i", m_SoundEffectType)); FAIL_M(ssprintf("Invalid sound effect type: %i", m_SoundEffectType));
} }
@@ -190,26 +227,26 @@ bool SongOptions::FromOneModString( const RString &sOneMod, RString &sErrorOut )
on = false; on = false;
} }
if( sBit == "norecover" ) m_DrainType = DRAIN_NO_RECOVER; if( sBit == "norecover" ) m_DrainType = DrainType_NoRecover;
else if( sBit == "suddendeath" || sBit == "death" ) m_DrainType = DRAIN_SUDDEN_DEATH; else if( sBit == "suddendeath" || sBit == "death" ) m_DrainType = DrainType_SuddenDeath;
else if( sBit == "power-drop" ) m_DrainType = DRAIN_NO_RECOVER; else if( sBit == "power-drop" ) m_DrainType = DrainType_NoRecover;
else if( sBit == "normal-drain" ) m_DrainType = DRAIN_NORMAL; else if( sBit == "normal-drain" ) m_DrainType = DrainType_Normal;
else if( sBit == "clap" ) m_bAssistClap = on; else if( sBit == "clap" ) m_bAssistClap = on;
else if( sBit == "metronome" ) m_bAssistMetronome = on; else if( sBit == "metronome" ) m_bAssistMetronome = on;
else if( sBit == "autosync" || sBit == "autosyncsong" ) m_AutosyncType = on ? AUTOSYNC_SONG : AUTOSYNC_OFF; else if( sBit == "autosync" || sBit == "autosyncsong" ) m_AutosyncType = on ? AutosyncType_Song : AutosyncType_Off;
else if( sBit == "autosyncmachine" ) m_AutosyncType = on ? AUTOSYNC_MACHINE : AUTOSYNC_OFF; else if( sBit == "autosyncmachine" ) m_AutosyncType = on ? AutosyncType_Machine : AutosyncType_Off;
else if( sBit == "autosynctempo" ) m_AutosyncType = on ? AUTOSYNC_TEMPO : AUTOSYNC_OFF; else if( sBit == "autosynctempo" ) m_AutosyncType = on ? AutosyncType_Tempo : AutosyncType_Off;
else if( sBit == "effect" && !on ) m_SoundEffectType = SOUNDEFFECT_OFF; else if( sBit == "effect" && !on ) m_SoundEffectType = SoundEffectType_Off;
else if( sBit == "effectspeed" ) m_SoundEffectType = on ? SOUNDEFFECT_SPEED : SOUNDEFFECT_OFF; else if( sBit == "effectspeed" ) m_SoundEffectType = on ? SoundEffectType_Speed : SoundEffectType_Off;
else if( sBit == "effectpitch" ) m_SoundEffectType = on ? SOUNDEFFECT_PITCH : SOUNDEFFECT_OFF; else if( sBit == "effectpitch" ) m_SoundEffectType = on ? SoundEffectType_Pitch : SoundEffectType_Off;
else if( sBit == "staticbg" ) m_bStaticBackground = on; else if( sBit == "staticbg" ) m_bStaticBackground = on;
else if( sBit == "randombg" ) m_bRandomBGOnly = on; else if( sBit == "randombg" ) m_bRandomBGOnly = on;
else if( sBit == "savescore" ) m_bSaveScore = on; else if( sBit == "savescore" ) m_bSaveScore = on;
else if( sBit == "savereplay" ) m_bSaveReplay = on; else if( sBit == "savereplay" ) m_bSaveReplay = on;
else if( sBit == "bar" ) m_LifeType = LIFE_BAR; else if( sBit == "bar" ) m_LifeType = LifeType_Bar;
else if( sBit == "battery" ) m_LifeType = LIFE_BATTERY; else if( sBit == "battery" ) m_LifeType = LifeType_Battery;
else if( sBit == "lifetime" ) m_LifeType = LIFE_TIME; else if( sBit == "lifetime" ) m_LifeType = LifeType_Time;
else if( sBit == "haste" ) m_fHaste = on? 1.0f:0.0f; else if( sBit == "haste" ) m_fHaste = on? 1.0f:0.0f;
else else
return false; return false;
@@ -237,6 +274,51 @@ bool SongOptions::operator==( const SongOptions &other ) const
return true; return true;
} }
// lua start
#include "LuaBinding.h"
#include "OptionsBinding.h"
/** @brief Allow Lua to have access to SongOptions. */
class LunaSongOptions: public Luna<SongOptions>
{
public:
ENUM_INTERFACE(LifeSetting, LifeType, LifeType);
ENUM_INTERFACE(DrainSetting, DrainType, DrainType);
ENUM_INTERFACE(AutosyncSetting, AutosyncType, AutosyncType);
//ENUM_INTERFACE(SoundEffectSetting, SoundEffectType, SoundEffectType);
// Broken, SoundEffectType_Speed disables rate mod, other settings have no effect. -Kyz
INT_INTERFACE(BatteryLives, BatteryLives);
BOOL_INTERFACE(AssistClap, AssistClap);
BOOL_INTERFACE(AssistMetronome, AssistMetronome);
BOOL_INTERFACE(StaticBackground, StaticBackground);
BOOL_INTERFACE(RandomBGOnly, RandomBGOnly);
BOOL_INTERFACE(SaveScore, SaveScore);
BOOL_INTERFACE(SaveReplay, SaveReplay);
FLOAT_INTERFACE(MusicRate, MusicRate, (v > 0.0f && v <= 3.0f)); // Greater than 3 seems to crash frequently, haven't investigated why. -Kyz
FLOAT_INTERFACE(Haste, Haste, true);
LunaSongOptions()
{
ADD_METHOD(LifeSetting);
ADD_METHOD(DrainSetting);
ADD_METHOD(AutosyncSetting);
//ADD_METHOD(SoundEffectSetting);
ADD_METHOD(BatteryLives);
ADD_METHOD(AssistClap);
ADD_METHOD(AssistMetronome);
ADD_METHOD(StaticBackground);
ADD_METHOD(RandomBGOnly);
ADD_METHOD(SaveScore);
ADD_METHOD(SaveReplay);
ADD_METHOD(MusicRate);
ADD_METHOD(Haste);
}
};
LUA_REGISTER_CLASS( SongOptions )
// lua end
/* /*
* (c) 2001-2004 Chris Danford, Glenn Maynard * (c) 2001-2004 Chris Danford, Glenn Maynard
* All rights reserved. * All rights reserved.
+57 -29
View File
@@ -3,43 +3,68 @@
#ifndef SONG_OPTIONS_H #ifndef SONG_OPTIONS_H
#define SONG_OPTIONS_H #define SONG_OPTIONS_H
#include "EnumHelper.h"
enum LifeType
{
LifeType_Bar,
LifeType_Battery,
LifeType_Time,
NUM_LifeType,
LifeType_Invalid
};
const RString& LifeTypeToString( LifeType cat );
const RString& LifeTypeToLocalizedString( LifeType cat );
LuaDeclareType( LifeType );
enum DrainType
{
DrainType_Normal,
DrainType_NoRecover,
DrainType_SuddenDeath,
NUM_DrainType,
DrainType_Invalid
};
const RString& DrainTypeToString( DrainType cat );
const RString& DrainTypeToLocalizedString( DrainType cat );
LuaDeclareType( DrainType );
enum AutosyncType
{
AutosyncType_Off,
AutosyncType_Song,
AutosyncType_Machine,
AutosyncType_Tempo,
NUM_AutosyncType,
AutosyncType_Invalid
};
const RString& AutosyncTypeToString( AutosyncType cat );
const RString& AutosyncTypeToLocalizedString( AutosyncType cat );
LuaDeclareType( AutosyncType );
enum SoundEffectType
{
SoundEffectType_Off,
SoundEffectType_Speed,
SoundEffectType_Pitch,
NUM_SoundEffectType,
SoundEffectType_Invalid
};
const RString& SoundEffectTypeToString( SoundEffectType cat );
const RString& SoundEffectTypeToLocalizedString( SoundEffectType cat );
LuaDeclareType( SoundEffectType );
class SongOptions class SongOptions
{ {
public: public:
enum LifeType
{
LIFE_BAR=0,
LIFE_BATTERY,
LIFE_TIME,
NUM_LIFE_TYPES
};
LifeType m_LifeType; LifeType m_LifeType;
enum DrainType
{
DRAIN_NORMAL,
DRAIN_NO_RECOVER,
DRAIN_SUDDEN_DEATH
};
DrainType m_DrainType; // only used with LifeBar DrainType m_DrainType; // only used with LifeBar
int m_iBatteryLives; int m_iBatteryLives;
bool m_bAssistClap; bool m_bAssistClap;
bool m_bAssistMetronome; bool m_bAssistMetronome;
float m_fMusicRate, m_SpeedfMusicRate; float m_fMusicRate, m_SpeedfMusicRate;
float m_fHaste, m_SpeedfHaste; float m_fHaste, m_SpeedfHaste;
enum AutosyncType {
AUTOSYNC_OFF,
AUTOSYNC_SONG,
AUTOSYNC_MACHINE,
AUTOSYNC_TEMPO,
NUM_AUTOSYNC_TYPES
};
AutosyncType m_AutosyncType; AutosyncType m_AutosyncType;
enum SoundEffectType {
SOUNDEFFECT_OFF,
SOUNDEFFECT_SPEED,
SOUNDEFFECT_PITCH,
NUM_SOUNDEFFECT
};
SoundEffectType m_SoundEffectType; SoundEffectType m_SoundEffectType;
bool m_bStaticBackground; bool m_bStaticBackground;
bool m_bRandomBGOnly; bool m_bRandomBGOnly;
@@ -51,12 +76,12 @@ public:
* *
* This is taken from Init(), but uses the intended * This is taken from Init(), but uses the intended
* initialization lists. */ * initialization lists. */
SongOptions(): m_LifeType(LIFE_BAR), m_DrainType(DRAIN_NORMAL), SongOptions(): m_LifeType(LifeType_Bar), m_DrainType(DrainType_Normal),
m_iBatteryLives(4), m_bAssistClap(false), m_iBatteryLives(4), m_bAssistClap(false),
m_bAssistMetronome(false), m_fMusicRate(1.0f), m_bAssistMetronome(false), m_fMusicRate(1.0f),
m_SpeedfMusicRate(1.0f), m_fHaste(0.0f), m_SpeedfMusicRate(1.0f), m_fHaste(0.0f),
m_SpeedfHaste(1.0f), m_AutosyncType(AUTOSYNC_OFF), m_SpeedfHaste(1.0f), m_AutosyncType(AutosyncType_Off),
m_SoundEffectType(SOUNDEFFECT_OFF), m_SoundEffectType(SoundEffectType_Off),
m_bStaticBackground(false), m_bRandomBGOnly(false), m_bStaticBackground(false), m_bRandomBGOnly(false),
m_bSaveScore(true), m_bSaveReplay(false) {}; m_bSaveScore(true), m_bSaveReplay(false) {};
void Init(); void Init();
@@ -70,6 +95,9 @@ public:
bool operator==( const SongOptions &other ) const; bool operator==( const SongOptions &other ) const;
bool operator!=( const SongOptions &other ) const { return !operator==(other); } bool operator!=( const SongOptions &other ) const { return !operator==(other); }
// Lua
void PushSelf( lua_State *L );
}; };
#endif #endif