#include "stdafx.h" /* ----------------------------------------------------------------------------- Class: Notes Desc: See header. Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved. Chris Danford ----------------------------------------------------------------------------- */ #include "Notes.h" #include "Song.h" #include "Notes.h" #include "IniFile.h" #include "math.h" // for fabs() #include "RageUtil.h" #include "RageLog.h" #include "NoteData.h" #include "GameInput.h" #include "RageException.h" #include "MsdFile.h" #include "GameManager.h" Notes::Notes() { /* FIXME: should we init this to NOTES_TYPE_INVALID? * I have a feeling that it's the right thing to do but that * it'd trip obscure asserts all over the place, so I'll wait * until after b6 to do this. -glenn */ m_NotesType = NOTES_TYPE_DANCE_SINGLE; m_DifficultyClass = CLASS_INVALID; m_iMeter = 0; ZeroMemory(m_fRadarValues, sizeof(m_fRadarValues)); m_iNumTimesPlayed = 0; m_iMaxCombo = 0; m_iTopScore = 0; m_TopGrade = GRADE_NO_DATA; } Notes::~Notes() { } void Notes::WriteSMNotesTag( FILE* fp ) { fprintf( fp, "\n//---------------%s - %s----------------\n", GameManager::NotesTypeToString(m_NotesType), m_sDescription ); fprintf( fp, "#NOTES:\n" ); fprintf( fp, " %s:\n", GameManager::NotesTypeToString(m_NotesType) ); fprintf( fp, " %s:\n", m_sDescription ); fprintf( fp, " %s:\n", DifficultyClassToString(m_DifficultyClass) ); fprintf( fp, " %d:\n", m_iMeter ); CStringArray asRadarValues; for( int r=0; rTrace( "Notes::WriteDWINotesTag" ); switch( m_NotesType ) { case NOTES_TYPE_DANCE_SINGLE: fprintf( fp, "#SINGLE:" ); break; case NOTES_TYPE_DANCE_COUPLE_1: fprintf( fp, "#COUPLE:" ); break; case NOTES_TYPE_DANCE_DOUBLE: fprintf( fp, "#DOUBLE:" ); break; case NOTES_TYPE_DANCE_SOLO: fprintf( fp, "#SOLO:" ); break; default: return; // not a type supported by DWI } switch( m_DifficultyClass ) { case CLASS_EASY: fprintf( fp, "BASIC:" ); break; case CLASS_MEDIUM: fprintf( fp, "ANOTHER:" ); break; case CLASS_HARD: fprintf( fp, "MANIAC:" ); break; default: ASSERT(0); return; } fprintf( fp, "%d:\n", m_iMeter ); NoteData notedata; this->GetNoteData( ¬edata ); notedata.ConvertHoldNotesTo2sAnd3s(); const int iNumPads = (m_NotesType==NOTES_TYPE_DANCE_COUPLE_1 || m_NotesType==NOTES_TYPE_DANCE_DOUBLE) ? 2 : 1; const int iLastMeasure = int( notedata.GetLastBeat()/BEATS_PER_MEASURE ); for( int pad=0; pad" ); break; } fprintf( fp, "\n" ); } } fprintf( fp, ";\n" ); } void Notes::SetNoteData( NoteData* pNewNoteData ) { ASSERT( pNewNoteData->m_iNumTracks == GameManager::NotesTypeToNumTracks(m_NotesType) ); m_sSMNoteData = pNewNoteData->GetSMNoteDataString(); } void Notes::GetNoteData( NoteData* pNoteDataOut ) const { pNoteDataOut->m_iNumTracks = GameManager::NotesTypeToNumTracks( m_NotesType ); pNoteDataOut->LoadFromSMNoteDataString( m_sSMNoteData ); } // Color is a function of DifficultyClass and Intended Style D3DXCOLOR Notes::GetColor() const { CString sDescription = m_sDescription; sDescription.MakeLower(); if( -1 != sDescription.Find("battle") ) return D3DXCOLOR(1,0.5f,0,1); // orange else if( -1 != m_sDescription.Find("couple") ) return D3DXCOLOR(0,0,1,1); // blue else return DifficultyClassToColor( m_DifficultyClass ); } void Notes::TidyUpData() { if( m_DifficultyClass == CLASS_INVALID ) m_DifficultyClass = DifficultyClassFromDescriptionAndMeter( m_sDescription, m_iMeter ); if( m_iMeter < 1 || m_iMeter > 10 ) { switch( m_DifficultyClass ) { case CLASS_EASY: m_iMeter = 3; break; case CLASS_MEDIUM: m_iMeter = 5; break; case CLASS_HARD: m_iMeter = 8; break; default: ASSERT(0); } } } DifficultyClass Notes::DifficultyClassFromDescriptionAndMeter( CString sDescription, int iMeter ) { sDescription.MakeLower(); const int DESCRIPTIONS_PER_CLASS = 4; const CString sDescriptionParts[NUM_DIFFICULTY_CLASSES][DESCRIPTIONS_PER_CLASS] = { { "easy", "basic", "light", "GARBAGE", // but don't worry - this will never match because the compare string is all lowercase }, { "medium", "another", "trick", "standard", }, { "hard", "ssr", "maniac", "heavy", }, }; for( int i=0; im_fRadarValues[r]; fScore2 += pNotes2->m_fRadarValues[r]; } if( fScore1 < fScore2 ) return -1; else if( fScore1 == fScore2 ) return 0; else return 1; } int CompareNotesPointersByMeter(const void *arg1, const void *arg2) { Notes* pNotes1 = *(Notes**)arg1; Notes* pNotes2 = *(Notes**)arg2; int iScore1 = pNotes1->m_iMeter; int iScore2 = pNotes2->m_iMeter; if( iScore1 < iScore2 ) return -1; else if( iScore1 == iScore2 ) return CompareNotesPointersByRadarValues( arg1, arg2 ); else return 1; } int CompareNotesPointersByDifficulty(Notes* pNotes1, Notes* pNotes2) { DifficultyClass class1 = pNotes1->m_DifficultyClass; DifficultyClass class2 = pNotes2->m_DifficultyClass; if( class1 < class2 ) return -1; else if( class1 == class2 ) return CompareNotesPointersByMeter( &pNotes1, &pNotes2 ); else return 1; } int CompareNotesPointersByDifficulty2(const void *arg1, const void *arg2) { Notes* pNotes1 = *(Notes**)arg1; Notes* pNotes2 = *(Notes**)arg2; return CompareNotesPointersByDifficulty( pNotes1, pNotes2 ); } void SortNotesArrayByDifficulty( CArray &arraySteps ) { qsort( arraySteps.GetData(), arraySteps.GetSize(), sizeof(Notes*), CompareNotesPointersByDifficulty2 ); }