diff options
Diffstat (limited to 'game/server/portal/prop_portal_stats_display.cpp')
| -rw-r--r-- | game/server/portal/prop_portal_stats_display.cpp | 478 |
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 |