source-engine/game/gamepadui/gamepadui_bonusmaps.cpp
2024-04-13 19:58:55 +03:00

1376 lines
50 KiB
C++

#include "gamepadui_interface.h"
#include "gamepadui_image.h"
#include "gamepadui_util.h"
#include "gamepadui_frame.h"
#include "gamepadui_scrollbar.h"
#include "gamepadui_genericconfirmation.h"
#include "ienginevgui.h"
#include "vgui/ILocalize.h"
#include "vgui/ISurface.h"
#include "vgui/IVGui.h"
#include "vgui_controls/ComboBox.h"
#include "vgui_controls/ImagePanel.h"
#include "vgui_controls/ScrollBar.h"
#include "KeyValues.h"
#include "filesystem.h"
#include "tier0/memdbgon.h"
#if defined ( GAMEPADUI_ENABLE_BONUSMAPS ) // SDK2013 lacks the necessary files to compile this. (Madi)
#define SDK_2013_HACKS MAPBASE
#if SDK_2013_HACKS
struct ChallengeDescription_t
{
int iBest;
int iGold;
int iSilver;
int iBronze;
char szName[64];
char szComment[64];
int iType;
};
struct BonusMapDescription_t
{
char szMapName[128];
char szMapFileName[128];
char szImageName[128];
char szComment[256];
char szFileName[128];
bool bIsFolder;
bool bComplete;
bool bLocked;
CUtlVector<ChallengeDescription_t> m_Challenges;
BonusMapDescription_t *m_pParent;
};
#endif
class GamepadUIBonusButton;
#define GAMEPADUI_BONUS_SCHEME GAMEPADUI_RESOURCE_FOLDER "schemebonusbutton.res"
#define NUM_CHALLENGES 5
ConVar gamepadui_selected_challenge("gamepadui_selected_challenge", "0", FCVAR_ARCHIVE);
const char g_pszMedalNames[4][8] =
{
"none",
"bronze",
"silver",
"gold"
};
void GetChallengeMedals( const ChallengeDescription_t *pChallengeDescription, int &iBest, int &iEarnedMedal, int &iNext, int &iNextMedal )
{
iBest = pChallengeDescription->iBest;
if ( iBest == -1 )
iEarnedMedal = 0;
else if ( iBest <= pChallengeDescription->iGold )
iEarnedMedal = 3;
else if ( iBest <= pChallengeDescription->iSilver )
iEarnedMedal = 2;
else if ( iBest <= pChallengeDescription->iBronze )
iEarnedMedal = 1;
else
iEarnedMedal = 0;
iNext = -1;
switch ( iEarnedMedal )
{
case 0:
iNext = pChallengeDescription->iBronze;
iNextMedal = 1;
break;
case 1:
iNext = pChallengeDescription->iSilver;
iNextMedal = 2;
break;
case 2:
iNext = pChallengeDescription->iGold;
iNextMedal = 3;
break;
case 3:
iNext = -1;
iNextMedal = -1;
break;
}
}
void CycleSelectedChallenge()
{
int nChallenge = Clamp( gamepadui_selected_challenge.GetInt(), 0, NUM_CHALLENGES-1 );
nChallenge = ( nChallenge + 1 ) % NUM_CHALLENGES;
gamepadui_selected_challenge.SetValue( nChallenge );
}
class GamepadUIBonusMapsPanel : public GamepadUIFrame
{
DECLARE_CLASS_SIMPLE( GamepadUIBonusMapsPanel, GamepadUIFrame );
public:
GamepadUIBonusMapsPanel( vgui::Panel *pParent, const char* pPanelName );
void UpdateGradients();
void OnThink() OVERRIDE;
void OnCommand( char const* pCommand ) OVERRIDE;
MESSAGE_FUNC_HANDLE( OnGamepadUIButtonNavigatedTo, "OnGamepadUIButtonNavigatedTo", button );
void BuildMapsList();
void LayoutBonusButtons();
void Paint() OVERRIDE;
void ApplySchemeSettings(vgui::IScheme* pScheme) OVERRIDE;
void OnMouseWheeled( int delta ) OVERRIDE;
#if SDK_2013_HACKS
void ScanBonusMaps();
void ScanBonusMapSubDir( const char *pszDir, BonusMapDescription_t *pParent );
void LoadBonusMapDir( const char *pszDir, BonusMapDescription_t *pParent = NULL, BonusMapDescription_t **ppFolder = NULL );
void LoadBonusMap( const char *pszMapList, BonusMapDescription_t *pParent = NULL );
void ClearBonusMapsList();
int BonusCount();
BonusMapDescription_t *GetBonusData( int iMapIndex );
bool IsValidIndex( int iMapIndex );
BonusMapDescription_t *GetCurrentFolder();
void BackFolder();
void EnterFolder( BonusMapDescription_t *pFolder );
void SetCurrentChallengeObjectives( int iBronze, int iSilver, int iGold );
void SetCurrentChallengeNames( const char *pszFileName, const char *pszMapName, const char *pszChallengeName );
private:
CUtlVector< BonusMapDescription_t > m_BonusFolderHierarchy;
#endif
private:
CUtlVector< GamepadUIBonusButton* > m_pBonusButtons;
CUtlVector< BonusMapDescription_t > m_Bonuses;
int m_nBonusRowSize = 3;
GamepadUIScrollState m_ScrollState;
GamepadUIScrollBar *m_pScrollBar;
GAMEPADUI_PANEL_PROPERTY( float, m_BonusOffsetX, "Bonus.OffsetX", "0", SchemeValueTypes::ProportionalFloat );
GAMEPADUI_PANEL_PROPERTY( float, m_BonusOffsetY, "Bonus.OffsetY", "0", SchemeValueTypes::ProportionalFloat );
GAMEPADUI_PANEL_PROPERTY( float, m_BonusSpacing, "Bonus.Spacing", "0", SchemeValueTypes::ProportionalFloat );
GAMEPADUI_PANEL_PROPERTY( float, m_flBonusFade, "Bonus.Fade", "80", SchemeValueTypes::ProportionalFloat );
GAMEPADUI_PANEL_PROPERTY( float, m_flFooterMedalSize, "FooterMedal.Current.Size", "0", SchemeValueTypes::ProportionalFloat );
GAMEPADUI_PANEL_PROPERTY( float, m_flFooterMedalNextSize, "FooterMedal.Next.Size", "0", SchemeValueTypes::ProportionalFloat );
GAMEPADUI_PANEL_PROPERTY( float, m_flBonusProgressOffsetX, "Bonus.Progress.OffsetX", "384", SchemeValueTypes::ProportionalFloat );
GAMEPADUI_PANEL_PROPERTY( float, m_flBonusProgressOffsetY, "Bonus.Progress.OffsetY", "56", SchemeValueTypes::ProportionalFloat );
GAMEPADUI_PANEL_PROPERTY( float, m_flBonusProgressWidth, "Bonus.Progress.Width", "256", SchemeValueTypes::ProportionalFloat );
GAMEPADUI_PANEL_PROPERTY( float, m_flBonusProgressHeight, "Bonus.Progress.Height", "32", SchemeValueTypes::ProportionalFloat );
GAMEPADUI_PANEL_PROPERTY( Color, m_colProgressBackgroundColor, "Bonus.Progress.Background", "32 32 32 128", SchemeValueTypes::Color );
GAMEPADUI_PANEL_PROPERTY( Color, m_colProgressFillColor, "Bonus.Progress.Fill", "255 192 0 255", SchemeValueTypes::Color );
vgui::HFont m_hDescFont = vgui::INVALID_FONT;
vgui::HFont m_hGoalFont = vgui::INVALID_FONT;
GamepadUIImage m_CachedMedals[2];
char m_szCachedMedalNames[256][2];
bool m_bHasChallenges;
float m_flCompletionPerc;
};
class GamepadUIBonusButton : public GamepadUIButton
{
public:
DECLARE_CLASS_SIMPLE( GamepadUIBonusButton, GamepadUIButton );
GamepadUIBonusButton( vgui::Panel* pParent, vgui::Panel* pActionSignalTarget, const char* pSchemeFile, const char* pCommand, const char* pText, const char* pDescription, const char *pBonusImage )
: BaseClass( pParent, pActionSignalTarget, pSchemeFile, pCommand, pText, pDescription )
, m_Image( pBonusImage )
, m_LockIcon( "gamepadui/lockylock" )
{
bCompleted[0] = false;
bCompleted[1] = false;
bCompleted[2] = false;
}
GamepadUIBonusButton( vgui::Panel* pParent, vgui::Panel* pActionSignalTarget, const char* pSchemeFile, const char* pCommand, const wchar* pText, const wchar* pDescription, const char *pBonusImage )
: BaseClass( pParent, pActionSignalTarget, pSchemeFile, pCommand, pText, pDescription )
, m_Image( pBonusImage )
, m_LockIcon( "gamepadui/lockylock" )
{
bCompleted[0] = false;
bCompleted[1] = false;
bCompleted[2] = false;
}
~GamepadUIBonusButton()
{
if ( s_pLastBonusButton == this )
s_pLastBonusButton = NULL;
}
ButtonState GetCurrentButtonState() OVERRIDE
{
if ( s_pLastBonusButton == this )
return ButtonState::Over;
return BaseClass::GetCurrentButtonState();
}
void Paint() OVERRIDE
{
int x, y, w, t;
GetBounds( x, y, w, t );
PaintButton();
int iAlpha = GetAlpha();
vgui::surface()->DrawSetColor( Color( iAlpha, iAlpha, iAlpha, iAlpha ) );
vgui::surface()->DrawSetTexture( m_Image );
int imgH = ( w * 9 ) / 16;
//vgui::surface()->DrawTexturedRect( 0, 0, w, );
float offset = m_flTextOffsetYAnimationValue[ButtonStates::Out] - m_flTextOffsetY;
if (m_bTGA)
vgui::surface()->DrawTexturedRect( 0, 0, w, ( imgH - offset ) );
else
vgui::surface()->DrawTexturedSubRect( 0, 0, w, w * 100 / 180, 0.0f, 0.0f, 1.0f * ( 180.0f / 256.0f ), ( ( imgH - offset ) / imgH ) * 100.0f / 128.0f );
vgui::surface()->DrawSetTexture( 0 );
if ( !IsEnabled() )
{
vgui::surface()->DrawSetColor( Color( 255, 255, 255, 16 ) );
vgui::surface()->DrawFilledRect( 0, 0, w, w * 100 / 180 );
vgui::surface()->DrawSetColor( m_colLock );
vgui::surface()->DrawSetTexture( m_LockIcon );
int nX = m_flWidth / 2 - m_flLockSize / 2;
int nY = imgH / 2 - m_flLockSize / 2;
vgui::surface()->DrawTexturedRect( nX, nY, nX + m_flLockSize, nY + m_flLockSize );
}
vgui::surface()->DrawSetColor( m_colProgressColor );
vgui::surface()->DrawFilledRect( 0, (w * 100 / 180) - m_flProgressHeight, w * ( IsComplete() ? 1.0f : 0.0f), (w * 100 / 180));
PaintText();
int nChallenge = Clamp( gamepadui_selected_challenge.GetInt(), 0, NUM_CHALLENGES-1 );
if ( m_Medals[ nChallenge ].IsValid() )
{
vgui::surface()->DrawSetColor( Color( iAlpha, iAlpha, iAlpha, iAlpha ) );
vgui::surface()->DrawSetTexture( m_Medals[ nChallenge ] );
vgui::surface()->DrawTexturedRect( m_flMedalOffsetX, m_flMedalOffsetY, m_flMedalOffsetX + m_flMedalSize, m_flMedalOffsetY + m_flMedalSize );
vgui::surface()->DrawSetTexture( 0 );
}
}
void ApplySchemeSettings( vgui::IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
float flX, flY;
if (GamepadUI::GetInstance().GetScreenRatio( flX, flY ))
{
if (flX != 1.0f)
{
// For now, undo the scaling from base class
m_flWidth /= flX;
for (int i = 0; i < ButtonStates::Count; i++)
m_flWidthAnimationValue[i] /= flX;
}
SetSize( m_flWidth, m_flHeight + m_flExtraHeight );
DoAnimations( true );
}
// Use a smaller font if necessary
int nTextSizeX, nTextSizeY;
vgui::surface()->GetTextSize( m_hTextFont, m_strButtonText.String(), nTextSizeX, nTextSizeY );
if ( nTextSizeX >= m_flWidth )
{
m_hTextFont = pScheme->GetFont( "Button.Text.Font.Small", true );
m_hTextFontOver = pScheme->GetFont( "Button.Text.Font.Small.Over", true );
if (m_hTextFontOver == vgui::INVALID_FONT )
m_hTextFontOver = m_hTextFont;
}
}
void NavigateTo() OVERRIDE
{
BaseClass::NavigateTo();
s_pLastBonusButton = this;
}
const BonusMapDescription_t& GetBonusMapDescription() const
{
return m_BonusMapDesc;
}
bool IsComplete() const
{
if ( m_BonusMapDesc.bIsFolder )
return false;
int nChallenge = Clamp( gamepadui_selected_challenge.GetInt(), 0, NUM_CHALLENGES-1 );
return m_BonusMapDesc.bComplete || bCompleted[ nChallenge ];
}
void SetBonusMapDescription( BonusMapDescription_t* pDesc )
{
for ( auto& medal : m_Medals )
medal.Cleanup();
m_BonusMapDesc = *pDesc;
#if SDK_2013_HACKS
if ( m_BonusMapDesc.m_Challenges.Count() == 0 )
#else
if ( !m_BonusMapDesc.m_pChallenges )
#endif
return;
int nNumChallenges = 0;
#if SDK_2013_HACKS
for ( ChallengeDescription_t& challenge : m_BonusMapDesc.m_Challenges )
#else
for ( ChallengeDescription_t& challenge : *m_BonusMapDesc.m_pChallenges )
#endif
{
int iChallengeNum = challenge.iType != -1 ? challenge.iType : nNumChallenges;
int iBest, iEarnedMedal, iNext, iNextMedal;
GetChallengeMedals( &challenge, iBest, iEarnedMedal, iNext, iNextMedal );
bCompleted[ iChallengeNum ] = iNextMedal == -1;
char szBuff[256];
if (iChallengeNum < 10)
Q_snprintf(szBuff, 256, "vgui/medals/medal_0%i_%s", iChallengeNum, g_pszMedalNames[iEarnedMedal]);
else
Q_snprintf(szBuff, 256, "vgui/medals/medal_%i_%s", iChallengeNum, g_pszMedalNames[iEarnedMedal]);
m_Medals[ iChallengeNum ].SetImage( szBuff );
nNumChallenges++;
}
}
void SetTGAImage( const char *pszImage )
{
m_Image.SetTGAImage( pszImage );
m_bTGA = true;
}
static GamepadUIBonusButton* GetLastBonusButton() { return s_pLastBonusButton; }
private:
GamepadUIImage m_Image;
GamepadUIImage m_Medals[NUM_CHALLENGES];
GamepadUIImage m_LockIcon;
bool bCompleted[NUM_CHALLENGES];
bool m_bTGA = false;
static GamepadUIBonusButton *s_pLastBonusButton;
BonusMapDescription_t m_BonusMapDesc = {};
GAMEPADUI_PANEL_PROPERTY( Color, m_colProgressColor, "Button.Background.Progress", "255 0 0 255", SchemeValueTypes::Color );
GAMEPADUI_PANEL_PROPERTY( float, m_flProgressHeight, "Button.Progress.Height", "1", SchemeValueTypes::ProportionalFloat );
GAMEPADUI_PANEL_PROPERTY( float, m_flMedalSize, "Button.Medal.Size", "64", SchemeValueTypes::ProportionalFloat );
GAMEPADUI_PANEL_PROPERTY( float, m_flMedalOffsetX, "Button.Medal.OffsetX", "8", SchemeValueTypes::ProportionalFloat );
GAMEPADUI_PANEL_PROPERTY( float, m_flMedalOffsetY, "Button.Medal.OffsetY", "8", SchemeValueTypes::ProportionalFloat );
GAMEPADUI_PANEL_PROPERTY( float, m_flLockSize, "Button.Lock.Size", "80", SchemeValueTypes::ProportionalFloat );
GAMEPADUI_PANEL_PROPERTY( Color, m_colLock, "Button.Lock", "20 20 20 255", SchemeValueTypes::Color );
};
GamepadUIBonusButton* GamepadUIBonusButton::s_pLastBonusButton = NULL;
GamepadUIBonusMapsPanel::GamepadUIBonusMapsPanel( vgui::Panel *pParent, const char* PanelName ) : BaseClass( pParent, PanelName )
{
vgui::HScheme hScheme = vgui::scheme()->LoadSchemeFromFileEx( GamepadUI::GetInstance().GetSizingVPanel(), GAMEPADUI_DEFAULT_PANEL_SCHEME, "SchemePanel" );
SetScheme( hScheme );
FooterButtonMask buttons = FooterButtons::Back | FooterButtons::Select;
SetFooterButtons( buttons, FooterButtons::Select );
BuildMapsList();
Activate();
UpdateGradients();
m_pScrollBar = new GamepadUIScrollBar(
this, this,
GAMEPADUI_RESOURCE_FOLDER "schemescrollbar.res",
NULL, false );
}
void GamepadUIBonusMapsPanel::UpdateGradients()
{
const float flTime = GamepadUI::GetInstance().GetTime();
GamepadUI::GetInstance().GetGradientHelper()->ResetTargets( flTime );
GamepadUI::GetInstance().GetGradientHelper()->SetTargetGradient( GradientSide::Up, { 1.0f, 1.0f }, flTime );
GamepadUI::GetInstance().GetGradientHelper()->SetTargetGradient( GradientSide::Down, { 1.0f, 0.5f }, flTime );
}
void GamepadUIBonusMapsPanel::OnThink()
{
BaseClass::OnThink();
LayoutBonusButtons();
}
void GamepadUIBonusMapsPanel::ApplySchemeSettings( vgui::IScheme* pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
m_hGoalFont = pScheme->GetFont( "Goal.Font", true );
m_hDescFont = pScheme->GetFont( "BonusDesc.Font", true );
float flX, flY;
if (GamepadUI::GetInstance().GetScreenRatio( flX, flY ))
{
m_BonusOffsetX *= flX;
}
int nX, nY;
GamepadUI::GetInstance().GetSizingPanelOffset( nX, nY );
if (nX > 0)
{
GamepadUI::GetInstance().GetSizingPanelScale( flX, flY );
flX *= 0.5f;
m_BonusOffsetX += ((float)nX) * flX;
m_flBonusFade += ((float)nX) * flX;
}
}
void GamepadUIBonusMapsPanel::OnGamepadUIButtonNavigatedTo( vgui::VPANEL button )
{
// TODO: Scroll
#if 1
GamepadUIBonusButton *pButton = dynamic_cast< GamepadUIBonusButton * >( vgui::ipanel()->GetPanel( button, GetModuleName() ) );
if ( pButton )
{
int nParentW, nParentH;
GetParent()->GetSize( nParentW, nParentH );
int nX, nY;
pButton->GetPos( nX, nY );
if ( nY + m_flFooterButtonsOffsetY + m_nFooterButtonHeight + pButton->GetTall() > nParentH || nY < m_BonusOffsetY )
{
int nRow = ( m_pBonusButtons.Find( pButton ) / m_nBonusRowSize );
if ( nY >= m_BonusOffsetY )
nRow--;
float flScrollProgress = (pButton->m_flHeight + m_BonusSpacing) * ((float)nRow);
m_ScrollState.SetScrollTarget( flScrollProgress, GamepadUI::GetInstance().GetTime() );
}
}
#endif
}
#define MAX_LISTED_BONUS_MAPS 128
void GamepadUIBonusMapsPanel::BuildMapsList()
{
m_pBonusButtons.PurgeAndDeleteElements();
#if SDK_2013_HACKS
ClearBonusMapsList();
ScanBonusMaps();
#else
GamepadUI::GetInstance().GetGameUI()->GetBonusMapsDatabase()->ClearBonusMapsList();
GamepadUI::GetInstance().GetGameUI()->GetBonusMapsDatabase()->ScanBonusMaps();
#endif
#if !SDK_2013_HACKS
char szDisplayPath[_MAX_PATH];
Q_snprintf( szDisplayPath, _MAX_PATH, "%s/", GamepadUI::GetInstance().GetGameUI()->GetBonusMapsDatabase()->GetPath() );
#endif
//bool bIsRoot = !Q_strcmp( GamepadUI::GetInstance().GetGameUI()->GetBonusMapsDatabase()->GetPath(), "." );
//if ( bIsRoot )
GetFrameTitle() = GamepadUIString( "#GameUI_BonusMaps" );
//else
// GetFrameTitle() = GamepadUIString( szDisplayPath );
m_bHasChallenges = false;
#if SDK_2013_HACKS
// add to the list
for ( int iMapIndex = 0; iMapIndex < m_Bonuses.Count() && iMapIndex < MAX_LISTED_BONUS_MAPS; ++iMapIndex)
{
BonusMapDescription_t *pDesc = &m_Bonuses[iMapIndex];
char szImage[MAX_PATH];
bool bTGA = false;
if (pDesc->szImageName[0])
{
if (pDesc->szImageName[0] == '.' && GetCurrentFolder())
V_snprintf( szImage, sizeof( szImage ), "%s%c%s", GetCurrentFolder()->szFileName, CORRECT_PATH_SEPARATOR, pDesc->szImageName );
else
V_strncpy( szImage, pDesc->szImageName, sizeof( szImage ) );
if (!g_pFullFileSystem->FileExists( szImage ))
V_snprintf( szImage, sizeof( szImage ), "vgui/%s", pDesc->szImageName );
const char *pszExt = V_GetFileExtension( szImage );
if (pszExt && V_strncmp( pszExt, "tga", 4 ) == 0)
bTGA = true;
}
else
{
// Look for a nearby image
if (pDesc->bIsFolder)
{
Q_snprintf( szImage, sizeof( szImage ), "%s%cfoldericon", pDesc->szFileName, CORRECT_PATH_SEPARATOR );
}
else
{
if (GetCurrentFolder() != NULL)
{
Q_snprintf( szImage, sizeof( szImage ), "%s%c%s", GetCurrentFolder()->szFileName, CORRECT_PATH_SEPARATOR, pDesc->szFileName );
}
else
{
V_strncpy( szImage, pDesc->szFileName, sizeof( szImage ) );
}
}
V_SetExtension( szImage, ".tga", sizeof( szImage ) );
if (!g_pFullFileSystem->FileExists( szImage ))
{
// Use default
V_strncpy( szImage, "vgui/bonusmaps/icon_bonus_map_default", sizeof( szImage ) );
}
else
bTGA = true;
}
if ( pDesc->m_Challenges.Count() > 0 )
m_bHasChallenges = true;
GamepadUIBonusButton *pChapterButton = new GamepadUIBonusButton(
this, this,
GAMEPADUI_BONUS_SCHEME, "action_map",
pDesc->szMapName, NULL, /*pDesc->szComment*/ szImage);
pChapterButton->SetPriority( iMapIndex );
pChapterButton->SetEnabled( !pDesc->bLocked );
pChapterButton->SetForwardToParent( true );
pChapterButton->SetBonusMapDescription( pDesc );
// Make bonus maps render under everything
pChapterButton->SetZPos( 1 );
if (bTGA)
pChapterButton->SetTGAImage( szImage );
m_pBonusButtons.AddToTail( pChapterButton );
}
#else
int iMapCount = GamepadUI::GetInstance().GetGameUI()->GetBonusMapsDatabase()->BonusCount();
// add to the list
for ( int iMapIndex = 0; iMapIndex < iMapCount && iMapIndex < MAX_LISTED_BONUS_MAPS; ++iMapIndex )
{
BonusMapDescription_t *pDesc = GamepadUI::GetInstance().GetGameUI()->GetBonusMapsDatabase()->GetBonusData( iMapIndex );
char szImage[MAX_PATH];
V_snprintf( szImage, sizeof( szImage ), "vgui/%s", pDesc->szImageName );
if ( pDesc->m_pChallenges )
m_bHasChallenges = true;
GamepadUIBonusButton *pChapterButton = new GamepadUIBonusButton(
this, this,
GAMEPADUI_BONUS_SCHEME, "action_map",
pDesc->szMapName, NULL, /*pDesc->szComment*/ szImage);
pChapterButton->SetPriority( iMapIndex );
pChapterButton->SetEnabled( !pDesc->bLocked );
pChapterButton->SetForwardToParent( true );
pChapterButton->SetBonusMapDescription( pDesc );
m_pBonusButtons.AddToTail( pChapterButton );
m_Bonuses.AddToTail( *pDesc );
}
#endif
if ( m_pBonusButtons.Count() > 0 )
m_pBonusButtons[0]->NavigateTo();
for ( int i = 1; i < m_pBonusButtons.Count(); i++)
{
m_pBonusButtons[i]->SetNavLeft(m_pBonusButtons[i - 1]);
m_pBonusButtons[i - 1]->SetNavRight(m_pBonusButtons[i] );
}
FooterButtonMask buttons = FooterButtons::Back | FooterButtons::Select;
if (m_bHasChallenges)
{
buttons |= FooterButtons::Challenge;
// Get completion percentage
int nNumChallenges = 0;
int nNumComplete = 0;
for ( int i = 0; i < m_pBonusButtons.Count(); i++ )
{
int nChallengeCount = m_pBonusButtons[i]->GetBonusMapDescription().m_Challenges.Count();
if (nChallengeCount <= 0)
continue;
nNumChallenges += (nChallengeCount*3);
if (m_pBonusButtons[i]->GetBonusMapDescription().bComplete)
{
nNumComplete += (nChallengeCount*3);
}
else
{
const CUtlVector<ChallengeDescription_t> &desc = m_pBonusButtons[i]->GetBonusMapDescription().m_Challenges;
for (int c = 0; c < nChallengeCount; c++)
{
if (desc[c].iBest != -1)
{
if (desc[c].iBest <= desc[c].iGold)
nNumComplete += 3;
else if (desc[c].iBest <= desc[c].iSilver)
nNumComplete += 2;
else if (desc[c].iBest <= desc[c].iBronze)
nNumComplete += 1;
}
}
}
}
m_flCompletionPerc = ((float)nNumComplete) / ((float)nNumChallenges);
}
SetFooterButtons( buttons, FooterButtons::Select );
}
void GamepadUIBonusMapsPanel::LayoutBonusButtons()
{
int nParentW, nParentH;
GetParent()->GetSize( nParentW, nParentH );
float flScrollClamp = ((float)m_pBonusButtons[0]->GetTall() + m_BonusSpacing) * Max(1.0f, ceilf(((float)m_pBonusButtons.Count() - m_nBonusRowSize*2) / ((float)m_nBonusRowSize)) );
m_ScrollState.UpdateScrollBounds( 0.0f, flScrollClamp );
if (m_pBonusButtons.Count() > 0)
{
m_pScrollBar->InitScrollBar( &m_ScrollState, nParentW - m_BonusOffsetX - m_BonusSpacing, m_BonusOffsetY );
m_pScrollBar->UpdateScrollBounds( 0.0f, flScrollClamp,
((m_pBonusButtons[0]->GetTall() + m_BonusSpacing) * m_nBonusRowSize*2), nParentH - m_flFooterButtonsOffsetY - m_nFooterButtonHeight - m_BonusOffsetY );
}
int x = m_BonusOffsetX;
int y = m_BonusOffsetY - m_ScrollState.GetScrollProgress();
CUtlVector< CUtlVector< GamepadUIBonusButton* > > pButtonRows;
int j = 0;
for ( int i = 0; i < m_pBonusButtons.Count(); i++ )
{
int size = ( m_pBonusButtons[0]->GetWide() + m_BonusSpacing );
if ( x + size > nParentW - m_BonusOffsetX )
{
j = 0;
x = m_BonusOffsetX;
y += m_pBonusButtons[0]->GetTall() + m_BonusSpacing;
}
int fade = 255;
if ( y < m_BonusOffsetY )
fade = RemapValClamped( m_BonusOffsetY - y, m_flBonusFade, 0, 0, 255 );
else if ( y > ( nParentH - (int)m_flFooterButtonsOffsetY - m_nFooterButtonHeight - (int)m_flBonusFade ) )
fade = RemapValClamped( y - ( nParentH - (int)m_flFooterButtonsOffsetY - m_nFooterButtonHeight - (int)m_flBonusFade ), 0, m_flBonusFade, 255, 0 );
if ( ( m_pBonusButtons[i]->HasFocus() && m_pBonusButtons[i]->IsEnabled() ) && fade != 0 )
fade = 255;
m_pBonusButtons[i]->SetAlpha( fade );
m_pBonusButtons[i]->SetPos( x, y );
m_pBonusButtons[i]->SetVisible( true );
j++;
x += size + m_BonusSpacing;
while (pButtonRows.Size() <= j)
pButtonRows.AddToTail();
pButtonRows[j].AddToTail( m_pBonusButtons[i] );
}
for ( int i = 0; i < pButtonRows.Count(); i++ )
{
for (int j = 1; j < pButtonRows[i].Count(); j++)
{
pButtonRows[i][j]->SetNavUp(pButtonRows[i][j - 1]);
pButtonRows[i][j - 1]->SetNavDown(pButtonRows[i][j]);
}
}
if (pButtonRows.Count() > 1)
m_nBonusRowSize = pButtonRows.Count()-1;
else
m_nBonusRowSize = 1;
m_ScrollState.UpdateScrolling( 2.0f, GamepadUI::GetInstance().GetTime() );
}
void GamepadUIBonusMapsPanel::OnCommand( char const* pCommand )
{
if ( !V_strcmp( pCommand, "action_back" ) )
{
#if SDK_2013_HACKS
bool bIsRoot = GetCurrentFolder() == NULL;
#else
bool bIsRoot = !Q_strcmp( GamepadUI::GetInstance().GetGameUI()->GetBonusMapsDatabase()->GetPath(), "." );
#endif
if ( bIsRoot )
Close();
else
{
#if SDK_2013_HACKS
BackFolder();
#else
GamepadUI::GetInstance().GetGameUI()->GetBonusMapsDatabase()->BackPath();
#endif
BuildMapsList();
}
}
else if ( !V_strcmp( pCommand, "action_challenges" ) )
{
CycleSelectedChallenge();
}
else if ( !V_strcmp( pCommand, "action_map" ) )
{
GamepadUIBonusButton* pButton = GamepadUIBonusButton::GetLastBonusButton();
if ( pButton )
{
int mapIndex = pButton->GetPriority();
#if SDK_2013_HACKS
if ( IsValidIndex( mapIndex ) )
#else
if ( GamepadUI::GetInstance().GetGameUI()->GetBonusMapsDatabase()->IsValidIndex( mapIndex ) )
#endif
{
#if SDK_2013_HACKS
BonusMapDescription_t *pBonusMap = GetBonusData( mapIndex );
#else
BonusMapDescription_t *pBonusMap = GamepadUI::GetInstance().GetGameUI()->GetBonusMapsDatabase()->GetBonusData( mapIndex );
#endif
// Don't do anything with locked items
if ( pBonusMap->bLocked )
return;
#if SDK_2013_HACKS
const char *shortName = pBonusMap->szFileName;
#else
const char *shortName = pBonusMap->szShortName;
#endif
if ( shortName && shortName[ 0 ] )
{
if ( pBonusMap->bIsFolder )
{
#if SDK_2013_HACKS
EnterFolder( pBonusMap );
#else
GamepadUI::GetInstance().GetGameUI()->GetBonusMapsDatabase()->AppendPath( shortName );
#endif
BuildMapsList();
}
else
{
// Load the game, return to top and switch to engine
char sz[ 256 ];
// Set the challenge mode if one is selected
int iChallenge = 0;
GamepadUIBonusButton* pButton = GamepadUIBonusButton::GetLastBonusButton();
if ( pButton )
{
const BonusMapDescription_t& desc = pButton->GetBonusMapDescription();
#if SDK_2013_HACKS
if ( desc.m_Challenges.Count() > 0 )
#else
if ( desc.m_pChallenges )
#endif
{
iChallenge = Clamp( gamepadui_selected_challenge.GetInt(), 0, NUM_CHALLENGES-1 ) + 1;
}
}
// Set commentary
ConVarRef commentary( "commentary" );
commentary.SetValue( 0 );
ConVarRef sv_cheats( "sv_cheats" );
sv_cheats.SetValue( 0 );
if ( iChallenge > 0 )
{
Q_snprintf( sz, sizeof( sz ), "sv_bonus_challenge %i\n", iChallenge );
GamepadUI::GetInstance().GetEngineClient()->ClientCmd_Unrestricted(sz);
#if SDK_2013_HACKS
ChallengeDescription_t *pChallengeDescription = &pBonusMap->m_Challenges[iChallenge - 1];
#else
ChallengeDescription_t *pChallengeDescription = &((*pBonusMap->m_pChallenges)[ iChallenge - 1 ]);
#endif
// Set up medal goals
#if SDK_2013_HACKS
SetCurrentChallengeObjectives( pChallengeDescription->iBronze, pChallengeDescription->iSilver, pChallengeDescription->iGold );
SetCurrentChallengeNames( pBonusMap->szFileName, pBonusMap->szMapName, pChallengeDescription->szName );
#else
GamepadUI::GetInstance().GetGameUI()->GetBonusMapsDatabase()->SetCurrentChallengeObjectives( pChallengeDescription->iBronze, pChallengeDescription->iSilver, pChallengeDescription->iGold );
GamepadUI::GetInstance().GetGameUI()->GetBonusMapsDatabase()->SetCurrentChallengeNames( pBonusMap->szFileName, pBonusMap->szMapName, pChallengeDescription->szName );
#endif
}
if ( pBonusMap->szMapFileName[ 0 ] != '.' )
{
Q_snprintf( sz, sizeof( sz ), "progress_enable\nmap %s\n", pBonusMap->szMapFileName );
}
else
{
#if SDK_2013_HACKS
const char *pchSubDir = Q_strnchr( pBonusMap->szFileName, '/', Q_strlen( pBonusMap->szFileName ) );
#else
const char *pchSubDir = Q_strnchr( GamepadUI::GetInstance().GetGameUI()->GetBonusMapsDatabase()->GetPath(), '/', Q_strlen( GamepadUI::GetInstance().GetGameUI()->GetBonusMapsDatabase()->GetPath() ) );
#endif
if ( pchSubDir )
{
pchSubDir = Q_strnchr( pchSubDir + 1, '/', Q_strlen( pchSubDir ) );
if ( pchSubDir )
{
++pchSubDir;
const char *pchMapFileName = pBonusMap->szMapFileName + 2;
Q_snprintf( sz, sizeof( sz ), "progress_enable\nmap %s/%s\n", pchSubDir, pchMapFileName );
}
}
}
GamepadUI::GetInstance().GetEngineClient()->ClientCmd_Unrestricted( sz );
OnClose();
}
}
}
}
}
else
{
BaseClass::OnCommand( pCommand );
}
}
void GamepadUIBonusMapsPanel::Paint()
{
BaseClass::Paint();
GamepadUIBonusButton* pButton = GamepadUIBonusButton::GetLastBonusButton();
if ( !pButton )
return;
const BonusMapDescription_t& desc = pButton->GetBonusMapDescription();
// Draw description
if (desc.szComment[0])
{
int nParentW, nParentH;
GetParent()->GetSize( nParentW, nParentH );
float flX = m_flFooterButtonsOffsetX + m_nFooterButtonWidth + m_flFooterButtonsSpacing;
float flY = nParentH - m_flFooterButtonsOffsetY - m_nFooterButtonHeight;
int nMaxWidth = 0;
if (desc.m_Challenges.Count() > 0)
{
flY += m_flFooterMedalSize + m_flFooterButtonsSpacing;
/*
flX += m_flFooterMedalSize + (m_flFooterButtonsSpacing*4) + m_flFooterDescMedalSpace;
#ifdef STEAM_INPUT
const bool bController = GamepadUI::GetInstance().GetSteamInput()->IsEnabled();
#elif defined(HL2_RETAIL) // Steam input and Steam Controller are not supported in SDK2013 (Madi)
const bool bController = g_pInputSystem->IsSteamControllerActive();
#else
const bool bController = (g_pInputSystem->GetJoystickCount() >= 1);
#endif
if (bController)
{
// Need extra room for the extra button
nMaxWidth -= m_nFooterButtonWidth + m_flFooterButtonsSpacing;
}
*/
}
vgui::surface()->DrawSetTextColor( Color( 255, 255, 255, 255 ) );
vgui::surface()->DrawSetTextFont( m_hDescFont );
vgui::surface()->DrawSetTextPos( flX, flY );
nMaxWidth += nParentW - flX - (m_flFooterButtonsOffsetX + m_nFooterButtonWidth + m_flFooterButtonsSpacing);
GamepadUIString strComment( desc.szComment );
DrawPrintWrappedText( m_hDescFont, flX, flY, strComment.String(), strComment.Length(), nMaxWidth, true);
}
#if SDK_2013_HACKS
if (desc.m_Challenges.Count() == 0)
#else
if ( !desc.m_pChallenges )
#endif
return;
// Draw progress bar
if (m_bHasChallenges)
{
float w = m_flBonusProgressOffsetX + m_flBonusProgressWidth;
float h = m_flBonusProgressOffsetY + m_flBonusProgressHeight;
vgui::surface()->DrawSetColor( m_colProgressBackgroundColor );
vgui::surface()->DrawFilledRect( m_flBonusProgressOffsetX, m_flBonusProgressOffsetY, w, h );
Color colFill = m_colProgressFillColor;
for (int i = 0; i < 3; i++)
colFill[i] *= m_flCompletionPerc;
vgui::surface()->DrawSetColor( colFill );
vgui::surface()->DrawFilledRect( m_flBonusProgressOffsetX, m_flBonusProgressOffsetY, m_flBonusProgressOffsetX + (m_flBonusProgressWidth * m_flCompletionPerc), h );
vgui::surface()->DrawSetColor( Color( 255, 255, 255, 255 ) );
vgui::surface()->DrawOutlinedRect( m_flBonusProgressOffsetX, m_flBonusProgressOffsetY, w, h );
// Text
wchar_t szWideBuff[64];
V_snwprintf( szWideBuff, sizeof( szWideBuff ), L"%i%% %ls", (int)(100.0f * m_flCompletionPerc), g_pVGuiLocalize->Find( "#GameUI_BonusMapsCompletion" ) );
int nTextW, nTextH;
vgui::surface()->GetTextSize( m_hGoalFont, szWideBuff, nTextW, nTextH );
vgui::surface()->DrawSetTextColor( Color( 255, 255, 255, 255 ) );
vgui::surface()->DrawSetTextFont( m_hGoalFont );
vgui::surface()->DrawSetTextPos( m_flBonusProgressOffsetX + (m_flBonusProgressWidth/2) - (nTextW/2), m_flBonusProgressOffsetY + (m_flBonusProgressHeight/2) - (nTextH/2) );
vgui::surface()->DrawPrintText( szWideBuff, V_wcslen( szWideBuff ) );
}
int nCurrentChallenge = Clamp(gamepadui_selected_challenge.GetInt(), 0, NUM_CHALLENGES-1);
int nNumChallenges = 0;
#if SDK_2013_HACKS
for (const ChallengeDescription_t& challenge : desc.m_Challenges)
#else
for (ChallengeDescription_t& challenge : *desc.m_pChallenges)
#endif
{
int iChallengeNum = challenge.iType != -1 ? challenge.iType : nNumChallenges;
if ( iChallengeNum == nCurrentChallenge )
{
int iBest, iEarnedMedal, iNext, iNextMedal;
GetChallengeMedals( &challenge, iBest, iEarnedMedal, iNext, iNextMedal );
int nParentW, nParentH;
GetParent()->GetSize( nParentW, nParentH );
char szBuff[256];
if ( iEarnedMedal != -1 )
{
if (iChallengeNum < 10)
Q_snprintf(szBuff, 256, "vgui/medals/medal_0%i_%s", iChallengeNum, g_pszMedalNames[iEarnedMedal]);
else
Q_snprintf(szBuff, 256, "vgui/medals/medal_%i_%s", iChallengeNum, g_pszMedalNames[iEarnedMedal]);
if ( V_strcmp( m_szCachedMedalNames[0], szBuff))
{
m_CachedMedals[ 0 ].SetImage( szBuff );
V_strcpy( m_szCachedMedalNames[0], szBuff);
}
}
else
{
m_CachedMedals[0].Cleanup();
V_strcpy(m_szCachedMedalNames[0], "");
}
if ( iNextMedal != -1 )
{
if (iChallengeNum < 10)
Q_snprintf(szBuff, 256, "vgui/medals/medal_0%i_%s", iChallengeNum, g_pszMedalNames[iNextMedal]);
else
Q_snprintf(szBuff, 256, "vgui/medals/medal_%i_%s", iChallengeNum, g_pszMedalNames[iNextMedal]);
if ( V_strcmp( m_szCachedMedalNames[1], szBuff))
{
m_CachedMedals[ 1 ].SetImage( szBuff );
V_strcpy( m_szCachedMedalNames[1], szBuff);
}
}
else
{
m_CachedMedals[1].Cleanup();
V_strcpy(m_szCachedMedalNames[1], "");
}
float flX = m_flFooterButtonsOffsetX + m_nFooterButtonWidth + m_flFooterButtonsSpacing;
float flY = nParentH - m_flFooterButtonsOffsetY - m_nFooterButtonHeight;
// Josh: I should clean this later...
int iBestWide = 0;
int iBestTall = 0;
if (iBest != -1)
{
char szBuff[256];
wchar_t szWideBuff[256];
wchar_t szWideBuff2[256];
#ifdef MAPBASE
// Negative ints are used for hacks related to upwards goals
if (iBest < 0)
iBest = -iBest;
#endif
Q_snprintf(szBuff, sizeof(szBuff), "%i", iBest);
g_pVGuiLocalize->ConvertANSIToUnicode(szBuff, szWideBuff2, sizeof(szWideBuff2));
g_pVGuiLocalize->ConstructString(szWideBuff, sizeof(szWideBuff), g_pVGuiLocalize->Find("#GameUI_BonusMapsBest"), 1, szWideBuff2);
if ( m_CachedMedals[0].IsValid() )
{
vgui::surface()->DrawSetTexture( m_CachedMedals[ 0 ] );
vgui::surface()->DrawSetColor( Color( 255, 255, 255, 255 ) );
vgui::surface()->DrawTexturedRect( flX, flY, flX + m_flFooterMedalSize, flY + m_flFooterMedalSize );
}
vgui::surface()->DrawSetTextColor(Color(255, 255, 255, 255));
vgui::surface()->DrawSetTextFont( m_hGoalFont );
vgui::surface()->DrawSetTextPos( flX + m_flFooterMedalSize + m_flFooterButtonsSpacing, flY );
vgui::surface()->GetTextSize( m_hGoalFont, szWideBuff, iBestWide, iBestTall);
vgui::surface()->DrawPrintText( szWideBuff, V_wcslen(szWideBuff) );
}
int iNextWide = 0;
int iNextTall = 0;
if (iNext != -1)
{
char szBuff[256];
wchar_t szWideBuff[256];
wchar_t szWideBuff2[256];
#ifdef MAPBASE
// Negative ints are used for hacks related to upwards goals
if (iNext < 0)
iNext = -iNext;
#endif
Q_snprintf(szBuff, sizeof(szBuff), "%i", iNext);
g_pVGuiLocalize->ConvertANSIToUnicode(szBuff, szWideBuff2, sizeof(szWideBuff2));
g_pVGuiLocalize->ConstructString(szWideBuff, sizeof(szWideBuff), g_pVGuiLocalize->Find("#GameUI_BonusMapsGoal"), 1, szWideBuff2);
vgui::surface()->DrawSetTextColor(Color(255, 255, 255, 255));
vgui::surface()->DrawSetTextFont( m_hGoalFont );
vgui::surface()->DrawSetTextPos( flX + m_flFooterMedalSize + m_flFooterButtonsSpacing, flY + iBestTall );
vgui::surface()->GetTextSize( m_hGoalFont, szWideBuff, iNextWide, iNextTall);
vgui::surface()->DrawPrintText( szWideBuff, V_wcslen(szWideBuff) );
if ( m_CachedMedals[1].IsValid() )
{
vgui::surface()->DrawSetTexture( m_CachedMedals[ 1 ] );
vgui::surface()->DrawSetColor( Color( 255, 255, 255, 255 ) );
float flX2 = flX + m_flFooterMedalSize + Max(iNextWide, iBestWide) + 2 * m_flFooterButtonsSpacing;
float flY2 = flY + iBestTall;
vgui::surface()->DrawTexturedRect( flX2, flY2, flX2 + m_flFooterMedalNextSize, flY2 + m_flFooterMedalNextSize);
}
}
return;
}
nNumChallenges++;
}
}
void GamepadUIBonusMapsPanel::OnMouseWheeled( int nDelta )
{
m_ScrollState.OnMouseWheeled( nDelta * m_BonusSpacing * 20.0f, GamepadUI::GetInstance().GetTime() );
}
#if SDK_2013_HACKS
void GamepadUIBonusMapsPanel::ScanBonusMaps()
{
if (GetCurrentFolder() == NULL)
{
// Load bonus maps from the bonus maps manifest
KeyValues *pBonusMapsManifest = new KeyValues( "BonusMapsManifest" );
if (pBonusMapsManifest->LoadFromFile( g_pFullFileSystem, "scripts/bonus_maps_manifest.txt" ))
{
for (KeyValues *pSubKey = pBonusMapsManifest->GetFirstSubKey(); pSubKey != NULL; pSubKey = pSubKey->GetNextKey())
{
if (Q_stricmp( pSubKey->GetName(), "dir" ) == 0)
{
LoadBonusMapDir( pSubKey->GetString() );
}
else if (Q_stricmp( pSubKey->GetName(), "search" ) == 0)
{
char szSearch[MAX_PATH];
Q_snprintf( szSearch, sizeof( szSearch ), "%s/*", pSubKey->GetString() );
FileFindHandle_t dirHandle;
const char *pszFileName = g_pFullFileSystem->FindFirst( szSearch, &dirHandle );
while (pszFileName)
{
if (g_pFullFileSystem->FindIsDirectory( dirHandle ))
{
char szBonusDir[MAX_PATH];
Q_snprintf( szBonusDir, sizeof( szBonusDir ), "%s/%s", pSubKey->GetString(), pszFileName );
LoadBonusMapDir( szBonusDir );
}
else if (Q_stricmp( Q_GetFileExtension( pszFileName ), "bns" ) == 0)
{
char szBonusDir[MAX_PATH];
Q_snprintf( szBonusDir, sizeof( szBonusDir ), "%s/%s", pSubKey->GetString(), pszFileName );
LoadBonusMap( szBonusDir );
}
pszFileName = g_pFullFileSystem->FindNext( dirHandle );
}
g_pFullFileSystem->FindClose( dirHandle );
}
}
}
pBonusMapsManifest->deleteThis();
}
else
{
// Just look in the folder's directory
ScanBonusMapSubDir( GetCurrentFolder()->szFileName, GetCurrentFolder() );
}
// Load save data and modify each entry accordingly
KeyValues *pBonusSaveData = new KeyValues( "BonusSaveData" );
if (pBonusSaveData->LoadFromFile( g_pFullFileSystem, "save/bonus_maps_data.bmd" ))
{
KeyValues *pBonusFiles = pBonusSaveData->FindKey( "bonusfiles" );
if (pBonusFiles)
{
for (KeyValues *pSubKey = pBonusFiles->GetFirstSubKey(); pSubKey != NULL; pSubKey = pSubKey->GetNextKey())
{
// Look for each map and modify data based on what's saved
for (KeyValues *pMap = pSubKey->GetFirstSubKey(); pMap != NULL; pMap = pMap->GetNextKey())
{
for ( int iMapIndex = 0; iMapIndex < m_Bonuses.Count() && iMapIndex < MAX_LISTED_BONUS_MAPS; ++iMapIndex)
{
BonusMapDescription_t *pDesc = &m_Bonuses[iMapIndex];
if (Q_strcmp( pDesc->szMapName, pMap->GetName() ) != 0)
continue;
pDesc->bLocked = pMap->GetBool( "lock" );
pDesc->bComplete = pMap->GetBool( "complete" );
for (int iChallenge = 0; iChallenge < pDesc->m_Challenges.Count(); iChallenge++)
{
pDesc->m_Challenges[iChallenge].iBest = pMap->GetInt( pDesc->m_Challenges[iChallenge].szName, -1 );
}
break;
}
}
}
}
}
pBonusSaveData->deleteThis();
}
void GamepadUIBonusMapsPanel::ScanBonusMapSubDir( const char *pszDir, BonusMapDescription_t *pParent )
{
char szSearch[MAX_PATH];
Q_snprintf( szSearch, sizeof( szSearch ), "%s/*", pszDir );
FileFindHandle_t dirHandle;
const char *pszFileName = g_pFullFileSystem->FindFirst( szSearch, &dirHandle );
while (pszFileName)
{
if (g_pFullFileSystem->FindIsDirectory( dirHandle ))
{
if (pszFileName[0] != '.')
{
char szBonusDir[MAX_PATH];
Q_snprintf( szBonusDir, sizeof( szBonusDir ), "%s/%s", pszDir, pszFileName );
//BonusMapDescription_t *pFolder = NULL;
LoadBonusMapDir( szBonusDir, pParent/*, &pFolder*/ );
//ScanBonusMapSubDir( szBonusDir, pFolder );
}
}
else if (Q_strcmp( Q_GetFileExtension( pszFileName ), "bns" ) == 0 && !Q_strstr(pszFileName, "folderinfo"))
{
char szBonusDir[MAX_PATH];
Q_snprintf( szBonusDir, sizeof( szBonusDir ), "%s/%s", pszDir, pszFileName );
LoadBonusMap( szBonusDir, pParent );
}
pszFileName = g_pFullFileSystem->FindNext( dirHandle );
}
g_pFullFileSystem->FindClose( dirHandle );
}
void GamepadUIBonusMapsPanel::LoadBonusMapDir( const char *pszDir, BonusMapDescription_t *pParent, BonusMapDescription_t **ppFolder )
{
char szFolderName[MAX_PATH];
Q_FileBase( pszDir, szFolderName, sizeof( szFolderName ) );
char szFolderInfo[MAX_PATH];
//char szMapList[MAX_PATH];
Q_snprintf( szFolderInfo, sizeof( szFolderInfo ), "%s/folderinfo.bns", pszDir );
//Q_snprintf( szMapList, sizeof( szMapList ), "%s/%s.bns", pszDir, szFolderName );
KeyValues *pFolderInfoKV = new KeyValues( "FolderInfo" );
if (!pFolderInfoKV->LoadFromFile( g_pFullFileSystem, szFolderInfo ))
{
pFolderInfoKV->deleteThis();
return;
}
int iFolder = m_Bonuses.AddToTail();
m_Bonuses[iFolder].bIsFolder = true;
m_Bonuses[iFolder].bComplete = false;
m_Bonuses[iFolder].bLocked = pFolderInfoKV->GetBool( "lock" );
Q_strncpy( m_Bonuses[iFolder].szMapName, pFolderInfoKV->GetName(), sizeof( m_Bonuses[iFolder].szMapName ) );
Q_strncpy( m_Bonuses[iFolder].szImageName, pFolderInfoKV->GetString( "image" ), sizeof( m_Bonuses[iFolder].szImageName ) );
Q_strncpy( m_Bonuses[iFolder].szComment, pFolderInfoKV->GetString( "comment" ), sizeof( m_Bonuses[iFolder].szComment ) );
Q_strncpy( m_Bonuses[iFolder].szFileName, pszDir, sizeof( m_Bonuses[iFolder].szFileName ) );
m_Bonuses[iFolder].m_pParent = pParent;
pFolderInfoKV->deleteThis();
//LoadBonusMap( szMapList, &m_Bonuses[iFolder] );
if (ppFolder)
{
*ppFolder = &m_Bonuses[iFolder];
}
}
void GamepadUIBonusMapsPanel::LoadBonusMap( const char *pszMapList, BonusMapDescription_t *pParent )
{
KeyValues *pMapListKV = new KeyValues( "MapList" );
if (!pMapListKV->LoadFromFile( g_pFullFileSystem, pszMapList ))
{
pMapListKV->deleteThis();
return;
}
for (KeyValues *pSubKey = pMapListKV; pSubKey != NULL; pSubKey = pSubKey->GetNextKey())
{
int i = m_Bonuses.AddToTail();
m_Bonuses[i].bIsFolder = false;
m_Bonuses[i].bComplete = false;
m_Bonuses[i].bLocked = pSubKey->GetBool( "lock" );
Q_strncpy( m_Bonuses[i].szMapName, pSubKey->GetName(), sizeof( m_Bonuses[i].szMapName ) );
Q_strncpy( m_Bonuses[i].szMapFileName, pSubKey->GetString( "map" ), sizeof( m_Bonuses[i].szMapFileName ) );
Q_strncpy( m_Bonuses[i].szImageName, pSubKey->GetString( "image" ), sizeof( m_Bonuses[i].szImageName ) );
Q_strncpy( m_Bonuses[i].szComment, pSubKey->GetString( "comment" ), sizeof( m_Bonuses[i].szComment ) );
Q_strncpy( m_Bonuses[i].szFileName, pszMapList, sizeof( m_Bonuses[i].szFileName ) );
m_Bonuses[i].m_pParent = pParent;
if (KeyValues *pChallenges = pSubKey->FindKey( "challenges" ))
{
for (KeyValues *pChallenge = pChallenges->GetFirstSubKey(); pChallenge != NULL; pChallenge = pChallenge->GetNextKey())
{
int i2 = m_Bonuses[i].m_Challenges.AddToTail();
Q_strncpy( m_Bonuses[i].m_Challenges[i2].szName, pChallenge->GetName(), sizeof( m_Bonuses[i].m_Challenges[i2].szName ) );
Q_strncpy( m_Bonuses[i].m_Challenges[i2].szComment, pChallenge->GetString("comment"), sizeof(m_Bonuses[i].m_Challenges[i2].szComment));
m_Bonuses[i].m_Challenges[i2].iType = pChallenge->GetInt("type");
m_Bonuses[i].m_Challenges[i2].iBronze = pChallenge->GetInt("bronze");
m_Bonuses[i].m_Challenges[i2].iSilver = pChallenge->GetInt("silver");
m_Bonuses[i].m_Challenges[i2].iGold = pChallenge->GetInt("gold");
}
}
}
pMapListKV->deleteThis();
}
void GamepadUIBonusMapsPanel::ClearBonusMapsList()
{
m_Bonuses.Purge();
m_ScrollState.SetScrollTarget( 0, 0 );
}
inline int GamepadUIBonusMapsPanel::BonusCount()
{
return m_Bonuses.Count();
}
inline BonusMapDescription_t *GamepadUIBonusMapsPanel::GetBonusData( int iMapIndex )
{
return &m_Bonuses[iMapIndex];
}
inline bool GamepadUIBonusMapsPanel::IsValidIndex( int iMapIndex )
{
return m_Bonuses.IsValidIndex( iMapIndex );
}
inline BonusMapDescription_t *GamepadUIBonusMapsPanel::GetCurrentFolder()
{
if (m_BonusFolderHierarchy.Count() > 0)
return &m_BonusFolderHierarchy[0];
return NULL;
}
inline void GamepadUIBonusMapsPanel::BackFolder()
{
if (m_BonusFolderHierarchy.Count() > 0)
m_BonusFolderHierarchy.Remove( 0 );
}
inline void GamepadUIBonusMapsPanel::EnterFolder( BonusMapDescription_t *pFolder )
{
int i = m_BonusFolderHierarchy.AddToHead();
memcpy( &m_BonusFolderHierarchy[i], pFolder, sizeof( m_BonusFolderHierarchy[i] ) );
if (m_BonusFolderHierarchy.Count() > 1)
m_BonusFolderHierarchy[i].m_pParent = &m_BonusFolderHierarchy.Element( i + 1 );
}
void GamepadUIBonusMapsPanel::SetCurrentChallengeObjectives( int iBronze, int iSilver, int iGold )
{
GamepadUI::GetInstance().SetCurrentChallengeObjectives( iBronze, iSilver, iGold );
}
void GamepadUIBonusMapsPanel::SetCurrentChallengeNames( const char *pszFileName, const char *pszMapName, const char *pszChallengeName )
{
GamepadUI::GetInstance().SetCurrentChallengeNames( pszFileName, pszMapName, pszChallengeName );
}
#endif
CON_COMMAND( gamepadui_openbonusmapsdialog, "" )
{
new GamepadUIBonusMapsPanel( GamepadUI::GetInstance().GetBasePanel(), "" );
}
#endif // GAMEPADUI_ENABLE_BONUSMAPS