summaryrefslogtreecommitdiff
path: root/game/server/portal/prop_portal_stats_display.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'game/server/portal/prop_portal_stats_display.cpp')
-rw-r--r--game/server/portal/prop_portal_stats_display.cpp478
1 files changed, 478 insertions, 0 deletions
diff --git a/game/server/portal/prop_portal_stats_display.cpp b/game/server/portal/prop_portal_stats_display.cpp
new file mode 100644
index 0000000..3e8ff86
--- /dev/null
+++ b/game/server/portal/prop_portal_stats_display.cpp
@@ -0,0 +1,478 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Implements the big scary boom-boom machine Antlions fear.
+//
+//=============================================================================//
+
+#include "cbase.h"
+#include "baseanimating.h"
+#include "portal_player.h"
+#include "EnvMessage.h"
+#include "fmtstr.h"
+#include "vguiscreen.h"
+#include "point_bonusmaps_accessor.h"
+#include "portal_shareddefs.h"
+
+
+#define PORTAL_STATS_DISPLAY_MODEL_NAME "models/props/Round_elevator_body.mdl"
+
+
+class CPropPortalStatsDisplay : public CBaseAnimating
+{
+public:
+
+ DECLARE_CLASS( CPropPortalStatsDisplay, CBaseAnimating );
+ DECLARE_DATADESC();
+ DECLARE_SERVERCLASS();
+
+ virtual ~CPropPortalStatsDisplay();
+
+ virtual int UpdateTransmitState();
+ virtual void SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways );
+
+ virtual void Spawn( void );
+ virtual void Precache( void );
+ virtual void OnRestore( void );
+
+ void ScreenVisible( bool bVisible );
+
+ void Disable( void );
+ void Enable( void );
+
+ void InputDisable( inputdata_t &inputdata );
+ void InputEnable( inputdata_t &inputdata );
+
+ void InputUpdateStats( inputdata_t &inputdata );
+ void InputResetPlayerStats( inputdata_t &inputdata );
+
+private:
+
+ CNetworkVar( bool, m_bEnabled );
+
+ CNetworkVar( int, m_iNumPortalsPlaced );
+ CNetworkVar( int, m_iNumStepsTaken );
+ CNetworkVar( float, m_fNumSecondsTaken );
+
+ CNetworkVar( int, m_iBronzeObjective );
+ CNetworkVar( int, m_iSilverObjective );
+ CNetworkVar( int, m_iGoldObjective );
+
+ CNetworkString( szChallengeFileName, 128 );
+ CNetworkString( szChallengeMapName, 32 );
+ CNetworkString( szChallengeName, 32 );
+
+ CNetworkVar( int, m_iDisplayObjective );
+
+ COutputEvent m_OnMetBronzeObjective;
+ COutputEvent m_OnMetSilverObjective;
+ COutputEvent m_OnMetGoldObjective;
+ COutputEvent m_OnFailedAllObjectives;
+
+private:
+
+ // Control panel
+ void GetControlPanelInfo( int nPanelIndex, const char *&pPanelName );
+ void GetControlPanelClassName( int nPanelIndex, const char *&pPanelName );
+ void SpawnControlPanels( void );
+ void RestoreControlPanels( void );
+
+ typedef CHandle<CVGuiScreen> ScreenHandle_t;
+ CUtlVector<ScreenHandle_t> m_hScreens;
+
+};
+
+
+LINK_ENTITY_TO_CLASS( prop_portal_stats_display, CPropPortalStatsDisplay );
+
+//-----------------------------------------------------------------------------
+// Save/load
+//-----------------------------------------------------------------------------
+BEGIN_DATADESC( CPropPortalStatsDisplay )
+ DEFINE_FIELD( m_bEnabled, FIELD_BOOLEAN ),
+
+ DEFINE_FIELD( m_iNumPortalsPlaced, FIELD_INTEGER ),
+ DEFINE_FIELD( m_iNumStepsTaken, FIELD_INTEGER ),
+ DEFINE_FIELD( m_fNumSecondsTaken, FIELD_FLOAT ),
+
+ DEFINE_FIELD( m_iBronzeObjective, FIELD_INTEGER ),
+ DEFINE_FIELD( m_iSilverObjective, FIELD_INTEGER ),
+ DEFINE_FIELD( m_iGoldObjective, FIELD_INTEGER ),
+
+ DEFINE_AUTO_ARRAY( szChallengeFileName, FIELD_CHARACTER ),
+ DEFINE_AUTO_ARRAY( szChallengeMapName, FIELD_CHARACTER ),
+ DEFINE_AUTO_ARRAY( szChallengeName, FIELD_CHARACTER ),
+
+ DEFINE_FIELD( m_iDisplayObjective, FIELD_INTEGER ),
+
+ //DEFINE_UTLVECTOR( m_hScreens, FIELD_EHANDLE ),
+
+ DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
+ DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
+ DEFINE_INPUTFUNC( FIELD_VOID, "UpdateStats", InputUpdateStats ),
+ DEFINE_INPUTFUNC( FIELD_VOID, "ResetPlayerStats", InputResetPlayerStats ),
+
+ DEFINE_OUTPUT ( m_OnMetBronzeObjective, "OnMetBronzeObjective" ),
+ DEFINE_OUTPUT ( m_OnMetSilverObjective, "OnMetSilverObjective" ),
+ DEFINE_OUTPUT ( m_OnMetGoldObjective, "OnMetGoldObjective" ),
+ DEFINE_OUTPUT ( m_OnFailedAllObjectives, "OnFailedAllObjectives" ),
+
+END_DATADESC()
+
+IMPLEMENT_SERVERCLASS_ST( CPropPortalStatsDisplay, DT_PropPortalStatsDisplay )
+ SendPropBool( SENDINFO(m_bEnabled) ),
+
+ SendPropInt( SENDINFO(m_iNumPortalsPlaced) ),
+ SendPropInt( SENDINFO(m_iNumStepsTaken) ),
+ SendPropFloat( SENDINFO(m_fNumSecondsTaken) ),
+
+ SendPropInt( SENDINFO(m_iBronzeObjective) ),
+ SendPropInt( SENDINFO(m_iSilverObjective) ),
+ SendPropInt( SENDINFO(m_iGoldObjective) ),
+
+ SendPropString( SENDINFO( szChallengeFileName ) ),
+ SendPropString( SENDINFO( szChallengeMapName ) ),
+ SendPropString( SENDINFO( szChallengeName ) ),
+
+ SendPropInt( SENDINFO(m_iDisplayObjective) ),
+END_SEND_TABLE()
+
+
+CPropPortalStatsDisplay::~CPropPortalStatsDisplay()
+{
+ int i;
+ // Kill the control panels
+ for ( i = m_hScreens.Count(); --i >= 0; )
+ {
+ DestroyVGuiScreen( m_hScreens[i].Get() );
+ }
+ m_hScreens.RemoveAll();
+}
+
+int CPropPortalStatsDisplay::UpdateTransmitState()
+{
+ return SetTransmitState( FL_EDICT_FULLCHECK );
+}
+
+void CPropPortalStatsDisplay::SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways )
+{
+ // Are we already marked for transmission?
+ if ( pInfo->m_pTransmitEdict->Get( entindex() ) )
+ return;
+
+ BaseClass::SetTransmit( pInfo, bAlways );
+
+ // Force our screens to be sent too.
+ for ( int i=0; i < m_hScreens.Count(); i++ )
+ {
+ CVGuiScreen *pScreen = m_hScreens[i].Get();
+ pScreen->SetTransmit( pInfo, bAlways );
+ }
+}
+
+void CPropPortalStatsDisplay::Spawn( void )
+{
+ char *szModel = (char *)STRING( GetModelName() );
+ if (!szModel || !*szModel)
+ {
+ szModel = PORTAL_STATS_DISPLAY_MODEL_NAME;
+ SetModelName( AllocPooledString(szModel) );
+ }
+
+ Precache();
+ SetModel( szModel );
+
+ SetSolid( SOLID_VPHYSICS );
+ VPhysicsInitStatic();
+
+ BaseClass::Spawn();
+
+ int iBronze, iSilver, iGold;
+ BonusMapChallengeObjectives( iBronze, iSilver, iGold );
+ m_iBronzeObjective = iBronze;
+ m_iSilverObjective = iSilver;
+ m_iGoldObjective = iGold;
+
+ BonusMapChallengeNames( szChallengeFileName.GetForModify(), szChallengeMapName.GetForModify(), szChallengeName.GetForModify() );
+
+ m_bEnabled = false;
+
+ int iSequence = SelectHeaviestSequence ( ACT_IDLE );
+
+ if ( iSequence != ACT_INVALID )
+ {
+ SetSequence( iSequence );
+ ResetSequenceInfo();
+
+ //Do this so we get the nice ramp-up effect.
+ m_flPlaybackRate = random->RandomFloat( 0.0f, 1.0f );
+ }
+
+ SpawnControlPanels();
+
+ ScreenVisible( m_bEnabled );
+}
+
+void CPropPortalStatsDisplay::Precache( void )
+{
+ BaseClass::Precache();
+
+ PrecacheModel( STRING( GetModelName() ) );
+
+ PrecacheVGuiScreen( "portal_stats_display_screen" );
+}
+
+void CPropPortalStatsDisplay::OnRestore( void )
+{
+ BaseClass::OnRestore();
+
+ RestoreControlPanels();
+
+ ScreenVisible( m_bEnabled );
+}
+
+void CPropPortalStatsDisplay::ScreenVisible( bool bVisible )
+{
+ for ( int iScreen = 0; iScreen < m_hScreens.Count(); ++iScreen )
+ {
+ CVGuiScreen *pScreen = m_hScreens[ iScreen ].Get();
+ if ( bVisible )
+ pScreen->RemoveEffects( EF_NODRAW );
+ else
+ pScreen->AddEffects( EF_NODRAW );
+ }
+}
+
+void CPropPortalStatsDisplay::Disable( void )
+{
+ if ( !m_bEnabled )
+ return;
+
+ m_bEnabled = false;
+
+ ScreenVisible( false );
+}
+
+void CPropPortalStatsDisplay::Enable( void )
+{
+ if ( m_bEnabled )
+ return;
+
+ // Don't show stats display in non challenge mode!
+ CBasePlayer *pPlayer = UTIL_GetLocalPlayer();
+ if ( pPlayer && pPlayer->GetBonusChallenge() == 0 )
+ return;
+
+ m_bEnabled = true;
+
+ m_iDisplayObjective = pPlayer->GetBonusChallenge() - 1;
+
+ // Check if they beat objectives
+ if ( pPlayer->GetBonusProgress() <= m_iBronzeObjective )
+ m_OnMetBronzeObjective.FireOutput( this, this );
+ else if ( pPlayer->GetBonusProgress() <= m_iSilverObjective )
+ m_OnMetSilverObjective.FireOutput( this, this );
+ else if ( pPlayer->GetBonusProgress() <= m_iGoldObjective )
+ m_OnMetGoldObjective.FireOutput( this, this );
+ else
+ m_OnFailedAllObjectives.FireOutput( this, this );
+
+ ScreenVisible( true );
+}
+
+void CPropPortalStatsDisplay::InputDisable( inputdata_t &inputdata )
+{
+ Disable();
+}
+
+void CPropPortalStatsDisplay::InputEnable( inputdata_t &inputdata )
+{
+ Enable();
+}
+
+void CPropPortalStatsDisplay::InputUpdateStats( inputdata_t &inputdata )
+{
+ CPortal_Player *pPlayer = (CPortal_Player *)UTIL_GetCommandClient();
+ if( pPlayer == NULL )
+ pPlayer = GetPortalPlayer( 1 ); //last ditch effort
+
+ if( pPlayer )
+ {
+ m_iNumPortalsPlaced = pPlayer->NumPortalsPlaced();
+ m_iNumStepsTaken = pPlayer->NumStepsTaken();
+ m_fNumSecondsTaken = pPlayer->NumSecondsTaken();
+
+ // Now that we've recorded it, don't let it change
+ pPlayer->PauseBonusProgress();
+ }
+}
+
+void CPropPortalStatsDisplay::InputResetPlayerStats( inputdata_t &inputdata )
+{
+ CPortal_Player *pPlayer = (CPortal_Player *)UTIL_GetCommandClient();
+ if( pPlayer == NULL )
+ pPlayer = GetPortalPlayer( 1 ); //last ditch effort
+
+ if( pPlayer )
+ {
+ pPlayer->ResetThisLevelStats();
+ }
+}
+
+void CPropPortalStatsDisplay::GetControlPanelInfo( int nPanelIndex, const char *&pPanelName )
+{
+ pPanelName = "portal_stats_display_screen";
+}
+
+void CPropPortalStatsDisplay::GetControlPanelClassName( int nPanelIndex, const char *&pPanelName )
+{
+ pPanelName = "vgui_screen";
+}
+
+//-----------------------------------------------------------------------------
+// This is called by the base object when it's time to spawn the control panels
+//-----------------------------------------------------------------------------
+void CPropPortalStatsDisplay::SpawnControlPanels()
+{
+ char buf[64];
+
+ // FIXME: Deal with dynamically resizing control panels?
+
+ // If we're attached to an entity, spawn control panels on it instead of use
+ CBaseAnimating *pEntityToSpawnOn = this;
+ char *pOrgLL = "statPanel%d_bl";
+ char *pOrgUR = "statPanel%d_tr";
+ char *pAttachmentNameLL = pOrgLL;
+ char *pAttachmentNameUR = pOrgUR;
+
+ Assert( pEntityToSpawnOn );
+
+ // Lookup the attachment point...
+ int nPanel;
+ for ( nPanel = 0; true; ++nPanel )
+ {
+ Q_snprintf( buf, sizeof( buf ), pAttachmentNameLL, nPanel );
+ int nLLAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf);
+ if (nLLAttachmentIndex <= 0)
+ {
+ // Try and use my panels then
+ pEntityToSpawnOn = this;
+ Q_snprintf( buf, sizeof( buf ), pOrgLL, nPanel );
+ nLLAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf);
+ if (nLLAttachmentIndex <= 0)
+ return;
+ }
+
+ Q_snprintf( buf, sizeof( buf ), pAttachmentNameUR, nPanel );
+ int nURAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf);
+ if (nURAttachmentIndex <= 0)
+ {
+ // Try and use my panels then
+ Q_snprintf( buf, sizeof( buf ), pOrgUR, nPanel );
+ nURAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf);
+ if (nURAttachmentIndex <= 0)
+ return;
+ }
+
+ const char *pScreenName;
+ GetControlPanelInfo( nPanel, pScreenName );
+ if (!pScreenName)
+ continue;
+
+ const char *pScreenClassname;
+ GetControlPanelClassName( nPanel, pScreenClassname );
+ if ( !pScreenClassname )
+ continue;
+
+ // Compute the screen size from the attachment points...
+ matrix3x4_t panelToWorld;
+ pEntityToSpawnOn->GetAttachment( nLLAttachmentIndex, panelToWorld );
+
+ matrix3x4_t worldToPanel;
+ MatrixInvert( panelToWorld, worldToPanel );
+
+ // Now get the lower right position + transform into panel space
+ Vector lr, lrlocal;
+ pEntityToSpawnOn->GetAttachment( nURAttachmentIndex, panelToWorld );
+ MatrixGetColumn( panelToWorld, 3, lr );
+ VectorTransform( lr, worldToPanel, lrlocal );
+
+ float flWidth = lrlocal.x;
+ float flHeight = lrlocal.y;
+
+ CVGuiScreen *pScreen = CreateVGuiScreen( pScreenClassname, pScreenName, pEntityToSpawnOn, this, nLLAttachmentIndex );
+ pScreen->ChangeTeam( GetTeamNumber() );
+ pScreen->SetActualSize( flWidth, flHeight );
+ pScreen->SetActive( true );
+ pScreen->MakeVisibleOnlyToTeammates( false );
+ pScreen->SetTransparency( true );
+ int nScreen = m_hScreens.AddToTail( );
+ m_hScreens[nScreen].Set( pScreen );
+ }
+}
+
+void CPropPortalStatsDisplay::RestoreControlPanels( void )
+{
+ char buf[64];
+
+ // FIXME: Deal with dynamically resizing control panels?
+
+ // If we're attached to an entity, spawn control panels on it instead of use
+ CBaseAnimating *pEntityToSpawnOn = this;
+ char *pOrgLL = "statPanel%d_bl";
+ char *pOrgUR = "statPanel%d_tr";
+ char *pAttachmentNameLL = pOrgLL;
+ char *pAttachmentNameUR = pOrgUR;
+
+ Assert( pEntityToSpawnOn );
+
+ // Lookup the attachment point...
+ int nPanel;
+ for ( nPanel = 0; true; ++nPanel )
+ {
+ Q_snprintf( buf, sizeof( buf ), pAttachmentNameLL, nPanel );
+ int nLLAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf);
+ if (nLLAttachmentIndex <= 0)
+ {
+ // Try and use my panels then
+ pEntityToSpawnOn = this;
+ Q_snprintf( buf, sizeof( buf ), pOrgLL, nPanel );
+ nLLAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf);
+ if (nLLAttachmentIndex <= 0)
+ return;
+ }
+
+ Q_snprintf( buf, sizeof( buf ), pAttachmentNameUR, nPanel );
+ int nURAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf);
+ if (nURAttachmentIndex <= 0)
+ {
+ // Try and use my panels then
+ Q_snprintf( buf, sizeof( buf ), pOrgUR, nPanel );
+ nURAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf);
+ if (nURAttachmentIndex <= 0)
+ return;
+ }
+
+ const char *pScreenName;
+ GetControlPanelInfo( nPanel, pScreenName );
+ if (!pScreenName)
+ continue;
+
+ const char *pScreenClassname;
+ GetControlPanelClassName( nPanel, pScreenClassname );
+ if ( !pScreenClassname )
+ continue;
+
+ CVGuiScreen *pScreen = (CVGuiScreen *)gEntList.FindEntityByClassname( NULL, pScreenClassname );
+
+ while ( pScreen && pScreen->GetOwnerEntity() != this && Q_strcmp( pScreen->GetPanelName(), pScreenName ) == 0 )
+ {
+ pScreen = (CVGuiScreen *)gEntList.FindEntityByClassname( pScreen, pScreenClassname );
+ }
+
+ if ( pScreen )
+ {
+ int nScreen = m_hScreens.AddToTail( );
+ m_hScreens[nScreen].Set( pScreen );
+ }
+ }
+} \ No newline at end of file