2011-03-17 01:47:30 -04:00
#include "global.h"
#include "PlayerOptions.h"
#include "RageUtil.h"
#include "GameState.h"
#include "NoteSkinManager.h"
#include "Song.h"
#include "Course.h"
#include "Steps.h"
#include "ThemeManager.h"
#include "Foreach.h"
#include "Style.h"
#include "CommonMetrics.h"
#include <float.h>
2011-06-12 19:20:43 -04:00
void NextFloat ( float fValues [], int size );
void NextBool ( bool bValues [], int size );
2011-03-17 01:47:30 -04:00
ThemeMetric < float > RANDOM_SPEED_CHANCE ( "PlayerOptions" , "RandomSpeedChance" );
ThemeMetric < float > RANDOM_REVERSE_CHANCE ( "PlayerOptions" , "RandomReverseChance" );
ThemeMetric < float > RANDOM_DARK_CHANCE ( "PlayerOptions" , "RandomDarkChance" );
ThemeMetric < float > RANDOM_ACCEL_CHANCE ( "PlayerOptions" , "RandomAccelChance" );
ThemeMetric < float > RANDOM_EFFECT_CHANCE ( "PlayerOptions" , "RandomEffectChance" );
ThemeMetric < float > RANDOM_HIDDEN_CHANCE ( "PlayerOptions" , "RandomHiddenChance" );
ThemeMetric < float > RANDOM_SUDDEN_CHANCE ( "PlayerOptions" , "RandomSuddenChance" );
2014-05-01 23:23:20 -06:00
static const float CMOD_DEFAULT = 200.0f ;
// Is there a better place for this?
// It needs to be a named constant because it's used in several places in
// this file, but nothing else has a named constant for its default value.
// -Kyz
2011-03-17 01:47:30 -04:00
void PlayerOptions :: Init ()
{
m_bSetScrollSpeed = false ;
2011-07-03 00:08:56 -07:00
m_fMaxScrollBPM = 0 ; m_SpeedfMaxScrollBPM = 1.0f ;
2011-03-17 01:47:30 -04:00
m_fTimeSpacing = 0 ; m_SpeedfTimeSpacing = 1.0f ;
m_fScrollSpeed = 1.0f ; m_SpeedfScrollSpeed = 1.0f ;
2014-05-01 23:23:20 -06:00
m_fScrollBPM = CMOD_DEFAULT ; m_SpeedfScrollBPM = 1.0f ;
2011-03-17 01:47:30 -04:00
ZERO ( m_fAccels ); ONE ( m_SpeedfAccels );
ZERO ( m_fEffects ); ONE ( m_SpeedfEffects );
ZERO ( m_fAppearances ); ONE ( m_SpeedfAppearances );
ZERO ( m_fScrolls ); ONE ( m_SpeedfScrolls );
m_fDark = 0 ; m_SpeedfDark = 1.0f ;
m_fBlind = 0 ; m_SpeedfBlind = 1.0f ;
m_fCover = 0 ; m_SpeedfCover = 1.0f ;
m_fRandAttack = 0 ; m_SpeedfRandAttack = 1.0f ;
2011-06-26 23:58:24 -04:00
m_fNoAttack = 0 ; m_SpeedfNoAttack = 1.0f ;
2011-03-17 01:47:30 -04:00
m_fPlayerAutoPlay = 0 ; m_SpeedfPlayerAutoPlay = 1.0f ;
m_fPerspectiveTilt = 0 ; m_SpeedfPerspectiveTilt = 1.0f ;
m_fSkew = 0 ; m_SpeedfSkew = 1.0f ;
m_fPassmark = 0 ; m_SpeedfPassmark = 1.0f ;
m_fRandomSpeed = 0 ; m_SpeedfRandomSpeed = 1.0f ;
ZERO ( m_bTurns );
ZERO ( m_bTransforms );
m_bMuteOnError = false ;
2014-05-01 23:23:20 -06:00
m_FailType = FailType_Immediate ;
2011-03-17 01:47:30 -04:00
m_sNoteSkin = "" ;
}
void PlayerOptions :: Approach ( const PlayerOptions & other , float fDeltaSeconds )
{
#define APPROACH( opt ) \
fapproach( m_ ## opt, other.m_ ## opt, fDeltaSeconds * other.m_Speed ## opt );
#define DO_COPY( x ) \
x = other.x;
APPROACH ( fTimeSpacing );
APPROACH ( fScrollSpeed );
2014-05-08 03:07:02 -06:00
APPROACH ( fMaxScrollBPM );
2011-03-17 01:47:30 -04:00
fapproach ( m_fScrollBPM , other . m_fScrollBPM , fDeltaSeconds * other . m_SpeedfScrollBPM * 150 );
for ( int i = 0 ; i < NUM_ACCELS ; i ++ )
APPROACH ( fAccels [ i ] );
for ( int i = 0 ; i < NUM_EFFECTS ; i ++ )
APPROACH ( fEffects [ i ] );
for ( int i = 0 ; i < NUM_APPEARANCES ; i ++ )
APPROACH ( fAppearances [ i ] );
for ( int i = 0 ; i < NUM_SCROLLS ; i ++ )
APPROACH ( fScrolls [ i ] );
APPROACH ( fDark );
APPROACH ( fBlind );
APPROACH ( fCover );
APPROACH ( fRandAttack );
2011-06-26 23:58:24 -04:00
APPROACH ( fNoAttack );
2011-03-17 01:47:30 -04:00
APPROACH ( fPlayerAutoPlay );
APPROACH ( fPerspectiveTilt );
APPROACH ( fSkew );
APPROACH ( fPassmark );
APPROACH ( fRandomSpeed );
DO_COPY ( m_bSetScrollSpeed );
for ( int i = 0 ; i < NUM_TURNS ; i ++ )
DO_COPY ( m_bTurns [ i ] );
for ( int i = 0 ; i < NUM_TRANSFORMS ; i ++ )
DO_COPY ( m_bTransforms [ i ] );
DO_COPY ( m_bMuteOnError );
DO_COPY ( m_FailType );
DO_COPY ( m_sNoteSkin );
#undef APPROACH
#undef DO_COPY
}
static void AddPart ( vector < RString > & AddTo , float level , RString name )
{
if ( level == 0 )
return ;
const RString LevelStr = ( level == 1 ) ? RString ( "" ) : ssprintf ( "%ld%% " , lrintf ( level * 100 ) );
AddTo . push_back ( LevelStr + name );
}
RString PlayerOptions :: GetString ( bool bForceNoteSkin ) const
{
vector < RString > v ;
GetMods ( v , bForceNoteSkin );
return join ( ", " , v );
}
void PlayerOptions :: GetMods ( vector < RString > & AddTo , bool bForceNoteSkin ) const
{
//RString sReturn;
if ( ! m_fTimeSpacing )
{
2013-04-19 21:49:55 -04:00
if ( m_fMaxScrollBPM )
2011-07-03 00:08:56 -07:00
{
RString s = ssprintf ( "m%.0f" , m_fMaxScrollBPM );
AddTo . push_back ( s );
}
2012-03-09 14:25:39 -06:00
else if ( m_bSetScrollSpeed || m_fScrollSpeed != 1 )
2011-03-17 01:47:30 -04:00
{
/* -> 1.00 */
RString s = ssprintf ( "%2.2f" , m_fScrollSpeed );
if ( s [ s . size () - 1 ] == '0' )
{
/* -> 1.0 */
s . erase ( s . size () - 1 ); // delete last char
if ( s [ s . size () - 1 ] == '0' )
{
/* -> 1 */
s . erase ( s . size () - 2 ); // delete last 2 chars
}
}
AddTo . push_back ( s + "x" );
}
}
else
{
RString s = ssprintf ( "C%.0f" , m_fScrollBPM );
AddTo . push_back ( s );
}
AddPart ( AddTo , m_fAccels [ ACCEL_BOOST ], "Boost" );
AddPart ( AddTo , m_fAccels [ ACCEL_BRAKE ], "Brake" );
AddPart ( AddTo , m_fAccels [ ACCEL_WAVE ], "Wave" );
AddPart ( AddTo , m_fAccels [ ACCEL_EXPAND ], "Expand" );
AddPart ( AddTo , m_fAccels [ ACCEL_BOOMERANG ], "Boomerang" );
AddPart ( AddTo , m_fEffects [ EFFECT_DRUNK ], "Drunk" );
AddPart ( AddTo , m_fEffects [ EFFECT_DIZZY ], "Dizzy" );
AddPart ( AddTo , m_fEffects [ EFFECT_CONFUSION ], "Confusion" );
AddPart ( AddTo , m_fEffects [ EFFECT_MINI ], "Mini" );
AddPart ( AddTo , m_fEffects [ EFFECT_TINY ], "Tiny" );
AddPart ( AddTo , m_fEffects [ EFFECT_FLIP ], "Flip" );
AddPart ( AddTo , m_fEffects [ EFFECT_INVERT ], "Invert" );
AddPart ( AddTo , m_fEffects [ EFFECT_TORNADO ], "Tornado" );
AddPart ( AddTo , m_fEffects [ EFFECT_TIPSY ], "Tipsy" );
AddPart ( AddTo , m_fEffects [ EFFECT_BUMPY ], "Bumpy" );
AddPart ( AddTo , m_fEffects [ EFFECT_BEAT ], "Beat" );
AddPart ( AddTo , m_fEffects [ EFFECT_XMODE ], "XMode" );
AddPart ( AddTo , m_fEffects [ EFFECT_TWIRL ], "Twirl" );
AddPart ( AddTo , m_fEffects [ EFFECT_ROLL ], "Roll" );
AddPart ( AddTo , m_fAppearances [ APPEARANCE_HIDDEN ], "Hidden" );
AddPart ( AddTo , m_fAppearances [ APPEARANCE_HIDDEN_OFFSET ], "HiddenOffset" );
AddPart ( AddTo , m_fAppearances [ APPEARANCE_SUDDEN ], "Sudden" );
AddPart ( AddTo , m_fAppearances [ APPEARANCE_SUDDEN_OFFSET ], "SuddenOffset" );
AddPart ( AddTo , m_fAppearances [ APPEARANCE_STEALTH ], "Stealth" );
AddPart ( AddTo , m_fAppearances [ APPEARANCE_BLINK ], "Blink" );
AddPart ( AddTo , m_fAppearances [ APPEARANCE_RANDOMVANISH ], "RandomVanish" );
AddPart ( AddTo , m_fScrolls [ SCROLL_REVERSE ], "Reverse" );
AddPart ( AddTo , m_fScrolls [ SCROLL_SPLIT ], "Split" );
AddPart ( AddTo , m_fScrolls [ SCROLL_ALTERNATE ], "Alternate" );
AddPart ( AddTo , m_fScrolls [ SCROLL_CROSS ], "Cross" );
AddPart ( AddTo , m_fScrolls [ SCROLL_CENTERED ], "Centered" );
AddPart ( AddTo , m_fDark , "Dark" );
AddPart ( AddTo , m_fBlind , "Blind" );
AddPart ( AddTo , m_fCover , "Cover" );
AddPart ( AddTo , m_fRandAttack , "RandomAttacks" );
2011-06-26 23:58:24 -04:00
AddPart ( AddTo , m_fNoAttack , "NoAttacks" );
2011-03-17 01:47:30 -04:00
AddPart ( AddTo , m_fPlayerAutoPlay , "PlayerAutoPlay" );
AddPart ( AddTo , m_fPassmark , "Passmark" );
AddPart ( AddTo , m_fRandomSpeed , "RandomSpeed" );
if ( m_bTurns [ TURN_MIRROR ] ) AddTo . push_back ( "Mirror" );
2011-10-16 15:41:26 -04:00
if ( m_bTurns [ TURN_BACKWARDS ] ) AddTo . push_back ( "Backwards" );
2011-03-17 01:47:30 -04:00
if ( m_bTurns [ TURN_LEFT ] ) AddTo . push_back ( "Left" );
if ( m_bTurns [ TURN_RIGHT ] ) AddTo . push_back ( "Right" );
if ( m_bTurns [ TURN_SHUFFLE ] ) AddTo . push_back ( "Shuffle" );
if ( m_bTurns [ TURN_SOFT_SHUFFLE ] ) AddTo . push_back ( "SoftShuffle" );
if ( m_bTurns [ TURN_SUPER_SHUFFLE ] ) AddTo . push_back ( "SuperShuffle" );
if ( m_bTransforms [ TRANSFORM_NOHOLDS ] ) AddTo . push_back ( "NoHolds" );
if ( m_bTransforms [ TRANSFORM_NOROLLS ] ) AddTo . push_back ( "NoRolls" );
if ( m_bTransforms [ TRANSFORM_NOMINES ] ) AddTo . push_back ( "NoMines" );
if ( m_bTransforms [ TRANSFORM_LITTLE ] ) AddTo . push_back ( "Little" );
if ( m_bTransforms [ TRANSFORM_WIDE ] ) AddTo . push_back ( "Wide" );
if ( m_bTransforms [ TRANSFORM_BIG ] ) AddTo . push_back ( "Big" );
if ( m_bTransforms [ TRANSFORM_QUICK ] ) AddTo . push_back ( "Quick" );
if ( m_bTransforms [ TRANSFORM_BMRIZE ] ) AddTo . push_back ( "BMRize" );
if ( m_bTransforms [ TRANSFORM_SKIPPY ] ) AddTo . push_back ( "Skippy" );
if ( m_bTransforms [ TRANSFORM_MINES ] ) AddTo . push_back ( "Mines" );
if ( m_bTransforms [ TRANSFORM_ATTACKMINES ] ) AddTo . push_back ( "AttackMines" );
if ( m_bTransforms [ TRANSFORM_ECHO ] ) AddTo . push_back ( "Echo" );
if ( m_bTransforms [ TRANSFORM_STOMP ] ) AddTo . push_back ( "Stomp" );
if ( m_bTransforms [ TRANSFORM_PLANTED ] ) AddTo . push_back ( "Planted" );
if ( m_bTransforms [ TRANSFORM_FLOORED ] ) AddTo . push_back ( "Floored" );
if ( m_bTransforms [ TRANSFORM_TWISTER ] ) AddTo . push_back ( "Twister" );
if ( m_bTransforms [ TRANSFORM_HOLDROLLS ] ) AddTo . push_back ( "HoldsToRolls" );
if ( m_bTransforms [ TRANSFORM_NOJUMPS ] ) AddTo . push_back ( "NoJumps" );
if ( m_bTransforms [ TRANSFORM_NOHANDS ] ) AddTo . push_back ( "NoHands" );
if ( m_bTransforms [ TRANSFORM_NOLIFTS ] ) AddTo . push_back ( "NoLifts" );
if ( m_bTransforms [ TRANSFORM_NOFAKES ] ) AddTo . push_back ( "NoFakes" );
if ( m_bTransforms [ TRANSFORM_NOQUADS ] ) AddTo . push_back ( "NoQuads" );
if ( m_bTransforms [ TRANSFORM_NOSTRETCH ] ) AddTo . push_back ( "NoStretch" );
if ( m_bMuteOnError ) AddTo . push_back ( "MuteOnError" );
switch ( m_FailType )
{
2014-05-01 23:23:20 -06:00
case FailType_Immediate : break ;
case FailType_ImmediateContinue : AddTo . push_back ( "FailImmediateContinue" ); break ;
case FailType_EndOfSong : AddTo . push_back ( "FailAtEnd" ); break ;
case FailType_Off : AddTo . push_back ( "FailOff" ); break ;
2012-12-27 16:59:35 -05:00
default :
FAIL_M ( ssprintf ( "Invalid FailType: %i" , m_FailType ));
2011-03-17 01:47:30 -04:00
}
2014-05-01 23:23:20 -06:00
if ( m_fSkew == 0 && m_fPerspectiveTilt == 0 )
{
AddTo . push_back ( "Overhead" );
}
2011-03-17 01:47:30 -04:00
else if ( m_fSkew == 0 )
{
if ( m_fPerspectiveTilt > 0 )
AddPart ( AddTo , m_fPerspectiveTilt , "Distant" );
else
AddPart ( AddTo , - m_fPerspectiveTilt , "Hallway" );
}
else if ( fabsf ( m_fSkew - m_fPerspectiveTilt ) < 0.0001f )
{
AddPart ( AddTo , m_fSkew , "Space" );
}
else if ( fabsf ( m_fSkew + m_fPerspectiveTilt ) < 0.0001f )
{
AddPart ( AddTo , m_fSkew , "Incoming" );
}
2014-05-02 16:45:49 -06:00
else
{
AddPart ( AddTo , m_fSkew , "Skew" );
AddPart ( AddTo , m_fPerspectiveTilt , "Tilt" );
}
2011-03-17 01:47:30 -04:00
// Don't display a string if using the default NoteSkin unless we force it.
if ( bForceNoteSkin || ( ! m_sNoteSkin . empty () && m_sNoteSkin != CommonMetrics :: DEFAULT_NOTESKIN_NAME . GetValue ()) )
{
RString s = m_sNoteSkin ;
Capitalize ( s );
AddTo . push_back ( s );
}
}
/* Options are added to the current settings; call Init() beforehand if
* you don't want this. */
void PlayerOptions :: FromString ( const RString & sMultipleMods )
{
RString sTemp = sMultipleMods ;
vector < RString > vs ;
split ( sTemp , "," , vs , true );
RString sThrowAway ;
FOREACH ( RString , vs , s )
{
2011-05-27 10:42:47 -04:00
if ( ! FromOneModString ( * s , sThrowAway ))
{
2011-06-03 19:52:20 -05:00
LOG -> Trace ( "Attempted to load a non-existing mod \' %s \' for the Player. Ignoring." , ( * s ). c_str () );
2011-05-27 10:42:47 -04:00
}
2011-03-17 01:47:30 -04:00
}
}
bool PlayerOptions :: FromOneModString ( const RString & sOneMod , RString & sErrorOut )
{
2012-12-27 11:38:53 -05:00
ASSERT_M ( NOTESKIN != NULL , "The Noteskin Manager must be loaded in order to process mods." );
2011-03-17 01:47:30 -04:00
RString sBit = sOneMod ;
sBit . MakeLower ();
Trim ( sBit );
/* "drunk"
* "no drunk"
* "150% drunk"
* "*2 100% drunk": approach at 2x normal speed */
float level = 1 ;
float speed = 1 ;
vector < RString > asParts ;
split ( sBit , " " , asParts , true );
FOREACH_CONST ( RString , asParts , s )
{
if ( * s == "no" )
{
level = 0 ;
}
else if ( isdigit (( * s )[ 0 ]) || ( * s )[ 0 ] == '-' )
{
/* If the last character is a *, they probably said "123*" when
* they meant "*123". */
if ( s -> Right ( 1 ) == "*" )
{
2011-06-03 19:52:20 -05:00
// XXX: We know what they want, is there any reason not to handle it?
// Yes. We should be strict in handling the format. -Chris
2011-05-11 15:58:31 -04:00
sErrorOut = ssprintf ( "Invalid player options \" %s \" ; did you mean '*%d'?" , s -> c_str (), StringToInt ( * s ) );
2011-03-17 01:47:30 -04:00
return false ;
}
else
{
level = StringToFloat ( * s ) / 100.0f ;
}
}
else if ( * s [ 0 ] == '*' )
{
sscanf ( * s , "*%f" , & speed );
if ( ! isfinite ( speed ) )
speed = 1.0f ;
}
}
sBit = asParts . back ();
#define SET_FLOAT( opt ) { m_ ## opt = level; m_Speed ## opt = speed; }
const bool on = ( level > 0.5f );
static Regex mult ( "^([0-9]+( \\ .[0-9]+) ? ) x $ ") ;
vector < RString > matches ;
if ( mult . Compare ( sBit , matches ) )
{
StringConversion :: FromString ( matches [ 0 ], level );
SET_FLOAT ( fScrollSpeed )
SET_FLOAT ( fTimeSpacing )
m_fTimeSpacing = 0 ;
2011-07-03 00:08:56 -07:00
m_fMaxScrollBPM = 0 ;
2011-03-17 01:47:30 -04:00
}
else if ( sscanf ( sBit , "c%f" , & level ) == 1 )
{
if ( ! isfinite ( level ) || level <= 0.0f )
2014-05-01 23:23:20 -06:00
level = CMOD_DEFAULT ;
2011-03-17 01:47:30 -04:00
SET_FLOAT ( fScrollBPM )
SET_FLOAT ( fTimeSpacing )
m_fTimeSpacing = 1 ;
2011-07-03 00:08:56 -07:00
m_fMaxScrollBPM = 0 ;
2011-03-17 01:47:30 -04:00
}
2011-07-03 00:08:56 -07:00
// oITG's m-mods
2011-03-17 01:47:30 -04:00
else if ( sscanf ( sBit , "m%f" , & level ) == 1 )
{
2012-01-15 23:39:53 -06:00
// OpenITG doesn't have this block:
/*
2011-03-17 01:47:30 -04:00
if( !isfinite(level) || level <= 0.0f )
2014-05-01 23:23:20 -06:00
level = CMOD_DEFAULT;
2012-01-15 23:39:53 -06:00
*/
2011-07-03 00:08:56 -07:00
SET_FLOAT ( fMaxScrollBPM )
m_fTimeSpacing = 0 ;
2011-03-17 01:47:30 -04:00
}
2011-07-03 00:08:56 -07:00
2011-03-17 01:47:30 -04:00
else if ( sBit == "clearall" ) Init ();
2014-02-12 15:49:51 -07:00
else if ( sBit == "resetspeed" )
{
2014-02-14 22:26:03 -07:00
/* level is set to the values from Init() because all speed related
fields are being reset to initial values, and they each have different
initial values. -kyz */
level = 0 ;
SET_FLOAT ( fMaxScrollBPM );
SET_FLOAT ( fTimeSpacing );
level = 1.0f ;
SET_FLOAT ( fScrollSpeed );
2014-05-01 23:23:20 -06:00
level = CMOD_DEFAULT ;
2014-02-14 22:26:03 -07:00
SET_FLOAT ( fScrollBPM )
2014-02-12 15:49:51 -07:00
}
2011-03-17 01:47:30 -04:00
else if ( sBit == "boost" ) SET_FLOAT ( fAccels [ ACCEL_BOOST ] )
else if ( sBit == "brake" || sBit == "land" ) SET_FLOAT ( fAccels [ ACCEL_BRAKE ] )
else if ( sBit == "wave" ) SET_FLOAT ( fAccels [ ACCEL_WAVE ] )
else if ( sBit == "expand" || sBit == "dwiwave" ) SET_FLOAT ( fAccels [ ACCEL_EXPAND ] )
else if ( sBit == "boomerang" ) SET_FLOAT ( fAccels [ ACCEL_BOOMERANG ] )
else if ( sBit == "drunk" ) SET_FLOAT ( fEffects [ EFFECT_DRUNK ] )
else if ( sBit == "dizzy" ) SET_FLOAT ( fEffects [ EFFECT_DIZZY ] )
else if ( sBit == "confusion" ) SET_FLOAT ( fEffects [ EFFECT_CONFUSION ] )
else if ( sBit == "mini" ) SET_FLOAT ( fEffects [ EFFECT_MINI ] )
else if ( sBit == "tiny" ) SET_FLOAT ( fEffects [ EFFECT_TINY ] )
else if ( sBit == "flip" ) SET_FLOAT ( fEffects [ EFFECT_FLIP ] )
else if ( sBit == "invert" ) SET_FLOAT ( fEffects [ EFFECT_INVERT ] )
else if ( sBit == "tornado" ) SET_FLOAT ( fEffects [ EFFECT_TORNADO ] )
else if ( sBit == "tipsy" ) SET_FLOAT ( fEffects [ EFFECT_TIPSY ] )
else if ( sBit == "bumpy" ) SET_FLOAT ( fEffects [ EFFECT_BUMPY ] )
else if ( sBit == "beat" ) SET_FLOAT ( fEffects [ EFFECT_BEAT ] )
else if ( sBit == "xmode" ) SET_FLOAT ( fEffects [ EFFECT_XMODE ] )
else if ( sBit == "twirl" ) SET_FLOAT ( fEffects [ EFFECT_TWIRL ] )
else if ( sBit == "roll" ) SET_FLOAT ( fEffects [ EFFECT_ROLL ] )
else if ( sBit == "hidden" ) SET_FLOAT ( fAppearances [ APPEARANCE_HIDDEN ] )
else if ( sBit == "hiddenoffset" ) SET_FLOAT ( fAppearances [ APPEARANCE_HIDDEN_OFFSET ] )
else if ( sBit == "sudden" ) SET_FLOAT ( fAppearances [ APPEARANCE_SUDDEN ] )
else if ( sBit == "suddenoffset" ) SET_FLOAT ( fAppearances [ APPEARANCE_SUDDEN_OFFSET ] )
else if ( sBit == "stealth" ) SET_FLOAT ( fAppearances [ APPEARANCE_STEALTH ] )
else if ( sBit == "blink" ) SET_FLOAT ( fAppearances [ APPEARANCE_BLINK ] )
else if ( sBit == "randomvanish" ) SET_FLOAT ( fAppearances [ APPEARANCE_RANDOMVANISH ] )
else if ( sBit == "turn" && ! on ) ZERO ( m_bTurns ); /* "no turn" */
else if ( sBit == "mirror" ) m_bTurns [ TURN_MIRROR ] = on ;
2011-10-16 15:41:26 -04:00
else if ( sBit == "backwards" ) m_bTurns [ TURN_BACKWARDS ] = on ;
2011-03-17 01:47:30 -04:00
else if ( sBit == "left" ) m_bTurns [ TURN_LEFT ] = on ;
else if ( sBit == "right" ) m_bTurns [ TURN_RIGHT ] = on ;
else if ( sBit == "shuffle" ) m_bTurns [ TURN_SHUFFLE ] = on ;
else if ( sBit == "softshuffle" ) m_bTurns [ TURN_SOFT_SHUFFLE ] = on ;
else if ( sBit == "supershuffle" ) m_bTurns [ TURN_SUPER_SHUFFLE ] = on ;
else if ( sBit == "little" ) m_bTransforms [ TRANSFORM_LITTLE ] = on ;
else if ( sBit == "wide" ) m_bTransforms [ TRANSFORM_WIDE ] = on ;
else if ( sBit == "big" ) m_bTransforms [ TRANSFORM_BIG ] = on ;
else if ( sBit == "quick" ) m_bTransforms [ TRANSFORM_QUICK ] = on ;
else if ( sBit == "bmrize" ) m_bTransforms [ TRANSFORM_BMRIZE ] = on ;
else if ( sBit == "skippy" ) m_bTransforms [ TRANSFORM_SKIPPY ] = on ;
else if ( sBit == "mines" ) m_bTransforms [ TRANSFORM_MINES ] = on ;
else if ( sBit == "attackmines" ) m_bTransforms [ TRANSFORM_ATTACKMINES ] = on ;
else if ( sBit == "echo" ) m_bTransforms [ TRANSFORM_ECHO ] = on ;
else if ( sBit == "stomp" ) m_bTransforms [ TRANSFORM_STOMP ] = on ;
else if ( sBit == "planted" ) m_bTransforms [ TRANSFORM_PLANTED ] = on ;
else if ( sBit == "floored" ) m_bTransforms [ TRANSFORM_FLOORED ] = on ;
else if ( sBit == "twister" ) m_bTransforms [ TRANSFORM_TWISTER ] = on ;
else if ( sBit == "holdrolls" ) m_bTransforms [ TRANSFORM_HOLDROLLS ] = on ;
else if ( sBit == "nojumps" ) m_bTransforms [ TRANSFORM_NOJUMPS ] = on ;
else if ( sBit == "nohands" ) m_bTransforms [ TRANSFORM_NOHANDS ] = on ;
else if ( sBit == "noquads" ) m_bTransforms [ TRANSFORM_NOQUADS ] = on ;
else if ( sBit == "reverse" ) SET_FLOAT ( fScrolls [ SCROLL_REVERSE ] )
else if ( sBit == "split" ) SET_FLOAT ( fScrolls [ SCROLL_SPLIT ] )
else if ( sBit == "alternate" ) SET_FLOAT ( fScrolls [ SCROLL_ALTERNATE ] )
else if ( sBit == "cross" ) SET_FLOAT ( fScrolls [ SCROLL_CROSS ] )
else if ( sBit == "centered" ) SET_FLOAT ( fScrolls [ SCROLL_CENTERED ] )
else if ( sBit == "noholds" ) m_bTransforms [ TRANSFORM_NOHOLDS ] = on ;
else if ( sBit == "norolls" ) m_bTransforms [ TRANSFORM_NOROLLS ] = on ;
else if ( sBit == "nomines" ) m_bTransforms [ TRANSFORM_NOMINES ] = on ;
else if ( sBit == "nostretch" ) m_bTransforms [ TRANSFORM_NOSTRETCH ] = on ;
else if ( sBit == "nolifts" ) m_bTransforms [ TRANSFORM_NOLIFTS ] = on ;
else if ( sBit == "nofakes" ) m_bTransforms [ TRANSFORM_NOFAKES ] = on ;
else if ( sBit == "dark" ) SET_FLOAT ( fDark )
else if ( sBit == "blind" ) SET_FLOAT ( fBlind )
else if ( sBit == "cover" ) SET_FLOAT ( fCover )
else if ( sBit == "randomattacks" ) SET_FLOAT ( fRandAttack )
2011-06-26 23:58:24 -04:00
else if ( sBit == "noattacks" ) SET_FLOAT ( fNoAttack )
2011-03-17 01:47:30 -04:00
else if ( sBit == "playerautoplay" ) SET_FLOAT ( fPlayerAutoPlay )
else if ( sBit == "passmark" ) SET_FLOAT ( fPassmark )
2014-05-01 23:23:20 -06:00
else if ( sBit == "overhead" ) { m_fSkew = 0 ; m_fPerspectiveTilt = 0 ; m_SpeedfSkew = m_SpeedfPerspectiveTilt = speed ; }
else if ( sBit == "incoming" ) { m_fSkew = level ; m_fPerspectiveTilt = - level ; m_SpeedfSkew = m_SpeedfPerspectiveTilt = speed ; }
else if ( sBit == "space" ) { m_fSkew = level ; m_fPerspectiveTilt = + level ; m_SpeedfSkew = m_SpeedfPerspectiveTilt = speed ; }
else if ( sBit == "hallway" ) { m_fSkew = 0 ; m_fPerspectiveTilt = - level ; m_SpeedfSkew = m_SpeedfPerspectiveTilt = speed ; }
else if ( sBit == "distant" ) { m_fSkew = 0 ; m_fPerspectiveTilt = + level ; m_SpeedfSkew = m_SpeedfPerspectiveTilt = speed ; }
2011-03-17 01:47:30 -04:00
else if ( NOTESKIN && NOTESKIN -> DoesNoteSkinExist ( sBit ) ) m_sNoteSkin = sBit ;
2014-05-02 16:45:49 -06:00
else if ( sBit == "skew" ) SET_FLOAT ( fSkew )
else if ( sBit == "tilt" ) SET_FLOAT ( fPerspectiveTilt )
2011-03-17 01:47:30 -04:00
else if ( sBit == "noteskin" && ! on ) /* "no noteskin" */ m_sNoteSkin = CommonMetrics :: DEFAULT_NOTESKIN_NAME ;
else if ( sBit == "randomspeed" ) SET_FLOAT ( fRandomSpeed )
else if ( sBit == "failarcade" ||
2014-05-01 23:23:20 -06:00
sBit == "failimmediate" ) m_FailType = FailType_Immediate ;
2011-03-17 01:47:30 -04:00
else if ( sBit == "failendofsong" ||
2014-05-01 23:23:20 -06:00
sBit == "failimmediatecontinue" ) m_FailType = FailType_ImmediateContinue ;
else if ( sBit == "failatend" ) m_FailType = FailType_EndOfSong ;
else if ( sBit == "failoff" ) m_FailType = FailType_Off ;
2011-03-17 01:47:30 -04:00
else if ( sBit == "faildefault" )
{
PlayerOptions po ;
GAMESTATE -> GetDefaultPlayerOptions ( po );
m_FailType = po . m_FailType ;
}
else if ( sBit == "muteonerror" ) m_bMuteOnError = on ;
else if ( sBit == "random" ) ChooseRandomModifiers ();
// deprecated mods/left in for compatibility
else if ( sBit == "converge" ) SET_FLOAT ( fScrolls [ SCROLL_CENTERED ] )
// end of the list
else
{
return false ;
}
return true ;
}
void NextFloat ( float fValues [], int size )
{
int index = - 1 ;
for ( int i = 0 ; i < size ; i ++ )
{
if ( fValues [ i ] == 1 )
{
index = i ;
break ;
}
}
for ( int i = 0 ; i < size ; i ++ )
fValues [ i ] = 0 ;
if ( index == size - 1 ) // if true, then the last float in the list was selected
; // leave all off
else
fValues [ index + 1 ] = 1 ;
}
void NextBool ( bool bValues [], int size )
{
int index = - 1 ;
for ( int i = 0 ; i < size ; i ++ )
{
if ( bValues [ i ] )
{
index = i ;
break ;
}
}
for ( int i = 0 ; i < size ; i ++ )
bValues [ i ] = false ;
if ( index == size - 1 ) // if true, then the last float in the list was selected
; // leave all off
else
bValues [ index + 1 ] = 1 ;
}
void PlayerOptions :: NextAccel ()
{
NextFloat ( m_fAccels , NUM_ACCELS );
}
void PlayerOptions :: NextEffect ()
{
NextFloat ( m_fEffects , NUM_EFFECTS );
}
void PlayerOptions :: NextAppearance ()
{
NextFloat ( m_fAppearances , NUM_APPEARANCES );
}
void PlayerOptions :: NextTurn ()
{
NextBool ( m_bTurns , NUM_TURNS );
}
void PlayerOptions :: NextTransform ()
{
NextBool ( m_bTransforms , NUM_TRANSFORMS );
}
void PlayerOptions :: NextScroll ()
{
NextFloat ( m_fScrolls , NUM_SCROLLS );
}
void PlayerOptions :: NextPerspective ()
{
switch ( ( int ) m_fPerspectiveTilt )
{
case - 1 : m_fPerspectiveTilt = 0 ; break ;
case 0 : m_fPerspectiveTilt = + 1 ; break ;
case + 1 : default : m_fPerspectiveTilt = - 1 ; break ;
}
}
void PlayerOptions :: ChooseRandomModifiers ()
{
if ( RandomFloat ( 0 , 1 ) < RANDOM_SPEED_CHANCE )
m_fScrollSpeed = 1.5f ;
if ( RandomFloat ( 0 , 1 ) < RANDOM_REVERSE_CHANCE )
m_fScrolls [ SCROLL_REVERSE ] = 1 ;
if ( RandomFloat ( 0 , 1 ) < RANDOM_DARK_CHANCE )
m_fDark = 1 ;
float f ;
f = RandomFloat ( 0 , 1 );
if ( f < RANDOM_ACCEL_CHANCE )
m_fAccels [ RandomInt ( NUM_ACCELS )] = 1 ;
else if ( f < RANDOM_EFFECT_CHANCE )
m_fEffects [ RandomInt ( NUM_EFFECTS )] = 1 ;
f = RandomFloat ( 0 , 1 );
if ( f < RANDOM_HIDDEN_CHANCE )
m_fAppearances [ APPEARANCE_HIDDEN ] = 1 ;
else if ( f < RANDOM_SUDDEN_CHANCE )
m_fAppearances [ APPEARANCE_SUDDEN ] = 1 ;
}
PlayerOptions :: Accel PlayerOptions :: GetFirstAccel ()
{
for ( int i = 0 ; i < NUM_ACCELS ; i ++ )
if ( m_fAccels [ i ] == 1.f )
return ( Accel ) i ;
return ( Accel ) - 1 ;
}
PlayerOptions :: Effect PlayerOptions :: GetFirstEffect ()
{
for ( int i = 0 ; i < NUM_EFFECTS ; i ++ )
if ( m_fEffects [ i ] == 1.f )
return ( Effect ) i ;
return ( Effect ) - 1 ;
}
PlayerOptions :: Appearance PlayerOptions :: GetFirstAppearance ()
{
for ( int i = 0 ; i < NUM_APPEARANCES ; i ++ )
if ( m_fAppearances [ i ] == 1.f )
return ( Appearance ) i ;
return ( Appearance ) - 1 ;
}
PlayerOptions :: Scroll PlayerOptions :: GetFirstScroll ()
{
for ( int i = 0 ; i < NUM_SCROLLS ; i ++ )
if ( m_fScrolls [ i ] == 1.f )
return ( Scroll ) i ;
return ( Scroll ) - 1 ;
}
void PlayerOptions :: SetOneAccel ( Accel a )
{
ZERO ( m_fAccels );
m_fAccels [ a ] = 1 ;
}
void PlayerOptions :: SetOneEffect ( Effect e )
{
ZERO ( m_fEffects );
m_fEffects [ e ] = 1 ;
}
void PlayerOptions :: SetOneAppearance ( Appearance a )
{
ZERO ( m_fAppearances );
m_fAppearances [ a ] = 1 ;
}
void PlayerOptions :: SetOneScroll ( Scroll s )
{
ZERO ( m_fScrolls );
m_fScrolls [ s ] = 1 ;
}
void PlayerOptions :: ToggleOneTurn ( Turn t )
{
bool bWasOn = m_bTurns [ t ];
ZERO ( m_bTurns );
m_bTurns [ t ] = ! bWasOn ;
}
float PlayerOptions :: GetReversePercentForColumn ( int iCol ) const
{
float f = 0 ;
int iNumCols = GAMESTATE -> GetCurrentStyle () -> m_iColsPerPlayer ;
f += m_fScrolls [ SCROLL_REVERSE ];
if ( iCol >= iNumCols / 2 )
f += m_fScrolls [ SCROLL_SPLIT ];
if ( ( iCol % 2 ) == 1 )
f += m_fScrolls [ SCROLL_ALTERNATE ];
int iFirstCrossCol = iNumCols / 4 ;
int iLastCrossCol = iNumCols - 1 - iFirstCrossCol ;
if ( iCol >= iFirstCrossCol && iCol <= iLastCrossCol )
f += m_fScrolls [ SCROLL_CROSS ];
if ( f > 2 )
f = fmodf ( f , 2 );
if ( f > 1 )
f = SCALE ( f , 1.f , 2.f , 1.f , 0.f );
return f ;
}
bool PlayerOptions :: operator == ( const PlayerOptions & other ) const
{
#define COMPARE(x) { if( x != other.x ) return false; }
COMPARE ( m_fTimeSpacing );
COMPARE ( m_fScrollSpeed );
COMPARE ( m_fScrollBPM );
2011-07-03 00:08:56 -07:00
COMPARE ( m_fMaxScrollBPM );
2011-03-17 01:47:30 -04:00
COMPARE ( m_fRandomSpeed );
COMPARE ( m_FailType );
COMPARE ( m_bMuteOnError );
COMPARE ( m_fDark );
COMPARE ( m_fBlind );
COMPARE ( m_fCover );
COMPARE ( m_fRandAttack );
2011-06-26 23:58:24 -04:00
COMPARE ( m_fNoAttack );
2011-03-17 01:47:30 -04:00
COMPARE ( m_fPlayerAutoPlay );
COMPARE ( m_fPerspectiveTilt );
COMPARE ( m_fSkew );
COMPARE ( m_sNoteSkin );
for ( int i = 0 ; i < PlayerOptions :: NUM_ACCELS ; ++ i )
COMPARE ( m_fAccels [ i ]);
for ( int i = 0 ; i < PlayerOptions :: NUM_EFFECTS ; ++ i )
COMPARE ( m_fEffects [ i ]);
for ( int i = 0 ; i < PlayerOptions :: NUM_APPEARANCES ; ++ i )
COMPARE ( m_fAppearances [ i ]);
for ( int i = 0 ; i < PlayerOptions :: NUM_SCROLLS ; ++ i )
COMPARE ( m_fScrolls [ i ]);
for ( int i = 0 ; i < PlayerOptions :: NUM_TURNS ; ++ i )
COMPARE ( m_bTurns [ i ]);
for ( int i = 0 ; i < PlayerOptions :: NUM_TRANSFORMS ; ++ i )
COMPARE ( m_bTransforms [ i ]);
#undef COMPARE
return true ;
}
bool PlayerOptions :: IsEasierForSongAndSteps ( Song * pSong , Steps * pSteps , PlayerNumber pn ) const
{
2011-05-15 14:05:02 -04:00
if ( m_fTimeSpacing && pSteps -> HasSignificantTimingChanges () )
2011-03-17 01:47:30 -04:00
return true ;
const RadarValues & rv = pSteps -> GetRadarValues ( pn );
if ( m_bTransforms [ TRANSFORM_NOHOLDS ] && rv [ RadarCategory_Holds ] > 0 )
return true ;
if ( m_bTransforms [ TRANSFORM_NOROLLS ] && rv [ RadarCategory_Rolls ] > 0 )
return true ;
if ( m_bTransforms [ TRANSFORM_NOMINES ] && rv [ RadarCategory_Mines ] > 0 )
return true ;
if ( m_bTransforms [ TRANSFORM_NOHANDS ] && rv [ RadarCategory_Hands ] > 0 )
return true ;
if ( m_bTransforms [ TRANSFORM_NOQUADS ] && rv [ RadarCategory_Hands ] > 0 )
return true ;
if ( m_bTransforms [ TRANSFORM_NOJUMPS ] && rv [ RadarCategory_Jumps ] > 0 )
return true ;
if ( m_bTransforms [ TRANSFORM_NOLIFTS ] && rv [ RadarCategory_Lifts ] > 0 )
return true ;
if ( m_bTransforms [ TRANSFORM_NOFAKES ] && rv [ RadarCategory_Fakes ] > 0 )
return true ;
if ( m_bTransforms [ TRANSFORM_NOSTRETCH ] )
return true ;
// Inserted holds can be really easy on some songs, and scores will be
// highly hold-weighted, and very little tap score weighted.
if ( m_bTransforms [ TRANSFORM_LITTLE ] ) return true ;
if ( m_bTransforms [ TRANSFORM_PLANTED ] ) return true ;
if ( m_bTransforms [ TRANSFORM_FLOORED ] ) return true ;
if ( m_bTransforms [ TRANSFORM_TWISTER ] ) return true ;
// This makes songs with sparse notes easier.
if ( m_bTransforms [ TRANSFORM_ECHO ] ) return true ;
2011-06-24 10:55:39 -04:00
// Removing attacks is easier in general.
2011-06-26 23:58:24 -04:00
if ( m_fNoAttack || ( ! m_fRandAttack && pSteps -> HasAttacks ()))
2011-06-24 10:55:39 -04:00
return true ;
2011-03-17 01:47:30 -04:00
if ( m_fCover ) return true ;
2011-07-03 00:08:56 -07:00
2013-04-19 21:49:55 -04:00
// M-mods make songs with indefinite BPMs easier because
2011-07-03 00:08:56 -07:00
// they ensure that the song has a scrollable speed.
2013-04-19 21:49:55 -04:00
if ( m_fMaxScrollBPM != 0 )
2011-07-03 00:08:56 -07:00
{
// BPM display is obfuscated
// if( pSong->m_DisplayBPMType == DISPLAY_BPM_RANDOM )
// return true;
DisplayBpms bpms ;
if ( GAMESTATE -> IsCourseMode () )
{
Trail * pTrail = GAMESTATE -> m_pCurCourse -> GetTrail ( GAMESTATE -> GetCurrentStyle () -> m_StepsType );
pTrail -> GetDisplayBpms ( bpms );
}
else
{
GAMESTATE -> m_pCurSong -> GetDisplayBpms ( bpms );
}
pSong -> GetDisplayBpms ( bpms );
// maximum BPM is obfuscated, so M-mods will set a playable speed.
if ( bpms . GetMax () <= 0 )
return true ;
}
2011-03-17 01:47:30 -04:00
if ( m_fPlayerAutoPlay ) return true ;
return false ;
}
bool PlayerOptions :: IsEasierForCourseAndTrail ( Course * pCourse , Trail * pTrail ) const
{
2012-12-27 11:38:53 -05:00
ASSERT ( pCourse != NULL );
ASSERT ( pTrail != NULL );
2011-03-17 01:47:30 -04:00
FOREACH_CONST ( TrailEntry , pTrail -> m_vEntries , e )
{
if ( e -> pSong && IsEasierForSongAndSteps ( e -> pSong , e -> pSteps , PLAYER_1 ) )
return true ;
}
return false ;
}
void PlayerOptions :: GetLocalizedMods ( vector < RString > & AddTo ) const
{
vector < RString > vMods ;
GetMods ( vMods );
FOREACH_CONST ( RString , vMods , s )
{
const RString & sOneMod = * s ;
ASSERT ( ! sOneMod . empty () );
vector < RString > asTokens ;
split ( sOneMod , " " , asTokens );
if ( asTokens . empty () )
continue ;
// Strip the approach speed token, if any
if ( asTokens [ 0 ][ 0 ] == '*' )
asTokens . erase ( asTokens . begin () );
// capitalize NoteSkin names
asTokens . back () = Capitalize ( asTokens . back () );
/* Theme the mod name (the last string). Allow this to not exist, since
* characters might use modifiers that don't exist in the theme. */
asTokens . back () = CommonMetrics :: LocalizeOptionItem ( asTokens . back (), true );
RString sLocalizedMod = join ( " " , asTokens );
AddTo . push_back ( sLocalizedMod );
}
}
bool PlayerOptions :: ContainsTransformOrTurn () const
{
for ( int i = 0 ; i < NUM_TRANSFORMS ; i ++ )
{
if ( m_bTransforms [ i ] )
return true ;
}
for ( int i = 0 ; i < NUM_TURNS ; i ++ )
{
if ( m_bTurns [ i ] )
return true ;
}
return false ;
}
RString PlayerOptions :: GetSavedPrefsString () const
{
PlayerOptions po_prefs ;
#define SAVE(x) po_prefs.x = this->x;
SAVE ( m_fTimeSpacing );
SAVE ( m_fScrollSpeed );
SAVE ( m_fScrollBPM );
2011-07-03 00:08:56 -07:00
SAVE ( m_fMaxScrollBPM );
2011-03-17 01:47:30 -04:00
SAVE ( m_fScrolls [ SCROLL_REVERSE ] );
SAVE ( m_fPerspectiveTilt );
SAVE ( m_bTransforms [ TRANSFORM_NOHOLDS ] );
SAVE ( m_bTransforms [ TRANSFORM_NOROLLS ] );
SAVE ( m_bTransforms [ TRANSFORM_NOMINES ] );
SAVE ( m_bTransforms [ TRANSFORM_NOJUMPS ] );
SAVE ( m_bTransforms [ TRANSFORM_NOHANDS ] );
SAVE ( m_bTransforms [ TRANSFORM_NOQUADS ] );
SAVE ( m_bTransforms [ TRANSFORM_NOSTRETCH ] );
SAVE ( m_bTransforms [ TRANSFORM_NOLIFTS ] );
SAVE ( m_bTransforms [ TRANSFORM_NOFAKES ] );
SAVE ( m_bMuteOnError );
SAVE ( m_sNoteSkin );
#undef SAVE
return po_prefs . GetString ();
}
void PlayerOptions :: ResetPrefs ( ResetPrefsType type )
{
PlayerOptions defaults ;
#define CPY(x) this->x = defaults.x;
switch ( type )
{
DEFAULT_FAIL ( type );
case saved_prefs :
CPY ( m_fTimeSpacing );
CPY ( m_fScrollSpeed );
CPY ( m_fScrollBPM );
2011-07-03 00:08:56 -07:00
CPY ( m_fMaxScrollBPM );
2011-03-17 01:47:30 -04:00
break ;
case saved_prefs_invalid_for_course :
break ;
}
CPY ( m_fPerspectiveTilt );
CPY ( m_bTransforms [ TRANSFORM_NOHOLDS ] );
CPY ( m_bTransforms [ TRANSFORM_NOROLLS ] );
CPY ( m_bTransforms [ TRANSFORM_NOMINES ] );
CPY ( m_bTransforms [ TRANSFORM_NOJUMPS ] );
CPY ( m_bTransforms [ TRANSFORM_NOHANDS ] );
CPY ( m_bTransforms [ TRANSFORM_NOQUADS ] );
CPY ( m_bTransforms [ TRANSFORM_NOSTRETCH ] );
CPY ( m_bTransforms [ TRANSFORM_NOLIFTS ] );
CPY ( m_bTransforms [ TRANSFORM_NOFAKES ] );
// Don't clear this.
// CPY( m_sNoteSkin );
#undef CPY
}
// lua start
#include "LuaBinding.h"
2014-05-03 19:27:32 -06:00
#include "OptionsBinding.h"
2011-03-17 01:47:30 -04:00
/** @brief Allow Lua to have access to PlayerOptions. */
class LunaPlayerOptions : public Luna < PlayerOptions >
{
public :
2011-11-30 00:35:06 -06:00
static int IsEasierForSongAndSteps ( T * p , lua_State * L )
{
Song * pSong = Luna < Song >:: check ( L , 1 );
Steps * pSteps = Luna < Steps >:: check ( L , 2 );
PlayerNumber pn = Enum :: Check < PlayerNumber > ( L , 3 );
lua_pushboolean ( L , p -> IsEasierForSongAndSteps ( pSong , pSteps , pn ) );
return 1 ;
}
static int IsEasierForCourseAndTrail ( T * p , lua_State * L )
{
// course, trail
Course * pCourse = Luna < Course >:: check ( L , 1 );
Trail * pTrail = Luna < Trail >:: check ( L , 2 );
lua_pushboolean ( L , p -> IsEasierForCourseAndTrail ( pCourse , pTrail ) );
return 1 ;
}
2014-05-01 23:23:20 -06:00
// Direct control functions, for themes that can handle it.
2014-05-03 19:27:32 -06:00
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 );
2014-05-01 23:23:20 -06:00
BOOL_INTERFACE ( TurnNone , Turns [ PlayerOptions :: TURN_NONE ]);
BOOL_INTERFACE ( Mirror , Turns [ PlayerOptions :: TURN_MIRROR ]);
BOOL_INTERFACE ( Backwards , Turns [ PlayerOptions :: TURN_BACKWARDS ]);
BOOL_INTERFACE ( Left , Turns [ PlayerOptions :: TURN_LEFT ]);
BOOL_INTERFACE ( Right , Turns [ PlayerOptions :: TURN_RIGHT ]);
BOOL_INTERFACE ( Shuffle , Turns [ PlayerOptions :: TURN_SHUFFLE ]);
BOOL_INTERFACE ( SoftShuffle , Turns [ PlayerOptions :: TURN_SOFT_SHUFFLE ]);
BOOL_INTERFACE ( SuperShuffle , Turns [ PlayerOptions :: TURN_SUPER_SHUFFLE ]);
BOOL_INTERFACE ( NoHolds , Transforms [ PlayerOptions :: TRANSFORM_NOHOLDS ]);
BOOL_INTERFACE ( NoRolls , Transforms [ PlayerOptions :: TRANSFORM_NOROLLS ]);
BOOL_INTERFACE ( NoMines , Transforms [ PlayerOptions :: TRANSFORM_NOMINES ]);
BOOL_INTERFACE ( Little , Transforms [ PlayerOptions :: TRANSFORM_LITTLE ]);
BOOL_INTERFACE ( Wide , Transforms [ PlayerOptions :: TRANSFORM_WIDE ]);
BOOL_INTERFACE ( Big , Transforms [ PlayerOptions :: TRANSFORM_BIG ]);
BOOL_INTERFACE ( Quick , Transforms [ PlayerOptions :: TRANSFORM_QUICK ]);
BOOL_INTERFACE ( BMRize , Transforms [ PlayerOptions :: TRANSFORM_BMRIZE ]);
BOOL_INTERFACE ( Skippy , Transforms [ PlayerOptions :: TRANSFORM_SKIPPY ]);
BOOL_INTERFACE ( Mines , Transforms [ PlayerOptions :: TRANSFORM_MINES ]);
BOOL_INTERFACE ( AttackMines , Transforms [ PlayerOptions :: TRANSFORM_ATTACKMINES ]);
BOOL_INTERFACE ( Echo , Transforms [ PlayerOptions :: TRANSFORM_ECHO ]);
BOOL_INTERFACE ( Stomp , Transforms [ PlayerOptions :: TRANSFORM_STOMP ]);
BOOL_INTERFACE ( Planted , Transforms [ PlayerOptions :: TRANSFORM_PLANTED ]);
BOOL_INTERFACE ( Floored , Transforms [ PlayerOptions :: TRANSFORM_FLOORED ]);
BOOL_INTERFACE ( Twister , Transforms [ PlayerOptions :: TRANSFORM_TWISTER ]);
BOOL_INTERFACE ( HoldRolls , Transforms [ PlayerOptions :: TRANSFORM_HOLDROLLS ]);
BOOL_INTERFACE ( NoJumps , Transforms [ PlayerOptions :: TRANSFORM_NOJUMPS ]);
BOOL_INTERFACE ( NoHands , Transforms [ PlayerOptions :: TRANSFORM_NOHANDS ]);
BOOL_INTERFACE ( NoLifts , Transforms [ PlayerOptions :: TRANSFORM_NOLIFTS ]);
BOOL_INTERFACE ( NoFakes , Transforms [ PlayerOptions :: TRANSFORM_NOFAKES ]);
BOOL_INTERFACE ( NoQuads , Transforms [ PlayerOptions :: TRANSFORM_NOQUADS ]);
BOOL_INTERFACE ( NoStretch , Transforms [ PlayerOptions :: TRANSFORM_NOSTRETCH ]);
BOOL_INTERFACE ( MuteOnError , MuteOnError );
2014-05-03 19:27:32 -06:00
ENUM_INTERFACE ( FailSetting , FailType , FailType );
2014-05-01 23:23:20 -06:00
2011-03-20 20:52:56 -05:00
// NoteSkins
2014-05-01 23:23:20 -06:00
static int NoteSkin ( T * p , lua_State * L )
2011-03-20 20:52:56 -05:00
{
2014-05-02 16:45:49 -06:00
DefaultNilArgs ( L , 2 );
2011-03-20 20:52:56 -05:00
if ( p -> m_sNoteSkin . empty () )
2014-05-01 23:23:20 -06:00
{
2011-03-20 20:52:56 -05:00
lua_pushstring ( L , CommonMetrics :: DEFAULT_NOTESKIN_NAME . GetValue () );
2014-05-01 23:23:20 -06:00
}
2011-03-20 20:52:56 -05:00
else
2014-05-01 23:23:20 -06:00
{
2011-03-20 20:52:56 -05:00
lua_pushstring ( L , p -> m_sNoteSkin );
2014-05-01 23:23:20 -06:00
}
if ( lua_isstring ( L , 1 ))
{
if ( NOTESKIN -> DoesNoteSkinExist ( SArg ( 1 )))
{
p -> m_sNoteSkin = SArg ( 1 );
lua_pushboolean ( L , true );
}
2014-05-02 16:45:49 -06:00
else
{
lua_pushnil ( L );
}
}
else
{
lua_pushnil ( L );
2014-05-01 23:23:20 -06:00
}
return 2 ;
}
static void SetSpeedModApproaches ( T * p , float speed )
2011-03-20 13:03:16 -05:00
{
2014-05-01 23:23:20 -06:00
p -> m_SpeedfScrollBPM = speed ;
p -> m_SpeedfScrollSpeed = speed ;
p -> m_SpeedfMaxScrollBPM = speed ;
p -> m_SpeedfTimeSpacing = speed ;
2011-03-20 13:03:16 -05:00
}
2011-03-17 01:47:30 -04:00
2011-03-20 21:25:49 -05:00
// Speed Mods
2014-05-01 23:23:20 -06:00
// Sanity checked functions for speed mods, for themes that want to use the
// engine's enforcement of sane separation between speed mod types.
static int CMod ( T * p , lua_State * L )
2011-03-20 21:25:49 -05:00
{
2014-05-02 16:45:49 -06:00
DefaultNilArgs ( L , 2 );
2014-05-01 23:23:20 -06:00
if ( p -> m_fTimeSpacing )
{
lua_pushnumber ( L , p -> m_fScrollBPM );
lua_pushnumber ( L , p -> m_SpeedfScrollBPM );
}
2011-03-20 21:25:49 -05:00
else
2014-05-01 23:23:20 -06:00
{
2011-03-20 21:25:49 -05:00
lua_pushnil ( L );
2014-05-01 23:23:20 -06:00
lua_pushnil ( L );
}
if ( lua_isnumber ( L , 1 ))
{
float speed = FArg ( 1 );
if ( ! isfinite ( speed ) || speed <= 0.0f )
{
luaL_error ( L , "CMod speed must be finite and greater than 0." );
}
p -> m_fScrollBPM = speed ;
p -> m_fTimeSpacing = 1 ;
p -> m_fScrollSpeed = 1 ;
p -> m_fMaxScrollBPM = 0 ;
}
if ( lua_isnumber ( L , 2 ))
{
2014-05-03 19:27:32 -06:00
SetSpeedModApproaches ( p , FArgGTEZero ( L , 2 ));
2014-05-01 23:23:20 -06:00
}
return 2 ;
2012-05-31 12:19:00 -05:00
}
2011-11-27 05:02:39 -06:00
2014-05-01 23:23:20 -06:00
static int XMod ( T * p , lua_State * L )
2011-03-20 21:25:49 -05:00
{
2014-05-02 16:45:49 -06:00
DefaultNilArgs ( L , 2 );
2014-05-01 23:23:20 -06:00
if ( ! p -> m_fTimeSpacing )
{
lua_pushnumber ( L , p -> m_fScrollSpeed );
lua_pushnumber ( L , p -> m_SpeedfScrollSpeed );
}
2011-03-20 21:25:49 -05:00
else
2014-05-01 23:23:20 -06:00
{
2011-03-20 21:25:49 -05:00
lua_pushnil ( L );
2014-05-01 23:23:20 -06:00
lua_pushnil ( L );
}
if ( lua_isnumber ( L , 1 ))
{
p -> m_fScrollSpeed = FArg ( 1 );
p -> m_fTimeSpacing = 0 ;
p -> m_fScrollBPM = CMOD_DEFAULT ;
p -> m_fMaxScrollBPM = 0 ;
}
if ( lua_isnumber ( L , 2 ))
{
2014-05-03 19:27:32 -06:00
SetSpeedModApproaches ( p , FArgGTEZero ( L , 2 ));
2014-05-01 23:23:20 -06:00
}
return 2 ;
2012-05-31 12:19:00 -05:00
}
2011-11-27 05:02:39 -06:00
2014-05-01 23:23:20 -06:00
static int MMod ( T * p , lua_State * L )
2012-05-31 12:19:00 -05:00
{
2014-05-02 16:45:49 -06:00
DefaultNilArgs ( L , 2 );
2014-05-01 23:23:20 -06:00
if ( ! p -> m_fTimeSpacing && p -> m_fMaxScrollBPM )
{
2012-05-31 12:19:00 -05:00
lua_pushnumber ( L , p -> m_fMaxScrollBPM );
2014-05-01 23:23:20 -06:00
lua_pushnumber ( L , p -> m_SpeedfMaxScrollBPM );
}
2012-05-31 12:19:00 -05:00
else
2014-05-01 23:23:20 -06:00
{
2012-05-31 12:19:00 -05:00
lua_pushnil ( L );
2014-05-01 23:23:20 -06:00
lua_pushnil ( L );
}
if ( lua_isnumber ( L , 1 ))
{
float speed = FArg ( 1 );
if ( ! isfinite ( speed ) || speed <= 0.0f )
{
luaL_error ( L , "MMod speed must be finite and greater than 0." );
}
p -> m_fScrollBPM = CMOD_DEFAULT ;
p -> m_fTimeSpacing = 0 ;
p -> m_fScrollSpeed = 1 ;
p -> m_fMaxScrollBPM = speed ;
}
if ( lua_isnumber ( L , 2 ))
{
2014-05-03 19:27:32 -06:00
SetSpeedModApproaches ( p , FArgGTEZero ( L , 2 ));
2014-05-01 23:23:20 -06:00
}
return 2 ;
}
2012-05-31 12:19:00 -05:00
2014-05-01 23:23:20 -06:00
static void SetPerspectiveApproach ( T * p , lua_State * L , float speed )
{
p -> m_SpeedfPerspectiveTilt = speed ;
p -> m_SpeedfSkew = speed ;
}
static int Overhead ( T * p , lua_State * L )
{
2014-05-02 16:45:49 -06:00
DefaultNilArgs ( L , 2 );
2014-05-01 23:23:20 -06:00
lua_pushboolean ( L , ( p -> m_fPerspectiveTilt == 0.0f && p -> m_fSkew == 0.0f ));
if ( lua_toboolean ( L , 1 ))
{
p -> m_fPerspectiveTilt = 0 ;
p -> m_fSkew = 0 ;
}
if ( lua_isnumber ( L , 2 ))
{
2014-05-03 19:27:32 -06:00
SetPerspectiveApproach ( p , L , FArgGTEZero ( L , 2 ));
2014-05-01 23:23:20 -06:00
}
2012-05-31 12:19:00 -05:00
return 1 ;
}
2014-05-01 23:23:20 -06:00
static int Incoming ( T * p , lua_State * L )
2012-05-31 12:19:00 -05:00
{
2014-05-02 16:45:49 -06:00
DefaultNilArgs ( L , 2 );
2014-05-01 23:23:20 -06:00
if (( p -> m_fSkew > 0.0f && p -> m_fPerspectiveTilt < 0.0f ) ||
( p -> m_fSkew < 0.0f && p -> m_fPerspectiveTilt > 0.0f ))
{
lua_pushnumber ( L , p -> m_fSkew );
lua_pushnumber ( L , p -> m_SpeedfSkew );
}
else
{
lua_pushnil ( L );
lua_pushnil ( L );
}
if ( lua_isnumber ( L , 1 ))
{
float value = FArg ( 1 );
p -> m_fPerspectiveTilt = - value ;
p -> m_fSkew = value ;
}
if ( lua_isnumber ( L , 2 ))
{
2014-05-03 19:27:32 -06:00
SetPerspectiveApproach ( p , L , FArgGTEZero ( L , 2 ));
2014-05-01 23:23:20 -06:00
}
return 2 ;
2012-05-31 12:19:00 -05:00
}
2011-03-20 21:25:49 -05:00
2014-05-01 23:23:20 -06:00
static int Space ( T * p , lua_State * L )
{
2014-05-02 16:45:49 -06:00
DefaultNilArgs ( L , 2 );
2014-05-01 23:23:20 -06:00
if (( p -> m_fSkew > 0.0f && p -> m_fPerspectiveTilt > 0.0f ) ||
( p -> m_fSkew < 0.0f && p -> m_fPerspectiveTilt < 0.0f ))
{
lua_pushnumber ( L , p -> m_fSkew );
lua_pushnumber ( L , p -> m_SpeedfSkew );
}
else
{
lua_pushnil ( L );
lua_pushnil ( L );
}
if ( lua_isnumber ( L , 1 ))
{
float value = FArg ( 1 );
p -> m_fPerspectiveTilt = value ;
p -> m_fSkew = value ;
}
if ( lua_isnumber ( L , 2 ))
{
2014-05-03 19:27:32 -06:00
SetPerspectiveApproach ( p , L , FArgGTEZero ( L , 2 ));
2014-05-01 23:23:20 -06:00
}
return 2 ;
}
2011-03-20 21:25:49 -05:00
2014-05-01 23:23:20 -06:00
static int Hallway ( T * p , lua_State * L )
{
2014-05-02 16:45:49 -06:00
DefaultNilArgs ( L , 2 );
2014-05-01 23:23:20 -06:00
if ( p -> m_fSkew == 0.0f && p -> m_fPerspectiveTilt < 0.0f )
{
lua_pushnumber ( L , - p -> m_fPerspectiveTilt );
lua_pushnumber ( L , p -> m_SpeedfPerspectiveTilt );
}
else
{
lua_pushnil ( L );
lua_pushnil ( L );
}
if ( lua_isnumber ( L , 1 ))
{
p -> m_fPerspectiveTilt = - FArg ( 1 );
p -> m_fSkew = 0 ;
}
if ( lua_isnumber ( L , 2 ))
{
2014-05-03 19:27:32 -06:00
SetPerspectiveApproach ( p , L , FArgGTEZero ( L , 2 ));
2014-05-01 23:23:20 -06:00
}
return 2 ;
}
static int Distant ( T * p , lua_State * L )
{
2014-05-02 16:45:49 -06:00
DefaultNilArgs ( L , 2 );
2014-05-01 23:23:20 -06:00
if ( p -> m_fSkew == 0.0f && p -> m_fPerspectiveTilt > 0.0f )
{
lua_pushnumber ( L , p -> m_fPerspectiveTilt );
lua_pushnumber ( L , p -> m_SpeedfPerspectiveTilt );
}
else
{
lua_pushnil ( L );
lua_pushnil ( L );
}
if ( lua_isnumber ( L , 1 ))
{
p -> m_fPerspectiveTilt = FArg ( 1 );
p -> m_fSkew = 0 ;
}
if ( lua_isnumber ( L , 2 ))
{
2014-05-03 19:27:32 -06:00
SetPerspectiveApproach ( p , L , FArgGTEZero ( L , 2 ));
2014-05-01 23:23:20 -06:00
}
return 2 ;
}
2011-03-20 21:25:49 -05:00
2014-05-01 23:23:20 -06:00
DEFINE_METHOD ( UsingReverse , m_fScrolls [ PlayerOptions :: SCROLL_REVERSE ] == 1.0f );
2011-03-20 21:25:49 -05:00
static int GetReversePercentForColumn ( T * p , lua_State * L )
{
2011-11-27 05:02:39 -06:00
const int colNum = IArg ( 1 );
const int numColumns = GAMESTATE -> GetCurrentStyle () -> m_iColsPerPlayer ;
// We don't want to go outside the bounds.
if ( colNum < 0 || colNum > numColumns )
lua_pushnil ( L );
else
lua_pushnumber ( L , p -> GetReversePercentForColumn ( colNum ) );
2011-03-20 21:25:49 -05:00
return 1 ;
}
2011-11-27 05:02:39 -06:00
2011-06-26 23:58:24 -04:00
static int GetStepAttacks ( T * p , lua_State * L )
{
lua_pushnumber ( L ,
2014-05-01 23:23:20 -06:00
( p -> m_fNoAttack > 0 || p -> m_fRandAttack > 0 ? false : true ));
2011-06-26 23:58:24 -04:00
return 1 ;
}
2011-03-20 21:25:49 -05:00
2011-03-17 01:47:30 -04:00
LunaPlayerOptions ()
{
2011-11-30 00:35:06 -06:00
ADD_METHOD ( IsEasierForSongAndSteps );
ADD_METHOD ( IsEasierForCourseAndTrail );
2014-05-01 23:23:20 -06:00
ADD_METHOD ( TimeSpacing );
ADD_METHOD ( MaxScrollBPM );
ADD_METHOD ( ScrollSpeed );
ADD_METHOD ( ScrollBPM );
ADD_METHOD ( Boost );
ADD_METHOD ( Brake );
ADD_METHOD ( Wave );
ADD_METHOD ( Expand );
ADD_METHOD ( Boomerang );
ADD_METHOD ( Drunk );
ADD_METHOD ( Dizzy );
ADD_METHOD ( Confusion );
ADD_METHOD ( Mini );
ADD_METHOD ( Tiny );
ADD_METHOD ( Flip );
ADD_METHOD ( Invert );
ADD_METHOD ( Tornado );
ADD_METHOD ( Tipsy );
ADD_METHOD ( Bumpy );
ADD_METHOD ( Beat );
ADD_METHOD ( Xmode );
ADD_METHOD ( Twirl );
ADD_METHOD ( Roll );
ADD_METHOD ( Hidden );
ADD_METHOD ( HiddenOffset );
ADD_METHOD ( Sudden );
ADD_METHOD ( SuddenOffset );
ADD_METHOD ( Stealth );
ADD_METHOD ( Blink );
ADD_METHOD ( RandomVanish );
ADD_METHOD ( Reverse );
ADD_METHOD ( Split );
ADD_METHOD ( Alternate );
ADD_METHOD ( Cross );
ADD_METHOD ( Centered );
ADD_METHOD ( Dark );
ADD_METHOD ( Blind );
ADD_METHOD ( Cover );
ADD_METHOD ( RandAttack );
ADD_METHOD ( NoAttack );
ADD_METHOD ( PlayerAutoPlay );
ADD_METHOD ( Tilt );
ADD_METHOD ( Skew );
ADD_METHOD ( Passmark );
ADD_METHOD ( RandomSpeed );
ADD_METHOD ( TurnNone );
ADD_METHOD ( Mirror );
ADD_METHOD ( Backwards );
ADD_METHOD ( Left );
ADD_METHOD ( Right );
ADD_METHOD ( Shuffle );
ADD_METHOD ( SoftShuffle );
ADD_METHOD ( SuperShuffle );
ADD_METHOD ( NoHolds );
ADD_METHOD ( NoRolls );
ADD_METHOD ( NoMines );
ADD_METHOD ( Little );
ADD_METHOD ( Wide );
ADD_METHOD ( Big );
ADD_METHOD ( Quick );
ADD_METHOD ( BMRize );
ADD_METHOD ( Skippy );
ADD_METHOD ( Mines );
ADD_METHOD ( AttackMines );
ADD_METHOD ( Echo );
ADD_METHOD ( Stomp );
ADD_METHOD ( Planted );
ADD_METHOD ( Floored );
ADD_METHOD ( Twister );
ADD_METHOD ( HoldRolls );
ADD_METHOD ( NoJumps );
ADD_METHOD ( NoHands );
ADD_METHOD ( NoLifts );
ADD_METHOD ( NoFakes );
ADD_METHOD ( NoQuads );
ADD_METHOD ( NoStretch );
ADD_METHOD ( MuteOnError );
ADD_METHOD ( NoteSkin );
ADD_METHOD ( FailSetting );
2011-11-27 05:02:39 -06:00
// Speed
2014-05-01 23:23:20 -06:00
ADD_METHOD ( CMod );
ADD_METHOD ( XMod );
ADD_METHOD ( MMod );
2011-03-20 21:25:49 -05:00
2014-05-01 23:23:20 -06:00
ADD_METHOD ( Overhead );
ADD_METHOD ( Incoming );
ADD_METHOD ( Space );
ADD_METHOD ( Hallway );
ADD_METHOD ( Distant );
2011-03-20 21:25:49 -05:00
2011-04-16 21:10:44 -05:00
ADD_METHOD ( UsingReverse );
2011-03-20 21:25:49 -05:00
ADD_METHOD ( GetReversePercentForColumn );
2014-05-01 23:23:20 -06:00
ADD_METHOD ( GetStepAttacks );
2011-03-17 01:47:30 -04:00
}
};
LUA_REGISTER_CLASS ( PlayerOptions )
// lua end
/*
* (c) 2001-2004 Chris Danford, Glenn Maynard
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, and/or sell copies of the Software, and to permit persons to
* whom the Software is furnished to do so, provided that the above
* copyright notice(s) and this permission notice appear in all copies of
* the Software and that both the above copyright notice(s) and this
* permission notice appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/