From 39ed87570bdb2f86969d4be821c94b722dc71179 Mon Sep 17 00:00:00 2001 From: Joe Ludwig Date: Wed, 26 Jun 2013 15:22:04 -0700 Subject: First version of the SOurce SDK 2013 --- mp/src/game/server/game_ui.cpp | 439 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 439 insertions(+) create mode 100644 mp/src/game/server/game_ui.cpp (limited to 'mp/src/game/server/game_ui.cpp') diff --git a/mp/src/game/server/game_ui.cpp b/mp/src/game/server/game_ui.cpp new file mode 100644 index 00000000..5d6f1cc5 --- /dev/null +++ b/mp/src/game/server/game_ui.cpp @@ -0,0 +1,439 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Entities that capture the player's UI and move it into game design +// as outputs. +// +// $NoKeywords: $ +//=============================================================================// + +#include "cbase.h" +#include "entitylist.h" +#include "util.h" +#include "physics.h" +#include "entityoutput.h" +#include "player.h" +#include "in_buttons.h" +#include "basecombatweapon.h" +#include "baseviewmodel.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +//---------------------------------------------------------------- +// Spawn flags +//---------------------------------------------------------------- +#define SF_GAMEUI_FREEZE_PLAYER 32 +#define SF_GAMEUI_HIDE_WEAPON 64 +#define SF_GAMEUI_USE_DEACTIVATES 128 +#define SF_GAMEUI_JUMP_DEACTIVATES 256 + + +class CGameUI : public CBaseEntity +{ +public: + DECLARE_CLASS( CGameUI, CBaseEntity ); + + DECLARE_DATADESC(); + + // Input handlers + void InputDeactivate( inputdata_t &inputdata ); + void InputActivate( inputdata_t &inputdata ); + + void Think( void ); + void Deactivate( CBaseEntity *pActivator ); + + float m_flFieldOfView; + CHandle m_hSaveWeapon; + + COutputEvent m_playerOn; + COutputEvent m_playerOff; + + COutputEvent m_pressedMoveLeft; + COutputEvent m_pressedMoveRight; + COutputEvent m_pressedForward; + COutputEvent m_pressedBack; + COutputEvent m_pressedAttack; + COutputEvent m_pressedAttack2; + + COutputEvent m_unpressedMoveLeft; + COutputEvent m_unpressedMoveRight; + COutputEvent m_unpressedForward; + COutputEvent m_unpressedBack; + COutputEvent m_unpressedAttack; + COutputEvent m_unpressedAttack2; + + COutputFloat m_xaxis; + COutputFloat m_yaxis; + COutputFloat m_attackaxis; + COutputFloat m_attack2axis; + + bool m_bForceUpdate; + int m_nLastButtonState; + + CHandle m_player; +}; + + +BEGIN_DATADESC( CGameUI ) + + DEFINE_KEYFIELD( m_flFieldOfView, FIELD_FLOAT, "FieldOfView" ), + DEFINE_FIELD( m_hSaveWeapon, FIELD_EHANDLE ), + DEFINE_FIELD( m_bForceUpdate, FIELD_BOOLEAN ), + DEFINE_FIELD( m_player, FIELD_EHANDLE ), + DEFINE_FIELD( m_nLastButtonState, FIELD_INTEGER ), + + DEFINE_INPUTFUNC( FIELD_VOID, "Deactivate", InputDeactivate ), + DEFINE_INPUTFUNC( FIELD_STRING, "Activate", InputActivate ), + + DEFINE_OUTPUT( m_playerOn, "PlayerOn" ), + DEFINE_OUTPUT( m_playerOff, "PlayerOff" ), + + DEFINE_OUTPUT( m_pressedMoveLeft, "PressedMoveLeft" ), + DEFINE_OUTPUT( m_pressedMoveRight, "PressedMoveRight" ), + DEFINE_OUTPUT( m_pressedForward, "PressedForward" ), + DEFINE_OUTPUT( m_pressedBack, "PressedBack" ), + DEFINE_OUTPUT( m_pressedAttack, "PressedAttack" ), + DEFINE_OUTPUT( m_pressedAttack2, "PressedAttack2" ), + + DEFINE_OUTPUT( m_unpressedMoveLeft, "UnpressedMoveLeft" ), + DEFINE_OUTPUT( m_unpressedMoveRight, "UnpressedMoveRight" ), + DEFINE_OUTPUT( m_unpressedForward, "UnpressedForward" ), + DEFINE_OUTPUT( m_unpressedBack, "UnpressedBack" ), + DEFINE_OUTPUT( m_unpressedAttack, "UnpressedAttack" ), + DEFINE_OUTPUT( m_unpressedAttack2, "UnpressedAttack2" ), + + DEFINE_OUTPUT( m_xaxis, "XAxis" ), + DEFINE_OUTPUT( m_yaxis, "YAxis" ), + DEFINE_OUTPUT( m_attackaxis, "AttackAxis" ), + DEFINE_OUTPUT( m_attack2axis, "Attack2Axis" ), + +END_DATADESC() + + +LINK_ENTITY_TO_CLASS( game_ui, CGameUI ); + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CGameUI::InputDeactivate( inputdata_t &inputdata ) +{ + Deactivate( inputdata.pActivator ); +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CGameUI::Deactivate( CBaseEntity *pActivator ) +{ + CBasePlayer *pPlayer = m_player; + + AssertMsg(pPlayer, "CGameUI deactivated without a player!"); + + if (pPlayer) + { + // Re-enable player motion + if ( FBitSet( m_spawnflags, SF_GAMEUI_FREEZE_PLAYER ) ) + { + m_player->RemoveFlag( FL_ATCONTROLS ); + } + + // Restore weapons + if ( FBitSet( m_spawnflags, SF_GAMEUI_HIDE_WEAPON ) ) + { + // Turn the hud back on + pPlayer->m_Local.m_iHideHUD &= ~HIDEHUD_WEAPONSELECTION; + + if ( m_hSaveWeapon.Get() ) + { + m_player->Weapon_Switch( m_hSaveWeapon.Get() ); + m_hSaveWeapon = NULL; + } + + if ( pPlayer->GetActiveWeapon() ) + { + pPlayer->GetActiveWeapon()->Deploy(); + } + } + + // Announce that the player is no longer controlling through us + m_playerOff.FireOutput( pPlayer, this, 0 ); + + // Clear out the axis controls + m_xaxis.Set( 0, pPlayer, this ); + m_yaxis.Set( 0, pPlayer, this ); + m_attackaxis.Set( 0, pPlayer, this ); + m_attack2axis.Set( 0, pPlayer, this ); + m_nLastButtonState = 0; + m_player = NULL; + } + else + { + Warning("%s Deactivate(): I have no player when called by %s!\n", GetEntityName().ToCStr(), pActivator->GetEntityName().ToCStr()); + } + + // Stop thinking + SetNextThink( TICK_NEVER_THINK ); +} + + +//------------------------------------------------------------------------------ +// Purpose : +//------------------------------------------------------------------------------ +void CGameUI::InputActivate( inputdata_t &inputdata ) +{ + CBasePlayer *pPlayer; + + // Determine if we're specifying this as an override parameter + if ( inputdata.value.StringID() != NULL_STRING ) + { + CBaseEntity *pEntity = gEntList.FindEntityByName( NULL, inputdata.value.String(), this, inputdata.pActivator, inputdata.pCaller ); + if ( pEntity == NULL || pEntity->IsPlayer() == false ) + { + Warning( "%s InputActivate: entity %s not found or is not a player!\n", GetEntityName().ToCStr(), inputdata.value.String() ); + return; + } + + pPlayer = ToBasePlayer( pEntity ); + } + else + { + // Otherwise try to use the activator + if ( inputdata.pActivator == NULL || inputdata.pActivator->IsPlayer() == false ) + { + Warning( "%s InputActivate: invalid or missing !activator!\n", GetEntityName().ToCStr() ); + return; + } + + pPlayer = ToBasePlayer( inputdata.pActivator ); + } + + // If another player is already using these controls3, ignore this activation + if ( m_player.Get() != NULL && pPlayer != m_player.Get() ) + { + // TODO: We could allow this by calling Deactivate() at this point and continuing on -- jdw + return; + } + + // Setup our internal data + m_player = pPlayer; + m_playerOn.FireOutput( pPlayer, this, 0 ); + + // Turn the hud off + SetNextThink( gpGlobals->curtime ); + + // Disable player's motion + if ( FBitSet( m_spawnflags, SF_GAMEUI_FREEZE_PLAYER ) ) + { + m_player->AddFlag( FL_ATCONTROLS ); + } + + // Store off and hide the currently held weapon + if ( FBitSet( m_spawnflags, SF_GAMEUI_HIDE_WEAPON ) ) + { + m_player->m_Local.m_iHideHUD |= HIDEHUD_WEAPONSELECTION; + + if ( m_player->GetActiveWeapon() ) + { + m_hSaveWeapon = m_player->GetActiveWeapon(); + + m_player->GetActiveWeapon()->Holster(); + m_player->ClearActiveWeapon(); + m_player->HideViewModels(); + } + } + + // We must update our state + m_bForceUpdate = true; +} + + +//------------------------------------------------------------------------------ +// Purpose: Samples the player's inputs and fires outputs based on what buttons +// are currently held down. +//------------------------------------------------------------------------------ +void CGameUI::Think( void ) +{ + CBasePlayer *pPlayer = m_player; + + // If player is gone, stop thinking + if (pPlayer == NULL) + { + SetNextThink( TICK_NEVER_THINK ); + return; + } + + // If we're forcing an update, state with a clean button state + if ( m_bForceUpdate ) + { + m_nLastButtonState = pPlayer->m_nButtons; + } + + // ------------------------------------------------ + // Check that toucher is facing the UI within + // the field of view tolerance. If not disconnect + // ------------------------------------------------ + if (m_flFieldOfView > -1) + { + Vector vPlayerFacing; + pPlayer->EyeVectors( &vPlayerFacing ); + Vector vPlayerToUI = GetAbsOrigin() - pPlayer->WorldSpaceCenter(); + VectorNormalize(vPlayerToUI); + + float flDotPr = DotProduct(vPlayerFacing,vPlayerToUI); + if (flDotPr < m_flFieldOfView) + { + Deactivate( pPlayer ); + return; + } + } + + pPlayer->AddFlag( FL_ONTRAIN ); + SetNextThink( gpGlobals->curtime ); + + // Deactivate if they jump or press +use. + // FIXME: prevent the use from going through in player.cpp + if ((( pPlayer->m_afButtonPressed & IN_USE ) && ( m_spawnflags & SF_GAMEUI_USE_DEACTIVATES )) || + (( pPlayer->m_afButtonPressed & IN_JUMP ) && ( m_spawnflags & SF_GAMEUI_JUMP_DEACTIVATES ))) + { + Deactivate( pPlayer ); + return; + } + + // Determine what's different + int nButtonsChanged = ( pPlayer->m_nButtons ^ m_nLastButtonState ); + + // + // Handle all our possible input triggers + // + + if ( nButtonsChanged & IN_MOVERIGHT ) + { + if ( m_nLastButtonState & IN_MOVERIGHT ) + { + m_unpressedMoveRight.FireOutput( pPlayer, this, 0 ); + } + else + { + m_pressedMoveRight.FireOutput( pPlayer, this, 0 ); + } + } + + if ( nButtonsChanged & IN_MOVELEFT ) + { + if ( m_nLastButtonState & IN_MOVELEFT ) + { + m_unpressedMoveLeft.FireOutput( pPlayer, this, 0 ); + } + else + { + m_pressedMoveLeft.FireOutput( pPlayer, this, 0 ); + } + } + + if ( nButtonsChanged & IN_FORWARD ) + { + if ( m_nLastButtonState & IN_FORWARD ) + { + m_unpressedForward.FireOutput( pPlayer, this, 0 ); + } + else + { + m_pressedForward.FireOutput( pPlayer, this, 0 ); + } + } + + if ( nButtonsChanged & IN_BACK ) + { + if ( m_nLastButtonState & IN_BACK ) + { + m_unpressedBack.FireOutput( pPlayer, this, 0 ); + } + else + { + m_pressedBack.FireOutput( pPlayer, this, 0 ); + } + } + + if ( nButtonsChanged & IN_ATTACK ) + { + if ( m_nLastButtonState & IN_ATTACK ) + { + m_unpressedAttack.FireOutput( pPlayer, this, 0 ); + } + else + { + m_pressedAttack.FireOutput( pPlayer, this, 0 ); + } + } + + if ( nButtonsChanged & IN_ATTACK2 ) + { + if ( m_nLastButtonState & IN_ATTACK2 ) + { + m_unpressedAttack2.FireOutput( pPlayer, this, 0 ); + } + else + { + m_pressedAttack2.FireOutput( pPlayer, this, 0 ); + } + } + + // Setup for the next frame + m_nLastButtonState = pPlayer->m_nButtons; + + float x = 0, y = 0, attack = 0, attack2 = 0; + if ( pPlayer->m_nButtons & IN_MOVERIGHT ) + { + x = 1; + } + else if ( pPlayer->m_nButtons & IN_MOVELEFT ) + { + x = -1; + } + + if ( pPlayer->m_nButtons & IN_FORWARD ) + { + y = 1; + } + else if ( pPlayer->m_nButtons & IN_BACK ) + { + y = -1; + } + + if ( pPlayer->m_nButtons & IN_ATTACK ) + { + attack = 1; + } + + if ( pPlayer->m_nButtons & IN_ATTACK2 ) + { + attack2 = 1; + } + + // + // Fire the analog outputs if they changed. + // + if ( m_bForceUpdate || ( m_xaxis.Get() != x ) ) + { + m_xaxis.Set( x, pPlayer, this ); + } + + if ( m_bForceUpdate || ( m_yaxis.Get() != y ) ) + { + m_yaxis.Set( y, pPlayer, this ); + } + + if ( m_bForceUpdate || ( m_attackaxis.Get() != attack ) ) + { + m_attackaxis.Set( attack, pPlayer, this ); + } + + if ( m_bForceUpdate || ( m_attack2axis.Get() != attack2 ) ) + { + m_attack2axis.Set( attack2, pPlayer, this ); + } + + m_bForceUpdate = false; +} -- cgit v1.2.3