This commit is contained in:
zardoru
2015-01-28 14:41:30 -03:00
325 changed files with 6353 additions and 1239 deletions
+66 -4
View File
@@ -164,6 +164,7 @@ Actor::Actor()
m_size = RageVector2( 1, 1 );
InitState();
m_pParent = NULL;
m_FakeParent= NULL;
m_bFirstUpdate = true;
}
@@ -183,6 +184,7 @@ Actor::Actor( const Actor &cpy ):
#define CPY(x) x = cpy.x
CPY( m_sName );
CPY( m_pParent );
CPY( m_FakeParent );
CPY( m_pLuaInstance );
CPY( m_baseRotation );
@@ -279,24 +281,56 @@ void Actor::LoadFromNode( const XNode* pNode )
PlayCommandNoRecurse( Message("Init") );
}
bool Actor::PartiallyOpaque()
{
return m_pTempState->diffuse[0].a > 0 || m_pTempState->diffuse[1].a > 0 ||
m_pTempState->diffuse[2].a > 0 || m_pTempState->diffuse[3].a > 0 ||
m_pTempState->glow.a > 0;
}
void Actor::Draw()
{
if( !m_bVisible ||
m_fHibernateSecondsLeft > 0 ||
this->EarlyAbortDraw() )
{
return; // early abort
}
bool fake_parent_partially_opaque= true;
if(m_FakeParent)
{
if(!m_FakeParent->m_bVisible || m_FakeParent->m_fHibernateSecondsLeft > 0
|| m_FakeParent->EarlyAbortDraw())
{
return;
}
m_FakeParent->PreDraw();
fake_parent_partially_opaque= m_FakeParent->PartiallyOpaque();
}
this->PreDraw();
ASSERT( m_pTempState != NULL );
if( m_pTempState->diffuse[0].a > 0 || m_pTempState->diffuse[1].a > 0 || m_pTempState->diffuse[2].a > 0 || m_pTempState->diffuse[3].a > 0 || m_pTempState->glow.a > 0 ) // This Actor is not fully transparent
{
if(PartiallyOpaque() && fake_parent_partially_opaque)
{
if(m_FakeParent)
{
m_FakeParent->BeginDraw();
}
// call the most-derived versions
this->BeginDraw();
this->DrawPrimitives(); // call the most-derived version of DrawPrimitives();
this->EndDraw();
if(m_FakeParent)
{
m_FakeParent->EndDraw();
}
}
this->PostDraw();
if(m_FakeParent)
{
m_FakeParent->PostDraw();
}
m_pTempState = NULL;
}
@@ -1300,9 +1334,9 @@ void Actor::QueueMessage( const RString& sMessageName )
TI.m_sCommandName = "!" + sMessageName;
}
void Actor::AddCommand( const RString &sCmdName, apActorCommands apac )
void Actor::AddCommand( const RString &sCmdName, apActorCommands apac, bool warn )
{
if( HasCommand(sCmdName) )
if( HasCommand(sCmdName) && warn)
{
RString sWarning = GetLineage()+"'s command '"+sCmdName+"' defined twice";
LuaHelpers::ReportScriptError(sWarning, "COMMAND_DEFINED_TWICE");
@@ -1705,6 +1739,32 @@ public:
pParent->PushSelf(L);
return 1;
}
static int GetFakeParent(T* p, lua_State *L)
{
Actor* fake= p->GetFakeParent();
if(fake == NULL)
{
lua_pushnil(L);
}
else
{
fake->PushSelf(L);
}
return 1;
}
static int SetFakeParent(T* p, lua_State* L)
{
if(lua_isnoneornil(L, 1))
{
p->SetFakeParent(NULL);
}
else
{
Actor* fake= Luna<Actor>::check(L, 1);
p->SetFakeParent(fake);
}
COMMON_RETURN_SELF;
}
static int Draw( T* p, lua_State *L )
{
LUA->YieldLua();
@@ -1876,6 +1936,8 @@ public:
ADD_METHOD( GetName );
ADD_METHOD( GetParent );
ADD_METHOD( GetFakeParent );
ADD_METHOD( SetFakeParent );
ADD_METHOD( Draw );
}
+10 -1
View File
@@ -232,6 +232,8 @@ public:
float aux;
};
// PartiallyOpaque broken out of Draw for reuse and clarity.
bool PartiallyOpaque();
/**
* @brief Calls multiple functions for drawing the Actors.
*
@@ -305,6 +307,9 @@ public:
* @return the Actor's lineage. */
RString GetLineage() const;
void SetFakeParent(Actor* mailman) { m_FakeParent= mailman; }
Actor* GetFakeParent() { return m_FakeParent; }
/**
* @brief Retrieve the Actor's x position.
* @return the Actor's x position. */
@@ -577,7 +582,7 @@ public:
virtual void PushContext( lua_State *L );
// Named commands
void AddCommand( const RString &sCmdName, apActorCommands apac );
void AddCommand( const RString &sCmdName, apActorCommands apac, bool warn= true );
bool HasCommand( const RString &sCmdName ) const;
const apActorCommands *GetCommand( const RString &sCommandName ) const;
void PlayCommand( const RString &sCommandName ) { HandleMessage( Message(sCommandName) ); } // convenience
@@ -607,6 +612,10 @@ protected:
RString m_sName;
/** @brief the current parent of this Actor if it exists. */
Actor *m_pParent;
// m_FakeParent exists to provide a way to render the actor inside another's
// state without making that actor the parent. It's like having multiple
// parents. -Kyz
Actor* m_FakeParent;
/** @brief Some general information about the Tween. */
struct TweenInfo
+84
View File
@@ -7,6 +7,7 @@
#include "RageLog.h"
#include "RageDisplay.h"
#include "RageTexture.h"
#include "RageTimer.h"
#include "RageUtil.h"
#include "ActorUtil.h"
#include "Foreach.h"
@@ -62,6 +63,12 @@ ActorMultiVertex::ActorMultiVertex()
_EffectMode = EffectMode_Normal;
_TextureMode = TextureMode_Modulate;
_splines.resize(num_vert_splines);
for(size_t i= 0; i < num_vert_splines; ++i)
{
_splines[i].redimension(3);
_splines[i].m_owned_by_actor= true;
}
}
ActorMultiVertex::~ActorMultiVertex()
@@ -78,6 +85,7 @@ ActorMultiVertex::ActorMultiVertex( const ActorMultiVertex &cpy ):
CPY( AMV_start );
CPY( _EffectMode );
CPY( _TextureMode );
CPY( _splines );
#undef CPY
if( cpy._Texture != NULL )
@@ -309,6 +317,62 @@ bool ActorMultiVertex::EarlyAbortDraw() const
return false;
}
void ActorMultiVertex::SetVertsFromSplinesInternal(size_t num_splines, size_t offset)
{
vector<RageSpriteVertex>& verts= AMV_DestTweenState().vertices;
size_t first= AMV_DestTweenState().FirstToDraw + offset;
size_t num_verts= AMV_DestTweenState().GetSafeNumToDraw(AMV_DestTweenState()._DrawMode, AMV_DestTweenState().NumToDraw) - offset;
vector<float> tper(num_splines, 0.0f);
float num_parts= static_cast<float>(num_verts) /
static_cast<float>(num_splines);
for(size_t i= 0; i < num_splines; ++i)
{
tper[i]= _splines[i].get_max_t() / num_parts;
}
for(size_t v= 0; v < num_verts; ++v)
{
vector<float> pos;
const int spi= v%num_splines;
float part= static_cast<float>(v/num_splines);
_splines[spi].evaluate(part * tper[spi], pos);
verts[v+first].p.x= pos[0];
verts[v+first].p.y= pos[1];
verts[v+first].p.z= pos[2];
}
}
void ActorMultiVertex::SetVertsFromSplines()
{
if(AMV_DestTweenState().vertices.empty()) { return; }
switch(AMV_DestTweenState()._DrawMode)
{
case DrawMode_Quads:
SetVertsFromSplinesInternal(4, 0);
break;
case DrawMode_QuadStrip:
case DrawMode_Strip:
SetVertsFromSplinesInternal(2, 0);
break;
case DrawMode_Fan:
// Skip the first vert because it is the center of the fan. -Kyz
SetVertsFromSplinesInternal(1, 1);
break;
case DrawMode_Triangles:
case DrawMode_SymmetricQuadStrip:
SetVertsFromSplinesInternal(3, 0);
break;
case DrawMode_LineStrip:
SetVertsFromSplinesInternal(1, 0);
break;
}
}
CubicSplineN* ActorMultiVertex::GetSpline(size_t i)
{
ASSERT(i < num_vert_splines);
return &(_splines[i]);
}
void ActorMultiVertex::SetCurrentTweenStart()
{
AMV_start= AMV_current;
@@ -638,6 +702,23 @@ public:
COMMON_RETURN_SELF;
}
static int GetSpline(T* p, lua_State* L)
{
size_t i= static_cast<size_t>(IArg(1)-1);
if(i >= ActorMultiVertex::num_vert_splines)
{
luaL_error(L, "Spline index must be greater than 0 and less than or equal to %zu.", ActorMultiVertex::num_vert_splines);
}
p->GetSpline(i)->PushSelf(L);
return 1;
}
static int SetVertsFromSplines(T* p, lua_State* L)
{
p->SetVertsFromSplines();
COMMON_RETURN_SELF;
}
static int SetTexture( T* p, lua_State *L )
{
RageTexture *Texture = Luna<RageTexture>::check(L, 1);
@@ -679,6 +760,9 @@ public:
ADD_METHOD( GetCurrFirstToDraw );
ADD_METHOD( GetCurrNumToDraw );
ADD_METHOD( GetSpline );
ADD_METHOD( SetVertsFromSplines );
// Copy from RageTexture
ADD_METHOD( SetTexture );
ADD_METHOD( GetTexture );
+14 -1
View File
@@ -1,7 +1,9 @@
/** @brief ActorMultiVertex - A texture created from multiple textures. */
#include "Actor.h"
#include "CubicSpline.h"
#include "RageDisplay.h"
#include "RageMath.h"
#include "RageTextureID.h"
enum DrawMode
@@ -26,6 +28,7 @@ class RageTexture;
class ActorMultiVertex: public Actor
{
public:
static const size_t num_vert_splines= 4;
ActorMultiVertex();
ActorMultiVertex( const ActorMultiVertex &cpy );
virtual ~ActorMultiVertex();
@@ -35,7 +38,9 @@ public:
struct AMV_TweenState
{
AMV_TweenState(): _DrawMode(DrawMode_Invalid), FirstToDraw(0), NumToDraw(-1), line_width(1.0f) {}
AMV_TweenState(): _DrawMode(DrawMode_Invalid), FirstToDraw(0),
NumToDraw(-1), line_width(1.0f)
{}
static void MakeWeightedAverage(AMV_TweenState& average_out, const AMV_TweenState& ts1, const AMV_TweenState& ts2, float percent_between);
bool operator==(const AMV_TweenState& other) const;
bool operator!=(const AMV_TweenState& other) const { return !operator==(other); }
@@ -102,6 +107,10 @@ public:
void SetVertexColor( int index , RageColor c );
void SetVertexCoords( int index , float TexCoordX , float TexCoordY );
inline void SetVertsFromSplinesInternal(size_t num_splines, size_t start_vert);
void SetVertsFromSplines();
CubicSplineN* GetSpline(size_t i);
virtual void PushSelf( lua_State *L );
private:
@@ -117,6 +126,10 @@ private:
EffectMode _EffectMode;
TextureMode _TextureMode;
// Four splines for controlling vert positions, because quads drawmode
// requires four. -Kyz
vector<CubicSplineN> _splines;
};
/**
+14 -13
View File
@@ -82,16 +82,16 @@ namespace
void ArrowEffects::Update()
{
const Style* pStyle = GAMESTATE->GetCurrentStyle();
static float fLastTime = 0;
float fTime = RageTimer::GetTimeSinceStartFast();
FOREACH_EnabledPlayer( pn )
{
const Style* pStyle = GAMESTATE->GetCurrentStyle(pn);
const Style::ColumnInfo* pCols = pStyle->m_ColumnInfo[pn];
const SongPosition &position = GAMESTATE->m_bIsUsingStepTiming
? GAMESTATE->m_pPlayerState[pn]->m_Position : GAMESTATE->m_Position;
const float field_zoom= GAMESTATE->m_pPlayerState[pn]->m_NotefieldZoom;
PerPlayerData &data = g_EffectData[pn];
@@ -127,8 +127,8 @@ void ArrowEffects::Update()
for( int i=iStartCol; i<=iEndCol; i++ )
{
data.m_fMinTornadoX[iColNum] = min( data.m_fMinTornadoX[iColNum], pCols[i].fXOffset );
data.m_fMaxTornadoX[iColNum] = max( data.m_fMaxTornadoX[iColNum], pCols[i].fXOffset );
data.m_fMinTornadoX[iColNum] = min( data.m_fMinTornadoX[iColNum], pCols[i].fXOffset * field_zoom );
data.m_fMaxTornadoX[iColNum] = max( data.m_fMaxTornadoX[iColNum], pCols[i].fXOffset * field_zoom);
}
}
@@ -439,7 +439,7 @@ float ArrowEffects::GetXPos( const PlayerState* pPlayerState, int iColNum, float
{
float fPixelOffsetFromCenter = 0; // fill this in below
const Style* pStyle = GAMESTATE->GetCurrentStyle();
const Style* pStyle = GAMESTATE->GetCurrentStyle(pPlayerState->m_PlayerNumber);
const float* fEffects = pPlayerState->m_PlayerOptions.GetCurrent().m_fEffects;
// TODO: Don't index by PlayerNumber.
@@ -448,7 +448,7 @@ float ArrowEffects::GetXPos( const PlayerState* pPlayerState, int iColNum, float
if( fEffects[PlayerOptions::EFFECT_TORNADO] != 0 )
{
const float fRealPixelOffset = pCols[iColNum].fXOffset;
const float fRealPixelOffset = pCols[iColNum].fXOffset * pPlayerState->m_NotefieldZoom;
const float fPositionBetween = SCALE( fRealPixelOffset, data.m_fMinTornadoX[iColNum], data.m_fMaxTornadoX[iColNum],
TORNADO_POSITION_SCALE_TO_LOW, TORNADO_POSITION_SCALE_TO_HIGH );
float fRads = acosf( fPositionBetween );
@@ -469,8 +469,8 @@ float ArrowEffects::GetXPos( const PlayerState* pPlayerState, int iColNum, float
const int iFirstCol = 0;
const int iLastCol = pStyle->m_iColsPerPlayer-1;
const int iNewCol = SCALE( iColNum, iFirstCol, iLastCol, iLastCol, iFirstCol );
const float fOldPixelOffset = pCols[iColNum].fXOffset;
const float fNewPixelOffset = pCols[iNewCol].fXOffset;
const float fOldPixelOffset = pCols[iColNum].fXOffset * pPlayerState->m_NotefieldZoom;
const float fNewPixelOffset = pCols[iNewCol].fXOffset * pPlayerState->m_NotefieldZoom;
const float fDistance = fNewPixelOffset - fOldPixelOffset;
fPixelOffsetFromCenter += fDistance * fEffects[PlayerOptions::EFFECT_FLIP];
}
@@ -515,7 +515,7 @@ float ArrowEffects::GetXPos( const PlayerState* pPlayerState, int iColNum, float
}
}
fPixelOffsetFromCenter += pCols[iColNum].fXOffset;
fPixelOffsetFromCenter += pCols[iColNum].fXOffset * pPlayerState->m_NotefieldZoom;
if( fEffects[PlayerOptions::EFFECT_TINY] != 0 )
{
@@ -764,10 +764,11 @@ bool ArrowEffects::NeedZBuffer( const PlayerState* pPlayerState )
float ArrowEffects::GetZoom( const PlayerState* pPlayerState )
{
float fZoom = 1.0f;
// FIXME: Move the zoom values into Style
if( GAMESTATE->GetCurrentStyle()->m_bNeedsZoomOutWith2Players &&
(GAMESTATE->GetNumSidesJoined()==2 || GAMESTATE->AnyPlayersAreCpu()) )
fZoom *= 0.6f;
// Design change: Instead of having a flag in the style that toggles a
// fixed zoom (0.6) that is only applied to the columns, ScreenGameplay now
// calculates a zoom factor to apply to the notefield and puts it in the
// PlayerState. -Kyz
fZoom*= pPlayerState->m_NotefieldZoom;
float fTinyPercent = pPlayerState->m_PlayerOptions.GetCurrent().m_fEffects[PlayerOptions::EFFECT_TINY];
if( fTinyPercent != 0 )
+8
View File
@@ -19,6 +19,14 @@ public:
return GetYOffset( pPlayerState, iCol, fNoteBeat, fThrowAway, bThrowAway, bAbsolute );
}
static void GetXYZPos(const PlayerState* player_state, int col, float y_offset, float y_reverse_offset, vector<float>& ret, bool with_reverse= true)
{
ASSERT(ret.size() == 3);
ret[0]= GetXPos(player_state, col, y_offset);
ret[1]= GetYPos(player_state, col, y_offset, y_reverse_offset, with_reverse);
ret[2]= GetZPos(player_state, col, y_offset);
}
/**
* @brief Retrieve the actual display position.
*
+3 -3
View File
@@ -213,9 +213,9 @@ void BPMDisplay::SetBpmFromSteps( const Steps* pSteps )
void BPMDisplay::SetBpmFromCourse( const Course* pCourse )
{
ASSERT( pCourse != NULL );
ASSERT( GAMESTATE->GetCurrentStyle() != NULL );
ASSERT( GAMESTATE->GetCurrentStyle(PLAYER_INVALID) != NULL );
StepsType st = GAMESTATE->GetCurrentStyle()->m_StepsType;
StepsType st = GAMESTATE->GetCurrentStyle(PLAYER_INVALID)->m_StepsType;
Trail *pTrail = pCourse->GetTrail( st );
// GetTranslitFullTitle because "Crashinfo.txt is garbled because of the ANSI output as usual." -f
ASSERT_M( pTrail != NULL, ssprintf("Course '%s' has no trail for StepsType '%s'", pCourse->GetTranslitFullTitle().c_str(), StringConversion::ToString(st).c_str() ) );
@@ -259,7 +259,7 @@ void BPMDisplay::SetFromGameState()
}
if( GAMESTATE->m_pCurCourse.Get() )
{
if( GAMESTATE->GetCurrentStyle() == NULL )
if( GAMESTATE->GetCurrentStyle(PLAYER_INVALID) == NULL )
; // This is true when backing out from ScreenSelectCourse to ScreenTitleMenu. So, don't call SetBpmFromCourse where an assert will fire.
else
SetBpmFromCourse( GAMESTATE->m_pCurCourse );
+1 -1
View File
@@ -205,7 +205,7 @@ void BackgroundImpl::Init()
{
bOneOrMoreChars = true;
// Disable dancing characters if Beginner Helper will be showing.
if( PREFSMAN->m_bShowBeginnerHelper && BeginnerHelper::CanUse() &&
if( PREFSMAN->m_bShowBeginnerHelper && BeginnerHelper::CanUse(p) &&
GAMESTATE->m_pCurSteps[p] && GAMESTATE->m_pCurSteps[p]->GetDifficulty() == Difficulty_Beginner )
bShowingBeginnerHelper = true;
}
+11 -4
View File
@@ -78,7 +78,7 @@ BeginnerHelper::~BeginnerHelper()
bool BeginnerHelper::Init( int iDancePadType )
{
ASSERT( !m_bInitialized );
if( !CanUse() )
if( !CanUse(PLAYER_INVALID) )
return false;
// If no players were successfully added, bail.
@@ -200,7 +200,7 @@ void BeginnerHelper::AddPlayer( PlayerNumber pn, const NoteData &ns )
ASSERT( pn >= 0 && pn < NUM_PLAYERS );
ASSERT( GAMESTATE->IsHumanPlayer(pn) );
if( !CanUse() )
if( !CanUse(pn) )
return;
const Character *Character = GAMESTATE->m_pCurCharacters[pn];
@@ -212,13 +212,20 @@ void BeginnerHelper::AddPlayer( PlayerNumber pn, const NoteData &ns )
m_bPlayerEnabled[pn] = true;
}
bool BeginnerHelper::CanUse()
bool BeginnerHelper::CanUse(PlayerNumber pn)
{
for (int i=0; i<NUM_ANIMATIONS; ++i )
if( !DoesFileExist(GetAnimPath((Animation)i)) )
return false;
return GAMESTATE->GetCurrentStyle()->m_bCanUseBeginnerHelper;
// This does not pass PLAYER_INVALID to GetCurrentStyle because that would
// only check the first non-NULL style. Both styles need to be checked. -Kyz
if(pn == PLAYER_INVALID)
{
return GAMESTATE->GetCurrentStyle(PLAYER_1)->m_bCanUseBeginnerHelper ||
GAMESTATE->GetCurrentStyle(PLAYER_2)->m_bCanUseBeginnerHelper;
}
return GAMESTATE->GetCurrentStyle(pn)->m_bCanUseBeginnerHelper;
}
void BeginnerHelper::DrawPrimitives()
+1 -1
View File
@@ -18,7 +18,7 @@ public:
bool Init( int iDancePadType );
bool IsInitialized() { return m_bInitialized; }
static bool CanUse();
static bool CanUse(PlayerNumber pn);
void AddPlayer( PlayerNumber pn, const NoteData &nd );
void ShowStepCircle( PlayerNumber pn, int CSTEP );
bool m_bShowBackground;
+5 -5
View File
@@ -95,14 +95,14 @@ void CourseUtil::SortCoursePointerArrayByDifficulty( vector<Course*> &vpCoursesI
void CourseUtil::SortCoursePointerArrayByRanking( vector<Course*> &vpCoursesInOut )
{
for( unsigned i=0; i<vpCoursesInOut.size(); i++ )
vpCoursesInOut[i]->UpdateCourseStats( GAMESTATE->GetCurrentStyle()->m_StepsType );
vpCoursesInOut[i]->UpdateCourseStats( GAMESTATE->GetCurrentStyle(PLAYER_INVALID)->m_StepsType );
sort( vpCoursesInOut.begin(), vpCoursesInOut.end(), CompareCoursePointersByRanking );
}
void CourseUtil::SortCoursePointerArrayByTotalDifficulty( vector<Course*> &vpCoursesInOut )
{
for( unsigned i=0; i<vpCoursesInOut.size(); i++ )
vpCoursesInOut[i]->UpdateCourseStats( GAMESTATE->GetCurrentStyle()->m_StepsType );
vpCoursesInOut[i]->UpdateCourseStats( GAMESTATE->GetCurrentStyle(PLAYER_INVALID)->m_StepsType );
sort( vpCoursesInOut.begin(), vpCoursesInOut.end(), CompareCoursePointersByTotalDifficulty );
}
@@ -176,7 +176,7 @@ void CourseUtil::SortCoursePointerArrayByAvgDifficulty( vector<Course*> &vpCours
course_sort_val.clear();
for( unsigned i = 0; i < vpCoursesInOut.size(); ++i )
{
int iMeter = vpCoursesInOut[i]->GetMeter( GAMESTATE->GetCurrentStyle()->m_StepsType, Difficulty_Medium );
int iMeter = vpCoursesInOut[i]->GetMeter( GAMESTATE->GetCurrentStyle(PLAYER_INVALID)->m_StepsType, Difficulty_Medium );
course_sort_val[vpCoursesInOut[i]] = ssprintf( "%06i", iMeter );
}
sort( vpCoursesInOut.begin(), vpCoursesInOut.end(), CompareCoursePointersByTitle );
@@ -448,8 +448,8 @@ bool EditCourseUtil::ValidateEditCourseName( const RString &sAnswer, RString &sE
void EditCourseUtil::UpdateAndSetTrail()
{
ASSERT( GAMESTATE->m_pCurStyle != NULL );
StepsType st = GAMESTATE->m_pCurStyle->m_StepsType;
ASSERT( GAMESTATE->GetCurrentStyle(PLAYER_INVALID) != NULL );
StepsType st = GAMESTATE->GetCurrentStyle(PLAYER_INVALID)->m_StepsType;
Trail *pTrail = NULL;
if( GAMESTATE->m_pCurCourse )
pTrail = GAMESTATE->m_pCurCourse->GetTrailForceRegenCache( st );
+1037
View File
File diff suppressed because it is too large Load Diff
+111
View File
@@ -0,0 +1,111 @@
#ifndef CUBIC_SPLINE_H
#define CUBIC_SPLINE_H
#include <vector>
using std::vector;
struct lua_State;
struct CubicSpline
{
CubicSpline() :m_spatial_extent(0.0f) {}
void solve_looped();
void solve_straight();
void solve_polygonal();
void p_and_tfrac_from_t(float t, bool loop, size_t& p, float& tfrac) const;
float evaluate(float t, bool loop) const;
float evaluate_derivative(float t, bool loop) const;
float evaluate_second_derivative(float t, bool loop) const;
float evaluate_third_derivative(float t, bool loop) const;
void set_point(size_t i, float v);
void set_coefficients(size_t i, float b, float c, float d);
void get_coefficients(size_t i, float& b, float& c, float& d) const;
void set_point_and_coefficients(size_t i, float a, float b, float c, float d);
void get_point_and_coefficients(size_t i, float& a, float& b, float& c, float& d) const;
void resize(size_t s);
size_t size() const;
bool empty() const;
float m_spatial_extent;
private:
bool check_minimum_size();
void prep_inner(size_t last, vector<float>& results);
void set_results(size_t last, vector<float>& diagonals, vector<float>& results);
struct SplinePoint
{
float a, b, c, d;
};
vector<SplinePoint> m_points;
};
struct CubicSplineN
{
CubicSplineN()
:m_owned_by_actor(false), m_loop(false), m_polygonal(false), m_dirty(true)
{}
static void weighted_average(CubicSplineN& out, const CubicSplineN& from,
const CubicSplineN& to, float between);
void solve();
void evaluate(float t, vector<float>& v) const;
void evaluate_derivative(float t, vector<float>& v) const;
void evaluate_second_derivative(float t, vector<float>& v) const;
void evaluate_third_derivative(float t, vector<float>& v) const;
void set_point(size_t i, const vector<float>& v);
void set_coefficients(size_t i, const vector<float>& b,
const vector<float>& c, const vector<float>& d);
void get_coefficients(size_t i, vector<float>& b,
vector<float>& c, vector<float>& d);
void set_spatial_extent(size_t i, float extent);
float get_spatial_extent(size_t i);
void resize(size_t s);
size_t size() const;
void redimension(size_t d);
size_t dimension() const;
bool empty() const;
float get_max_t() const {
if(m_loop) { return static_cast<float>(size()); }
else { return static_cast<float>(size()-1); }
}
typedef vector<CubicSpline> spline_cont_t;
void set_loop(bool l);
bool get_loop() const;
void set_polygonal(bool p);
bool get_polygonal() const;
void set_dirty(bool d);
bool get_dirty() const;
bool m_owned_by_actor;
void PushSelf(lua_State* L);
private:
bool m_loop;
bool m_polygonal;
bool m_dirty;
spline_cont_t m_splines;
};
#endif
// Side note: Actually written between 2014/12/26 and 2014/12/28
/*
* Copyright (c) 2014-2015 Eric Reese
* 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.
*/
+1 -1
View File
@@ -277,7 +277,7 @@ void StepsDisplayList::SetFromGameState()
FOREACH_CONST( Difficulty, difficulties, d )
{
m_Rows[i].m_dc = *d;
m_Lines[i].m_Meter.SetFromStepsTypeAndMeterAndDifficultyAndCourseType( GAMESTATE->m_pCurStyle->m_StepsType, 0, *d, CourseType_Invalid );
m_Lines[i].m_Meter.SetFromStepsTypeAndMeterAndDifficultyAndCourseType( GAMESTATE->GetCurrentStyle(PLAYER_INVALID)->m_StepsType, 0, *d, CourseType_Invalid );
++i;
}
}
+218 -126
View File
@@ -51,6 +51,11 @@ void EditMenu::StripLockedStepsAndDifficulty( vector<StepsAndDifficulty> &v )
void EditMenu::GetSongsToShowForGroup( const RString &sGroup, vector<Song*> &vpSongsOut )
{
if(sGroup == "")
{
vpSongsOut.clear();
return;
}
vpSongsOut = SONGMAN->GetSongs( SHOW_GROUPS.GetValue()? sGroup:GROUP_ALL );
EditMode mode = EDIT_MODE.GetValue();
switch( mode )
@@ -189,6 +194,8 @@ void EditMenu::Load( const RString &sType )
void EditMenu::RefreshAll()
{
if(!SafeToUse()) { return; }
ChangeToRow( GetFirstRow() );
OnRowValueChanged( (EditMenuRow)0 );
@@ -230,6 +237,11 @@ void EditMenu::RefreshAll()
}
}
bool EditMenu::SafeToUse()
{
return !m_sGroups.empty();
}
bool EditMenu::CanGoUp()
{
return m_SelectedRow != GetFirstRow();
@@ -242,6 +254,10 @@ bool EditMenu::CanGoDown()
bool EditMenu::CanGoLeft()
{
if(GetRowSize(m_SelectedRow) <= 0)
{
return false;
}
if( m_SelectedRow == ROW_SONG || m_SelectedRow == ROW_GROUP )
return true; // wraps
return m_iSelection[m_SelectedRow] != 0;
@@ -265,6 +281,10 @@ int EditMenu::GetRowSize( EditMenuRow er ) const
bool EditMenu::CanGoRight()
{
if(GetRowSize(m_SelectedRow) <= 0)
{
return false;
}
if( m_SelectedRow == ROW_SONG || m_SelectedRow == ROW_GROUP )
return true; // wraps
return m_iSelection[m_SelectedRow] != GetRowSize(m_SelectedRow)-1;
@@ -358,6 +378,8 @@ void EditMenu::UpdateArrows()
static LocalizedString BLANK ( "EditMenu", "Blank" );
void EditMenu::OnRowValueChanged( EditMenuRow row )
{
if(!SafeToUse()) { return; }
UpdateArrows();
EditMode mode = EDIT_MODE.GetValue();
@@ -365,69 +387,108 @@ void EditMenu::OnRowValueChanged( EditMenuRow row )
switch( row )
{
case ROW_GROUP:
m_textValue[ROW_GROUP].SetText( SONGMAN->ShortenGroupName(GetSelectedGroup()) );
if( SHOW_GROUPS.GetValue() )
{
m_GroupBanner.LoadFromSongGroup( GetSelectedGroup() );
m_GroupBanner.PlayCommand("Changed");
}
m_pSongs.clear();
if( mode == EditMode_Practice )
if(GetSelectedGroup() == "")
{
m_pSongs.clear();
vector<Song*> vtSongs;
GetSongsToShowForGroup( GetSelectedGroup(), vtSongs );
// Filter out songs that aren't playable.
FOREACH( Song*, vtSongs, s )
if( SongUtil::IsSongPlayable(*s) )
m_pSongs.push_back(*s);
m_textValue[ROW_GROUP].SetText(THEME->GetString(m_sName, "No Group Selected."));
if(SHOW_GROUPS.GetValue())
{
m_GroupBanner.LoadFallback();
m_GroupBanner.PlayCommand("Changed");
}
}
else
GetSongsToShowForGroup( GetSelectedGroup(), m_pSongs );
{
m_textValue[ROW_GROUP].SetText( SONGMAN->ShortenGroupName(GetSelectedGroup()) );
if( SHOW_GROUPS.GetValue() )
{
m_GroupBanner.LoadFromSongGroup(GetSelectedGroup());
m_GroupBanner.PlayCommand("Changed");
}
if( mode == EditMode_Practice )
{
vector<Song*> vtSongs;
GetSongsToShowForGroup(GetSelectedGroup(), vtSongs);
// Filter out songs that aren't playable.
FOREACH(Song*, vtSongs, s)
{
if(SongUtil::IsSongPlayable(*s))
{
m_pSongs.push_back(*s);
}
}
}
else
{
GetSongsToShowForGroup(GetSelectedGroup(), m_pSongs);
}
}
m_iSelection[ROW_SONG] = 0;
// fall through
case ROW_SONG:
m_textValue[ROW_SONG].SetText( "" );
m_SongBanner.LoadFromSong( GetSelectedSong() );
m_SongBanner.PlayCommand("Changed");
m_SongTextBanner.SetFromSong( GetSelectedSong() );
if( mode == EditMode_Practice )
if(GetSelectedSong() == NULL)
{
StepsType orgSel = StepsType_Invalid;
if( !m_StepsTypes.empty() ) // Not first run
m_textValue[ROW_SONG].SetText("");
m_SongBanner.LoadFallback();
m_SongBanner.PlayCommand("Changed");
m_SongTextBanner.SetFromString("", "", "", "", "", "");
if(mode == EditMode_Practice)
{
ASSERT( (int) m_StepsTypes.size() > m_iSelection[ROW_STEPS_TYPE] );
orgSel = m_StepsTypes[m_iSelection[ROW_STEPS_TYPE]];
m_iSelection[ROW_STEPS_TYPE] = 0;
m_StepsTypes.clear();
}
// The StepsType selection may no longer be valid. Zero it for now.
m_iSelection[ROW_STEPS_TYPE] = 0;
m_StepsTypes.clear();
// Only show StepsTypes for which we have valid Steps.
vector<StepsType> vSts = CommonMetrics::STEPS_TYPES_TO_SHOW.GetValue();
FOREACH( StepsType, vSts, st )
}
else
{
m_textValue[ROW_SONG].SetText("");
m_SongBanner.LoadFromSong(GetSelectedSong());
m_SongBanner.PlayCommand("Changed");
m_SongTextBanner.SetFromSong(GetSelectedSong());
if(mode == EditMode_Practice)
{
if( SongUtil::GetStepsByDifficulty( GetSelectedSong(), *st, Difficulty_Invalid, false) != NULL )
m_StepsTypes.push_back( *st );
StepsType orgSel = StepsType_Invalid;
if(!m_StepsTypes.empty()) // Not first run
{
ASSERT( (int) m_StepsTypes.size() > m_iSelection[ROW_STEPS_TYPE] );
orgSel = m_StepsTypes[m_iSelection[ROW_STEPS_TYPE]];
}
// The StepsType selection may no longer be valid. Zero it for now.
m_iSelection[ROW_STEPS_TYPE] = 0;
m_StepsTypes.clear();
// Only show StepsTypes for which we have valid Steps.
vector<StepsType> vSts = CommonMetrics::STEPS_TYPES_TO_SHOW.GetValue();
FOREACH( StepsType, vSts, st )
{
if(SongUtil::GetStepsByDifficulty( GetSelectedSong(), *st, Difficulty_Invalid, false) != NULL)
m_StepsTypes.push_back(*st);
// Try to preserve the user's StepsType selection.
if( *st == orgSel )
// Try to preserve the user's StepsType selection.
if(*st == orgSel)
m_iSelection[ROW_STEPS_TYPE] = m_StepsTypes.size() - 1;
}
}
}
// fall through
case ROW_STEPS_TYPE:
m_textValue[ROW_STEPS_TYPE].SetText( GAMEMAN->GetStepsTypeInfo(GetSelectedStepsType()).GetLocalizedString() );
if(GetSelectedStepsType() == StepsType_Invalid)
{
m_textValue[ROW_STEPS_TYPE].SetText(THEME->GetString(m_sName, "No StepsType selected."));
m_vpSteps.clear();
}
else
{
m_textValue[ROW_STEPS_TYPE].SetText( GAMEMAN->GetStepsTypeInfo(GetSelectedStepsType()).GetLocalizedString() );
Difficulty dcOld = Difficulty_Invalid;
if( !m_vpSteps.empty() )
if(!m_vpSteps.empty())
{
dcOld = GetSelectedDifficulty();
}
m_vpSteps.clear();
@@ -437,60 +498,60 @@ void EditMenu::OnRowValueChanged( EditMenuRow row )
{
switch( mode )
{
case EditMode_Full:
case EditMode_CourseMods:
case EditMode_Practice:
{
vector<Steps*> v;
SongUtil::GetSteps( GetSelectedSong(), v, GetSelectedStepsType(), Difficulty_Edit );
StepsUtil::SortStepsByDescription( v );
FOREACH_CONST( Steps*, v, p )
m_vpSteps.push_back( StepsAndDifficulty(*p,dc) );
}
break;
case EditMode_Home:
// have only "New Edit"
break;
default:
FAIL_M(ssprintf("Invalid edit mode: %i", mode));
case EditMode_Full:
case EditMode_CourseMods:
case EditMode_Practice:
{
vector<Steps*> v;
SongUtil::GetSteps( GetSelectedSong(), v, GetSelectedStepsType(), Difficulty_Edit );
StepsUtil::SortStepsByDescription( v );
FOREACH_CONST( Steps*, v, p )
m_vpSteps.push_back( StepsAndDifficulty(*p,dc) );
}
break;
case EditMode_Home:
// have only "New Edit"
break;
default:
FAIL_M(ssprintf("Invalid edit mode: %i", mode));
}
switch( mode )
{
case EditMode_Practice:
case EditMode_CourseMods:
break;
case EditMode_Home:
case EditMode_Full:
m_vpSteps.push_back( StepsAndDifficulty(NULL,dc) ); // "New Edit"
break;
default:
FAIL_M(ssprintf("Invalid edit mode: %i", mode));
case EditMode_Practice:
case EditMode_CourseMods:
break;
case EditMode_Home:
case EditMode_Full:
m_vpSteps.push_back( StepsAndDifficulty(NULL,dc) ); // "New Edit"
break;
default:
FAIL_M(ssprintf("Invalid edit mode: %i", mode));
}
}
else
{
Steps *pSteps = SongUtil::GetStepsByDifficulty( GetSelectedSong(), GetSelectedStepsType(), dc );
if( pSteps && UNLOCKMAN->StepsIsLocked( GetSelectedSong(), pSteps ) )
pSteps = NULL;
pSteps = NULL;
switch( mode )
{
case EditMode_Home:
// don't allow selecting of non-edits in HomeMode
break;
case EditMode_Practice:
case EditMode_CourseMods:
// only show this difficulty if steps exist
if( pSteps )
case EditMode_Home:
// don't allow selecting of non-edits in HomeMode
break;
case EditMode_Practice:
case EditMode_CourseMods:
// only show this difficulty if steps exist
if( pSteps )
m_vpSteps.push_back( StepsAndDifficulty(pSteps,dc) );
break;
case EditMode_Full:
// show this difficulty whether or not steps exist.
m_vpSteps.push_back( StepsAndDifficulty(pSteps,dc) );
break;
default:
FAIL_M(ssprintf("Invalid edit mode: %i", mode));
break;
case EditMode_Full:
// show this difficulty whether or not steps exist.
m_vpSteps.push_back( StepsAndDifficulty(pSteps,dc) );
break;
default:
FAIL_M(ssprintf("Invalid edit mode: %i", mode));
}
}
}
@@ -504,51 +565,75 @@ void EditMenu::OnRowValueChanged( EditMenuRow row )
break;
}
}
CLAMP( m_iSelection[ROW_STEPS], 0, m_vpSteps.size()-1 );
}
CLAMP( m_iSelection[ROW_STEPS], 0, m_vpSteps.size()-1 );
// fall through
case ROW_STEPS:
if(GetSelectedSteps() == NULL && mode == EditMode_Practice)
{
m_textValue[ROW_STEPS].SetText(THEME->GetString(m_sName, "No Steps selected."));
m_StepsDisplay.Unset();
}
else
{
RString s = CustomDifficultyToLocalizedString( GetCustomDifficulty( GetSelectedStepsType(), GetSelectedDifficulty(), CourseType_Invalid ) );
m_textValue[ROW_STEPS].SetText( s );
}
if( GetSelectedSteps() )
m_StepsDisplay.SetFromSteps( GetSelectedSteps() );
else
m_StepsDisplay.SetFromStepsTypeAndMeterAndDifficultyAndCourseType( GetSelectedSourceStepsType(), 0, GetSelectedDifficulty(), CourseType_Invalid );
// fall through
case ROW_SOURCE_STEPS_TYPE:
m_textLabel[ROW_SOURCE_STEPS_TYPE].SetVisible( GetSelectedSteps() ? false : true );
m_textValue[ROW_SOURCE_STEPS_TYPE].SetVisible( GetSelectedSteps() ? false : true );
m_textValue[ROW_SOURCE_STEPS_TYPE].SetText( GAMEMAN->GetStepsTypeInfo(GetSelectedSourceStepsType()).GetLocalizedString() );
m_vpSourceSteps.clear();
m_vpSourceSteps.push_back( StepsAndDifficulty(NULL,Difficulty_Invalid) ); // "blank"
FOREACH_ENUM( Difficulty, dc )
{
// fill in m_vpSourceSteps
if( dc != Difficulty_Edit )
if( GetSelectedSteps() )
{
Steps *pSteps = SongUtil::GetStepsByDifficulty( GetSelectedSong(), GetSelectedSourceStepsType(), dc );
if( pSteps != NULL )
m_vpSourceSteps.push_back( StepsAndDifficulty(pSteps,dc) );
m_StepsDisplay.SetFromSteps( GetSelectedSteps() );
}
else
{
vector<Steps*> v;
SongUtil::GetSteps( GetSelectedSong(), v, GetSelectedSourceStepsType(), dc );
StepsUtil::SortStepsByDescription( v );
FOREACH_CONST( Steps*, v, pSteps )
m_vpSourceSteps.push_back( StepsAndDifficulty(*pSteps,dc) );
m_StepsDisplay.SetFromStepsTypeAndMeterAndDifficultyAndCourseType( GetSelectedSourceStepsType(), 0, GetSelectedDifficulty(), CourseType_Invalid );
}
}
StripLockedStepsAndDifficulty( m_vpSteps );
CLAMP( m_iSelection[ROW_SOURCE_STEPS], 0, m_vpSourceSteps.size()-1 );
// fall through
case ROW_SOURCE_STEPS_TYPE:
if(mode == EditMode_Practice)
{
m_textLabel[ROW_SOURCE_STEPS_TYPE].SetVisible(false);
m_textValue[ROW_SOURCE_STEPS_TYPE].SetVisible(false);
}
else
{
m_textLabel[ROW_SOURCE_STEPS_TYPE].SetVisible( GetSelectedSteps() ? false : true );
m_textValue[ROW_SOURCE_STEPS_TYPE].SetVisible( GetSelectedSteps() ? false : true );
m_textValue[ROW_SOURCE_STEPS_TYPE].SetText( GAMEMAN->GetStepsTypeInfo(GetSelectedSourceStepsType()).GetLocalizedString() );
m_vpSourceSteps.clear();
m_vpSourceSteps.push_back( StepsAndDifficulty(NULL,Difficulty_Invalid) ); // "blank"
FOREACH_ENUM( Difficulty, dc )
{
// fill in m_vpSourceSteps
if( dc != Difficulty_Edit )
{
Steps *pSteps = SongUtil::GetStepsByDifficulty( GetSelectedSong(), GetSelectedSourceStepsType(), dc );
if( pSteps != NULL )
m_vpSourceSteps.push_back( StepsAndDifficulty(pSteps,dc) );
}
else
{
vector<Steps*> v;
SongUtil::GetSteps( GetSelectedSong(), v, GetSelectedSourceStepsType(), dc );
StepsUtil::SortStepsByDescription( v );
FOREACH_CONST( Steps*, v, pSteps )
m_vpSourceSteps.push_back( StepsAndDifficulty(*pSteps,dc) );
}
}
StripLockedStepsAndDifficulty( m_vpSteps );
CLAMP( m_iSelection[ROW_SOURCE_STEPS], 0, m_vpSourceSteps.size()-1 );
}
// fall through
case ROW_SOURCE_STEPS:
if(mode == EditMode_Practice)
{
m_textLabel[ROW_SOURCE_STEPS].SetVisible(false);
m_textValue[ROW_SOURCE_STEPS].SetVisible(false);
m_Actions.clear();
m_Actions.push_back( EditMenuAction_Practice );
}
else
{
m_textLabel[ROW_SOURCE_STEPS].SetVisible( GetSelectedSteps() ? false : true );
m_textValue[ROW_SOURCE_STEPS].SetVisible( GetSelectedSteps() ? false : true );
@@ -566,11 +651,11 @@ void EditMenu::OnRowValueChanged( EditMenuRow row )
}
bool bHideMeter = false;
if( GetSelectedSourceDifficulty() == Difficulty_Invalid )
bHideMeter = true;
bHideMeter = true;
else if( GetSelectedSourceSteps() )
m_StepsDisplaySource.SetFromSteps( GetSelectedSourceSteps() );
m_StepsDisplaySource.SetFromSteps( GetSelectedSourceSteps() );
else
m_StepsDisplaySource.SetFromStepsTypeAndMeterAndDifficultyAndCourseType( GetSelectedSourceStepsType(), 0, GetSelectedSourceDifficulty(), CourseType_Invalid );
m_StepsDisplaySource.SetFromStepsTypeAndMeterAndDifficultyAndCourseType( GetSelectedSourceStepsType(), 0, GetSelectedSourceDifficulty(), CourseType_Invalid );
m_StepsDisplaySource.SetVisible( !(bHideMeter || GetSelectedSteps()) );
m_Actions.clear();
@@ -578,17 +663,17 @@ void EditMenu::OnRowValueChanged( EditMenuRow row )
{
switch( mode )
{
case EditMode_Practice:
case EditMode_CourseMods:
m_Actions.push_back( EditMenuAction_Practice );
break;
case EditMode_Home:
case EditMode_Full:
m_Actions.push_back( EditMenuAction_Edit );
m_Actions.push_back( EditMenuAction_Delete );
break;
default:
FAIL_M(ssprintf("Invalid edit mode: %i", mode));
case EditMode_Practice:
case EditMode_CourseMods:
m_Actions.push_back( EditMenuAction_Practice );
break;
case EditMode_Home:
case EditMode_Full:
m_Actions.push_back( EditMenuAction_Edit );
m_Actions.push_back( EditMenuAction_Delete );
break;
default:
FAIL_M(ssprintf("Invalid edit mode: %i", mode));
}
}
else
@@ -599,7 +684,14 @@ void EditMenu::OnRowValueChanged( EditMenuRow row )
}
// fall through
case ROW_ACTION:
m_textValue[ROW_ACTION].SetText( EditMenuActionToLocalizedString(GetSelectedAction()) );
if(GetSelectedAction() == EditMenuAction_Invalid)
{
m_textValue[ROW_ACTION].SetText(THEME->GetString(m_sName, "No valid action."));
}
else
{
m_textValue[ROW_ACTION].SetText( EditMenuActionToLocalizedString(GetSelectedAction()) );
}
break;
default:
FAIL_M(ssprintf("Invalid EditMenuRow: %i", row));
+24 -12
View File
@@ -102,74 +102,86 @@ public:
void RefreshAll();
bool SafeToUse();
#define RETURN_IF_INVALID(check, retval) if(check) { return retval; }
/** @brief Retrieve the currently selected group.
* @return the current group. */
RString GetSelectedGroup() const
{
if( !SHOW_GROUPS.GetValue() ) return GROUP_ALL;
int groups = static_cast<int>(m_sGroups.size());
ASSERT_M(m_iSelection[ROW_GROUP] < groups,
ssprintf("Group selection %d < Number of groups %d",
m_iSelection[ROW_GROUP],
groups));
RETURN_IF_INVALID(m_iSelection[ROW_GROUP] >= groups, "");
return m_sGroups[m_iSelection[ROW_GROUP]];
}
/** @brief Retrieve the currently selected song.
* @return the current song. */
Song* GetSelectedSong() const
{
ASSERT(m_iSelection[ROW_SONG] < (int)m_pSongs.size());
RETURN_IF_INVALID(m_pSongs.empty() ||
m_iSelection[ROW_SONG] >= (int)m_pSongs.size(), NULL);
return m_pSongs[m_iSelection[ROW_SONG]];
}
/** @brief Retrieve the currently selected steps type.
* @return the current steps type. */
StepsType GetSelectedStepsType() const
{
ASSERT(m_iSelection[ROW_STEPS_TYPE] < (int)m_StepsTypes.size());
RETURN_IF_INVALID(m_StepsTypes.empty() ||
m_iSelection[ROW_STEPS_TYPE] >= (int)m_StepsTypes.size(), StepsType_Invalid);
return m_StepsTypes[m_iSelection[ROW_STEPS_TYPE]];
}
/** @brief Retrieve the currently selected steps.
* @return the current steps. */
Steps* GetSelectedSteps() const
{
ASSERT(m_iSelection[ROW_STEPS] < (int)m_vpSteps.size());
RETURN_IF_INVALID(m_vpSteps.empty() ||
m_iSelection[ROW_STEPS] >= (int)m_vpSteps.size(), NULL);
return m_vpSteps[m_iSelection[ROW_STEPS]].pSteps;
}
/** @brief Retrieve the currently selected difficulty.
* @return the current difficulty. */
Difficulty GetSelectedDifficulty() const
{
ASSERT(m_iSelection[ROW_STEPS] < (int)m_vpSteps.size());
RETURN_IF_INVALID(m_vpSteps.empty() ||
m_iSelection[ROW_STEPS] >= (int)m_vpSteps.size(), Difficulty_Invalid);
return m_vpSteps[m_iSelection[ROW_STEPS]].dc;
}
/** @brief Retrieve the currently selected source steps type.
* @return the current source steps type. */
StepsType GetSelectedSourceStepsType() const
{
ASSERT(m_iSelection[ROW_SOURCE_STEPS_TYPE] < (int)m_StepsTypes.size());
RETURN_IF_INVALID(m_StepsTypes.empty() ||
m_iSelection[ROW_SOURCE_STEPS_TYPE] >= (int)m_StepsTypes.size(), StepsType_Invalid);
return m_StepsTypes[m_iSelection[ROW_SOURCE_STEPS_TYPE]];
}
/** @brief Retrieve the currently selected source steps.
* @return the current source steps. */
Steps* GetSelectedSourceSteps() const
{
ASSERT(m_iSelection[ROW_SOURCE_STEPS] < (int)m_vpSourceSteps.size());
RETURN_IF_INVALID(m_vpSourceSteps.empty() ||
m_iSelection[ROW_SOURCE_STEPS] >= (int)m_vpSourceSteps.size(), NULL);
return m_vpSourceSteps[m_iSelection[ROW_SOURCE_STEPS]].pSteps;
}
/** @brief Retrieve the currently selected difficulty.
* @return the current difficulty. */
Difficulty GetSelectedSourceDifficulty() const
{
ASSERT(m_iSelection[ROW_SOURCE_STEPS] < (int)m_vpSourceSteps.size());
RETURN_IF_INVALID(m_vpSourceSteps.empty() ||
m_iSelection[ROW_SOURCE_STEPS] >= (int)m_vpSourceSteps.size(), Difficulty_Invalid);
return m_vpSourceSteps[m_iSelection[ROW_SOURCE_STEPS]].dc;
}
/** @brief Retrieve the currently selected action.
* @return the current action. */
EditMenuAction GetSelectedAction() const
{
ASSERT(m_iSelection[ROW_ACTION] < (int)m_Actions.size());
RETURN_IF_INVALID(m_Actions.empty() ||
m_iSelection[ROW_ACTION] >= (int)m_Actions.size(), EditMenuAction_Invalid);
return m_Actions[m_iSelection[ROW_ACTION]];
}
#undef RETURN_IF_INVALID
/** @brief Retrieve the currently selected row.
* @return the current row. */
EditMenuRow GetSelectedRow() const { return m_SelectedRow; }
+2
View File
@@ -62,12 +62,14 @@ public:
static int GetName( T* p, lua_State *L ) { lua_pushstring( L, p->m_szName ); return 1; }
static int CountNotesSeparately( T* p, lua_State *L ) { lua_pushboolean( L, p->m_bCountNotesSeparately ); return 1; }
DEFINE_METHOD( GetMapJudgmentTo, GetMapJudgmentTo(Enum::Check<TapNoteScore>(L, 1)) )
DEFINE_METHOD(GetSeparateStyles, m_PlayersHaveSeparateStyles);
LunaGame()
{
ADD_METHOD( GetName );
ADD_METHOD( CountNotesSeparately );
ADD_METHOD( GetMapJudgmentTo );
ADD_METHOD( GetSeparateStyles );
}
};
+1
View File
@@ -34,6 +34,7 @@ struct Game
/** @brief Do we count multiple notes in a row as separate notes, or as one note? */
bool m_bCountNotesSeparately;
bool m_bTickHolds;
bool m_PlayersHaveSeparateStyles;
InputScheme m_InputScheme;
+5 -5
View File
@@ -84,7 +84,7 @@ bool GameCommand::DescribesCurrentMode( PlayerNumber pn ) const
{
if( m_pm != PlayMode_Invalid && GAMESTATE->m_PlayMode != m_pm )
return false;
if( m_pStyle && GAMESTATE->GetCurrentStyle() != m_pStyle )
if( m_pStyle && GAMESTATE->GetCurrentStyle(pn) != m_pStyle )
return false;
// HACK: don't compare m_dc if m_pSteps is set. This causes problems
// in ScreenSelectOptionsMaster::ImportOptions if m_PreferredDifficulty
@@ -289,7 +289,7 @@ void GameCommand::LoadOne( const Command& cmd )
if( !m_bInvalid )
{
Song *pSong = (m_pSong != NULL)? m_pSong:GAMESTATE->m_pCurSong;
const Style *pStyle = m_pStyle ? m_pStyle : GAMESTATE->GetCurrentStyle();
const Style *pStyle = m_pStyle ? m_pStyle : GAMESTATE->GetCurrentStyle(GAMESTATE->GetMasterPlayerNumber());
if( pSong == NULL || pStyle == NULL )
{
MAKE_INVALID("Must set Song and Style to set Steps.");
@@ -327,7 +327,7 @@ void GameCommand::LoadOne( const Command& cmd )
if( !m_bInvalid )
{
Course *pCourse = (m_pCourse != NULL)? m_pCourse:GAMESTATE->m_pCurCourse;
const Style *pStyle = m_pStyle ? m_pStyle : GAMESTATE->GetCurrentStyle();
const Style *pStyle = m_pStyle ? m_pStyle : GAMESTATE->GetCurrentStyle(GAMESTATE->GetMasterPlayerNumber());
if( pCourse == NULL || pStyle == NULL )
{
MAKE_INVALID("Must set Course and Style to set Trail.");
@@ -598,7 +598,7 @@ bool GameCommand::IsPlayable( RString *why ) const
if( m_pm != PlayMode_Invalid || m_pStyle != NULL )
{
const PlayMode pm = (m_pm != PlayMode_Invalid) ? m_pm : GAMESTATE->m_PlayMode;
const Style *style = (m_pStyle != NULL)? m_pStyle: GAMESTATE->GetCurrentStyle();
const Style *style = (m_pStyle != NULL)? m_pStyle: GAMESTATE->GetCurrentStyle(GAMESTATE->GetMasterPlayerNumber());
if( !AreStyleAndPlayModeCompatible( style, pm ) )
{
if( why )
@@ -705,7 +705,7 @@ void GameCommand::ApplySelf( const vector<PlayerNumber> &vpns ) const
if( m_pStyle != NULL )
{
GAMESTATE->SetCurrentStyle( m_pStyle );
GAMESTATE->SetCurrentStyle( m_pStyle, GAMESTATE->GetMasterPlayerNumber() );
// It's possible to choose a style that didn't have enough players joined.
// If enough players aren't joined, then we need to subtract credits
+4
View File
@@ -104,6 +104,10 @@ enum StepsType
StepsType_popn_five,
StepsType_popn_nine,
StepsType_lights_cabinet,
StepsType_kickbox_human,
StepsType_kickbox_quadarm,
StepsType_kickbox_insect,
StepsType_kickbox_arachnid,
NUM_StepsType, // leave this at the end
StepsType_Invalid,
};
+10
View File
@@ -174,6 +174,16 @@ GameButton StringToGameButton( const InputScheme* pInputs, const RString& s );
#define LIGHTS_BUTTON_BASS_RIGHT GAME_BUTTON_CUSTOM_08
#define NUM_LIGHTS_BUTTONS GAME_BUTTON_CUSTOM_09
#define KICKBOX_BUTTON_DOWN_LEFT_FOOT GAME_BUTTON_CUSTOM_01
#define KICKBOX_BUTTON_UP_LEFT_FOOT GAME_BUTTON_CUSTOM_02
#define KICKBOX_BUTTON_UP_LEFT_FIST GAME_BUTTON_CUSTOM_03
#define KICKBOX_BUTTON_DOWN_LEFT_FIST GAME_BUTTON_CUSTOM_04
#define KICKBOX_BUTTON_DOWN_RIGHT_FIST GAME_BUTTON_CUSTOM_05
#define KICKBOX_BUTTON_UP_RIGHT_FIST GAME_BUTTON_CUSTOM_06
#define KICKBOX_BUTTON_UP_RIGHT_FOOT GAME_BUTTON_CUSTOM_07
#define KICKBOX_BUTTON_DOWN_RIGHT_FOOT GAME_BUTTON_CUSTOM_08
#define NUM_KICKBOX_BUTTONS GAME_BUTTON_CUSTOM_09
#define GAME_BUTTON_LEFT GAME_BUTTON_MENULEFT
#define GAME_BUTTON_RIGHT GAME_BUTTON_MENURIGHT
#define GAME_BUTTON_UP GAME_BUTTON_MENUUP
+1
View File
@@ -239,6 +239,7 @@ namespace
* case going from theme to theme, but if it was, it should be fixed
* now. There's probably be a better way to do it, but I'm not sure
* what it'd be. -aj */
THEME->UpdateLuaGlobals();
THEME->ReloadMetrics();
g_NewGame= RString();
g_NewTheme= RString();
+452 -98
View File
@@ -93,6 +93,11 @@ static const StepsTypeInfo g_StepsTypeInfos[] = {
{ "pnm-nine", 9, true, StepsTypeCategory_Single }, // called "pnm" for backward compat
// cabinet lights and other fine StepsTypes that don't exist lol
{ "lights-cabinet", NUM_CabinetLight, false, StepsTypeCategory_Single }, // XXX disable lights autogen for now
// kickbox mania
{ "kickbox-human", 4, true, StepsTypeCategory_Single },
{ "kickbox-quadarm", 4, true, StepsTypeCategory_Single },
{ "kickbox-insect", 6, true, StepsTypeCategory_Single },
{ "kickbox-arachnid", 8, true, StepsTypeCategory_Single },
};
@@ -165,7 +170,6 @@ static const Style g_Style_Dance_Single =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0, 1, 2, 3
},
false, // m_bNeedsZoomOutWith2Players
true, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -201,7 +205,6 @@ static const Style g_Style_Dance_Versus =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0, 1, 2, 3
},
false, // m_bNeedsZoomOutWith2Players
true, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -245,7 +248,6 @@ static const Style g_Style_Dance_Double =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0,1,2,3,4,5,6,7
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -281,7 +283,6 @@ static const Style g_Style_Dance_Couple =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0,1,2,3
},
false, // m_bNeedsZoomOutWith2Players
true, // m_bCanUseBeginnerHelper
true, // m_bLockDifficulties
};
@@ -321,7 +322,6 @@ static const Style g_Style_Dance_Solo =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0,1,2,3,4,5
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -365,7 +365,6 @@ static const Style g_Style_Dance_Couple_Edit =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0,1,2,3,4,5,6,7
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -400,7 +399,6 @@ static const Style g_Style_Dance_ThreePanel =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0,1,2
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -438,7 +436,6 @@ static const Style g_Style_Dance_Solo_Versus =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0,5,1,4,2,3 // outside in
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
}; */
@@ -482,10 +479,8 @@ static const Style g_Style_Dance_Routine =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0,1,2,3,4,5,6,7
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
true, // m_bLockDifficulties
};
static const Style *g_apGame_Dance_Styles[] =
@@ -507,6 +502,7 @@ static const Game g_Game_Dance =
g_apGame_Dance_Styles, // m_apStyles
false, // m_bCountNotesSeparately
false, // m_bTickHolds
false, // m_PlayersHaveSeparateStyles
{ // m_InputScheme
"dance", // m_szName
NUM_DANCE_BUTTONS, // m_iButtonsPerController
@@ -595,7 +591,6 @@ static const Style g_Style_Pump_Single =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
2,1,3,0,4
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -633,7 +628,6 @@ static const Style g_Style_Pump_Versus =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
2,1,3,0,4
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -673,7 +667,6 @@ static const Style g_Style_Pump_HalfDouble =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
2,3,1,4,0,5
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -721,7 +714,6 @@ static const Style g_Style_Pump_Double =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
2,1,3,0,4, 2+5,1+5,3+5,0+5,4+5
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -759,7 +751,6 @@ static const Style g_Style_Pump_Couple =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
2,1,3,0,4
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
true, // m_bLockDifficulties
};
@@ -807,7 +798,6 @@ static const Style g_Style_Pump_Couple_Edit =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
2,1,3,0,4, 2+5,1+5,3+5,0+5,4+5
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -855,7 +845,6 @@ static const Style g_Style_Pump_Routine =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
2,1,3,0,4,7,6,8,5,9
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
true, // m_bLockDifficulties
};
@@ -878,6 +867,7 @@ static const Game g_Game_Pump =
g_apGame_Pump_Styles, // m_apStyles
false, // m_bCountNotesSeparately
true, // m_bTickHolds
false, // m_PlayersHaveSeparateStyles
{ // m_InputScheme
"pump", // m_szName
NUM_PUMP_BUTTONS, // m_iButtonsPerController
@@ -956,7 +946,6 @@ static const Style g_Style_KB7_Single =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0,1,2,3,4,5,6 // doesn't work?
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -1000,7 +989,6 @@ static const Style g_Style_KB7_Small =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0,1,2,3,4,5,6 // doesn't work?
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
}; */
@@ -1042,7 +1030,6 @@ static const Style g_Style_KB7_Versus =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0,1,2,3,4,5,6
},
true, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -1061,6 +1048,7 @@ static const Game g_Game_KB7 =
g_apGame_KB7_Styles, // m_apStyles
true, // m_bCountNotesSeparately
false, // m_bTickHolds
false, // m_PlayersHaveSeparateStyles
{ // m_InputScheme
"kb7", // m_szName
NUM_KB7_BUTTONS, // m_iButtonsPerController
@@ -1129,7 +1117,6 @@ static const Style g_Style_Ez2_Single =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
2,0,4,1,3 // This should be from back to front: Down, UpLeft, UpRight, Upper Left Hand, Upper Right Hand
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -1171,7 +1158,6 @@ static const Style g_Style_Ez2_Real =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
3,0,6,1,5,2,4 // This should be from back to front: Down, UpLeft, UpRight, Lower Left Hand, Lower Right Hand, Upper Left Hand, Upper Right Hand
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -1209,7 +1195,6 @@ static const Style g_Style_Ez2_Single_Versus =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
2,0,4,1,3 // This should be from back to front: Down, UpLeft, UpRight, Upper Left Hand, Upper Right Hand
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -1251,7 +1236,6 @@ static const Style g_Style_Ez2_Real_Versus =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
3,0,6,2,4,1,5 // This should be from back to front: Down, UpLeft, UpRight, Lower Left Hand, Lower Right Hand, Upper Left Hand, Upper Right Hand
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -1299,7 +1283,6 @@ static const Style g_Style_Ez2_Double =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
2,0,4,1,3,7,5,9,6,8 // This should be from back to front: Down, UpLeft, UpRight, Upper Left Hand, Upper Right Hand
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -1333,6 +1316,7 @@ static const Game g_Game_Ez2 =
g_apGame_Ez2_Styles, // m_apStyles
true, // m_bCountNotesSeparately
false, // m_bTickHolds
false, // m_PlayersHaveSeparateStyles
{ // m_InputScheme
"ez2", // m_szName
NUM_EZ2_BUTTONS, // m_iButtonsPerController
@@ -1399,7 +1383,6 @@ static const Style g_Style_Para_Single =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
2,0,4,1,3
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -1437,7 +1420,6 @@ static const Style g_Style_Para_Versus =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
2,0,4,1,3
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -1466,6 +1448,7 @@ static const Game g_Game_Para =
g_apGame_Para_Styles, // m_apStyles
false, // m_bCountNotesSeparately
false, // m_bTickHolds
false, // m_PlayersHaveSeparateStyles
{ // m_InputScheme
"para", // m_szName
NUM_PARA_BUTTONS, // m_iButtonsPerController
@@ -1533,7 +1516,6 @@ static const Style g_Style_DS3DDX_Single =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0,1,2,3,4,5,6,7
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -1564,6 +1546,7 @@ static const Game g_Game_DS3DDX =
g_apGame_DS3DDX_Styles, // m_apStyles
false, // m_bCountNotesSeparately
false, // m_bTickHolds
false, // m_PlayersHaveSeparateStyles
{ // m_InputScheme
"ds3ddx", // m_szName
NUM_DS3DDX_BUTTONS, // m_iButtonsPerController
@@ -1633,7 +1616,6 @@ static const Style g_Style_Beat_Single5 =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0,1,2,3,4,5
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -1673,7 +1655,6 @@ static const Style g_Style_Beat_Versus5 =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0,1,2,3,4,5
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -1725,7 +1706,6 @@ static const Style g_Style_Beat_Double5 =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0,1,2,3,4,5,6,7,8,9,10,11
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -1769,7 +1749,6 @@ static const Style g_Style_Beat_Single7 =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0,1,2,3,4,5,6,7
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -1813,7 +1792,6 @@ static const Style g_Style_Beat_Versus7 =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0,1,2,3,4,5,6,7
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -1874,7 +1852,6 @@ static const Style g_Style_Beat_Double7 =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -1910,6 +1887,7 @@ static const Game g_Game_Beat =
g_apGame_Beat_Styles, // m_apStyles
true, // m_bCountNotesSeparately
false, // m_bTickHolds
false, // m_PlayersHaveSeparateStyles
{ // m_InputScheme
"beat", // m_szName
NUM_BEAT_BUTTONS, // m_iButtonsPerController
@@ -1977,7 +1955,6 @@ static const Style g_Style_Maniax_Single =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0, 1, 2, 3
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -2013,7 +1990,6 @@ static const Style g_Style_Maniax_Versus =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0, 1, 2, 3
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -2057,7 +2033,6 @@ static const Style g_Style_Maniax_Double =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0,1,2,3,4,5,6,7
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -2090,6 +2065,7 @@ static const Game g_Game_Maniax =
g_apGame_Maniax_Styles, // m_apStyles
false, // m_bCountNotesSeparately
false, // m_bTickHolds
false, // m_PlayersHaveSeparateStyles
{ // m_InputScheme
"maniax", // m_szName
NUM_MANIAX_BUTTONS, // m_iButtonsPerController
@@ -2119,7 +2095,6 @@ static const Game g_Game_Maniax =
//ThemeMetric<int> TECHNO_COL_SPACING ("ColumnSpacing","Techno");
static const int TECHNO_COL_SPACING = 56;
//ThemeMetric<int> TECHNO_VERSUS_COL_SPACING ("ColumnSpacing","TechnoVersus");
static const int TECHNO_VERSUS_COL_SPACING = 33;
static const Style g_Style_Techno_Single4 =
{ // STYLE_TECHNO_SINGLE4
true, // m_bUsedForGameplay
@@ -2151,7 +2126,6 @@ static const Style g_Style_Techno_Single4 =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0,1,2,3
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -2191,7 +2165,6 @@ static const Style g_Style_Techno_Single5 =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0,1,2,3,4
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -2235,7 +2208,6 @@ static const Style g_Style_Techno_Single8 =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0,1,2,3,4,5,6,7
},
true, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -2271,7 +2243,6 @@ static const Style g_Style_Techno_Versus4 =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0,1,2,3
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -2311,7 +2282,6 @@ static const Style g_Style_Techno_Versus5 =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0,1,2,3,4
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -2328,24 +2298,24 @@ static const Style g_Style_Techno_Versus8 =
8, // m_iColsPerPlayer
{ // m_ColumnInfo[NUM_PLAYERS][MAX_COLS_PER_PLAYER];
{ // PLAYER_1
{ TRACK_1, -TECHNO_VERSUS_COL_SPACING*3.5f, NULL },
{ TRACK_2, -TECHNO_VERSUS_COL_SPACING*2.5f, NULL },
{ TRACK_3, -TECHNO_VERSUS_COL_SPACING*1.5f, NULL },
{ TRACK_4, -TECHNO_VERSUS_COL_SPACING*0.5f, NULL },
{ TRACK_5, +TECHNO_VERSUS_COL_SPACING*0.5f, NULL },
{ TRACK_6, +TECHNO_VERSUS_COL_SPACING*1.5f, NULL },
{ TRACK_7, +TECHNO_VERSUS_COL_SPACING*2.5f, NULL },
{ TRACK_8, +TECHNO_VERSUS_COL_SPACING*3.5f, NULL },
{ TRACK_1, -TECHNO_COL_SPACING*3.5f, NULL },
{ TRACK_2, -TECHNO_COL_SPACING*2.5f, NULL },
{ TRACK_3, -TECHNO_COL_SPACING*1.5f, NULL },
{ TRACK_4, -TECHNO_COL_SPACING*0.5f, NULL },
{ TRACK_5, +TECHNO_COL_SPACING*0.5f, NULL },
{ TRACK_6, +TECHNO_COL_SPACING*1.5f, NULL },
{ TRACK_7, +TECHNO_COL_SPACING*2.5f, NULL },
{ TRACK_8, +TECHNO_COL_SPACING*3.5f, NULL },
},
{ // PLAYER_2
{ TRACK_1, -TECHNO_VERSUS_COL_SPACING*3.5f, NULL },
{ TRACK_2, -TECHNO_VERSUS_COL_SPACING*2.5f, NULL },
{ TRACK_3, -TECHNO_VERSUS_COL_SPACING*1.5f, NULL },
{ TRACK_4, -TECHNO_VERSUS_COL_SPACING*0.5f, NULL },
{ TRACK_5, +TECHNO_VERSUS_COL_SPACING*0.5f, NULL },
{ TRACK_6, +TECHNO_VERSUS_COL_SPACING*1.5f, NULL },
{ TRACK_7, +TECHNO_VERSUS_COL_SPACING*2.5f, NULL },
{ TRACK_8, +TECHNO_VERSUS_COL_SPACING*3.5f, NULL },
{ TRACK_1, -TECHNO_COL_SPACING*3.5f, NULL },
{ TRACK_2, -TECHNO_COL_SPACING*2.5f, NULL },
{ TRACK_3, -TECHNO_COL_SPACING*1.5f, NULL },
{ TRACK_4, -TECHNO_COL_SPACING*0.5f, NULL },
{ TRACK_5, +TECHNO_COL_SPACING*0.5f, NULL },
{ TRACK_6, +TECHNO_COL_SPACING*1.5f, NULL },
{ TRACK_7, +TECHNO_COL_SPACING*2.5f, NULL },
{ TRACK_8, +TECHNO_COL_SPACING*3.5f, NULL },
},
},
{ // m_iInputColumn[NUM_GameController][NUM_GameButton]
@@ -2357,7 +2327,6 @@ static const Style g_Style_Techno_Versus8 =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0,1,2,3,4,5,6,7
},
true, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -2401,7 +2370,6 @@ static const Style g_Style_Techno_Double4 =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0,1,2,3,4,5,6,7
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -2461,7 +2429,6 @@ static const Style g_Style_Techno_Double5 =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0,1,2,3,4,5,6,7,8,9
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -2478,40 +2445,40 @@ static const Style g_Style_Techno_Double8 =
16, // m_iColsPerPlayer
{ // m_ColumnInfo[NUM_PLAYERS][MAX_COLS_PER_PLAYER];
{ // PLAYER_1
{ TRACK_1, -TECHNO_VERSUS_COL_SPACING*7.5f, NULL },
{ TRACK_2, -TECHNO_VERSUS_COL_SPACING*6.5f, NULL },
{ TRACK_3, -TECHNO_VERSUS_COL_SPACING*5.5f, NULL },
{ TRACK_4, -TECHNO_VERSUS_COL_SPACING*4.5f, NULL },
{ TRACK_5, -TECHNO_VERSUS_COL_SPACING*3.5f, NULL },
{ TRACK_6, -TECHNO_VERSUS_COL_SPACING*2.5f, NULL },
{ TRACK_7, -TECHNO_VERSUS_COL_SPACING*1.5f, NULL },
{ TRACK_8, -TECHNO_VERSUS_COL_SPACING*0.5f, NULL },
{ TRACK_9, +TECHNO_VERSUS_COL_SPACING*0.5f, NULL },
{ TRACK_10, +TECHNO_VERSUS_COL_SPACING*1.5f, NULL },
{ TRACK_11, +TECHNO_VERSUS_COL_SPACING*2.5f, NULL },
{ TRACK_12, +TECHNO_VERSUS_COL_SPACING*3.5f, NULL },
{ TRACK_13, +TECHNO_VERSUS_COL_SPACING*4.5f, NULL },
{ TRACK_14, +TECHNO_VERSUS_COL_SPACING*5.5f, NULL },
{ TRACK_15, +TECHNO_VERSUS_COL_SPACING*6.5f, NULL },
{ TRACK_16, +TECHNO_VERSUS_COL_SPACING*7.5f, NULL },
{ TRACK_1, -TECHNO_COL_SPACING*7.5f, NULL },
{ TRACK_2, -TECHNO_COL_SPACING*6.5f, NULL },
{ TRACK_3, -TECHNO_COL_SPACING*5.5f, NULL },
{ TRACK_4, -TECHNO_COL_SPACING*4.5f, NULL },
{ TRACK_5, -TECHNO_COL_SPACING*3.5f, NULL },
{ TRACK_6, -TECHNO_COL_SPACING*2.5f, NULL },
{ TRACK_7, -TECHNO_COL_SPACING*1.5f, NULL },
{ TRACK_8, -TECHNO_COL_SPACING*0.5f, NULL },
{ TRACK_9, +TECHNO_COL_SPACING*0.5f, NULL },
{ TRACK_10, +TECHNO_COL_SPACING*1.5f, NULL },
{ TRACK_11, +TECHNO_COL_SPACING*2.5f, NULL },
{ TRACK_12, +TECHNO_COL_SPACING*3.5f, NULL },
{ TRACK_13, +TECHNO_COL_SPACING*4.5f, NULL },
{ TRACK_14, +TECHNO_COL_SPACING*5.5f, NULL },
{ TRACK_15, +TECHNO_COL_SPACING*6.5f, NULL },
{ TRACK_16, +TECHNO_COL_SPACING*7.5f, NULL },
},
{ // PLAYER_2
{ TRACK_1, -TECHNO_VERSUS_COL_SPACING*7.5f, NULL },
{ TRACK_2, -TECHNO_VERSUS_COL_SPACING*6.5f, NULL },
{ TRACK_3, -TECHNO_VERSUS_COL_SPACING*5.5f, NULL },
{ TRACK_4, -TECHNO_VERSUS_COL_SPACING*4.5f, NULL },
{ TRACK_5, -TECHNO_VERSUS_COL_SPACING*3.5f, NULL },
{ TRACK_6, -TECHNO_VERSUS_COL_SPACING*2.5f, NULL },
{ TRACK_7, -TECHNO_VERSUS_COL_SPACING*1.5f, NULL },
{ TRACK_8, -TECHNO_VERSUS_COL_SPACING*0.5f, NULL },
{ TRACK_9, +TECHNO_VERSUS_COL_SPACING*0.5f, NULL },
{ TRACK_10, +TECHNO_VERSUS_COL_SPACING*1.5f, NULL },
{ TRACK_11, +TECHNO_VERSUS_COL_SPACING*2.5f, NULL },
{ TRACK_12, +TECHNO_VERSUS_COL_SPACING*3.5f, NULL },
{ TRACK_13, +TECHNO_VERSUS_COL_SPACING*4.5f, NULL },
{ TRACK_14, +TECHNO_VERSUS_COL_SPACING*5.5f, NULL },
{ TRACK_15, +TECHNO_VERSUS_COL_SPACING*6.5f, NULL },
{ TRACK_16, +TECHNO_VERSUS_COL_SPACING*7.5f, NULL },
{ TRACK_1, -TECHNO_COL_SPACING*7.5f, NULL },
{ TRACK_2, -TECHNO_COL_SPACING*6.5f, NULL },
{ TRACK_3, -TECHNO_COL_SPACING*5.5f, NULL },
{ TRACK_4, -TECHNO_COL_SPACING*4.5f, NULL },
{ TRACK_5, -TECHNO_COL_SPACING*3.5f, NULL },
{ TRACK_6, -TECHNO_COL_SPACING*2.5f, NULL },
{ TRACK_7, -TECHNO_COL_SPACING*1.5f, NULL },
{ TRACK_8, -TECHNO_COL_SPACING*0.5f, NULL },
{ TRACK_9, +TECHNO_COL_SPACING*0.5f, NULL },
{ TRACK_10, +TECHNO_COL_SPACING*1.5f, NULL },
{ TRACK_11, +TECHNO_COL_SPACING*2.5f, NULL },
{ TRACK_12, +TECHNO_COL_SPACING*3.5f, NULL },
{ TRACK_13, +TECHNO_COL_SPACING*4.5f, NULL },
{ TRACK_14, +TECHNO_COL_SPACING*5.5f, NULL },
{ TRACK_15, +TECHNO_COL_SPACING*6.5f, NULL },
{ TRACK_16, +TECHNO_COL_SPACING*7.5f, NULL },
},
},
{ // m_iInputColumn[NUM_GameController][NUM_GameButton]
@@ -2521,7 +2488,6 @@ static const Style g_Style_Techno_Double8 =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -2570,6 +2536,7 @@ static const Game g_Game_Techno =
g_apGame_Techno_Styles, // m_apStyles
false, // m_bCountNotesSeparately
false, // m_bTickHolds
false, // m_PlayersHaveSeparateStyles
{ // m_InputScheme
"techno", // m_szName
NUM_TECHNO_BUTTONS, // m_iButtonsPerController
@@ -2642,7 +2609,6 @@ static const Style g_Style_Popn_Five =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0,1,2,3,4
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -2688,7 +2654,6 @@ static const Style g_Style_Popn_Nine =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0,1,2,3,4,5,6,7,8
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -2721,6 +2686,7 @@ static const Game g_Game_Popn =
g_apGame_Popn_Styles, // m_apStyles
true, // m_bCountNotesSeparately
false, // m_bTickHolds
false, // m_PlayersHaveSeparateStyles
{ // m_InputScheme
"popn", // m_szName
NUM_POPN_BUTTONS, // m_iButtonsPerController
@@ -2810,7 +2776,6 @@ static const Style g_Style_Lights_Cabinet =
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0,1,2,3,4,5,6,7
},
false, // m_bNeedsZoomOutWith2Players
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
@@ -2827,6 +2792,7 @@ static const Game g_Game_Lights =
g_apGame_Lights_Styles, // m_apStyles
false, // m_bCountNotesSeparately
false, // m_bTickHolds
false, // m_PlayersHaveSeparateStyles
{ // m_InputScheme
"lights", // m_szName
NUM_LIGHTS_BUTTONS, // m_iButtonsPerController
@@ -2859,6 +2825,393 @@ static const Game g_Game_Lights =
TNS_W5, // m_mapW5To
};
/** Kickbox mania **********************************************************/
static const AutoMappings g_AutoKeyMappings_Kickbox = AutoMappings (
"", "", "",
AutoMappingEntry(0, KEY_Cq, GAME_BUTTON_MENULEFT, false),
AutoMappingEntry(0, KEY_Cr, GAME_BUTTON_MENURIGHT, false),
AutoMappingEntry(0, KEY_Ce, GAME_BUTTON_MENUUP, false),
AutoMappingEntry(0, KEY_Cw, GAME_BUTTON_MENUDOWN, false),
AutoMappingEntry(0, KEY_Cz, KICKBOX_BUTTON_DOWN_LEFT_FOOT, false),
AutoMappingEntry(0, KEY_Ca, KICKBOX_BUTTON_UP_LEFT_FOOT, false),
AutoMappingEntry(0, KEY_Cs, KICKBOX_BUTTON_UP_LEFT_FIST, false),
AutoMappingEntry(0, KEY_Cx, KICKBOX_BUTTON_DOWN_LEFT_FIST, false),
AutoMappingEntry(0, KEY_Cc, KICKBOX_BUTTON_DOWN_RIGHT_FIST, false),
AutoMappingEntry(0, KEY_Cd, KICKBOX_BUTTON_UP_RIGHT_FIST, false),
AutoMappingEntry(0, KEY_Cf, KICKBOX_BUTTON_UP_RIGHT_FOOT, false),
AutoMappingEntry(0, KEY_Cv, KICKBOX_BUTTON_DOWN_RIGHT_FOOT, false),
AutoMappingEntry(0, KEY_Cu, GAME_BUTTON_MENULEFT, true),
AutoMappingEntry(0, KEY_Cp, GAME_BUTTON_MENURIGHT, true),
AutoMappingEntry(0, KEY_Ci, GAME_BUTTON_MENUUP, true),
AutoMappingEntry(0, KEY_Co, GAME_BUTTON_MENUDOWN, true),
AutoMappingEntry(0, KEY_Cm, KICKBOX_BUTTON_DOWN_LEFT_FOOT, true),
AutoMappingEntry(0, KEY_Cj, KICKBOX_BUTTON_UP_LEFT_FOOT, true),
AutoMappingEntry(0, KEY_Ck, KICKBOX_BUTTON_UP_LEFT_FIST, true),
AutoMappingEntry(0, KEY_COMMA, KICKBOX_BUTTON_DOWN_LEFT_FIST, true),
AutoMappingEntry(0, KEY_PERIOD, KICKBOX_BUTTON_DOWN_RIGHT_FIST, true),
AutoMappingEntry(0, KEY_Cl, KICKBOX_BUTTON_UP_RIGHT_FIST, true),
AutoMappingEntry(0, KEY_SEMICOLON, KICKBOX_BUTTON_UP_RIGHT_FOOT, true),
AutoMappingEntry(0, KEY_SLASH, KICKBOX_BUTTON_DOWN_RIGHT_FOOT, true)
);
static const int KICKBOX_COL_SPACING= 64;
static const Style g_Style_Kickbox_Human=
{
true, // m_bUsedForGameplay
true, // m_bUsedForEdit
true, // m_bUsedForDemonstration
true, // m_bUsedForHowToPlay
"human", // m_szName
StepsType_kickbox_human, // m_StepsType
StyleType_OnePlayerOneSide, // m_StyleType
4, // m_iColsPerPlayer
{ // m_ColumnInfo[NUM_PLAYERS][MAX_COLS_PER_PLAYER];
{ // PLAYER_1
{ TRACK_1, -KICKBOX_COL_SPACING*1.5f, NULL },
{ TRACK_2, -KICKBOX_COL_SPACING*0.5f, NULL },
{ TRACK_3, +KICKBOX_COL_SPACING*0.5f, NULL },
{ TRACK_4, +KICKBOX_COL_SPACING*1.5f, NULL },
},
{ // PLAYER_2
{ TRACK_1, -KICKBOX_COL_SPACING*1.5f, NULL },
{ TRACK_2, -KICKBOX_COL_SPACING*0.5f, NULL },
{ TRACK_3, +KICKBOX_COL_SPACING*0.5f, NULL },
{ TRACK_4, +KICKBOX_COL_SPACING*1.5f, NULL },
},
},
{ // m_iInputColumn[NUM_GameController][NUM_GameButton]
{ 0, 0, 1, 1, 2, 2, 3, 3, Style::END_MAPPING },
{ 0, 0, 1, 1, 2, 2, 3, 3, Style::END_MAPPING }
},
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0, 1, 2, 3
},
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
static const Style g_Style_Kickbox_Human_Versus=
{
true, // m_bUsedForGameplay
false, // m_bUsedForEdit
true, // m_bUsedForDemonstration
false, // m_bUsedForHowToPlay
"hversus", // m_szName
StepsType_kickbox_human, // m_StepsType
StyleType_TwoPlayersTwoSides, // m_StyleType
4, // m_iColsPerPlayer
{ // m_ColumnInfo[NUM_PLAYERS][MAX_COLS_PER_PLAYER];
{ // PLAYER_1
{ TRACK_1, -KICKBOX_COL_SPACING*1.5f, NULL },
{ TRACK_2, -KICKBOX_COL_SPACING*0.5f, NULL },
{ TRACK_3, +KICKBOX_COL_SPACING*0.5f, NULL },
{ TRACK_4, +KICKBOX_COL_SPACING*1.5f, NULL },
},
{ // PLAYER_2
{ TRACK_1, -KICKBOX_COL_SPACING*1.5f, NULL },
{ TRACK_2, -KICKBOX_COL_SPACING*0.5f, NULL },
{ TRACK_3, +KICKBOX_COL_SPACING*0.5f, NULL },
{ TRACK_4, +KICKBOX_COL_SPACING*1.5f, NULL },
},
},
{ // m_iInputColumn[NUM_GameController][NUM_GameButton]
{ 0, 0, 1, 1, 2, 2, 3, 3, Style::END_MAPPING },
{ 0, 0, 1, 1, 2, 2, 3, 3, Style::END_MAPPING }
},
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0, 1, 2, 3
},
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
static const Style g_Style_Kickbox_Quadarm=
{
true, // m_bUsedForGameplay
true, // m_bUsedForEdit
true, // m_bUsedForDemonstration
true, // m_bUsedForHowToPlay
"quadarm", // m_szName
StepsType_kickbox_quadarm, // m_StepsType
StyleType_OnePlayerOneSide, // m_StyleType
4, // m_iColsPerPlayer
{ // m_ColumnInfo[NUM_PLAYERS][MAX_COLS_PER_PLAYER];
{ // PLAYER_1
{ TRACK_1, -KICKBOX_COL_SPACING*1.5f, NULL },
{ TRACK_2, -KICKBOX_COL_SPACING*0.5f, NULL },
{ TRACK_3, +KICKBOX_COL_SPACING*0.5f, NULL },
{ TRACK_4, +KICKBOX_COL_SPACING*1.5f, NULL },
},
{ // PLAYER_2
{ TRACK_1, -KICKBOX_COL_SPACING*1.5f, NULL },
{ TRACK_2, -KICKBOX_COL_SPACING*0.5f, NULL },
{ TRACK_3, +KICKBOX_COL_SPACING*0.5f, NULL },
{ TRACK_4, +KICKBOX_COL_SPACING*1.5f, NULL },
},
},
{ // m_iInputColumn[NUM_GameController][NUM_GameButton]
{ Style::NO_MAPPING, Style::NO_MAPPING, 0, 1, 2, 3, Style::NO_MAPPING, Style::NO_MAPPING, Style::END_MAPPING },
{ Style::NO_MAPPING, Style::NO_MAPPING, 0, 1, 2, 3, Style::NO_MAPPING, Style::NO_MAPPING, Style::END_MAPPING }
},
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0, 1, 2, 3
},
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
static const Style g_Style_Kickbox_Quadarm_Versus=
{
true, // m_bUsedForGameplay
false, // m_bUsedForEdit
true, // m_bUsedForDemonstration
false, // m_bUsedForHowToPlay
"qversus", // m_szName
StepsType_kickbox_quadarm, // m_StepsType
StyleType_TwoPlayersTwoSides, // m_StyleType
4, // m_iColsPerPlayer
{ // m_ColumnInfo[NUM_PLAYERS][MAX_COLS_PER_PLAYER];
{ // PLAYER_1
{ TRACK_1, -KICKBOX_COL_SPACING*1.5f, NULL },
{ TRACK_2, -KICKBOX_COL_SPACING*0.5f, NULL },
{ TRACK_3, +KICKBOX_COL_SPACING*0.5f, NULL },
{ TRACK_4, +KICKBOX_COL_SPACING*1.5f, NULL },
},
{ // PLAYER_2
{ TRACK_1, -KICKBOX_COL_SPACING*1.5f, NULL },
{ TRACK_2, -KICKBOX_COL_SPACING*0.5f, NULL },
{ TRACK_3, +KICKBOX_COL_SPACING*0.5f, NULL },
{ TRACK_4, +KICKBOX_COL_SPACING*1.5f, NULL },
},
},
{ // m_iInputColumn[NUM_GameController][NUM_GameButton]
{ Style::NO_MAPPING, Style::NO_MAPPING, 0, 1, 2, 3, Style::NO_MAPPING, Style::NO_MAPPING, Style::END_MAPPING },
{ Style::NO_MAPPING, Style::NO_MAPPING, 0, 1, 2, 3, Style::NO_MAPPING, Style::NO_MAPPING, Style::END_MAPPING }
},
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0, 1, 2, 3
},
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
static const Style g_Style_Kickbox_Insect=
{
true, // m_bUsedForGameplay
true, // m_bUsedForEdit
true, // m_bUsedForDemonstration
true, // m_bUsedForHowToPlay
"insect", // m_szName
StepsType_kickbox_insect, // m_StepsType
StyleType_OnePlayerOneSide, // m_StyleType
6, // m_iColsPerPlayer
{ // m_ColumnInfo[NUM_PLAYERS][MAX_COLS_PER_PLAYER];
{ // PLAYER_1
{ TRACK_1, -KICKBOX_COL_SPACING*2.5f, NULL },
{ TRACK_2, -KICKBOX_COL_SPACING*1.5f, NULL },
{ TRACK_3, -KICKBOX_COL_SPACING*0.5f, NULL },
{ TRACK_4, +KICKBOX_COL_SPACING*0.5f, NULL },
{ TRACK_5, +KICKBOX_COL_SPACING*1.5f, NULL },
{ TRACK_6, +KICKBOX_COL_SPACING*2.5f, NULL },
},
{ // PLAYER_2
{ TRACK_1, -KICKBOX_COL_SPACING*2.5f, NULL },
{ TRACK_2, -KICKBOX_COL_SPACING*1.5f, NULL },
{ TRACK_3, -KICKBOX_COL_SPACING*0.5f, NULL },
{ TRACK_4, +KICKBOX_COL_SPACING*0.5f, NULL },
{ TRACK_5, +KICKBOX_COL_SPACING*1.5f, NULL },
{ TRACK_6, +KICKBOX_COL_SPACING*2.5f, NULL },
},
},
{ // m_iInputColumn[NUM_GameController][NUM_GameButton]
{ 0, 0, 1, 2, 3, 4, 5, 5, Style::END_MAPPING },
{ 0, 0, 1, 2, 3, 4, 5, 5, Style::END_MAPPING }
},
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0, 1, 2, 3, 4, 5
},
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
static const Style g_Style_Kickbox_Insect_Versus=
{
true, // m_bUsedForGameplay
false, // m_bUsedForEdit
true, // m_bUsedForDemonstration
false, // m_bUsedForHowToPlay
"iversus", // m_szName
StepsType_kickbox_insect, // m_StepsType
StyleType_TwoPlayersTwoSides, // m_StyleType
6, // m_iColsPerPlayer
{ // m_ColumnInfo[NUM_PLAYERS][MAX_COLS_PER_PLAYER];
{ // PLAYER_1
{ TRACK_1, -KICKBOX_COL_SPACING*2.5f, NULL },
{ TRACK_2, -KICKBOX_COL_SPACING*1.5f, NULL },
{ TRACK_3, -KICKBOX_COL_SPACING*0.5f, NULL },
{ TRACK_4, +KICKBOX_COL_SPACING*0.5f, NULL },
{ TRACK_5, +KICKBOX_COL_SPACING*1.5f, NULL },
{ TRACK_6, +KICKBOX_COL_SPACING*2.5f, NULL },
},
{ // PLAYER_2
{ TRACK_1, -KICKBOX_COL_SPACING*2.5f, NULL },
{ TRACK_2, -KICKBOX_COL_SPACING*1.5f, NULL },
{ TRACK_3, -KICKBOX_COL_SPACING*0.5f, NULL },
{ TRACK_4, +KICKBOX_COL_SPACING*0.5f, NULL },
{ TRACK_5, +KICKBOX_COL_SPACING*1.5f, NULL },
{ TRACK_6, +KICKBOX_COL_SPACING*2.5f, NULL },
},
},
{ // m_iInputColumn[NUM_GameController][NUM_GameButton]
{ 0, 0, 1, 2, 3, 4, 5, 5, Style::END_MAPPING },
{ 0, 0, 1, 2, 3, 4, 5, 5, Style::END_MAPPING }
},
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0, 1, 2, 3, 4, 5
},
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
static const Style g_Style_Kickbox_Arachnid=
{
true, // m_bUsedForGameplay
true, // m_bUsedForEdit
true, // m_bUsedForDemonstration
true, // m_bUsedForHowToPlay
"arachnid", // m_szName
StepsType_kickbox_arachnid, // m_StepsType
StyleType_OnePlayerOneSide, // m_StyleType
8, // m_iColsPerPlayer
{ // m_ColumnInfo[NUM_PLAYERS][MAX_COLS_PER_PLAYER];
{ // PLAYER_1
{ TRACK_1, -KICKBOX_COL_SPACING*3.5f, NULL },
{ TRACK_2, -KICKBOX_COL_SPACING*2.5f, NULL },
{ TRACK_3, -KICKBOX_COL_SPACING*1.5f, NULL },
{ TRACK_4, -KICKBOX_COL_SPACING*0.5f, NULL },
{ TRACK_5, +KICKBOX_COL_SPACING*0.5f, NULL },
{ TRACK_6, +KICKBOX_COL_SPACING*1.5f, NULL },
{ TRACK_7, +KICKBOX_COL_SPACING*2.5f, NULL },
{ TRACK_8, +KICKBOX_COL_SPACING*3.5f, NULL },
},
{ // PLAYER_2
{ TRACK_1, -KICKBOX_COL_SPACING*3.5f, NULL },
{ TRACK_2, -KICKBOX_COL_SPACING*2.5f, NULL },
{ TRACK_3, -KICKBOX_COL_SPACING*1.5f, NULL },
{ TRACK_4, -KICKBOX_COL_SPACING*0.5f, NULL },
{ TRACK_5, +KICKBOX_COL_SPACING*0.5f, NULL },
{ TRACK_6, +KICKBOX_COL_SPACING*1.5f, NULL },
{ TRACK_7, +KICKBOX_COL_SPACING*2.5f, NULL },
{ TRACK_8, +KICKBOX_COL_SPACING*3.5f, NULL },
},
},
{ // m_iInputColumn[NUM_GameController][NUM_GameButton]
{ 0, 1, 2, 3, 4, 5, 6, 7, Style::END_MAPPING },
{ 0, 1, 2, 3, 4, 5, 6, 7, Style::END_MAPPING }
},
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0, 1, 2, 3, 4, 5, 6, 7
},
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
static const Style g_Style_Kickbox_Arachnid_Versus=
{
true, // m_bUsedForGameplay
false, // m_bUsedForEdit
true, // m_bUsedForDemonstration
false, // m_bUsedForHowToPlay
"aversus", // m_szName
StepsType_kickbox_arachnid, // m_StepsType
StyleType_TwoPlayersTwoSides, // m_StyleType
8, // m_iColsPerPlayer
{ // m_ColumnInfo[NUM_PLAYERS][MAX_COLS_PER_PLAYER];
{ // PLAYER_1
{ TRACK_1, -KICKBOX_COL_SPACING*3.5f, NULL },
{ TRACK_2, -KICKBOX_COL_SPACING*2.5f, NULL },
{ TRACK_3, -KICKBOX_COL_SPACING*1.5f, NULL },
{ TRACK_4, -KICKBOX_COL_SPACING*0.5f, NULL },
{ TRACK_5, +KICKBOX_COL_SPACING*0.5f, NULL },
{ TRACK_6, +KICKBOX_COL_SPACING*1.5f, NULL },
{ TRACK_7, +KICKBOX_COL_SPACING*2.5f, NULL },
{ TRACK_8, +KICKBOX_COL_SPACING*3.5f, NULL },
},
{ // PLAYER_2
{ TRACK_1, -KICKBOX_COL_SPACING*3.5f, NULL },
{ TRACK_2, -KICKBOX_COL_SPACING*2.5f, NULL },
{ TRACK_3, -KICKBOX_COL_SPACING*1.5f, NULL },
{ TRACK_4, -KICKBOX_COL_SPACING*0.5f, NULL },
{ TRACK_5, +KICKBOX_COL_SPACING*0.5f, NULL },
{ TRACK_6, +KICKBOX_COL_SPACING*1.5f, NULL },
{ TRACK_7, +KICKBOX_COL_SPACING*2.5f, NULL },
{ TRACK_8, +KICKBOX_COL_SPACING*3.5f, NULL },
},
},
{ // m_iInputColumn[NUM_GameController][NUM_GameButton]
{ 0, 1, 2, 3, 4, 5, 6, 7, Style::END_MAPPING },
{ 0, 1, 2, 3, 4, 5, 6, 7, Style::END_MAPPING }
},
{ // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER];
0, 1, 2, 3, 4, 5, 6, 7
},
false, // m_bCanUseBeginnerHelper
false, // m_bLockDifficulties
};
static const Style* g_apGame_Kickbox_Styles[] =
{
&g_Style_Kickbox_Human,
&g_Style_Kickbox_Quadarm,
&g_Style_Kickbox_Insect,
&g_Style_Kickbox_Arachnid,
&g_Style_Kickbox_Human_Versus,
&g_Style_Kickbox_Quadarm_Versus,
&g_Style_Kickbox_Insect_Versus,
&g_Style_Kickbox_Arachnid_Versus,
NULL
};
static const Game g_Game_Kickbox =
{
"kickbox", // m_szName
g_apGame_Kickbox_Styles, // m_apStyles
true, // m_bCountNotesSeparately
false, // m_bTickHolds
true, // m_PlayersHaveSeparateStyles
{ // m_InputScheme
"kickbox", // m_szName
NUM_KICKBOX_BUTTONS, // m_iButtonsPerController
{ // m_szButtonNames
{ "DownLeftFoot", GameButton_Invalid },
{ "UpLeftFoot", GameButton_Invalid },
{ "UpLeftFist", GAME_BUTTON_LEFT },
{ "DownLeftFist", GAME_BUTTON_UP },
{ "DownRightFist", GAME_BUTTON_DOWN },
{ "UpRightFist", GAME_BUTTON_RIGHT },
{ "UpRightFoot", GameButton_Invalid },
{ "DownRightFoot", GameButton_Invalid },
},
&g_AutoKeyMappings_Kickbox
},
{
{ GameButtonType_Step },
{ GameButtonType_Step },
{ GameButtonType_Step },
{ GameButtonType_Step },
{ GameButtonType_Step },
{ GameButtonType_Step },
{ GameButtonType_Step },
{ GameButtonType_Step },
},
TNS_W1, // m_mapW1To
TNS_W2, // m_mapW2To
TNS_W3, // m_mapW3To
TNS_W4, // m_mapW4To
TNS_W5, // m_mapW5To
};
static const Game *g_Games[] =
{
&g_Game_Dance,
@@ -2872,6 +3225,7 @@ static const Game *g_Games[] =
&g_Game_Techno,
&g_Game_Popn,
&g_Game_Lights,
&g_Game_Kickbox,
};
GameManager::GameManager()
+375 -48
View File
@@ -20,6 +20,7 @@
#include "LuaReference.h"
#include "MessageManager.h"
#include "MemoryCardManager.h"
#include "NoteData.h"
#include "NoteSkinManager.h"
#include "PlayerState.h"
#include "PrefsManager.h"
@@ -136,7 +137,11 @@ GameState::GameState() :
{
g_pImpl = new GameStateImpl;
SetCurrentStyle( NULL );
m_pCurStyle.Set(NULL);
FOREACH_PlayerNumber(rpn)
{
m_SeparatedStyles[rpn]= NULL;
}
m_pCurGame.Set( NULL );
m_iCoins.Set( 0 );
@@ -153,12 +158,12 @@ GameState::GameState() :
FOREACH_PlayerNumber( p )
{
m_pPlayerState[p] = new PlayerState;
m_pPlayerState[p]->m_PlayerNumber = p;
m_pPlayerState[p]->SetPlayerNumber(p);
}
FOREACH_MultiPlayer( p )
{
m_pMultiPlayerState[p] = new PlayerState;
m_pMultiPlayerState[p]->m_PlayerNumber = PLAYER_1;
m_pMultiPlayerState[p]->SetPlayerNumber(PLAYER_1);
m_pMultiPlayerState[p]->m_mp = p;
}
@@ -285,7 +290,7 @@ void GameState::Reset()
ASSERT( THEME != NULL );
m_timeGameStarted.SetZero();
SetCurrentStyle( NULL );
SetCurrentStyle( NULL, PLAYER_INVALID );
FOREACH_MultiPlayer( p )
m_MultiPlayerStatus[p] = MultiPlayerStatus_NotJoined;
FOREACH_PlayerNumber( pn )
@@ -391,23 +396,32 @@ void GameState::JoinPlayer( PlayerNumber pn )
}
// Set the current style to something appropriate for the new number of joined players.
if( ALLOW_LATE_JOIN && m_pCurStyle != NULL )
// beat gametype's versus styles use a different stepstype from its single
// styles, so when GameCommand tries to join both players for a versus
// style, it hits the assert when joining the first player. So if the first
// player is being joined and the current styletype is for two players,
// assume that the second player will be joined immediately afterwards and
// don't try to change the style. -Kyz
const Style* cur_style= GetCurrentStyle(PLAYER_INVALID);
if( ALLOW_LATE_JOIN && cur_style != NULL && !(pn == PLAYER_1 &&
(cur_style->m_StyleType == StyleType_TwoPlayersTwoSides ||
cur_style->m_StyleType == StyleType_TwoPlayersSharedSides)))
{
const Style *pStyle;
// Only use one player for StyleType_OnePlayerTwoSides and StepsTypes
// that can only be played by one player (e.g. dance-solo,
// dance-threepanel, popn-nine). -aj
// XXX?: still shows joined player as "Insert Card". May not be an issue? -aj
if( m_pCurStyle->m_StyleType == StyleType_OnePlayerTwoSides ||
m_pCurStyle->m_StepsType == StepsType_dance_solo ||
m_pCurStyle->m_StepsType == StepsType_dance_threepanel ||
m_pCurStyle->m_StepsType == StepsType_popn_nine )
pStyle = GAMEMAN->GetFirstCompatibleStyle( m_pCurGame, 1, m_pCurStyle->m_StepsType );
if( cur_style->m_StyleType == StyleType_OnePlayerTwoSides ||
cur_style->m_StepsType == StepsType_dance_solo ||
cur_style->m_StepsType == StepsType_dance_threepanel ||
cur_style->m_StepsType == StepsType_popn_nine )
pStyle = GAMEMAN->GetFirstCompatibleStyle( m_pCurGame, 1, cur_style->m_StepsType );
else
pStyle = GAMEMAN->GetFirstCompatibleStyle( m_pCurGame, GetNumSidesJoined(), m_pCurStyle->m_StepsType );
pStyle = GAMEMAN->GetFirstCompatibleStyle( m_pCurGame, GetNumSidesJoined(), cur_style->m_StepsType );
// use SetCurrentStyle in case of StyleType_OnePlayerTwoSides
SetCurrentStyle( pStyle );
SetCurrentStyle( pStyle, pn );
}
Message msg( MessageIDToString(Message_PlayerJoined) );
@@ -657,7 +671,7 @@ int GameState::GetNumStagesForCurrentSongAndStepsOrCourse() const
int iNumStagesOfThisSong = 1;
if( m_pCurSong )
{
const Style *pStyle = m_pCurStyle;
const Style *pStyle = GetCurrentStyle(PLAYER_INVALID);
int numSidesJoined = GetNumSidesJoined();
if( pStyle == NULL )
{
@@ -734,7 +748,12 @@ void GameState::BeginStage()
// only do this check with human players, assume CPU players (Rave)
// always have tokens. -aj (this could probably be moved below, even.)
if( !IsEventMode() && !IsCpuPlayer(p) )
ASSERT( m_iPlayerStageTokens[p] >= m_iNumStagesOfThisSong );
{
if(m_iPlayerStageTokens[p] < m_iNumStagesOfThisSong)
{
LuaHelpers::ReportScriptErrorFmt("Player %d only has %d stage tokens, but needs %d.", p, m_iPlayerStageTokens[p], m_iNumStagesOfThisSong);
}
}
m_iPlayerStageTokens[p] -= m_iNumStagesOfThisSong;
}
FOREACH_HumanPlayer( pn )
@@ -894,6 +913,170 @@ void GameState::SaveCurrentSettingsToProfile( PlayerNumber pn )
pProfile->m_lastCourse.FromCourse( m_pPreferredCourse );
}
bool GameState::CanSafelyEnterGameplay(RString& reason)
{
if(!IsCourseMode())
{
Song const* song= m_pCurSong;
if(song == NULL)
{
reason= "Current song is NULL.";
return false;
}
}
else
{
Course const* song= m_pCurCourse;
if(song == NULL)
{
reason= "Current course is NULL.";
return false;
}
}
FOREACH_EnabledPlayer(pn)
{
Style const* style= GetCurrentStyle(pn);
if(style == NULL)
{
reason= ssprintf("Style for player %d is NULL.", pn+1);
return false;
}
if(!IsCourseMode())
{
Steps const* steps= m_pCurSteps[pn];
if(steps == NULL)
{
reason= ssprintf("Steps for player %d is NULL.", pn+1);
return false;
}
if(steps->m_StepsType != style->m_StepsType)
{
reason= ssprintf("Player %d StepsType %s for steps does not equal "
"StepsType %s for style.", pn+1,
GAMEMAN->GetStepsTypeInfo(steps->m_StepsType).szName,
GAMEMAN->GetStepsTypeInfo(style->m_StepsType).szName);
return false;
}
if(steps->m_pSong != m_pCurSong)
{
reason= ssprintf("Steps for player %d are not for the current song.",
pn+1);
return false;
}
NoteData ndtemp;
steps->GetNoteData(ndtemp);
if(ndtemp.GetNumTracks() != style->m_iColsPerPlayer)
{
reason= ssprintf("Steps for player %d have %d columns, style has %d "
"columns.", pn+1, ndtemp.GetNumTracks(), style->m_iColsPerPlayer);
return false;
}
}
else
{
Trail const* steps= m_pCurTrail[pn];
if(steps == NULL)
{
reason= ssprintf("Steps for player %d is NULL.", pn+1);
return false;
}
if(steps->m_StepsType != style->m_StepsType)
{
reason= ssprintf("Player %d StepsType %s for steps does not equal "
"StepsType %s for style.", pn+1,
GAMEMAN->GetStepsTypeInfo(steps->m_StepsType).szName,
GAMEMAN->GetStepsTypeInfo(style->m_StepsType).szName);
return false;
}
}
}
return true;
}
void GameState::SetCompatibleStylesForPlayers()
{
bool style_set= false;
if(IsCourseMode())
{
if(m_pCurCourse != NULL)
{
const Style* style= m_pCurCourse->GetCourseStyle(m_pCurGame, GetNumSidesJoined());
if(style != NULL)
{
style_set= true;
SetCurrentStyle(style, PLAYER_INVALID);
}
}
else if(GetCurrentStyle(PLAYER_INVALID) == NULL)
{
vector<StepsType> vst;
GAMEMAN->GetStepsTypesForGame(m_pCurGame, vst);
const Style *style = GAMEMAN->GetFirstCompatibleStyle(
m_pCurGame, GetNumSidesJoined(), vst[0]);
SetCurrentStyle(style, PLAYER_INVALID);
}
}
if(!style_set)
{
FOREACH_EnabledPlayer(pn)
{
StepsType st= StepsType_Invalid;
if(m_pCurSteps[pn] != NULL)
{
st= m_pCurSteps[pn]->m_StepsType;
}
else if(m_pCurTrail[pn] != NULL)
{
st= m_pCurTrail[pn]->m_StepsType;
}
else
{
vector<StepsType> vst;
GAMEMAN->GetStepsTypesForGame(m_pCurGame, vst);
st= vst[0];
}
const Style *style = GAMEMAN->GetFirstCompatibleStyle(
m_pCurGame, GetNumSidesJoined(), st);
SetCurrentStyle(style, pn);
}
}
}
void GameState::ForceSharedSidesMatch()
{
PlayerNumber pn_with_shared= PLAYER_INVALID;
const Style* shared_style= NULL;
FOREACH_EnabledPlayer(pn)
{
const Style* style= GetCurrentStyle(pn);
ASSERT_M(style != NULL, "Style being null should not be possible.");
if(style->m_StyleType == StyleType_TwoPlayersSharedSides)
{
pn_with_shared= pn;
shared_style= style;
}
}
if(pn_with_shared != PLAYER_INVALID)
{
ASSERT_M(GetNumPlayersEnabled() == 2, "2 players must be enabled for shared sides.");
PlayerNumber other_pn= OPPOSITE_PLAYER[pn_with_shared];
const Style* other_style= GetCurrentStyle(other_pn);
ASSERT_M(other_style != NULL, "Other player's style being null should not be possible.");
if(other_style->m_StyleType != StyleType_TwoPlayersSharedSides)
{
SetCurrentStyle(shared_style, other_pn);
if(IsCourseMode())
{
m_pCurTrail[other_pn].Set(m_pCurTrail[pn_with_shared]);
}
else
{
m_pCurSteps[other_pn].Set(m_pCurSteps[pn_with_shared]);
}
}
}
}
void GameState::Update( float fDelta )
{
m_SongOptions.Update( fDelta );
@@ -1197,7 +1380,7 @@ RString GameState::GetPlayerDisplayName( PlayerNumber pn ) const
bool GameState::PlayersCanJoin() const
{
bool b = GetNumSidesJoined() == 0 || GetCurrentStyle() == NULL; // selecting a style finalizes the players
bool b = GetNumSidesJoined() == 0 || GetCurrentStyle(PLAYER_INVALID) == NULL; // selecting a style finalizes the players
if( ALLOW_LATE_JOIN.IsLoaded() && ALLOW_LATE_JOIN )
{
Screen *pScreen = SCREENMAN->GetTopScreen();
@@ -1216,39 +1399,69 @@ int GameState::GetNumSidesJoined() const
return iNumSidesJoined;
}
const Game* GameState::GetCurrentGame()
const Game* GameState::GetCurrentGame() const
{
ASSERT( m_pCurGame != NULL ); // the game must be set before calling this
return m_pCurGame;
}
const Style* GameState::GetCurrentStyle() const
const Style* GameState::GetCurrentStyle(PlayerNumber pn) const
{
return m_pCurStyle;
}
void GameState::SetCurrentStyle( const Style *pStyle )
{
m_pCurStyle.Set( pStyle );
if( INPUTMAPPER )
if(GetCurrentGame() == NULL) { return NULL; }
if(!GetCurrentGame()->m_PlayersHaveSeparateStyles)
{
if( GetCurrentStyle() && GetCurrentStyle()->m_StyleType == StyleType_OnePlayerTwoSides )
INPUTMAPPER->SetJoinControllers( this->GetMasterPlayerNumber() );
else
INPUTMAPPER->SetJoinControllers( PLAYER_INVALID );
return m_pCurStyle;
}
else
{
if(pn >= NUM_PLAYERS)
{
return m_SeparatedStyles[PLAYER_1] == NULL ? m_SeparatedStyles[PLAYER_2]
: m_SeparatedStyles[PLAYER_1];
}
return m_SeparatedStyles[pn];
}
}
bool GameState::SetCompatibleStyle(StepsType stype)
void GameState::SetCurrentStyle(const Style *style, PlayerNumber pn)
{
if(!GetCurrentGame()->m_PlayersHaveSeparateStyles)
{
m_pCurStyle.Set(style);
}
else
{
if(pn == PLAYER_INVALID)
{
FOREACH_PlayerNumber(rpn)
{
m_SeparatedStyles[rpn]= style;
}
}
else
{
m_SeparatedStyles[pn]= style;
}
}
if(INPUTMAPPER)
{
if(GetCurrentStyle(pn) && GetCurrentStyle(pn)->m_StyleType == StyleType_OnePlayerTwoSides)
INPUTMAPPER->SetJoinControllers(this->GetMasterPlayerNumber());
else
INPUTMAPPER->SetJoinControllers(PLAYER_INVALID);
}
}
bool GameState::SetCompatibleStyle(StepsType stype, PlayerNumber pn)
{
bool style_incompatible= false;
if(!m_pCurStyle)
if(!GetCurrentStyle(pn))
{
style_incompatible= true;
}
else
{
style_incompatible= stype != m_pCurStyle->m_StepsType;
style_incompatible= stype != GetCurrentStyle(pn)->m_StepsType;
}
if(CommonMetrics::AUTO_SET_STYLE && style_incompatible)
{
@@ -1258,9 +1471,9 @@ bool GameState::SetCompatibleStyle(StepsType stype)
{
return false;
}
SetCurrentStyle(compatible_style);
SetCurrentStyle(compatible_style, pn);
}
return stype == m_pCurStyle->m_StepsType;
return stype == GetCurrentStyle(pn)->m_StepsType;
}
bool GameState::IsPlayerEnabled( PlayerNumber pn ) const
@@ -1303,7 +1516,29 @@ bool GameState::IsHumanPlayer( PlayerNumber pn ) const
if( pn == PLAYER_INVALID )
return false;
if( GetCurrentStyle() == NULL ) // no style chosen
if(GetCurrentGame()->m_PlayersHaveSeparateStyles)
{
if( GetCurrentStyle(pn) == NULL ) // no style chosen
{
return m_bSideIsJoined[pn];
}
else
{
StyleType type = GetCurrentStyle(pn)->m_StyleType;
switch( type )
{
case StyleType_TwoPlayersTwoSides:
case StyleType_TwoPlayersSharedSides:
return true;
case StyleType_OnePlayerOneSide:
case StyleType_OnePlayerTwoSides:
return pn == this->GetMasterPlayerNumber();
default:
FAIL_M(ssprintf("Invalid style type: %i", type));
}
}
}
if( GetCurrentStyle(pn) == NULL ) // no style chosen
{
if( PlayersCanJoin() )
return m_bSideIsJoined[pn]; // only allow input from sides that have already joined
@@ -1311,7 +1546,7 @@ bool GameState::IsHumanPlayer( PlayerNumber pn ) const
return true; // if we can't join, then we're on a screen like MusicScroll or GameOver
}
StyleType type = GetCurrentStyle()->m_StyleType;
StyleType type = GetCurrentStyle(pn)->m_StyleType;
switch( type )
{
case StyleType_TwoPlayersTwoSides:
@@ -1669,7 +1904,7 @@ void GameState::GetRankingFeats( PlayerNumber pn, vector<RankingFeat> &asFeatsOu
{
CHECKPOINT;
StepsType st = GetCurrentStyle()->m_StepsType;
StepsType st = GetCurrentStyle(pn)->m_StepsType;
// Find unique Song and Steps combinations that were played.
// We must keep only the unique combination or else we'll double-count
@@ -2012,7 +2247,7 @@ bool GameState::DifficultiesLocked() const
return true;
if( IsCourseMode() )
return PREFSMAN->m_bLockCourseDifficulties;
if( GetCurrentStyle()->m_bLockDifficulties )
if( GetCurrentStyle(PLAYER_INVALID)->m_bLockDifficulties )
return true;
return false;
}
@@ -2099,7 +2334,7 @@ bool GameState::ChangePreferredCourseDifficulty( PlayerNumber pn, int dir )
return false;
if( find(v.begin(),v.end(),cd) == v.end() )
continue; /* not available */
if( !pCourse || pCourse->GetTrail( GetCurrentStyle()->m_StepsType, cd ) )
if( !pCourse || pCourse->GetTrail( GetCurrentStyle(pn)->m_StepsType, cd ) )
break;
}
@@ -2319,13 +2554,21 @@ public:
else { Song *pS = Luna<Song>::check( L, 1, true ); p->m_pCurSong.Set( pS ); }
COMMON_RETURN_SELF;
}
static void SetCompatibleStyleOrError(T* p, lua_State* L, StepsType stype)
static int CanSafelyEnterGameplay(T* p, lua_State* L)
{
if(!p->SetCompatibleStyle(stype))
RString reason;
bool can= p->CanSafelyEnterGameplay(reason);
lua_pushboolean(L, can);
LuaHelpers::Push(L, reason);
return 2;
}
static void SetCompatibleStyleOrError(T* p, lua_State* L, StepsType stype, PlayerNumber pn)
{
if(!p->SetCompatibleStyle(stype, pn))
{
luaL_error(L, "No compatible style for steps/trail.");
}
if(!p->m_pCurStyle)
if(!p->GetCurrentStyle(pn))
{
luaL_error(L, "No style set and AutoSetStyle is false, cannot set steps/trail.");
}
@@ -2348,7 +2591,7 @@ public:
else
{
Steps *pS = Luna<Steps>::check(L,2);
SetCompatibleStyleOrError(p, L, pS->m_StepsType);
SetCompatibleStyleOrError(p, L, pS->m_StepsType, pn);
p->m_pCurSteps[pn].Set(pS);
}
COMMON_RETURN_SELF;
@@ -2378,7 +2621,7 @@ public:
else
{
Trail *pS = Luna<Trail>::check(L,2);
SetCompatibleStyleOrError(p, L, pS->m_StepsType);
SetCompatibleStyleOrError(p, L, pS->m_StepsType, pn);
p->m_pCurTrail[pn].Set(pS);
}
COMMON_RETURN_SELF;
@@ -2579,7 +2822,8 @@ public:
}
static int GetCurrentStyle( T* p, lua_State *L )
{
Style *pStyle = const_cast<Style *> (p->GetCurrentStyle());
PlayerNumber pn= Enum::Check<PlayerNumber>(L, 1, true, true);
Style *pStyle = const_cast<Style *> (p->GetCurrentStyle(pn));
LuaHelpers::Push( L, pStyle );
return 1;
}
@@ -2732,9 +2976,9 @@ public:
static void ClearIncompatibleStepsAndTrails( T *p, lua_State* L )
{
const Style *style = p->m_pCurStyle;
FOREACH_HumanPlayer( pn )
{
const Style *style = p->GetCurrentStyle(pn);
if( p->m_pCurSteps[pn] && ( !style || style->m_StepsType != p->m_pCurSteps[pn]->m_StepsType ) )
{
p->m_pCurSteps[pn].Set( NULL );
@@ -2779,8 +3023,9 @@ public:
{
COMMON_RETURN_SELF;
}
PlayerNumber pn= Enum::Check<PlayerNumber>(L, 2, true, true);
p->SetCurrentStyle( pStyle );
p->SetCurrentStyle(pStyle, pn);
ClearIncompatibleStepsAndTrails( p, L );
COMMON_RETURN_SELF;
@@ -2789,13 +3034,92 @@ public:
static int SetCurrentPlayMode( T* p, lua_State *L )
{
PlayMode pm = Enum::Check<PlayMode>( L, 1 );
if( AreStyleAndPlayModeCompatible( p, L, p->m_pCurStyle, pm ) )
if( AreStyleAndPlayModeCompatible( p, L, p->GetCurrentStyle(PLAYER_INVALID), pm ) )
{
p->m_PlayMode.Set( pm );
}
COMMON_RETURN_SELF;
}
static int SetStepsForEditMode(T* p, lua_State *L)
{
// Arg forms:
// 1. Edit existing steps:
// song, steps
// 2. Create new steps to edit:
// song, nil, stepstype, difficulty
// 3. Copy steps to new difficulty to edit:
// song, steps, stepstype, difficulty
Song* song= Luna<Song>::check(L, 1);
Steps* steps= NULL;
if(!lua_isnil(L, 2))
{
steps= Luna<Steps>::check(L, 2);
}
// Form 1.
if(steps != NULL && lua_gettop(L) == 2)
{
p->m_pCurSong.Set(song);
p->m_pCurSteps[PLAYER_1].Set(steps);
p->SetCurrentStyle(GAMEMAN->GetEditorStyleForStepsType(
steps->m_StepsType), PLAYER_INVALID);
p->m_pCurCourse.Set(NULL);
return 0;
}
StepsType stype= Enum::Check<StepsType>(L, 3);
Difficulty diff= Enum::Check<Difficulty>(L, 4);
Steps* new_steps= song->CreateSteps();
RString edit_name;
// Form 2.
if(steps == NULL)
{
new_steps->CreateBlank(stype);
new_steps->SetMeter(1);
edit_name= "";
}
// Form 3.
else
{
new_steps->CopyFrom(steps, stype, song->m_fMusicLengthSeconds);
edit_name= steps->GetDescription();
}
SongUtil::MakeUniqueEditDescription(song, stype, edit_name);
steps->SetDescription(edit_name);
song->AddSteps(new_steps);
p->m_pCurSong.Set(song);
p->m_pCurSteps[PLAYER_1].Set(steps);
p->SetCurrentStyle(GAMEMAN->GetEditorStyleForStepsType(
steps->m_StepsType), PLAYER_INVALID);
p->m_pCurCourse.Set(NULL);
return 0;
}
static int GetAutoGenFarg(T* p, lua_State *L)
{
int i= IArg(1) - 1;
if(i < 0) { lua_pushnil(L); return 1; }
size_t si= static_cast<size_t>(i);
if(si >= p->m_autogen_fargs.size()) { lua_pushnil(L); return 1; }
lua_pushnumber(L, p->GetAutoGenFarg(si));
return 1;
}
static int SetAutoGenFarg(T* p, lua_State* L)
{
int i= IArg(1) - 1;
if(i < 0)
{
luaL_error(L, "%i is not a valid autogen arg index.", i);
}
float v= FArg(2);
size_t si= static_cast<size_t>(i);
while(si >= p->m_autogen_fargs.size())
{
p->m_autogen_fargs.push_back(0.0f);
}
p->m_autogen_fargs[si]= v;
COMMON_RETURN_SELF;
}
LunaGameState()
{
ADD_METHOD( IsPlayerEnabled );
@@ -2811,6 +3135,7 @@ public:
ADD_METHOD( GetPlayerState );
ADD_METHOD( GetMultiPlayerState );
ADD_METHOD( ApplyGameCommand );
ADD_METHOD( CanSafelyEnterGameplay );
ADD_METHOD( GetCurrentSong );
ADD_METHOD( SetCurrentSong );
ADD_METHOD( GetCurrentSteps );
@@ -2877,7 +3202,6 @@ public:
ADD_METHOD( IsWinner );
ADD_METHOD( IsDraw );
ADD_METHOD( GetCurrentGame );
//ADD_METHOD( SetCurrentGame );
ADD_METHOD( GetEditCourseEntryIndex );
ADD_METHOD( GetEditLocalProfileID );
ADD_METHOD( GetEditLocalProfile );
@@ -2919,6 +3243,9 @@ public:
ADD_METHOD( StoreRankingName );
ADD_METHOD( SetCurrentStyle );
ADD_METHOD( SetCurrentPlayMode );
ADD_METHOD( SetStepsForEditMode );
ADD_METHOD( GetAutoGenFarg );
ADD_METHOD( SetAutoGenFarg );
}
};
+21 -4
View File
@@ -73,6 +73,10 @@ public:
void SaveCurrentSettingsToProfile( PlayerNumber pn );
Song* GetDefaultSong() const;
bool CanSafelyEnterGameplay(RString& reason);
void SetCompatibleStylesForPlayers();
void ForceSharedSidesMatch();
void Update( float fDelta );
// Main state info
@@ -85,7 +89,11 @@ public:
* @param pGame the game to start using. */
void SetCurGame( const Game *pGame );
BroadcastOnChangePtr<const Game> m_pCurGame;
private: // DO NOT access directly. Use Get/SetCurrentStyle.
BroadcastOnChangePtr<const Style> m_pCurStyle;
// Only used if the Game specifies that styles are separate.
Style const* m_SeparatedStyles[NUM_PlayerNumber];
public:
/** @brief Determine which side is joined.
*
* The left side is player 1, and the right side is player 2. */
@@ -127,10 +135,10 @@ public:
bool EnoughCreditsToJoin() const { return m_iCoins >= GetCoinsNeededToJoin(); }
int GetNumSidesJoined() const;
const Game* GetCurrentGame();
const Style* GetCurrentStyle() const;
void SetCurrentStyle( const Style *pStyle );
bool SetCompatibleStyle(StepsType stype);
const Game* GetCurrentGame() const;
const Style* GetCurrentStyle(PlayerNumber pn) const;
void SetCurrentStyle(const Style *style, PlayerNumber pn);
bool SetCompatibleStyle(StepsType stype, PlayerNumber pn);
void GetPlayerInfo( PlayerNumber pn, bool& bIsEnabledOut, bool& bIsHumanOut );
bool IsPlayerEnabled( PlayerNumber pn ) const;
@@ -396,6 +404,15 @@ public:
bool m_bDopefish;
// Autogen stuff. This should probably be moved to its own singleton or
// something when autogen is generalized and more customizable. -Kyz
float GetAutoGenFarg(size_t i)
{
if(i >= m_autogen_fargs.size()) { return 0.0f; }
return m_autogen_fargs[i];
}
vector<float> m_autogen_fargs;
// Lua
void PushSelf( lua_State *L );
+17 -19
View File
@@ -15,17 +15,18 @@ void GhostArrowRow::Load( const PlayerState* pPlayerState, float fYReverseOffset
m_pPlayerState = pPlayerState;
m_fYReverseOffsetPixels = fYReverseOffset;
const Style* pStyle = GAMESTATE->GetCurrentStyle();
const PlayerNumber pn = m_pPlayerState->m_PlayerNumber;
const Style* pStyle = GAMESTATE->GetCurrentStyle(pn);
NOTESKIN->SetPlayerNumber( pn );
// init arrows
for( int c=0; c<pStyle->m_iColsPerPlayer; c++ )
{
const RString &sButton = GAMESTATE->GetCurrentStyle()->ColToButtonName( c );
const RString &sButton = GAMESTATE->GetCurrentStyle(pn)->ColToButtonName( c );
const GameInput GameI = GAMESTATE->GetCurrentStyle()->StyleInputToGameInput( c, pn );
NOTESKIN->SetGameController( GameI.controller );
vector<GameInput> GameI;
GAMESTATE->GetCurrentStyle(pn)->StyleInputToGameInput( c, pn, GameI );
NOTESKIN->SetGameController( GameI[0].controller );
m_bHoldShowing.push_back( TapNoteSubType_Invalid );
m_bLastHoldShowing.push_back( TapNoteSubType_Invalid );
@@ -35,6 +36,16 @@ void GhostArrowRow::Load( const PlayerState* pPlayerState, float fYReverseOffset
}
}
void GhostArrowRow::SetColumnRenderers(vector<NoteColumnRenderer>& renderers)
{
ASSERT_M(renderers.size() == m_Ghost.size(), "Notefield has different number of columns than ghost row.");
for(size_t c= 0; c < m_Ghost.size(); ++c)
{
m_Ghost[c]->SetFakeParent(&(renderers[c]));
}
m_renderers= &renderers;
}
GhostArrowRow::~GhostArrowRow()
{
for( unsigned i = 0; i < m_Ghost.size(); ++i )
@@ -47,20 +58,7 @@ void GhostArrowRow::Update( float fDeltaTime )
for( unsigned c=0; c<m_Ghost.size(); c++ )
{
m_Ghost[c]->Update( fDeltaTime );
float fX = ArrowEffects::GetXPos( m_pPlayerState, c, 0 );
float fY = ArrowEffects::GetYPos( m_pPlayerState, c, 0, m_fYReverseOffsetPixels );
float fZ = ArrowEffects::GetZPos( m_pPlayerState, c, 0 );
m_Ghost[c]->SetX( fX );
m_Ghost[c]->SetY( fY );
m_Ghost[c]->SetZ( fZ );
const float fRotation = ArrowEffects::ReceptorGetRotationZ( m_pPlayerState );
m_Ghost[c]->SetRotationZ( fRotation );
const float fZoom = ArrowEffects::GetZoom( m_pPlayerState );
m_Ghost[c]->SetZoom( fZoom );
(*m_renderers)[c].UpdateReceptorGhostStuff(m_Ghost[c]);
}
for( unsigned i = 0; i < m_bHoldShowing.size(); ++i )
@@ -92,7 +90,7 @@ void GhostArrowRow::Update( float fDeltaTime )
void GhostArrowRow::DrawPrimitives()
{
const Style* pStyle = GAMESTATE->GetCurrentStyle();
const Style* pStyle = GAMESTATE->GetCurrentStyle(m_pPlayerState->m_PlayerNumber);
for( unsigned i=0; i<m_Ghost.size(); i++ )
{
const int c = pStyle->m_iColumnDrawOrder[i];
+3
View File
@@ -4,6 +4,7 @@
#include "ActorFrame.h"
#include "GameConstantsAndTypes.h"
#include "NoteTypes.h"
#include "NoteDisplay.h"
class PlayerState;
/** @brief Row of GhostArrow Actors. */
@@ -15,6 +16,7 @@ public:
virtual void DrawPrimitives();
void Load( const PlayerState* pPlayerState, float fYReverseOffset );
void SetColumnRenderers(vector<NoteColumnRenderer>& renderers);
void DidTapNote( int iCol, TapNoteScore tns, bool bBright );
void DidHoldNote( int iCol, HoldNoteScore hns, bool bBright );
@@ -24,6 +26,7 @@ protected:
float m_fYReverseOffsetPixels;
const PlayerState* m_pPlayerState;
vector<NoteColumnRenderer> const* m_renderers;
vector<Actor *> m_Ghost;
vector<TapNoteSubType> m_bHoldShowing;
vector<TapNoteSubType> m_bLastHoldShowing;
+8
View File
@@ -288,6 +288,14 @@ public:
{
StageStats *pStageStats = Luna<StageStats>::check( L, 1 );
PlayerStageStats *pPlayerStageStats = Luna<PlayerStageStats>::check( L, 2 );
if(pStageStats == NULL)
{
luaL_error(L, "The StageStats passed to GraphDisplay:Set are nil.");
}
if(pPlayerStageStats == NULL)
{
luaL_error(L, "The PlayerStageStats passed to GraphDisplay:Set are nil.");
}
p->Set( *pStageStats, *pPlayerStageStats );
COMMON_RETURN_SELF;
}
+10
View File
@@ -910,6 +910,16 @@ bool InputMapper::IsBeingPressed( GameButton MenuI, PlayerNumber pn ) const
return false;
}
bool InputMapper::IsBeingPressed(const vector<GameInput>& GameI, MultiPlayer mp, const DeviceInputList *pButtonState ) const
{
bool pressed= false;
for(size_t i= 0; i < GameI.size(); ++i)
{
pressed |= IsBeingPressed(GameI[i], mp, pButtonState);
}
return pressed;
}
void InputMapper::RepeatStopKey( const GameInput &GameI )
{
for( int i=0; i<NUM_GAME_TO_DEVICE_SLOTS; i++ )
+1
View File
@@ -179,6 +179,7 @@ public:
bool IsBeingPressed( const GameInput &GameI, MultiPlayer mp = MultiPlayer_Invalid, const DeviceInputList *pButtonState = NULL ) const;
bool IsBeingPressed( GameButton MenuI, PlayerNumber pn ) const;
bool IsBeingPressed(const vector<GameInput>& GameI, MultiPlayer mp = MultiPlayer_Invalid, const DeviceInputList *pButtonState = NULL ) const;
void ResetKeyRepeat( const GameInput &GameI );
void ResetKeyRepeat( GameButton MenuI, PlayerNumber pn );
+7 -3
View File
@@ -80,10 +80,14 @@ static void GetUsedGameInputs( vector<GameInput> &vGameInputsOut )
{
for( int iCol=0; iCol<(*style)->m_iColsPerPlayer; ++iCol )
{
GameInput gi = (*style)->StyleInputToGameInput( iCol, pn );
if( gi.IsValid() )
vector<GameInput> gi;
(*style)->StyleInputToGameInput( iCol, pn, gi );
for(size_t i= 0; i < gi.size(); ++i)
{
vGIs.insert( gi );
if(gi[i].IsValid())
{
vGIs.insert(gi[i]);
}
}
}
}
+13
View File
@@ -257,6 +257,19 @@ inline bool TableContainsOnlyStrings(lua_State* L, int index)
#define BArg(n) (MyLua_checkboolean(L,(n)))
#define FArg(n) ((float) luaL_checknumber(L,(n)))
// SafeFArg is for places that need to get a number off the lua stack, but
// can't risk an error being raised. IArg and luaL_optnumber would both raise
// an error on a type mismatch. -Kyz
inline int SafeFArg(lua_State* L, int index, RString const& err, int def)
{
if(lua_isnumber(L, index))
{
return lua_tonumber(L, index);
}
LuaHelpers::ReportScriptError(err);
return def;
}
#define LuaFunction( func, expr ) \
int LuaFunc_##func( lua_State *L ); \
int LuaFunc_##func( lua_State *L ) { \
+17 -8
View File
@@ -14,7 +14,7 @@ if BUILD_TESTS
endif
AM_LDFLAGS =
AM_CXXFLAGS =
AM_CXXFLAGS =
AM_CFLAGS =
noinst_LIBRARIES =
EXTRA_DIST =
@@ -28,12 +28,10 @@ AM_CXXFLAGS += -finline-limit=300
AM_CXXFLAGS += $(GL_CFLAGS)
.PHONY: increment_version
all: increment_version
.PHONY: increment_version gitversion
increment_version:
if test -e ver.cpp; then \
if test -e ver.h; then \
build=`sed -rs 's/.*version_num = ([[:digit:]]+);/\1/;q' ver.cpp`; \
build=`expr $$build + 1`; \
else \
@@ -43,8 +41,18 @@ increment_version:
echo "extern const char *const version_time = \"`date +"%X %Z (UTC%:z)"`\";" >> ver.cpp;
echo "extern const char *const version_date = \"`date +"%Y%m%d"`\";" >> ver.cpp;
ver.cpp:
$(MAKE) increment_version
ver.cpp: increment_version
gitversion:
rm -f gitversion.h
touch gitversion.h
if git rev-parse --short HEAD; then \
echo "#define PRODUCT_VER_BARE 5.0-git-`git rev-parse --short HEAD`" > gitversion.h; \
fi
gitversion.h: gitversion
BUILT_SOURCES = gitversion.h ver.cpp
PNG = \
../extern/libpng/include/png.c ../extern/libpng/include/.png.h \
@@ -516,6 +524,7 @@ RageFileDriverSlice.cpp RageFileDriverSlice.h \
RageFileDriverTimeout.cpp RageFileDriverTimeout.h
Rage = $(PCRE) $(Lua) $(jsoncpp) $(RageFile) $(RageSoundFileReaders) \
CubicSpline.cpp CubicSpline.h \
RageBitmapTexture.cpp RageBitmapTexture.h \
RageDisplay.cpp RageDisplay.h \
RageDisplay_OGL.cpp RageDisplay_OGL.h \
@@ -736,7 +745,7 @@ main_LDADD = \
$(GL_LIBS) \
libtomcrypt.a libtommath.a
nodist_stepmania_SOURCES = ver.cpp
nodist_stepmania_SOURCES = ver.cpp gitversion.h
stepmania_CPPFLAGS = $(main_CPPFLAGS)
stepmania_SOURCES = $(main_SOURCES)
+10 -10
View File
@@ -445,7 +445,7 @@ void MusicWheel::GetSongList( vector<Song*> &arraySongs, SortOrder so )
if( PREFSMAN->m_bOnlyPreferredDifficulties )
{
// if the song has steps that fit the preferred difficulty of the default player
if( pSong->HasStepsTypeAndDifficulty( GAMESTATE->GetCurrentStyle()->m_StepsType,GAMESTATE->m_PreferredDifficulty[GAMESTATE->GetFirstHumanPlayer()] ) )
if( pSong->HasStepsTypeAndDifficulty( GAMESTATE->GetCurrentStyle(PLAYER_INVALID)->m_StepsType,GAMESTATE->m_PreferredDifficulty[GAMESTATE->GetFirstHumanPlayer()] ) )
arraySongs.push_back( pSong );
}
else
@@ -472,7 +472,7 @@ void MusicWheel::GetSongList( vector<Song*> &arraySongs, SortOrder so )
else
{
// If the song has at least one steps, add it.
if( pSong->HasStepsType(GAMESTATE->GetCurrentStyle()->m_StepsType) )
if( pSong->HasStepsType(GAMESTATE->GetCurrentStyle(PLAYER_INVALID)->m_StepsType) )
arraySongs.push_back( pSong );
}
}
@@ -484,7 +484,7 @@ void MusicWheel::GetSongList( vector<Song*> &arraySongs, SortOrder so )
{
Song* pSong;
Steps* pSteps;
SONGMAN->GetExtraStageInfo( GAMESTATE->IsExtraStage2(), GAMESTATE->GetCurrentStyle(), pSong, pSteps );
SONGMAN->GetExtraStageInfo( GAMESTATE->IsExtraStage2(), GAMESTATE->GetCurrentStyle(PLAYER_INVALID), pSong, pSteps );
if( find( arraySongs.begin(), arraySongs.end(), pSong ) == arraySongs.end() )
arraySongs.push_back( pSong );
@@ -728,7 +728,7 @@ void MusicWheel::BuildWheelItemDatas( vector<MusicWheelItemData *> &arrayWheelIt
{
Song* pSong;
Steps* pSteps;
SONGMAN->GetExtraStageInfo( GAMESTATE->IsExtraStage2(), GAMESTATE->GetCurrentStyle(), pSong, pSteps );
SONGMAN->GetExtraStageInfo( GAMESTATE->IsExtraStage2(), GAMESTATE->GetCurrentStyle(PLAYER_INVALID), pSong, pSteps );
for( unsigned i=0; i<arrayWheelItemDatas.size(); i++ )
{
@@ -830,7 +830,7 @@ void MusicWheel::BuildWheelItemDatas( vector<MusicWheelItemData *> &arrayWheelIt
}
// check that this course has at least one song playable in the current style
if( !pCourse->IsPlayableIn(GAMESTATE->GetCurrentStyle()->m_StepsType) )
if( !pCourse->IsPlayableIn(GAMESTATE->GetCurrentStyle(PLAYER_INVALID)->m_StepsType) )
continue;
if( sThisSection != sLastSection ) // new section, make a section item
@@ -856,7 +856,7 @@ void MusicWheel::BuildWheelItemDatas( vector<MusicWheelItemData *> &arrayWheelIt
MusicWheelItemData& WID = *arrayWheelItemDatas[i];
if( WID.m_pSong != NULL )
{
WID.m_Flags.bHasBeginnerOr1Meter = WID.m_pSong->IsEasy( GAMESTATE->GetCurrentStyle()->m_StepsType ) && SHOW_EASY_FLAG;
WID.m_Flags.bHasBeginnerOr1Meter = WID.m_pSong->IsEasy( GAMESTATE->GetCurrentStyle(PLAYER_INVALID)->m_StepsType ) && SHOW_EASY_FLAG;
WID.m_Flags.bEdits = false;
set<StepsType> vStepsType;
SongUtil::GetPlayableStepsTypes( WID.m_pSong, vStepsType );
@@ -919,7 +919,7 @@ void MusicWheel::FilterWheelItemDatas(vector<MusicWheelItemData *> &aUnFilteredD
if( GAMESTATE->IsAnExtraStage() )
{
Steps *pSteps;
SONGMAN->GetExtraStageInfo( GAMESTATE->IsExtraStage2(), GAMESTATE->GetCurrentStyle(), pExtraStageSong, pSteps );
SONGMAN->GetExtraStageInfo( GAMESTATE->IsExtraStage2(), GAMESTATE->GetCurrentStyle(PLAYER_INVALID), pExtraStageSong, pSteps );
}
/* Mark any songs that aren't playable in aiRemove. */
@@ -984,7 +984,7 @@ void MusicWheel::FilterWheelItemDatas(vector<MusicWheelItemData *> &aUnFilteredD
}
/* If the song has no steps for the current style, remove it. */
if( !CommonMetrics::AUTO_SET_STYLE && !pSong->HasStepsType(GAMESTATE->GetCurrentStyle()->m_StepsType) )
if( !CommonMetrics::AUTO_SET_STYLE && !pSong->HasStepsType(GAMESTATE->GetCurrentStyle(PLAYER_INVALID)->m_StepsType) )
{
aiRemove[i] = true;
continue;
@@ -1000,7 +1000,7 @@ void MusicWheel::FilterWheelItemDatas(vector<MusicWheelItemData *> &aUnFilteredD
if( WID.m_Type == WheelItemDataType_Course )
{
if( !WID.m_pCourse->IsPlayableIn(GAMESTATE->GetCurrentStyle()->m_StepsType) )
if( !WID.m_pCourse->IsPlayableIn(GAMESTATE->GetCurrentStyle(PLAYER_INVALID)->m_StepsType) )
aiRemove[i] = true;
}
}
@@ -1573,7 +1573,7 @@ Song *MusicWheel::GetPreferredSelectionForRandomOrPortal()
RString sPreferredGroup = m_sExpandedSectionName;
vector<MusicWheelItemData *> &wid = getWheelItemsData(GAMESTATE->m_SortOrder);
StepsType st = GAMESTATE->GetCurrentStyle()->m_StepsType;
StepsType st = GAMESTATE->GetCurrentStyle(PLAYER_INVALID)->m_StepsType;
#define NUM_PROBES 1000
for( int i=0; i<NUM_PROBES; i++ )
+1 -1
View File
@@ -338,7 +338,7 @@ void MusicWheelItem::RefreshGrades()
else if( GAMESTATE->m_pCurTrail[p] )
st = GAMESTATE->m_pCurTrail[p]->m_StepsType;
else
st = GAMESTATE->m_pCurStyle->m_StepsType;
st = GAMESTATE->GetCurrentStyle(PLAYER_INVALID)->m_StepsType;
m_pGradeDisplay[p]->SetVisible( true );
+1 -1
View File
@@ -642,7 +642,7 @@ void NetworkSyncManager::ProcessInput()
StyleName = m_packet.ReadNT();
GAMESTATE->SetCurGame( GAMEMAN->StringToGame(GameName) );
GAMESTATE->SetCurrentStyle( GAMEMAN->GameAndStringToStyle(GAMESTATE->m_pCurGame,StyleName) );
GAMESTATE->SetCurrentStyle( GAMEMAN->GameAndStringToStyle(GAMESTATE->m_pCurGame,StyleName), PLAYER_INVALID );
SCREENMAN->SetNewScreen( "ScreenNetSelectMusic" ); //Should this be metric'd out?
}
+265 -1
View File
@@ -454,7 +454,7 @@ void NoteDataUtil::SplitCompositeNoteData( const NoteData &in, vector<NoteData>
occuring to begin with, but at this time, I am unsure how to deal with it.
Hopefully this hack can be removed soon. -- Jason "Wolfman2000" Felds
*/
const Style *curStyle = GAMESTATE->GetCurrentStyle();
const Style *curStyle = GAMESTATE->GetCurrentStyle(PLAYER_INVALID);
if( (curStyle == NULL || curStyle->m_StyleType == StyleType_TwoPlayersSharedSides )
&& int( tn.pn ) > NUM_PlayerNumber )
{
@@ -781,6 +781,174 @@ void NoteDataUtil::LoadTransformedLightsFromTwo( const NoteData &marquee, const
NoteDataUtil::RemoveMines( out );
}
// This kickbox_limb enum should not be used anywhere outside the
// Autogenkickbox function. -Kyz
enum kickbox_limb
{
left_foot, left_fist, right_fist, right_foot, num_kickbox_limbs, invalid_limb= -1
};
void NoteDataUtil::AutogenKickbox(const NoteData& in, NoteData& out, const TimingData& timing, StepsType out_type, int nonrandom_seed)
{
// Each limb has its own list of tracks it is used for. This allows
// abstract handling of the different styles.
// By convention, the lower panels are pushed first. This gives the upper
// panels a higher index, which is mnemonically useful.
vector<vector<int> > limb_tracks(num_kickbox_limbs);
bool have_feet= true;
switch(out_type)
{
case StepsType_kickbox_human:
out.SetNumTracks(4);
limb_tracks[left_foot].push_back(0);
limb_tracks[left_fist].push_back(1);
limb_tracks[right_fist].push_back(2);
limb_tracks[right_foot].push_back(3);
break;
case StepsType_kickbox_quadarm:
out.SetNumTracks(4);
have_feet= false;
limb_tracks[left_fist].push_back(1);
limb_tracks[left_fist].push_back(0);
limb_tracks[right_fist].push_back(2);
limb_tracks[right_fist].push_back(3);
break;
case StepsType_kickbox_insect:
out.SetNumTracks(6);
limb_tracks[left_foot].push_back(0);
limb_tracks[left_fist].push_back(2);
limb_tracks[left_fist].push_back(1);
limb_tracks[right_fist].push_back(3);
limb_tracks[right_fist].push_back(4);
limb_tracks[right_foot].push_back(5);
break;
case StepsType_kickbox_arachnid:
out.SetNumTracks(8);
limb_tracks[left_foot].push_back(0);
limb_tracks[left_foot].push_back(1);
limb_tracks[left_fist].push_back(3);
limb_tracks[left_fist].push_back(2);
limb_tracks[right_fist].push_back(4);
limb_tracks[right_fist].push_back(5);
limb_tracks[right_foot].push_back(7);
limb_tracks[right_foot].push_back(6);
break;
DEFAULT_FAIL(out_type);
}
// prev_limb_panels keeps track of which panel in the track list the limb
// hit last.
vector<size_t> prev_limb_panels(num_kickbox_limbs, 0);
vector<int> panel_repeat_counts(num_kickbox_limbs, 0);
vector<int> panel_repeat_goals(num_kickbox_limbs, 0);
RandomGen rnd(nonrandom_seed);
kickbox_limb prev_limb_used= invalid_limb;
// Kicks are only allowed if there is enough setup/recovery time.
float kick_recover_time= GAMESTATE->GetAutoGenFarg(0);
if(kick_recover_time <= 0.0f)
{
kick_recover_time= .25f;
}
float prev_note_time= -1.0f;
int rows_done= 0;
#define RAND_FIST ((rnd() % 2) ? left_fist : right_fist)
#define RAND_FOOT ((rnd() % 2) ? left_foot : right_foot)
FOREACH_NONEMPTY_ROW_ALL_TRACKS(in, r)
{
// Arbitrary: Drop everything except taps and hold heads out entirely,
// convert holds to tap just the head.
bool has_valid_tapnote= false;
for(int t= 0; t < in.GetNumTracks(); ++t)
{
const TapNote& tn= in.GetTapNote(t, r);
if(tn.type == TapNoteType_Tap || tn.type == TapNoteType_HoldHead)
{
has_valid_tapnote= true;
break;
}
}
if(!has_valid_tapnote) { continue; }
int next_row= r;
bool next_has_valid= false;
while(!next_has_valid)
{
if(!in.GetNextTapNoteRowForAllTracks(next_row))
{
next_row= -1;
next_has_valid= true;
}
else
{
for(int t= 0; t < in.GetNumTracks(); ++t)
{
const TapNote& tn= in.GetTapNote(t, next_row);
if(tn.type == TapNoteType_Tap || tn.type == TapNoteType_HoldHead)
{
next_has_valid= true;
break;
}
}
}
}
float this_note_time= timing.GetElapsedTimeFromBeat(NoteRowToBeat(r));
float next_note_time= timing.GetElapsedTimeFromBeat(NoteRowToBeat(next_row));
kickbox_limb this_limb= invalid_limb;
switch(prev_limb_used)
{
case invalid_limb:
// First limb is arbitrarily always a fist.
this_limb= RAND_FIST;
break;
case left_foot:
case right_foot:
// Multiple kicks in a row are allowed if they're on the same foot.
// Allow the last note to be a kick.
// Switch feet if there's enough time.
if(next_note_time - this_note_time > kick_recover_time * 2.0f)
{
this_limb= prev_limb_used == left_foot ? right_foot : left_foot;
}
else if((next_note_time - this_note_time > kick_recover_time * .5f ||
next_note_time < 0.0f) && (rnd() % 2))
{
this_limb= prev_limb_used;
}
else
{
this_limb= RAND_FIST;
}
break;
case left_fist:
case right_fist:
if(this_note_time - prev_note_time > kick_recover_time &&
(next_note_time - this_note_time > kick_recover_time ||
next_note_time < 0.0f) && have_feet)
{
this_limb= RAND_FOOT;
}
else
{
// Alternate fists.
this_limb= prev_limb_used == left_fist ? right_fist : left_fist;
}
break;
}
size_t this_panel= prev_limb_panels[this_limb];
if(panel_repeat_counts[this_limb] + 1 > panel_repeat_goals[this_limb])
{
// Use a different panel.
this_panel= (this_panel + 1) % limb_tracks[this_limb].size();
panel_repeat_counts[this_limb]= 0;
panel_repeat_goals[this_limb]= (rnd() % 8) + 1;
}
out.SetTapNote(limb_tracks[this_limb][this_panel], r, TAP_ORIGINAL_TAP);
++panel_repeat_counts[this_limb];
prev_limb_panels[this_limb]= this_panel;
prev_note_time= this_note_time;
prev_limb_used= this_limb;
++rows_done;
}
out.RevalidateATIs(vector<int>(), false);
}
RadarStats CalculateRadarStatsFast( const NoteData &in, RadarStats &out )
{
out.taps = 0;
@@ -1411,6 +1579,72 @@ static void GetTrackMapping( StepsType st, NoteDataUtil::TrackMapping tt, int Nu
iTakeFromTrack[8] = 0;
iTakeFromTrack[9] = 1;
break;
case StepsType_kickbox_human:
if(iRandChoice == 1)
{
iTakeFromTrack[0]= 3;
iTakeFromTrack[3]= 0;
}
if(iRandChoice == 2)
{
iTakeFromTrack[1]= 2;
iTakeFromTrack[2]= 1;
}
break;
case StepsType_kickbox_quadarm:
if(iRandChoice == 1)
{
iTakeFromTrack[0]= 1;
iTakeFromTrack[1]= 0;
iTakeFromTrack[2]= 3;
iTakeFromTrack[3]= 2;
}
if(iRandChoice == 2)
{
iTakeFromTrack[1]= 2;
iTakeFromTrack[2]= 1;
}
break;
case StepsType_kickbox_insect:
if(iRandChoice == 1)
{
iTakeFromTrack[1]= 2;
iTakeFromTrack[2]= 1;
iTakeFromTrack[3]= 4;
iTakeFromTrack[4]= 3;
}
if(iRandChoice == 2)
{
iTakeFromTrack[1]= 4;
iTakeFromTrack[2]= 3;
iTakeFromTrack[3]= 2;
iTakeFromTrack[4]= 1;
}
break;
case StepsType_kickbox_arachnid:
if(iRandChoice == 1)
{
iTakeFromTrack[0]= 1;
iTakeFromTrack[1]= 0;
iTakeFromTrack[2]= 3;
iTakeFromTrack[3]= 2;
iTakeFromTrack[4]= 5;
iTakeFromTrack[5]= 4;
iTakeFromTrack[6]= 7;
iTakeFromTrack[7]= 6;
}
if(iRandChoice == 2)
{
iTakeFromTrack[0]= 6;
iTakeFromTrack[1]= 7;
iTakeFromTrack[2]= 4;
iTakeFromTrack[3]= 5;
iTakeFromTrack[4]= 2;
iTakeFromTrack[5]= 3;
iTakeFromTrack[6]= 0;
iTakeFromTrack[7]= 1;
}
break;
default: break;
}
break;
@@ -1449,6 +1683,36 @@ static void GetTrackMapping( StepsType st, NoteDataUtil::TrackMapping tt, int Nu
iTakeFromTrack[6] = 7;
iTakeFromTrack[7] = 6;
break;
case StepsType_kickbox_human:
iTakeFromTrack[0]= 1;
iTakeFromTrack[1]= 0;
iTakeFromTrack[2]= 3;
iTakeFromTrack[3]= 2;
break;
case StepsType_kickbox_quadarm:
iTakeFromTrack[0]= 1;
iTakeFromTrack[1]= 0;
iTakeFromTrack[2]= 3;
iTakeFromTrack[3]= 2;
break;
case StepsType_kickbox_insect:
iTakeFromTrack[0]= 1;
iTakeFromTrack[1]= 4;
iTakeFromTrack[2]= 3;
iTakeFromTrack[3]= 2;
iTakeFromTrack[4]= 1;
iTakeFromTrack[5]= 4;
break;
case StepsType_kickbox_arachnid:
iTakeFromTrack[0]= 5;
iTakeFromTrack[1]= 4;
iTakeFromTrack[2]= 5;
iTakeFromTrack[3]= 4;
iTakeFromTrack[4]= 3;
iTakeFromTrack[5]= 2;
iTakeFromTrack[6]= 1;
iTakeFromTrack[7]= 0;
break;
default:
break;
}
+5
View File
@@ -63,6 +63,11 @@ namespace NoteDataUtil
void LoadTransformedLightsFromTwo( const NoteData &marquee, const NoteData &bass, NoteData &out );
void InsertHoldTails( NoteData &inout );
// Special case so that kickbox can have autogen steps that are playable.
// Hopefully I'll replace this with a good generalized autogen system
// later. -Kyz
void AutogenKickbox(const NoteData& in, NoteData& out, const TimingData& timing, StepsType out_type, int nonrandom_seed);
// radar values - return between 0.0 and 1.2
float GetStreamRadarValue( const NoteData &in, float fSongSeconds );
float GetVoltageRadarValue( const NoteData &in, float fSongSeconds );
+850 -107
View File
File diff suppressed because it is too large Load Diff
+184 -21
View File
@@ -1,13 +1,17 @@
#ifndef NOTE_DISPLAY_H
#define NOTE_DISPLAY_H
#include "ActorFrame.h"
#include "CubicSpline.h"
#include "NoteData.h"
#include "PlayerNumber.h"
#include "GameInput.h"
class Actor;
class Sprite;
class Model;
class PlayerState;
class GhostArrowRow;
class ReceptorArrowRow;
struct TapNote;
struct HoldNoteResult;
struct NoteMetricCache_t;
@@ -83,6 +87,88 @@ enum ActiveType
#define FOREACH_ActiveType( i ) FOREACH_ENUM( ActiveType, i )
const RString &ActiveTypeToString( ActiveType at );
enum NoteColumnSplineMode
{
NCSM_Disabled,
NCSM_Offset,
NCSM_Position,
NUM_NoteColumnSplineMode,
NoteColumnSplineMode_Invalid
};
const RString& NoteColumnSplineModeToString(NoteColumnSplineMode ncsm);
LuaDeclareType(NoteColumnSplineMode);
// A little pod struct to carry the data the NoteField needs to pass to the
// NoteDisplay during rendering.
struct NoteFieldRenderArgs
{
const PlayerState* player_state; // to look up PlayerOptions
float reverse_offset_pixels;
ReceptorArrowRow* receptor_row;
GhostArrowRow* ghost_row;
const NoteData* note_data;
float first_beat;
float last_beat;
int first_row;
int last_row;
float draw_pixels_before_targets;
float draw_pixels_after_targets;
int* selection_begin_marker;
int* selection_end_marker;
float selection_glow;
float fail_fade;
float fade_before_targets;
};
// NCSplineHandler exists to allow NoteColumnRenderer to have separate
// splines for position, rotation, and zoom, while concisely presenting the
// same interface for all three.
struct NCSplineHandler
{
NCSplineHandler()
{
m_spline.redimension(3);
m_spline.m_owned_by_actor= true;
m_spline_mode= NCSM_Disabled;
m_receptor_t= 0.0f;
m_beats_per_t= 1.0f;
m_subtract_song_beat_from_curr= true;
}
float BeatToTValue(float song_beat, float note_beat) const;
void EvalForBeat(float song_beat, float note_beat, vector<float>& ret) const;
void EvalDerivForBeat(float song_beat, float note_beat, vector<float>& ret) const;
void EvalForReceptor(float song_beat, vector<float>& ret) const;
static void MakeWeightedAverage(NCSplineHandler& out,
const NCSplineHandler& from, const NCSplineHandler& to, float between);
CubicSplineN m_spline;
NoteColumnSplineMode m_spline_mode;
float m_receptor_t;
float m_beats_per_t;
bool m_subtract_song_beat_from_curr;
void PushSelf(lua_State* L);
};
struct NoteColumnRenderArgs
{
void spae_pos_for_beat(const PlayerState* state,
float beat, float y_offset, float y_reverse_offset,
vector<float>& sp_pos, vector<float>& ae_pos) const;
void spae_zoom_for_beat(const PlayerState* state, float beat,
vector<float>& sp_zoom, vector<float>& ae_zoom) const;
void SetPRZForActor(Actor* actor,
const vector<float>& sp_pos, const vector<float>& ae_pos,
const vector<float>& sp_rot, const vector<float>& ae_rot,
const vector<float>& sp_zoom, const vector<float>& ae_zoom) const;
const NCSplineHandler* pos_handler;
const NCSplineHandler* rot_handler;
const NCSplineHandler* zoom_handler;
float song_beat;
int column;
};
/** @brief Draws TapNotes and HoldNotes. */
class NoteDisplay
{
@@ -94,6 +180,14 @@ public:
static void Update( float fDeltaTime );
bool IsOnScreen( float fBeat, int iCol, int iDrawDistanceAfterTargetsPixels, int iDrawDistanceBeforeTargetsPixels ) const;
bool DrawHoldsInRange(const NoteFieldRenderArgs& field_args,
const NoteColumnRenderArgs& column_args,
const vector<NoteData::TrackMap::const_iterator>& tap_set);
bool DrawTapsInRange(const NoteFieldRenderArgs& field_args,
const NoteColumnRenderArgs& column_args,
const vector<NoteData::TrackMap::const_iterator>& tap_set);
/**
* @brief Draw the TapNote onto the NoteField.
* @param tn the TapNote in question.
@@ -107,19 +201,16 @@ public:
* @param fDrawDistanceAfterTargetsPixels how much to draw after the receptors.
* @param fDrawDistanceBeforeTargetsPixels how much ot draw before the receptors.
* @param fFadeInPercentOfDrawFar when to start fading in. */
void DrawTap(const TapNote& tn, int iCol, float fBeat,
bool bOnSameRowAsHoldStart, bool bOnSameRowAsRollBeat,
bool bIsAddition, float fPercentFadeToFail,
float fReverseOffsetPixels,
float fDrawDistanceAfterTargetsPixels,
float fDrawDistanceBeforeTargetsPixels,
float fFadeInPercentOfDrawFar );
void DrawHold( const TapNote& tn, int iCol, int iRow, bool bIsBeingHeld, const HoldNoteResult &Result,
bool bIsAddition, float fPercentFadeToFail, float fReverseOffsetPixels, float fDrawDistanceAfterTargetsPixels, float fDrawDistanceBeforeTargetsPixels,
float fDrawDistanceBeforeTargetsPixels2, float fFadeInPercentOfDrawFar );
void DrawTap(const TapNote& tn, const NoteFieldRenderArgs& field_args,
const NoteColumnRenderArgs& column_args, float fBeat,
bool bOnSameRowAsHoldStart,
bool bOnSameRowAsRollBeat, bool bIsAddition, float fPercentFadeToFail);
void DrawHold(const TapNote& tn, const NoteFieldRenderArgs& field_args,
const NoteColumnRenderArgs& column_args, int iRow, bool bIsBeingHeld,
const HoldNoteResult &Result,
bool bIsAddition, float fPercentFadeToFail);
bool DrawHoldHeadForTapsOnSameRow() const;
bool DrawRollHeadForTapsOnSameRow() const;
private:
@@ -128,14 +219,23 @@ private:
Actor *GetHoldActor( NoteColorActor nca[NUM_HoldType][NUM_ActiveType], NotePart part, float fNoteBeat, bool bIsRoll, bool bIsBeingHeld );
Sprite *GetHoldSprite( NoteColorSprite ncs[NUM_HoldType][NUM_ActiveType], NotePart part, float fNoteBeat, bool bIsRoll, bool bIsBeingHeld );
void DrawActor( const TapNote& tn, Actor* pActor, NotePart part, int iCol, float fYOffset, float fBeat, bool bIsAddition, float fPercentFadeToFail,
float fReverseOffsetPixels, float fColorScale, float fDrawDistanceAfterTargetsPixels, float fDrawDistanceBeforeTargetsPixels, float fFadeInPercentOfDrawFar );
void DrawHoldBody( const TapNote& tn, int iCol, float fBeat, bool bIsBeingHeld, float fYHead, float fYTail, bool bIsAddition, float fPercentFadeToFail,
float fColorScale,
bool bGlow, float fDrawDistanceAfterTargetsPixels, float fDrawDistanceBeforeTargetsPixels, float fFadeInPercentOfDrawFar );
void DrawHoldPart( vector<Sprite*> &vpSpr, int iCol, int fYStep, float fPercentFadeToFail, float fColorScale, bool bGlow,
float fDrawDistanceAfterTargetsPixels, float fDrawDistanceBeforeTargetsPixels, float fFadeInPercentOfDrawFar, float fOverlappedTime,
float fYTop, float fYBottom, float fYStartPos, float fYEndPos, bool bWrapping, bool bAnchorToTop, bool bFlipTextureVertically );
void DrawActor(const TapNote& tn, Actor* pActor, NotePart part,
const NoteFieldRenderArgs& field_args,
const NoteColumnRenderArgs& column_args, float fYOffset, float fBeat,
bool bIsAddition, float fPercentFadeToFail, float fColorScale,
bool is_being_held);
void DrawHoldBody(const TapNote& tn, const NoteFieldRenderArgs& field_args,
const NoteColumnRenderArgs& column_args, float fBeat, bool bIsBeingHeld,
float fYHead, float fYTail,
bool bIsAddition, float fPercentFadeToFail, float fColorScale,
bool bGlow, float top_beat, float bottom_beat);
void DrawHoldPart(vector<Sprite*> &vpSpr,
const NoteFieldRenderArgs& field_args,
const NoteColumnRenderArgs& column_args, int fYStep,
float fPercentFadeToFail, float fColorScale, bool bGlow,
float fOverlappedTime, float fYTop, float fYBottom, float fYStartPos,
float fYEndPos, bool bWrapping, bool bAnchorToTop,
bool bFlipTextureVertically, float top_beat, float bottom_beat);
const PlayerState *m_pPlayerState; // to look up PlayerOptions
NoteMetricCache_t *cache;
@@ -152,9 +252,72 @@ private:
float m_fYReverseOffsetPixels;
};
// So, this is a bit screwy, and it's partly because routine forces rendering
// notes from different noteskins in the same column.
// NoteColumnRenderer exists to hold all the data needed for rendering a
// column and apply any transforms from that column's actor to the
// NoteDisplays that render the notes.
// NoteColumnRenderer is also used as a fake parent for the receptor and ghost
// actors so they can move with the rest of the column. I didn't use
// ActorProxy because the receptor/ghost actors need to pull in the parent
// state of their rows and the parent state of the column. -Kyz
struct NoteColumnRenderer : public Actor
{
NoteDisplay* m_displays[PLAYER_INVALID+1];
NoteFieldRenderArgs* m_field_render_args;
NoteColumnRenderArgs m_column_render_args;
int m_column;
// UpdateReceptorGhostStuff takes care of the logic for making the ghost
// and receptor positions follow the splines. It's called by their row
// update functions. -Kyz
void UpdateReceptorGhostStuff(Actor* receptor) const;
virtual void DrawPrimitives();
virtual void PushSelf(lua_State* L);
struct NCR_TweenState
{
NCR_TweenState();
NCSplineHandler m_pos_handler;
NCSplineHandler m_rot_handler;
NCSplineHandler m_zoom_handler;
static void MakeWeightedAverage(NCR_TweenState& out,
const NCR_TweenState& from, const NCR_TweenState& to, float between);
bool operator==(const NCR_TweenState& other) const;
bool operator!=(const NCR_TweenState& other) const { return !operator==(other); }
};
NCR_TweenState& NCR_DestTweenState()
{
if(NCR_Tweens.empty())
{ return NCR_current; }
else
{ return NCR_Tweens.back(); }
}
const NCR_TweenState& NCR_DestTweenState() const { return const_cast<NoteColumnRenderer*>(this)->NCR_DestTweenState(); }
virtual void SetCurrentTweenStart();
virtual void EraseHeadTween();
virtual void UpdatePercentThroughTween(float between);
virtual void BeginTweening(float time, ITween* interp);
virtual void StopTweening();
virtual void FinishTweening();
NCSplineHandler* GetPosHandler() { return &NCR_DestTweenState().m_pos_handler; }
NCSplineHandler* GetRotHandler() { return &NCR_DestTweenState().m_rot_handler; }
NCSplineHandler* GetZoomHandler() { return &NCR_DestTweenState().m_zoom_handler; }
private:
vector<NCR_TweenState> NCR_Tweens;
NCR_TweenState NCR_current;
NCR_TweenState NCR_start;
};
#endif
/**
* NoteColumnRenderer and associated spline stuff (c) Eric Reese 2014-2015
* @file
* @author Brian Bugh, Ben Nordstrom, Chris Danford, Steve Checkoway (c) 2001-2006
* @section LICENSE
+149 -253
View File
@@ -36,11 +36,8 @@ static ThemeMetric<float> FADE_FAIL_TIME( "NoteField", "FadeFailTime" );
static RString RoutineNoteSkinName( size_t i ) { return ssprintf("RoutineNoteSkinP%i",int(i+1)); }
static ThemeMetric1D<RString> ROUTINE_NOTESKIN( "NoteField", RoutineNoteSkinName, NUM_PLAYERS );
static bool FAST_NOTE_RENDERING_PREF_CACHED= false;
NoteField::NoteField()
{
FAST_NOTE_RENDERING_PREF_CACHED= PREFSMAN->m_FastNoteRendering;
m_pNoteData = NULL;
m_pCurDisplay = NULL;
@@ -64,9 +61,13 @@ NoteField::NoteField()
m_sprBeatBars.Load( THEME->GetPathG("NoteField","bars") );
m_sprBeatBars.StopAnimating();
// I decided to do it this way because I don't want to dig through
// ScreenEdit to change all the places it touches the markers. -Kyz
m_FieldRenderArgs.selection_begin_marker= &m_iBeginMarker;
m_FieldRenderArgs.selection_end_marker= &m_iEndMarker;
m_iBeginMarker = m_iEndMarker = -1;
m_fPercentFadeToFail = -1;
m_FieldRenderArgs.fail_fade = -1;
m_StepCallback.SetFromNil();
m_SetPressedCallback.SetFromNil();
@@ -100,9 +101,9 @@ void NoteField::CacheNoteSkin( const RString &sNoteSkin_ )
LockNoteSkin l( sNoteSkinLower );
LOG->Trace("NoteField::CacheNoteSkin: cache %s", sNoteSkinLower.c_str() );
NoteDisplayCols *nd = new NoteDisplayCols( GAMESTATE->GetCurrentStyle()->m_iColsPerPlayer );
NoteDisplayCols *nd = new NoteDisplayCols( GAMESTATE->GetCurrentStyle(m_pPlayerState->m_PlayerNumber)->m_iColsPerPlayer );
for( int c=0; c<GAMESTATE->GetCurrentStyle()->m_iColsPerPlayer; c++ )
for( int c=0; c<GAMESTATE->GetCurrentStyle(m_pPlayerState->m_PlayerNumber)->m_iColsPerPlayer; c++ )
nd->display[c].Load( c, m_pPlayerState, m_fYReverseOffsetPixels );
nd->m_ReceptorArrowRow.Load( m_pPlayerState, m_fYReverseOffsetPixels );
nd->m_GhostArrowRow.Load( m_pPlayerState, m_fYReverseOffsetPixels );
@@ -124,7 +125,7 @@ void NoteField::UncacheNoteSkin( const RString &sNoteSkin_ )
void NoteField::CacheAllUsedNoteSkins()
{
// If we're in Routine mode, apply our per-player noteskins.
if( GAMESTATE->GetCurrentStyle()->m_StyleType == StyleType_TwoPlayersSharedSides )
if( GAMESTATE->GetCurrentStyle(m_pPlayerState->m_PlayerNumber)->m_StyleType == StyleType_TwoPlayersSharedSides )
{
FOREACH_EnabledPlayer( pn )
GAMESTATE->ApplyStageModifiers( pn, ROUTINE_NOTESKIN.GetValue(pn) );
@@ -169,18 +170,30 @@ void NoteField::CacheAllUsedNoteSkins()
ASSERT_M( it != m_NoteDisplays.end(), sNoteSkinLower );
m_pDisplays[pn] = it->second;
}
InitColumnRenderers();
}
void NoteField::Init( const PlayerState* pPlayerState, float fYReverseOffsetPixels )
void NoteField::Init( const PlayerState* pPlayerState, float fYReverseOffsetPixels, bool use_states_zoom )
{
m_pPlayerState = pPlayerState;
m_fYReverseOffsetPixels = fYReverseOffsetPixels;
CacheAllUsedNoteSkins();
// Design change: Instead of having a flag in the style that toggles a
// fixed zoom that is only applied to the columns, ScreenGameplay now
// calculates a zoom factor to apply to the notefield and puts it in the
// PlayerState. -Kyz
// use_states_zoom flag exists because edit mode has to set its own special
// zoom factor. -Kyz
if(use_states_zoom)
{
SetZoom(pPlayerState->m_NotefieldZoom);
}
}
void NoteField::Load(
const NoteData *pNoteData,
int iDrawDistanceAfterTargetsPixels,
int iDrawDistanceAfterTargetsPixels,
int iDrawDistanceBeforeTargetsPixels )
{
ASSERT( pNoteData != NULL );
@@ -189,13 +202,13 @@ void NoteField::Load(
m_iDrawDistanceBeforeTargetsPixels = iDrawDistanceBeforeTargetsPixels;
ASSERT( m_iDrawDistanceBeforeTargetsPixels >= m_iDrawDistanceAfterTargetsPixels );
m_fPercentFadeToFail = -1;
m_FieldRenderArgs.fail_fade = -1;
//int i1 = m_pNoteData->GetNumTracks();
//int i2 = GAMESTATE->GetCurrentStyle()->m_iColsPerPlayer;
ASSERT_M(m_pNoteData->GetNumTracks() == GAMESTATE->GetCurrentStyle()->m_iColsPerPlayer,
ssprintf("NumTracks %d = ColsPerPlayer %d",m_pNoteData->GetNumTracks(),
GAMESTATE->GetCurrentStyle()->m_iColsPerPlayer));
//int i2 = GAMESTATE->GetCurrentStyle(m_pPlayerState->m_PlayerNumber)->m_iColsPerPlayer;
ASSERT_M(m_pNoteData->GetNumTracks() == GAMESTATE->GetCurrentStyle(m_pPlayerState->m_PlayerNumber)->m_iColsPerPlayer,
ssprintf("NumTracks %d = ColsPerPlayer %d",m_pNoteData->GetNumTracks(),
GAMESTATE->GetCurrentStyle(m_pPlayerState->m_PlayerNumber)->m_iColsPerPlayer));
// The NoteSkin may have changed at the beginning of a new course song.
RString sNoteSkinLower = m_pPlayerState->m_PlayerOptions.GetCurrent().m_sNoteSkin;
@@ -240,6 +253,30 @@ void NoteField::Load(
ASSERT_M( it != m_NoteDisplays.end(), sNoteSkinLower );
m_pDisplays[pn] = it->second;
}
InitColumnRenderers();
}
void NoteField::InitColumnRenderers()
{
m_FieldRenderArgs.player_state= m_pPlayerState;
m_FieldRenderArgs.reverse_offset_pixels= m_fYReverseOffsetPixels;
m_FieldRenderArgs.receptor_row= &(m_pCurDisplay->m_ReceptorArrowRow);
m_FieldRenderArgs.ghost_row= &(m_pCurDisplay->m_GhostArrowRow);
m_FieldRenderArgs.note_data= m_pNoteData;
m_ColumnRenderers.resize(GAMESTATE->GetCurrentStyle(m_pPlayerState->m_PlayerNumber)->m_iColsPerPlayer);
for(size_t ncr= 0; ncr < m_ColumnRenderers.size(); ++ncr)
{
FOREACH_EnabledPlayer(pn)
{
m_ColumnRenderers[ncr].m_displays[pn]= &(m_pDisplays[pn]->display[ncr]);
}
m_ColumnRenderers[ncr].m_displays[PLAYER_INVALID]= &(m_pCurDisplay->display[ncr]);
m_ColumnRenderers[ncr].m_column= ncr;
m_ColumnRenderers[ncr].m_column_render_args.column= ncr;
m_ColumnRenderers[ncr].m_field_render_args= &m_FieldRenderArgs;
}
m_pCurDisplay->m_ReceptorArrowRow.SetColumnRenderers(m_ColumnRenderers);
m_pCurDisplay->m_GhostArrowRow.SetColumnRenderers(m_ColumnRenderers);
}
void NoteField::Update( float fDeltaTime )
@@ -251,6 +288,11 @@ void NoteField::Update( float fDeltaTime )
ActorFrame::Update( fDeltaTime );
for(size_t c= 0; c < m_ColumnRenderers.size(); ++c)
{
m_ColumnRenderers[c].Update(fDeltaTime);
}
// update m_fBoardOffsetPixels, m_fCurrentBeatLastUpdate, m_fYPosCurrentBeatLastUpdate
const float fCurrentBeat = m_pPlayerState->GetDisplayedPosition().m_fSongBeat;
bool bTweeningOn = m_sprBoard->GetCurrentDiffuseAlpha() >= 0.98 && m_sprBoard->GetCurrentDiffuseAlpha() < 1.00; // HACK
@@ -276,11 +318,11 @@ void NoteField::Update( float fDeltaTime )
cur->m_ReceptorArrowRow.Update( fDeltaTime );
cur->m_GhostArrowRow.Update( fDeltaTime );
if( m_fPercentFadeToFail >= 0 )
m_fPercentFadeToFail = min( m_fPercentFadeToFail + fDeltaTime/FADE_FAIL_TIME, 1 );
if( m_FieldRenderArgs.fail_fade >= 0 )
m_FieldRenderArgs.fail_fade = min( m_FieldRenderArgs.fail_fade + fDeltaTime/FADE_FAIL_TIME, 1 );
// Update fade to failed
m_pCurDisplay->m_ReceptorArrowRow.SetFadeToFailPercent( m_fPercentFadeToFail );
m_pCurDisplay->m_ReceptorArrowRow.SetFadeToFailPercent( m_FieldRenderArgs.fail_fade );
NoteDisplay::Update( fDeltaTime );
/* Update all NoteDisplays. Hack: We need to call this once per frame, not
@@ -294,7 +336,7 @@ void NoteField::Update( float fDeltaTime )
float NoteField::GetWidth() const
{
const Style* pStyle = GAMESTATE->GetCurrentStyle();
const Style* pStyle = GAMESTATE->GetCurrentStyle(m_pPlayerState->m_PlayerNumber);
float fMinX, fMaxX;
// TODO: Remove use of PlayerNumber.
pStyle->GetMinAndMaxColX( m_pPlayerState->m_PlayerNumber, fMinX, fMaxX );
@@ -801,13 +843,11 @@ float FindLastDisplayedBeat( const PlayerState* pPlayerState, int iDrawDistanceB
return fLastBeatToDraw;
}
inline float NoteRowToVisibleBeat( const PlayerState *pPlayerState, int iRow )
{
return NoteRowToBeat(iRow);
}
bool NoteField::IsOnScreen( float fBeat, int iCol, int iDrawDistanceAfterTargetsPixels, int iDrawDistanceBeforeTargetsPixels ) const
{
// IMPORTANT: Do not modify this function without also modifying the
// version that is in NoteDisplay.cpp or coming up with a good way to
// merge them. -Kyz
// TRICKY: If boomerang is on, then ones in the range
// [iFirstRowToDraw,iLastRowToDraw] aren't necessarily visible.
// Test to see if this beat is visible before drawing.
@@ -834,41 +874,41 @@ void NoteField::DrawPrimitives()
const PlayerOptions &current_po = m_pPlayerState->m_PlayerOptions.GetCurrent();
// Adjust draw range depending on some effects
int iDrawDistanceAfterTargetsPixels = m_iDrawDistanceAfterTargetsPixels;
m_FieldRenderArgs.draw_pixels_after_targets= m_iDrawDistanceAfterTargetsPixels;
// HACK: If boomerang and centered are on, then we want to draw much
// earlier so that the notes don't pop on screen.
float fCenteredTimesBoomerang =
current_po.m_fScrolls[PlayerOptions::SCROLL_CENTERED] *
current_po.m_fAccels[PlayerOptions::ACCEL_BOOMERANG];
iDrawDistanceAfterTargetsPixels += int(SCALE( fCenteredTimesBoomerang, 0.f, 1.f, 0.f, -SCREEN_HEIGHT/2 ));
int iDrawDistanceBeforeTargetsPixels = m_iDrawDistanceBeforeTargetsPixels;
m_FieldRenderArgs.draw_pixels_after_targets += int(SCALE( fCenteredTimesBoomerang, 0.f, 1.f, 0.f, -SCREEN_HEIGHT/2 ));
m_FieldRenderArgs.draw_pixels_before_targets = m_iDrawDistanceBeforeTargetsPixels;
float fDrawScale = 1;
fDrawScale *= 1 + 0.5f * fabsf( current_po.m_fPerspectiveTilt );
fDrawScale *= 1 + fabsf( current_po.m_fEffects[PlayerOptions::EFFECT_MINI] );
iDrawDistanceAfterTargetsPixels = (int)(iDrawDistanceAfterTargetsPixels * fDrawScale);
iDrawDistanceBeforeTargetsPixels = (int)(iDrawDistanceBeforeTargetsPixels * fDrawScale);
m_FieldRenderArgs.draw_pixels_after_targets = (int)(m_FieldRenderArgs.draw_pixels_after_targets * fDrawScale);
m_FieldRenderArgs.draw_pixels_before_targets = (int)(m_FieldRenderArgs.draw_pixels_before_targets * fDrawScale);
// Probe for first and last notes on the screen
float fFirstBeatToDraw = FindFirstDisplayedBeat( m_pPlayerState, iDrawDistanceAfterTargetsPixels );
float fLastBeatToDraw = FindLastDisplayedBeat( m_pPlayerState, iDrawDistanceBeforeTargetsPixels );
float fFirstBeatToDraw = FindFirstDisplayedBeat( m_pPlayerState, m_FieldRenderArgs.draw_pixels_after_targets );
float fLastBeatToDraw = FindLastDisplayedBeat( m_pPlayerState, m_FieldRenderArgs.draw_pixels_before_targets );
m_pPlayerState->m_fLastDrawnBeat = fLastBeatToDraw;
const int iFirstRowToDraw = BeatToNoteRow(fFirstBeatToDraw);
const int iLastRowToDraw = BeatToNoteRow(fLastBeatToDraw);
m_FieldRenderArgs.first_row = BeatToNoteRow(fFirstBeatToDraw);
m_FieldRenderArgs.last_row = BeatToNoteRow(fLastBeatToDraw);
//LOG->Trace( "start = %f.1, end = %f.1", fFirstBeatToDraw-fSongBeat, fLastBeatToDraw-fSongBeat );
//LOG->Trace( "Drawing elements %d through %d", iFirstRowToDraw, iLastRowToDraw );
//LOG->Trace( "Drawing elements %d through %d", m_FieldRenderArgs.first_row, m_FieldRenderArgs.last_row );
#define IS_ON_SCREEN( fBeat ) ( fFirstBeatToDraw <= (fBeat) && (fBeat) <= fLastBeatToDraw && IsOnScreen( fBeat, 0, iDrawDistanceAfterTargetsPixels, iDrawDistanceBeforeTargetsPixels ) )
#define IS_ON_SCREEN( fBeat ) ( fFirstBeatToDraw <= (fBeat) && (fBeat) <= fLastBeatToDraw && IsOnScreen( fBeat, 0, m_FieldRenderArgs.draw_pixels_after_targets, m_FieldRenderArgs.draw_pixels_before_targets ) )
// Draw board
if( SHOW_BOARD )
{
DrawBoard( iDrawDistanceAfterTargetsPixels, iDrawDistanceBeforeTargetsPixels );
DrawBoard( m_FieldRenderArgs.draw_pixels_after_targets, m_FieldRenderArgs.draw_pixels_before_targets );
}
// Draw Receptors
@@ -891,7 +931,7 @@ void NoteField::DrawPrimitives()
for (i = 0; i < tSigs.size(); i++)
{
const TimeSignatureSegment *ts = ToTimeSignature(tSigs[i]);
int iSegmentEndRow = (i + 1 == tSigs.size()) ? iLastRowToDraw : tSigs[i+1]->GetRow();
int iSegmentEndRow = (i + 1 == tSigs.size()) ? m_FieldRenderArgs.last_row : tSigs[i+1]->GetRow();
// beat bars every 16th note
int iDrawBeatBarsEveryRows = BeatToNoteRow( ((float)ts->GetDen()) / 4 ) / 4;
@@ -934,7 +974,7 @@ void NoteField::DrawPrimitives()
for (i = 0; i < segs[SEGMENT_SCROLL]->size(); i++)
{
ScrollSegment *seg = ToScroll( segs[SEGMENT_SCROLL]->at(i) );
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
if( seg->GetRow() >= m_FieldRenderArgs.first_row && seg->GetRow() <= m_FieldRenderArgs.last_row )
{
float fBeat = seg->GetBeat();
if( IS_ON_SCREEN(fBeat) )
@@ -946,7 +986,7 @@ void NoteField::DrawPrimitives()
for (i = 0; i < segs[SEGMENT_BPM]->size(); i++)
{
const BPMSegment *seg = ToBPM( segs[SEGMENT_BPM]->at(i) );
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
if( seg->GetRow() >= m_FieldRenderArgs.first_row && seg->GetRow() <= m_FieldRenderArgs.last_row )
{
float fBeat = seg->GetBeat();
if( IS_ON_SCREEN(fBeat) )
@@ -958,7 +998,7 @@ void NoteField::DrawPrimitives()
for (i = 0; i < segs[SEGMENT_STOP]->size(); i++)
{
const StopSegment *seg = ToStop( segs[SEGMENT_STOP]->at(i) );
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
if( seg->GetRow() >= m_FieldRenderArgs.first_row && seg->GetRow() <= m_FieldRenderArgs.last_row )
{
float fBeat = seg->GetBeat();
if( IS_ON_SCREEN(fBeat) )
@@ -970,7 +1010,7 @@ void NoteField::DrawPrimitives()
for (i = 0; i < segs[SEGMENT_DELAY]->size(); i++)
{
const DelaySegment *seg = ToDelay( segs[SEGMENT_DELAY]->at(i) );
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
if( seg->GetRow() >= m_FieldRenderArgs.first_row && seg->GetRow() <= m_FieldRenderArgs.last_row )
{
float fBeat = seg->GetBeat();
if( IS_ON_SCREEN(fBeat) )
@@ -982,7 +1022,7 @@ void NoteField::DrawPrimitives()
for (i = 0; i < segs[SEGMENT_WARP]->size(); i++)
{
const WarpSegment *seg = ToWarp( segs[SEGMENT_WARP]->at(i) );
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
if( seg->GetRow() >= m_FieldRenderArgs.first_row && seg->GetRow() <= m_FieldRenderArgs.last_row )
{
float fBeat = seg->GetBeat();
if( IS_ON_SCREEN(fBeat) )
@@ -994,7 +1034,7 @@ void NoteField::DrawPrimitives()
for (i = 0; i < segs[SEGMENT_TIME_SIG]->size(); i++)
{
const TimeSignatureSegment *seg = ToTimeSignature( segs[SEGMENT_TIME_SIG]->at(i) );
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
if( seg->GetRow() >= m_FieldRenderArgs.first_row && seg->GetRow() <= m_FieldRenderArgs.last_row )
{
float fBeat = seg->GetBeat();
if( IS_ON_SCREEN(fBeat) )
@@ -1006,7 +1046,7 @@ void NoteField::DrawPrimitives()
for (i = 0; i < segs[SEGMENT_TICKCOUNT]->size(); i++)
{
const TickcountSegment *seg = ToTickcount( segs[SEGMENT_TICKCOUNT]->at(i) );
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
if( seg->GetRow() >= m_FieldRenderArgs.first_row && seg->GetRow() <= m_FieldRenderArgs.last_row )
{
float fBeat = seg->GetBeat();
if( IS_ON_SCREEN(fBeat) )
@@ -1018,7 +1058,7 @@ void NoteField::DrawPrimitives()
for (i = 0; i < segs[SEGMENT_COMBO]->size(); i++)
{
const ComboSegment *seg = ToCombo( segs[SEGMENT_COMBO]->at(i) );
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
if( seg->GetRow() >= m_FieldRenderArgs.first_row && seg->GetRow() <= m_FieldRenderArgs.last_row )
{
float fBeat = seg->GetBeat();
if( IS_ON_SCREEN(fBeat) )
@@ -1030,7 +1070,7 @@ void NoteField::DrawPrimitives()
for (i = 0; i < segs[SEGMENT_LABEL]->size(); i++)
{
const LabelSegment *seg = ToLabel( segs[SEGMENT_LABEL]->at(i) );
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
if( seg->GetRow() >= m_FieldRenderArgs.first_row && seg->GetRow() <= m_FieldRenderArgs.last_row )
{
float fBeat = seg->GetBeat();
if( IS_ON_SCREEN(fBeat) )
@@ -1042,7 +1082,7 @@ void NoteField::DrawPrimitives()
for (i = 0; i < segs[SEGMENT_SPEED]->size(); i++)
{
const SpeedSegment *seg = ToSpeed( segs[SEGMENT_SPEED]->at(i) );
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
if( seg->GetRow() >= m_FieldRenderArgs.first_row && seg->GetRow() <= m_FieldRenderArgs.last_row )
{
float fBeat = seg->GetBeat();
if( IS_ON_SCREEN(fBeat) )
@@ -1055,7 +1095,7 @@ void NoteField::DrawPrimitives()
for (i = 0; i < segs[SEGMENT_FAKE]->size(); i++)
{
const FakeSegment *seg = ToFake( segs[SEGMENT_FAKE]->at(i) );
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
if( seg->GetRow() >= m_FieldRenderArgs.first_row && seg->GetRow() <= m_FieldRenderArgs.last_row )
{
float fBeat = seg->GetBeat();
if( IS_ON_SCREEN(fBeat) )
@@ -1075,8 +1115,8 @@ void NoteField::DrawPrimitives()
float fSecond = a->fStartSecond;
float fBeat = timing.GetBeatFromElapsedTime( fSecond );
if( BeatToNoteRow(fBeat) >= iFirstRowToDraw &&
BeatToNoteRow(fBeat) <= iLastRowToDraw)
if( BeatToNoteRow(fBeat) >= m_FieldRenderArgs.first_row &&
BeatToNoteRow(fBeat) <= m_FieldRenderArgs.last_row)
{
if( IS_ON_SCREEN(fBeat) )
DrawAttackText( fBeat, *a );
@@ -1094,8 +1134,8 @@ void NoteField::DrawPrimitives()
FOREACH_CONST(Attack, attacks, a)
{
float fBeat = timing.GetBeatFromElapsedTime(a->fStartSecond);
if (BeatToNoteRow(fBeat) >= iFirstRowToDraw &&
BeatToNoteRow(fBeat) <= iLastRowToDraw &&
if (BeatToNoteRow(fBeat) >= m_FieldRenderArgs.first_row &&
BeatToNoteRow(fBeat) <= m_FieldRenderArgs.last_row &&
IS_ON_SCREEN(fBeat))
{
this->DrawAttackText(fBeat, *a);
@@ -1179,20 +1219,20 @@ void NoteField::DrawPrimitives()
{
int iBegin = m_iBeginMarker;
int iEnd = m_iEndMarker;
CLAMP( iBegin, iFirstRowToDraw, iLastRowToDraw );
CLAMP( iEnd, iFirstRowToDraw, iLastRowToDraw );
CLAMP( iBegin, m_FieldRenderArgs.first_row, m_FieldRenderArgs.last_row );
CLAMP( iEnd, m_FieldRenderArgs.first_row, m_FieldRenderArgs.last_row );
DrawAreaHighlight( iBegin, iEnd );
}
else if( m_iBeginMarker != -1 )
{
if( m_iBeginMarker >= iFirstRowToDraw &&
m_iBeginMarker <= iLastRowToDraw )
if( m_iBeginMarker >= m_FieldRenderArgs.first_row &&
m_iBeginMarker <= m_FieldRenderArgs.last_row )
DrawMarkerBar( m_iBeginMarker );
}
else if( m_iEndMarker != -1 )
{
if( m_iEndMarker >= iFirstRowToDraw &&
m_iEndMarker <= iLastRowToDraw )
if( m_iEndMarker >= m_FieldRenderArgs.first_row &&
m_iEndMarker <= m_FieldRenderArgs.last_row )
DrawMarkerBar( m_iEndMarker );
}
}
@@ -1201,175 +1241,19 @@ void NoteField::DrawPrimitives()
// Draw the arrows in order of column. This minimizes texture switches and
// lets us draw in big batches.
float fSelectedRangeGlow = SCALE( RageFastCos(RageTimer::GetTimeSinceStartFast()*2), -1, 1, 0.1f, 0.3f );
const Style* pStyle = GAMESTATE->GetCurrentStyle(m_pPlayerState->m_PlayerNumber);
ASSERT_M(m_pNoteData->GetNumTracks() == GAMESTATE->GetCurrentStyle(m_pPlayerState->m_PlayerNumber)->m_iColsPerPlayer,
ssprintf("NumTracks %d != ColsPerPlayer %d",m_pNoteData->GetNumTracks(),
GAMESTATE->GetCurrentStyle(m_pPlayerState->m_PlayerNumber)->m_iColsPerPlayer));
const Style* pStyle = GAMESTATE->GetCurrentStyle();
ASSERT_M(m_pNoteData->GetNumTracks() == GAMESTATE->GetCurrentStyle()->m_iColsPerPlayer,
ssprintf("NumTracks %d != ColsPerPlayer %d",m_pNoteData->GetNumTracks(),
GAMESTATE->GetCurrentStyle()->m_iColsPerPlayer));
m_FieldRenderArgs.selection_glow= SCALE(
RageFastCos(RageTimer::GetTimeSinceStartFast()*2), -1, 1, 0.1f, 0.3f);
m_FieldRenderArgs.fade_before_targets= FADE_BEFORE_TARGETS_PERCENT;
for( int j=0; j<m_pNoteData->GetNumTracks(); j++ ) // for each arrow column
{
const int c = pStyle->m_iColumnDrawOrder[j];
bool bAnyUpcomingInThisCol = false;
// Draw all HoldNotes in this column (so that they appear under the tap notes)
{
NoteData::TrackMap::const_iterator begin, end;
m_pNoteData->GetTapNoteRangeInclusive( c, iFirstRowToDraw, iLastRowToDraw+1, begin, end );
for( ; begin != end; ++begin )
{
const TapNote &tn = begin->second; //m_pNoteData->GetTapNote(c, j);
if( tn.type != TapNoteType_HoldHead )
continue; // skip
const HoldNoteResult &Result = tn.HoldResult;
if( Result.hns == HNS_Held ) // if this HoldNote was completed
continue; // don't draw anything
int iStartRow = begin->first;
int iEndRow = iStartRow + tn.iDuration;
// TRICKY: If boomerang is on, then all notes in the range
// [iFirstRowToDraw,iLastRowToDraw] aren't necessarily visible.
// Test every note to make sure it's on screen before drawing
float fThrowAway;
bool bStartIsPastPeak = false;
bool bEndIsPastPeak = false;
float fStartYOffset = ArrowEffects::GetYOffset( m_pPlayerState, c, NoteRowToVisibleBeat(m_pPlayerState, iStartRow), fThrowAway, bStartIsPastPeak );
float fEndYOffset = ArrowEffects::GetYOffset( m_pPlayerState, c, NoteRowToVisibleBeat(m_pPlayerState, iEndRow), fThrowAway, bEndIsPastPeak );
bool bTailIsOnVisible = iDrawDistanceAfterTargetsPixels <= fEndYOffset && fEndYOffset <= iDrawDistanceBeforeTargetsPixels;
bool bHeadIsVisible = iDrawDistanceAfterTargetsPixels <= fStartYOffset && fStartYOffset <= iDrawDistanceBeforeTargetsPixels;
bool bStraddlingVisible = fStartYOffset <= iDrawDistanceAfterTargetsPixels && iDrawDistanceBeforeTargetsPixels <= fEndYOffset;
bool bStaddlingPeak = bStartIsPastPeak && !bEndIsPastPeak;
if( !(bTailIsOnVisible || bHeadIsVisible || bStraddlingVisible || bStaddlingPeak) )
{
//LOG->Trace( "skip drawing this hold." );
continue; // skip
}
bool bIsAddition = (tn.source == TapNoteSource_Addition);
bool bIsHopoPossible = (tn.bHopoPossible);
bool bUseAdditionColoring = bIsAddition || bIsHopoPossible;
const bool bHoldGhostShowing = tn.HoldResult.bActive && tn.HoldResult.fLife > 0;
const bool bIsHoldingNote = tn.HoldResult.bHeld;
if( bHoldGhostShowing )
m_pCurDisplay->m_GhostArrowRow.SetHoldShowing( c, tn );
ASSERT_M( NoteRowToBeat(iStartRow) > -2000, ssprintf("%i %i %i", iStartRow, iEndRow, c) );
bool bIsInSelectionRange = false;
if( m_iBeginMarker!=-1 && m_iEndMarker!=-1 )
bIsInSelectionRange = (m_iBeginMarker <= iStartRow && iEndRow < m_iEndMarker);
NoteDisplayCols *displayCols = tn.pn == PLAYER_INVALID ? m_pCurDisplay : m_pDisplays[tn.pn];
displayCols->display[c].DrawHold( tn, c, iStartRow, bIsHoldingNote, Result, bUseAdditionColoring, bIsInSelectionRange ? fSelectedRangeGlow : m_fPercentFadeToFail,
m_fYReverseOffsetPixels, (float) iDrawDistanceAfterTargetsPixels, (float) iDrawDistanceBeforeTargetsPixels, iDrawDistanceBeforeTargetsPixels, FADE_BEFORE_TARGETS_PERCENT );
bool bNoteIsUpcoming = NoteRowToBeat(iStartRow) > m_pPlayerState->GetDisplayedPosition().m_fSongBeat;
bAnyUpcomingInThisCol |= bNoteIsUpcoming;
}
}
// Draw all TapNotes in this column
// draw notes from furthest to closest
NoteData::TrackMap::const_iterator begin, end;
m_pNoteData->GetTapNoteRange( c, iFirstRowToDraw, iLastRowToDraw+1, begin, end );
for( ; begin != end; ++begin )
{
int q = begin->first;
const TapNote &tn = begin->second; //m_pNoteData->GetTapNote(c, q);
// Switch modified by Wolfman2000, tested by Saturn2888
// Fixes hold head overlapping issue, but not the rolls.
switch( tn.type )
{
case TapNoteType_Empty: // no note here
{
continue;
}
case TapNoteType_HoldHead:
{
//if (tn.subType == TapNoteSubType_Roll)
continue; // skip
}
default: break;
}
// Don't draw hidden (fully judged) steps.
if( tn.result.bHidden )
continue;
// TRICKY: If boomerang is on, then all notes in the range
// [iFirstRowToDraw,iLastRowToDraw] aren't necessarily visible.
// Test every note to make sure it's on screen before drawing.
if( !IsOnScreen( NoteRowToBeat(q), c, iDrawDistanceAfterTargetsPixels, iDrawDistanceBeforeTargetsPixels ) )
continue; // skip
ASSERT_M( NoteRowToBeat(q) > -2000, ssprintf("%i %i %i, %f %f", q, iLastRowToDraw,
iFirstRowToDraw, m_pPlayerState->GetDisplayedPosition().m_fSongBeat, m_pPlayerState->GetDisplayedPosition().m_fMusicSeconds) );
// See if there is a hold step that begins on this index.
// Only do this if the noteskin cares.
bool bHoldNoteBeginsOnThisBeat = false;
if( m_pCurDisplay->display[c].DrawHoldHeadForTapsOnSameRow() )
{
for( int c2=0; c2<m_pNoteData->GetNumTracks(); c2++ )
{
const TapNote &tmp = m_pNoteData->GetTapNote(c2, q);
if(tmp.type == TapNoteType_HoldHead &&
tmp.subType == TapNoteSubType_Hold)
{
bHoldNoteBeginsOnThisBeat = true;
break;
}
}
}
// do the same for a roll.
bool bRollNoteBeginsOnThisBeat = false;
if (m_pCurDisplay->display[c].DrawRollHeadForTapsOnSameRow() )
{
for( int c2=0; c2<m_pNoteData->GetNumTracks(); c2++ )
{
const TapNote &tmp = m_pNoteData->GetTapNote(c2, q);
if(tmp.type == TapNoteType_HoldHead &&
tmp.subType == TapNoteSubType_Roll)
{
bRollNoteBeginsOnThisBeat = true;
break;
}
}
}
bool bIsInSelectionRange = false;
if( m_iBeginMarker!=-1 && m_iEndMarker!=-1 )
bIsInSelectionRange = m_iBeginMarker<=q && q<m_iEndMarker;
bool bIsAddition = (tn.source == TapNoteSource_Addition);
bool bIsHopoPossible = (tn.bHopoPossible);
bool bUseAdditionColoring = bIsAddition || bIsHopoPossible;
NoteDisplayCols *displayCols = tn.pn == PLAYER_INVALID ? m_pCurDisplay : m_pDisplays[tn.pn];
displayCols->display[c].DrawTap(tn, c, NoteRowToVisibleBeat(m_pPlayerState, q),
bHoldNoteBeginsOnThisBeat, bRollNoteBeginsOnThisBeat,
bUseAdditionColoring, bIsInSelectionRange ? fSelectedRangeGlow : m_fPercentFadeToFail,
m_fYReverseOffsetPixels, iDrawDistanceAfterTargetsPixels, iDrawDistanceBeforeTargetsPixels,
FADE_BEFORE_TARGETS_PERCENT );
bool bNoteIsUpcoming = NoteRowToBeat(q) > m_pPlayerState->GetDisplayedPosition().m_fSongBeat;
bAnyUpcomingInThisCol |= bNoteIsUpcoming;
if(!FAST_NOTE_RENDERING_PREF_CACHED)
{
DISPLAY->ClearZBuffer();
}
}
cur->m_ReceptorArrowRow.SetNoteUpcoming( c, bAnyUpcomingInThisCol );
m_ColumnRenderers[c].Draw();
}
cur->m_GhostArrowRow.Draw();
@@ -1377,7 +1261,7 @@ void NoteField::DrawPrimitives()
void NoteField::FadeToFail()
{
m_fPercentFadeToFail = max( 0.0f, m_fPercentFadeToFail ); // this will slowly increase every Update()
m_FieldRenderArgs.fail_fade = max( 0.0f, m_FieldRenderArgs.fail_fade ); // this will slowly increase every Update()
// don't fade all over again if this is called twice
}
@@ -1398,18 +1282,18 @@ void NoteField::FadeToFail()
#define CLOSE_RUN_AND_CALLBACK_BLOCKS } lua_settop(L, 0); LUA->Release(L); }
#define PUSH_COLUMN lua_pushnumber(L, col+1)
static void get_returned_column(Lua* L, int index, int& col)
static void get_returned_column(Lua* L, PlayerNumber pn, int index, int& col)
{
if(lua_isnumber(L, index))
{
// 1-indexed columns in lua
int tmpcol= lua_tonumber(L, index) - 1;
if(tmpcol < 0 || tmpcol >= GAMESTATE->GetCurrentStyle()->m_iColsPerPlayer)
if(tmpcol < 0 || tmpcol >= GAMESTATE->GetCurrentStyle(pn)->m_iColsPerPlayer)
{
LuaHelpers::ReportScriptErrorFmt(
"Column returned by callback must be between 1 and %d "
"(GAMESTATE:GetCurrentStyle():ColumnsPerPlayer()).",
GAMESTATE->GetCurrentStyle()->m_iColsPerPlayer);
GAMESTATE->GetCurrentStyle(pn)->m_iColsPerPlayer);
}
else
{
@@ -1442,7 +1326,7 @@ void NoteField::Step(int col, TapNoteScore score, bool from_lua)
PUSH_COLUMN;
Enum::Push(L, score);
OPEN_RUN_BLOCK(2);
get_returned_column(L, 1, col);
get_returned_column(L, m_pPlayerState->m_PlayerNumber, 1, col);
get_returned_score(L, 2, score);
CLOSE_RUN_AND_CALLBACK_BLOCKS;
m_pCurDisplay->m_ReceptorArrowRow.Step(col, score);
@@ -1452,7 +1336,7 @@ void NoteField::SetPressed(int col, bool from_lua)
OPEN_CALLBACK_BLOCK(m_SetPressedCallback);
PUSH_COLUMN;
OPEN_RUN_BLOCK(1);
get_returned_column(L, 1, col);
get_returned_column(L, m_pPlayerState->m_PlayerNumber, 1, col);
CLOSE_RUN_AND_CALLBACK_BLOCKS;
m_pCurDisplay->m_ReceptorArrowRow.SetPressed(col);
}
@@ -1463,7 +1347,7 @@ void NoteField::DidTapNote(int col, TapNoteScore score, bool bright, bool from_l
Enum::Push(L, score);
lua_pushboolean(L, bright);
OPEN_RUN_BLOCK(3);
get_returned_column(L, 1, col);
get_returned_column(L, m_pPlayerState->m_PlayerNumber, 1, col);
get_returned_score(L, 2, score);
get_returned_bright(L, 3, bright);
CLOSE_RUN_AND_CALLBACK_BLOCKS;
@@ -1476,7 +1360,7 @@ void NoteField::DidHoldNote(int col, HoldNoteScore score, bool bright, bool from
Enum::Push(L, score);
lua_pushboolean(L, bright);
OPEN_RUN_BLOCK(3);
get_returned_column(L, 1, col);
get_returned_column(L, m_pPlayerState->m_PlayerNumber, 1, col);
get_returned_score(L, 2, score);
get_returned_bright(L, 3, bright);
CLOSE_RUN_AND_CALLBACK_BLOCKS;
@@ -1523,68 +1407,80 @@ public:
} \
return 0; \
}
SET_CALLBACK_GENERIC(SetStepCallback, m_StepCallback);
SET_CALLBACK_GENERIC(SetSetPressedCallback, m_SetPressedCallback);
SET_CALLBACK_GENERIC(SetDidTapNoteCallback, m_DidTapNoteCallback);
SET_CALLBACK_GENERIC(SetDidHoldNoteCallback, m_DidHoldNoteCallback);
SET_CALLBACK_GENERIC(set_step_callback, m_StepCallback);
SET_CALLBACK_GENERIC(set_set_pressed_callback, m_SetPressedCallback);
SET_CALLBACK_GENERIC(set_did_tap_note_callback, m_DidTapNoteCallback);
SET_CALLBACK_GENERIC(set_did_hold_note_callback, m_DidHoldNoteCallback);
#undef SET_CALLBACK_GENERIC
static int check_column(lua_State* L, int index)
static int check_column(lua_State* L, int index, PlayerNumber pn)
{
// 1-indexed columns in lua
int col= IArg(1)-1;
if(col < 0 || col >= GAMESTATE->GetCurrentStyle()->m_iColsPerPlayer)
if(col < 0 || col >= GAMESTATE->GetCurrentStyle(pn)->m_iColsPerPlayer)
{
luaL_error(L, "Column must be between 1 and %d "
"(GAMESTATE:GetCurrentStyle():ColumnsPerPlayer()).",
GAMESTATE->GetCurrentStyle()->m_iColsPerPlayer);
"(GAMESTATE:GetCurrentStyle(pn):ColumnsPerPlayer()).",
GAMESTATE->GetCurrentStyle(pn)->m_iColsPerPlayer);
}
return col;
}
static int Step(T* p, lua_State* L)
static int step(T* p, lua_State* L)
{
int col= check_column(L, 1);
int col= check_column(L, 1, p->GetPlayerState()->m_PlayerNumber);
TapNoteScore tns= Enum::Check<TapNoteScore>(L, 2);
p->Step(col, tns, true);
return 0;
}
static int SetPressed(T* p, lua_State* L)
static int set_pressed(T* p, lua_State* L)
{
int col= check_column(L, 1);
int col= check_column(L, 1, p->GetPlayerState()->m_PlayerNumber);
p->SetPressed(col, true);
return 0;
}
static int DidTapNote(T* p, lua_State* L)
static int did_tap_note(T* p, lua_State* L)
{
int col= check_column(L, 1);
int col= check_column(L, 1, p->GetPlayerState()->m_PlayerNumber);
TapNoteScore tns= Enum::Check<TapNoteScore>(L, 2);
bool bright= BArg(3);
p->DidTapNote(col, tns, bright, true);
return 0;
}
static int DidHoldNote(T* p, lua_State* L)
static int did_hold_note(T* p, lua_State* L)
{
int col= check_column(L, 1);
int col= check_column(L, 1, p->GetPlayerState()->m_PlayerNumber);
HoldNoteScore hns= Enum::Check<HoldNoteScore>(L, 2);
bool bright= BArg(3);
p->DidHoldNote(col, hns, bright, true);
return 0;
}
static int get_column_actors(T* p, lua_State* L)
{
lua_createtable(L, p->m_ColumnRenderers.size(), 0);
for(size_t i= 0; i < p->m_ColumnRenderers.size(); ++i)
{
p->m_ColumnRenderers[i].PushSelf(L);
lua_rawseti(L, -2, i+1);
}
return 1;
}
LunaNoteField()
{
ADD_METHOD(SetStepCallback);
ADD_METHOD(SetSetPressedCallback);
ADD_METHOD(SetDidTapNoteCallback);
ADD_METHOD(SetDidHoldNoteCallback);
ADD_METHOD(Step);
ADD_METHOD(SetPressed);
ADD_METHOD(DidTapNote);
ADD_METHOD(DidHoldNote);
ADD_METHOD(set_step_callback);
ADD_METHOD(set_set_pressed_callback);
ADD_METHOD(set_did_tap_note_callback);
ADD_METHOD(set_did_hold_note_callback);
ADD_METHOD(step);
ADD_METHOD(set_pressed);
ADD_METHOD(did_tap_note);
ADD_METHOD(did_hold_note);
ADD_METHOD(get_column_actors);
}
};
+9 -3
View File
@@ -22,13 +22,15 @@ public:
virtual void Update( float fDeltaTime );
virtual void DrawPrimitives();
virtual void Init( const PlayerState* pPlayerState, float fYReverseOffsetPixels );
virtual void Init( const PlayerState* pPlayerState, float fYReverseOffsetPixels, bool use_states_zoom= true );
virtual void Load(
const NoteData* pNoteData,
int iDrawDistanceAfterTargetsPixels,
int iDrawDistanceBeforeTargetsPixels );
virtual void Unload();
void InitColumnRenderers();
virtual void HandleMessage( const Message &msg );
// This is done automatically by Init(), but can be re-called explicitly if the
@@ -55,6 +57,10 @@ public:
int m_iBeginMarker, m_iEndMarker; // only used with MODE_EDIT
// m_ColumnRenderers belongs in the protected section, but it's here in
// public so that the Lua API can access it. -Kyz
vector<NoteColumnRenderer> m_ColumnRenderers;
protected:
void CacheNoteSkin( const RString &sNoteSkin );
void UncacheNoteSkin( const RString &sNoteSkin );
@@ -84,8 +90,6 @@ protected:
const NoteData *m_pNoteData;
float m_fPercentFadeToFail; // -1 if not fading to fail
const PlayerState* m_pPlayerState;
int m_iDrawDistanceAfterTargetsPixels; // this should be a negative number
int m_iDrawDistanceBeforeTargetsPixels; // this should be a positive number
@@ -101,6 +105,8 @@ protected:
~NoteDisplayCols() { delete [] display; }
};
NoteFieldRenderArgs m_FieldRenderArgs;
/* All loaded note displays, mapped by their name. */
map<RString, NoteDisplayCols *> m_NoteDisplays;
NoteDisplayCols *m_pCurDisplay;
+1 -1
View File
@@ -221,7 +221,7 @@ RString OptionRow::GetRowTitle() const
else if( GAMESTATE->m_pCurCourse )
{
const Course *pCourse = GAMESTATE->m_pCurCourse;
StepsType st = GAMESTATE->GetCurrentStyle()->m_StepsType;
StepsType st = GAMESTATE->GetCurrentStyle(GAMESTATE->GetMasterPlayerNumber())->m_StepsType;
const Trail* pTrail = pCourse->GetTrail( st );
ASSERT( pTrail != NULL );
pTrail->GetDisplayBpms( bpms );
+7 -4
View File
@@ -434,13 +434,16 @@ class OptionRowHandlerListSteps : public OptionRowHandlerList
m_Def.m_vsChoices.push_back( "" );
m_aListEntries.push_back( GameCommand() );
}
else if(GAMESTATE->GetCurrentStyle() && GAMESTATE->IsCourseMode() && GAMESTATE->m_pCurCourse) // playing a course
// TODO: Fix this OptionRow to fetch steps for all styles available.
// This is broken in kickbox game mode because kickbox uses separated
// styles. -Kyz
else if(GAMESTATE->GetCurrentStyle(GAMESTATE->GetMasterPlayerNumber()) && GAMESTATE->IsCourseMode() && GAMESTATE->m_pCurCourse) // playing a course
{
m_Def.m_bOneChoiceForAllPlayers = (bool)PREFSMAN->m_bLockCourseDifficulties;
m_Def.m_layoutType = StringToLayoutType( STEPS_ROW_LAYOUT_TYPE );
vector<Trail*> vTrails;
GAMESTATE->m_pCurCourse->GetTrails( vTrails, GAMESTATE->GetCurrentStyle()->m_StepsType );
GAMESTATE->m_pCurCourse->GetTrails( vTrails, GAMESTATE->GetCurrentStyle(GAMESTATE->GetMasterPlayerNumber())->m_StepsType );
for( unsigned i=0; i<vTrails.size(); i++ )
{
Trail* pTrail = vTrails[i];
@@ -453,13 +456,13 @@ class OptionRowHandlerListSteps : public OptionRowHandlerList
m_aListEntries.push_back( mc );
}
}
else if(GAMESTATE->GetCurrentStyle() && GAMESTATE->m_pCurSong) // playing a song
else if(GAMESTATE->GetCurrentStyle(GAMESTATE->GetMasterPlayerNumber()) && GAMESTATE->m_pCurSong) // playing a song
{
m_Def.m_layoutType = StringToLayoutType( STEPS_ROW_LAYOUT_TYPE );
vector<Steps*> vpSteps;
Song *pSong = GAMESTATE->m_pCurSong;
SongUtil::GetSteps( pSong, vpSteps, GAMESTATE->GetCurrentStyle()->m_StepsType );
SongUtil::GetSteps( pSong, vpSteps, GAMESTATE->GetCurrentStyle(GAMESTATE->GetMasterPlayerNumber())->m_StepsType );
StepsUtil::RemoveLockedSteps( pSong, vpSteps );
StepsUtil::SortNotesArrayByDifficulty( vpSteps );
for( unsigned i=0; i<vpSteps.size(); i++ )
+1 -1
View File
@@ -193,7 +193,7 @@ void PercentageDisplay::Refresh()
bool PercentageDisplay::ShowDancePointsNotPercentage() const
{
// Use staight dance points in workout because the percentage denominator isn't accurate - we don't know when the players are going to stop.
// Use straight dance points in workout because the percentage denominator isn't accurate - we don't know when the players are going to stop.
if( GAMESTATE->m_pCurCourse )
{
+57 -37
View File
@@ -300,7 +300,7 @@ void Player::Init(
{
// Init judgment positions
bool bPlayerUsingBothSides = GAMESTATE->GetCurrentStyle()->GetUsesCenteredArrows();
bool bPlayerUsingBothSides = GAMESTATE->GetCurrentStyle(pPlayerState->m_PlayerNumber)->GetUsesCenteredArrows();
Actor TempJudgment;
TempJudgment.SetName( "Judgment" );
ActorUtil::LoadCommand( TempJudgment, sType, "Transform" );
@@ -499,13 +499,13 @@ void Player::Init(
}
// Load HoldJudgments
m_vpHoldJudgment.resize( GAMESTATE->GetCurrentStyle()->m_iColsPerPlayer );
for( int i = 0; i < GAMESTATE->GetCurrentStyle()->m_iColsPerPlayer; ++i )
m_vpHoldJudgment.resize( GAMESTATE->GetCurrentStyle(GetPlayerState()->m_PlayerNumber)->m_iColsPerPlayer );
for( int i = 0; i < GAMESTATE->GetCurrentStyle(GetPlayerState()->m_PlayerNumber)->m_iColsPerPlayer; ++i )
m_vpHoldJudgment[i] = NULL;
if( HasVisibleParts() )
{
for( int i = 0; i < GAMESTATE->GetCurrentStyle()->m_iColsPerPlayer; ++i )
for( int i = 0; i < GAMESTATE->GetCurrentStyle(GetPlayerState()->m_PlayerNumber)->m_iColsPerPlayer; ++i )
{
HoldJudgment *pJudgment = new HoldJudgment;
// xxx: assumes sprite; todo: don't force 1x2 -aj
@@ -523,7 +523,7 @@ void Player::Init(
this->AddChild( m_pNoteField );
}
m_vbFretIsDown.resize( GAMESTATE->GetCurrentStyle()->m_iColsPerPlayer );
m_vbFretIsDown.resize( GAMESTATE->GetCurrentStyle(GetPlayerState()->m_PlayerNumber)->m_iColsPerPlayer );
FOREACH( bool, m_vbFretIsDown, b )
*b = false;
@@ -649,7 +649,7 @@ void Player::Load()
// m_pScore->Init( pn );
/* Apply transforms. */
NoteDataUtil::TransformNoteData( m_NoteData, m_pPlayerState->m_PlayerOptions.GetStage(), GAMESTATE->GetCurrentStyle()->m_StepsType );
NoteDataUtil::TransformNoteData( m_NoteData, m_pPlayerState->m_PlayerOptions.GetStage(), GAMESTATE->GetCurrentStyle(GetPlayerState()->m_PlayerNumber)->m_StepsType );
const Song* pSong = GAMESTATE->m_pCurSong;
@@ -668,7 +668,7 @@ void Player::Load()
// it has to do with there only being four cases. This is a lame
// workaround, but since only DDR has ever really implemented those
// modes, it's stayed like this. -aj
StepsType st = GAMESTATE->GetCurrentStyle()->m_StepsType;
StepsType st = GAMESTATE->GetCurrentStyle(GetPlayerState()->m_PlayerNumber)->m_StepsType;
NoteDataUtil::TransformNoteData( m_NoteData, m_pPlayerState->m_PlayerOptions.GetStage(), st );
if (BATTLE_RAVE_MIRROR)
@@ -707,7 +707,7 @@ void Player::Load()
m_pNoteField->Load( &m_NoteData, iDrawDistanceAfterTargetsPixels, iDrawDistanceBeforeTargetsPixels );
}
bool bPlayerUsingBothSides = GAMESTATE->GetCurrentStyle()->GetUsesCenteredArrows();
bool bPlayerUsingBothSides = GAMESTATE->GetCurrentStyle(GetPlayerState()->m_PlayerNumber)->GetUsesCenteredArrows();
if( m_pAttackDisplay )
m_pAttackDisplay->SetX( ATTACK_DISPLAY_X.GetValue(pn, bPlayerUsingBothSides) - 40 );
// set this in Update //m_pAttackDisplay->SetY( bReverse ? ATTACK_DISPLAY_Y_REVERSE : ATTACK_DISPLAY_Y );
@@ -860,7 +860,7 @@ void Player::Update( float fDeltaTime )
// Update Y positions
{
for( int c=0; c<GAMESTATE->GetCurrentStyle()->m_iColsPerPlayer; c++ )
for( int c=0; c<GAMESTATE->GetCurrentStyle(GetPlayerState()->m_PlayerNumber)->m_iColsPerPlayer; c++ )
{
float fPercentReverse = m_pPlayerState->m_PlayerOptions.GetCurrent().GetReversePercentForColumn(c);
float fHoldJudgeYPos = SCALE( fPercentReverse, 0.f, 1.f, HOLD_JUDGMENT_Y_STANDARD, HOLD_JUDGMENT_Y_REVERSE );
@@ -920,16 +920,17 @@ void Player::Update( float fDeltaTime )
}
// update pressed flag
const int iNumCols = GAMESTATE->GetCurrentStyle()->m_iColsPerPlayer;
const int iNumCols = GAMESTATE->GetCurrentStyle(GetPlayerState()->m_PlayerNumber)->m_iColsPerPlayer;
ASSERT_M( iNumCols <= MAX_COLS_PER_PLAYER, ssprintf("%i > %i", iNumCols, MAX_COLS_PER_PLAYER) );
for( int col=0; col < iNumCols; ++col )
{
ASSERT( m_pPlayerState != NULL );
// TODO: Remove use of PlayerNumber.
GameInput GameI = GAMESTATE->GetCurrentStyle()->StyleInputToGameInput( col, m_pPlayerState->m_PlayerNumber );
vector<GameInput> GameI;
GAMESTATE->GetCurrentStyle(GetPlayerState()->m_PlayerNumber)->StyleInputToGameInput( col, m_pPlayerState->m_PlayerNumber, GameI );
bool bIsHoldingButton = INPUTMAPPER->IsBeingPressed( GameI );
bool bIsHoldingButton= INPUTMAPPER->IsBeingPressed(GameI);
// TODO: Make this work for non-human-controlled players
if( bIsHoldingButton && !GAMESTATE->m_bDemonstrationOrJukebox && m_pPlayerState->m_PlayerController==PC_HUMAN )
@@ -1221,10 +1222,10 @@ void Player::UpdateHoldNotes( int iSongRow, float fDeltaTime, vector<TrackRowTap
}
else
{
GameInput GameI = GAMESTATE->GetCurrentStyle()->StyleInputToGameInput( iTrack, pn );
// this previously read as bIsHoldingButton &=
// was there a specific reason for this? - Friez
bIsHoldingButton &= INPUTMAPPER->IsBeingPressed( GameI, m_pPlayerState->m_mp );
vector<GameInput> GameI;
GAMESTATE->GetCurrentStyle(GetPlayerState()->m_PlayerNumber)->StyleInputToGameInput( iTrack, pn, GameI );
bIsHoldingButton &= INPUTMAPPER->IsBeingPressed(GameI, m_pPlayerState->m_mp);
}
}
}
@@ -1505,7 +1506,7 @@ void Player::ApplyWaitingTransforms()
// if re-adding noteskin changes, this is one place to edit -aj
NoteDataUtil::TransformNoteData( m_NoteData, po, GAMESTATE->GetCurrentStyle()->m_StepsType, BeatToNoteRow(fStartBeat), BeatToNoteRow(fEndBeat) );
NoteDataUtil::TransformNoteData( m_NoteData, po, GAMESTATE->GetCurrentStyle(GetPlayerState()->m_PlayerNumber)->m_StepsType, BeatToNoteRow(fStartBeat), BeatToNoteRow(fEndBeat) );
}
m_pPlayerState->m_ModsToApply.clear();
}
@@ -1516,7 +1517,7 @@ void Player::DrawPrimitives()
PlayerNumber pn = m_pPlayerState->m_PlayerNumber;
// May have both players in doubles (for battle play); only draw primary player.
if( GAMESTATE->GetCurrentStyle()->m_StyleType == StyleType_OnePlayerTwoSides &&
if( GAMESTATE->GetCurrentStyle(GetPlayerState()->m_PlayerNumber)->m_StyleType == StyleType_OnePlayerTwoSides &&
pn != GAMESTATE->GetMasterPlayerNumber() )
return;
@@ -2141,9 +2142,14 @@ void Player::StepStrumHopo( int col, int row, const RageTimer &tm, bool bHeld, b
int iNumTracksHeld = 0;
for( int t=0; t<m_NoteData.GetNumTracks(); t++ )
{
GameInput GameI = GAMESTATE->GetCurrentStyle()->StyleInputToGameInput( t, pn );
const float fSecsHeld = INPUTMAPPER->GetSecsHeld( GameI );
if( fSecsHeld > 0 && fSecsHeld < m_fTimingWindowJump )
vector<GameInput> GameI;
GAMESTATE->GetCurrentStyle(GetPlayerState()->m_PlayerNumber)->StyleInputToGameInput( t, pn, GameI );
float secs_held= 0.0f;
for(size_t i= 0; i < GameI.size(); ++i)
{
secs_held= max(secs_held, INPUTMAPPER->GetSecsHeld( GameI[i] ));
}
if( secs_held > 0 && secs_held < m_fTimingWindowJump )
iNumTracksHeld++;
}
@@ -2417,7 +2423,7 @@ void Player::StepStrumHopo( int col, int row, const RageTimer &tm, bool bHeld, b
{
bool bNoteRowMatchesFrets = true;
int iFirstNoteCol = -1;
for( int i=0; i<GAMESTATE->GetCurrentStyle()->m_iColsPerPlayer; i++ )
for( int i=0; i<GAMESTATE->GetCurrentStyle(GetPlayerState()->m_PlayerNumber)->m_iColsPerPlayer; i++ )
{
const TapNote &tn = m_NoteData.GetTapNote( i, iRowOfOverlappingNoteOrRow );
bool bIsNote = (tn.type != TapNoteType_Empty);
@@ -2444,7 +2450,7 @@ void Player::StepStrumHopo( int col, int row, const RageTimer &tm, bool bHeld, b
else
{
int iLastNoteCol = -1;
for( int i=GAMESTATE->GetCurrentStyle()->m_iColsPerPlayer-1; i>=0; i-- )
for( int i=GAMESTATE->GetCurrentStyle(GetPlayerState()->m_PlayerNumber)->m_iColsPerPlayer-1; i>=0; i-- )
{
const TapNote &tn = m_NoteData.GetTapNote( i, iRowOfOverlappingNoteOrRow );
bool bIsNote = (tn.type != TapNoteType_Empty);
@@ -2950,16 +2956,25 @@ void Player::CrossedRows( int iLastRowCrossed, const RageTimer &now )
if( !REQUIRE_STEP_ON_HOLD_HEADS )
{
PlayerNumber pn = m_pPlayerState->m_PlayerNumber;
GameInput GameI = GAMESTATE->GetCurrentStyle()->StyleInputToGameInput( iTrack, pn );
vector<GameInput> GameI;
GAMESTATE->GetCurrentStyle(GetPlayerState()->m_PlayerNumber)->StyleInputToGameInput( iTrack, pn, GameI );
if( PREFSMAN->m_fPadStickSeconds > 0.f )
{
float fSecsHeld = INPUTMAPPER->GetSecsHeld( GameI, m_pPlayerState->m_mp );
if( fSecsHeld >= PREFSMAN->m_fPadStickSeconds )
Step( iTrack, -1, now - PREFSMAN->m_fPadStickSeconds, true, false );
for(size_t i= 0; i < GameI.size(); ++i)
{
float fSecsHeld = INPUTMAPPER->GetSecsHeld(GameI[i], m_pPlayerState->m_mp);
if(fSecsHeld >= PREFSMAN->m_fPadStickSeconds)
{
Step(iTrack, -1, now - PREFSMAN->m_fPadStickSeconds, true, false);
}
}
}
else if( INPUTMAPPER->IsBeingPressed(GameI, m_pPlayerState->m_mp) )
else
{
Step( iTrack, -1, now, true, false );
if(INPUTMAPPER->IsBeingPressed(GameI, m_pPlayerState->m_mp))
{
Step(iTrack, -1, now, true, false);
}
}
}
break;
@@ -2969,17 +2984,22 @@ void Player::CrossedRows( int iLastRowCrossed, const RageTimer &now )
// Hold the panel while crossing a mine will cause the mine to explode
// TODO: Remove use of PlayerNumber.
PlayerNumber pn = m_pPlayerState->m_PlayerNumber;
GameInput GameI = GAMESTATE->GetCurrentStyle()->StyleInputToGameInput( iTrack, pn );
if( PREFSMAN->m_fPadStickSeconds > 0 )
vector<GameInput> GameI;
GAMESTATE->GetCurrentStyle(GetPlayerState()->m_PlayerNumber)->StyleInputToGameInput( iTrack, pn, GameI );
if( PREFSMAN->m_fPadStickSeconds > 0.0f )
{
float fSecsHeld = INPUTMAPPER->GetSecsHeld( GameI, m_pPlayerState->m_mp );
if( fSecsHeld >= PREFSMAN->m_fPadStickSeconds )
Step( iTrack, -1, now - PREFSMAN->m_fPadStickSeconds, true, false );
for(size_t i= 0; i < GameI.size(); ++i)
{
float fSecsHeld = INPUTMAPPER->GetSecsHeld(GameI[i], m_pPlayerState->m_mp);
if(fSecsHeld >= PREFSMAN->m_fPadStickSeconds)
{
Step( iTrack, -1, now - PREFSMAN->m_fPadStickSeconds, true, false );
}
}
}
else
else if(INPUTMAPPER->IsBeingPressed(GameI, m_pPlayerState->m_mp))
{
if( INPUTMAPPER->IsBeingPressed(GameI, m_pPlayerState->m_mp) )
Step( iTrack, iRow, now, true, false );
Step( iTrack, iRow, now, true, false );
}
break;
}
+61 -3
View File
@@ -723,7 +723,9 @@ void PlayerOptions::ToggleOneTurn( Turn t )
float PlayerOptions::GetReversePercentForColumn( int iCol ) const
{
float f = 0;
int iNumCols = GAMESTATE->GetCurrentStyle()->m_iColsPerPlayer;
ASSERT(m_pn == PLAYER_1 || m_pn == PLAYER_2);
ASSERT(GAMESTATE->GetCurrentStyle(m_pn) != NULL);
int iNumCols = GAMESTATE->GetCurrentStyle(m_pn)->m_iColsPerPlayer;
f += m_fScrolls[SCROLL_REVERSE];
@@ -784,6 +786,62 @@ bool PlayerOptions::operator==( const PlayerOptions &other ) const
return true;
}
PlayerOptions& PlayerOptions::operator=(PlayerOptions const& other)
{
// Do not copy m_pn from the other, it must be preserved as what PlayerState set it to.
#define CPY(x) x= other.x;
#define CPY_SPEED(x) m_ ## x = other.m_ ## x; m_Speed ## x = other.m_Speed ## x;
CPY(m_LifeType);
CPY(m_DrainType);
CPY(m_BatteryLives);
CPY_SPEED(fTimeSpacing);
CPY_SPEED(fScrollSpeed);
CPY_SPEED(fScrollBPM);
CPY_SPEED(fMaxScrollBPM);
CPY_SPEED(fRandomSpeed);
CPY(m_FailType);
CPY(m_MinTNSToHideNotes);
CPY(m_bMuteOnError);
CPY_SPEED(fDark);
CPY_SPEED(fBlind);
CPY_SPEED(fCover);
CPY_SPEED(fRandAttack);
CPY_SPEED(fNoAttack);
CPY_SPEED(fPlayerAutoPlay);
CPY_SPEED(fPerspectiveTilt);
CPY_SPEED(fSkew);
CPY(m_sNoteSkin);
for( int i = 0; i < PlayerOptions::NUM_ACCELS; ++i )
{
CPY_SPEED(fAccels[i]);
}
for( int i = 0; i < PlayerOptions::NUM_EFFECTS; ++i )
{
CPY_SPEED(fEffects[i]);
}
for( int i = 0; i < PlayerOptions::NUM_APPEARANCES; ++i )
{
CPY_SPEED(fAppearances[i]);
}
for( int i = 0; i < PlayerOptions::NUM_SCROLLS; ++i )
{
CPY_SPEED(fScrolls[i]);
}
for( int i = 0; i < PlayerOptions::NUM_TURNS; ++i )
{
CPY(m_bTurns[i]);
}
for( int i = 0; i < PlayerOptions::NUM_TRANSFORMS; ++i )
{
CPY(m_bTransforms[i]);
}
#undef CPY
#undef CPY_SPEED
return *this;
}
bool PlayerOptions::IsEasierForSongAndSteps( Song* pSong, Steps* pSteps, PlayerNumber pn ) const
{
if( m_fTimeSpacing && pSteps->HasSignificantTimingChanges() )
@@ -835,7 +893,7 @@ bool PlayerOptions::IsEasierForSongAndSteps( Song* pSong, Steps* pSteps, PlayerN
DisplayBpms bpms;
if( GAMESTATE->IsCourseMode() )
{
Trail *pTrail = GAMESTATE->m_pCurCourse->GetTrail( GAMESTATE->GetCurrentStyle()->m_StepsType );
Trail *pTrail = GAMESTATE->m_pCurCourse->GetTrail( GAMESTATE->GetCurrentStyle(m_pn)->m_StepsType );
pTrail->GetDisplayBpms( bpms );
}
else
@@ -1357,7 +1415,7 @@ public:
static int GetReversePercentForColumn( T *p, lua_State *L )
{
const int colNum = IArg(1);
const int numColumns = GAMESTATE->GetCurrentStyle()->m_iColsPerPlayer;
const int numColumns = GAMESTATE->GetCurrentStyle(p->m_pn)->m_iColsPerPlayer;
// We don't want to go outside the bounds.
if(colNum < 0 || colNum > numColumns)
+3
View File
@@ -96,6 +96,7 @@ public:
bool operator==( const PlayerOptions &other ) const;
bool operator!=( const PlayerOptions &other ) const { return !operator==(other); }
PlayerOptions& operator=(PlayerOptions const& other);
/** @brief The various acceleration mods. */
enum Accel {
@@ -183,6 +184,8 @@ public:
float GetReversePercentForColumn( int iCol ) const; // accounts for all Directions
PlayerNumber m_pn; // Needed for fetching the style.
LifeType m_LifeType;
DrainType m_DrainType; // only used with LifeBar
int m_BatteryLives;
+21 -1
View File
@@ -27,6 +27,7 @@ Grade GetGradeFromPercent( float fPercent );
void PlayerStageStats::InternalInit()
{
m_pStyle= NULL;
m_for_multiplayer= false;
m_player_number= PLAYER_1;
m_multiplayer_number= MultiPlayer_P1;
@@ -85,6 +86,7 @@ void PlayerStageStats::Init(MultiPlayer pn)
void PlayerStageStats::AddStats( const PlayerStageStats& other )
{
m_pStyle= other.m_pStyle;
m_bJoined = other.m_bJoined;
FOREACH_CONST( Steps*, other.m_vpPossibleSteps, s )
m_vpPossibleSteps.push_back( *s );
@@ -372,7 +374,25 @@ void PlayerStageStats::SetLifeRecordAt( float fLife, float fStepsSecond )
m_fLastSecond = max( fStepsSecond, m_fLastSecond );
//LOG->Trace( "fLastSecond = %f", m_fLastSecond );
// fSecond will always be greater than any value already in the map.
// fStepsSecond will usually be greater than any value already in the map,
// but if a tap and a hold both set the life on the same frame, it won't.
// Check whether an entry already exists for the current time, and move it
// back a tiny bit if it does and the new value is not the same as the old.
// Otherwise, you get the rare bug where the life graph shows a gradual
// decline when the lifebar was actually full up to a miss. This occurs
// because the first call has full life, and removes the previous full life
// entry. Then the second call of the frame occurs and sets the life for
// the current time to a lower value.
// -Kyz
map<float,float>::iterator curr= m_fLifeRecord.find(fStepsSecond);
if(curr != m_fLifeRecord.end())
{
if(curr->second != fLife)
{
// 2^-8
m_fLifeRecord[fStepsSecond - 0.00390625]= curr->second;
}
}
m_fLifeRecord[fStepsSecond] = fLife;
Message msg(static_cast<MessageID>(Message_LifeMeterChangedP1+m_player_number));
+2
View File
@@ -7,6 +7,7 @@
#include "PlayerNumber.h"
#include <map>
class Steps;
class Style;
struct lua_State;
/** @brief Contains statistics for one stage of play - either one song, or a whole course. */
class PlayerStageStats
@@ -36,6 +37,7 @@ public:
bool m_for_multiplayer;
PlayerNumber m_player_number;
MultiPlayer m_multiplayer_number;
const Style* m_pStyle;
bool m_bJoined;
bool m_bPlayerCanAchieveFullCombo;
+10
View File
@@ -16,6 +16,7 @@ PlayerState::PlayerState()
void PlayerState::Reset()
{
m_NotefieldZoom= 1.0f;
m_PlayerOptions.Init();
m_fLastDrawnBeat = -100;
@@ -96,6 +97,15 @@ void PlayerState::Update( float fDelta )
m_fSecondsUntilAttacksPhasedOut = max( 0, m_fSecondsUntilAttacksPhasedOut - fDelta );
}
void PlayerState::SetPlayerNumber(PlayerNumber pn)
{
m_PlayerNumber = pn;
FOREACH_ENUM(ModsLevel, ml)
{
m_PlayerOptions.Get(ml).m_pn= pn;
}
}
void PlayerState::ResetToDefaultPlayerOptions( ModsLevel l )
{
PlayerOptions po;
+6
View File
@@ -37,6 +37,8 @@ public:
* @param fDelta the current time. */
void Update( float fDelta );
void SetPlayerNumber(PlayerNumber pn);
/**
* @brief The PlayerNumber assigned to this Player: usually 1 or 2.
*
@@ -51,6 +53,10 @@ public:
*/
MultiPlayer m_mp;
// This is used by ArrowEffects and the NoteField to zoom both appropriately
// to fit in the space available. -Kyz
float m_NotefieldZoom;
// Music statistics:
SongPosition m_Position;
+8 -2
View File
@@ -3,6 +3,12 @@
#ifndef PRODUCT_INFO_H
#define PRODUCT_INFO_H
// XXX: VC doesn't generate this yet. Hack around it for now
#include "config.h"
#ifdef USE_GITVERSION
#include "gitversion.h"
#endif
/**
* @brief A friendly string to refer to the product in crash dialogs, etc.
*
@@ -16,7 +22,7 @@
* As an example, use "StepMania4" here, not "StepMania".
* It would cause a conflict with older versions such as StepMania 3.X.
*/
#define PRODUCT_ID_BARE StepMania 5
#define PRODUCT_ID_BARE StepMania 5.0
/**
* @brief Version info displayed to the user.
@@ -30,7 +36,7 @@
* </li></ul>
*/
#ifndef PRODUCT_VER_BARE
#define PRODUCT_VER_BARE v5.0 beta 4a
#define PRODUCT_VER_BARE 5.0-UNKNOWN
#endif
/**
+35 -1
View File
@@ -5,6 +5,7 @@
*/
#include "global.h"
#include "RageLog.h"
#include "RageMath.h"
#include "RageTypes.h"
#include <float.h>
@@ -40,6 +41,22 @@ void RageVec3Normalize( RageVector3* pOut, const RageVector3* pV )
pOut->z = pV->z * scale;
}
void VectorFloatNormalize(vector<float>& v)
{
ASSERT_M(v.size() == 3, "Can't normalize a non-3D vector.");
float scale = 1.0f / sqrtf(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
v[0]*= scale;
v[1]*= scale;
v[2]*= scale;
}
void RageVec3Cross(RageVector3* ret, RageVector3 const* a, RageVector3 const* b)
{
ret->x= (a->y * b->z) - (a->z * b->y);
ret->y= ((a->x * b->z) - (a->z * b->x));
ret->z= (a->x * b->y) - (a->y * b->x);
}
void RageVec3TransformCoord( RageVector3* pOut, const RageVector3* pV, const RageMatrix* pM )
{
RageVector4 temp( pV->x, pV->y, pV->z, 1.0f ); // translate
@@ -313,6 +330,21 @@ void RageMatrixRotationXYZ( RageMatrix* pOut, float rX, float rY, float rZ )
pOut->m33 = 1;
}
void RageAARotate(RageVector3* inret, RageVector3 const* axis, float angle)
{
float ha= angle/2.0f;
float ca2= RageFastCos(ha);
float sa2= RageFastSin(ha);
RageVector4 quat(axis->x * sa2, axis->y * sa2, axis->z * sa2, ca2);
RageVector4 quatc(-quat.x, -quat.y, -quat.z, ca2);
RageVector4 point(inret->x, inret->y, inret->z, 0.0f);
RageQuatMultiply(&point, quat, point);
RageQuatMultiply(&point, point, quatc);
inret->x= point.x;
inret->y= point.y;
inret->z= point.z;
}
void RageQuatMultiply( RageVector4* pOut, const RageVector4 &pA, const RageVector4 &pB )
{
RageVector4 out;
@@ -673,7 +705,8 @@ float RageBezier2D::EvaluateYFromX( float fX ) const
* http://www.tinaja.com/text/bezmath.html). This usually finds T within an
* acceptable error margin in a few steps. */
float fT = SCALE( fX, m_X.GetBezierStart(), m_X.GetBezierEnd(), 0, 1 );
while(1)
// Don't try more than 100 times, the curve might be a bit nonsensical. -Kyz
for(int i= 0; i < 100; ++i)
{
float fGuessedX = m_X.Evaluate( fT );
float fError = fX-fGuessedX;
@@ -685,6 +718,7 @@ float RageBezier2D::EvaluateYFromX( float fX ) const
float fSlope = m_X.GetSlope( fT );
fT += fError/fSlope;
}
return m_Y.Evaluate( fT );
}
void RageBezier2D::SetFromBezier(
+3
View File
@@ -18,6 +18,8 @@ void RageVec3AddToBounds( const RageVector3 &p, RageVector3 &mins, RageVector3 &
void RageVec2Normalize( RageVector2* pOut, const RageVector2* pV );
void RageVec3Normalize( RageVector3* pOut, const RageVector3* pV );
void VectorFloatNormalize(vector<float>& v);
void RageVec3Cross(RageVector3* ret, RageVector3 const* a, RageVector3 const* b);
void RageVec3TransformCoord( RageVector3* pOut, const RageVector3* pV, const RageMatrix* pM );
void RageVec3TransformNormal( RageVector3* pOut, const RageVector3* pV, const RageMatrix* pM );
void RageVec4TransformCoord( RageVector4* pOut, const RageVector4* pV, const RageMatrix* pM );
@@ -34,6 +36,7 @@ void RageMatrixRotationX( RageMatrix* pOut, float fTheta );
void RageMatrixRotationY( RageMatrix* pOut, float fTheta );
void RageMatrixRotationZ( RageMatrix* pOut, float fTheta );
void RageMatrixRotationXYZ( RageMatrix* pOut, float rX, float rY, float rZ );
void RageAARotate(RageVector3* inret, RageVector3 const* axis, float angle);
void RageQuatFromHPR(RageVector4* pOut, RageVector3 hpr );
void RageQuatFromPRH(RageVector4* pOut, RageVector3 prh );
void RageMatrixFromQuat( RageMatrix* pOut, const RageVector4 q );
+5 -15
View File
@@ -49,24 +49,14 @@ inline U lerp( T x, U l, U h )
return U(x * (h - l) + l);
}
inline bool CLAMP( int &x, int l, int h )
template<typename T, typename U, typename V>
inline bool CLAMP(T& x, U l, V h)
{
if (x > h) { x = h; return true; }
else if (x < l) { x = l; return true; }
return false;
}
inline bool CLAMP( unsigned &x, unsigned l, unsigned h )
{
if (x > h) { x = h; return true; }
else if (x < l) { x = l; return true; }
return false;
}
inline bool CLAMP( float &x, float l, float h )
{
if (x > h) { x = h; return true; }
else if (x < l) { x = l; return true; }
if(x > static_cast<T>(h)) { x= static_cast<T>(h); return true; }
else if(x < static_cast<T>(l)) { x= static_cast<T>(l); return true; }
return false;
}
template<class T>
inline bool ENUM_CLAMP( T &x, T l, T h )
{
+8 -3
View File
@@ -20,11 +20,16 @@ void ReceptorArrow::Load( const PlayerState* pPlayerState, int iColNo )
m_iColNo = iColNo;
const PlayerNumber pn = m_pPlayerState->m_PlayerNumber;
const GameInput GameI = GAMESTATE->GetCurrentStyle()->StyleInputToGameInput( iColNo, pn );
vector<GameInput> GameI;
GAMESTATE->GetCurrentStyle(pn)->StyleInputToGameInput(iColNo, pn, GameI);
NOTESKIN->SetPlayerNumber( pn );
NOTESKIN->SetGameController( GameI.controller );
// FIXME? Does this cause a problem when game inputs on different
// controllers are mapped to the same column? Such a thing could be set
// up in a style that uses two controllers and has a mapping that fits the
// requirements. -Kyz
NOTESKIN->SetGameController( GameI[0].controller );
RString sButton = GAMESTATE->GetCurrentStyle()->ColToButtonName( iColNo );
RString sButton = GAMESTATE->GetCurrentStyle(pn)->ColToButtonName( iColNo );
m_pReceptor.Load( NOTESKIN->LoadActor(sButton, "Receptor") );
this->AddChild( m_pReceptor );
+13 -14
View File
@@ -19,7 +19,7 @@ void ReceptorArrowRow::Load( const PlayerState* pPlayerState, float fYReverseOff
m_pPlayerState = pPlayerState;
m_fYReverseOffsetPixels = fYReverseOffset;
const Style* pStyle = GAMESTATE->GetCurrentStyle();
const Style* pStyle = GAMESTATE->GetCurrentStyle(pPlayerState->m_PlayerNumber);
for( int c=0; c<pStyle->m_iColsPerPlayer; c++ )
{
@@ -30,6 +30,16 @@ void ReceptorArrowRow::Load( const PlayerState* pPlayerState, float fYReverseOff
}
}
void ReceptorArrowRow::SetColumnRenderers(vector<NoteColumnRenderer>& renderers)
{
ASSERT_M(renderers.size() == m_ReceptorArrow.size(), "Notefield has different number of columns than receptor row.");
for(size_t c= 0; c < m_ReceptorArrow.size(); ++c)
{
m_ReceptorArrow[c]->SetFakeParent(&(renderers[c]));
}
m_renderers= &renderers;
}
ReceptorArrowRow::~ReceptorArrowRow()
{
for( unsigned i = 0; i < m_ReceptorArrow.size(); ++i )
@@ -53,24 +63,13 @@ void ReceptorArrowRow::Update( float fDeltaTime )
m_ReceptorArrow[c]->SetBaseAlpha( fBaseAlpha );
// set arrow XYZ
float fX = ArrowEffects::GetXPos( m_pPlayerState, c, 0 );
const float fY = ArrowEffects::GetYPos( m_pPlayerState, c, 0, m_fYReverseOffsetPixels );
const float fZ = ArrowEffects::GetZPos( m_pPlayerState, c, 0 );
m_ReceptorArrow[c]->SetX( fX );
m_ReceptorArrow[c]->SetY( fY );
m_ReceptorArrow[c]->SetZ( fZ );
const float fRotation = ArrowEffects::ReceptorGetRotationZ( m_pPlayerState );
m_ReceptorArrow[c]->SetRotationZ( fRotation );
const float fZoom = ArrowEffects::GetZoom( m_pPlayerState );
m_ReceptorArrow[c]->SetZoom( fZoom );
(*m_renderers)[c].UpdateReceptorGhostStuff(m_ReceptorArrow[c]);
}
}
void ReceptorArrowRow::DrawPrimitives()
{
const Style* pStyle = GAMESTATE->GetCurrentStyle();
const Style* pStyle = GAMESTATE->GetCurrentStyle(m_pPlayerState->m_PlayerNumber);
for( unsigned i=0; i<m_ReceptorArrow.size(); i++ )
{
const int c = pStyle->m_iColumnDrawOrder[i];
+3
View File
@@ -4,6 +4,7 @@
#include "ReceptorArrow.h"
#include "ActorFrame.h"
#include "GameConstantsAndTypes.h"
#include "NoteDisplay.h"
class PlayerState;
/** @brief A row of ReceptorArrow objects. */
@@ -16,6 +17,7 @@ public:
virtual void DrawPrimitives();
void Load( const PlayerState* pPlayerState, float fYReverseOffset );
void SetColumnRenderers(vector<NoteColumnRenderer>& renderers);
void Step( int iCol, TapNoteScore score );
void SetPressed( int iCol );
@@ -28,6 +30,7 @@ protected:
float m_fYReverseOffsetPixels;
float m_fFadeToFailPercent;
vector<NoteColumnRenderer> const* m_renderers;
vector<ReceptorArrow *> m_ReceptorArrow;
};
+1 -1
View File
@@ -74,7 +74,7 @@ void ScoreKeeperNormal::Load(
// We might have been given lots of songs; don't keep them in memory uncompressed.
pSteps->Compress();
const Style* pStyle = GAMESTATE->GetCurrentStyle();
const Style* pStyle = GAMESTATE->GetCurrentStyle(m_pPlayerState->m_PlayerNumber);
NoteData ndPre;
pStyle->GetTransformedNoteDataForStyle( m_pPlayerState->m_PlayerNumber, ndTemp, ndPre );
+1 -1
View File
@@ -22,7 +22,7 @@ void ScreenContinue::Init()
void ScreenContinue::BeginScreen()
{
GAMESTATE->SetCurrentStyle( NULL );
GAMESTATE->SetCurrentStyle( NULL, PLAYER_INVALID );
// Unjoin human players with 0 stages left and reset non-human players.
// We need to reset non-human players because data in non-human (CPU)
+1 -1
View File
@@ -50,7 +50,7 @@ void ScreenDemonstration::Init()
ASSERT( vStylePossible.size() > 0 );
const Style* pStyle = vStylePossible[ RandomInt(vStylePossible.size()) ];
GAMESTATE->SetCurrentStyle( pStyle );
GAMESTATE->SetCurrentStyle( pStyle, PLAYER_INVALID );
}
GAMESTATE->m_PlayMode.Set( PLAY_MODE_REGULAR );
+5 -1
View File
@@ -35,7 +35,11 @@ float ScreenDimensions::GetScreenWidth()
if( fAspect > THEME_NATIVE_ASPECT )
fScale = fAspect / THEME_NATIVE_ASPECT;
ASSERT( fScale >= 1 );
return (float) ceilf(THEME_SCREEN_WIDTH * fScale);
// ceilf causes the width to come out odd when it shouldn't.
// 576 * 1.7778 = 1024.0128, which is rounded to 1025. -Kyz
int width= (int)ceilf(THEME_SCREEN_WIDTH * fScale);
width-= width % 2;
return (float)width;
}
float ScreenDimensions::GetScreenHeight()
+22 -15
View File
@@ -1273,7 +1273,7 @@ void ScreenEdit::Init()
m_CurrentAction = MAIN_MENU_CHOICE_INVALID;
m_InputPlayerNumber = PLAYER_INVALID;
if( GAMESTATE->GetCurrentStyle()->m_StyleType == StyleType_TwoPlayersSharedSides )
if( GAMESTATE->GetCurrentStyle(GAMESTATE->GetMasterPlayerNumber())->m_StyleType == StyleType_TwoPlayersSharedSides )
m_InputPlayerNumber = PLAYER_1;
FOREACH_PlayerNumber( p )
@@ -1328,7 +1328,8 @@ void ScreenEdit::Init()
ModsLevel_Preferred, m_sNoteSkin, sNoteSkin );
}
}
m_PlayerStateEdit.m_PlayerNumber = PLAYER_1;
m_PlayerStateEdit.SetPlayerNumber(PLAYER_1);
m_PlayerStateEdit.m_NotefieldZoom= 1.0f;
// If we always go with the GAMESTATE NoteSkin, we will have fun effects
// like Vivid or Flat in the editor notefield. This is not conducive to
// productive editing.
@@ -1349,7 +1350,7 @@ void ScreenEdit::Init()
m_pSteps->GetNoteData( m_NoteDataEdit );
m_NoteFieldEdit.SetXY( EDIT_X, EDIT_Y );
m_NoteFieldEdit.SetZoom( 0.5f );
m_NoteFieldEdit.Init( &m_PlayerStateEdit, PLAYER_HEIGHT*2 );
m_NoteFieldEdit.Init( &m_PlayerStateEdit, PLAYER_HEIGHT*2, false );
m_NoteFieldEdit.Load( &m_NoteDataEdit, -240, 850 );
this->AddChild( &m_NoteFieldEdit );
@@ -1511,10 +1512,15 @@ void ScreenEdit::Update( float fDeltaTime )
{
// TODO: Find a way to prevent STATE_RECORDING when in Song Timing.
for( int t=0; t<GAMESTATE->GetCurrentStyle()->m_iColsPerPlayer; t++ ) // for each track
for( int t=0; t<GAMESTATE->GetCurrentStyle(GAMESTATE->GetMasterPlayerNumber())->m_iColsPerPlayer; t++ ) // for each track
{
GameInput GameI = GAMESTATE->GetCurrentStyle()->StyleInputToGameInput( t, PLAYER_1 );
float fSecsHeld = INPUTMAPPER->GetSecsHeld( GameI );
vector<GameInput> GameI;
GAMESTATE->GetCurrentStyle(GAMESTATE->GetMasterPlayerNumber())->StyleInputToGameInput( t, PLAYER_1, GameI );
float fSecsHeld= 0.0f;
for(size_t i= 0; i < GameI.size(); ++i)
{
fSecsHeld= max(fSecsHeld, INPUTMAPPER->GetSecsHeld(GameI[i]));
}
fSecsHeld = min( fSecsHeld, m_RemoveNoteButtonLastChanged.Ago() );
if( fSecsHeld == 0 )
continue;
@@ -1565,9 +1571,10 @@ void ScreenEdit::Update( float fDeltaTime )
* range.
*/
bool bButtonIsBeingPressed = false;
for( int t=0; t<GAMESTATE->GetCurrentStyle()->m_iColsPerPlayer; t++ ) // for each track
for( int t=0; t<GAMESTATE->GetCurrentStyle(GAMESTATE->GetMasterPlayerNumber())->m_iColsPerPlayer; t++ ) // for each track
{
GameInput GameI = GAMESTATE->GetCurrentStyle()->StyleInputToGameInput( t, PLAYER_1 );
vector<GameInput> GameI;
GAMESTATE->GetCurrentStyle(GAMESTATE->GetMasterPlayerNumber())->StyleInputToGameInput( t, PLAYER_1, GameI );
if( INPUTMAPPER->IsBeingPressed(GameI) )
bButtonIsBeingPressed = true;
}
@@ -1912,9 +1919,9 @@ bool ScreenEdit::Input( const InputEventPlus &input )
static void ShiftToRightSide( int &iCol, int iNumTracks )
{
switch( GAMESTATE->GetCurrentStyle()->m_StyleType )
switch( GAMESTATE->GetCurrentStyle(GAMESTATE->GetMasterPlayerNumber())->m_StyleType )
{
DEFAULT_FAIL( GAMESTATE->GetCurrentStyle()->m_StyleType );
DEFAULT_FAIL( GAMESTATE->GetCurrentStyle(GAMESTATE->GetMasterPlayerNumber())->m_StyleType );
case StyleType_OnePlayerOneSide:
break;
case StyleType_TwoPlayersTwoSides:
@@ -2900,7 +2907,7 @@ bool ScreenEdit::InputRecord( const InputEventPlus &input, EditButton EditB )
if( input.pn != PLAYER_1 )
return false; // ignore
const int iCol = GAMESTATE->GetCurrentStyle()->GameInputToColumn( input.GameI );
const int iCol = GAMESTATE->GetCurrentStyle(GAMESTATE->GetMasterPlayerNumber())->GameInputToColumn( input.GameI );
//Is this actually a column? If not, ignore the input.
if( iCol == -1 )
@@ -3017,13 +3024,13 @@ bool ScreenEdit::InputPlay( const InputEventPlus &input, EditButton EditB )
if( GamePreferences::m_AutoPlay == PC_HUMAN && GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions.GetCurrent().m_fPlayerAutoPlay == 0 )
{
const int iCol = GAMESTATE->GetCurrentStyle()->GameInputToColumn( input.GameI );
const int iCol = GAMESTATE->GetCurrentStyle(GAMESTATE->GetMasterPlayerNumber())->GameInputToColumn( input.GameI );
bool bRelease = input.type == IET_RELEASE;
switch( input.pn )
{
case PLAYER_2:
// ignore player 2 input unless this mode requires it
if( GAMESTATE->GetCurrentStyle()->m_StyleType != StyleType_TwoPlayersSharedSides )
if( GAMESTATE->GetCurrentStyle(GAMESTATE->GetMasterPlayerNumber())->m_StyleType != StyleType_TwoPlayersSharedSides )
break;
// fall through to input handling logic:
@@ -4833,7 +4840,7 @@ void ScreenEdit::HandleAlterMenuChoice(AlterMenuChoice c, const vector<int> &iAn
const NoteData OldClipboard( m_Clipboard );
HandleAlterMenuChoice( cut, false );
StepsType st = GAMESTATE->GetCurrentStyle()->m_StepsType;
StepsType st = GAMESTATE->GetCurrentStyle(GAMESTATE->GetMasterPlayerNumber())->m_StepsType;
TurnType tt = (TurnType)iAnswers[c];
switch( tt )
{
@@ -4855,7 +4862,7 @@ void ScreenEdit::HandleAlterMenuChoice(AlterMenuChoice c, const vector<int> &iAn
int iBeginRow = m_NoteFieldEdit.m_iBeginMarker;
int iEndRow = m_NoteFieldEdit.m_iEndMarker;
TransformType tt = (TransformType)iAnswers[c];
StepsType st = GAMESTATE->GetCurrentStyle()->m_StepsType;
StepsType st = GAMESTATE->GetCurrentStyle(GAMESTATE->GetMasterPlayerNumber())->m_StepsType;
switch( tt )
{
+22 -2
View File
@@ -32,7 +32,7 @@ REGISTER_SCREEN_CLASS( ScreenEditMenu );
void ScreenEditMenu::Init()
{
// HACK: Disable any style set by the editor.
GAMESTATE->m_pCurStyle.Set( NULL );
GAMESTATE->SetCurrentStyle( NULL, PLAYER_INVALID );
// Enable all players.
FOREACH_PlayerNumber( pn )
@@ -56,6 +56,16 @@ void ScreenEditMenu::Init()
LOAD_ALL_COMMANDS_AND_SET_XY_AND_ON_COMMAND( m_textNumStepsLoadedFromProfile );
RefreshNumStepsLoadedFromProfile();
this->AddChild( &m_textNumStepsLoadedFromProfile );
if(!m_Selector.SafeToUse())
{
m_NoSongsMessage.SetName("NoSongsMessage");
m_NoSongsMessage.LoadFromFont(THEME->GetPathF(m_sName, "NoSongsMessage"));
LOAD_ALL_COMMANDS_AND_SET_XY_AND_ON_COMMAND(m_NoSongsMessage);
AddChild(&m_NoSongsMessage);
m_Selector.SetVisible(false);
m_textExplanation.SetVisible(false);
m_textNumStepsLoadedFromProfile.SetVisible(false);
}
}
void ScreenEditMenu::HandleScreenMessage( const ScreenMessage SM )
@@ -161,11 +171,16 @@ static LocalizedString DELETED_AUTOGEN_STEPS ( "ScreenEditMenu", "These steps ar
static LocalizedString STEPS_WILL_BE_LOST ( "ScreenEditMenu", "These steps will be lost permanently." );
static LocalizedString CONTINUE_WITH_DELETE ( "ScreenEditMenu", "Continue with delete?" );
static LocalizedString ENTER_EDIT_DESCRIPTION ( "ScreenEditMenu", "Enter a description for this edit.");
static LocalizedString INVALID_SELECTION("ScreenEditMenu", "One of the selected things is invalid. Pick something valid instead.");
bool ScreenEditMenu::MenuStart( const InputEventPlus & )
{
if( IsTransitioning() )
return false;
if(!m_Selector.SafeToUse())
{
return false;
}
if( m_Selector.CanGoDown() )
{
@@ -182,10 +197,15 @@ bool ScreenEditMenu::MenuStart( const InputEventPlus & )
// Difficulty sourceDiff = m_Selector.GetSelectedSourceDifficulty();
Steps* pSourceSteps = m_Selector.GetSelectedSourceSteps();
EditMenuAction action = m_Selector.GetSelectedAction();
if(st == StepsType_Invalid)
{
ScreenPrompt::Prompt(SM_None, INVALID_SELECTION);
return true;
}
GAMESTATE->m_pCurSong.Set( pSong );
GAMESTATE->m_pCurCourse.Set( NULL );
GAMESTATE->SetCurrentStyle( GAMEMAN->GetEditorStyleForStepsType(st) );
GAMESTATE->SetCurrentStyle( GAMEMAN->GetEditorStyleForStepsType(st), PLAYER_INVALID );
GAMESTATE->m_pCurSteps[PLAYER_1].Set( pSteps );
// handle error cases
+1
View File
@@ -29,6 +29,7 @@ private:
private:
BitmapText m_textExplanation;
BitmapText m_textNumStepsLoadedFromProfile;
BitmapText m_NoSongsMessage;
};
#endif
+1 -1
View File
@@ -30,7 +30,7 @@ ScreenEnding::ScreenEnding()
PROFILEMAN->LoadFirstAvailableProfile(PLAYER_2);
GAMESTATE->m_PlayMode.Set( PLAY_MODE_REGULAR );
GAMESTATE->SetCurrentStyle( GAMEMAN->GameAndStringToStyle( GAMEMAN->GetDefaultGame(),"versus") );
GAMESTATE->SetCurrentStyle( GAMEMAN->GameAndStringToStyle( GAMEMAN->GetDefaultGame(),"versus"), PLAYER_INVALID );
GAMESTATE->JoinPlayer( PLAYER_1 );
GAMESTATE->JoinPlayer( PLAYER_2 );
GAMESTATE->m_pCurSong.Set( SONGMAN->GetRandomSong() );
+2 -2
View File
@@ -103,9 +103,8 @@ void ScreenEvaluation::Init()
StageStats &ss = STATSMAN->m_vPlayedStageStats.back();
GAMESTATE->m_PlayMode.Set( PLAY_MODE_REGULAR );
GAMESTATE->SetCurrentStyle( GAMEMAN->GameAndStringToStyle(GAMEMAN->GetDefaultGame(),"versus") );
GAMESTATE->SetCurrentStyle( GAMEMAN->GameAndStringToStyle(GAMEMAN->GetDefaultGame(),"versus"), PLAYER_INVALID );
ss.m_playMode = GAMESTATE->m_PlayMode;
ss.m_pStyle = GAMESTATE->GetCurrentStyle();
ss.m_Stage = Stage_1st;
enum_add( ss.m_Stage, rand()%3 );
ss.m_EarnedExtraStage = (EarnedExtraStage)(rand() % NUM_EarnedExtraStage);
@@ -120,6 +119,7 @@ void ScreenEvaluation::Init()
FOREACH_PlayerNumber( p )
{
ss.m_player[p].m_pStyle = GAMESTATE->GetCurrentStyle(p);
if( RandomInt(2) )
PO_GROUP_ASSIGN_N( GAMESTATE->m_pPlayerState[p]->m_PlayerOptions, ModsLevel_Stage, m_bTransforms, PlayerOptions::TRANSFORM_ECHO, true ); // show "disqualified"
SO_GROUP_ASSIGN( GAMESTATE->m_SongOptions, ModsLevel_Stage, m_fMusicRate, 1.1f );
+134 -28
View File
@@ -65,7 +65,6 @@
#define SHOW_LIFE_METER_FOR_DISABLED_PLAYERS THEME->GetMetricB(m_sName,"ShowLifeMeterForDisabledPlayers")
#define SHOW_SCORE_IN_RAVE THEME->GetMetricB(m_sName,"ShowScoreInRave")
#define SONG_POSITION_METER_WIDTH THEME->GetMetricF(m_sName,"SongPositionMeterWidth")
#define PLAYER_X( sName, styleType ) THEME->GetMetricF(m_sName,ssprintf("Player%s%sX",sName.c_str(),StyleTypeToString(styleType).c_str()))
#define STOP_COURSE_EARLY THEME->GetMetricB(m_sName,"StopCourseEarly") // evaluate this every time it's used
static ThemeMetric<float> INITIAL_BACKGROUND_BRIGHTNESS ("ScreenGameplay","InitialBackgroundBrightness");
@@ -444,7 +443,14 @@ void ScreenGameplay::Init()
// fill in difficulty of CPU players with that of the first human player
// this should not need to worry about step content.
FOREACH_PotentialCpuPlayer(p)
GAMESTATE->m_pCurSteps[p].Set( GAMESTATE->m_pCurSteps[ GAMESTATE->GetFirstHumanPlayer() ] );
{
PlayerNumber human_pn= GAMESTATE->GetFirstHumanPlayer();
GAMESTATE->m_pCurSteps[p].Set( GAMESTATE->m_pCurSteps[human_pn] );
if(GAMESTATE->GetCurrentGame()->m_PlayersHaveSeparateStyles)
{
GAMESTATE->SetCurrentStyle(GAMESTATE->GetCurrentStyle(human_pn), p);
}
}
FOREACH_EnabledPlayer(p)
ASSERT( GAMESTATE->m_pCurSteps[p].Get() != NULL );
@@ -458,7 +464,14 @@ void ScreenGameplay::Init()
STATSMAN->m_CurStageStats.m_Stage = GAMESTATE->GetCurrentStage();
STATSMAN->m_CurStageStats.m_iStageIndex = GAMESTATE->m_iCurrentStageIndex;
STATSMAN->m_CurStageStats.m_playMode = GAMESTATE->m_PlayMode;
STATSMAN->m_CurStageStats.m_pStyle = GAMESTATE->GetCurrentStyle();
FOREACH_PlayerNumber(pn)
{
STATSMAN->m_CurStageStats.m_player[pn].m_pStyle= GAMESTATE->GetCurrentStyle(pn);
}
FOREACH_MultiPlayer(pn)
{
STATSMAN->m_CurStageStats.m_multiPlayer[pn].m_pStyle= GAMESTATE->GetCurrentStyle(PLAYER_INVALID);
}
/* Record combo rollover. */
FOREACH_EnabledPlayerInfoNotDummy( m_vPlayerInfo, pi )
@@ -501,26 +514,99 @@ void ScreenGameplay::Init()
this->AddChild( &m_Toasty );
}
// Use the margin function to calculate where the notefields should be and
// what size to zoom them to. This way, themes get margins to put cut-ins
// in, and the engine can have players on different styles without the
// notefields overlapping. -Kyz
LuaReference margarine;
float margins[NUM_PLAYERS][2];
FOREACH_PlayerNumber(pn)
{
margins[pn][0]= 40;
margins[pn][1]= 40;
}
THEME->GetMetric(m_sName, "MarginFunction", margarine);
if(margarine.GetLuaType() != LUA_TFUNCTION)
{
LuaHelpers::ReportScriptErrorFmt("MarginFunction metric for %s must be a function.", m_sName.c_str());
}
else
{
Lua* L= LUA->Get();
margarine.PushSelf(L);
lua_createtable(L, 0, 0);
int next_player_slot= 1;
FOREACH_EnabledPlayer(pn)
{
Enum::Push(L, pn);
lua_rawseti(L, -2, next_player_slot);
++next_player_slot;
}
Enum::Push(L, GAMESTATE->GetCurrentStyle(PLAYER_INVALID)->m_StyleType);
RString err= "Error running MarginFunction: ";
if(LuaHelpers::RunScriptOnStack(L, err, 2, 3, true))
{
RString marge= "Margin value must be a number.";
margins[PLAYER_1][0]= SafeFArg(L, -3, marge, 40);
float center= SafeFArg(L, -2, marge, 80);
margins[PLAYER_1][1]= center / 2.0f;
margins[PLAYER_2][0]= center / 2.0f;
margins[PLAYER_2][1]= SafeFArg(L, -1, marge, 40);
}
lua_settop(L, 0);
LUA->Release(L);
}
float left_edge[NUM_PLAYERS]= {0.0f, SCREEN_WIDTH / 2.0f};
FOREACH_EnabledPlayerInfo( m_vPlayerInfo, pi )
{
RString sName = ssprintf("Player%s", pi->GetName().c_str());
pi->m_pPlayer->SetName( sName );
Style const* style= GAMESTATE->GetCurrentStyle(pi->m_pn);
float style_width= style->GetWidth(pi->m_pn);
float edge= left_edge[pi->m_pn];
float screen_space;
float field_space;
float left_marge;
float right_marge;
#define CENTER_PLAYER_BLOCK \
{ \
edge= 0.0f; \
screen_space= SCREEN_WIDTH; \
left_marge= margins[PLAYER_1][0]; \
right_marge= margins[PLAYER_2][1]; \
field_space= screen_space - left_marge - right_marge; \
}
// If pi->m_pn is set, then the player will be visible. If not, then it's not
// visible and don't bother setting its position.
float fPlayerX;
if( GAMESTATE->m_bMultiplayer && !pi->m_bIsDummy )
{
fPlayerX = SCREEN_CENTER_X;
}
if(GAMESTATE->m_bMultiplayer && !pi->m_bIsDummy)
CENTER_PLAYER_BLOCK
else
{
fPlayerX = PLAYER_X( pi->GetName(), GAMESTATE->GetCurrentStyle()->m_StyleType );
if( Center1Player() )
fPlayerX = SCREEN_CENTER_X;
screen_space= SCREEN_WIDTH / 2.0f;
left_marge= margins[pi->m_pn][0];
right_marge= margins[pi->m_pn][1];
field_space= screen_space - left_marge - right_marge;
if(Center1Player() ||
style->m_StyleType == StyleType_TwoPlayersSharedSides ||
(style_width > field_space && GAMESTATE->GetNumPlayersEnabled() == 1
&& (bool)ALLOW_CENTER_1_PLAYER))
CENTER_PLAYER_BLOCK
}
#undef CENTER_PLAYER_BLOCK
float player_x= edge + left_marge + (field_space / 2.0f);
float field_zoom= field_space / style_width;
/*
LuaHelpers::ReportScriptErrorFmt("Positioning player %d at %.0f: "
"screen_space %.0f, left_edge %.0f, field_space %.0f, left_marge %.0f,"
" right_marge %.0f, style_width %.0f, field_zoom %.2f.",
pi->m_pn+1, player_x, screen_space, left_edge[pi->m_pn], field_space,
left_marge, right_marge, style_width, field_zoom);
*/
pi->GetPlayerState()->m_NotefieldZoom= min(1.0f, field_zoom);
pi->m_pPlayer->SetX( fPlayerX );
pi->m_pPlayer->SetX(player_x);
pi->m_pPlayer->RunCommands( PLAYER_INIT_COMMAND );
//ActorUtil::LoadAllCommands(pi->m_pPlayer, m_sName);
this->AddChild( pi->m_pPlayer );
@@ -602,7 +688,7 @@ void ScreenGameplay::Init()
#if !defined(WITHOUT_NETWORKING)
// Only used in SMLAN/SMOnline:
if( !m_bForceNoNetwork && NSMAN->useSMserver && GAMESTATE->GetCurrentStyle()->m_StyleType != StyleType_OnePlayerTwoSides )
if( !m_bForceNoNetwork && NSMAN->useSMserver && GAMESTATE->GetCurrentStyle(PLAYER_INVALID)->m_StyleType != StyleType_OnePlayerTwoSides )
{
m_bShowScoreboard = PREFSMAN->m_bEnableScoreboard.Get();
PlayerNumber pn = GAMESTATE->GetFirstDisabledPlayer();
@@ -825,7 +911,7 @@ bool ScreenGameplay::Center1Player() const
(bool)ALLOW_CENTER_1_PLAYER &&
GAMESTATE->m_PlayMode != PLAY_MODE_BATTLE &&
GAMESTATE->m_PlayMode != PLAY_MODE_RAVE &&
GAMESTATE->GetCurrentStyle()->m_StyleType == StyleType_OnePlayerOneSide;
GAMESTATE->GetCurrentStyle(PLAYER_INVALID)->m_StyleType == StyleType_OnePlayerOneSide;
}
// fill in m_apSongsQueue, m_vpStepsQueue, m_asModifiersQueue
@@ -989,7 +1075,7 @@ void ScreenGameplay::SetupSong( int iSongIndex )
NoteData originalNoteData;
pSteps->GetNoteData( originalNoteData );
const Style* pStyle = GAMESTATE->GetCurrentStyle();
const Style* pStyle = GAMESTATE->GetCurrentStyle(pi->m_pn);
NoteData ndTransformed;
pStyle->GetTransformedNoteDataForStyle( pi->GetStepsAndTrailIndex(), originalNoteData, ndTransformed );
@@ -2050,7 +2136,6 @@ void ScreenGameplay::UpdateLights()
if( m_CabinetLightsNoteData.GetNumTracks() == 0 ) // light data wasn't loaded
return;
const Style* pStyle = GAMESTATE->GetCurrentStyle();
bool bBlinkCabinetLight[NUM_CabinetLight];
bool bBlinkGameButton[NUM_GameController][NUM_GameButton];
ZERO( bBlinkCabinetLight );
@@ -2076,6 +2161,7 @@ void ScreenGameplay::UpdateLights()
FOREACH_EnabledPlayerNumberInfo( m_vPlayerInfo, pi )
{
const Style* pStyle = GAMESTATE->GetCurrentStyle(pi->m_pn);
const NoteData &nd = pi->m_pPlayer->GetNoteData();
for( int t=0; t<nd.GetNumTracks(); t++ )
{
@@ -2095,8 +2181,12 @@ void ScreenGameplay::UpdateLights()
if( bBlink )
{
GameInput gi = pStyle->StyleInputToGameInput( t, pi->m_pn );
bBlinkGameButton[gi.controller][gi.button] = true;
vector<GameInput> gi;
pStyle->StyleInputToGameInput( t, pi->m_pn, gi );
for(size_t i= 0; i < gi.size(); ++i)
{
bBlinkGameButton[gi[i].controller][gi[i].button] = true;
}
}
}
}
@@ -2188,12 +2278,28 @@ void ScreenGameplay::SendCrossedMessages()
iNumTracksWithTapOrHoldHead++;
// send crossed message
const Style *pStyle = GAMESTATE->GetCurrentStyle();
RString sButton = pStyle->ColToButtonName( t );
Message msg( i == 0 ? "NoteCrossed" : "NoteWillCross" );
msg.SetParam( "ButtonName", sButton );
msg.SetParam( "NumMessagesFromCrossed", i );
MESSAGEMAN->Broadcast( msg );
if(GAMESTATE->GetCurrentGame()->m_PlayersHaveSeparateStyles)
{
FOREACH_EnabledPlayerNumberInfo(m_vPlayerInfo, pi)
{
const Style *pStyle = GAMESTATE->GetCurrentStyle(pi->m_pn);
RString sButton = pStyle->ColToButtonName( t );
Message msg( i == 0 ? "NoteCrossed" : "NoteWillCross" );
msg.SetParam( "ButtonName", sButton );
msg.SetParam( "NumMessagesFromCrossed", i );
msg.SetParam("PlayerNumber", pi->m_pn);
MESSAGEMAN->Broadcast( msg );
}
}
else
{
const Style *pStyle = GAMESTATE->GetCurrentStyle(PLAYER_INVALID);
RString sButton = pStyle->ColToButtonName( t );
Message msg( i == 0 ? "NoteCrossed" : "NoteWillCross" );
msg.SetParam( "ButtonName", sButton );
msg.SetParam( "NumMessagesFromCrossed", i );
MESSAGEMAN->Broadcast( msg );
}
}
if( iNumTracksWithTapOrHoldHead > 0 )
@@ -2281,7 +2387,7 @@ bool ScreenGameplay::Input( const InputEventPlus &input )
* If this is also a style button, don't do this; pump center is start.
*/
bool bHoldingGiveUp = false;
if( GAMESTATE->GetCurrentStyle()->GameInputToColumn(input.GameI) == Column_Invalid )
if( GAMESTATE->GetCurrentStyle(input.pn)->GameInputToColumn(input.GameI) == Column_Invalid )
{
bHoldingGiveUp |= ( START_GIVES_UP && input.MenuI == GAME_BUTTON_START );
bHoldingGiveUp |= ( BACK_GIVES_UP && input.MenuI == GAME_BUTTON_BACK );
@@ -2307,7 +2413,7 @@ bool ScreenGameplay::Input( const InputEventPlus &input )
/* Only handle GAME_BUTTON_BACK as a regular BACK button if BACK_GIVES_UP is
* disabled. */
bool bHoldingBack = false;
if( GAMESTATE->GetCurrentStyle()->GameInputToColumn(input.GameI) == Column_Invalid )
if( GAMESTATE->GetCurrentStyle(input.pn)->GameInputToColumn(input.GameI) == Column_Invalid )
{
bHoldingBack |= input.MenuI == GAME_BUTTON_BACK && !BACK_GIVES_UP;
}
@@ -2339,7 +2445,7 @@ bool ScreenGameplay::Input( const InputEventPlus &input )
if( !input.GameI.IsValid() )
return false;
int iCol = GAMESTATE->GetCurrentStyle()->GameInputToColumn( input.GameI );
int iCol = GAMESTATE->GetCurrentStyle(input.pn)->GameInputToColumn( input.GameI );
// Don't pass on any inputs to Player that aren't a press or a release.
switch( input.type )
+1 -1
View File
@@ -15,7 +15,7 @@ ScreenGameplayLesson::ScreenGameplayLesson()
void ScreenGameplayLesson::Init()
{
ASSERT( GAMESTATE->GetCurrentStyle() != NULL );
ASSERT( GAMESTATE->GetCurrentStyle(GAMESTATE->GetMasterPlayerNumber()) != NULL );
ASSERT( GAMESTATE->m_pCurSong != NULL );
/* Now that we've set up, init the base class. */
+2 -2
View File
@@ -18,7 +18,7 @@ void ScreenGameplaySyncMachine::Init()
m_bForceNoNetwork = true;
GAMESTATE->m_PlayMode.Set( PLAY_MODE_REGULAR );
GAMESTATE->SetCurrentStyle( GAMEMAN->GetHowToPlayStyleForGame(GAMESTATE->m_pCurGame) );
GAMESTATE->SetCurrentStyle( GAMEMAN->GetHowToPlayStyleForGame(GAMESTATE->m_pCurGame), PLAYER_INVALID );
AdjustSync::ResetOriginalSyncData();
RString sFile = THEME->GetPathO("ScreenGameplaySyncMachine","music");
@@ -99,7 +99,7 @@ void ScreenGameplaySyncMachine::HandleScreenMessage( const ScreenMessage SM )
GAMESTATE->m_pCurSteps[pn].Set( NULL );
}
GAMESTATE->m_PlayMode.Set( PlayMode_Invalid );
GAMESTATE->SetCurrentStyle( NULL );
GAMESTATE->SetCurrentStyle( NULL, PLAYER_INVALID );
GAMESTATE->m_pCurSong.Set( NULL );
}
}
+2 -2
View File
@@ -124,7 +124,7 @@ void ScreenHowToPlay::Init()
}
}
GAMESTATE->SetCurrentStyle( GAMEMAN->GetHowToPlayStyleForGame(GAMESTATE->m_pCurGame) );
GAMESTATE->SetCurrentStyle( GAMEMAN->GetHowToPlayStyleForGame(GAMESTATE->m_pCurGame), PLAYER_INVALID );
if( USE_PLAYER )
{
@@ -146,7 +146,7 @@ void ScreenHowToPlay::Init()
loaderSM.LoadFromSimfile( sStepsPath, m_Song, false );
m_Song.AddAutoGenNotes();
const Style* pStyle = GAMESTATE->GetCurrentStyle();
const Style* pStyle = GAMESTATE->GetCurrentStyle(PLAYER_INVALID);
Steps *pSteps = SongUtil::GetClosestNotes( &m_Song, pStyle->m_StepsType, Difficulty_Beginner );
if(pSteps == NULL)
+1 -1
View File
@@ -379,7 +379,7 @@ void ScreenInstallOverlay::Update( float fDeltaTime )
GAMESTATE->m_PlayMode.Set( PLAY_MODE_REGULAR );
GAMESTATE->m_bSideIsJoined[0] = true;
GAMESTATE->SetMasterPlayerNumber(PLAYER_1);
GAMESTATE->m_pCurStyle.Set( vpStyle[0] );
GAMESTATE->SetCurrentStyle( vpStyle[0], PLAYER_1 );
GAMESTATE->m_pCurSong.Set( pSong );
GAMESTATE->m_pPreferredSong = pSong;
sInitialScreen = StepMania::GetSelectMusicScreen();
+3 -3
View File
@@ -83,7 +83,7 @@ void ScreenJukebox::SetSong()
continue; // skip
Difficulty dc = vDifficultiesToShow[ RandomInt(vDifficultiesToShow.size()) ];
Steps* pSteps = SongUtil::GetStepsByDifficulty( pSong, GAMESTATE->GetCurrentStyle()->m_StepsType, dc );
Steps* pSteps = SongUtil::GetStepsByDifficulty( pSong, GAMESTATE->GetCurrentStyle(PLAYER_INVALID)->m_StepsType, dc );
if( pSteps == NULL )
continue; // skip
@@ -152,7 +152,7 @@ void ScreenJukebox::SetSong()
GAMESTATE->m_pCurCourse.Set( lCourse );
FOREACH_PlayerNumber( p )
{
GAMESTATE->m_pCurTrail[p].Set( lCourse->GetTrail( GAMESTATE->GetCurrentStyle()->m_StepsType ) );
GAMESTATE->m_pCurTrail[p].Set( lCourse->GetTrail( GAMESTATE->GetCurrentStyle(PLAYER_INVALID)->m_StepsType ) );
ASSERT( GAMESTATE->m_pCurTrail[p] != NULL );
}
}
@@ -174,7 +174,7 @@ static LocalizedString NO_MATCHING_STEPS("ScreenJukebox", "NoMatchingSteps");
void ScreenJukebox::Init()
{
// ScreenJukeboxMenu must set this
ASSERT( GAMESTATE->GetCurrentStyle() != NULL );
ASSERT( GAMESTATE->GetCurrentStyle(PLAYER_INVALID) != NULL );
GAMESTATE->m_PlayMode.Set( PLAY_MODE_REGULAR );
SetSong();
+15 -9
View File
@@ -120,16 +120,16 @@ ScreenNameEntry::ScreenNameEntry()
GAMESTATE->m_bSideIsJoined[PLAYER_2] = true;
GAMESTATE->SetMasterPlayerNumber(PLAYER_1);
GAMESTATE->m_PlayMode.Set( PLAY_MODE_REGULAR );
GAMESTATE->SetCurrentStyle( GAMEMAN->GameAndStringToStyle( GAMEMAN->GetDefaultGame(),"versus") );
GAMESTATE->SetCurrentStyle( GAMEMAN->GameAndStringToStyle( GAMEMAN->GetDefaultGame(),"versus"), PLAYER_INVALID );
StageStats ss;
for( int z = 0; z < 3; ++z )
{
ss.m_vpPlayedSongs.push_back( SONGMAN->GetRandomSong() );
ss.m_vpPossibleSongs = ss.m_vpPlayedSongs;
ss.m_pStyle = GAMESTATE->GetCurrentStyle();
ss.m_player[PLAYER_1].m_pStyle = GAMESTATE->GetCurrentStyle(PLAYER_1);
ss.m_playMode = GAMESTATE->m_PlayMode;
ASSERT( ss.m_vpPlayedSongs[0]->GetAllSteps().size() != 0 );
StepsType st = GAMESTATE->GetCurrentStyle()->m_StepsType;
StepsType st = GAMESTATE->GetCurrentStyle(PLAYER_1)->m_StepsType;
FOREACH_PlayerNumber( p )
{
@@ -247,7 +247,7 @@ void ScreenNameEntry::Init()
ASSERT( GAMESTATE->IsHumanPlayer(p) ); // they better be enabled if they made a high score!
const float fPlayerX = PLAYER_X( p, GAMESTATE->GetCurrentStyle()->m_StyleType );
const float fPlayerX = PLAYER_X( p, GAMESTATE->GetCurrentStyle(p)->m_StyleType );
{
LockNoteSkin l( GAMESTATE->m_pPlayerState[p]->m_PlayerOptions.GetCurrent().m_sNoteSkin );
@@ -258,7 +258,7 @@ void ScreenNameEntry::Init()
this->AddChild( &m_ReceptorArrowRow[p] );
}
const Style* pStyle = GAMESTATE->GetCurrentStyle();
const Style* pStyle = GAMESTATE->GetCurrentStyle(p);
const int iMaxCols = min( int(ABS_MAX_RANKING_NAME_LENGTH), pStyle->m_iColsPerPlayer );
m_ColToStringIndex[p].insert(m_ColToStringIndex[p].begin(), pStyle->m_iColsPerPlayer, -1);
int CurrentStringIndex = 0;
@@ -270,9 +270,15 @@ void ScreenNameEntry::Init()
break; // We have enough columns.
// Find out if this column is associated with the START menu button.
GameInput gi = GAMESTATE->GetCurrentStyle()->StyleInputToGameInput( iCol, p );
GameButton mb = INPUTMAPPER->GameButtonToMenuButton( gi.button );
if( mb == GAME_BUTTON_START )
vector<GameInput> gi;
GAMESTATE->GetCurrentStyle(p)->StyleInputToGameInput( iCol, p, gi );
bool gi_is_start= false;
for(size_t i= 0; i < gi.size(); ++i)
{
gi_is_start|= (INPUTMAPPER->GameButtonToMenuButton(gi[i].button)
== GAME_BUTTON_START);
}
if(gi_is_start)
continue;
m_ColToStringIndex[p][iCol] = CurrentStringIndex++;
@@ -338,7 +344,7 @@ bool ScreenNameEntry::Input( const InputEventPlus &input )
if( input.type != IET_FIRST_PRESS || !input.GameI.IsValid() )
return false; // ignore
const int iCol = GAMESTATE->GetCurrentStyle()->GameInputToColumn( input.GameI );
const int iCol = GAMESTATE->GetCurrentStyle(input.pn)->GameInputToColumn( input.GameI );
bool bHandled = false;
if( iCol != Column_Invalid && m_bStillEnteringName[input.pn] )
{
+3 -3
View File
@@ -24,20 +24,20 @@ void ScreenNameEntryTraditional::Init()
GAMESTATE->m_bSideIsJoined[PLAYER_2] = true;
GAMESTATE->SetMasterPlayerNumber(PLAYER_1);
GAMESTATE->m_PlayMode.Set( PLAY_MODE_REGULAR );
GAMESTATE->SetCurrentStyle( GAMEMAN->GameAndStringToStyle( GAMEMAN->GetDefaultGame(),"versus") );
GAMESTATE->SetCurrentStyle( GAMEMAN->GameAndStringToStyle( GAMEMAN->GetDefaultGame(),"versus"), GAMESTATE->GetMasterPlayerNumber() );
for( int z = 0; z < 3; ++z )
{
StageStats ss;
const vector<Song*> &apSongs = SONGMAN->GetAllSongs();
ss.m_vpPlayedSongs.push_back( apSongs[rand()%apSongs.size()] );
ss.m_vpPossibleSongs = ss.m_vpPlayedSongs;
ss.m_pStyle = GAMESTATE->GetCurrentStyle();
ss.m_playMode = GAMESTATE->m_PlayMode;
ASSERT( ss.m_vpPlayedSongs[0]->GetAllSteps().size() );
StepsType st = GAMESTATE->GetCurrentStyle()->m_StepsType;
FOREACH_PlayerNumber( p )
{
ss.m_player[p].m_pStyle = GAMESTATE->GetCurrentStyle(p);
StepsType st = GAMESTATE->GetCurrentStyle(p)->m_StepsType;
Steps *pSteps = ss.m_vpPlayedSongs[0]->GetAllSteps()[0];
ss.m_player[p].m_iStepsPlayed = 1;
GAMESTATE->m_pCurSteps[p].Set( pSteps );
+1 -1
View File
@@ -209,7 +209,7 @@ void ScreenNetEvaluation::UpdateStats()
m_textPlayerOptions[m_pActivePlayer].SetText( NSMAN->m_EvalPlayerData[m_iCurrentPlayer].playerOptions );
StepsType st = GAMESTATE->GetCurrentStyle()->m_StepsType;
StepsType st = GAMESTATE->GetCurrentStyle(PLAYER_INVALID)->m_StepsType;
Difficulty dc = NSMAN->m_EvalPlayerData[m_iCurrentPlayer].difficulty;
Steps *pSteps = SongUtil::GetOneSteps( GAMESTATE->m_pCurSong, st, dc );
+4 -4
View File
@@ -344,7 +344,7 @@ bool ScreenNetSelectMusic::MenuDown( const InputEventPlus &input )
if( GAMESTATE->m_pCurSong == NULL )
return false;
StepsType st = GAMESTATE->GetCurrentStyle()->m_StepsType;
StepsType st = GAMESTATE->GetCurrentStyle(pn)->m_StepsType;
vector <Steps *> MultiSteps;
MultiSteps = GAMESTATE->m_pCurSong->GetStepsByStepsType( st );
if(MultiSteps.size() == 0)
@@ -449,9 +449,9 @@ void ScreenNetSelectMusic::StartSelectedSong()
{
Song * pSong = m_MusicWheel.GetSelectedSong();
GAMESTATE->m_pCurSong.Set( pSong );
StepsType st = GAMESTATE->GetCurrentStyle()->m_StepsType; //StepsType_dance_single;
FOREACH_EnabledPlayer (pn)
{
StepsType st = GAMESTATE->GetCurrentStyle(pn)->m_StepsType; //StepsType_dance_single;
GAMESTATE->m_PreferredDifficulty[pn].Set( m_DC[pn] );
Steps *pSteps = SongUtil::GetStepsByDifficulty(pSong, st, m_DC[pn]);
GAMESTATE->m_pCurSteps[pn].Set( pSteps );
@@ -476,7 +476,7 @@ void ScreenNetSelectMusic::UpdateDifficulties( PlayerNumber pn )
return;
}
StepsType st = GAMESTATE->GetCurrentStyle()->m_StepsType;
StepsType st = GAMESTATE->GetCurrentStyle(pn)->m_StepsType;
Steps * pSteps = SongUtil::GetStepsByDifficulty( GAMESTATE->m_pCurSong, st, m_DC[pn] );
GAMESTATE->m_pCurSteps[pn].Set( pSteps );
@@ -503,7 +503,7 @@ void ScreenNetSelectMusic::MusicChanged()
FOREACH_EnabledPlayer (pn)
{
m_DC[pn] = GAMESTATE->m_PreferredDifficulty[pn];
StepsType st = GAMESTATE->GetCurrentStyle()->m_StepsType;
StepsType st = GAMESTATE->GetCurrentStyle(pn)->m_StepsType;
vector <Steps *> MultiSteps;
MultiSteps = GAMESTATE->m_pCurSong->GetStepsByStepsType( st );
if(MultiSteps.size() == 0)
+10 -1
View File
@@ -1352,13 +1352,21 @@ public:
static int FocusedItemEndsScreen( T* p, lua_State *L ) { lua_pushboolean( L, p->FocusedItemEndsScreen(Enum::Check<PlayerNumber>(L, 1)) ); return 1; }
static int GetCurrentRowIndex( T* p, lua_State *L ) { lua_pushnumber( L, p->GetCurrentRow(Enum::Check<PlayerNumber>(L, 1)) ); return 1; }
static int GetOptionRow( T* p, lua_State *L ) {
OptionRow* pOptRow = p->GetRow( IArg(1) );
int row_index= IArg(1);
// TODO: Change row indices to be 1-indexed when breaking compatibility
// is allowed. -Kyz
if(row_index < 0 || row_index >= p->GetNumRows())
{
luaL_error(L, "Row index %d is invalid.", row_index);
}
OptionRow* pOptRow = p->GetRow(row_index);
if( pOptRow )
pOptRow->PushSelf(L);
else
lua_pushnil( L );
return 1;
}
DEFINE_METHOD(GetNumRows, GetNumRows());
//static int SetOptionRowFromName( T* p, lua_State *L ) { p->SetOptionRowFromName( SArg(1) ); return 0; }
LunaScreenOptions()
@@ -1367,6 +1375,7 @@ public:
ADD_METHOD( FocusedItemEndsScreen );
ADD_METHOD( GetCurrentRowIndex );
ADD_METHOD( GetOptionRow );
ADD_METHOD( GetNumRows );
//ADD_METHOD( SetOptionRowFromName );
}
};
+1
View File
@@ -98,6 +98,7 @@ protected:
bool AllAreOnLastRow() const;
OptionRow* GetRow( int iRow ) const { return m_pRows[iRow]; }
//void SetOptionRowFromName( const RString& nombre );
int GetNumRows() const { return static_cast<int>(m_pRows.size()); }
protected: // derived classes need access to these
enum Navigation { NAV_THREE_KEY, NAV_THREE_KEY_MENU, NAV_THREE_KEY_ALT, NAV_FIVE_KEY, NAV_TOGGLE_THREE_KEY, NAV_TOGGLE_FIVE_KEY };
+1 -1
View File
@@ -203,7 +203,7 @@ void ScreenOptionsCourseOverview::ProcessMenuStart( const InputEventPlus &input
{
Course *pCourse = GAMESTATE->m_pCurCourse;
random_shuffle( pCourse->m_vEntries.begin(), pCourse->m_vEntries.end() );
Trail *pTrail = pCourse->GetTrailForceRegenCache( GAMESTATE->m_pCurStyle->m_StepsType );
Trail *pTrail = pCourse->GetTrailForceRegenCache( GAMESTATE->GetCurrentStyle(input.pn)->m_StepsType );
GAMESTATE->m_pCurTrail[PLAYER_1].Set( pTrail );
SCREENMAN->PlayStartSound();
MESSAGEMAN->Broadcast("CurrentCourseChanged");
+1 -1
View File
@@ -16,7 +16,7 @@
static void GetStepsForSong( Song *pSong, vector<Steps*> &vpStepsOut )
{
SongUtil::GetSteps( pSong, vpStepsOut, GAMESTATE->GetCurrentStyle()->m_StepsType );
SongUtil::GetSteps( pSong, vpStepsOut, GAMESTATE->GetCurrentStyle(GAMESTATE->GetMasterPlayerNumber())->m_StepsType );
// xxx: If the StepsType isn't valid for the current game, this will cause
// a crash when changing songs. -aj
StepsUtil::RemoveLockedSteps( pSong, vpStepsOut );
+1 -1
View File
@@ -79,7 +79,7 @@ void ScreenOptionsManageCourses::BeginScreen()
vector<const Style*> vpStyles;
GAMEMAN->GetStylesForGame( GAMESTATE->m_pCurGame, vpStyles );
const Style *pStyle = vpStyles[0];
GAMESTATE->SetCurrentStyle( pStyle );
GAMESTATE->SetCurrentStyle( pStyle, PLAYER_INVALID );
if( GAMESTATE->m_stEdit == StepsType_Invalid ||
GAMESTATE->m_cdEdit == Difficulty_Invalid )
+1 -1
View File
@@ -142,7 +142,7 @@ void ScreenOptionsManageEditSteps::HandleScreenMessage( const ScreenMessage SM )
Steps *pSteps = GAMESTATE->m_pCurSteps[PLAYER_1];
ASSERT( pSteps != NULL );
const Style *pStyle = GAMEMAN->GetEditorStyleForStepsType( pSteps->m_StepsType );
GAMESTATE->SetCurrentStyle( pStyle );
GAMESTATE->SetCurrentStyle( pStyle, PLAYER_INVALID );
// do base behavior
}
}
+2 -1
View File
@@ -1,4 +1,5 @@
#include "global.h"
#include "ScreenDimensions.h"
#include "ScreenOptionsManageProfiles.h"
#include "ScreenManager.h"
#include "RageLog.h"
@@ -454,7 +455,7 @@ void ScreenOptionsManageProfiles::ProcessMenuStart( const InputEventPlus & )
int iWidth, iX, iY;
this->GetWidthXY( PLAYER_1, iCurRow, 0, iWidth, iX, iY );
ScreenMiniMenu::MiniMenu( &g_TempMenu, SM_BackFromContextMenu, SM_BackFromContextMenu, (float)iX, (float)iY );
ScreenMiniMenu::MiniMenu( &g_TempMenu, SM_BackFromContextMenu, SM_BackFromContextMenu, (float)iX, SCREEN_CENTER_Y );
}
}
+40
View File
@@ -31,6 +31,46 @@ void ScreenSelect::Init()
this->SubscribeToMessage( Message_PlayerJoined );
// Load choices
// Allow lua as an alternative to metrics.
RString choice_names= CHOICE_NAMES;
if(choice_names.Left(4) == "lua,")
{
RString command= choice_names.Right(choice_names.size()-4);
Lua* L= LUA->Get();
if(LuaHelpers::RunExpression(L, command, m_sName + "::ChoiceNames"))
{
if(!lua_istable(L, 1))
{
LuaHelpers::ReportScriptError(m_sName + "::ChoiceNames expression did not return a table of gamecommands.");
}
else
{
size_t len= lua_objlen(L, 1);
for(size_t i= 1; i <= len; ++i)
{
lua_rawgeti(L, 1, i);
if(!lua_isstring(L, -1))
{
LuaHelpers::ReportScriptErrorFmt(m_sName + "::ChoiceNames element %zu is not a string.", i);
}
else
{
RString com= SArg(-1);
GameCommand mc;
mc.ApplyCommitsScreens(false);
mc.m_sName = ssprintf("%zu", i);
Commands cmd= ParseCommands(com);
mc.Load(i, cmd);
m_aGameCommands.push_back(mc);
}
lua_pop(L, 1);
}
}
}
lua_settop(L, 0);
LUA->Release(L);
}
else
{
// Instead of using NUM_CHOICES, use a comma-separated list of choices.
// Each element in the list is a choice name. This level of indirection
+119 -3
View File
@@ -104,6 +104,68 @@ void ScreenSelectMaster::Init()
FOREACH( PlayerNumber, vpns, p )
m_vsprScroll[*p].resize( m_aGameCommands.size() );
vector<RageVector3> positions;
bool positions_set_by_lua= false;
if(THEME->HasMetric(m_sName, "IconChoicePosFunction"))
{
positions_set_by_lua= true;
LuaReference command= THEME->GetMetricR(m_sName, "IconChoicePosFunction");
if(command.GetLuaType() != LUA_TFUNCTION)
{
LuaHelpers::ReportScriptError(m_sName+"::IconChoicePosFunction must be a function.");
positions_set_by_lua= false;
}
else
{
Lua* L= LUA->Get();
command.PushSelf(L);
lua_pushnumber(L, m_aGameCommands.size());
RString err= m_sName + "::IconChoicePosFunction: ";
if(!LuaHelpers::RunScriptOnStack(L, err, 1, 1, true))
{
positions_set_by_lua= false;
}
else
{
if(!lua_istable(L, -1))
{
LuaHelpers::ReportScriptError(m_sName+"::IconChoicePosFunction did not return a table of positions.");
positions_set_by_lua= false;
}
else
{
size_t poses= lua_objlen(L, -1);
for(size_t p= 1; p <= poses; ++p)
{
lua_rawgeti(L, -1, p);
RageVector3 pos(0.0f, 0.0f, 0.0f);
if(!lua_istable(L, -1))
{
LuaHelpers::ReportScriptErrorFmt("Position %zu is not a table.", p);
}
else
{
#define SET_POS_PART(i, part) \
lua_rawgeti(L, -1, i); \
pos.part= lua_tonumber(L, -1); \
lua_pop(L, 1);
// If part of the position is not provided, we want it to
// default to zero, which lua_tonumber does. -Kyz
SET_POS_PART(1, x);
SET_POS_PART(2, y);
SET_POS_PART(3, z);
#undef SET_POS_PART
}
lua_pop(L, 1);
positions.push_back(pos);
}
}
}
lua_settop(L, 0);
LUA->Release(L);
}
}
for( unsigned c=0; c<m_aGameCommands.size(); c++ )
{
GameCommand& mc = m_aGameCommands[c];
@@ -122,7 +184,26 @@ void ScreenSelectMaster::Init()
RString sName = "Icon" "Choice" + mc.m_sName;
m_vsprIcon[c]->SetName( sName );
if( USE_ICON_METRICS )
LOAD_ALL_COMMANDS_AND_SET_XY( m_vsprIcon[c] );
{
if(positions_set_by_lua)
{
LOAD_ALL_COMMANDS(m_vsprIcon[c]);
m_vsprIcon[c]->SetXY(positions[c].x, positions[c].y);
m_vsprIcon[c]->SetZ(positions[c].z);
}
else
{
LOAD_ALL_COMMANDS_AND_SET_XY( m_vsprIcon[c] );
}
#define OPTIONAL_COMMAND(onoff) \
if(THEME->HasMetric(m_sName, "IconChoice" onoff "Command")) \
{ \
m_vsprIcon[c]->AddCommand(onoff, THEME->GetMetricA(m_sName, "IconChoice" onoff "Command"), false); \
}
OPTIONAL_COMMAND("On");
OPTIONAL_COMMAND("Off");
#undef OPTIONAL_COMMAND
}
this->AddChild( m_vsprIcon[c] );
}
@@ -353,15 +434,50 @@ void ScreenSelectMaster::UpdateSelectableChoices()
{
vector<PlayerNumber> vpns;
GetActiveElementPlayerNumbers( vpns );
int first_playable= -1;
bool on_unplayable[NUM_PLAYERS];
FOREACH_PlayerNumber(pn)
{
on_unplayable[pn]= false;
}
for( unsigned c=0; c<m_aGameCommands.size(); c++ )
{
RString command= "Enabled";
bool disabled= false;
if(!m_aGameCommands[c].IsPlayable())
{
command= "Disabled";
disabled= true;
}
else if(first_playable == -1)
{
first_playable= c;
}
if( SHOW_ICON )
m_vsprIcon[c]->PlayCommand( m_aGameCommands[c].IsPlayable()? "Enabled":"Disabled" );
{
m_vsprIcon[c]->PlayCommand(command);
}
FOREACH( PlayerNumber, vpns, p )
{
if(disabled && m_iChoice[*p] == c)
{
on_unplayable[*p]= true;
}
if( m_vsprScroll[*p][c].IsLoaded() )
m_vsprScroll[*p][c]->PlayCommand( m_aGameCommands[c].IsPlayable()? "Enabled":"Disabled" );
{
m_vsprScroll[*p][c]->PlayCommand(command);
}
}
}
FOREACH(PlayerNumber, vpns, pn)
{
if(on_unplayable[*pn])
{
ChangeSelection(*pn, first_playable < m_iChoice[*pn] ? MenuDir_Left :
MenuDir_Right, first_playable);
}
}
/* If no options are playable at all, just wait. Some external
+15 -34
View File
@@ -43,6 +43,8 @@ const int NUM_SCORE_DIGITS = 9;
#define SHOW_OPTIONS_MESSAGE_SECONDS THEME->GetMetricF( m_sName, "ShowOptionsMessageSeconds" )
static const ThemeMetric<int> HARD_COMMENT_METER("ScreenSelectMusic", "HardCommentMeter");
AutoScreenMessage( SM_AllowOptionsMenuRepeat );
AutoScreenMessage( SM_SongChanged );
AutoScreenMessage( SM_SortOrderChanging );
@@ -66,7 +68,7 @@ void ScreenSelectMusic::Init()
if( PREFSMAN->m_sTestInitialScreen.Get() == m_sName )
{
GAMESTATE->m_PlayMode.Set( PLAY_MODE_REGULAR );
GAMESTATE->SetCurrentStyle( GAMEMAN->GameAndStringToStyle(GAMEMAN->GetDefaultGame(),"versus") );
GAMESTATE->SetCurrentStyle( GAMEMAN->GameAndStringToStyle(GAMEMAN->GetDefaultGame(),"versus"), PLAYER_INVALID );
GAMESTATE->JoinPlayer( PLAYER_1 );
GAMESTATE->SetMasterPlayerNumber(PLAYER_1);
}
@@ -232,20 +234,17 @@ void ScreenSelectMusic::BeginScreen()
if( CommonMetrics::AUTO_SET_STYLE )
{
vector<StepsType> vst;
GAMEMAN->GetStepsTypesForGame( GAMESTATE->m_pCurGame, vst );
const Style *pStyle = GAMEMAN->GetFirstCompatibleStyle( GAMESTATE->m_pCurGame, GAMESTATE->GetNumSidesJoined(), vst[0] );
GAMESTATE->SetCurrentStyle( pStyle );
GAMESTATE->SetCompatibleStylesForPlayers();
}
if( GAMESTATE->GetCurrentStyle() == NULL )
if( GAMESTATE->GetCurrentStyle(PLAYER_INVALID) == NULL )
{
LuaHelpers::ReportScriptError("The Style has not been set. A theme must set the Style before loading ScreenSelectMusic.");
// Instead of crashing, set the first compatible style.
vector<StepsType> vst;
GAMEMAN->GetStepsTypesForGame( GAMESTATE->m_pCurGame, vst );
const Style *pStyle = GAMEMAN->GetFirstCompatibleStyle( GAMESTATE->m_pCurGame, GAMESTATE->GetNumSidesJoined(), vst[0] );
GAMESTATE->SetCurrentStyle( pStyle );
GAMESTATE->SetCurrentStyle( pStyle, PLAYER_INVALID );
}
if( GAMESTATE->m_PlayMode == PlayMode_Invalid )
@@ -1211,7 +1210,7 @@ bool ScreenSelectMusic::MenuStart( const InputEventPlus &input )
bool bIsHard = false;
FOREACH_HumanPlayer( p )
{
if( GAMESTATE->m_pCurSteps[p] && GAMESTATE->m_pCurSteps[p]->GetMeter() >= 10 )
if( GAMESTATE->m_pCurSteps[p] && GAMESTATE->m_pCurSteps[p]->GetMeter() >= HARD_COMMENT_METER )
bIsHard = true;
}
@@ -1434,31 +1433,9 @@ bool ScreenSelectMusic::MenuStart( const InputEventPlus &input )
}
}
if( CommonMetrics::AUTO_SET_STYLE )
{
// Now that Steps have been chosen, set a Style that can play them.
const Style *pStyle = NULL;
if( GAMESTATE->IsCourseMode() )
pStyle = GAMESTATE->m_pCurCourse->GetCourseStyle( GAMESTATE->m_pCurGame, GAMESTATE->GetNumSidesJoined() );
if( pStyle == NULL )
{
StepsType stCurrent;
PlayerNumber pn = GAMESTATE->GetMasterPlayerNumber();
if( GAMESTATE->IsCourseMode() )
{
ASSERT( GAMESTATE->m_pCurTrail[pn] != NULL );
stCurrent = GAMESTATE->m_pCurTrail[pn]->m_StepsType;
}
else
{
ASSERT( GAMESTATE->m_pCurSteps[pn] != NULL );
stCurrent = GAMESTATE->m_pCurSteps[pn]->m_StepsType;
}
vector<StepsType> vst;
pStyle = GAMEMAN->GetFirstCompatibleStyle( GAMESTATE->m_pCurGame, GAMESTATE->GetNumSidesJoined(), stCurrent );
}
GAMESTATE->SetCurrentStyle( pStyle );
}
// Now that Steps have been chosen, set a Style that can play them.
GAMESTATE->SetCompatibleStylesForPlayers();
GAMESTATE->ForceSharedSidesMatch();
/* If we're currently waiting on song assets, abort all except the music
* and start the music, so if we make a choice quickly before background
@@ -1829,6 +1806,10 @@ void ScreenSelectMusic::AfterMusicChange()
}
SongUtil::GetPlayableSteps( pSong, m_vpSteps );
if(m_vpSteps.empty())
{
//LuaHelpers::ReportScriptError("GetPlayableSteps returned nothing.");
}
if ( PREFSMAN->m_bShowBanners )
g_sBannerPath = pSong->GetBannerPath();
@@ -1846,7 +1827,7 @@ void ScreenSelectMusic::AfterMusicChange()
if( CommonMetrics::AUTO_SET_STYLE )
pStyle = pCourse->GetCourseStyle( GAMESTATE->m_pCurGame, GAMESTATE->GetNumSidesJoined() );
if( pStyle == NULL )
pStyle = GAMESTATE->GetCurrentStyle();
pStyle = GAMESTATE->GetCurrentStyle(PLAYER_INVALID);
lCourse->GetTrails( m_vpTrails, pStyle->m_StepsType );
m_sSampleMusicToPlay = m_sCourseMusicPath;
+1 -1
View File
@@ -22,7 +22,7 @@ SnapDisplay::SnapDisplay()
void SnapDisplay::Load()
{
m_iNumCols = GAMESTATE->GetCurrentStyle()->m_iColsPerPlayer;
m_iNumCols = GAMESTATE->GetCurrentStyle(GAMESTATE->GetMasterPlayerNumber())->m_iColsPerPlayer;
m_sprIndicators[0].SetX( -ARROW_SIZE * (m_iNumCols/2 + 0.5f) );
m_sprIndicators[1].SetX( ARROW_SIZE * (m_iNumCols/2 + 0.5f) );
+5 -5
View File
@@ -1167,7 +1167,7 @@ void SongManager::GetCoursesInGroup( vector<Course*> &AddTo, const RString &sCou
AddTo.push_back( m_pCourses[i] );
}
bool SongManager::GetExtraStageInfoFromCourse( bool bExtra2, RString sPreferredGroup, Song*& pSongOut, Steps*& pStepsOut )
bool SongManager::GetExtraStageInfoFromCourse( bool bExtra2, RString sPreferredGroup, Song*& pSongOut, Steps*& pStepsOut, StepsType stype )
{
const RString sCourseSuffix = sPreferredGroup + (bExtra2 ? "/extra2.crs" : "/extra1.crs");
RString sCoursePath = SpecialFiles::SONGS_DIR + sCourseSuffix;
@@ -1184,7 +1184,7 @@ bool SongManager::GetExtraStageInfoFromCourse( bool bExtra2, RString sPreferredG
CourseLoaderCRS::LoadFromCRSFile( sCoursePath, course );
if( course.GetEstimatedNumStages() <= 0 ) return false;
Trail *pTrail = course.GetTrail( GAMESTATE->GetCurrentStyle()->m_StepsType );
Trail *pTrail = course.GetTrail(stype);
if( pTrail->m_vEntries.empty() )
return false;
@@ -1231,11 +1231,11 @@ void SongManager::GetExtraStageInfo( bool bExtra2, const Style *sd, Song*& pSong
GAMESTATE->m_pCurSong? GAMESTATE->m_pCurSong->m_sGroupName.c_str():"") );
// Check preferred group
if( GetExtraStageInfoFromCourse(bExtra2, sGroup, pSongOut, pStepsOut) )
if( GetExtraStageInfoFromCourse(bExtra2, sGroup, pSongOut, pStepsOut, sd->m_StepsType) )
return;
// Optionally, check the Songs folder for extra1/2.crs files.
if( GetExtraStageInfoFromCourse(bExtra2, "", pSongOut, pStepsOut) )
if( GetExtraStageInfoFromCourse(bExtra2, "", pSongOut, pStepsOut, sd->m_StepsType) )
return;
// Choose a hard song for the extra stage
@@ -1894,7 +1894,7 @@ int FindCourseIndexOfSameMode( T begin, T end, const Course *p )
/* If it's not playable in this mode, don't increment. It might result in
* different output in different modes, but that's better than having holes. */
if( !(*it)->IsPlayableIn( GAMESTATE->GetCurrentStyle()->m_StepsType ) )
if( !(*it)->IsPlayableIn( GAMESTATE->GetCurrentStyle(GAMESTATE->GetMasterPlayerNumber())->m_StepsType ) )
continue;
if( (*it)->GetPlayMode() != pm )
continue;
+1 -1
View File
@@ -172,7 +172,7 @@ public:
protected:
void LoadStepManiaSongDir( RString sDir, LoadingWindow *ld );
void LoadDWISongDir( RString sDir );
bool GetExtraStageInfoFromCourse( bool bExtra2, RString sPreferredGroup, Song*& pSongOut, Steps*& pStepsOut );
bool GetExtraStageInfoFromCourse( bool bExtra2, RString sPreferredGroup, Song*& pSongOut, Steps*& pStepsOut, StepsType stype );
void SanityCheckGroupDir( RString sDir ) const;
void AddGroup( RString sDir, RString sGroupDirName );
int GetNumEditsLoadedFromProfile( ProfileSlot slot ) const;
+6 -6
View File
@@ -478,7 +478,7 @@ void SongUtil::SortSongPointerArrayByGrades( vector<Song*> &vpSongsInOut, bool b
int iCounts[NUM_Grade];
const Profile *pProfile = PROFILEMAN->GetMachineProfile();
ASSERT( pProfile != NULL );
pProfile->GetGrades( pSong, GAMESTATE->GetCurrentStyle()->m_StepsType, iCounts );
pProfile->GetGrades( pSong, GAMESTATE->GetCurrentStyle(GAMESTATE->GetMasterPlayerNumber())->m_StepsType, iCounts );
RString foo;
foo.reserve(256);
@@ -632,7 +632,7 @@ RString SongUtil::GetSectionNameFromSongAndSort( const Song* pSong, SortOrder so
case SORT_TOP_GRADES:
{
int iCounts[NUM_Grade];
PROFILEMAN->GetMachineProfile()->GetGrades( pSong, GAMESTATE->GetCurrentStyle()->m_StepsType, iCounts );
PROFILEMAN->GetMachineProfile()->GetGrades( pSong, GAMESTATE->GetCurrentStyle(GAMESTATE->GetMasterPlayerNumber())->m_StepsType, iCounts );
for( int i=Grade_Tier01; i<NUM_Grade; ++i )
{
@@ -932,10 +932,10 @@ void SongUtil::GetPlayableStepsTypes( const Song *pSong, set<StepsType> &vOut )
{
vector<const Style*> vpPossibleStyles;
// If AutoSetStyle, or a Style hasn't been chosen, check StepsTypes for all Styles.
if( CommonMetrics::AUTO_SET_STYLE || GAMESTATE->m_pCurStyle == NULL )
if( CommonMetrics::AUTO_SET_STYLE || GAMESTATE->GetCurrentStyle(PLAYER_INVALID) == NULL )
GAMEMAN->GetCompatibleStyles( GAMESTATE->m_pCurGame, GAMESTATE->GetNumPlayersEnabled(), vpPossibleStyles );
else
vpPossibleStyles.push_back( GAMESTATE->m_pCurStyle );
vpPossibleStyles.push_back( GAMESTATE->GetCurrentStyle(PLAYER_INVALID) );
// Only allow OneSide Styles in Workout
if( GAMESTATE->m_bMultiplayer )
@@ -1048,13 +1048,13 @@ bool SongUtil::GetStepsTypeAndDifficultyFromSortOrder( SortOrder so, StepsType &
case SORT_MEDIUM_METER:
case SORT_HARD_METER:
case SORT_CHALLENGE_METER:
stOut = GAMESTATE->GetCurrentStyle()->m_StepsType;
stOut = GAMESTATE->GetCurrentStyle(GAMESTATE->GetMasterPlayerNumber())->m_StepsType;
break;
case SORT_DOUBLE_EASY_METER:
case SORT_DOUBLE_MEDIUM_METER:
case SORT_DOUBLE_HARD_METER:
case SORT_DOUBLE_CHALLENGE_METER:
stOut = GAMESTATE->GetCurrentStyle()->m_StepsType; // in case we don't find any matches below
stOut = GAMESTATE->GetCurrentStyle(GAMESTATE->GetMasterPlayerNumber())->m_StepsType; // in case we don't find any matches below
vector<const Style*> vpStyles;
GAMEMAN->GetStylesForGame(GAMESTATE->m_pCurGame,vpStyles);
FOREACH_CONST( const Style*, vpStyles, i )
+1 -1
View File
@@ -180,7 +180,7 @@ namespace SongUtil
void GetPlayableSteps( const Song *pSong, vector<Steps*> &vOut );
bool IsStepsTypePlayable( Song *pSong, StepsType st );
bool IsStepsPlayable( Song *pSong, Steps *pSteps );
/**
* @brief Determine if the song has any playable steps in the present game.
* @param s the current song.
+105 -3
View File
@@ -16,6 +16,7 @@
REGISTER_ACTOR_CLASS( Sprite );
const float min_state_delay= 0.0001f;
Sprite::Sprite()
{
@@ -182,12 +183,21 @@ void Sprite::LoadFromNode( const XNode* pNode )
State newState;
if( !pFrame->GetAttrValue("Delay", newState.fDelay) )
{
newState.fDelay = 0.1f;
}
if(newState.fDelay <= min_state_delay)
{
LuaHelpers::ReportScriptErrorFmt("%s: State #%i has near-zero delay.", ActorUtil::GetWhere(pNode).c_str(), i+1);
newState.fDelay= 0.1f;
}
pFrame->GetAttrValue( "Frame", iFrameIndex );
if( iFrameIndex >= m_pTexture->GetNumFrames() )
{
LuaHelpers::ReportScriptErrorFmt( "%s: State #%i is frame %d, but the texture \"%s\" only has %d frames",
ActorUtil::GetWhere(pNode).c_str(), i, iFrameIndex, sPath.c_str(), m_pTexture->GetNumFrames() );
ActorUtil::GetWhere(pNode).c_str(), i+1, iFrameIndex, sPath.c_str(), m_pTexture->GetNumFrames() );
}
newState.rect = *m_pTexture->GetTextureCoordRect( iFrameIndex );
const XNode *pPoints[2] = { pFrame->GetChild( "1" ), pFrame->GetChild( "2" ) };
@@ -352,7 +362,7 @@ void Sprite::UpdateAnimationState()
// We already know what's going to show.
if( m_States.size() > 1 )
{
while( m_fSecsIntoState+0.0001f > m_States[m_iCurState].fDelay ) // it's time to switch frames
while( m_fSecsIntoState+min_state_delay > m_States[m_iCurState].fDelay ) // it's time to switch frames
{
// increment frame and reset the counter
m_fSecsIntoState -= m_States[m_iCurState].fDelay; // leave the left over time for the next frame
@@ -1037,6 +1047,15 @@ void Sprite::AddImageCoords( float fX, float fY )
class LunaSprite: public Luna<Sprite>
{
public:
static float valid_state_delay(lua_State* L, int i)
{
float delay= FArg(i);
if(delay <= min_state_delay)
{
luaL_error(L, "State delay cannot be less than or equal to zero.");
}
return delay;
}
static int Load( T* p, lua_State *L )
{
if( lua_isnil(L, 1) )
@@ -1093,6 +1112,83 @@ public:
static int addimagecoords( T* p, lua_State *L ) { p->AddImageCoords( FArg(1),FArg(2) ); COMMON_RETURN_SELF; }
static int setstate( T* p, lua_State *L ) { p->SetState( IArg(1) ); COMMON_RETURN_SELF; }
static int GetState( T* p, lua_State *L ) { lua_pushnumber( L, p->GetState() ); return 1; }
static int SetStateProperties(T* p, lua_State* L)
{
// States table example:
// {{Frame= 0, Delay= .016, {0, 0}, {.25, .25}}}
// Each element in the States table must have a Frame and a Delay.
// Frame is optional, defaulting to 0.
// Delay is optional, defaulting to 0.
// The two tables in the state are the upper left and lower right and are
// optional.
if(!lua_istable(L, 1))
{
luaL_error(L, "State properties must be in a table.");
}
vector<Sprite::State> new_states;
size_t num_states= lua_objlen(L, 1);
if(num_states == 0)
{
luaL_error(L, "A Sprite cannot have zero states.");
}
for(size_t s= 0; s < num_states; ++s)
{
Sprite::State new_state;
lua_rawgeti(L, 1, s+1);
lua_getfield(L, -1, "Frame");
int frame_index= 0;
if(lua_isnumber(L, -1))
{
frame_index= IArg(-1);
if(frame_index < 0 || frame_index >= p->GetTexture()->GetNumFrames())
{
luaL_error(L, "Frame index out of range 0-%d.",
p->GetTexture()->GetNumFrames()-1);
}
}
new_state.rect= *p->GetTexture()->GetTextureCoordRect(frame_index);
lua_pop(L, 1);
lua_getfield(L, -1, "Delay");
if(lua_isnumber(L, -1))
{
new_state.fDelay= valid_state_delay(L, -1);
}
lua_pop(L, 1);
RectF r= new_state.rect;
lua_rawgeti(L, -1, 1);
if(lua_istable(L, -1))
{
lua_rawgeti(L, -1, 1);
// I have no idea why the points are from 0 to 1 and make it use only
// a portion of the state. This is just copied from LoadFromNode.
// -Kyz
new_state.rect.left= SCALE(FArg(-1), 0.0f, 1.0f, r.left, r.right);
lua_pop(L, 1);
lua_rawgeti(L, -1, 2);
new_state.rect.top= SCALE(FArg(-1), 0.0f, 1.0f, r.top, r.bottom);
lua_pop(L, 1);
}
lua_pop(L, 1);
lua_rawgeti(L, -1, 2);
if(lua_istable(L, -1))
{
lua_rawgeti(L, -1, 1);
// I have no idea why the points are from 0 to 1 and make it use only
// a portion of the state. This is just copied from LoadFromNode.
// -Kyz
new_state.rect.right= SCALE(FArg(-1), 0.0f, 1.0f, r.left, r.right);
lua_pop(L, 1);
lua_rawgeti(L, -1, 2);
new_state.rect.bottom= SCALE(FArg(-1), 0.0f, 1.0f, r.top, r.bottom);
lua_pop(L, 1);
}
lua_pop(L, 1);
new_states.push_back(new_state);
lua_pop(L, 1);
}
p->SetStateProperties(new_states);
COMMON_RETURN_SELF;
}
static int GetAnimationLengthSeconds( T* p, lua_State *L ) { lua_pushnumber( L, p->GetAnimationLengthSeconds() ); return 1; }
static int SetSecondsIntoAnimation( T* p, lua_State *L ) { p->SetSecondsIntoAnimation(FArg(0)); COMMON_RETURN_SELF; }
static int SetTexture( T* p, lua_State *L )
@@ -1118,7 +1214,12 @@ public:
COMMON_RETURN_SELF;
}
static int GetNumStates( T* p, lua_State *L ) { lua_pushnumber( L, p->GetNumStates() ); return 1; }
static int SetAllStateDelays( T* p, lua_State *L ) { p->SetAllStateDelays(FArg(1)); COMMON_RETURN_SELF; }
static int SetAllStateDelays( T* p, lua_State *L )
{
float delay= valid_state_delay(L, -1);
p->SetAllStateDelays(delay);
COMMON_RETURN_SELF;
}
LunaSprite()
{
@@ -1136,6 +1237,7 @@ public:
ADD_METHOD( addimagecoords );
ADD_METHOD( setstate );
ADD_METHOD( GetState );
ADD_METHOD( SetStateProperties );
ADD_METHOD( GetAnimationLengthSeconds );
ADD_METHOD( SetSecondsIntoAnimation );
ADD_METHOD( SetTexture );
+10 -7
View File
@@ -11,6 +11,14 @@ class RageTexture;
class Sprite: public Actor
{
public:
/** @brief The Sprite's present state. */
struct State
{
RectF rect;
/** @brief The number of "seconds to show". */
float fDelay;
};
Sprite();
Sprite( const Sprite &cpy );
virtual ~Sprite();
@@ -48,6 +56,8 @@ public:
int GetState() { return m_iCurState; }
virtual float GetAnimationLengthSeconds() const;
virtual void SetSecondsIntoAnimation( float fSeconds );
void SetStateProperties(const vector<State>& new_states)
{ m_States= new_states; SetState(0); }
RString GetTexturePath() const;
@@ -90,13 +100,6 @@ private:
RageTexture* m_pTexture;
/** @brief The Sprite's present state. */
struct State
{
RectF rect;
/** @brief The number of "seconds to show". */
float fDelay;
};
vector<State> m_States;
int m_iCurState;
/** @brief The number of seconds that have elapsed since we switched to this frame. */
+2 -5
View File
@@ -20,7 +20,6 @@ StageStats::StageStats()
m_playMode = PlayMode_Invalid;
m_Stage = Stage_Invalid;
m_iStageIndex = -1;
m_pStyle = NULL;
m_vpPlayedSongs.clear();
m_vpPossibleSongs.clear();
m_EarnedExtraStage = EarnedExtraStage_No;
@@ -54,7 +53,6 @@ void StageStats::AssertValid( PlayerNumber pn ) const
ASSERT( m_player[pn].m_vpPossibleSteps.size() != 0 );
ASSERT( m_player[pn].m_vpPossibleSteps[0] != NULL );
ASSERT_M( m_playMode < NUM_PlayMode, ssprintf("playmode %i", m_playMode) );
ASSERT( m_pStyle != NULL );
ASSERT_M( m_player[pn].m_vpPossibleSteps[0]->GetDifficulty() < NUM_Difficulty, ssprintf("Invalid Difficulty %i", m_player[pn].m_vpPossibleSteps[0]->GetDifficulty()) );
ASSERT_M( (int) m_vpPlayedSongs.size() == m_player[pn].m_iStepsPlayed, ssprintf("%i Songs Played != %i Steps Played for player %i", (int)m_vpPlayedSongs.size(), (int)m_player[pn].m_iStepsPlayed, pn) );
ASSERT_M( m_vpPossibleSongs.size() == m_player[pn].m_vpPossibleSteps.size(), ssprintf("%i Possible Songs != %i Possible Steps for player %i", (int)m_vpPossibleSongs.size(), (int)m_player[pn].m_vpPossibleSteps.size(), pn) );
@@ -69,7 +67,6 @@ void StageStats::AssertValid( MultiPlayer pn ) const
ASSERT( m_multiPlayer[pn].m_vpPossibleSteps.size() != 0 );
ASSERT( m_multiPlayer[pn].m_vpPossibleSteps[0] != NULL );
ASSERT_M( m_playMode < NUM_PlayMode, ssprintf("playmode %i", m_playMode) );
ASSERT( m_pStyle != NULL );
ASSERT_M( m_player[pn].m_vpPossibleSteps[0]->GetDifficulty() < NUM_Difficulty, ssprintf("difficulty %i", m_player[pn].m_vpPossibleSteps[0]->GetDifficulty()) );
ASSERT( (int) m_vpPlayedSongs.size() == m_player[pn].m_iStepsPlayed );
ASSERT( m_vpPossibleSongs.size() == m_player[pn].m_vpPossibleSteps.size() );
@@ -216,7 +213,7 @@ void StageStats::FinalizeScores( bool bSummary )
FOREACH_HumanPlayer( p )
{
const HighScore &hs = m_player[p].m_HighScore;
StepsType st = GAMESTATE->GetCurrentStyle()->m_StepsType;
StepsType st = GAMESTATE->GetCurrentStyle(p)->m_StepsType;
const Song* pSong = GAMESTATE->m_pCurSong;
const Steps* pSteps = GAMESTATE->m_pCurSteps[p];
@@ -270,7 +267,7 @@ void StageStats::FinalizeScores( bool bSummary )
HighScore &hs = m_player[p].m_HighScore;
Profile* pProfile = PROFILEMAN->GetMachineProfile();
StepsType st = GAMESTATE->GetCurrentStyle()->m_StepsType;
StepsType st = GAMESTATE->GetCurrentStyle(p)->m_StepsType;
const HighScoreList *pHSL = NULL;
if( bSummary )
-1
View File
@@ -37,7 +37,6 @@ public:
Stage m_Stage;
int m_iStageIndex;
PlayMode m_playMode;
const Style* m_pStyle;
vector<Song*> m_vpPlayedSongs;
vector<Song*> m_vpPossibleSongs;
+1 -2
View File
@@ -52,7 +52,6 @@ static StageStats AccumPlayedStageStats( const vector<StageStats>& vss )
if( !vss.empty() )
{
ssreturn.m_pStyle = vss[0].m_pStyle;
ssreturn.m_playMode = vss[0].m_playMode;
}
@@ -111,7 +110,7 @@ void AddPlayerStatsToProfile( Profile *pProfile, const StageStats &ss, PlayerNum
CHECKPOINT;
StyleID sID;
sID.FromStyle( ss.m_pStyle );
sID.FromStyle( ss.m_player[pn].m_pStyle );
ASSERT( (int) ss.m_vpPlayedSongs.size() == ss.m_player[pn].m_iStepsPlayed );
for( int i=0; i<ss.m_player[pn].m_iStepsPlayed; i++ )
+8
View File
@@ -1172,6 +1172,14 @@
RelativePath="CryptHelpers.h"
>
</File>
<File
RelativePath="CubicSpline.cpp"
>
</File>
<File
RelativePath="CubicSpline.h"
>
</File>
<File
RelativePath="DateTime.cpp"
>
+2
View File
@@ -442,6 +442,7 @@ cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)</Command>
<ClCompile Include="ControllerStateDisplay.cpp" />
<ClCompile Include="CreateZip.cpp" />
<ClCompile Include="CryptHelpers.cpp" />
<ClCompile Include="CubicSpline.cpp" />
<ClCompile Include="DateTime.cpp" />
<ClCompile Include="Difficulty.cpp" />
<ClCompile Include="EnumHelper.cpp" />
@@ -1757,6 +1758,7 @@ cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)</Command>
<ClInclude Include="ControllerStateDisplay.h" />
<ClInclude Include="CreateZip.h" />
<ClInclude Include="CryptHelpers.h" />
<ClInclude Include="CubicSpline.h" />
<ClInclude Include="DateTime.h" />
<ClInclude Include="Difficulty.h" />
<ClInclude Include="EnumHelper.h" />

Some files were not shown because too many files have changed in this diff Show More