From 0dfb13129109f738ca7765a7e036b822513fc31e Mon Sep 17 00:00:00 2001 From: Kyzentun Date: Sat, 3 May 2014 19:27:32 -0600 Subject: [PATCH 1/2] 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. --- Docs/Luadoc/Lua.xml | 31 ++++++ Docs/Luadoc/LuaDocumentation.xml | 37 ++++++- src/AdjustSync.cpp | 33 ++---- src/GameCommand.cpp | 4 +- src/GameState.cpp | 7 ++ src/LifeMeter.cpp | 8 +- src/LifeMeter.h | 2 +- src/LifeMeterBar.cpp | 28 ++--- src/LuaBinding.cpp | 19 ++++ src/LuaBinding.h | 5 + src/Player.cpp | 4 +- src/PlayerOptions.cpp | 176 ++++++++++-------------------- src/ScreenDebugOverlay.cpp | 20 ++-- src/ScreenGameplay.cpp | 20 ++-- src/ScreenGameplaySyncMachine.cpp | 2 +- src/ScreenJukebox.cpp | 2 +- src/ScreenSelectMusic.cpp | 4 +- src/ScreenSyncOverlay.cpp | 12 +- src/SongOptions.cpp | 142 +++++++++++++++++++----- src/SongOptions.h | 86 ++++++++++----- 20 files changed, 384 insertions(+), 258 deletions(-) diff --git a/Docs/Luadoc/Lua.xml b/Docs/Luadoc/Lua.xml index 964eb04199..b10019410c 100644 --- a/Docs/Luadoc/Lua.xml +++ b/Docs/Luadoc/Lua.xml @@ -780,6 +780,7 @@ + @@ -1453,6 +1454,20 @@ + + + + + + + + + + + + + + @@ -1777,6 +1792,12 @@ + + + + + + @@ -1832,6 +1853,11 @@ + + + + + @@ -1951,6 +1977,11 @@ + + + + + diff --git a/Docs/Luadoc/LuaDocumentation.xml b/Docs/Luadoc/LuaDocumentation.xml index 40d13157d9..63a3def1dd 100644 --- a/Docs/Luadoc/LuaDocumentation.xml +++ b/Docs/Luadoc/LuaDocumentation.xml @@ -2330,6 +2330,9 @@ save yourself some time, copy this for undocumented things: Returns the song options as a string. + + Returns the song options for the specified ModsLevel as an object. + Returns how much of the song is through at beat fBeat. @@ -2825,7 +2828,7 @@ save yourself some time, copy this for undocumented things: - Most options fall into one of two types: float or bool.
+ Most options fall into one of four types: float, int, bool, or enum.
Float type options have this interface:
Option(value, approach_speed)
If value is a float, sets the TimeSpacing modifier to value.
@@ -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.

