diff --git a/stepmania/src/ConditionalBGA.cpp b/stepmania/src/ConditionalBGA.cpp new file mode 100644 index 0000000000..4734c756c4 --- /dev/null +++ b/stepmania/src/ConditionalBGA.cpp @@ -0,0 +1,645 @@ +#include "global.h" +#include + +#include "GameState.h" +#include "GameManager.h" +#include "Song.h" +#include "GameConstantsAndTypes.h" +#include "RageLog.h" +#include "BGAnimation.h" +#include "ConditionalBGA.h" +#include "ThemeManager.h" +#include "RageUtil.h" +#include "RageFile.h" +#include "StageStats.h" +#include "Steps.h" + +ConditionalBGA::ConditionalBGA() +{ + +} + +ConditionalBGA::~ConditionalBGA() +{ + +} + +void ConditionalBGA::Load(CString szScreenName) +{ + RageFile file; + + CString szThemeDir = THEME->GetCurThemeDir(); + CString szConditionalBGAFile = szThemeDir += szScreenName += " ConditionalBGA.ini"; + + +// char filepath[512]; +// strcpy(filepath,""); // empty the path first +// strcpy(filepath,szConditionalBGAFile.c_str()); + + LOG->Trace("ConditionalBGA Load:%s",szConditionalBGAFile.c_str()); + + bool loaded = file.Open(szConditionalBGAFile,RageFile::READ); +// FILE* fp = NULL; +// fp = fopen(filepath,"r"); + if(!loaded) + { + LOG->Warn("ConditionalBGA File Not Found"); + return; + } + else + { + CString currentline; + int bgano=0; + + while(!file.AtEOF()) + { + file.GetLine(currentline); // get the current line + + // kill any possible comments + CStringArray asKillComments; + asKillComments.clear(); // get rid of anything in there + split(currentline, "#",asKillComments); // A comment starting with # + if(!asKillComments.empty()) + { + currentline = asKillComments[0]; // there was some commentstuff here, take the first bit to be the actual data + } + asKillComments.clear(); // get rid of anything in there + split(currentline, "/",asKillComments); // A comment starting with // or /* + if(!asKillComments.empty()) + { + currentline = asKillComments[0]; // there was some commentstuff here, take the first bit to be the actual data + } + TrimRight(currentline); // nuke trailing whitespace + + // start parsing the data + if(currentline.c_str()[0] == '[') // we found a new bganimation + { + if(!m_bgainfo.empty()) // last one wasnt empty + { + CheckBgaRequirements(m_bgainfo[bgano]); + bgano++; + } + BgaCondInfo temp; + m_bgainfo.push_back(temp); + ClearINFO(bgano); // wipe out the old info structure. + + CStringArray asSplitLine; + split(currentline,"[",asSplitLine); + split(asSplitLine[0],"]",asSplitLine); + if(!asSplitLine.empty() && asSplitLine.size() - 1 >= 0) + m_bgainfo[bgano].bganame = asSplitLine[asSplitLine.size() - 1]; + } + else + { + CStringArray asSplitLine; + split(currentline,":",asSplitLine); + if(asSplitLine.empty()) continue; + + if(!asSplitLine[0].CompareNoCase("clear") && asSplitLine.size() > 1) + { + if(!asSplitLine[1].CompareNoCase("true") || !asSplitLine[1].CompareNoCase("cleared") || !asSplitLine[1].CompareNoCase("clear")) // true / clear (any clear condition) + m_bgainfo[bgano].cleared = CBGA_CSCLEARED; + else if(!asSplitLine[1].CompareNoCase("false") || !asSplitLine[1].CompareNoCase("failed")) // false / failed + m_bgainfo[bgano].cleared = CBGA_CSFAILED; + else if(!asSplitLine[1].CompareNoCase("maxcombo") || !asSplitLine[1].CompareNoCase("fullcombo")) // passed with maxcombo + m_bgainfo[bgano].cleared = CBGA_CSMAXCOMBO; + else if(!asSplitLine[1].CompareNoCase("brokencombo")) // passed with a broken combo + m_bgainfo[bgano].cleared = CBGA_CSBROKECOMBO; + + // LOG->Trace("Clear Conditon: %d",info.cleared); + } + if(!asSplitLine[0].CompareNoCase("songtitle") && asSplitLine.size() > 1) + { + m_bgainfo[bgano].songtitle = asSplitLine[1]; + // LOG->Trace("SongTitle: %s",info.songtitle.c_str()); + } + if(!asSplitLine[0].CompareNoCase("songartist") && asSplitLine.size() > 1) + { + m_bgainfo[bgano].songartist = asSplitLine[1]; + // LOG->Trace("SongArtist: %s",info.songartist.c_str()); + } + if(!asSplitLine[0].CompareNoCase("songday") && asSplitLine.size() > 1) + { + CStringArray asDays; + split( asSplitLine[1], ",", asDays ); + for( unsigned d=0; d 32)) // ignore if date is out of range + { + m_bgainfo[bgano].songdays.push_back(dn); + } + } + // for(d=0; dTrace("SongDay: %d",info.songdays[d]); + // } + } + if(!asSplitLine[0].CompareNoCase("songmonth") && asSplitLine.size() > 1) + { + CStringArray asMonths; + split( asSplitLine[1], ",", asMonths ); + for( unsigned d=0; d 12)) // ignore if date is out of range + { + m_bgainfo[bgano].songmonths.push_back(dn); + } + } + // for(d=0; dTrace("SongMonth: %d",info.songmonths[d]); + // } + } + + // foot meter ratings + if(!asSplitLine[0].CompareNoCase("songdifficulty") && asSplitLine.size() > 1) + { + CStringArray asDifficulties; + split( asSplitLine[1], ",", asDifficulties ); + + for(unsigned d=0;d 1) + { + m_bgainfo[bgano].dpoused = true; + m_bgainfo[bgano].disallowedpo.FromString(asSplitLine[1]); + + } + + // heavy, light e.t.c. + if(!asSplitLine[0].CompareNoCase("songrating") && asSplitLine.size() > 1) + { + CStringArray asDifficulties; + split( asSplitLine[1], ",", asDifficulties ); + for( unsigned d=0; dTrace("Difficulty: %d",info.difficulties[d]); + // } + } + if(!asSplitLine[0].CompareNoCase("grade") && asSplitLine.size() > 1) + { + CStringArray asGrades; + split( asSplitLine[1], ",", asGrades ); + for( unsigned d=0; d 1) + { + LOG->Info("Comparing Styles"); + CStringArray asStyles; + split( asSplitLine[1], ",", asStyles ); + for( unsigned d=0; dInfo("Style:%s (%d) (current: %d)",asStyles[d].c_str(),GAMEMAN->GameAndStringToStyle(GAMESTATE->m_CurGame,asStyles[d]),GAMESTATE->m_CurStyle); + + m_bgainfo[bgano].styles.push_back(GAMEMAN->GameAndStringToStyle(GAMESTATE->m_CurGame,asStyles[d])); + } + + } + + + } + + } + if(bganimtouse.CompareNoCase("")!=0) + { + LOG->Info("Best Match BGA Was: %s",bganimtouse.c_str()); + bganim.LoadFromAniDir( THEME->GetPathToB(bganimtouse) ); + } + + } + file.Close(); +} + +void ConditionalBGA::Update( float fDeltaTime ) +{ + bganim.Update(fDeltaTime); +} + +void ConditionalBGA::DrawPrimitives() +{ + bganim.Draw(); +} + +void ConditionalBGA::ClearINFO(int iEntry) +{ + m_bgainfo[iEntry].bganame = ""; + m_bgainfo[iEntry].songtitle = ""; + m_bgainfo[iEntry].songartist = ""; + m_bgainfo[iEntry].songdays.clear(); + m_bgainfo[iEntry].songdows.clear(); + m_bgainfo[iEntry].songmeters.clear(); + m_bgainfo[iEntry].difficulties.clear(); + m_bgainfo[iEntry].songmonths.clear(); + m_bgainfo[iEntry].styles.clear(); + m_bgainfo[iEntry].cleared = CBGA_CSUNUSED; + m_bgainfo[iEntry].dpoused = false; +} + +void ConditionalBGA::CheckBgaRequirements(BgaCondInfo info) +{ + LOG->Trace("Checking Conditions For BGA: %s",info.bganame.c_str()); + + +/* + for(unsigned d=0; dTrace("Difficulty: %d",info.difficulties[d]); + } + for(d=0; dTrace("SongMonth: %d",info.songmonths[d]); + } + for(d=0; dTrace("SongDay: %d",info.songdays[d]); + } + + LOG->Trace("Clear Conditon: %d",info.cleared); + LOG->Trace("SongTitle: %s",info.songtitle.c_str()); + LOG->Trace("SongArtist: %s",info.songartist.c_str()); + +*/ + bool valid = true; // valid until proven otherwise. + bool hasconditions = false; // if there is a bga with no conditions for display + // then we dont want it to appear + + if(info.songtitle.CompareNoCase("")!=0) // not equal + { + // LOG->Info("COMP: %s",info.songtitle.c_str()); + + hasconditions = true; + if(GAMESTATE->m_pCurSong != NULL) + { + if(!GAMESTATE->m_pCurSong->m_sMainTitle.CompareNoCase(info.songtitle)) + { + LOG->Info("SongTitle Matches"); + // valid + } + else + valid = false; // different song + } + else // song not being played at the time + { + valid = false; + } + } + + if(info.songartist.CompareNoCase("")!=0 && valid) // not equal + { + // LOG->Info("COMP: %s",info.songtitle.c_str()); + + hasconditions = true; + if(GAMESTATE->m_pCurSong != NULL) + { + if(!GAMESTATE->m_pCurSong->m_sArtist.CompareNoCase(info.songartist)) + { + LOG->Info("SongArtist Matches"); + // valid + } + else + valid = false; // different song + } + else // song not being played at the time + { + valid = false; + } + } + + + if(!info.difficulties.empty() && valid) // dont bother checking any more if its already been invalidated. + { + // LOG->Info("Checking Difficulties"); + hasconditions = true; + bool foundmatchingdiff=false; + for(unsigned d=0;dIsPlayerEnabled(pn)) + { + if(GAMESTATE->m_pCurNotes[pn] != NULL) + { + if(GAMESTATE->m_pCurNotes[pn]->GetDifficulty() == info.difficulties[d]) + { + foundmatchingdiff = true; + LOG->Info("Found Valid Difficulty"); + + } + } + } + } + } + valid = foundmatchingdiff; + } + + if(info.dpoused) + { + PlayerOptions po = info.disallowedpo; + bool bModsValid = true; + for(unsigned pn=0;pnIsPlayerEnabled(pn)) + { + for(unsigned md=0;mdm_PlayerOptions[pn].m_fAccels[md] != 0.0f) + { + bModsValid=false; + LOG->Info("Found Invalid Accel Mod"); + } + } + for(md=0;mdm_PlayerOptions[pn].m_fEffects[md] != 0.0f) + { + bModsValid=false; + LOG->Info("Found Invalid Effect Mod"); + } + } + for(md=0;mdm_PlayerOptions[pn].m_fAppearances[md] != 0.0f) + { + bModsValid=false; + LOG->Info("Found Invalid Appearance Mod"); + } + } + if((po.m_Turn != PlayerOptions::TURN_NONE) && (po.m_Turn == GAMESTATE->m_PlayerOptions[pn].m_Turn)) + { + bModsValid=false; + LOG->Info("Found Invalid Turn Mod"); + } + for(md=0;mdm_PlayerOptions[pn].m_bTransforms[md] != 0.0f) + { + bModsValid=false; + LOG->Info("Found Invalid Transform Mod"); + } + } + + + } + } + valid = bModsValid; + } + + if(!info.songmeters.empty() && valid) // dont bother checking any more if its already been invalidated. + { + hasconditions = true; + bool foundmatchingmeter=false; + for(unsigned d=0;dInfo("MeterRating: %d",info.songmeters[d]); + for(int pn=0;pnIsPlayerEnabled(pn)) + { + if(GAMESTATE->m_pCurNotes[pn] != NULL) + { + if(info.songmeters[d] < 0) // negative values stored mean we want to check a value greaterthan or equal to its negative + { + // first make it positive then check to see if the footrating is >= to it + int tmp = 0 - info.songmeters[d]; + if(GAMESTATE->m_pCurNotes[pn]->GetMeter() >= tmp) + { + LOG->Info("Found Valid MeterRating"); + foundmatchingmeter = true; + } + } + else if(GAMESTATE->m_pCurNotes[pn]->GetMeter() == info.songmeters[d]) + { + LOG->Info("Found Valid MeterRating"); + foundmatchingmeter = true; + } + } + } + } + } + valid = foundmatchingmeter; + } + + + if(!info.styles.empty() && valid) + { + hasconditions = true; + bool foundmatchingstyle=false; + for(unsigned d=0;dInfo("info.styles = %d m_CurStyle = %d",info.styles[d],GAMESTATE->m_CurStyle); + if(info.styles[d] == GAMESTATE->m_CurStyle) + { + foundmatchingstyle = true; + LOG->Info("Found Valid Style"); + } + + } + valid = foundmatchingstyle; + } + + if(!info.grades.empty() && valid) // dont bother checking any more if its already been invalidated. + { + // LOG->Info("Checking Difficulties"); + hasconditions = true; + bool foundmatchinggrades=true; // assume true until proven otherwise + if(info.grades.size() == 1) // only looking for a single grade + { + LOG->Info("Checking Single Grade"); + bool foundaplayerwithgrade = false; + for(unsigned pn=0; pnIsPlayerEnabled(pn)) + { + if(g_CurStageStats.GetGrade((PlayerNumber)pn) == info.grades[0]) + { + LOG->Info("Found Valid Grade"); + foundaplayerwithgrade = true; + } + } + } + foundmatchinggrades = foundaplayerwithgrade; + } + else if(g_vPlayedStageStats.size() < info.grades.size()) // we've not played enough stages to achieve a grade history condition + { + LOG->Info("Not Enough Stages Played To Compare Grade History"); + foundmatchinggrades = false; + } + else // we have to check the history of grades to ensure they met the spec asked + { + LOG->Info("Checking Grade History"); + LOG->Info("Stage Stats Size: %d NumConditionalGrades: %d",g_vPlayedStageStats.size(),info.grades.size()); + bool foundavalidgradeforstage = false; + for(unsigned d=info.grades.size()-1,g=g_vPlayedStageStats.size()-1;d>0;d--,g--) + { + if(d>g) ASSERT(0); // this should never happen. + + for(unsigned pn=0; pnIsPlayerEnabled((PlayerNumber)pn)) + { + LOG->Info("Player%d Grade: %d :: Expected Grade: %d",pn,g_vPlayedStageStats[g].GetGrade((PlayerNumber)pn),info.grades[d]); + if(g_vPlayedStageStats[g].GetGrade((PlayerNumber)pn) == info.grades[d]) + { + LOG->Info("One Valid Grade"); + foundavalidgradeforstage = true; + } + } + } + } + foundmatchinggrades = foundavalidgradeforstage; + } + + valid = foundmatchinggrades; + } + + + if(!info.songmonths.empty() && valid) + { + time_t rawtime; + time(&rawtime); + struct tm* ptm = localtime(&rawtime); + int month = ptm->tm_mon; /* Month 0..11 */ + LOG->Info("Month: %d",month); + bool foundvalidmonth = false; + for(unsigned d=0;dInfo("Month: %d, THIS Month: %d",info.songmonths[d],month); + if(info.songmonths[d] == month) + { + foundvalidmonth = true; + LOG->Info("Found Valid Month"); + } + } + valid = foundvalidmonth; + } + + + if(!info.songdays.empty() && valid) + { + time_t rawtime; + time(&rawtime); + struct tm* ptm = localtime(&rawtime); + int day = ptm->tm_mday; /* day in the month */ + LOG->Info("DAy: %d",day); + bool foundvalidday = false; + for(unsigned d=0;dInfo("Day: %d, THIS Day: %d",info.songdays[d],day); + if(info.songdays[d] == day) + { + foundvalidday = true; + LOG->Info("Found Valid Day"); + } + } + valid = foundvalidday; + } + + + if(info.cleared != CBGA_CSUNUSED && valid) // already found invalid? forget it :> + { + bool foundclearcond = false; + if(info.cleared == CBGA_CSFAILED) + { + if(GAMESTATE->AllAreDead() || g_CurStageStats.AllFailed()) // they met the fail condition + { + LOG->Info("Failed Condition"); + foundclearcond = true; + } + } + else if(info.cleared == CBGA_CSCLEARED) + { + if(!g_CurStageStats.AllFailed() || !GAMESTATE->AllAreDead() ) // stage was cleared + { + LOG->Info("Cleared Condition"); + foundclearcond = true; + } + } + else if(info.cleared == CBGA_CSMAXCOMBO) + { + for(unsigned pn=0;pnIsPlayerEnabled(pn)) + if(g_CurStageStats.FullCombo((PlayerNumber)pn)) + { + foundclearcond = true; + LOG->Info("MaxCombo Condition"); + } + } + else if(info.cleared == CBGA_CSBROKECOMBO) + { + for(unsigned pn=0;pnIsPlayerEnabled(pn)) + if(!g_CurStageStats.FullCombo((PlayerNumber)pn)) + { + LOG->Info("BrokenCombo Condition"); + foundclearcond = true; + } + } + + valid = foundclearcond; + } + + if(valid && hasconditions) + { + LOG->Info("Valid"); + bganimtouse = info.bganame; + } +} \ No newline at end of file diff --git a/stepmania/src/ConditionalBGA.h b/stepmania/src/ConditionalBGA.h new file mode 100644 index 0000000000..27389be6ed --- /dev/null +++ b/stepmania/src/ConditionalBGA.h @@ -0,0 +1,56 @@ +#ifndef CONDITIONALBGA_H +#define CONDITIONALBGA_H + +#include "Style.h" +#include "PlayerOptions.h" +//#include "StyleDef.h" + +enum CBGACLEAREDSTATES +{ + CBGA_CSUNUSED = 0, // unused is if the condition doesnt matter + CBGA_CSCLEARED, // if the player must have cleared the stage + CBGA_CSFAILED, // if the player must have failed the stage + CBGA_CSMAXCOMBO, // if the player cleared the song with full combo + CBGA_CSBROKECOMBO // if the player cleared the song with a broken combo +}; + +struct BgaCondInfo +{ +// char bganame[512]; + CString bganame; +// char songtitle[512]; + CString songtitle; +// char songartist[512]; + CString songartist; + int cleared; + vector difficulties; // heavy, light e.t.c. + vector songmeters; // footmeter + vector songdays; + vector songdows; + vector songmonths; + vector grades; + vector