Files
itgmania212121/stepmania/src/ScreenHowToPlay.cpp
T

332 lines
9.9 KiB
C++
Raw Normal View History

2003-04-05 03:49:03 +00:00
#include "global.h"
#include "ScreenHowToPlay.h"
#include "ThemeManager.h"
#include "GameState.h"
2005-07-03 02:48:38 +00:00
#include "Steps.h"
#include "GameManager.h"
#include "NotesLoaderSM.h"
2004-07-08 00:10:34 +00:00
#include "GameSoundManager.h"
2004-08-19 01:18:11 +00:00
#include "Model.h"
#include "ThemeMetric.h"
#include "PlayerState.h"
2005-01-15 02:01:26 +00:00
#include "Style.h"
2005-07-04 20:52:21 +00:00
#include "PrefsManager.h"
#include "CharacterManager.h"
#include "StatsManager.h"
2007-02-14 09:33:31 +00:00
#include "RageDisplay.h"
#include "SongUtil.h"
2007-02-14 09:33:31 +00:00
#include "Character.h"
#include "LifeMeterBar.h"
2003-04-05 03:49:03 +00:00
2007-02-14 09:33:31 +00:00
static const ThemeMetric<int> NUM_W2S ("ScreenHowToPlay","NumW2s");
static const ThemeMetric<int> NUM_MISSES ("ScreenHowToPlay","NumMisses");
2007-05-29 18:08:11 +00:00
static const ThemeMetric<bool> USE_CHARACTER ("ScreenHowToPlay","UseCharacter");
static const ThemeMetric<bool> USE_PAD ("ScreenHowToPlay","UsePad");
static const ThemeMetric<bool> USE_PLAYER ("ScreenHowToPlay","UsePlayer");
2003-04-05 03:49:03 +00:00
enum Animation
{
ANIM_DANCE_PAD,
ANIM_DANCE_PADS,
ANIM_UP,
ANIM_DOWN,
ANIM_LEFT,
ANIM_RIGHT,
ANIM_JUMPLR,
NUM_ANIMATIONS
};
2006-01-22 01:00:06 +00:00
static const RString anims[NUM_ANIMATIONS] =
{
"DancePad.txt",
"DancePads.txt",
"BeginnerHelper_step-up.bones.txt",
"BeginnerHelper_step-down.bones.txt",
"BeginnerHelper_step-left.bones.txt",
"BeginnerHelper_step-right.bones.txt",
"BeginnerHelper_step-jumplr.bones.txt"
};
2006-01-22 01:00:06 +00:00
static RString GetAnimPath( Animation a )
{
2006-01-22 01:00:06 +00:00
return RString("Characters/") + anims[a];
}
static bool HaveAllCharAnimations()
{
for( int i = ANIM_UP; i < NUM_ANIMATIONS; ++i )
if( !DoesFileExist( GetAnimPath( (Animation) i ) ) )
return false;
return true;
}
2006-01-15 20:46:15 +00:00
REGISTER_SCREEN_CLASS( ScreenHowToPlay );
2006-01-15 19:18:57 +00:00
ScreenHowToPlay::ScreenHowToPlay()
2003-04-05 03:49:03 +00:00
{
m_iW2s = 0;
m_iNumW2s = NUM_W2S;
// initialize these because they might not be used.
m_pLifeMeterBar = NULL;
m_pmCharacter = NULL;
m_pmDancePad = NULL;
}
void ScreenHowToPlay::Init()
{
ScreenAttract::Init();
2007-05-29 18:08:11 +00:00
if( (bool)USE_PAD && DoesFileExist( GetAnimPath(ANIM_DANCE_PAD) ) )
{
m_pmDancePad = new Model;
2004-11-06 23:54:34 +00:00
m_pmDancePad->SetName( "Pad" );
m_pmDancePad->LoadMilkshapeAscii( GetAnimPath(ANIM_DANCE_PAD) );
m_pmDancePad->SetRotationX( 35 );
2007-02-19 09:30:07 +00:00
LOAD_ALL_COMMANDS_AND_SET_XY_AND_ON_COMMAND( m_pmDancePad );
}
2003-09-01 11:21:52 +00:00
// Display random character
vector<Character*> vpCharacters;
CHARMAN->GetCharacters( vpCharacters );
2007-05-29 18:08:11 +00:00
if( (bool)USE_CHARACTER && vpCharacters.size() && HaveAllCharAnimations() )
{
Character* rndchar = CHARMAN->GetRandomCharacter();
2006-01-22 01:00:06 +00:00
RString sModelPath = rndchar->GetModelPath();
2003-10-12 20:00:22 +00:00
if( sModelPath != "" )
{
m_pmCharacter = new Model;
m_pmCharacter->SetName( "Character" );
2003-10-12 20:00:22 +00:00
m_pmCharacter->LoadMilkshapeAscii( rndchar->GetModelPath() );
m_pmCharacter->LoadMilkshapeAsciiBones( "Step-LEFT", GetAnimPath( ANIM_LEFT ) );
m_pmCharacter->LoadMilkshapeAsciiBones( "Step-DOWN", GetAnimPath( ANIM_DOWN ) );
m_pmCharacter->LoadMilkshapeAsciiBones( "Step-UP", GetAnimPath( ANIM_UP ) );
m_pmCharacter->LoadMilkshapeAsciiBones( "Step-RIGHT", GetAnimPath( ANIM_RIGHT ) );
m_pmCharacter->LoadMilkshapeAsciiBones( "Step-JUMPLR", GetAnimPath( ANIM_JUMPLR ) );
2006-01-22 01:00:06 +00:00
RString sRestFile = rndchar->GetRestAnimationPath();
ASSERT( !sRestFile.empty() );
2003-10-12 20:00:22 +00:00
m_pmCharacter->LoadMilkshapeAsciiBones( "rest",rndchar->GetRestAnimationPath() );
m_pmCharacter->SetDefaultAnimation( "rest" );
2007-03-26 02:46:55 +00:00
m_pmCharacter->PlayAnimation( "rest" ); // Stay bouncing after a step has finished animating.
2003-10-12 20:00:22 +00:00
m_pmCharacter->SetRotationX( 40 );
m_pmCharacter->SetCullMode( CULL_NONE ); // many of the models floating around have the vertex order flipped
2007-02-19 09:30:07 +00:00
LOAD_ALL_COMMANDS_AND_SET_XY_AND_ON_COMMAND( m_pmCharacter );
2003-10-12 20:00:22 +00:00
}
}
2008-11-24 06:45:48 +00:00
GAMESTATE->SetCurrentStyle( GameManager::GetHowToPlayStyleForGame(GAMESTATE->m_pCurGame) );
if( USE_PLAYER )
{
m_pLifeMeterBar = new LifeMeterBar;
2004-11-06 23:54:34 +00:00
m_pLifeMeterBar->SetName("LifeMeterBar");
m_pLifeMeterBar->Load( GAMESTATE->m_pPlayerState[PLAYER_1], &STATSMAN->m_CurStageStats.m_player[PLAYER_1] );
2007-02-19 09:30:07 +00:00
LOAD_ALL_COMMANDS_AND_SET_XY_AND_ON_COMMAND( m_pLifeMeterBar );
m_pLifeMeterBar->FillForHowToPlay( NUM_W2S, NUM_MISSES );
2003-04-05 03:49:03 +00:00
2007-02-14 10:09:05 +00:00
SMLoader::LoadFromSMFile( THEME->GetPathO(m_sName, "steps"), m_Song, false );
m_Song.AddAutoGenNotes();
2004-06-28 07:26:00 +00:00
const Style* pStyle = GAMESTATE->GetCurrentStyle();
Steps *pSteps = SongUtil::GetStepsByDescription( &m_Song, pStyle->m_StepsType, "" );
2004-07-12 22:57:37 +00:00
ASSERT_M( pSteps != NULL, ssprintf("%i", pStyle->m_StepsType) );
2004-10-23 17:43:49 +00:00
NoteData tempNoteData;
pSteps->GetNoteData( tempNoteData );
pStyle->GetTransformedNoteDataForStyle( PLAYER_1, tempNoteData, m_NoteData );
GAMESTATE->m_pCurSong.Set( &m_Song );
GAMESTATE->m_bGameplayLeadIn.Set( false );
GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerController = PC_AUTOPLAY;
2003-08-27 08:02:51 +00:00
m_Player->Init(
2005-02-26 05:59:12 +00:00
"Player",
GAMESTATE->m_pPlayerState[PLAYER_1],
NULL,
m_pLifeMeterBar,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL );
m_Player.Load( m_NoteData );
m_Player->SetName( "Player" );
this->AddChild( m_Player );
2007-02-19 09:30:07 +00:00
LOAD_ALL_COMMANDS_AND_SET_XY_AND_ON_COMMAND( m_Player );
// Don't show judgement
PO_GROUP_ASSIGN( GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions, ModsLevel_Stage, m_fBlind, 1.0f );
GAMESTATE->m_MasterPlayerNumber = PLAYER_1;
GAMESTATE->m_bDemonstrationOrJukebox = true;
}
// deferred until after the player, so the notes go under it
if( m_pLifeMeterBar )
this->AddChild( m_pLifeMeterBar );
if( m_pmDancePad )
this->AddChild( m_pmDancePad );
if( m_pmCharacter )
this->AddChild( m_pmCharacter );
2003-08-27 08:02:51 +00:00
2003-04-05 03:49:03 +00:00
m_fFakeSecondsIntoSong = 0;
2003-08-27 08:02:51 +00:00
this->MoveToTail( &m_In );
this->MoveToTail( &m_Out );
2003-04-05 03:49:03 +00:00
}
ScreenHowToPlay::~ScreenHowToPlay()
{
2003-09-12 00:23:54 +00:00
delete m_pLifeMeterBar;
delete m_pmCharacter;
delete m_pmDancePad;
2003-04-05 03:49:03 +00:00
}
void ScreenHowToPlay::Step()
{
2003-09-12 00:39:40 +00:00
#define ST_LEFT 0x01
#define ST_DOWN 0x02
#define ST_UP 0x04
#define ST_RIGHT 0x08
#define ST_JUMPLR (ST_LEFT | ST_RIGHT)
#define ST_JUMPUD (ST_UP | ST_DOWN)
int iStep = 0;
2003-09-12 00:39:40 +00:00
const int iNoteRow = BeatToNoteRowNotRounded( GAMESTATE->m_fSongBeat + 0.6f );
// if we want to miss from here on out, don't process steps.
if( m_iW2s < m_iNumW2s && m_NoteData.IsThereATapAtRow( iNoteRow ) )
{
2003-09-12 00:39:40 +00:00
const int iNumTracks = m_NoteData.GetNumTracks();
for( int k=0; k<iNumTracks; k++ )
if( m_NoteData.GetTapNote(k, iNoteRow).type == TapNote::tap )
2003-09-12 00:39:40 +00:00
iStep |= 1 << k;
switch( iStep )
{
case ST_LEFT: m_pmCharacter->PlayAnimation( "Step-LEFT", 1.8f ); break;
case ST_RIGHT: m_pmCharacter->PlayAnimation( "Step-RIGHT", 1.8f ); break;
2007-02-14 09:33:31 +00:00
case ST_UP: m_pmCharacter->PlayAnimation( "Step-UP", 1.8f ); break;
case ST_DOWN: m_pmCharacter->PlayAnimation( "Step-DOWN", 1.8f ); break;
case ST_JUMPLR: m_pmCharacter->PlayAnimation( "Step-JUMPLR", 1.8f ); break;
case ST_JUMPUD:
// Until I can get an UP+DOWN jump animation, this will have to do.
m_pmCharacter->PlayAnimation( "Step-JUMPLR", 1.8f );
m_pmCharacter->StopTweening();
m_pmCharacter->BeginTweening( GAMESTATE->m_fCurBPS /8, TWEEN_LINEAR );
m_pmCharacter->SetRotationY( 90 );
m_pmCharacter->BeginTweening( (1/(GAMESTATE->m_fCurBPS * 2) ) ); //sleep between jump-frames
m_pmCharacter->BeginTweening( GAMESTATE->m_fCurBPS /6, TWEEN_LINEAR );
m_pmCharacter->SetRotationY( 0 );
break;
}
}
}
2003-04-05 03:49:03 +00:00
void ScreenHowToPlay::Update( float fDelta )
{
2007-02-14 09:33:31 +00:00
if( GAMESTATE->m_pCurSong != NULL )
2003-05-28 03:33:46 +00:00
{
GAMESTATE->UpdateSongPosition( m_fFakeSecondsIntoSong, GAMESTATE->m_pCurSong->m_Timing );
2003-05-28 03:33:46 +00:00
m_fFakeSecondsIntoSong += fDelta;
static int iLastNoteRowCounted = 0;
int iCurNoteRow = BeatToNoteRowNotRounded( GAMESTATE->m_fSongBeat );
2007-02-14 09:33:31 +00:00
if( iCurNoteRow != iLastNoteRowCounted &&m_NoteData.IsThereATapAtRow(iCurNoteRow) )
{
if( m_pLifeMeterBar && !m_Player )
{
if ( m_iW2s < m_iNumW2s )
2007-02-14 09:33:31 +00:00
m_pLifeMeterBar->ChangeLife( TNS_W2 );
else
2007-02-14 09:33:31 +00:00
m_pLifeMeterBar->ChangeLife( TNS_Miss );
}
m_iW2s++;
iLastNoteRowCounted = iCurNoteRow;
}
// once we hit the number of perfects we want, we want to fail.
// switch the controller to HUMAN. since we aren't taking input,
// the steps will always be misses.
2007-02-14 09:33:31 +00:00
if( m_iW2s > m_iNumW2s )
GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerController = PC_HUMAN;
2003-09-01 11:21:52 +00:00
if ( m_pmCharacter )
Step();
2003-05-28 03:33:46 +00:00
}
2003-04-05 03:49:03 +00:00
ScreenAttract::Update( fDelta );
}
void ScreenHowToPlay::HandleScreenMessage( const ScreenMessage SM )
{
2006-02-24 00:20:41 +00:00
if( SM == SM_GainFocus )
{
/* We do this ourself. */
SOUND->HandleSongTimer( false );
2006-02-24 00:20:41 +00:00
}
else if( SM == SM_LoseFocus )
{
SOUND->HandleSongTimer( true );
2006-02-24 00:20:41 +00:00
}
else if( SM == SM_GoToNextScreen )
{
GAMESTATE->Reset();
}
ScreenAttract::HandleScreenMessage( SM );
}
// lua start
#include "LuaBinding.h"
class LunaScreenHowToPlay: public Luna<ScreenHowToPlay>
{
public:
static int GetLifeMeter( T* p, lua_State *L )
{
//PlayerNumber pn = Enum::Check<PlayerNumber>( L, 1 );
p->m_pLifeMeterBar->PushSelf( L );
return 1;
}
LunaScreenHowToPlay()
{
ADD_METHOD( GetLifeMeter );
}
};
LUA_REGISTER_DERIVED_CLASS( ScreenHowToPlay, ScreenAttract )
// lua end
2004-06-08 05:22:33 +00:00
/*
* (c) 2001-2004 Chris Danford, Thad Ward
2004-06-08 05:22:33 +00:00
* 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.
*/