diff --git a/Docs/Luadoc/Lua.xml b/Docs/Luadoc/Lua.xml
index d523d5514c..7686476a35 100644
--- a/Docs/Luadoc/Lua.xml
+++ b/Docs/Luadoc/Lua.xml
@@ -1641,6 +1641,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Docs/Luadoc/LuaDocumentation.xml b/Docs/Luadoc/LuaDocumentation.xml
index b78ceba84d..addb2faaa4 100644
--- a/Docs/Luadoc/LuaDocumentation.xml
+++ b/Docs/Luadoc/LuaDocumentation.xml
@@ -453,7 +453,7 @@ save yourself some time, copy this for undocumented things:
[02 Colors.lua] Modifies the saturation of the specified color
-
+
Saves a screenshot. If pn is nil, saves to the machine's Screenshots dir, otherwise saves to the profile's Screenshots dir. Saves as jpg if compress is true, or png if compress is false. The screenshot is signed if sign is true. prefix and suffix are optional strings to add to the beginning and end of the filename.
Returns success and full path of the resulting screenshot.
@@ -648,56 +648,56 @@ save yourself some time, copy this for undocumented things:
Updates ArrowEffects, which sets current values for Tornado, Invert, and Beat.
-
+
Returns the Y Offset of a note in column iCol at beat fNoteBeat for the provided PlayerState. Y Offset is affected by Speed mods and Accel mods, and impacts most other arrow effects.
-
+
Returns the Y position of a note in column iCol with a Y offset of fYOffset for the provided PlayerState. fYReverseOffsetPixels is the separation between targets with and without reverse. This argument is optional and will pull defaults from the metrics for [Player]
-
+
Returns the Y offset of a note in column iCol with a Y position of fYPos for the provided PlayerState. fYReverseOffsetPixels is the separation between targets with and without reverse. This argument is optional and will pull defaults from the metrics for [Player]
-
+
Returns the X position of a note in column iCol with a Y offset of fYOffset for the provided PlayerState.
-
+
Returns the Z position of a note in column iCol with a Y offset of fYOffset for the provided PlayerState.
-
+
Returns the X rotation of a note with a Y offset of fYOffset for the provided PlayerState.
-
+
Returns the Y rotation of a note with a Y offset of fYOffset for the provided PlayerState.
-
+
Returns the Z rotation of a note at beat fNoteBeat for the provided PlayerState. bIsHoldHead is an optional argument which defaults to false. If true, this function will return 0 if the [ArrowEffects] metric DizzyHoldHeads is false.
-
+
Returns the Z rotation of the receptors for the provided PlayerState.
-
+
Returns the Alpha of a note in column iCol with a Y offset of fYOffset for the provided PlayerState. fPercentFadeToFail is optional and defaults to -1. fYReverseOffsetPixels is the separation between targets with and without reverse. This argument is optional and will pull defaults from the metrics for [Player] fDrawDistanceBeforeTargetsPixels is optional and will pull defaults from the [Player] metric DrawDistanceBeforeTargetsPixels fFadeInPercentOfDrawFar is optional and will pull defaults from the [NoteField] metric FadeBeforeTargetsPercent
-
+
Returns the Glow of a note in column iCol with a Y offset of fYOffset for the provided PlayerState. The arguments are the same as for GetAlpha.
-
+
Returns the brightness of a note at beat fNoteBeat for the provided PlayerState.
-
+
Returns true if any arrow effects for the provided PlayerState require the z buffer.
-
+
Returns the zoom of a note for the provided PlayerState.
-
+
Returns the FrameWidthScale of a hold part with a Y offset of fYOffset for the provided PlayerState. fOverlappedTime is optional and will default to 0.
@@ -755,7 +755,7 @@ save yourself some time, copy this for undocumented things:
Tries to read the file at sPath. If successful, it returns the file's contents.
If unsuccessful, it returns two values: nil and "error".
-
+
Reports the error through the error reporting system. error_type is the type used for the dialog that is presented, a dialog will not appear for a type the user has chosen to ignore.
error is optional an defaults to "Script error occurred.". error_type is optional and defaults to "LUA_ERROR".
@@ -4630,7 +4630,7 @@ save yourself some time, copy this for undocumented things:
Returns the StyleType for this Style.
-
+
Returns a table containing the Track, XOffset, and Name of the column.
@@ -4643,6 +4643,75 @@ save yourself some time, copy this for undocumented things:
Returns true if the Style needs to be zoomed out with two players.
+
+
+ Returns the of the Tap Note.
+
+
+ Returns the of the Tap Note.
+
+
+ Returns the of the Tap Note.
+
+
+ Returns the of the Tap Note.
+
+
+ Returns the of the Tap Note. Relevant for routine steps.
+
+
+ Returns the Attack Modifiers of the Tap Note.
+
+
+ Returns the Attack Duration of the Tap Note in seconds.
+
+
+ Returns the Keysound Index of the Tap Note.
+
+
+ Returns the Hold Duration of the Tap Note in beats.
+
+
+ Returns the of the Tap Note.
+
+
+
+
+ Returns the of the Tap Note.
+
+
+ Returns the TapNotOffset of the Tap Note.
+
+
+ Returns true if the Tap Note was judged with a result that would stop it from drawing.
+
+
+
+
+ Returns the of the Hold Note.
+
+
+ Returns the life of the Hold Note.
+
+
+ Returns the amount of time the hold has overlapped the target.
+
+
+ Returns the last beat the Hold Note was held.
+
+
+ Returns the number of checkpoints hit.
+
+
+ Returns the number of checkpoints missed.
+
+
+ Returns true if the note was initiated and is being held.
+
+
+ Returns true if the note was initiated.
+
+
Loads the TextBanner from the specified metrics group.
diff --git a/Makefile.am b/Makefile.am
index 7da514dda1..271f0346ed 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -6,7 +6,8 @@ ACLOCAL_AMFLAGS = -I autoconf/m4
## Black magic (read: sed) for getting the product ID as defined in code, not by the autotools.
## Quotes are making vim's highlighting of this even worse, so just escape everything,
## including the escapes. Make it lowercase to match ArchHooks::MountInitialFileSystems().
-productID := $(shell sed -nr /define\\s+PRODUCT_ID_BARE/\{s/.*define\\s+PRODUCT_ID_BARE\\s+\(.+\)/\\1/\;y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/\;p\;q\} $(srcdir)/src/ProductInfo.h)
+## Replace space with - so package build tools won't choke on the installation directory.
+productID := $(shell sed -nr /define\\s+PRODUCT_ID_BARE/\{s/.*define\\s+PRODUCT_ID_BARE\\s+\(.+\)/\\1/\;y/ABCDEFGHIJKLMNOPQRSTUVWXYZ\ /abcdefghijklmnopqrstuvwxyz-/\;p\;q\} $(srcdir)/src/ProductInfo.h)
installFiles = src/stepmania
if HAVE_GTK
@@ -26,14 +27,14 @@ dist-hook: SMData
cp -r -t "$(distdir)" $(installFiles)
install-exec-hook:
- mkdir -p "$(prefix)/$(productID)"
- $(INSTALL) $(installFiles) "$(prefix)/$(productID)"
+ mkdir -p "$(DESTDIR)$(prefix)/$(productID)"
+ $(INSTALL) $(installFiles) "$(DESTDIR)$(prefix)/$(productID)"
install-data-local:
- cp -r -t "$(prefix)/$(productID)" $(installData)
- mkdir -p "$(prefix)/$(productID)/Songs"
+ mkdir -p "$(DESTDIR)$(prefix)/$(productID)/Songs"
+ cp -r -t "$(DESTDIR)$(prefix)/$(productID)" $(installData)
uninstall-hook:
- rm -f "$(prefix)/$(productID)/stepmania"
- rm -f "$(prefix)/$(productID)/GtkModule.so"
+ rm -f "$(DESTDIR)$(prefix)/$(productID)/stepmania"
+ rm -f "$(DESTDIR)$(prefix)/$(productID)/GtkModule.so"
# todo: properly remove data
diff --git a/Themes/_fallback/Languages/pl.ini b/Themes/_fallback/Languages/pl.ini
old mode 100755
new mode 100644
diff --git a/Themes/default/Graphics/LifeMeterBattery lives/_lives 1x10.png b/Themes/default/Graphics/LifeMeterBattery lives/_lives 1x10.png
old mode 100755
new mode 100644
diff --git a/Themes/default/Graphics/LifeMeterBattery lives/default.lua b/Themes/default/Graphics/LifeMeterBattery lives/default.lua
old mode 100755
new mode 100644
diff --git a/Themes/default/Languages/pl.ini b/Themes/default/Languages/pl.ini
old mode 100755
new mode 100644
diff --git a/src/Course.cpp b/src/Course.cpp
index 73528353e0..8b291d7b6a 100644
--- a/src/Course.cpp
+++ b/src/Course.cpp
@@ -404,6 +404,9 @@ bool Course::GetTrailUnsorted( StepsType st, CourseDifficulty cd, Trail &trail )
trail.Init();
// XXX: Why are beginner and challenge excluded here? -Wolfman2000
+ // No idea, probably an obsolete design decision from ITG, removing
+ // exclusion here, but there's some other area that prevents it too. -Kyz
+ /*
switch( cd )
{
case Difficulty_Beginner:
@@ -412,6 +415,7 @@ bool Course::GetTrailUnsorted( StepsType st, CourseDifficulty cd, Trail &trail )
return false;
default: break;
}
+ */
// Construct a new Trail, add it to the cache, then return it.
// Different seed for each course, but the same for the whole round:
@@ -848,9 +852,9 @@ bool Course::CourseHasBestOrWorst() const
{
FOREACH_CONST( CourseEntry, m_vEntries, e )
{
- if( e->iChooseIndex == SongSort_MostPlays && e->iChooseIndex != -1 )
+ if( e->songSort == SongSort_MostPlays && e->iChooseIndex != -1 )
return true;
- if( e->iChooseIndex == SongSort_FewestPlays && e->iChooseIndex != -1 )
+ if( e->songSort == SongSort_FewestPlays && e->iChooseIndex != -1 )
return true;
}
diff --git a/src/GameState.cpp b/src/GameState.cpp
index eb993a701e..370cdb6ef3 100644
--- a/src/GameState.cpp
+++ b/src/GameState.cpp
@@ -2109,6 +2109,11 @@ Difficulty GameState::GetHardestStepsDifficulty() const
return dc;
}
+void GameState::SetNewStageSeed()
+{
+ m_iStageSeed= rand();
+}
+
bool GameState::IsEventMode() const
{
return m_bTemporaryEventMode || PREFSMAN->m_bEventMode;
diff --git a/src/GameState.h b/src/GameState.h
index 3b6bf60345..3c463e0e69 100644
--- a/src/GameState.h
+++ b/src/GameState.h
@@ -117,6 +117,8 @@ public:
int m_iGameSeed, m_iStageSeed;
RString m_sStageGUID;
+ void SetNewStageSeed();
+
/**
* @brief Determine if a second player can join in at this time.
* @return true if a player can still enter the game, false otherwise. */
diff --git a/src/NoteTypes.cpp b/src/NoteTypes.cpp
index b164ab7663..851a981dfe 100644
--- a/src/NoteTypes.cpp
+++ b/src/NoteTypes.cpp
@@ -5,47 +5,47 @@
#include "XmlFile.h"
#include "LocalizedString.h"
-TapNote TAP_EMPTY ( TapNoteType_Empty, TapNoteSubType_Invalid, TapNoteSource_Original, "", 0, -1 );
-TapNote TAP_ORIGINAL_TAP ( TapNoteType_Tap, TapNoteSubType_Invalid, TapNoteSource_Original, "", 0, -1 );
-TapNote TAP_ORIGINAL_LIFT ( TapNoteType_Lift, TapNoteSubType_Invalid, TapNoteSource_Original, "", 0, -1 );
-TapNote TAP_ORIGINAL_HOLD_HEAD ( TapNoteType_HoldHead, TapNoteSubType_Hold, TapNoteSource_Original, "", 0, -1 );
-TapNote TAP_ORIGINAL_ROLL_HEAD ( TapNoteType_HoldHead, TapNoteSubType_Roll, TapNoteSource_Original, "", 0, -1 );
-TapNote TAP_ORIGINAL_MINE ( TapNoteType_Mine, TapNoteSubType_Invalid, TapNoteSource_Original, "", 0, -1 );
-TapNote TAP_ORIGINAL_ATTACK ( TapNoteType_Attack, TapNoteSubType_Invalid, TapNoteSource_Original, "", 0, -1 );
-TapNote TAP_ORIGINAL_AUTO_KEYSOUND ( TapNoteType_AutoKeysound,TapNoteSubType_Invalid, TapNoteSource_Original, "", 0, -1 );
-TapNote TAP_ORIGINAL_FAKE ( TapNoteType_Fake, TapNoteSubType_Invalid, TapNoteSource_Original, "", 0, -1 );
+TapNote TAP_EMPTY ( TapNoteType_Empty, TapNoteSubType_Invalid, TapNoteSource_Original, "", 0, -1 );
+TapNote TAP_ORIGINAL_TAP ( TapNoteType_Tap, TapNoteSubType_Invalid, TapNoteSource_Original, "", 0, -1 );
+TapNote TAP_ORIGINAL_LIFT ( TapNoteType_Lift, TapNoteSubType_Invalid, TapNoteSource_Original, "", 0, -1 );
+TapNote TAP_ORIGINAL_HOLD_HEAD ( TapNoteType_HoldHead, TapNoteSubType_Hold, TapNoteSource_Original, "", 0, -1 );
+TapNote TAP_ORIGINAL_ROLL_HEAD ( TapNoteType_HoldHead, TapNoteSubType_Roll, TapNoteSource_Original, "", 0, -1 );
+TapNote TAP_ORIGINAL_MINE ( TapNoteType_Mine, TapNoteSubType_Invalid, TapNoteSource_Original, "", 0, -1 );
+TapNote TAP_ORIGINAL_ATTACK ( TapNoteType_Attack, TapNoteSubType_Invalid, TapNoteSource_Original, "", 0, -1 );
+TapNote TAP_ORIGINAL_AUTO_KEYSOUND ( TapNoteType_AutoKeysound,TapNoteSubType_Invalid, TapNoteSource_Original, "", 0, -1 );
+TapNote TAP_ORIGINAL_FAKE ( TapNoteType_Fake, TapNoteSubType_Invalid, TapNoteSource_Original, "", 0, -1 );
//TapNote TAP_ORIGINAL_MINE_HEAD ( TapNoteType_HoldHead, TapNoteSubType_Mine, TapNoteSource_Original, "", 0, -1 );
-TapNote TAP_ADDITION_TAP ( TapNoteType_Tap, TapNoteSubType_Invalid, TapNoteSource_Addition, "", 0, -1 );
-TapNote TAP_ADDITION_MINE ( TapNoteType_Mine, TapNoteSubType_Invalid, TapNoteSource_Addition, "", 0, -1 );
+TapNote TAP_ADDITION_TAP ( TapNoteType_Tap, TapNoteSubType_Invalid, TapNoteSource_Addition, "", 0, -1 );
+TapNote TAP_ADDITION_MINE ( TapNoteType_Mine, TapNoteSubType_Invalid, TapNoteSource_Addition, "", 0, -1 );
static const char *TapNoteTypeNames[] = {
- "Empty",
- "Tap",
- "HoldHead",
- "HoldTail",
- "Mine",
- "Lift",
- "Attack",
- "AutoKeySound",
- "Fake",
+ "Empty",
+ "Tap",
+ "HoldHead",
+ "HoldTail",
+ "Mine",
+ "Lift",
+ "Attack",
+ "AutoKeySound",
+ "Fake",
};
XToString( TapNoteType );
XToLocalizedString( TapNoteType );
LuaXType( TapNoteType );
static const char *TapNoteSubTypeNames[] = {
- "Hold",
- "Roll",
- //"Mine",
+ "Hold",
+ "Roll",
+ //"Mine",
};
XToString( TapNoteSubType );
XToLocalizedString( TapNoteSubType );
LuaXType( TapNoteSubType );
static const char *TapNoteSourceNames[] = {
- "Original",
- "Addition",
+ "Original",
+ "Addition",
};
XToString( TapNoteSource );
XToLocalizedString( TapNoteSource );
@@ -127,7 +127,7 @@ static const int ROWS_PER_MEASURE = ROWS_PER_BEAT * BEATS_PER_MEASURE;
* @return the quantized NoteType. */
NoteType GetNoteType( int row )
{
- if( row % (ROWS_PER_MEASURE/4) == 0) return NOTE_TYPE_4TH;
+ if( row % (ROWS_PER_MEASURE/4) == 0) return NOTE_TYPE_4TH;
else if( row % (ROWS_PER_MEASURE/8) == 0) return NOTE_TYPE_8TH;
else if( row % (ROWS_PER_MEASURE/12) == 0) return NOTE_TYPE_12TH;
else if( row % (ROWS_PER_MEASURE/16) == 0) return NOTE_TYPE_16TH;
@@ -200,6 +200,84 @@ float HoldNoteResult::GetLastHeldBeat() const
return NoteRowToBeat(iLastHeldRow);
}
+// lua start
+#include "LuaBinding.h"
+
+/** @brief Allow Lua to have access to the TapNoteResult. */
+class LunaTapNoteResult: public Luna
+{
+public:
+ DEFINE_METHOD(GetTapNoteScore, tns);
+ DEFINE_METHOD(GetTapNoteOffset, fTapNoteOffset);
+ DEFINE_METHOD(GetHidden, bHidden);
+
+ LunaTapNoteResult()
+ {
+ ADD_METHOD( GetTapNoteScore );
+ ADD_METHOD( GetTapNoteOffset );
+ ADD_METHOD( GetHidden );
+ }
+};
+LUA_REGISTER_CLASS( TapNoteResult )
+
+/** @brief Allow Lua to have access to the HoldNoteResult. */
+class LunaHoldNoteResult: public Luna
+{
+public:
+ DEFINE_METHOD(GetHoldNoteScore, hns);
+ DEFINE_METHOD(GetLife, fLife);
+ DEFINE_METHOD(GetOverlappedTime, fOverlappedTime);
+ DEFINE_METHOD(GetLastHeldBeat, GetLastHeldBeat() );
+ DEFINE_METHOD(GetCheckpointsHit, iCheckpointsHit );
+ DEFINE_METHOD(GetCheckpointsMissed, iCheckpointsMissed );
+ DEFINE_METHOD(GetHeld, bHeld );
+ DEFINE_METHOD(GetActive, bActive );
+
+ LunaHoldNoteResult()
+ {
+ ADD_METHOD( GetHoldNoteScore );
+ ADD_METHOD( GetLife );
+ ADD_METHOD( GetOverlappedTime );
+ ADD_METHOD( GetLastHeldBeat );
+ ADD_METHOD( GetCheckpointsHit );
+ ADD_METHOD( GetCheckpointsMissed );
+ ADD_METHOD( GetHeld );
+ ADD_METHOD( GetActive );
+ }
+};
+LUA_REGISTER_CLASS( HoldNoteResult )
+
+/** @brief Allow Lua to have access to the TapNote. */
+class LunaTapNote: public Luna
+{
+public:
+ DEFINE_METHOD( GetTapNoteType, type );
+ DEFINE_METHOD( GetTapNoteSubType, subType );
+ DEFINE_METHOD( GetTapNoteSource, source );
+ DEFINE_METHOD( GetPlayerNumber, pn );
+ DEFINE_METHOD( GetAttackModifiers, sAttackModifiers );
+ DEFINE_METHOD( GetAttackDuration, fAttackDurationSeconds );
+ DEFINE_METHOD( GetKeysoundIndex, iKeysoundIndex );
+ static int GetHoldDuration( T* p, lua_State* L ) { lua_pushnumber(L, NoteRowToBeat(p->iDuration)); return 1; }
+ static int GetTapNoteResult( T* p, lua_State* L ) { p->result.PushSelf(L); return 1; }
+ static int GetHoldNoteResult( T* p, lua_State* L ) { p->HoldResult.PushSelf(L); return 1; }
+
+ LunaTapNote()
+ {
+ ADD_METHOD( GetTapNoteType );
+ ADD_METHOD( GetTapNoteSubType );
+ ADD_METHOD( GetTapNoteSource );
+ ADD_METHOD( GetTapNoteResult );
+ ADD_METHOD( GetPlayerNumber );
+ ADD_METHOD( GetAttackModifiers );
+ ADD_METHOD( GetAttackDuration );
+ ADD_METHOD( GetKeysoundIndex );
+ ADD_METHOD( GetHoldDuration );
+ ADD_METHOD( GetHoldNoteResult );
+ }
+};
+LUA_REGISTER_CLASS( TapNote )
+
/*
* (c) 2001-2004 Chris Danford, Glenn Maynard
* All rights reserved.
diff --git a/src/NoteTypes.h b/src/NoteTypes.h
index 4cabac1e9c..bd9304828d 100644
--- a/src/NoteTypes.h
+++ b/src/NoteTypes.h
@@ -31,6 +31,9 @@ struct TapNoteResult
// XML
XNode* CreateNode() const;
void LoadFromNode( const XNode* pNode );
+
+ // Lua
+ void PushSelf( lua_State *L );
};
/** @brief The result of holding (or letting go of) a hold note. */
struct HoldNoteResult
@@ -73,6 +76,9 @@ struct HoldNoteResult
// XML
XNode* CreateNode() const;
void LoadFromNode( const XNode* pNode );
+
+ // Lua
+ void PushSelf( lua_State *L );
};
/** @brief What is the TapNote's core type? */
@@ -87,8 +93,8 @@ enum TapNoteType
TapNoteType_Attack, /**< Hitting this note causes an attack to take place. */
TapNoteType_AutoKeysound, /**< A special sound is played when this note crosses the target area. */
TapNoteType_Fake, /**< This arrow can't be scored for or against the player. */
- NUM_TapNoteType,
- TapNoteType_Invalid
+ NUM_TapNoteType,
+ TapNoteType_Invalid
};
const RString& TapNoteTypeToString( TapNoteType tnt );
const RString& TapNoteTypeToLocalizedString( TapNoteType tnt );
@@ -97,11 +103,11 @@ LuaDeclareType( TapNoteType );
/** @brief The list of a TapNote's sub types. */
enum TapNoteSubType
{
- TapNoteSubType_Hold, /**< The start of a traditional hold note. */
- TapNoteSubType_Roll, /**< The start of a roll note that must be hit repeatedly. */
- //TapNoteSubType_Mine,
- NUM_TapNoteSubType,
- TapNoteSubType_Invalid
+ TapNoteSubType_Hold, /**< The start of a traditional hold note. */
+ TapNoteSubType_Roll, /**< The start of a roll note that must be hit repeatedly. */
+ //TapNoteSubType_Mine,
+ NUM_TapNoteSubType,
+ TapNoteSubType_Invalid
};
const RString& TapNoteSubTypeToString( TapNoteSubType tnst );
const RString& TapNoteSubTypeToLocalizedString( TapNoteSubType tnst );
@@ -110,10 +116,10 @@ LuaDeclareType( TapNoteSubType );
/** @brief The different places a TapNote could come from. */
enum TapNoteSource
{
- TapNoteSource_Original, /**< This note is part of the original NoteData. */
- TapNoteSource_Addition, /**< This note is additional note added by a transform. */
- NUM_TapNoteSource,
- TapNoteSource_Invalid
+ TapNoteSource_Original, /**< This note is part of the original NoteData. */
+ TapNoteSource_Addition, /**< This note is additional note added by a transform. */
+ NUM_TapNoteSource,
+ TapNoteSource_Invalid
};
const RString& TapNoteSourceToString( TapNoteSource tns );
const RString& TapNoteSourceToLocalizedString( TapNoteSource tns );
@@ -145,11 +151,14 @@ struct TapNote
// also used for hold_head only:
int iDuration;
HoldNoteResult HoldResult;
-
+
// XML
XNode* CreateNode() const;
void LoadFromNode( const XNode* pNode );
+ // Lua
+ void PushSelf( lua_State *L );
+
TapNote(): type(TapNoteType_Empty), subType(TapNoteSubType_Invalid),
source(TapNoteSource_Original), result(), pn(PLAYER_INVALID),
bHopoPossible(false), sAttackModifiers(""), fAttackDurationSeconds(0),
@@ -301,7 +310,7 @@ inline float NoteRowToBeat( int iRow ) { return iRow / (float)ROWS_PER_BEAT; }
* @brief Convert the note row to note row (returns itself).
* @param row the row to convert.
*/
-static inline int ToNoteRow(int row) { return row; }
+static inline int ToNoteRow(int row) { return row; }
/**
* @brief Convert the beat to note row.
@@ -313,7 +322,7 @@ static inline int ToNoteRow(float beat) { return BeatToNoteRow(beat); }
* @brief Convert the note row to beat.
* @param row the row to convert.
*/
-static inline float ToBeat(int row) { return NoteRowToBeat(row); }
+static inline float ToBeat(int row) { return NoteRowToBeat(row); }
/**
* @brief Convert the beat row to beat (return itself).
diff --git a/src/Player.cpp b/src/Player.cpp
index 9c4b6786f3..ea07357e20 100644
--- a/src/Player.cpp
+++ b/src/Player.cpp
@@ -1464,7 +1464,7 @@ void Player::UpdateHoldNotes( int iSongRow, float fDeltaTime, vectorTrace("tap note scoring time.");
TapNote &tn = *vTN[0].pTN;
- SetHoldJudgment( tn.result.tns, tn.HoldResult.hns, iFirstTrackWithMaxEndRow );
+ SetHoldJudgment( tn, iFirstTrackWithMaxEndRow );
HandleHoldScore( tn );
//LOG->Trace("hold result = %s",StringConversion::ToString(tn.HoldResult.hns).c_str());
}
@@ -1914,7 +1914,6 @@ void Player::DoTapScoreNone()
SendComboMessages( iOldCombo, iOldMissCombo );
-
if( m_pLifeMeter )
m_pLifeMeter->HandleTapScoreNone();
// TODO: Remove use of PlayerNumber
@@ -1924,7 +1923,7 @@ void Player::DoTapScoreNone()
if( PENALIZE_TAP_SCORE_NONE )
{
- SetJudgment( TNS_Miss, -1, 0 );
+ SetJudgment( BeatToNoteRow( m_pPlayerState->m_Position.m_fSongBeat ), -1, TAP_EMPTY, TNS_Miss, 0 );
// the ScoreKeeper will subtract points later.
}
}
@@ -1960,7 +1959,7 @@ void Player::ScoreAllActiveHoldsLetGo()
tn.HoldResult.hns = HNS_LetGo;
tn.HoldResult.fLife = 0;
- SetHoldJudgment( tn.result.tns, tn.HoldResult.hns, iTrack );
+ SetHoldJudgment( tn, iTrack );
HandleHoldScore( tn );
}
}
@@ -2796,22 +2795,12 @@ void Player::UpdateJudgedRows()
if (tn.type == TapNoteType_Empty ||
tn.type == TapNoteType_Mine ||
tn.type == TapNoteType_AutoKeysound) continue;
- SetJudgment( tn.result.tns, iTrack, tn.result.fTapNoteOffset );
+ SetJudgment( iRow, iTrack, tn );
}
}
else
{
- vector viColsWithTaps;
- for( int iTrack = 0; iTrack < m_NoteData.GetNumTracks(); ++iTrack )
- {
- const TapNote &tn = m_NoteData.GetTapNote( iTrack, iRow );
- if (tn.type == TapNoteType_Tap || tn.type == TapNoteType_Lift ||
- ( tn.type == TapNoteType_HoldHead && REQUIRE_STEP_ON_HOLD_HEADS ) )
- {
- viColsWithTaps.push_back( iTrack );
- };
- }
- SetJudgment( lastTNR.tns, m_NoteData.GetFirstTrackWithTapOrHoldHead(iRow), lastTNR.fTapNoteOffset, viColsWithTaps );
+ SetJudgment( iRow, m_NoteData.GetFirstTrackWithTapOrHoldHead(iRow), NoteDataWithScoring::LastTapNoteWithResult( m_NoteData, iRow ) );
}
HandleTapRowScore( iRow );
}
@@ -3245,7 +3234,7 @@ void Player::HandleHoldCheckpoint(int iRow,
ChangeLife( iNumHoldsMissedThisRow == 0? TNS_CheckpointHit:TNS_CheckpointMiss );
- SetJudgment( iNumHoldsMissedThisRow == 0? TNS_CheckpointHit:TNS_CheckpointMiss, viColsWithHold[0], 0 );
+ SetJudgment( iRow, viColsWithHold[0], TAP_EMPTY, iNumHoldsMissedThisRow == 0? TNS_CheckpointHit:TNS_CheckpointMiss, 0 );
}
void Player::HandleHoldScore( const TapNote &tn )
@@ -3330,7 +3319,7 @@ void Player::SetMineJudgment( TapNoteScore tns , int iTrack )
}
}
-void Player::SetJudgment( TapNoteScore tns, int iTrack, float fTapNoteOffset, vector viCols )
+void Player::SetJudgment( int iRow, int iTrack, const TapNote &tn, TapNoteScore tns, float fTapNoteOffset )
{
if( m_bSendJudgmentAndComboMessages )
{
@@ -3340,17 +3329,44 @@ void Player::SetJudgment( TapNoteScore tns, int iTrack, float fTapNoteOffset, ve
msg.SetParam( "FirstTrack", iTrack );
msg.SetParam( "TapNoteScore", tns );
msg.SetParam( "Early", fTapNoteOffset < 0.0f );
- msg.SetParam( "TapNoteOffset", fTapNoteOffset );
- msg.SetParam( "Tracks" , viCols );
+ msg.SetParam( "TapNoteOffset", tn.result.fTapNoteOffset );
+
+ Lua* L= LUA->Get();
+ lua_createtable( L, 0, m_NoteData.GetNumTracks() ); // TapNotes this row
+ lua_createtable( L, 0, m_NoteData.GetNumTracks() ); // HoldHeads of tracks held at this row.
+
+ for( int iTrack = 0; iTrack < m_NoteData.GetNumTracks(); ++iTrack )
+ {
+ NoteData::iterator tn = m_NoteData.FindTapNote(iTrack, iRow);
+ if( tn != m_NoteData.end(iTrack) )
+ {
+ tn->second.PushSelf(L);
+ lua_rawseti(L, -3, iTrack + 1);
+ }
+ else
+ {
+ int iHeadRow;
+ if( m_NoteData.IsHoldNoteAtRow( iTrack, iRow, &iHeadRow ) )
+ {
+ NoteData::iterator hold = m_NoteData.FindTapNote(iTrack, iHeadRow);
+ hold->second.PushSelf(L);
+ lua_rawseti(L, -2, iTrack + 1);
+ }
+ }
+ }
+ msg.SetParamFromStack( L, "Holds" );
+ msg.SetParamFromStack( L, "Notes" );
+
+ LUA->Release( L );
MESSAGEMAN->Broadcast( msg );
}
}
-void Player::SetHoldJudgment( TapNoteScore tns, HoldNoteScore hns, int iTrack )
+void Player::SetHoldJudgment( TapNote &tn, int iTrack )
{
ASSERT( iTrack < (int)m_vpHoldJudgment.size() );
if( m_vpHoldJudgment[iTrack] )
- m_vpHoldJudgment[iTrack]->SetHoldJudgment( hns );
+ m_vpHoldJudgment[iTrack]->SetHoldJudgment( tn.HoldResult.hns );
if( m_bSendJudgmentAndComboMessages )
{
@@ -3359,8 +3375,13 @@ void Player::SetHoldJudgment( TapNoteScore tns, HoldNoteScore hns, int iTrack )
msg.SetParam( "MultiPlayer", m_pPlayerState->m_mp );
msg.SetParam( "FirstTrack", iTrack );
msg.SetParam( "NumTracks", (int)m_vpHoldJudgment.size() );
- msg.SetParam( "TapNoteScore", tns );
- msg.SetParam( "HoldNoteScore", hns );
+ msg.SetParam( "TapNoteScore", tn.result.tns );
+ msg.SetParam( "HoldNoteScore", tn.HoldResult.hns );
+
+ Lua* L = LUA->Get();
+ tn.PushSelf(L);
+ msg.SetParamFromStack( L, "TapNote" );
+
MESSAGEMAN->Broadcast( msg );
}
}
diff --git a/src/Player.h b/src/Player.h
index a4b8b486f5..9d75b98235 100644
--- a/src/Player.h
+++ b/src/Player.h
@@ -132,9 +132,9 @@ protected:
void PlayKeysound( const TapNote &tn, TapNoteScore score );
void SetMineJudgment( TapNoteScore tns , int iTrack );
- void SetJudgment( TapNoteScore tns, int iFirstTrack, float fTapNoteOffset ) { vector viCols (1,iFirstTrack); SetJudgment( tns, iFirstTrack, fTapNoteOffset, viCols ); }
- void SetJudgment( TapNoteScore tns, int iFirstTrack, float fTapNoteOffset, vector viCols ); // -1 if no track as in TNS_Miss
- void SetHoldJudgment( TapNoteScore tns, HoldNoteScore hns, int iTrack );
+ void SetJudgment( int iRow, int iFirstTrack, const TapNote &tn ) { SetJudgment( iRow, iFirstTrack, tn, tn.result.tns, tn.result.fTapNoteOffset ); }
+ void SetJudgment( int iRow, int iFirstTrack, const TapNote &tn, TapNoteScore tns, float fTapNoteOffset ); // -1 if no track as in TNS_Miss
+ void SetHoldJudgment( TapNote &tn, int iTrack );
void SetCombo( int iCombo, int iMisses );
void ChangeLife( TapNoteScore tns );
diff --git a/src/ScreenGameplay.cpp b/src/ScreenGameplay.cpp
index aff5d2b36a..2c1a96e36e 100644
--- a/src/ScreenGameplay.cpp
+++ b/src/ScreenGameplay.cpp
@@ -2618,6 +2618,72 @@ void ScreenGameplay::HandleScreenMessage( const ScreenMessage SM )
pi->m_pLifeMeter->OnSongEnded();
}
+ // If this is a repeating course, and we're at the end of it, repick and
+ // add new songs to the players' step and song queues.
+ if(GAMESTATE->IsCourseMode() && GAMESTATE->m_pCurCourse &&
+ GAMESTATE->m_pCurCourse->m_bRepeat &&
+ GAMESTATE->GetCourseSongIndex() >= (int)m_apSongsQueue.size()-1)
+ {
+ Course* course= GAMESTATE->m_pCurCourse;
+ ASSERT(course != NULL);
+ // Need to store these so they can be used to refetch the players'
+ // trails after they're invalidated.
+ vector trail_sts;
+ vector trail_cds;
+ FOREACH_EnabledPlayerInfo(m_vPlayerInfo, pi)
+ {
+ Trail* trail= GAMESTATE->m_pCurTrail[pi->GetStepsAndTrailIndex()];
+ ASSERT(trail != NULL);
+ trail_sts.push_back(trail->m_StepsType);
+ trail_cds.push_back(trail->m_CourseDifficulty);
+ }
+ // Set a new stage seed so the order will be different.
+ GAMESTATE->SetNewStageSeed();
+ course->InvalidateTrailCache();
+ course->RegenerateNonFixedTrails();
+ size_t info_id= 0; // Can't use the player number in the playerinfo
+ // because it won't match up in 2-player.
+ FOREACH_EnabledPlayerInfo(m_vPlayerInfo, pi)
+ {
+ Trail* trail= course->GetTrail(trail_sts[info_id], trail_cds[info_id]);
+ ASSERT(trail != NULL);
+ GAMESTATE->m_pCurTrail[pi->m_pn].Set(trail);
+ ++info_id;
+ }
+ PlayerNumber master_pn = GAMESTATE->GetMasterPlayerNumber();
+ Trail *master_trail= GAMESTATE->m_pCurTrail[master_pn];
+ ASSERT(master_trail != NULL);
+ FOREACH_CONST(TrailEntry, master_trail->m_vEntries, entry)
+ {
+ ASSERT(entry->pSong != NULL);
+ m_apSongsQueue.push_back(entry->pSong);
+ STATSMAN->m_CurStageStats.m_vpPossibleSongs.push_back(entry->pSong);
+ }
+ FOREACH_EnabledPlayerInfo(m_vPlayerInfo, pi)
+ {
+ Trail* trail= GAMESTATE->m_pCurTrail[pi->GetStepsAndTrailIndex()];
+ ASSERT(trail != NULL);
+ FOREACH_CONST(TrailEntry, trail->m_vEntries, entry)
+ {
+ ASSERT(entry->pSteps != NULL);
+ pi->m_vpStepsQueue.push_back(entry->pSteps);
+ AttackArray a;
+ entry->GetAttackArray(a);
+ pi->m_asModifiersQueue.push_back(a);
+ pi->GetPlayerStageStats()->m_vpPossibleSteps.push_back(entry->pSteps);
+ }
+ // In a survival course, override stored mods
+ if(course->GetCourseType() == COURSE_TYPE_SURVIVAL &&
+ SURVIVAL_MOD_OVERRIDE)
+ {
+ pi->GetPlayerState()->m_PlayerOptions.FromString(ModsLevel_Stage,
+ "clearall," + CommonMetrics::DEFAULT_NOTESKIN_NAME.GetValue() +
+ "," + CommonMetrics::DEFAULT_MODIFIERS.GetValue());
+ pi->GetPlayerState()->RebuildPlayerOptionsFromActiveAttacks();
+ }
+ }
+ }
+
GAMESTATE->m_bLoadingNextSong = true;
MESSAGEMAN->Broadcast( "BeforeLoadingNextCourseSong" );
m_NextSong.Reset();