From b3e11dcb94cf3b94ffd1764e61d39e3b91ecc47f Mon Sep 17 00:00:00 2001 From: Mike Hawkins Date: Fri, 16 May 2008 04:00:13 +0000 Subject: [PATCH] Random attacks modifier --- stepmania/Data/RandomAttacks.txt | 73 +++++++++++++++++++++++ stepmania/Themes/default/Languages/en.ini | 3 + stepmania/Themes/default/metrics.ini | 17 ++++-- stepmania/src/GameState.h | 5 ++ stepmania/src/Player.cpp | 39 ++++++++++++ stepmania/src/Player.h | 4 ++ stepmania/src/PlayerOptions.cpp | 6 ++ stepmania/src/PlayerOptions.h | 1 + stepmania/src/SongManager.cpp | 53 ++++++++++++++++ stepmania/src/SongManager.h | 1 + 10 files changed, 196 insertions(+), 6 deletions(-) create mode 100644 stepmania/Data/RandomAttacks.txt diff --git a/stepmania/Data/RandomAttacks.txt b/stepmania/Data/RandomAttacks.txt new file mode 100644 index 0000000000..59a7d6ee3f --- /dev/null +++ b/stepmania/Data/RandomAttacks.txt @@ -0,0 +1,73 @@ +// File for specifying Random Attacks, used by the Random Attacks mod and Attack Mines mod. +// Only specify one modifier per attack. +// +// Sample lines: +// +// #ATTACK:drunk; +// #ATTACK:30% tornado; +// #ATTACK:-20% beat; +// + +// +// Speed Mods +// +#ATTACK:0.5x; +#ATTACK:1x; +#ATTACK:1.5x; +#ATTACK:2x; + +// +// Accel Mods +// +#ATTACK:boost; +#ATTACK:brake; +#ATTACK:wave; +#ATTACK:expand; + +// +// Effect Mods +// +#ATTACK:drunk; +#ATTACK:dizzy; +#ATTACK:confusion; +#ATTACK:65% mini; +#ATTACK:20% flip; +#ATTACK:30% invert; +#ATTACK:30% tornado; +#ATTACK:tipsy; +#ATTACK:beat; +#ATTACK:bumpy; + +// +// Appearance Mods +// +#ATTACK:50% hidden; +#ATTACK:50% sudden; +#ATTACK:30% blink; + +// +// Hide Mods +// +#ATTACK:dark; +#ATTACK:blind; + +// +// Transform Mods +// +#ATTACK:mines; + +// +// Scroll +// +#ATTACK:30% reverse; +#ATTACK:reverse; +#ATTACK:centered; + +// +// Perspective Mods +// +#ATTACK:hallway; +#ATTACK:space; +#ATTACK:incoming; +#ATTACK:overhead; +#ATTACK:distant; \ No newline at end of file diff --git a/stepmania/Themes/default/Languages/en.ini b/stepmania/Themes/default/Languages/en.ini index 75c2e2de81..32f7b8fe21 100644 --- a/stepmania/Themes/default/Languages/en.ini +++ b/stepmania/Themes/default/Languages/en.ini @@ -277,6 +277,7 @@ Appearance=Appearance Appearance Options=Change the theme, announcer, and other style options. ArcadeOptionsNavigation=When using &oq;SM style&cq;, the Start button will take you to the next screen and Up/Down will switch option lines. When using &oq;Arcade style&cq;, the Start button will move the cursor to the next line and Up/Down will be ignored. Assist=Assist +Attacks=Choose whether non-course attacks will appear during gameplay. AttractSoundFrequency=Set to ALWAYS to play sound every during the attract screens. Set to N TIMES to play sounds every N attract sequences. AutoAdjust=AutoAdjust AutoMapOnJoyChange=&oq;ON&cq; will cause the game to automatically remap all the joysticks attached to your computer if the joysticks attached to your system are different than the last time you started the game. Auto mapping will override any manually defined mappings. @@ -598,6 +599,7 @@ Press Start=Press Start Quick=Quick R.Vanish=R.Vanish Random=Random +RandomAttacks=Random Attacks RandomBG=Random Backgrounds Random Movies=Random Movies Ranking=Ranking @@ -679,6 +681,7 @@ ArcadeOptionsNavigation=Options Navigation Artist=Artist Artist transliteration=Artist transliteration Assist=Assist +Attacks=Attacks AttractSoundFrequency=Attract Sound Frequency AutoAdjust=Auto Adjust AutoMapOnJoyChange=Auto Map On Joy Change diff --git a/stepmania/Themes/default/metrics.ini b/stepmania/Themes/default/metrics.ini index b80e6ab873..f2fb57fb6a 100644 --- a/stepmania/Themes/default/metrics.ini +++ b/stepmania/Themes/default/metrics.ini @@ -3466,7 +3466,7 @@ NextScreen=ScreenPlayerOptionsNext() PlayMusic=false TimerSeconds=30 ShowStyleIcon=false -LineNames="1,2,3,4,5,6,7,8,9,10,11,12,13,14,15" +LineNames="1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16" Line1="list,Speed" Line2="list,Accel" Line3="list,Effect" @@ -3477,11 +3477,12 @@ Line7="list,Scroll" Line8="list,NoteSkins" Line9="list,Holds" Line10="list,Mines" -Line11="list,Hide" -Line12="list,Persp" -Line13="list,ScoreDisplay" -Line14="list,Steps" -Line15="list,Characters" +Line11="list,Attacks" +Line12="list,Hide" +Line13="list,Persp" +Line14="list,ScoreDisplay" +Line15="list,Steps" +Line16="list,Characters" [ScreenRaveOptions] Fallback="ScreenOptions" @@ -3680,6 +3681,10 @@ MinesDefault="mod,no nomines,no mines" Mines,1="mod,nomines;name,Off" Mines,2="name,On" Mines,3="mod,mines;name,Add" +Attacks="2" +AttacksDefault="mod,no randomattacks" +Attacks,1="name,Off" +Attacks,2="mod,randomattacks;name,RandomAttacks" Hide="3" HideDefault="mod,no dark,no blind" Hide,1="name,Off" diff --git a/stepmania/src/GameState.h b/stepmania/src/GameState.h index da2e295803..4c9441533c 100644 --- a/stepmania/src/GameState.h +++ b/stepmania/src/GameState.h @@ -205,6 +205,11 @@ public: float m_fLastHasteUpdateMusicSeconds; float m_fAccumulatedHasteSeconds; + // + // Random Attacks & Attack Mines + // + vector m_RandomAttacks; + // used in PLAY_MODE_BATTLE float m_fOpponentHealthPercent; diff --git a/stepmania/src/Player.cpp b/stepmania/src/Player.cpp index e9206ee734..80962fee30 100644 --- a/stepmania/src/Player.cpp +++ b/stepmania/src/Player.cpp @@ -380,6 +380,8 @@ void Player::Init( m_vbFretIsDown.resize( GAMESTATE->GetCurrentStyle()->m_iColsPerPlayer ); FOREACH( bool, m_vbFretIsDown, b ) *b = false; + + m_fActiveRandomAttackStart = -1.0f; } static bool NeedsTapJudging( const TapNote &tn ) @@ -596,6 +598,34 @@ void Player::Update( float fDeltaTime ) // if the Player doesn't show anything on the screen. if( HasVisibleParts() ) { + // + // Random Attack Mod + // + if( m_pPlayerState->m_PlayerOptions.GetCurrent().m_fRandAttack ) + { + float fCurrentGameTime = STATSMAN->m_CurStageStats.m_fGameplaySeconds; + + // Should we hardcode this, or make it a preference/theme metric? ~ Mike + const float fAttackRunTime = 6.0f; + + // Don't start until 1 seconds into game, minimum + if( fCurrentGameTime > 1.0f ) + { + /* Update the attack if there are no others currently running. + * Note that we have a new one activate a little early; this is to have a bit + * of overlap rather than an abrupt change */ + if( (fCurrentGameTime - m_fActiveRandomAttackStart) > (fAttackRunTime - 0.5f) ) + { + m_fActiveRandomAttackStart = fCurrentGameTime; + + Attack attRandomAttack; + attRandomAttack.sModifiers = ApplyRandomAttack(); + attRandomAttack.fSecsRemaining = fAttackRunTime; + m_pPlayerState->LaunchAttack( attRandomAttack); + } + } + } + if( g_bEnableAttackSoundPlayback ) { if( m_pPlayerState->m_bAttackBeganThisUpdate ) @@ -2807,6 +2837,15 @@ void Player::SetCombo( int iCombo, int iMisses ) this->HandleMessage( msg ); } +RString Player::ApplyRandomAttack() +{ + if( GAMESTATE->m_RandomAttacks.size() < 1 ) + return ""; + + int iAttackToUse = rand() % GAMESTATE->m_RandomAttacks.size(); + return GAMESTATE->m_RandomAttacks[iAttackToUse]; +} + // lua start #include "LuaBinding.h" diff --git a/stepmania/src/Player.h b/stepmania/src/Player.h index 5a93516bc5..a38ac1fe88 100644 --- a/stepmania/src/Player.h +++ b/stepmania/src/Player.h @@ -130,6 +130,8 @@ protected: int GetClosestNonEmptyRowDirectional( int iStartRow, int iMaxRowsAhead, bool bAllowGraded, bool bForward ) const; int GetClosestNonEmptyRow( int iNoteRow, int iMaxRowsAhead, int iMaxRowsBehind, bool bAllowGraded ) const; + RString ApplyRandomAttack(); + inline void HideNote( int col, int row ) { NoteData::iterator iter = m_NoteData.FindTapNote( col, row ); @@ -179,6 +181,8 @@ protected: RageSound m_soundAttackLaunch; RageSound m_soundAttackEnding; + float m_fActiveRandomAttackStart; + vector m_vbFretIsDown; vector m_vKeysounds; diff --git a/stepmania/src/PlayerOptions.cpp b/stepmania/src/PlayerOptions.cpp index 4bcee642fb..7e92400ca5 100644 --- a/stepmania/src/PlayerOptions.cpp +++ b/stepmania/src/PlayerOptions.cpp @@ -27,6 +27,7 @@ void PlayerOptions::Init() 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; m_bSetTiltOrSkew = false; m_fPerspectiveTilt = 0; m_SpeedfPerspectiveTilt = 1.0f; m_fSkew = 0; m_SpeedfSkew = 1.0f; @@ -61,6 +62,7 @@ void PlayerOptions::Approach( const PlayerOptions& other, float fDeltaSeconds ) APPROACH( fDark ); APPROACH( fBlind ); APPROACH( fCover ); + APPROACH( fRandAttack ); APPROACH( fPerspectiveTilt ); APPROACH( fSkew ); APPROACH( fPassmark ); @@ -163,6 +165,8 @@ void PlayerOptions::GetMods( vector &AddTo, bool bForceNoteSkin ) const AddPart( AddTo, m_fBlind, "Blind" ); AddPart( AddTo, m_fCover, "Cover" ); + AddPart( AddTo, m_fRandAttack, "RandomAttacks" ); + AddPart( AddTo, m_fPassmark, "Passmark" ); AddPart( AddTo, m_fRandomSpeed, "RandomSpeed" ); @@ -373,6 +377,7 @@ bool PlayerOptions::FromOneModString( const RString &sOneMod, RString &sErrorOut 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 ) else if( sBit == "passmark" ) SET_FLOAT( fPassmark ) else if( sBit == "overhead" ) { m_bSetTiltOrSkew = true; m_fSkew = 0; m_fPerspectiveTilt = 0; m_SpeedfSkew = m_SpeedfPerspectiveTilt = speed; } else if( sBit == "incoming" ) { m_bSetTiltOrSkew = true; m_fSkew = level; m_fPerspectiveTilt = -level; m_SpeedfSkew = m_SpeedfPerspectiveTilt = speed; } @@ -611,6 +616,7 @@ bool PlayerOptions::operator==( const PlayerOptions &other ) const COMPARE(m_fDark); COMPARE(m_fBlind); COMPARE(m_fCover); + COMPARE(m_fRandAttack); COMPARE(m_fPerspectiveTilt); COMPARE(m_fSkew); COMPARE(m_sNoteSkin); diff --git a/stepmania/src/PlayerOptions.h b/stepmania/src/PlayerOptions.h index c7c5e21f16..05b2c45641 100644 --- a/stepmania/src/PlayerOptions.h +++ b/stepmania/src/PlayerOptions.h @@ -125,6 +125,7 @@ public: float m_fDark, m_SpeedfDark; float m_fBlind, m_SpeedfBlind; float m_fCover, m_SpeedfCover; // hide the background per-player--can't think of a good name + float m_fRandAttack, m_SpeedfRandAttack; bool m_bSetTiltOrSkew; // true if the tilt or skew was set by FromString float m_fPerspectiveTilt, m_SpeedfPerspectiveTilt; // -1 = near, 0 = overhead, +1 = space float m_fSkew, m_SpeedfSkew; // 0 = vanish point is in center of player, 1 = vanish point is in center of screen diff --git a/stepmania/src/SongManager.cpp b/stepmania/src/SongManager.cpp index f46ae87151..90c42ee035 100644 --- a/stepmania/src/SongManager.cpp +++ b/stepmania/src/SongManager.cpp @@ -44,6 +44,8 @@ const RString COURSES_DIR = "/Courses/"; const RString ADDITIONAL_COURSES_DIR = "/AdditionalCourses/"; const RString EDIT_SUBDIR = "Edits/"; +const RString ATTACK_FILE = "/Data/RandomAttacks.txt"; + static const ThemeMetric EXTRA_COLOR ( "SongManager", "ExtraColor" ); static const ThemeMetric EXTRA_COLOR_METER ( "SongManager", "ExtraColorMeter" ); static const ThemeMetric USE_PREFERRED_SORT_COLOR ( "SongManager", "UsePreferredSortColor" ); @@ -92,6 +94,7 @@ void SongManager::InitAll( LoadingWindow *ld ) InitSongsFromDisk( ld ); InitCoursesFromDisk( ld ); InitAutogenCourses(); + InitRandomAttacks(); } static LocalizedString RELOADING ( "SongManager", "Reloading..." ); @@ -798,6 +801,56 @@ void SongManager::InitAutogenCourses() } } +void SongManager::InitRandomAttacks() +{ + GAMESTATE->m_RandomAttacks.clear(); + + if( !IsAFile(ATTACK_FILE) ) + LOG->Trace( "File Data/RandomAttacks.txt was not found" ); + else + { + MsdFile msd; + + if( !msd.ReadFile( ATTACK_FILE, true ) ) + LOG->Warn( "Error opening file '%s' for reading: %s.", ATTACK_FILE, msd.GetError().c_str() ); + else + { + for( unsigned i=0; i 2 ) + { + LOG->Warn( "Got \"%s:%s\" tag with too many parameters", sType.c_str(), sAttack.c_str() ); + continue; + } + + if( stricmp(sType,"ATTACK") != 0 ) + { + LOG->Warn( "Got \"%s:%s\" tag with wrong declaration", sType.c_str(), sAttack.c_str() ); + continue; + } + + // Check to make sure only one attack has been specified + // TODO: Allow combinations of mods + vector sAttackCheck; + split( sAttack, ",", sAttackCheck, false ); + + if( sAttackCheck.size() > 1 ) + { + LOG->Warn( "Attack \"%s\" has more than one modifier; must only be one modifier specified", sAttack.c_str() ); + continue; + } + + GAMESTATE->m_RandomAttacks.push_back( sAttack ); + } + } + } +} + void SongManager::FreeCourses() { for( unsigned i=0; i