bool KSFLoader::LoadNoteDataFromSimfile( const std::string & cachePath, Steps &out ) { bool KIUCompliant = false; Song dummy; if (!LoadGlobalData(cachePath, dummy, KIUCompliant)) return false; Steps *notes = dummy.CreateSteps(); if (LoadFromKSFFile(cachePath, *notes, dummy, KIUCompliant)) { KIUCompliant = true; // yeah, reusing a variable. out.SetNoteData(notes->GetNoteData()); } delete notes; return KIUCompliant; }
void ScoreKeeperNormal::Load( const vector<Song*>& apSongs, const vector<Steps*>& apSteps, const vector<AttackArray> &asModifiers ) { m_apSteps = apSteps; ASSERT( apSongs.size() == apSteps.size() ); ASSERT( apSongs.size() == asModifiers.size() ); // True if a jump is one to combo, false if combo is purely based on tap count. m_ComboIsPerRow.Load( "Gameplay", "ComboIsPerRow" ); m_MissComboIsPerRow.Load( "Gameplay", "MissComboIsPerRow" ); m_MinScoreToContinueCombo.Load( "Gameplay", "MinScoreToContinueCombo" ); m_MinScoreToMaintainCombo.Load( "Gameplay", "MinScoreToMaintainCombo" ); m_MaxScoreToIncrementMissCombo.Load( "Gameplay", "MaxScoreToIncrementMissCombo" ); m_MineHitIncrementsMissCombo.Load( "Gameplay", "MineHitIncrementsMissCombo" ); m_AvoidMineIncrementsCombo.Load( "Gameplay", "AvoidMineIncrementsCombo" ); m_UseInternalScoring.Load( "Gameplay", "UseInternalScoring" ); // This can be a function or a number, the type is checked when needed. // -Kyz m_toasty_trigger.Load("Gameplay", "ToastyTriggersAt"); m_toasty_min_tns.Load("Gameplay", "ToastyMinTNS"); // Fill in STATSMAN->m_CurStageStats, calculate multiplier int iTotalPossibleDancePoints = 0; int iTotalPossibleGradePoints = 0; for( unsigned i=0; i<apSteps.size(); i++ ) { Song* pSong = apSongs[i]; ASSERT( pSong != NULL ); Steps* pSteps = apSteps[i]; ASSERT( pSteps != NULL ); const AttackArray &aa = asModifiers[i]; NoteData ndTemp; pSteps->GetNoteData( ndTemp ); // We might have been given lots of songs; don't keep them in memory uncompressed. pSteps->Compress(); const Style* pStyle = GAMESTATE->GetCurrentStyle(m_pPlayerState->m_PlayerNumber); NoteData ndPre; pStyle->GetTransformedNoteDataForStyle( m_pPlayerState->m_PlayerNumber, ndTemp, ndPre ); /* Compute RadarValues before applying any user-selected mods. Apply * Course mods and count them in the "pre" RadarValues because they're * forced and not chosen by the user. */ NoteDataUtil::TransformNoteData(ndPre, *(pSteps->GetTimingData()), aa, pSteps->m_StepsType, pSong ); /* Apply user transforms to find out how the notes will really look. * * XXX: This is brittle: if we end up combining mods for a song differently * than ScreenGameplay, we'll end up with the wrong data. We should probably * have eg. GAMESTATE->GetOptionsForCourse(po,so,pn) to get options based on * the last call to StoreSelectedOptions and the modifiers list, but that'd * mean moving the queues in ScreenGameplay to GameState ... */ NoteData ndPost = ndPre; NoteDataUtil::TransformNoteData(ndPost, *(pSteps->GetTimingData()), m_pPlayerState->m_PlayerOptions.GetStage(), pSteps->m_StepsType); GAMESTATE->SetProcessedTimingData(pSteps->GetTimingData()); // XXX: Not sure why but NoteDataUtil::CalculateRadarValues segfaults without this iTotalPossibleDancePoints += this->GetPossibleDancePoints( &ndPre, &ndPost, pSteps->GetTimingData(), pSong->m_fMusicLengthSeconds ); iTotalPossibleGradePoints += this->GetPossibleGradePoints( &ndPre, &ndPost, pSteps->GetTimingData(), pSong->m_fMusicLengthSeconds ); GAMESTATE->SetProcessedTimingData(NULL); } m_pPlayerStageStats->m_iPossibleDancePoints = iTotalPossibleDancePoints; m_pPlayerStageStats->m_iPossibleGradePoints = iTotalPossibleGradePoints; m_iScoreRemainder = 0; m_cur_toasty_combo = 0; m_cur_toasty_level= 0; // Initialize m_next_toasty_at to 0 so that CalcNextToastyAt just needs to // add the value. -Kyz m_next_toasty_at= 0; m_next_toasty_at= CalcNextToastyAt(m_cur_toasty_level); m_iMaxScoreSoFar = 0; m_iPointBonus = 0; m_iNumTapsAndHolds = 0; m_iNumNotesHitThisRow = 0; m_bIsLastSongInCourse = false; Message msg( "ScoreChanged" ); msg.SetParam( "PlayerNumber", m_pPlayerState->m_PlayerNumber ); msg.SetParam( "MultiPlayer", m_pPlayerState->m_mp ); MESSAGEMAN->Broadcast( msg ); memset( m_ComboBonusFactor, 0, sizeof(m_ComboBonusFactor) ); m_iRoundTo = 1; }
static void WriteDWINotesField( RageFile &f, const Steps &out, int start ) { NoteData notedata; out.GetNoteData( notedata ); NoteDataUtil::InsertHoldTails( notedata ); const int iLastMeasure = int( notedata.GetLastBeat()/BEATS_PER_MEASURE ); for( int m=0; m<=iLastMeasure; m++ ) // foreach measure { NoteType nt = NoteDataUtil::GetSmallestNoteTypeForMeasure( notedata, m ); double fCurrentIncrementer = 0; switch( nt ) { case NOTE_TYPE_4TH: case NOTE_TYPE_8TH: fCurrentIncrementer = 1.0/8 * BEATS_PER_MEASURE; break; case NOTE_TYPE_12TH: case NOTE_TYPE_24TH: f.Write( "[" ); fCurrentIncrementer = 1.0/24 * BEATS_PER_MEASURE; break; case NOTE_TYPE_16TH: f.Write( "(" ); fCurrentIncrementer = 1.0/16 * BEATS_PER_MEASURE; break; case NOTE_TYPE_32ND: case NOTE_TYPE_64TH: f.Write( "{" ); fCurrentIncrementer = 1.0/64 * BEATS_PER_MEASURE; break; case NOTE_TYPE_48TH: case NOTE_TYPE_192ND: case NoteType_Invalid: // since, for whatever reason, the only way to do // 48ths is through a block of 192nds... f.Write( "`" ); fCurrentIncrementer = 1.0/192 * BEATS_PER_MEASURE; break; default: ASSERT_M(0, ssprintf("nt = %d",nt) ); break; } double fFirstBeatInMeasure = m * BEATS_PER_MEASURE; double fLastBeatInMeasure = (m+1) * BEATS_PER_MEASURE; for( double b=fFirstBeatInMeasure; b<=fLastBeatInMeasure-1/64.0f; b+=fCurrentIncrementer ) // need the -0.0001 to account for rounding errors { int row = BeatToNoteRow( (float)b ); RString str; switch( out.m_StepsType ) { case StepsType_dance_single: case StepsType_dance_couple: case StepsType_dance_double: str = NotesToDWIString( notedata.GetTapNote(start+0, row), notedata.GetTapNote(start+1, row), notedata.GetTapNote(start+2, row), notedata.GetTapNote(start+3, row) ); // Blank out the notes so we don't write them again if the incrementer is small notedata.SetTapNote(start+0, row, TAP_EMPTY); notedata.SetTapNote(start+1, row, TAP_EMPTY); notedata.SetTapNote(start+2, row, TAP_EMPTY); notedata.SetTapNote(start+3, row, TAP_EMPTY); break; case StepsType_dance_solo: str = NotesToDWIString( notedata.GetTapNote(0, row), notedata.GetTapNote(1, row), notedata.GetTapNote(2, row), notedata.GetTapNote(3, row), notedata.GetTapNote(4, row), notedata.GetTapNote(5, row) ); // Blank out the notes so we don't write them again if the incrementer is small notedata.SetTapNote(start+0, row, TAP_EMPTY); notedata.SetTapNote(start+1, row, TAP_EMPTY); notedata.SetTapNote(start+2, row, TAP_EMPTY); notedata.SetTapNote(start+3, row, TAP_EMPTY); notedata.SetTapNote(start+4, row, TAP_EMPTY); notedata.SetTapNote(start+5, row, TAP_EMPTY); break; default: ASSERT(0); // not a type supported by DWI. We shouldn't have called in here if that's the case } f.Write( str ); } switch( nt ) { case NOTE_TYPE_4TH: case NOTE_TYPE_8TH: break; case NOTE_TYPE_12TH: case NOTE_TYPE_24TH: f.Write( "]" ); break; case NOTE_TYPE_16TH: f.Write( ")" ); break; case NOTE_TYPE_32ND: case NOTE_TYPE_64TH: f.Write( "}" ); break; case NOTE_TYPE_48TH: case NOTE_TYPE_192ND: case NoteType_Invalid: f.Write( "'" ); break; default: ASSERT(0); // fall though } f.PutLine( "" ); } }
void ScoreKeeperMAX2::Load( const vector<Song*>& apSongs, const vector<Steps*>& apSteps, const vector<AttackArray> &asModifiers ) { m_apSteps = apSteps; ASSERT( apSongs.size() == apSteps.size() ); ASSERT( apSongs.size() == asModifiers.size() ); /* True if a jump is one to combo, false if combo is purely based on tap count. */ m_bComboIsPerRow = THEME->GetMetricB( "Gameplay", "ComboIsPerRow" ); m_MinScoreToContinueCombo = (TapNoteScore) THEME->GetMetricI( "Gameplay", "MinScoreToContinueCombo" ); m_MinScoreToMaintainCombo = (TapNoteScore) THEME->GetMetricI( "Gameplay", "MinScoreToMaintainCombo" ); // // Fill in STATSMAN->m_CurStageStats, calculate multiplier // int iTotalPossibleDancePoints = 0; int iTotalPossibleGradePoints = 0; for( unsigned i=0; i<apSteps.size(); i++ ) { Song* pSong = apSongs[i]; ASSERT( pSong ); Steps* pSteps = apSteps[i]; ASSERT( pSteps ); const AttackArray &aa = asModifiers[i]; NoteData ndTemp; pSteps->GetNoteData( ndTemp ); /* We might have been given lots of songs; don't keep them in memory uncompressed. */ pSteps->Compress(); const Style* pStyle = GAMESTATE->GetCurrentStyle(); NoteData nd; pStyle->GetTransformedNoteDataForStyle( m_pPlayerState->m_PlayerNumber, ndTemp, nd ); /* Compute RadarValues before applying any user-selected mods. Apply * Course mods and count them in the "pre" RadarValues because they're * forced and not chosen by the user. */ NoteDataUtil::TransformNoteData( nd, aa, pSteps->m_StepsType, pSong ); RadarValues rvPre; NoteDataUtil::CalculateRadarValues( nd, pSong->m_fMusicLengthSeconds, rvPre ); /* Apply user transforms to find out how the notes will really look. * * XXX: This is brittle: if we end up combining mods for a song differently * than ScreenGameplay, we'll end up with the wrong data. We should probably * have eg. GAMESTATE->GetOptionsForCourse(po,so,pn) to get options based on * the last call to StoreSelectedOptions and the modifiers list, but that'd * mean moving the queues in ScreenGameplay to GameState ... */ NoteDataUtil::TransformNoteData( nd, m_pPlayerState->m_PlayerOptions, pSteps->m_StepsType ); RadarValues rvPost; NoteDataUtil::CalculateRadarValues( nd, pSong->m_fMusicLengthSeconds, rvPost ); iTotalPossibleDancePoints += this->GetPossibleDancePoints( rvPre, rvPost ); iTotalPossibleGradePoints += this->GetPossibleGradePoints( rvPre, rvPost ); } m_pPlayerStageStats->iPossibleDancePoints = iTotalPossibleDancePoints; m_pPlayerStageStats->iPossibleGradePoints = iTotalPossibleGradePoints; m_iScoreRemainder = 0; m_iCurToastyCombo = 0; m_iMaxScoreSoFar = 0; m_iPointBonus = 0; m_iNumTapsAndHolds = 0; m_bIsLastSongInCourse = false; memset( m_ComboBonusFactor, 0, sizeof(m_ComboBonusFactor) ); switch( PREFSMAN->m_ScoringType ) { case PrefsManager::SCORING_MAX2: m_iRoundTo = 1; break; case PrefsManager::SCORING_5TH: m_iRoundTo = 5; if (!GAMESTATE->IsCourseMode()) { m_ComboBonusFactor[TNS_MARVELOUS] = 55; m_ComboBonusFactor[TNS_PERFECT] = 55; m_ComboBonusFactor[TNS_GREAT] = 33; } break; default: ASSERT(0); } }
void ScreenHowToPlay::Init() { ScreenAttract::Init(); if( (bool)USE_PAD && DoesFileExist( GetAnimPath(ANIM_DANCE_PAD) ) ) { m_pmDancePad = new Model; m_pmDancePad->SetName( "Pad" ); m_pmDancePad->LoadMilkshapeAscii( GetAnimPath(ANIM_DANCE_PAD) ); m_pmDancePad->SetRotationX( 35 ); LOAD_ALL_COMMANDS_AND_SET_XY_AND_ON_COMMAND( m_pmDancePad ); } // Display random character vector<Character*> vpCharacters; CHARMAN->GetCharacters( vpCharacters ); if( (bool)USE_CHARACTER && vpCharacters.size() && HaveAllCharAnimations() ) { Character* rndchar = CHARMAN->GetRandomCharacter(); RString sModelPath = rndchar->GetModelPath(); if( sModelPath != "" ) { m_pmCharacter = new Model; m_pmCharacter->SetName( "Character" ); m_pmCharacter->LoadMilkshapeAscii( rndchar->GetModelPath() ); m_pmCharacter->LoadMilkshapeAsciiBones( "Step-LEFT", GetAnimPath( ANIM_LEFT ) ); m_pmCharacter->LoadMilkshapeAsciiBones( "Step-DOWN", GetAnimPath( ANIM_DOWN ) ); m_pmCharacter->LoadMilkshapeAsciiBones( "Step-UP", GetAnimPath( ANIM_UP ) ); m_pmCharacter->LoadMilkshapeAsciiBones( "Step-RIGHT", GetAnimPath( ANIM_RIGHT ) ); m_pmCharacter->LoadMilkshapeAsciiBones( "Step-JUMPLR", GetAnimPath( ANIM_JUMPLR ) ); RString sRestFile = rndchar->GetRestAnimationPath(); ASSERT( !sRestFile.empty() ); m_pmCharacter->LoadMilkshapeAsciiBones( "rest",rndchar->GetRestAnimationPath() ); m_pmCharacter->SetDefaultAnimation( "rest" ); m_pmCharacter->PlayAnimation( "rest" ); // Stay bouncing after a step has finished animating. m_pmCharacter->SetRotationX( 40 ); m_pmCharacter->SetCullMode( CULL_NONE ); // many of the models floating around have the vertex order flipped LOAD_ALL_COMMANDS_AND_SET_XY_AND_ON_COMMAND( m_pmCharacter ); } } GAMESTATE->SetCurrentStyle( GAMEMAN->GetHowToPlayStyleForGame(GAMESTATE->m_pCurGame) ); if( USE_PLAYER ) { m_pLifeMeterBar = new LifeMeterBar; m_pLifeMeterBar->SetName("LifeMeterBar"); m_pLifeMeterBar->Load( GAMESTATE->m_pPlayerState[PLAYER_1], &STATSMAN->m_CurStageStats.m_player[PLAYER_1] ); LOAD_ALL_COMMANDS_AND_SET_XY_AND_ON_COMMAND( m_pLifeMeterBar ); m_pLifeMeterBar->FillForHowToPlay( NUM_W2S, NUM_MISSES ); SMLoader::LoadFromSMFile( THEME->GetPathO(m_sName, "steps"), m_Song, false ); m_Song.AddAutoGenNotes(); const Style* pStyle = GAMESTATE->GetCurrentStyle(); Steps *pSteps = SongUtil::GetStepsByDescription( &m_Song, pStyle->m_StepsType, "" ); ASSERT_M( pSteps != NULL, ssprintf("%i", pStyle->m_StepsType) ); NoteData tempNoteData; pSteps->GetNoteData( tempNoteData ); pStyle->GetTransformedNoteDataForStyle( PLAYER_1, tempNoteData, m_NoteData ); GAMESTATE->m_pCurSong.Set( &m_Song ); GAMESTATE->m_bGameplayLeadIn.Set( false ); GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerController = PC_AUTOPLAY; m_Player->Init( "Player", GAMESTATE->m_pPlayerState[PLAYER_1], NULL, m_pLifeMeterBar, NULL, NULL, NULL, NULL, NULL, NULL ); m_Player.Load( m_NoteData ); m_Player->SetName( "Player" ); this->AddChild( m_Player ); LOAD_ALL_COMMANDS_AND_SET_XY_AND_ON_COMMAND( m_Player ); // Don't show judgement PO_GROUP_ASSIGN( GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions, ModsLevel_Stage, m_fBlind, 1.0f ); GAMESTATE->m_MasterPlayerNumber = PLAYER_1; GAMESTATE->m_bDemonstrationOrJukebox = true; } // deferred until after the player, so the notes go under it if( m_pLifeMeterBar ) this->AddChild( m_pLifeMeterBar ); if( m_pmDancePad ) this->AddChild( m_pmDancePad ); if( m_pmCharacter ) this->AddChild( m_pmCharacter ); m_fFakeSecondsIntoSong = 0; this->MoveToTail( &m_In ); this->MoveToTail( &m_Out ); }