Files
itgmania212121/src/NoteTypes.h
T

254 lines
7.6 KiB
C++
Raw Normal View History

2005-02-13 03:40:37 +00:00
/* NoteTypes - Types for holding tap notes and scores. */
2004-05-31 22:42:12 +00:00
#ifndef NOTE_TYPES_H
#define NOTE_TYPES_H
#include "GameConstantsAndTypes.h"
2007-06-09 07:49:40 +00:00
#include "PlayerNumber.h"
class XNode;
struct TapNoteResult
{
2006-08-14 10:45:43 +00:00
TapNoteResult() : tns(TNS_None), fTapNoteOffset(0.f), bHidden(false) { }
TapNoteScore tns;
/* Offset, in seconds, for a tap grade. Negative numbers mean the note
* was hit early; positive numbers mean it was hit late. These values are
* only meaningful for graded taps (tns >= TNS_W5). */
2006-08-14 10:45:43 +00:00
float fTapNoteOffset;
/* If the whole row has been judged, all taps on the row will be set to hidden. */
2006-08-14 10:45:43 +00:00
bool bHidden;
// XML
XNode* CreateNode() const;
void LoadFromNode( const XNode* pNode );
};
struct HoldNoteResult
{
HoldNoteResult() : hns(HNS_None), fLife(1.f), fOverlappedTime(0), iLastHeldRow(0), iCheckpointsHit(0), iCheckpointsMissed(0), bHeld(false), bActive(false) { }
2006-08-14 10:45:43 +00:00
float GetLastHeldBeat() const;
HoldNoteScore hns;
/* 1.0 means this HoldNote has full life.
* 0.0 means this HoldNote is dead
2006-12-28 04:07:15 +00:00
* When this value hits 0.0 for the first time, m_HoldScore becomes HNS_LetGo.
* If the life is > 0.0 when the HoldNote ends, then m_HoldScore becomes HNS_Held. */
2007-01-05 01:20:32 +00:00
float fLife;
2007-01-15 06:35:09 +00:00
/* The number of seconds the hold note has overlapped the current beat, or 0 if it
* doesn't overlap. */
float fOverlappedTime;
/* Last index where fLife was greater than 0. If the tap was missed, this will
* be the first index of the hold. */
2006-08-14 10:45:43 +00:00
int iLastHeldRow;
/* If checkpoint holds are enabled, the number of checkpoints hit and missed. */
int iCheckpointsHit;
int iCheckpointsMissed;
2007-01-05 01:20:32 +00:00
bool bHeld; // Was button held during last update?
bool bActive; // Is life > 0 && overlaps current beat
// XML
XNode* CreateNode() const;
void LoadFromNode( const XNode* pNode );
};
2008-03-12 23:17:39 +00:00
const int8_t MIDI_NOTE_INVALID = -1;
const int NUM_MIDI_NOTES = 128;
const int MIDI_NOTES_PER_OCTAVE = 12;
struct TapNote
{
2006-06-16 22:09:39 +00:00
enum Type
{
2004-10-23 23:41:49 +00:00
empty, // no note here
2006-08-14 07:58:03 +00:00
tap, // step on this
hold_head, // graded like a tap
hold_tail, // in 2sand3s mode, holds are deleted and hold_tail is added
mine, // don't step!
2006-08-14 12:16:31 +00:00
lift, // up
attack,
2004-10-24 10:45:30 +00:00
autoKeysound,
fake, // not scored for or against
2006-08-14 10:45:43 +00:00
};
enum SubType
{
hold_head_hold,
hold_head_roll,
2007-01-15 23:09:23 +00:00
NUM_SubType,
2007-01-15 23:47:55 +00:00
SubType_Invalid
2006-08-14 10:45:43 +00:00
};
2006-06-16 22:09:39 +00:00
enum Source
{
original, // part of the original NoteData
addition, // additional note added by a transform
2006-08-14 10:45:43 +00:00
};
Type type;
SubType subType; // Only used if type is hold_head.
Source source;
TapNoteResult result;
2008-03-12 23:17:39 +00:00
int8_t iMidiNote; // ignored by all game types but Karaoke
PlayerNumber pn; // used in routine mode
bool bHopoPossible; // set just before gameplay begins
2006-08-14 10:45:43 +00:00
2008-03-12 23:17:39 +00:00
RString sAttackModifiers; // used only if Type == attack
float fAttackDurationSeconds; // used only if Type == attack
2005-02-02 06:52:07 +00:00
2008-03-12 23:17:39 +00:00
int iKeysoundIndex; // Index into Song's vector of keysound files if nonnegative.
2005-02-02 06:52:07 +00:00
2008-03-12 23:17:39 +00:00
int iDuration; // used if hold_head only
HoldNoteResult HoldResult; // used if hold_head only
2006-06-16 23:43:17 +00:00
// XML
XNode* CreateNode() const;
void LoadFromNode( const XNode* pNode );
2008-03-12 23:17:39 +00:00
TapNote()
{
Init();
}
void Init()
{
type = empty;
subType = SubType_Invalid;
source = original;
iMidiNote = MIDI_NOTE_INVALID;
pn = PLAYER_INVALID,
bHopoPossible = false;
fAttackDurationSeconds = 0.f;
iKeysoundIndex = -1;
iDuration = 0;
}
2004-10-23 23:41:49 +00:00
TapNote(
2005-04-18 01:23:57 +00:00
Type type_,
SubType subType_,
Source source_,
2006-01-22 01:00:06 +00:00
RString sAttackModifiers_,
2004-10-23 23:41:49 +00:00
float fAttackDurationSeconds_,
int iKeysoundIndex_ )
{
2008-03-12 23:17:39 +00:00
Init();
type = type_;
subType = subType_;
source = source_;
2004-10-23 23:41:49 +00:00
sAttackModifiers = sAttackModifiers_;
fAttackDurationSeconds = fAttackDurationSeconds_;
iKeysoundIndex = iKeysoundIndex_;
2005-02-02 06:52:07 +00:00
iDuration = 0;
2006-06-16 23:43:17 +00:00
pn = PLAYER_INVALID;
}
2004-10-24 10:20:24 +00:00
bool operator==( const TapNote &other ) const
{
2006-08-14 10:45:43 +00:00
#define COMPARE(x) if(x!=other.x) return false
COMPARE(type);
COMPARE(subType);
COMPARE(source);
2004-10-23 23:41:49 +00:00
COMPARE(sAttackModifiers);
COMPARE(fAttackDurationSeconds);
COMPARE(iKeysoundIndex);
2005-01-25 05:02:35 +00:00
COMPARE(iDuration);
2008-03-12 23:17:39 +00:00
COMPARE(iMidiNote);
2006-06-16 23:43:17 +00:00
COMPARE(pn);
#undef COMPARE
return true;
}
bool operator!=( const TapNote &other ) const { return !operator==( other ); }
};
2006-06-16 22:09:39 +00:00
extern TapNote TAP_EMPTY; // '0'
extern TapNote TAP_ORIGINAL_TAP; // '1'
2004-10-24 10:20:24 +00:00
extern TapNote TAP_ORIGINAL_HOLD_HEAD; // '2'
2005-04-18 01:23:57 +00:00
extern TapNote TAP_ORIGINAL_ROLL_HEAD; // '4'
2006-06-16 22:09:39 +00:00
extern TapNote TAP_ORIGINAL_MINE; // 'M'
2006-08-14 12:16:31 +00:00
extern TapNote TAP_ORIGINAL_LIFT; // 'L'
2006-06-16 22:09:39 +00:00
extern TapNote TAP_ORIGINAL_ATTACK; // 'A'
2004-10-24 10:45:30 +00:00
extern TapNote TAP_ORIGINAL_AUTO_KEYSOUND; // 'K'
extern TapNote TAP_ORIGINAL_FAKE; // 'F'
extern TapNote TAP_ADDITION_TAP;
extern TapNote TAP_ADDITION_MINE;
// TODO: Don't have a hard-coded track limit.
2004-09-25 07:59:56 +00:00
const int MAX_NOTE_TRACKS = 16;
/* This is a divisor for our "fixed-point" time/beat representation. It must be evenly divisible
* by 2, 3, and 4, to exactly represent 8th, 12th and 16th notes. */
const int ROWS_PER_BEAT = 48;
2005-03-23 10:43:57 +00:00
/* In the editor, enforce a reasonable limit on the number of notes. */
2005-03-23 19:39:15 +00:00
const int MAX_NOTES_PER_MEASURE = 50;
2005-03-23 10:43:57 +00:00
2005-01-22 19:18:02 +00:00
const int MAX_NOTE_ROW = (1<<30);
enum NoteType
{
NOTE_TYPE_4TH, // quarter note
NOTE_TYPE_8TH, // eighth note
NOTE_TYPE_12TH, // quarter note triplet
NOTE_TYPE_16TH, // sixteenth note
NOTE_TYPE_24TH, // eighth note triplet
2002-09-11 04:49:07 +00:00
NOTE_TYPE_32ND, // thirty-second note
NOTE_TYPE_48TH, // sixteenth note triplet
2003-11-03 08:44:49 +00:00
NOTE_TYPE_64TH, // sixty-fourth note
NOTE_TYPE_192ND,// sixty-fourth note triplet
2006-02-02 08:43:05 +00:00
NUM_NoteType,
2006-10-07 04:39:48 +00:00
NoteType_Invalid
};
2006-01-22 01:00:06 +00:00
const RString& NoteTypeToString( NoteType nt );
2006-02-02 22:50:14 +00:00
const RString& NoteTypeToLocalizedString( NoteType nt );
2006-09-26 01:54:36 +00:00
LuaDeclareType( NoteType );
float NoteTypeToBeat( NoteType nt );
2004-10-24 00:17:15 +00:00
NoteType GetNoteType( int row );
NoteType BeatToNoteType( float fBeat );
2004-10-24 00:17:15 +00:00
bool IsNoteOfType( int row, NoteType t );
/* This is more accurate: by computing the integer and fractional parts separately, we
* can avoid storing very large numbers in a float and possibly losing precision. It's
* slower; use this once less stuff uses BeatToNoteRow. */
/*
inline int BeatToNoteRow( float fBeatNum )
{
float fraction = fBeatNum - truncf(fBeatNum);
int integer = int(fBeatNum) * ROWS_PER_BEAT;
return integer + lrintf(fraction * ROWS_PER_BEAT);
}
*/
2006-06-16 22:09:39 +00:00
inline int BeatToNoteRow( float fBeatNum ) { return lrintf( fBeatNum * ROWS_PER_BEAT ); } // round
2005-01-23 23:23:34 +00:00
inline int BeatToNoteRowNotRounded( float fBeatNum ) { return (int)( fBeatNum * ROWS_PER_BEAT ); }
2006-06-16 22:09:39 +00:00
inline float NoteRowToBeat( int iRow ) { return iRow / (float)ROWS_PER_BEAT; }
2003-12-16 04:00:39 +00:00
#endif
2004-05-31 22:42:12 +00:00
/*
* (c) 2001-2004 Chris Danford, Glenn Maynard
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, and/or sell copies of the Software, and to permit persons to
* whom the Software is furnished to do so, provided that the above
* copyright notice(s) and this permission notice appear in all copies of
* the Software and that both the above copyright notice(s) and this
* permission notice appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/