Setting the approach speed only matters when modifying the PlayerOptions from ModsLevel_Song.
+ Int type options are similar to float in that they return and take a number, but they do not have an approach speed.
Bool type options have an almost identical interface, the difference is that they can not have an approach speed.
+ Enum type options are almost identical to bool type. They take and return an enum value.
For brevity, the functions are only given a description if the option requires careful handling or does not follow the float or bool interfaces.
@@ -4039,6 +4044,36 @@ save yourself some time, copy this for undocumented things: Returns true if the specified song was loaded from AdditionalSongs.
+ + + See the description for PlayerOptions. The functions follow the same design. + + + + + + + + + + + + + + + + + + + + + + + Limited to the range 0 < rate <= 3 because speeds greater than 3 are likely to crash. + + + + Returns the current beats per second. diff --git a/src/AdjustSync.cpp b/src/AdjustSync.cpp index fb88d39475..0234cffbf4 100644 --- a/src/AdjustSync.cpp +++ b/src/AdjustSync.cpp @@ -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& 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; diff --git a/src/GameCommand.cpp b/src/GameCommand.cpp index e3b60582d2..cf399ad2ef 100644 --- a/src/GameCommand.cpp +++ b/src/GameCommand.cpp @@ -805,9 +805,9 @@ void GameCommand::ApplySelf( const vector &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 ); } } diff --git a/src/GameState.cpp b/src/GameState.cpp index 12554cb666..fd135343d8 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -2366,6 +2366,12 @@ public: LuaHelpers::Push( L, s ); return 1; } + static int GetSongOptionsObject( T* p, lua_State *L ) + { + ModsLevel m = Enum::Check( 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 ); diff --git a/src/LifeMeter.cpp b/src/LifeMeter.cpp index 1d6fd285fb..2f72d0c953 100644 --- a/src/LifeMeter.cpp +++ b/src/LifeMeter.cpp @@ -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)); } diff --git a/src/LifeMeter.h b/src/LifeMeter.h index 33a74be67f..1f45c68bea 100644 --- a/src/LifeMeter.h +++ b/src/LifeMeter.h @@ -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 diff --git a/src/LifeMeterBar.cpp b/src/LifeMeterBar.cpp index 90a9106228..09f56eea70 100644 --- a/src/LifeMeterBar.cpp +++ b/src/LifeMeterBar.cpp @@ -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; diff --git a/src/LuaBinding.cpp b/src/LuaBinding.cpp index a264675164..0c7aa4dc21 100644 --- a/src/LuaBinding.cpp +++ b/src/LuaBinding.cpp @@ -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. diff --git a/src/LuaBinding.h b/src/LuaBinding.h index 91c0392646..91c27c6dec 100644 --- a/src/LuaBinding.h +++ b/src/LuaBinding.h @@ -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 /* diff --git a/src/Player.cpp b/src/Player.cpp index 8fcf4dbb59..133fbc1cbc 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -628,7 +628,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 @@ -1781,7 +1781,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 ) diff --git a/src/PlayerOptions.cpp b/src/PlayerOptions.cpp index b5eeadb339..cc354c3b95 100644 --- a/src/PlayerOptions.cpp +++ b/src/PlayerOptions.cpp @@ -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 @@ -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(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; } diff --git a/src/ScreenDebugOverlay.cpp b/src/ScreenDebugOverlay.cpp index 68204bd00c..3cdfe08a9f 100644 --- a/src/ScreenDebugOverlay.cpp +++ b/src/ScreenDebugOverlay.cpp @@ -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 ); } diff --git a/src/ScreenGameplay.cpp b/src/ScreenGameplay.cpp index efae737af1..ed67500d1b 100644 --- a/src/ScreenGameplay.cpp +++ b/src/ScreenGameplay.cpp @@ -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(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; diff --git a/src/ScreenGameplaySyncMachine.cpp b/src/ScreenGameplaySyncMachine.cpp index 037ced9f97..24456d85bf 100644 --- a/src/ScreenGameplaySyncMachine.cpp +++ b/src/ScreenGameplaySyncMachine.cpp @@ -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. diff --git a/src/ScreenJukebox.cpp b/src/ScreenJukebox.cpp index 6176a50ebe..925e9fb209 100644 --- a/src/ScreenJukebox.cpp +++ b/src/ScreenJukebox.cpp @@ -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 ) diff --git a/src/ScreenSelectMusic.cpp b/src/ScreenSelectMusic.cpp index 48e01e7a77..89045a53b2 100644 --- a/src/ScreenSelectMusic.cpp +++ b/src/ScreenSelectMusic.cpp @@ -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 { diff --git a/src/ScreenSyncOverlay.cpp b/src/ScreenSyncOverlay.cpp index b0ba604e4b..be23fc1c08 100644 --- a/src/ScreenSyncOverlay.cpp +++ b/src/ScreenSyncOverlay.cpp @@ -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 ) { diff --git a/src/SongOptions.cpp b/src/SongOptions.cpp index 6580f729a0..360b96505e 100644 --- a/src/SongOptions.cpp +++ b/src/SongOptions.cpp @@ -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 &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 &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 +{ +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. diff --git a/src/SongOptions.h b/src/SongOptions.h index 9bb88f4236..9d2c93d911 100644 --- a/src/SongOptions.h +++ b/src/SongOptions.h @@ -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 From 782a66502e9c2ef622d6e7c26bd17da18b1b8ad6 Mon Sep 17 00:00:00 2001 From: Kyzentun Date: Sat, 3 May 2014 19:36:59 -0600 Subject: [PATCH 2/2] Accidentally left OptionsBinding.h out of previous commit. --- src/OptionsBinding.h | 95 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 src/OptionsBinding.h diff --git a/src/OptionsBinding.h b/src/OptionsBinding.h new file mode 100644 index 0000000000..67628b541b --- /dev/null +++ b/src/OptionsBinding.h @@ -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(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. + */