Merge pull request #151 from kyzentun/player_options_fix

SongOptions Lua interface with the same design as the PlayerOptions interface.
This commit is contained in:
Colby Klein
2014-05-03 20:54:58 -07:00
21 changed files with 479 additions and 258 deletions
+31
View File
@@ -780,6 +780,7 @@
<Function name='GetSongDelay'/>
<Function name='GetSongFreeze'/>
<Function name='GetSongOptions'/>
<Function name='GetSongOptionsObject'/>
<Function name='GetSongOptionsString'/>
<Function name='GetSongPercent'/>
<Function name='GetSongPosition'/>
@@ -1453,6 +1454,20 @@
<Function name='WasLoadedFromAdditionalCourses'/>
<Function name='WasLoadedFromAdditionalSongs'/>
</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'>
<Function name='GetCurBPS'/>
<Function name='GetDelay'/>
@@ -1777,6 +1792,12 @@
<EnumValue name='&apos;AttractSoundFrequency_Every4Times&apos;' value='4'/>
<EnumValue name='&apos;AttractSoundFrequency_Every5Times&apos;' value='5'/>
</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'>
<EnumValue name='&apos;BannerCacheMode_Off&apos;' value='0'/>
<EnumValue name='&apos;BannerCacheMode_LowResPreload&apos;' value='1'/>
@@ -1832,6 +1853,11 @@
<EnumValue name='&apos;DisplayBPM_Specified&apos;' value='1'/>
<EnumValue name='&apos;DisplayBPM_Random&apos;' value='2'/>
</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'>
<EnumValue name='&apos;DrawMode_Quads&apos;' value='0'/>
<EnumValue name='&apos;DrawMode_QuadStrip&apos;' value='1'/>
@@ -1951,6 +1977,11 @@
<EnumValue name='&apos;LayoutType_ShowAllInRow&apos;' value='0'/>
<EnumValue name='&apos;LayoutType_ShowOneInRow&apos;' value='1'/>
</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'>
<EnumValue name='&apos;LightsMode_Attract&apos;' value='0'/>
<EnumValue name='&apos;LightsMode_Joining&apos;' value='1'/>
+36 -1
View File
@@ -2335,6 +2335,9 @@ save yourself some time, copy this for undocumented things:
<Function name='GetSongOptionsString' return='string' arguments=''>
Returns the song options as a string.
</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'>
Returns how much of the song is through at beat <code>fBeat</code>.
</Function>
@@ -2830,7 +2833,7 @@ save yourself some time, copy this for undocumented things:
</Class>
<Class name='PlayerOptions'>
<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 />
Option(value, approach_speed)<br />
If value is a float, sets the TimeSpacing modifier to value.<br />
@@ -2843,7 +2846,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 />
<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 />
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 />
</Description>
<Function name='IsEasierForCourseAndTrail' return='bool' arguments='Course c, Trail t'>
@@ -4044,6 +4049,36 @@ save yourself some time, copy this for undocumented things:
Returns <code>true</code> if the specified song was loaded from AdditionalSongs.
</Function>
</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'>
<Function name='GetCurBPS' return='float' arguments=''>
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_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 )
{
if( GAMESTATE->IsCourseMode() )
return;
SongOptions::AutosyncType type = GAMESTATE->m_SongOptions.GetCurrent().m_AutosyncType;
AutosyncType type = GAMESTATE->m_SongOptions.GetCurrent().m_AutosyncType;
switch( type ) {
case SongOptions::AUTOSYNC_OFF:
case AutosyncType_Off:
return;
case SongOptions::AUTOSYNC_TEMPO:
case AutosyncType_Tempo:
{
// We collect all of the data and process it at the end
s_vAutosyncTempoData.push_back( make_pair(fStepTime, fNoteOffBySeconds) );
break;
}
case SongOptions::AUTOSYNC_MACHINE:
case SongOptions::AUTOSYNC_SONG:
case AutosyncType_Machine:
case AutosyncType_Song:
{
s_fAutosyncOffset[s_iAutosyncOffsetSample] = fNoteOffBySeconds;
++s_iAutosyncOffsetSample;
@@ -179,7 +176,7 @@ void AdjustSync::HandleSongEnd()
{
if( GAMESTATE->IsCourseMode() )
return;
if( GAMESTATE->m_SongOptions.GetCurrent().m_AutosyncType == SongOptions::AUTOSYNC_TEMPO )
if( GAMESTATE->m_SongOptions.GetCurrent().m_AutosyncType == AutosyncType_Tempo )
{
AutosyncTempo();
}
@@ -192,25 +189,13 @@ void AdjustSync::AutosyncOffset()
const float mean = calc_mean( s_fAutosyncOffset, s_fAutosyncOffset+OFFSET_SAMPLE_COUNT );
const float stddev = calc_stddev( s_fAutosyncOffset, s_fAutosyncOffset+OFFSET_SAMPLE_COUNT );
RString sAutosyncType;
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));
}
AutosyncType type = GAMESTATE->m_SongOptions.GetCurrent().m_AutosyncType;
if( stddev < .03f ) // If they stepped with less than .03 error
{
switch( type )
{
case SongOptions::AUTOSYNC_SONG:
case AutosyncType_Song:
{
GAMESTATE->m_pCurSong->m_SongTiming.m_fBeat0OffsetInSeconds += mean;
const vector<Steps *>& vpSteps = GAMESTATE->m_pCurSong->GetAllSteps();
@@ -224,7 +209,7 @@ void AdjustSync::AutosyncOffset()
}
break;
}
case SongOptions::AUTOSYNC_MACHINE:
case AutosyncType_Machine:
// Step timing is not needed for this operation.
PREFSMAN->m_fGlobalOffsetSeconds.Set( PREFSMAN->m_fGlobalOffsetSeconds + mean );
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.
if( GAMESTATE->m_PlayMode == PLAY_MODE_ONI &&
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 );
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 )
{
SongOptions so;
@@ -2643,6 +2649,7 @@ public:
ADD_METHOD( GetPremium );
ADD_METHOD( GetSongOptionsString );
ADD_METHOD( GetSongOptions );
ADD_METHOD( GetSongOptionsObject );
ADD_METHOD( GetDefaultSongOptions );
ADD_METHOD( ApplyPreferredModifiers );
ADD_METHOD( ApplyStageModifiers );
+4 -4
View File
@@ -4,13 +4,13 @@
#include "LifeMeterBattery.h"
#include "LifeMeterTime.h"
LifeMeter *LifeMeter::MakeLifeMeter( SongOptions::LifeType t )
LifeMeter *LifeMeter::MakeLifeMeter( LifeType t )
{
switch( t )
{
case SongOptions::LIFE_BAR: return new LifeMeterBar;
case SongOptions::LIFE_BATTERY: return new LifeMeterBattery;
case SongOptions::LIFE_TIME: return new LifeMeterTime;
case LifeType_Bar: return new LifeMeterBar;
case LifeType_Battery: return new LifeMeterBattery;
case LifeType_Time: return new LifeMeterTime;
default:
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 void UpdateNonstopLifebar() { }
static LifeMeter *MakeLifeMeter( SongOptions::LifeType t );
static LifeMeter *MakeLifeMeter( LifeType t );
//
// Lua
+14 -14
View File
@@ -31,16 +31,16 @@ LifeMeterBar::LifeMeterBar()
m_pPlayerState = NULL;
SongOptions::DrainType dtype = GAMESTATE->m_SongOptions.GetStage().m_DrainType;
DrainType dtype = GAMESTATE->m_SongOptions.GetStage().m_DrainType;
switch( dtype )
{
case SongOptions::DRAIN_NORMAL:
case DrainType_Normal:
m_fLifePercentage = INITIAL_VALUE;
break;
/* These types only go down, so they always start at full. */
case SongOptions::DRAIN_NO_RECOVER:
case SongOptions::DRAIN_SUDDEN_DEATH:
case DrainType_NoRecover:
case DrainType_SuddenDeath:
m_fLifePercentage = 1.0f; break;
default:
FAIL_M(ssprintf("Invalid DrainType: %i", dtype));
@@ -132,12 +132,12 @@ void LifeMeterBar::ChangeLife( TapNoteScore score )
switch( GAMESTATE->m_SongOptions.GetSong().m_DrainType )
{
DEFAULT_FAIL( GAMESTATE->m_SongOptions.GetSong().m_DrainType );
case SongOptions::DRAIN_NORMAL:
case DrainType_Normal:
break;
case SongOptions::DRAIN_NO_RECOVER:
case DrainType_NoRecover:
fDeltaLife = min( fDeltaLife, 0 );
break;
case SongOptions::DRAIN_SUDDEN_DEATH:
case DrainType_SuddenDeath:
if( score < MIN_STAY_ALIVE )
fDeltaLife = -1.0f;
else
@@ -151,10 +151,10 @@ void LifeMeterBar::ChangeLife( TapNoteScore score )
void LifeMeterBar::ChangeLife( HoldNoteScore score, TapNoteScore tscore )
{
float fDeltaLife=0.f;
SongOptions::DrainType dtype = GAMESTATE->m_SongOptions.GetSong().m_DrainType;
DrainType dtype = GAMESTATE->m_SongOptions.GetSong().m_DrainType;
switch( dtype )
{
case SongOptions::DRAIN_NORMAL:
case DrainType_Normal:
switch( score )
{
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 )
fDeltaLife = -0.10f; // make it take a while to get back to "hot"
break;
case SongOptions::DRAIN_NO_RECOVER:
case DrainType_NoRecover:
switch( score )
{
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));
}
break;
case SongOptions::DRAIN_SUDDEN_DEATH:
case DrainType_SuddenDeath:
switch( score )
{
case HNS_Held: fDeltaLife = +0; break;
@@ -221,14 +221,14 @@ void LifeMeterBar::ChangeLife( float fDeltaLife )
switch( GAMESTATE->m_SongOptions.GetSong().m_DrainType )
{
case SongOptions::DRAIN_NORMAL:
case SongOptions::DRAIN_NO_RECOVER:
case DrainType_Normal:
case DrainType_NoRecover:
if( fDeltaLife > 0 )
fDeltaLife *= m_fLifeDifficulty;
else
fDeltaLife /= m_fLifeDifficulty;
break;
case SongOptions::DRAIN_SUDDEN_DEATH:
case DrainType_SuddenDeath:
// This should always -1.0f;
if( fDeltaLife < 0 )
fDeltaLife = -1.0f;
+19
View File
@@ -376,6 +376,25 @@ LuaClass::~LuaClass()
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
* All rights reserved.
+5
View File
@@ -170,6 +170,11 @@ public:
#define LIST_METHOD( 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
/*
+95
View File
@@ -0,0 +1,95 @@
/* OptionsBinding - little helpers so that SongOptions and PlayerOptions can more easily have similar interfaces. */
// No .cpp file because it's just some #defines, and not in a makefile because it doesn't need to be.
// DefaultNilArgs would be in here, but then there would need to be a .cpp file, and DefaultNilArgs is more widely useful.
#ifndef OptionsBinding_H
#define OptionsBinding_H
// 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, valid) \
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)) \
{ \
float v= FArg(1); \
if(!valid) \
{ \
luaL_error(L, "Invalid value %f", v); \
} \
p->m_f ## member = v; \
if(p->m_Speedf ## member <= 0.0f) \
{ \
p->m_Speedf ## member = 1.0f; \
} \
} \
if(lua_isnumber(L, 2)) \
{ \
p->m_Speedf ## member = FArgGTEZero(L, 2); \
} \
return 2; \
}
#define INT_INTERFACE(func_name, member) \
static int func_name(T* p, lua_State* L) \
{ \
DefaultNilArgs(L, 1); \
lua_pushnumber(L, p->m_i ## member); \
if(lua_isnumber(L, 1)) \
{ \
p->m_i ## member = IArg(1); \
} \
return 1; \
}
#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; \
}
#define ENUM_INTERFACE(func_name, member, enum_name) \
static int func_name(T* p, lua_State* L) \
{ \
DefaultNilArgs(L, 1); \
Enum::Push(L, p->m_ ## member); \
if(!lua_isnil(L, 1)) \
{ \
p->m_ ## member= Enum::Check<enum_name>(L, 1); \
} \
return 1; \
}
#endif
/*
* (c) 2014 Eric Reese
* 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.
*/
+2 -2
View File
@@ -629,7 +629,7 @@ void Player::Load()
// TODO: Remove use of 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);
/* The editor reuses Players ... so we really need to make sure everything
@@ -1782,7 +1782,7 @@ int Player::GetClosestNonEmptyRow( int iNoteRow, int iMaxRowsAhead, int iMaxRows
bool Player::IsOniDead() const
{
// 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 )
+55 -121
View File
@@ -908,6 +908,7 @@ void PlayerOptions::ResetPrefs( ResetPrefsType type )
// lua start
#include "LuaBinding.h"
#include "OptionsBinding.h"
/** @brief Allow Lua to have access to PlayerOptions. */
class LunaPlayerOptions: public Luna<PlayerOptions>
@@ -930,107 +931,53 @@ public:
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.
FLOAT_INTERFACE(TimeSpacing, TimeSpacing);
FLOAT_INTERFACE(MaxScrollBPM, MaxScrollBPM);
FLOAT_INTERFACE(ScrollSpeed, ScrollSpeed);
FLOAT_INTERFACE(ScrollBPM, ScrollBPM);
FLOAT_INTERFACE(Boost, Accels[PlayerOptions::ACCEL_BOOST]);
FLOAT_INTERFACE(Brake, Accels[PlayerOptions::ACCEL_BRAKE]);
FLOAT_INTERFACE(Wave, Accels[PlayerOptions::ACCEL_WAVE]);
FLOAT_INTERFACE(Expand, Accels[PlayerOptions::ACCEL_EXPAND]);
FLOAT_INTERFACE(Boomerang, Accels[PlayerOptions::ACCEL_BOOMERANG]);
FLOAT_INTERFACE(Drunk, Effects[PlayerOptions::EFFECT_DRUNK]);
FLOAT_INTERFACE(Dizzy, Effects[PlayerOptions::EFFECT_DIZZY]);
FLOAT_INTERFACE(Confusion, Effects[PlayerOptions::EFFECT_CONFUSION]);
FLOAT_INTERFACE(Mini, Effects[PlayerOptions::EFFECT_MINI]);
FLOAT_INTERFACE(Tiny, Effects[PlayerOptions::EFFECT_TINY]);
FLOAT_INTERFACE(Flip, Effects[PlayerOptions::EFFECT_FLIP]);
FLOAT_INTERFACE(Invert, Effects[PlayerOptions::EFFECT_INVERT]);
FLOAT_INTERFACE(Tornado, Effects[PlayerOptions::EFFECT_TORNADO]);
FLOAT_INTERFACE(Tipsy, Effects[PlayerOptions::EFFECT_TIPSY]);
FLOAT_INTERFACE(Bumpy, Effects[PlayerOptions::EFFECT_BUMPY]);
FLOAT_INTERFACE(Beat, Effects[PlayerOptions::EFFECT_BEAT]);
FLOAT_INTERFACE(Xmode, Effects[PlayerOptions::EFFECT_XMODE]);
FLOAT_INTERFACE(Twirl, Effects[PlayerOptions::EFFECT_TWIRL]);
FLOAT_INTERFACE(Roll, Effects[PlayerOptions::EFFECT_ROLL]);
FLOAT_INTERFACE(Hidden, Appearances[PlayerOptions::APPEARANCE_HIDDEN]);
FLOAT_INTERFACE(HiddenOffset, Appearances[PlayerOptions::APPEARANCE_HIDDEN_OFFSET]);
FLOAT_INTERFACE(Sudden, Appearances[PlayerOptions::APPEARANCE_SUDDEN]);
FLOAT_INTERFACE(SuddenOffset, Appearances[PlayerOptions::APPEARANCE_SUDDEN_OFFSET]);
FLOAT_INTERFACE(Stealth, Appearances[PlayerOptions::APPEARANCE_STEALTH]);
FLOAT_INTERFACE(Blink, Appearances[PlayerOptions::APPEARANCE_BLINK]);
FLOAT_INTERFACE(RandomVanish, Appearances[PlayerOptions::APPEARANCE_RANDOMVANISH]);
FLOAT_INTERFACE(Reverse, Scrolls[PlayerOptions::SCROLL_REVERSE]);
FLOAT_INTERFACE(Split, Scrolls[PlayerOptions::SCROLL_SPLIT]);
FLOAT_INTERFACE(Alternate, Scrolls[PlayerOptions::SCROLL_ALTERNATE]);
FLOAT_INTERFACE(Cross, Scrolls[PlayerOptions::SCROLL_CROSS]);
FLOAT_INTERFACE(Centered, Scrolls[PlayerOptions::SCROLL_CENTERED]);
FLOAT_INTERFACE(Dark, Dark);
FLOAT_INTERFACE(Blind, Blind);
FLOAT_INTERFACE(Cover, Cover);
FLOAT_INTERFACE(RandAttack, RandAttack);
FLOAT_INTERFACE(NoAttack, NoAttack);
FLOAT_INTERFACE(PlayerAutoPlay, PlayerAutoPlay);
FLOAT_INTERFACE(Skew, Skew);
FLOAT_INTERFACE(Tilt, PerspectiveTilt);
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(RandomSpeed, RandomSpeed);
FLOAT_INTERFACE(TimeSpacing, TimeSpacing, true);
FLOAT_INTERFACE(MaxScrollBPM, MaxScrollBPM, true);
FLOAT_INTERFACE(ScrollSpeed, ScrollSpeed, true);
FLOAT_INTERFACE(ScrollBPM, ScrollBPM, true);
FLOAT_INTERFACE(Boost, Accels[PlayerOptions::ACCEL_BOOST], true);
FLOAT_INTERFACE(Brake, Accels[PlayerOptions::ACCEL_BRAKE], true);
FLOAT_INTERFACE(Wave, Accels[PlayerOptions::ACCEL_WAVE], true);
FLOAT_INTERFACE(Expand, Accels[PlayerOptions::ACCEL_EXPAND], true);
FLOAT_INTERFACE(Boomerang, Accels[PlayerOptions::ACCEL_BOOMERANG], true);
FLOAT_INTERFACE(Drunk, Effects[PlayerOptions::EFFECT_DRUNK], true);
FLOAT_INTERFACE(Dizzy, Effects[PlayerOptions::EFFECT_DIZZY], true);
FLOAT_INTERFACE(Confusion, Effects[PlayerOptions::EFFECT_CONFUSION], true);
FLOAT_INTERFACE(Mini, Effects[PlayerOptions::EFFECT_MINI], true);
FLOAT_INTERFACE(Tiny, Effects[PlayerOptions::EFFECT_TINY], true);
FLOAT_INTERFACE(Flip, Effects[PlayerOptions::EFFECT_FLIP], true);
FLOAT_INTERFACE(Invert, Effects[PlayerOptions::EFFECT_INVERT], true);
FLOAT_INTERFACE(Tornado, Effects[PlayerOptions::EFFECT_TORNADO], true);
FLOAT_INTERFACE(Tipsy, Effects[PlayerOptions::EFFECT_TIPSY], true);
FLOAT_INTERFACE(Bumpy, Effects[PlayerOptions::EFFECT_BUMPY], true);
FLOAT_INTERFACE(Beat, Effects[PlayerOptions::EFFECT_BEAT], true);
FLOAT_INTERFACE(Xmode, Effects[PlayerOptions::EFFECT_XMODE], true);
FLOAT_INTERFACE(Twirl, Effects[PlayerOptions::EFFECT_TWIRL], true);
FLOAT_INTERFACE(Roll, Effects[PlayerOptions::EFFECT_ROLL], true);
FLOAT_INTERFACE(Hidden, Appearances[PlayerOptions::APPEARANCE_HIDDEN], true);
FLOAT_INTERFACE(HiddenOffset, Appearances[PlayerOptions::APPEARANCE_HIDDEN_OFFSET], true);
FLOAT_INTERFACE(Sudden, Appearances[PlayerOptions::APPEARANCE_SUDDEN], true);
FLOAT_INTERFACE(SuddenOffset, Appearances[PlayerOptions::APPEARANCE_SUDDEN_OFFSET], true);
FLOAT_INTERFACE(Stealth, Appearances[PlayerOptions::APPEARANCE_STEALTH], true);
FLOAT_INTERFACE(Blink, Appearances[PlayerOptions::APPEARANCE_BLINK], true);
FLOAT_INTERFACE(RandomVanish, Appearances[PlayerOptions::APPEARANCE_RANDOMVANISH], true);
FLOAT_INTERFACE(Reverse, Scrolls[PlayerOptions::SCROLL_REVERSE], true);
FLOAT_INTERFACE(Split, Scrolls[PlayerOptions::SCROLL_SPLIT], true);
FLOAT_INTERFACE(Alternate, Scrolls[PlayerOptions::SCROLL_ALTERNATE], true);
FLOAT_INTERFACE(Cross, Scrolls[PlayerOptions::SCROLL_CROSS], true);
FLOAT_INTERFACE(Centered, Scrolls[PlayerOptions::SCROLL_CENTERED], true);
FLOAT_INTERFACE(Dark, Dark, true);
FLOAT_INTERFACE(Blind, Blind, true);
FLOAT_INTERFACE(Cover, Cover, true);
FLOAT_INTERFACE(RandAttack, RandAttack, true);
FLOAT_INTERFACE(NoAttack, NoAttack, true);
FLOAT_INTERFACE(PlayerAutoPlay, PlayerAutoPlay, true);
FLOAT_INTERFACE(Skew, Skew, true);
FLOAT_INTERFACE(Tilt, PerspectiveTilt, true);
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, true);
BOOL_INTERFACE(TurnNone, Turns[PlayerOptions::TURN_NONE]);
BOOL_INTERFACE(Mirror, Turns[PlayerOptions::TURN_MIRROR]);
BOOL_INTERFACE(Backwards, Turns[PlayerOptions::TURN_BACKWARDS]);
@@ -1063,9 +1010,7 @@ public:
BOOL_INTERFACE(NoQuads, Transforms[PlayerOptions::TRANSFORM_NOQUADS]);
BOOL_INTERFACE(NoStretch, Transforms[PlayerOptions::TRANSFORM_NOSTRETCH]);
BOOL_INTERFACE(MuteOnError, MuteOnError);
#undef FLOAT_INTERFACE
#undef BOOL_INTERFACE
ENUM_INTERFACE(FailSetting, FailType, FailType);
// NoteSkins
static int NoteSkin(T* p, lua_State* L)
@@ -1098,17 +1043,6 @@ public:
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)
{
p->m_SpeedfScrollBPM= speed;
@@ -1147,7 +1081,7 @@ public:
}
if(lua_isnumber(L, 2))
{
SetSpeedModApproaches(p, CheckedApproachSpeed(L, FArg(2)));
SetSpeedModApproaches(p, FArgGTEZero(L, 2));
}
return 2;
}
@@ -1174,7 +1108,7 @@ public:
}
if(lua_isnumber(L, 2))
{
SetSpeedModApproaches(p, CheckedApproachSpeed(L, FArg(2)));
SetSpeedModApproaches(p, FArgGTEZero(L, 2));
}
return 2;
}
@@ -1206,7 +1140,7 @@ public:
}
if(lua_isnumber(L, 2))
{
SetSpeedModApproaches(p, CheckedApproachSpeed(L, FArg(2)));
SetSpeedModApproaches(p, FArgGTEZero(L, 2));
}
return 2;
}
@@ -1228,7 +1162,7 @@ public:
}
if(lua_isnumber(L, 2))
{
SetPerspectiveApproach(p, L, CheckedApproachSpeed(L, FArg(2)));
SetPerspectiveApproach(p, L, FArgGTEZero(L, 2));
}
return 1;
}
@@ -1255,7 +1189,7 @@ public:
}
if(lua_isnumber(L, 2))
{
SetPerspectiveApproach(p, L, CheckedApproachSpeed(L, FArg(2)));
SetPerspectiveApproach(p, L, FArgGTEZero(L, 2));
}
return 2;
}
@@ -1282,7 +1216,7 @@ public:
}
if(lua_isnumber(L, 2))
{
SetPerspectiveApproach(p, L, CheckedApproachSpeed(L, FArg(2)));
SetPerspectiveApproach(p, L, FArgGTEZero(L, 2));
}
return 2;
}
@@ -1307,7 +1241,7 @@ public:
}
if(lua_isnumber(L, 2))
{
SetPerspectiveApproach(p, L, CheckedApproachSpeed(L, FArg(2)));
SetPerspectiveApproach(p, L, FArgGTEZero(L, 2));
}
return 2;
}
@@ -1332,7 +1266,7 @@ public:
}
if(lua_isnumber(L, 2))
{
SetPerspectiveApproach(p, L, CheckedApproachSpeed(L, FArg(2)));
SetPerspectiveApproach(p, L, FArgGTEZero(L, 2));
}
return 2;
}
+10 -10
View File
@@ -647,28 +647,28 @@ class DebugLineAutosync : public IDebugLine
virtual RString GetDisplayTitle() { return AUTOSYNC.GetValue(); }
virtual RString GetDisplayValue()
{
SongOptions::AutosyncType type = GAMESTATE->m_SongOptions.GetSong().m_AutosyncType;
AutosyncType type = GAMESTATE->m_SongOptions.GetSong().m_AutosyncType;
switch( type )
{
case SongOptions::AUTOSYNC_OFF: return OFF.GetValue(); break;
case SongOptions::AUTOSYNC_SONG: return SONG.GetValue(); break;
case SongOptions::AUTOSYNC_MACHINE: return MACHINE.GetValue(); break;
case SongOptions::AUTOSYNC_TEMPO: return SYNC_TEMPO.GetValue(); break;
case AutosyncType_Off: return OFF.GetValue(); break;
case AutosyncType_Song: return SONG.GetValue(); break;
case AutosyncType_Machine: return MACHINE.GetValue(); break;
case AutosyncType_Tempo: return SYNC_TEMPO.GetValue(); break;
default:
FAIL_M(ssprintf("Invalid autosync type: %i", type));
}
}
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 )
{
int as = GAMESTATE->m_SongOptions.GetSong().m_AutosyncType + 1;
bool bAllowSongAutosync = !GAMESTATE->IsCourseMode();
if( !bAllowSongAutosync &&
( as == SongOptions::AUTOSYNC_SONG || as == SongOptions::AUTOSYNC_TEMPO ) )
as = SongOptions::AUTOSYNC_MACHINE;
wrap( as, SongOptions::NUM_AUTOSYNC_TYPES );
SO_GROUP_ASSIGN( GAMESTATE->m_SongOptions, ModsLevel_Song, m_AutosyncType, SongOptions::AutosyncType(as) );
( as == AutosyncType_Song || as == AutosyncType_Tempo ) )
as = AutosyncType_Machine;
wrap( as, NUM_AutosyncType );
SO_GROUP_ASSIGN( GAMESTATE->m_SongOptions, ModsLevel_Song, m_AutosyncType, AutosyncType(as) );
MESSAGEMAN->Broadcast( Message_AutosyncChanged );
IDebugLine::DoAndLog( sMessageOut );
}
+10 -10
View File
@@ -135,7 +135,7 @@ void PlayerInfo::Load( PlayerNumber pn, MultiPlayer mp, bool bShowNoteField, int
break;
case PLAY_MODE_ONI:
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;
else
m_pPrimaryScoreDisplay = new ScoreDisplayOni;
@@ -570,7 +570,7 @@ void ScreenGameplay::Init()
// not 100% sure of that. -freem
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);
}
}
@@ -1017,9 +1017,9 @@ void ScreenGameplay::SetupSong( int iSongIndex )
RString sType;
switch( GAMESTATE->m_SongOptions.GetCurrent().m_SoundEffectType )
{
case SongOptions::SOUNDEFFECT_OFF: sType = "SoundEffectControl_Off"; break;
case SongOptions::SOUNDEFFECT_SPEED: sType = "SoundEffectControl_Speed"; break;
case SongOptions::SOUNDEFFECT_PITCH: sType = "SoundEffectControl_Pitch"; break;
case SoundEffectType_Off: sType = "SoundEffectControl_Off"; break;
case SoundEffectType_Speed: sType = "SoundEffectControl_Speed"; break;
case SoundEffectType_Pitch: sType = "SoundEffectControl_Pitch"; break;
default: break;
}
@@ -1082,7 +1082,7 @@ void ScreenGameplay::LoadNextSong()
/* If we're in battery mode, force FailImmediate. We assume in Player::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 )
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
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();
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();
if( pi->m_pStepsDisplay )
@@ -1634,7 +1634,7 @@ void ScreenGameplay::Update( float fDeltaTime )
PlayerNumber pn = pi->GetStepsAndTrailIndex();
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 )
continue;
@@ -1658,7 +1658,7 @@ void ScreenGameplay::Update( float fDeltaTime )
bool bAllowOniDie = false;
switch( lt )
{
case SongOptions::LIFE_BATTERY:
case LifeType_Battery:
bAllowOniDie = true;
default:
break;
+1 -1
View File
@@ -45,7 +45,7 @@ void ScreenGameplaySyncMachine::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.
+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_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 )
+2 -2
View File
@@ -1247,11 +1247,11 @@ bool ScreenSelectMusic::MenuStart( const InputEventPlus &input )
// apply #LIVES
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 );
}
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
{
+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 )
{
case SongOptions::AUTOSYNC_OFF: break;
case SongOptions::AUTOSYNC_SONG: vs.push_back(AUTO_SYNC_SONG); break;
case SongOptions::AUTOSYNC_MACHINE: vs.push_back(AUTO_SYNC_MACHINE); break;
case SongOptions::AUTOSYNC_TEMPO: vs.push_back(AUTO_SYNC_TEMPO); break;
case AutosyncType_Off: break;
case AutosyncType_Song: vs.push_back(AUTO_SYNC_SONG); break;
case AutosyncType_Machine: vs.push_back(AUTO_SYNC_MACHINE); break;
case AutosyncType_Tempo: vs.push_back(AUTO_SYNC_TEMPO); break;
default:
FAIL_M(ssprintf("Invalid autosync type: %i", type));
}
@@ -134,7 +134,7 @@ void ScreenSyncOverlay::UpdateText()
// 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 );
if( bVisible )
{
+112 -30
View File
@@ -4,10 +4,47 @@
#include "GameState.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()
{
m_LifeType = LIFE_BAR;
m_DrainType = DRAIN_NORMAL;
m_LifeType = LifeType_Bar;
m_DrainType = DrainType_Normal;
m_iBatteryLives = 4;
m_bAssistClap = false;
m_bAssistMetronome = false;
@@ -15,8 +52,8 @@ void SongOptions::Init()
m_SpeedfMusicRate = 1.0f;
m_fHaste = 0.0f;
m_SpeedfHaste = 1.0f;
m_AutosyncType = AUTOSYNC_OFF;
m_SoundEffectType = SOUNDEFFECT_OFF;
m_AutosyncType = AutosyncType_Off;
m_SoundEffectType = SoundEffectType_Off;
m_bStaticBackground = false;
m_bRandomBGOnly = false;
m_bSaveScore = true;
@@ -61,18 +98,18 @@ void SongOptions::GetMods( vector<RString> &AddTo ) const
{
switch( m_LifeType )
{
case LIFE_BAR:
case LifeType_Bar:
switch( m_DrainType )
{
case DRAIN_NORMAL: break;
case DRAIN_NO_RECOVER: AddTo.push_back("NoRecover"); break;
case DRAIN_SUDDEN_DEATH: AddTo.push_back("SuddenDeath"); break;
case DrainType_Normal: break;
case DrainType_NoRecover: AddTo.push_back("NoRecover"); break;
case DrainType_SuddenDeath: AddTo.push_back("SuddenDeath"); break;
}
break;
case LIFE_BATTERY:
case LifeType_Battery:
AddTo.push_back( ssprintf( "%dLives", m_iBatteryLives ) );
break;
case LIFE_TIME:
case LifeType_Time:
AddTo.push_back( "LifeTime" );
break;
default:
@@ -92,19 +129,19 @@ void SongOptions::GetMods( vector<RString> &AddTo ) const
switch( m_AutosyncType )
{
case AUTOSYNC_OFF: break;
case AUTOSYNC_SONG: AddTo.push_back("AutosyncSong"); break;
case AUTOSYNC_MACHINE: AddTo.push_back("AutosyncMachine"); break;
case AUTOSYNC_TEMPO: AddTo.push_back("AutosyncTempo"); break;
case AutosyncType_Off: break;
case AutosyncType_Song: AddTo.push_back("AutosyncSong"); break;
case AutosyncType_Machine: AddTo.push_back("AutosyncMachine"); break;
case AutosyncType_Tempo: AddTo.push_back("AutosyncTempo"); break;
default:
FAIL_M(ssprintf("Invalid autosync type: %i", m_AutosyncType));
}
switch( m_SoundEffectType )
{
case SOUNDEFFECT_OFF: break;
case SOUNDEFFECT_SPEED: AddTo.push_back("EffectSpeed"); break;
case SOUNDEFFECT_PITCH: AddTo.push_back("EffectPitch"); break;
case SoundEffectType_Off: break;
case SoundEffectType_Speed: AddTo.push_back("EffectSpeed"); break;
case SoundEffectType_Pitch: AddTo.push_back("EffectPitch"); break;
default:
FAIL_M(ssprintf("Invalid sound effect type: %i", m_SoundEffectType));
}
@@ -190,26 +227,26 @@ bool SongOptions::FromOneModString( const RString &sOneMod, RString &sErrorOut )
on = false;
}
if( sBit == "norecover" ) m_DrainType = DRAIN_NO_RECOVER;
else if( sBit == "suddendeath" || sBit == "death" ) m_DrainType = DRAIN_SUDDEN_DEATH;
else if( sBit == "power-drop" ) m_DrainType = DRAIN_NO_RECOVER;
else if( sBit == "normal-drain" ) m_DrainType = DRAIN_NORMAL;
if( sBit == "norecover" ) m_DrainType = DrainType_NoRecover;
else if( sBit == "suddendeath" || sBit == "death" ) m_DrainType = DrainType_SuddenDeath;
else if( sBit == "power-drop" ) m_DrainType = DrainType_NoRecover;
else if( sBit == "normal-drain" ) m_DrainType = DrainType_Normal;
else if( sBit == "clap" ) m_bAssistClap = on;
else if( sBit == "metronome" ) m_bAssistMetronome = on;
else if( sBit == "autosync" || sBit == "autosyncsong" ) m_AutosyncType = on ? AUTOSYNC_SONG : AUTOSYNC_OFF;
else if( sBit == "autosyncmachine" ) m_AutosyncType = on ? AUTOSYNC_MACHINE : AUTOSYNC_OFF;
else if( sBit == "autosynctempo" ) m_AutosyncType = on ? AUTOSYNC_TEMPO : AUTOSYNC_OFF;
else if( sBit == "effect" && !on ) m_SoundEffectType = SOUNDEFFECT_OFF;
else if( sBit == "effectspeed" ) m_SoundEffectType = on ? SOUNDEFFECT_SPEED : SOUNDEFFECT_OFF;
else if( sBit == "effectpitch" ) m_SoundEffectType = on ? SOUNDEFFECT_PITCH : SOUNDEFFECT_OFF;
else if( sBit == "autosync" || sBit == "autosyncsong" ) m_AutosyncType = on ? AutosyncType_Song : AutosyncType_Off;
else if( sBit == "autosyncmachine" ) m_AutosyncType = on ? AutosyncType_Machine : AutosyncType_Off;
else if( sBit == "autosynctempo" ) m_AutosyncType = on ? AutosyncType_Tempo : AutosyncType_Off;
else if( sBit == "effect" && !on ) m_SoundEffectType = SoundEffectType_Off;
else if( sBit == "effectspeed" ) m_SoundEffectType = on ? SoundEffectType_Speed : SoundEffectType_Off;
else if( sBit == "effectpitch" ) m_SoundEffectType = on ? SoundEffectType_Pitch : SoundEffectType_Off;
else if( sBit == "staticbg" ) m_bStaticBackground = on;
else if( sBit == "randombg" ) m_bRandomBGOnly = on;
else if( sBit == "savescore" ) m_bSaveScore = on;
else if( sBit == "savereplay" ) m_bSaveReplay = on;
else if( sBit == "bar" ) m_LifeType = LIFE_BAR;
else if( sBit == "battery" ) m_LifeType = LIFE_BATTERY;
else if( sBit == "lifetime" ) m_LifeType = LIFE_TIME;
else if( sBit == "bar" ) m_LifeType = LifeType_Bar;
else if( sBit == "battery" ) m_LifeType = LifeType_Battery;
else if( sBit == "lifetime" ) m_LifeType = LifeType_Time;
else if( sBit == "haste" ) m_fHaste = on? 1.0f:0.0f;
else
return false;
@@ -237,6 +274,51 @@ bool SongOptions::operator==( const SongOptions &other ) const
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
* All rights reserved.
+57 -29
View File
@@ -3,43 +3,68 @@
#ifndef 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
{
public:
enum LifeType
{
LIFE_BAR=0,
LIFE_BATTERY,
LIFE_TIME,
NUM_LIFE_TYPES
};
LifeType m_LifeType;
enum DrainType
{
DRAIN_NORMAL,
DRAIN_NO_RECOVER,
DRAIN_SUDDEN_DEATH
};
DrainType m_DrainType; // only used with LifeBar
int m_iBatteryLives;
bool m_bAssistClap;
bool m_bAssistMetronome;
float m_fMusicRate, m_SpeedfMusicRate;
float m_fHaste, m_SpeedfHaste;
enum AutosyncType {
AUTOSYNC_OFF,
AUTOSYNC_SONG,
AUTOSYNC_MACHINE,
AUTOSYNC_TEMPO,
NUM_AUTOSYNC_TYPES
};
AutosyncType m_AutosyncType;
enum SoundEffectType {
SOUNDEFFECT_OFF,
SOUNDEFFECT_SPEED,
SOUNDEFFECT_PITCH,
NUM_SOUNDEFFECT
};
SoundEffectType m_SoundEffectType;
bool m_bStaticBackground;
bool m_bRandomBGOnly;
@@ -51,12 +76,12 @@ public:
*
* This is taken from Init(), but uses the intended
* 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_bAssistMetronome(false), m_fMusicRate(1.0f),
m_SpeedfMusicRate(1.0f), m_fHaste(0.0f),
m_SpeedfHaste(1.0f), m_AutosyncType(AUTOSYNC_OFF),
m_SoundEffectType(SOUNDEFFECT_OFF),
m_SpeedfHaste(1.0f), m_AutosyncType(AutosyncType_Off),
m_SoundEffectType(SoundEffectType_Off),
m_bStaticBackground(false), m_bRandomBGOnly(false),
m_bSaveScore(true), m_bSaveReplay(false) {};
void Init();
@@ -70,6 +95,9 @@ public:
bool operator==( const SongOptions &other ) const;
bool operator!=( const SongOptions &other ) const { return !operator==(other); }
// Lua
void PushSelf( lua_State *L );
};
#endif