Etterna 0.74.4
Loading...
Searching...
No Matches
Player.h
1#ifndef PLAYER_H
2#define PLAYER_H
3
4#include "Etterna/Actor/Base/ActorFrame.h"
5#include "Etterna/Actor/Base/AutoActor.h"
6#include "Etterna/Screen/Others/ScreenMessage.h"
7#include "RageUtil/Sound/RageSound.h"
8#include "Etterna/Models/NoteData/NoteData.h"
9#include "Etterna/Models/Misc/TimingData.h"
10
11#include <chrono>
12
13class LifeMeter;
14class ScoreKeeper;
15class RageTimer;
16class NoteField;
18class JudgedRows;
19class PlayerState;
20class HoldJudgment;
21class Replay;
22
23// todo: replace these with a Message and MESSAGEMAN? -aj
24AutoScreenMessage(SM_100Combo);
25AutoScreenMessage(SM_200Combo);
26AutoScreenMessage(SM_300Combo);
27AutoScreenMessage(SM_400Combo);
28AutoScreenMessage(SM_500Combo);
29AutoScreenMessage(SM_600Combo);
30AutoScreenMessage(SM_700Combo);
31AutoScreenMessage(SM_800Combo);
32AutoScreenMessage(SM_900Combo);
33AutoScreenMessage(SM_1000Combo);
34AutoScreenMessage(SM_ComboStopped);
35AutoScreenMessage(SM_ComboContinuing);
36
37constexpr float initialHoldLife = 1.F;
38
41class Player : public ActorFrame
42{
43 public:
44 // The passed in NoteData isn't touched until Load() is called.
45 Player(NoteData& nd, bool bVisibleParts = true);
46 ~Player() override;
47
48 void Update(float fDeltaTime) override;
49 void DrawPrimitives() override;
50 // PushPlayerMatrix and PopPlayerMatrix are separate functions because
51 // they need to be used twice so that the notefield board can rendered
52 // underneath the combo and judgment. They're not embedded in
53 // PlayerMatrixPusher so that some nutjob can later decide to expose them
54 // to lua. -Kyz
55 static void PushPlayerMatrix(float x, float skew, float center_y);
56 static void PopPlayerMatrix();
57
58 // This exists so that the board can be drawn underneath combo/judge. -Kyz
59 void DrawNoteFieldBoard();
60
61 // Here's a fun construct for people that haven't seen it before:
62 // This object does some task when it's created, then cleans up when it's
63 // destroyed. That way, you stick it inside a block, and can't forget the
64 // cleanup. -Kyz
66 {
68 float x,
69 float tilt,
70 float skew,
71 float mini,
72 float center_y,
73 bool reverse);
75 Player* player;
76 float original_y;
77 float y_offset;
78 };
79
81 {
82 int iTrack;
83 int iRow;
84 TapNote* pTN;
85 };
86 virtual void UpdateHoldNotes(int iSongRow,
87 float fDeltaTime,
88 std::vector<TrackRowTapNote>& vTN);
89
90 virtual void Init(const std::string& sType,
91 PlayerState* pPlayerState,
92 PlayerStageStats* pPlayerStageStats,
93 LifeMeter* pLM,
94 ScoreKeeper* pPrimaryScoreKeeper);
95 virtual void Load();
96 virtual void Reload();
97 virtual void CrossedRows(int iLastRowCrossed,
98 const std::chrono::steady_clock::time_point& now);
104 auto GetPlayerTimingData() const -> TimingData { return *(this->m_Timing); }
105
106 void ScoreAllActiveHoldsLetGo();
107 void DoTapScoreNone();
108 void AddHoldToReplayData(int col,
109 const TapNote* pTN,
110 int RowOfOverlappingNoteOrRow) const;
111 void AddNoteToReplayData(int col,
112 const TapNote* pTN,
113 int RowOfOverlappingNoteOrRow) const;
114 void AddMineToReplayData(int col, int row) const;
115
116 virtual void Step(int col,
117 int row,
118 const std::chrono::steady_clock::time_point& tm,
119 bool bHeld,
120 bool bRelease,
121 float padStickSeconds = 0.0F);
122
123 void FadeToFail();
124 void CacheAllUsedNoteSkins() const;
125 auto GetLastTapNoteScore() const -> TapNoteScore
126 {
127 return m_LastTapNoteScore;
128 }
129 void SetPaused(bool bPaused) { m_bPaused = bPaused; }
130
131 static auto GetMaxStepDistanceSeconds() -> float;
132 static auto GetWindowSeconds(TimingWindow tw) -> float;
133 static auto GetWindowSecondsCustomScale(TimingWindow tw,
134 float timingScale = 1.F) -> float;
135 static auto GetTimingWindowScale() -> float;
136 auto GetNoteData() const -> const NoteData& { return m_NoteData; }
137 auto HasVisibleParts() const -> bool { return m_pNoteField != nullptr; }
138
139 void SetSendJudgmentAndComboMessages(bool b)
140 {
141 m_bSendJudgmentAndComboMessages = b;
142 }
143 void RenderAllNotesIgnoreScores();
144
145 // Lua
146 void PushSelf(lua_State* L) override;
147
148 auto GetPlayerState() const -> PlayerState* { return this->m_pPlayerState; }
149 void ChangeLife(float delta) const;
150 void SetLife(float value) const;
151 bool m_inside_lua_set_life;
152
153 // Mina perma-temp stuff
154 std::vector<int> nerv; // the non empty row vector where we are somehwere in
155 size_t nervpos = 0; // where we are in the non-empty row vector
156 float maxwifescore = 0.F;
157 float curwifescore = 0.F;
158 float wifescorepersonalbest = 0.F;
159 int totalwifescore;
160
161 protected:
162 static auto NeedsTapJudging(const TapNote& tn) -> bool;
163 static auto NeedsHoldJudging(const TapNote& tn) -> bool;
164 virtual void UpdateTapNotesMissedOlderThan(float fMissIfOlderThanSeconds);
165 void UpdateJudgedRows(float fDeltaTime);
166 // Updates visible parts: Hold Judgments, NoteField Zoom, Combo based Actors
167 void UpdateVisibleParts();
168 // Updates the pressed flags depending on input
169 // Tells the NoteField to do stuff basically
170 virtual void UpdatePressedFlags();
171 // Updates Holds and Rolls
172 // For Rolls, just tells Autoplay to restep them
173 // For Holds, tells their life to decay
174 // ... oh man this is redundant
175 virtual void UpdateHoldsAndRolls(
176 float fDeltaTime,
177 const std::chrono::steady_clock::time_point& now);
178 // Updates Crossed Rows for NoteData
179 // What this involves is:
180 // Hold Life/Tapping Heads/Checkpoints
181 // Mines (The act of holding a button to hit one)
182 // Autoplay hitting taps
183 // Keysounds
184 void UpdateCrossedRows(const std::chrono::steady_clock::time_point& now);
185 void FlashGhostRow(int iRow);
186 virtual void HandleTapRowScore(unsigned row);
187 void HandleHoldScore(const TapNote& tn) const;
188 void HandleHoldCheckpoint(int iRow,
189 int iNumHoldsHeldThisRow,
190 int iNumHoldsMissedThisRow,
191 const std::vector<int>& viColsWithHold);
192 void DrawTapJudgments();
193 void DrawHoldJudgments();
194 void SendComboMessages(unsigned int iOldCombo,
195 unsigned int iOldMissCombo) const;
196 void PlayKeysound(const TapNote& tn, TapNoteScore score);
197
198 void SetMineJudgment(TapNoteScore tns, int iTrack, int iRow);
199 void SetJudgment(int iRow, int iFirstTrack, const TapNote& tn)
200 {
201 SetJudgment(
202 iRow, iFirstTrack, tn, tn.result.tns, tn.result.fTapNoteOffset);
203 }
204 void SetJudgment(int iRow,
205 int iTrack,
206 const TapNote& tn,
207 TapNoteScore tns,
208 float fTapNoteOffset); // -1 if no track as in TNS_Miss
209 void SetHoldJudgment(TapNote& tn, int iTrack, int iRow);
210 void SetCombo(unsigned int iCombo, unsigned int iMisses);
211 void IncrementComboOrMissCombo(bool bComboOrMissCombo);
212 void IncrementCombo() { IncrementComboOrMissCombo(true); };
213 void IncrementMissCombo() { IncrementComboOrMissCombo(false); };
214
215 void ChangeLife(TapNoteScore tns) const;
216 void ChangeLife(HoldNoteScore hns, TapNoteScore tns) const;
217 void ChangeLifeRecord() const;
218
219 void ChangeWifeRecord() const;
220
221 auto GetClosestNoteDirectional(int col,
222 int iStartRow,
223 int iEndRow,
224 bool bAllowGraded,
225 bool bForward) const -> int;
226 auto GetClosestNote(int col,
227 int iNoteRow,
228 int iMaxRowsAhead,
229 int iMaxRowsBehind,
230 bool bAllowGraded,
231 bool bUseSongTiming = true,
232 bool bAllowOldMines = true) const -> int;
233 auto GetClosestNonEmptyRowDirectional(int iStartRow,
234 int iEndRow,
235 bool bAllowGraded,
236 bool bForward) const -> int;
237 auto GetClosestNonEmptyRow(int iNoteRow,
238 int iMaxRowsAhead,
239 int iMaxRowsBehind,
240 bool bAllowGraded) const -> int;
241
242 void HideNote(int col, int row) const
243 {
244 const auto iter = m_NoteData.FindTapNote(col, row);
245 if (iter != m_NoteData.end(col)) {
246 iter->second.result.bHidden = true;
247 }
248 }
249
250 bool m_bLoaded;
251
256 TimingData* m_Timing;
257 float m_fNoteFieldHeight;
258
259 std::vector<float> lastHoldHeadsSeconds;
260
261 bool m_bPaused;
262 bool m_bDelay;
263
264 NoteData& m_NoteData;
265 NoteField* m_pNoteField;
266 Replay* pbReplay = nullptr;
267
268 std::vector<HoldJudgment*> m_vpHoldJudgment;
269
270 AutoActor m_sprJudgment;
271 AutoActor m_sprCombo;
272
273 TapNoteScore m_LastTapNoteScore;
274 LifeMeter* m_pLifeMeter;
275 ScoreKeeper* m_pPrimaryScoreKeeper;
276
277 int m_iFirstUncrossedRow; // used by hold checkpoints logic
278 NoteData::all_tracks_iterator* m_pIterNeedsTapJudging;
279 NoteData::all_tracks_iterator* m_pIterNeedsHoldJudging;
280 NoteData::all_tracks_iterator* m_pIterUncrossedRows;
281 NoteData::all_tracks_iterator* m_pIterUnjudgedRows;
282 NoteData::all_tracks_iterator* m_pIterUnjudgedMineRows;
283 unsigned int m_iLastSeenCombo;
284 bool m_bSeenComboYet;
285 JudgedRows* m_pJudgedRows;
286
287 RageSound m_soundMine;
288
289 std::vector<RageSound> m_vKeysounds;
290
291 bool m_bSendJudgmentAndComboMessages;
292 bool m_bTickHolds;
293 // This exists so that the board can be drawn underneath combo/judge. -Kyz
294 bool m_drawing_notefield_board;
295};
296
302{
303 std::vector<bool> m_vRows;
304 int m_iStart{ 0 };
305 int m_iOffset{ 0 };
306 void Resize(size_t iMin);
307
308 public:
309 JudgedRows() { Resize(32); }
310 // Returns true if the row has already been judged.
311 auto JudgeRow(int iRow) -> bool
312 {
313 if (iRow < m_iStart) {
314 return true;
315 }
316 if (iRow >= m_iStart + static_cast<int>(m_vRows.size())) {
317 Resize(iRow + 1 - m_iStart);
318 }
319 const int iIndex = (iRow - m_iStart + m_iOffset) % m_vRows.size();
320 const bool ret = m_vRows[iIndex];
321 m_vRows[iIndex] = true;
322 while (m_vRows[m_iOffset]) {
323 m_vRows[m_iOffset] = false;
324 ++m_iStart;
325 if (++m_iOffset >= static_cast<int>(m_vRows.size())) {
326 m_iOffset -= m_vRows.size();
327 }
328 }
329 return ret;
330 }
331 void Reset(int iStart)
332 {
333 m_iStart = iStart;
334 m_iOffset = 0;
335 m_vRows.assign(m_vRows.size(), false);
336 }
337};
338
339#endif
A container for other Actors.
Definition ActorFrame.h:8
A smart pointer for Actor.
Definition AutoActor.h:13
Definition HoldJudgment.h:10
Helper class to ensure that each row is only judged once without taking too much memory.
Definition Player.h:302
The player's life.
Definition LifeMeter.h:13
Definition NoteData.h:107
Holds data about the notes that the player is supposed to hit.
Definition NoteData.h:43
An Actor that renders NoteData.
Definition NoteField.h:15
Contains statistics for one stage of play - either one song, or a whole course.
Definition PlayerStageStats.h:19
The player's indivdual state.
Definition PlayerState.h:30
Accepts input, knocks down TapNotes that were stepped on, and keeps score for the player.
Definition Player.h:42
PlayerState * m_pPlayerState
The player's present state.
Definition Player.h:253
PlayerStageStats * m_pPlayerStageStats
The player's present stage stats.
Definition Player.h:255
static auto NeedsHoldJudging(const TapNote &tn) -> bool
Determine if a TapNote needs a hold note style judgment.
Definition Player.cpp:484
void DrawPrimitives() override
Draw the primitives of the Actor.
Definition Player.cpp:1338
static auto NeedsTapJudging(const TapNote &tn) -> bool
Determine if a TapNote needs a tap note style judgment.
Definition Player.cpp:462
auto GetPlayerTimingData() const -> TimingData
Retrieve the Player's TimingData.
Definition Player.h:104
Definition RageSound.h:130
Definition RageTimer.h:9
Definition Replay.h:15
Abstract class to handle scorekeeping, stat-taking, etc.
Definition ScoreKeeper.h:20
Holds data for translating beats<->seconds.
Definition TimingData.h:54
Definition Player.h:66
Definition Player.h:81
float fTapNoteOffset
Offset, in seconds, for a tap grade.
Definition NoteTypes.h:27
TapNoteScore tns
The TapNoteScore that was achieved by the player.
Definition NoteTypes.h:19
The various properties of a tap note.
Definition NoteTypes.h:149
TapNoteResult result
The result of hitting or missing the TapNote.
Definition NoteTypes.h:158