don't hard code a sleep - let a BGAnimation control the transition
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
_fade out normal
|
||||||
@@ -6,7 +6,6 @@ InitialScreen=ScreenCompany
|
|||||||
WindowTitle=StepMania
|
WindowTitle=StepMania
|
||||||
DefaultModifiers=
|
DefaultModifiers=
|
||||||
DefaultCpuModifiers=
|
DefaultCpuModifiers=
|
||||||
JoinPauseSeconds=0.8
|
|
||||||
DifficultiesToShow=beginner,easy,medium,hard,challenge
|
DifficultiesToShow=beginner,easy,medium,hard,challenge
|
||||||
CourseDifficultiesToShow=easy,regular,difficult
|
CourseDifficultiesToShow=easy,regular,difficult
|
||||||
StepsTypesToHide=dance-couple,dance-solo,pump-halfdouble,lights-cabinet
|
StepsTypesToHide=dance-couple,dance-solo,pump-halfdouble,lights-cabinet
|
||||||
@@ -998,7 +997,7 @@ OverlayOffCommand=
|
|||||||
|
|
||||||
[ScreenGameplay]
|
[ScreenGameplay]
|
||||||
Class=ScreenGameplay
|
Class=ScreenGameplay
|
||||||
Fallback=Screen
|
Fallback=ScreenWithMenuElementsBlank
|
||||||
ShowEvaluationOnFail=0
|
ShowEvaluationOnFail=0
|
||||||
StaticBGY=SCREEN_CENTER_Y+0
|
StaticBGY=SCREEN_CENTER_Y+0
|
||||||
StaticBGX=SCREEN_CENTER_X+0
|
StaticBGX=SCREEN_CENTER_X+0
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ ThemeMetric<CString> FIRST_RUN_INITIAL_SCREEN ("Common","FirstRunInitialScreen
|
|||||||
ThemeMetric<CString> DEFAULT_MODIFIERS ("Common","DefaultModifiers" );
|
ThemeMetric<CString> DEFAULT_MODIFIERS ("Common","DefaultModifiers" );
|
||||||
ThemeMetric<CString> DEFAULT_CPU_MODIFIERS ("Common","DefaultCpuModifiers" );
|
ThemeMetric<CString> DEFAULT_CPU_MODIFIERS ("Common","DefaultCpuModifiers" );
|
||||||
ThemeMetric1D<RageColor> PLAYER_COLOR ("Common",PLAYER_COLOR_NAME,NUM_PLAYERS);
|
ThemeMetric1D<RageColor> PLAYER_COLOR ("Common",PLAYER_COLOR_NAME,NUM_PLAYERS);
|
||||||
ThemeMetric<float> JOIN_PAUSE_SECONDS ("Common","JoinPauseSeconds");
|
|
||||||
ThemeMetric<CString> WINDOW_TITLE ("Common","WindowTitle");
|
ThemeMetric<CString> WINDOW_TITLE ("Common","WindowTitle");
|
||||||
ThemeMetric<bool> HOME_EDIT_MODE ("Common","HomeEditMode");
|
ThemeMetric<bool> HOME_EDIT_MODE ("Common","HomeEditMode");
|
||||||
ThemeMetric<int> MAX_COURSE_ENTRIES_BEFORE_VARIOUS ("Common","MaxCourseEntriesBeforeShowVarious");
|
ThemeMetric<int> MAX_COURSE_ENTRIES_BEFORE_VARIOUS ("Common","MaxCourseEntriesBeforeShowVarious");
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ extern ThemeMetric<CString> FIRST_RUN_INITIAL_SCREEN;
|
|||||||
extern ThemeMetric<CString> DEFAULT_MODIFIERS;
|
extern ThemeMetric<CString> DEFAULT_MODIFIERS;
|
||||||
extern ThemeMetric<CString> DEFAULT_CPU_MODIFIERS;
|
extern ThemeMetric<CString> DEFAULT_CPU_MODIFIERS;
|
||||||
extern ThemeMetric1D<RageColor> PLAYER_COLOR;
|
extern ThemeMetric1D<RageColor> PLAYER_COLOR;
|
||||||
extern ThemeMetric<float> JOIN_PAUSE_SECONDS;
|
|
||||||
extern ThemeMetric<CString> WINDOW_TITLE;
|
extern ThemeMetric<CString> WINDOW_TITLE;
|
||||||
extern ThemeMetric<bool> HOME_EDIT_MODE;
|
extern ThemeMetric<bool> HOME_EDIT_MODE;
|
||||||
extern ThemeMetric<int> MAX_COURSE_ENTRIES_BEFORE_VARIOUS;
|
extern ThemeMetric<int> MAX_COURSE_ENTRIES_BEFORE_VARIOUS;
|
||||||
|
|||||||
@@ -16,10 +16,9 @@
|
|||||||
#include "CommonMetrics.h"
|
#include "CommonMetrics.h"
|
||||||
#include "BGAnimation.h"
|
#include "BGAnimation.h"
|
||||||
|
|
||||||
#define NEXT_SCREEN THEME->GetMetric (m_sName,"NextScreen")
|
#define NEXT_SCREEN THEME->GetMetric (m_sName,"NextScreen")
|
||||||
#define START_SCREEN(sScreenName) THEME->GetMetric (sScreenName,"StartScreen")
|
#define START_SCREEN(sScreenName) THEME->GetMetric (sScreenName,"StartScreen")
|
||||||
|
|
||||||
|
|
||||||
REGISTER_SCREEN_CLASS( ScreenAttract );
|
REGISTER_SCREEN_CLASS( ScreenAttract );
|
||||||
ScreenAttract::ScreenAttract( CString sName, bool bResetGameState ) : ScreenWithMenuElements( sName )
|
ScreenAttract::ScreenAttract( CString sName, bool bResetGameState ) : ScreenWithMenuElements( sName )
|
||||||
{
|
{
|
||||||
@@ -49,10 +48,10 @@ void ScreenAttract::Input( const DeviceInput& DeviceI, const InputEventType type
|
|||||||
{
|
{
|
||||||
// LOG->Trace( "ScreenAttract::Input()" );
|
// LOG->Trace( "ScreenAttract::Input()" );
|
||||||
|
|
||||||
AttractInput( DeviceI, type, GameI, MenuI, StyleI, m_In.IsTransitioning() || m_Out.IsTransitioning(), m_sName );
|
AttractInput( DeviceI, type, GameI, MenuI, StyleI, this );
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScreenAttract::AttractInput( const DeviceInput& DeviceI, const InputEventType type, const GameInput &GameI, const MenuInput &MenuI, const StyleInput &StyleI, bool bTransitioning, CString sScreenName )
|
void ScreenAttract::AttractInput( const DeviceInput& DeviceI, const InputEventType type, const GameInput &GameI, const MenuInput &MenuI, const StyleInput &StyleI, ScreenWithMenuElements *pScreen )
|
||||||
{
|
{
|
||||||
if(type != IET_FIRST_PRESS)
|
if(type != IET_FIRST_PRESS)
|
||||||
return; // don't care
|
return; // don't care
|
||||||
@@ -75,14 +74,19 @@ void ScreenAttract::AttractInput( const DeviceInput& DeviceI, const InputEventTy
|
|||||||
// fall through
|
// fall through
|
||||||
case COIN_HOME:
|
case COIN_HOME:
|
||||||
case COIN_FREE:
|
case COIN_FREE:
|
||||||
|
if( pScreen->IsTransitioning() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
LOG->Trace("ScreenAttract::AttractInput: begin fading to START_SCREEN" );
|
||||||
|
|
||||||
SOUND->StopMusic();
|
SOUND->StopMusic();
|
||||||
|
SCREENMAN->SendMessageToTopScreen( SM_StopMusic );
|
||||||
|
|
||||||
/* HandleGlobalInputs() already played the coin sound. Don't play it again. */
|
/* HandleGlobalInputs() already played the coin sound. Don't play it again. */
|
||||||
if( MenuI.button != MENU_BUTTON_COIN )
|
if( MenuI.button != MENU_BUTTON_COIN )
|
||||||
SCREENMAN->PlayCoinSound();
|
SCREENMAN->PlayCoinSound();
|
||||||
SCREENMAN->SendMessageToTopScreen( SM_StopMusic );
|
|
||||||
usleep( (int)(JOIN_PAUSE_SECONDS*1000*1000) ); // do a little pause, like the arcade does
|
pScreen->Cancel( SM_GoToStartScreen );
|
||||||
LOG->Trace("ScreenAttract::AttractInput: go to START_SCREEN" );
|
|
||||||
SCREENMAN->SetNewScreen( START_SCREEN(sScreenName) );
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ASSERT(0);
|
ASSERT(0);
|
||||||
@@ -91,7 +95,7 @@ void ScreenAttract::AttractInput( const DeviceInput& DeviceI, const InputEventTy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( bTransitioning )
|
if( pScreen->IsTransitioning() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if( MenuI.IsValid() )
|
if( MenuI.IsValid() )
|
||||||
@@ -126,14 +130,18 @@ void ScreenAttract::Update( float fDelta )
|
|||||||
|
|
||||||
void ScreenAttract::HandleScreenMessage( const ScreenMessage SM )
|
void ScreenAttract::HandleScreenMessage( const ScreenMessage SM )
|
||||||
{
|
{
|
||||||
switch( SM )
|
if( SM == SM_MenuTimer ||
|
||||||
|
SM == SM_BeginFadingOut )
|
||||||
{
|
{
|
||||||
case SM_MenuTimer:
|
|
||||||
case SM_BeginFadingOut:
|
|
||||||
if( !IsTransitioning() )
|
if( !IsTransitioning() )
|
||||||
StartTransitioning( SM_GoToNextScreen );
|
StartTransitioning( SM_GoToNextScreen );
|
||||||
break;
|
}
|
||||||
case SM_GoToNextScreen:
|
else if( SM == SM_GoToStartScreen )
|
||||||
|
{
|
||||||
|
GoToStartScreen( m_sName );
|
||||||
|
}
|
||||||
|
else if( SM == SM_GoToNextScreen )
|
||||||
|
{
|
||||||
/* Look at the def of the screen we're going to; if it has a music theme element
|
/* Look at the def of the screen we're going to; if it has a music theme element
|
||||||
* and it's the same as the one we're playing now, don't stop. However, if we're
|
* and it's the same as the one we're playing now, don't stop. However, if we're
|
||||||
* going to interrupt it when we fade in, stop the old music before we fade out. */
|
* going to interrupt it when we fade in, stop the old music before we fade out. */
|
||||||
@@ -145,10 +153,14 @@ void ScreenAttract::HandleScreenMessage( const ScreenMessage SM )
|
|||||||
SOUND->PlayMusic( "" ); // stop the music
|
SOUND->PlayMusic( "" ); // stop the music
|
||||||
|
|
||||||
SCREENMAN->SetNewScreen( NEXT_SCREEN );
|
SCREENMAN->SetNewScreen( NEXT_SCREEN );
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScreenAttract::GoToStartScreen( CString sScreenName )
|
||||||
|
{
|
||||||
|
SCREENMAN->SetNewScreen( START_SCREEN(sScreenName) );
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (c) 2003-2004 Chris Danford
|
* (c) 2003-2004 Chris Danford
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include "ScreenWithMenuElements.h"
|
#include "ScreenWithMenuElements.h"
|
||||||
|
|
||||||
|
AutoScreenMessage( SM_GoToStartScreen )
|
||||||
|
|
||||||
class ScreenAttract : public ScreenWithMenuElements
|
class ScreenAttract : public ScreenWithMenuElements
|
||||||
{
|
{
|
||||||
@@ -13,8 +14,10 @@ public:
|
|||||||
virtual void Init();
|
virtual void Init();
|
||||||
virtual ~ScreenAttract();
|
virtual ~ScreenAttract();
|
||||||
|
|
||||||
|
static void AttractInput( const DeviceInput& DeviceI, const InputEventType type, const GameInput &GameI, const MenuInput &MenuI, const StyleInput &StyleI, ScreenWithMenuElements *pScreen );
|
||||||
|
static void GoToStartScreen( CString sScreenName );
|
||||||
|
|
||||||
virtual void Input( const DeviceInput& DeviceI, const InputEventType type, const GameInput &GameI, const MenuInput &MenuI, const StyleInput &StyleI );
|
virtual void Input( const DeviceInput& DeviceI, const InputEventType type, const GameInput &GameI, const MenuInput &MenuI, const StyleInput &StyleI );
|
||||||
static void AttractInput( const DeviceInput& DeviceI, const InputEventType type, const GameInput &GameI, const MenuInput &MenuI, const StyleInput &StyleI, bool bTransitioning, CString sScreenName );
|
|
||||||
virtual void Update( float fDelta );
|
virtual void Update( float fDelta );
|
||||||
virtual void HandleScreenMessage( const ScreenMessage SM );
|
virtual void HandleScreenMessage( const ScreenMessage SM );
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ void ScreenDemonstration::HandleScreenMessage( const ScreenMessage SM )
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScreenGameplay::HandleScreenMessage( SM );
|
ScreenJukebox::HandleScreenMessage( SM );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ AutoScreenMessage( SM_StopHereWeGo )
|
|||||||
static Preference<float> g_fNetStartOffset( Options, "NetworkStartOffset", -3.0 );
|
static Preference<float> g_fNetStartOffset( Options, "NetworkStartOffset", -3.0 );
|
||||||
|
|
||||||
REGISTER_SCREEN_CLASS( ScreenGameplay );
|
REGISTER_SCREEN_CLASS( ScreenGameplay );
|
||||||
ScreenGameplay::ScreenGameplay( CString sName ) : Screen(sName)
|
ScreenGameplay::ScreenGameplay( CString sName ) : ScreenWithMenuElements(sName)
|
||||||
{
|
{
|
||||||
PLAYER_TYPE.Load( sName, "PlayerType" );
|
PLAYER_TYPE.Load( sName, "PlayerType" );
|
||||||
GIVE_UP_TEXT.Load( sName, "GiveUpText" );
|
GIVE_UP_TEXT.Load( sName, "GiveUpText" );
|
||||||
@@ -99,7 +99,7 @@ ScreenGameplay::ScreenGameplay( CString sName ) : Screen(sName)
|
|||||||
|
|
||||||
void ScreenGameplay::Init()
|
void ScreenGameplay::Init()
|
||||||
{
|
{
|
||||||
Screen::Init();
|
ScreenWithMenuElements::Init();
|
||||||
|
|
||||||
/* Pause MEMCARDMAN. If a memory card is remove, we don't want to interrupt the
|
/* Pause MEMCARDMAN. If a memory card is remove, we don't want to interrupt the
|
||||||
* player by making a noise until the game finishes. */
|
* player by making a noise until the game finishes. */
|
||||||
@@ -620,14 +620,6 @@ void ScreenGameplay::Init()
|
|||||||
m_textDebug.SetDrawOrder( DRAW_ORDER_TRANSITIONS-1 ); // just under transitions, over the foreground
|
m_textDebug.SetDrawOrder( DRAW_ORDER_TRANSITIONS-1 ); // just under transitions, over the foreground
|
||||||
this->AddChild( &m_textDebug );
|
this->AddChild( &m_textDebug );
|
||||||
|
|
||||||
m_In.Load( THEME->GetPathB(m_sName,"in") );
|
|
||||||
m_In.SetDrawOrder( DRAW_ORDER_TRANSITIONS );
|
|
||||||
this->AddChild( &m_In );
|
|
||||||
|
|
||||||
m_Cancel.Load( THEME->GetPathB(m_sName,"cancel") );
|
|
||||||
m_Cancel.SetDrawOrder( DRAW_ORDER_TRANSITIONS ); // on top of everything else
|
|
||||||
this->AddChild( &m_Cancel );
|
|
||||||
|
|
||||||
|
|
||||||
if( GAMESTATE->IsExtraStage() || GAMESTATE->IsExtraStage2() ) // only load if we're going to use it
|
if( GAMESTATE->IsExtraStage() || GAMESTATE->IsExtraStage2() ) // only load if we're going to use it
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#ifndef SCREEN_GAMEPLAY_H
|
#ifndef SCREEN_GAMEPLAY_H
|
||||||
#define SCREEN_GAMEPLAY_H
|
#define SCREEN_GAMEPLAY_H
|
||||||
|
|
||||||
#include "Screen.h"
|
#include "ScreenWithMenuElements.h"
|
||||||
#include "Sprite.h"
|
#include "Sprite.h"
|
||||||
#include "Transition.h"
|
#include "Transition.h"
|
||||||
#include "BitmapText.h"
|
#include "BitmapText.h"
|
||||||
@@ -30,7 +30,7 @@ class Inventory;
|
|||||||
AutoScreenMessage( SM_NotesEnded )
|
AutoScreenMessage( SM_NotesEnded )
|
||||||
|
|
||||||
class LyricsLoader;
|
class LyricsLoader;
|
||||||
class ScreenGameplay : public Screen
|
class ScreenGameplay : public ScreenWithMenuElements
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ScreenGameplay( CString sName );
|
ScreenGameplay( CString sName );
|
||||||
@@ -139,8 +139,6 @@ protected:
|
|||||||
Transition m_Toasty; // easter egg
|
Transition m_Toasty; // easter egg
|
||||||
Transition m_Win[NUM_PLAYERS];
|
Transition m_Win[NUM_PLAYERS];
|
||||||
Transition m_Draw;
|
Transition m_Draw;
|
||||||
Transition m_In;
|
|
||||||
Transition m_Cancel;
|
|
||||||
AutoActor m_Overlay;
|
AutoActor m_Overlay;
|
||||||
|
|
||||||
BitmapText m_textSurviveTime; // used in extra stage
|
BitmapText m_textSurviveTime; // used in extra stage
|
||||||
|
|||||||
@@ -23,7 +23,6 @@
|
|||||||
#define SHOW_COURSE_MODIFIERS THEME->GetMetricB("ScreenJukebox","ShowCourseModifiers")
|
#define SHOW_COURSE_MODIFIERS THEME->GetMetricB("ScreenJukebox","ShowCourseModifiers")
|
||||||
static ThemeMetricDifficultiesToShow DIFFICULTIES_TO_SHOW_HERE("ScreenDemonstration","DifficultiesToShow");
|
static ThemeMetricDifficultiesToShow DIFFICULTIES_TO_SHOW_HERE("ScreenDemonstration","DifficultiesToShow");
|
||||||
|
|
||||||
|
|
||||||
REGISTER_SCREEN_CLASS( ScreenJukebox );
|
REGISTER_SCREEN_CLASS( ScreenJukebox );
|
||||||
bool ScreenJukebox::SetSong( bool bDemonstration )
|
bool ScreenJukebox::SetSong( bool bDemonstration )
|
||||||
{
|
{
|
||||||
@@ -126,11 +125,8 @@ void ScreenJukebox::Init()
|
|||||||
{
|
{
|
||||||
/* Note that you also need to make sure you benchmark with the
|
/* Note that you also need to make sure you benchmark with the
|
||||||
* same notes. I use a copy of MaxU with only heavy notes included. */
|
* same notes. I use a copy of MaxU with only heavy notes included. */
|
||||||
FOREACH_PlayerNumber( p )
|
FOREACH_EnabledPlayer( p )
|
||||||
{
|
{
|
||||||
if( !GAMESTATE->IsPlayerEnabled(p) )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Lots and lots of arrows. This might even bias to arrows a little
|
/* Lots and lots of arrows. This might even bias to arrows a little
|
||||||
* too much. */
|
* too much. */
|
||||||
GAMESTATE->m_pPlayerState[p]->m_PlayerOptions = PlayerOptions();
|
GAMESTATE->m_pPlayerState[p]->m_PlayerOptions = PlayerOptions();
|
||||||
@@ -142,11 +138,8 @@ void ScreenJukebox::Init()
|
|||||||
GAMESTATE->m_SongOptions.m_FailType = SongOptions::FAIL_OFF;
|
GAMESTATE->m_SongOptions.m_FailType = SongOptions::FAIL_OFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
FOREACH_PlayerNumber( p )
|
FOREACH_EnabledPlayer( p )
|
||||||
{
|
{
|
||||||
if( !GAMESTATE->IsPlayerEnabled(p) )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Reset the combo, in case ComboContinuesBetweenSongs is enabled. */
|
/* Reset the combo, in case ComboContinuesBetweenSongs is enabled. */
|
||||||
Profile* pProfile = PROFILEMAN->GetProfile(p);
|
Profile* pProfile = PROFILEMAN->GetProfile(p);
|
||||||
if( pProfile )
|
if( pProfile )
|
||||||
@@ -176,13 +169,6 @@ void ScreenJukebox::Init()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_In.Load( THEME->GetPathB("ScreenDemonstration","in") );
|
|
||||||
this->AddChild( &m_In );
|
|
||||||
m_In.StartTransitioning();
|
|
||||||
|
|
||||||
m_Out.Load( THEME->GetPathB("ScreenDemonstration","out") );
|
|
||||||
this->AddChild( &m_Out );
|
|
||||||
|
|
||||||
ClearMessageQueue(); // remove all of the messages set in ScreenGameplay that animate "ready", "here we go", etc.
|
ClearMessageQueue(); // remove all of the messages set in ScreenGameplay that animate "ready", "here we go", etc.
|
||||||
|
|
||||||
GAMESTATE->m_bPastHereWeGo = true;
|
GAMESTATE->m_bPastHereWeGo = true;
|
||||||
@@ -208,7 +194,7 @@ void ScreenJukebox::Input( const DeviceInput& DeviceI, const InputEventType type
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ScreenAttract::AttractInput( DeviceI, type, GameI, MenuI, StyleI, m_Out.IsTransitioning(), m_sName );
|
ScreenAttract::AttractInput( DeviceI, type, GameI, MenuI, StyleI, this );
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScreenJukebox::HandleScreenMessage( const ScreenMessage SM )
|
void ScreenJukebox::HandleScreenMessage( const ScreenMessage SM )
|
||||||
@@ -227,6 +213,10 @@ void ScreenJukebox::HandleScreenMessage( const ScreenMessage SM )
|
|||||||
SCREENMAN->SetNewScreen( "ScreenJukebox" );
|
SCREENMAN->SetNewScreen( "ScreenJukebox" );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else if( SM == SM_GoToStartScreen )
|
||||||
|
{
|
||||||
|
ScreenAttract::GoToStartScreen( m_sName );
|
||||||
|
}
|
||||||
|
|
||||||
ScreenGameplay::HandleScreenMessage( SM );
|
ScreenGameplay::HandleScreenMessage( SM );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,8 +21,6 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool m_bDemonstration;
|
bool m_bDemonstration;
|
||||||
Transition m_In;
|
|
||||||
Transition m_Out;
|
|
||||||
|
|
||||||
virtual void InitSongQueues();
|
virtual void InitSongQueues();
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user