Files
itgmania212121/stepmania/src/ScoreKeeperMAX2.cpp
T
Glenn Maynard 57aefba669 unused variable
2003-03-26 19:05:13 +00:00

360 lines
9.6 KiB
C++

#include "global.h"
/*
-----------------------------------------------------------------------------
Class: ScoreKeeperMAX2
Desc:
Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved.
Chris Danford
-----------------------------------------------------------------------------
*/
#include "ScoreKeeperMAX2.h"
#include "GameState.h"
#include "PrefsManager.h"
#include "Notes.h"
#include "PrefsManager.h"
#include "ScreenManager.h"
#include "ScreenGameplay.h"
#include "GameState.h"
ScoreKeeperMAX2::ScoreKeeperMAX2(Notes *notes, PlayerNumber pn_):
ScoreKeeper(pn_)
{
if( notes )
{
NoteData noteData;
notes->GetNoteData( &noteData );
int Meter = notes->GetMeter();
Meter = min(Meter, 10);
int N = noteData.GetNumRowsWithTaps() + noteData.GetNumHoldNotes();
int sum = (N * (N + 1)) / 2;
if(sum)
m_fScoreMultiplier = float(Meter * 1000000) / sum;
else /* avoid div/0 on empty songs */
m_fScoreMultiplier = 0.f;
ASSERT(m_fScoreMultiplier >= 0.0);
}
else
{
ASSERT( GAMESTATE->IsCourseMode() );
m_fScoreMultiplier = 0.f;
}
m_iTapNotesHit = 0;
m_lScore = 0;
m_iCurToastyCombo = 0;
}
void ScoreKeeperMAX2::AddScore( TapNoteScore score )
{
int p; // score multiplier
switch( score )
{
case TNS_MARVELOUS: p = 10; break;
case TNS_PERFECT: p = 10; break;
case TNS_GREAT: p = 5; break;
default: p = 0; break;
}
m_lScore += p * ++m_iTapNotesHit;
ASSERT(m_lScore >= 0);
GAMESTATE->m_CurStageStats.fScore[m_PlayerNumber] = m_lScore * m_fScoreMultiplier;
}
void ScoreKeeperMAX2::HandleTapRowScore( TapNoteScore scoreOfLastTap, int iNumTapsInRow, Inventory* pInventory )
{
ASSERT( iNumTapsInRow >= 1 );
// update dance points
GAMESTATE->m_CurStageStats.iActualDancePoints[m_PlayerNumber] += TapNoteScoreToDancePoints( scoreOfLastTap );
GAMESTATE->m_CurStageStats.iTapNoteScores[m_PlayerNumber][scoreOfLastTap] += 1;
/*
http://www.aaroninjapan.com/ddr2.html
A single step's points are calculated as follows:
p = score multiplier (Perfect = 10, Great = 5, other = 0)
N = total number of steps and freeze steps
S = The sum of all integers from 1 to N (the total number of steps/freeze steps)
n = number of the current step or freeze step (varies from 1 to N)
B = Base value of the song (1,000,000 X the number of feet difficulty) - All edit data is rated as 5 feet
So, the score for one step is:
one_step_score = p * (B/S) * n
*IMPORTANT* : Double steps (U+L, D+R, etc.) count as two steps instead of one *for your combo count only*,
so if you get a double L+R on the 112th step of a song, you score is calculated for only one step, not two,
as the combo counter might otherwise imply.
Now, through simple algebraic manipulation:
S = 1+...+N = (1+N)*N/2 (1 through N added together)
Okay, time for an example. Suppose we wanted to calculate the step score of a "Great" on the 57th step of
a 441 step, 8-foot difficulty song (I'm just making this one up):
S = (1 + 441)*441 / 2
= 194,222 / 2
= 97,461
StepScore = p * (B/S) * n
= 5 * (8,000,000 / 97,461) * 57
= 5 * (82) * 57 (The 82 is rounded down from 82.08411...)
= 23,370
Remember this is just the score for the step, not the cumulative score up to the 57th step. Also, please note that
I am currently checking into rounding errors with the system and if there are any, how they are resolved in the system.
Note: if you got all Perfect on this song, you would get (p=10)*B, which is 80,000,000. In fact, the maximum possible
score for any song is the number of feet difficulty X 10,000,000.
3dfsux:
I redid this code so it will store the score as a long, then correct the score for each song based on that value.
lScore == p * n
m_fScoreMultiplier = (B/S)
keeping these seperate for as long as possible improves accuracy.
*/
AddScore( scoreOfLastTap ); // only score once per row
//
// handle combo logic
//
#ifndef DEBUG
if( PREFSMAN->m_bAutoPlay && !GAMESTATE->m_bDemonstrationOrJukebox ) // cheaters never prosper
{
m_iCurToastyCombo = 0;
return;
}
#endif //DEBUG
//
// Toasty combo
//
switch( scoreOfLastTap )
{
case TNS_MARVELOUS:
case TNS_PERFECT:
m_iCurToastyCombo += iNumTapsInRow;
if( m_iCurToastyCombo==250 && !GAMESTATE->m_bDemonstrationOrJukebox )
SCREENMAN->PostMessageToTopScreen( SM_PlayToasty, 0 );
break;
default:
m_iCurToastyCombo = 0;
break;
}
//
// Regular combo
//
int &iCurCombo = GAMESTATE->m_CurStageStats.iCurCombo[m_PlayerNumber];
int iOldCombo = iCurCombo;
/*
http://www.aaroninjapan.com/ddr2.html
Note on ONI Mode scoring
Your combo counter only increased with a "Marvelous/Perfect", and double Marvelous/Perfect steps (left and right, etc.)
only add 1 to your combo instead of 2. The combo counter thus becomes a "Marvelous/Perfect" counter.
*/
switch( GAMESTATE->m_PlayMode )
{
case PLAY_MODE_ARCADE:
case PLAY_MODE_BATTLE:
case PLAY_MODE_NONSTOP:
case PLAY_MODE_ENDLESS:
switch( scoreOfLastTap )
{
case TNS_MARVELOUS:
case TNS_PERFECT:
case TNS_GREAT:
iCurCombo += iNumTapsInRow;
break;
}
break;
case PLAY_MODE_ONI:
switch( scoreOfLastTap )
{
case TNS_MARVELOUS:
case TNS_PERFECT:
iCurCombo++;
break;
}
break;
default:
ASSERT(0);
}
#define CROSSED( i ) (iOldCombo<i && i<=iCurCombo)
if ( CROSSED(100) ) SCREENMAN->PostMessageToTopScreen( SM_100Combo, 0 );
else if( CROSSED(200) ) SCREENMAN->PostMessageToTopScreen( SM_200Combo, 0 );
else if( CROSSED(300) ) SCREENMAN->PostMessageToTopScreen( SM_300Combo, 0 );
else if( CROSSED(400) ) SCREENMAN->PostMessageToTopScreen( SM_400Combo, 0 );
else if( CROSSED(500) ) SCREENMAN->PostMessageToTopScreen( SM_500Combo, 0 );
else if( CROSSED(600) ) SCREENMAN->PostMessageToTopScreen( SM_600Combo, 0 );
else if( CROSSED(700) ) SCREENMAN->PostMessageToTopScreen( SM_700Combo, 0 );
else if( CROSSED(800) ) SCREENMAN->PostMessageToTopScreen( SM_800Combo, 0 );
else if( CROSSED(900) ) SCREENMAN->PostMessageToTopScreen( SM_900Combo, 0 );
else if( CROSSED(1000)) SCREENMAN->PostMessageToTopScreen( SM_1000Combo, 0 );
// new max combo
GAMESTATE->m_CurStageStats.iMaxCombo[m_PlayerNumber] = max(GAMESTATE->m_CurStageStats.iMaxCombo[m_PlayerNumber], iCurCombo);
switch( scoreOfLastTap )
{
case TNS_GOOD:
case TNS_BOO:
case TNS_MISS:
// don't play "combo stopped" in battle
switch( GAMESTATE->m_PlayMode )
{
case PLAY_MODE_BATTLE:
if( pInventory )
pInventory->OnComboBroken( m_PlayerNumber, iCurCombo );
default:
if( iCurCombo>50 )
SCREENMAN->PostMessageToTopScreen( SM_ComboStopped, 0 );
}
iCurCombo = 0;
break;
}
}
void ScoreKeeperMAX2::HandleHoldScore( HoldNoteScore holdScore, TapNoteScore tapScore )
{
// update dance points totals
GAMESTATE->m_CurStageStats.iHoldNoteScores[m_PlayerNumber][holdScore] ++;
GAMESTATE->m_CurStageStats.iActualDancePoints[m_PlayerNumber] += HoldNoteScoreToDancePoints( holdScore );
if( holdScore == HNS_OK )
AddScore( TNS_PERFECT );
}
int ScoreKeeperMAX2::GetPossibleDancePoints( const NoteData* pNoteData )
{
/* Note that, if Marvelous timing is disabled or not active (not course mode),
* PERFECT will be used instead. */
TapNoteScore maxPossibleTapScore = PREFSMAN->m_bMarvelousTiming ? TNS_MARVELOUS : TNS_PERFECT;
return pNoteData->GetNumRowsWithTaps()*TapNoteScoreToDancePoints(maxPossibleTapScore)+
pNoteData->GetNumHoldNotes()*HoldNoteScoreToDancePoints(HNS_OK);
}
int ScoreKeeperMAX2::TapNoteScoreToDancePoints( TapNoteScore tns )
{
if(!PREFSMAN->m_bMarvelousTiming && tns == TNS_MARVELOUS)
tns = TNS_PERFECT;
/*
http://www.aaroninjapan.com/ddr2.html
Regular play scoring
A "Perfect" is worth 2 points
A "Great" is worth 1 points
A "Good" is worth 0 points
A "Boo" will subtract 4 points
A "Miss" will subtract 8 points
An "OK" (Successful Freeze step) will add 6 points
A "NG" (Unsuccessful Freeze step) is worth 0 points
Note on ONI Mode scoring
The total number of Dance Points is calculated with Marvelous steps being worth 3 points, Perfects getting
2 points, OKs getting 3 points, Greats getting 1 point, and everything else is worth 0 points. (Note: The
"Marvelous" step rating is a new rating to DDR Extreme only used in Oni and Nonstop modes. They are rated
higher than "Perfect" steps).
Note on NONSTOP Mode scoring
A "Marvelous" is worth 2 points
A "Perfect" is also worth 2 points
A "Great" is worth 1 points
A "Good" is worth 0 points
A "Boo" will subtract 4 points
A "Miss" will subtract 8 points
An "OK" (Successful Freeze step) will add 6 points
A "NG" (Unsuccessful Freeze step) is worth 0 points
*/
switch( GAMESTATE->m_PlayMode )
{
case PLAY_MODE_ARCADE:
case PLAY_MODE_BATTLE:
case PLAY_MODE_ENDLESS:
case PLAY_MODE_NONSTOP:
switch( tns )
{
case TNS_MARVELOUS: return +2;
case TNS_PERFECT: return +2;
case TNS_GREAT: return +1;
case TNS_GOOD: return +0;
case TNS_BOO: return -4;
case TNS_MISS: return -8;
}
break;
case PLAY_MODE_ONI:
switch( tns )
{
case TNS_MARVELOUS: return +3;
case TNS_PERFECT: return +2;
case TNS_GREAT: return +1;
case TNS_GOOD: return +0;
case TNS_BOO: return +0;
case TNS_MISS: return +0;
}
break;
default:
ASSERT(0);
}
return +0;
}
int ScoreKeeperMAX2::HoldNoteScoreToDancePoints( HoldNoteScore hns )
{
switch( GAMESTATE->m_PlayMode )
{
case PLAY_MODE_ARCADE:
case PLAY_MODE_BATTLE:
case PLAY_MODE_ENDLESS:
case PLAY_MODE_NONSTOP:
switch( hns )
{
case HNS_OK: return +6;
case HNS_NG: return +0;
}
break;
case PLAY_MODE_ONI:
switch( hns )
{
case HNS_OK: return +3;
case HNS_NG: return +0;
}
break;
default:
ASSERT(0);
}
return +0;
}