From 1c817ca08dab4077f906389af3a233837e2f6973 Mon Sep 17 00:00:00 2001 From: Glenn Maynard Date: Thu, 27 Mar 2003 00:48:58 +0000 Subject: [PATCH] Add TimingAssist; this roughly implements the timing helper in PNM. This lets us add an announcer that's played after each non-perfect step, eg. "gameplay assist late good". It only works reasonably for sparse songs--songs that only have notes far enough apart that the announcer makes sense. That's mostly beginner songs, which is what this is targetted at anyway. It's meaningless to use this assist mode in harder songs; even if the announcer was rate limited, it'd be impossible to tell which step the announcer was for, so I didn't bother trying. (It'd be amusing to turn this on in MaxU. :) A different timing assist type (TimingTip) is probably coming soon, targetted to higher level (light/med) songs. The only major problem at the moment is that there's no way to tell who the announcer is talking to if there's two players. If we implement per-player announcers, that would help (and allow a number of other neat things, like having the p1 announcer say "Ready" and the p2 announcer say "HWG"). --- stepmania/src/TimingAssist.cpp | 102 +++++++++++++++++++++++++++++++++ stepmania/src/TimingAssist.h | 35 +++++++++++ 2 files changed, 137 insertions(+) create mode 100644 stepmania/src/TimingAssist.cpp create mode 100644 stepmania/src/TimingAssist.h diff --git a/stepmania/src/TimingAssist.cpp b/stepmania/src/TimingAssist.cpp new file mode 100644 index 0000000000..107df420f2 --- /dev/null +++ b/stepmania/src/TimingAssist.cpp @@ -0,0 +1,102 @@ +#include "global.h" +#include "TimingAssist.h" +#include "AnnouncerManager.h" +#include "GameState.h" +#include "NoteData.h" +#include "NoteTypes.h" +#include "PrefsManager.h" + +#include "RageLog.h" +TimingAssist::TimingAssist() +{ + for(int i = 0; i < 2; ++i) + { + const CString direction = i? "early":"late"; + for(TapNoteScore j = TNS_BOO; j < TNS_MARVELOUS; j = TapNoteScore(j+1)) + { + CString name; + switch(j) + { + case TNS_MISS: name = "miss"; break; + case TNS_BOO: name = "boo"; break; + case TNS_GOOD: name = "good"; break; + case TNS_GREAT: name = "great"; break; + case TNS_PERFECT: name = "perfect"; break; + } + CString path = ssprintf("gameplay assist %s %s", direction.GetString(), name.GetString()); + Timing[j][i].Load(ANNOUNCER->GetPathTo(path)); + } + } + + Miss.Load(ANNOUNCER->GetPathTo("gameplay assist miss")); + memset(data, 0, sizeof(data)); +} + +void TimingAssist::Load(PlayerNumber pn, NoteDataWithScoring *nd) +{ + data[pn] = nd; +} + +void TimingAssist::Reset() +{ + LastRow = 0; +} + +void TimingAssist::Update(float fDeltaTime) +{ + Actor::Update(fDeltaTime); + + for( int pn=0; pnIsPlayerEnabled(PlayerNumber(pn)) ) + continue; + + DoTimingAssist((PlayerNumber)pn); + } +} + +void TimingAssist::DoTimingAssist(PlayerNumber pn) +{ + ASSERT(data[pn]); + + if(!GAMESTATE->m_PlayerOptions[pn].m_bTimingAssist) + return; + + const int maxrow = BeatToNoteRow(GAMESTATE->m_fSongBeat); + for( ; LastRow <= maxrow; LastRow++) + { + TapNoteScore mintns = data[pn]->MinTapNoteScore(LastRow); + + /* If the minimum score is TNS_NONE, then not all notes on this row have + * been graded, so stop. */ + if(mintns == TNS_NONE) return; + + /* Don't announce if the score is the maximum. */ + if(mintns == TNS_MARVELOUS) continue; + if(mintns == TNS_PERFECT && !PREFSMAN->m_bMarvelousTiming) continue; + + if(mintns == TNS_MISS) + { + Miss.PlayRandom(); + continue; + } + + const int last_tns_track = data[pn]->LastTapNoteScoreTrack(LastRow); + + /* We shouldn't get here if there're no notes on this row, since MinTNS + * above should have returned TNS_NONE. */ + ASSERT(last_tns_track != -1); + + const TapNoteScore last_tns = data[pn]->GetTapNoteScore(last_tns_track, LastRow); + const float offset = data[pn]->GetTapNoteOffset(last_tns_track, LastRow); + const bool early = offset < 0; + + Timing[last_tns][early].PlayRandom(); + } +} +/* +----------------------------------------------------------------------------- + Copyright (c) 2003 by the person(s) listed below. All rights reserved. + Glenn Maynard +----------------------------------------------------------------------------- +*/ diff --git a/stepmania/src/TimingAssist.h b/stepmania/src/TimingAssist.h new file mode 100644 index 0000000000..3811f6c4c7 --- /dev/null +++ b/stepmania/src/TimingAssist.h @@ -0,0 +1,35 @@ +#ifndef TIMING_ASSIST_H +#define TIMING_ASSIST_H + +#include "Actor.h" +#include "RandomSample.h" +#include "GameConstantsAndTypes.h" +#include "PlayerNumber.h" +#include "NoteDataWithScoring.h" + +class TimingAssist: public Actor +{ +public: + TimingAssist(); + void Load(PlayerNumber pn, NoteDataWithScoring *nd); + void DrawPrimitives() { } + void Update(float fDeltaTime); + void Reset(); + +private: + void DoTimingAssist(PlayerNumber pn); + + RandomSample Timing[NUM_TAP_NOTE_SCORES][2]; + RandomSample Miss; + + NoteDataWithScoring *data[NUM_PLAYERS]; + int LastRow; +}; + +#endif +/* +----------------------------------------------------------------------------- + Copyright (c) 2003 by the person(s) listed below. All rights reserved. + Glenn Maynard +----------------------------------------------------------------------------- +*/