Merge pull request #264 from Petercov/mapbase-feature/vgui-screens

Outputs for vgui_screen
This commit is contained in:
Blixibon 2025-01-04 08:48:37 -06:00 committed by GitHub
commit a8d69e56e3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 305 additions and 41 deletions

View File

@ -1133,6 +1133,9 @@ void C_BasePlayer::DetermineVguiInputMode( CUserCmd *pCmd )
// Kill all attack inputs if we're in vgui screen mode // Kill all attack inputs if we're in vgui screen mode
pCmd->buttons &= ~(IN_ATTACK | IN_ATTACK2 | IN_VALIDVGUIINPUT); pCmd->buttons &= ~(IN_ATTACK | IN_ATTACK2 | IN_VALIDVGUIINPUT);
#ifdef MAPBASE
pCmd->buttons |= IN_VGUIMODE;
#endif // MAPBASE
return; return;
} }
#else #else
@ -1142,6 +1145,10 @@ void C_BasePlayer::DetermineVguiInputMode( CUserCmd *pCmd )
// Kill all attack inputs if we're in vgui screen mode // Kill all attack inputs if we're in vgui screen mode
pCmd->buttons &= ~(IN_ATTACK | IN_ATTACK2); pCmd->buttons &= ~(IN_ATTACK | IN_ATTACK2);
#ifdef MAPBASE
pCmd->buttons &= ~(IN_USE | IN_ATTACK3);
pCmd->buttons |= IN_VGUIMODE;
#endif // MAPBASE
return; return;
} }
#endif #endif
@ -1206,6 +1213,10 @@ void C_BasePlayer::DetermineVguiInputMode( CUserCmd *pCmd )
// Kill all attack inputs if we're in vgui screen mode // Kill all attack inputs if we're in vgui screen mode
pCmd->buttons &= ~(IN_ATTACK | IN_ATTACK2); pCmd->buttons &= ~(IN_ATTACK | IN_ATTACK2);
#ifdef MAPBASE
pCmd->buttons &= ~(IN_USE | IN_ATTACK3);
pCmd->buttons |= IN_VGUIMODE;
#endif // MAPBASE
} }
} }

View File

@ -42,6 +42,10 @@ CLIENTEFFECT_REGISTER_BEGIN( PrecacheEffectVGuiScreen )
CLIENTEFFECT_MATERIAL("engine/writez") CLIENTEFFECT_MATERIAL("engine/writez")
CLIENTEFFECT_REGISTER_END() CLIENTEFFECT_REGISTER_END()
#ifdef MAPBASE
C_EntityClassList<C_VGuiScreen> g_VGUIScreenList;
template <> C_VGuiScreen* C_EntityClassList<C_VGuiScreen>::m_pClassList = NULL;
#endif // MAPBASE
// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- //
// This is a cache of preloaded keyvalues. // This is a cache of preloaded keyvalues.
@ -102,11 +106,19 @@ C_VGuiScreen::C_VGuiScreen()
m_WriteZMaterial.Init( "engine/writez", TEXTURE_GROUP_VGUI ); m_WriteZMaterial.Init( "engine/writez", TEXTURE_GROUP_VGUI );
m_OverlayMaterial.Init( m_WriteZMaterial ); m_OverlayMaterial.Init( m_WriteZMaterial );
#ifdef MAPBASE
g_VGUIScreenList.Insert(this);
#endif // MAPBASE
} }
C_VGuiScreen::~C_VGuiScreen() C_VGuiScreen::~C_VGuiScreen()
{ {
DestroyVguiScreen(); DestroyVguiScreen();
#ifdef MAPBASE
g_VGUIScreenList.Remove(this);
#endif // MAPBASE
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -416,10 +428,12 @@ void C_VGuiScreen::ClientThink( void )
int px = (int)(u * m_nPixelWidth + 0.5f); int px = (int)(u * m_nPixelWidth + 0.5f);
int py = (int)(v * m_nPixelHeight + 0.5f); int py = (int)(v * m_nPixelHeight + 0.5f);
#ifndef MAPBASE
// Generate mouse input commands // Generate mouse input commands
if ((px != m_nOldPx) || (py != m_nOldPy)) if ((px != m_nOldPx) || (py != m_nOldPy))
{ {
g_InputInternal->InternalCursorMoved(px, py); g_InputInternal->InternalCursorMoved(px, py);
m_nOldPx = px; m_nOldPx = px;
m_nOldPy = py; m_nOldPy = py;
} }
@ -444,6 +458,39 @@ void C_VGuiScreen::ClientThink( void )
g_InputInternal->SetMouseCodeState(MOUSE_RIGHT, vgui::BUTTON_RELEASED); g_InputInternal->SetMouseCodeState(MOUSE_RIGHT, vgui::BUTTON_RELEASED);
g_InputInternal->InternalMouseReleased(MOUSE_RIGHT); g_InputInternal->InternalMouseReleased(MOUSE_RIGHT);
} }
#else
vgui::VPANEL focus = g_InputInternal->GetMouseOver();
// Generate mouse input commands
if ((px != m_nOldPx) || (py != m_nOldPy))
{
g_InputInternal->UpdateCursorPosInternal(px, py);
m_nOldPx = px;
m_nOldPy = py;
focus = pPanel->IsWithinTraverse(px, py, true);
g_InputInternal->SetMouseFocus(focus);
vgui::ivgui()->PostMessage(focus, new KeyValues("CursorMoved", "xpos", px, "ypos", py), NULL);
}
for (int i = 0; i < 2; i++)
{
const int nBit = i ? IN_ATTACK2 : (IN_ATTACK | IN_USE);
const vgui::MouseCode nButton = i ? MOUSE_RIGHT : MOUSE_LEFT;
if ((m_nButtonReleased & nBit) || ((m_nButtonState & nBit) && m_bLoseThinkNextFrame)) // for a button release on loosing focus
{
g_InputInternal->SetMouseCodeState(nButton, vgui::BUTTON_RELEASED);
vgui::ivgui()->PostMessage(focus, new KeyValues("MouseReleased", "code", nButton), NULL);
}
else if (m_nButtonPressed & nBit)
{
g_InputInternal->SetMouseCodeState(nButton, vgui::BUTTON_PRESSED);
vgui::ivgui()->PostMessage(focus, new KeyValues("MousePressed", "code", nButton), NULL);
}
}
#endif // !MAPBASE
if ( m_bLoseThinkNextFrame == true ) if ( m_bLoseThinkNextFrame == true )
{ {
@ -627,6 +674,7 @@ bool C_VGuiScreen::IsInputOnlyToOwner( void )
return (m_fScreenFlags & VGUI_SCREEN_ONLY_USABLE_BY_OWNER) != 0; return (m_fScreenFlags & VGUI_SCREEN_ONLY_USABLE_BY_OWNER) != 0;
} }
#ifndef MAPBASE
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
// Enumator class for finding vgui screens close to the local player // Enumator class for finding vgui screens close to the local player
@ -671,6 +719,8 @@ C_VGuiScreen *CVGuiScreenEnumerator::GetVGuiScreen( int index )
{ {
return m_VguiScreens[index].Get(); return m_VguiScreens[index].Get();
} }
#endif // !MAPBASE
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -704,18 +754,29 @@ C_BaseEntity *FindNearbyVguiScreen( const Vector &viewPosition, const QAngle &vi
Ray_t lookRay; Ray_t lookRay;
lookRay.Init( viewPosition, lookEnd ); lookRay.Init( viewPosition, lookEnd );
#ifndef MAPBASE
// Look for vgui screens that are close to the player // Look for vgui screens that are close to the player
CVGuiScreenEnumerator localScreens; CVGuiScreenEnumerator localScreens;
partition->EnumerateElementsInSphere(PARTITION_CLIENT_NON_STATIC_EDICTS, viewPosition, VGUI_SCREEN_MODE_RADIUS, false, &localScreens); partition->EnumerateElementsInSphere(PARTITION_CLIENT_NON_STATIC_EDICTS, viewPosition, VGUI_SCREEN_MODE_RADIUS, false, &localScreens);
#endif // !MAPBASE
Vector vecOut, vecViewDelta; Vector vecOut, vecViewDelta;
float flBestDist = 2.0f; float flBestDist = 2.0f;
C_VGuiScreen *pBestScreen = NULL; C_VGuiScreen *pBestScreen = NULL;
#ifndef MAPBASE
for (int i = localScreens.GetScreenCount(); --i >= 0; ) for (int i = localScreens.GetScreenCount(); --i >= 0; )
#else
for (C_VGuiScreen* pScreen = g_VGUIScreenList.m_pClassList; pScreen != NULL; pScreen = pScreen->m_pNext)
#endif // !MAPBASE
{ {
#ifndef MAPBASE
C_VGuiScreen* pScreen = localScreens.GetVGuiScreen(i); C_VGuiScreen* pScreen = localScreens.GetVGuiScreen(i);
#else
// Skip if out of PVS
if (pScreen->IsDormant())
continue;
#endif
if ( pScreen->IsAttachedToViewModel() ) if ( pScreen->IsAttachedToViewModel() )
continue; continue;
@ -869,6 +930,16 @@ void CVGuiScreenPanel::OnCommand( const char *command)
{ {
if (Q_stricmp(command, "vguicancel")) if (Q_stricmp(command, "vguicancel"))
{ {
#ifdef MAPBASE
if (m_hEntity && m_hEntity->IsServerEntity())
{
KeyValues* pCommand = new KeyValues("EntityCommand");
pCommand->SetInt("entindex", m_hEntity->index);
pCommand->SetString("command_data", command);
engine->ServerCmdKeyValues(pCommand);
}
else
#endif
engine->ClientCmd(const_cast<char*>(command)); engine->ClientCmd(const_cast<char*>(command));
} }

View File

@ -66,6 +66,10 @@ class C_VGuiScreen : public C_BaseEntity
public: public:
DECLARE_CLIENTCLASS(); DECLARE_CLIENTCLASS();
#ifdef MAPBASE
C_VGuiScreen* m_pNext;
#endif // MAPBASE
C_VGuiScreen(); C_VGuiScreen();
~C_VGuiScreen(); ~C_VGuiScreen();

View File

@ -606,6 +606,9 @@ public:
void ValidateEntityConnections(); void ValidateEntityConnections();
void FireNamedOutput( const char *pszOutput, variant_t variant, CBaseEntity *pActivator, CBaseEntity *pCaller, float flDelay = 0.0f ); void FireNamedOutput( const char *pszOutput, variant_t variant, CBaseEntity *pActivator, CBaseEntity *pCaller, float flDelay = 0.0f );
#ifdef MAPBASE
virtual
#endif
CBaseEntityOutput *FindNamedOutput( const char *pszOutput ); CBaseEntityOutput *FindNamedOutput( const char *pszOutput );
#ifdef MAPBASE_VSCRIPT #ifdef MAPBASE_VSCRIPT
void ScriptFireOutput( const char *pszOutput, HSCRIPT hActivator, HSCRIPT hCaller, const char *szValue, float flDelay ); void ScriptFireOutput( const char *pszOutput, HSCRIPT hActivator, HSCRIPT hCaller, const char *szValue, float flDelay );
@ -864,6 +867,13 @@ public:
void SetAIWalkable( bool bBlocksLOS ); void SetAIWalkable( bool bBlocksLOS );
bool IsAIWalkable( void ); bool IsAIWalkable( void );
#ifdef MAPBASE
// Handle a potentially complex command from a client.
// Returns true if the command was handled successfully.
virtual bool HandleEntityCommand(CBasePlayer* pClient, KeyValues* pKeyValues) { return false; }
#endif // MAPBASE
private: private:
int SaveDataDescBlock( ISave &save, datamap_t *dmap ); int SaveDataDescBlock( ISave &save, datamap_t *dmap );
int RestoreDataDescBlock( IRestore &restore, datamap_t *dmap ); int RestoreDataDescBlock( IRestore &restore, datamap_t *dmap );

View File

@ -3617,6 +3617,20 @@ void CHL2_Player::UpdateWeaponPosture( void )
{ {
m_LowerWeaponTimer.Set( .3 ); m_LowerWeaponTimer.Set( .3 );
VPROF( "CHL2_Player::UpdateWeaponPosture-CheckLower" ); VPROF( "CHL2_Player::UpdateWeaponPosture-CheckLower" );
#ifdef MAPBASE
if (m_nButtons & IN_VGUIMODE)
{
//We're over a friendly, drop our weapon
if (Weapon_Lower() == false)
{
//FIXME: We couldn't lower our weapon!
}
return;
}
#endif // MAPBASE
Vector vecAim = BaseClass::GetAutoaimVector( AUTOAIM_SCALE_DIRECT_ONLY ); Vector vecAim = BaseClass::GetAutoaimVector( AUTOAIM_SCALE_DIRECT_ONLY );
const float CHECK_FRIENDLY_RANGE = 50 * 12; const float CHECK_FRIENDLY_RANGE = 50 * 12;

View File

@ -49,7 +49,7 @@ BEGIN_DATADESC( CVGuiScreen )
DEFINE_INPUTFUNC(FIELD_VOID, "SetActive", InputSetActive), DEFINE_INPUTFUNC(FIELD_VOID, "SetActive", InputSetActive),
DEFINE_INPUTFUNC(FIELD_VOID, "SetInactive", InputSetInactive), DEFINE_INPUTFUNC(FIELD_VOID, "SetInactive", InputSetInactive),
END_DATADESC() END_DATADESC();
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -75,6 +75,24 @@ bool CVGuiScreen::KeyValue( const char *szKeyName, const char *szValue )
*s = '\0'; *s = '\0';
} }
#ifdef MAPBASE
// Named command outputs
if (szKeyName[0] == '~' && szKeyName[1])
{
const char* pszOutputName = szKeyName + 1;
int i = m_PanelOutputs.Find(pszOutputName);
if (!m_PanelOutputs.IsValidIndex(i))
{
auto pMem = new COutputEvent;
V_memset(pMem, 0, sizeof(COutputEvent));
i = m_PanelOutputs.Insert(pszOutputName, pMem);
}
m_PanelOutputs[i]->ParseEventAction(szValue);
return true;
}
#endif // MAPBASE
if ( FStrEq( szKeyName, "panelname" )) if ( FStrEq( szKeyName, "panelname" ))
{ {
SetPanelName( szValue ); SetPanelName( szValue );
@ -158,6 +176,95 @@ void CVGuiScreen::OnRestore()
BaseClass::OnRestore(); BaseClass::OnRestore();
} }
#ifdef MAPBASE
CVGuiScreen::~CVGuiScreen()
{
m_PanelOutputs.PurgeAndDeleteElements();
}
int CVGuiScreen::Save(ISave& save)
{
int status = BaseClass::Save(save);
if (!status)
return 0;
const int iCount = m_PanelOutputs.Count();
save.WriteInt(&iCount);
for (int i = 0; i < iCount; i++)
{
CBaseEntityOutput* output = m_PanelOutputs[i];
const int nElems = output->NumberOfElements();
save.WriteString(m_PanelOutputs.GetElementName(i));
save.WriteInt(&nElems);
if (!output->Save(save))
return 0;
}
return status;
}
int CVGuiScreen::Restore(IRestore& restore)
{
int status = BaseClass::Restore(restore);
if (!status)
return 0;
const int iCount = restore.ReadInt();
m_PanelOutputs.EnsureCapacity(iCount);
for (int i = 0; i < iCount; i++)
{
char cName[MAX_KEY];
restore.ReadString(cName, MAX_KEY, 0);
const int iIndex = m_PanelOutputs.Insert(cName, new COutputEvent);
const int nElems = restore.ReadInt();
if (!m_PanelOutputs[iIndex]->Restore(restore, nElems))
return 0;
}
return status;
}
// Handle a command from the client-side vgui panel.
bool CVGuiScreen::HandleEntityCommand(CBasePlayer* pClient, KeyValues* pKeyValues)
{
#if defined(HL2MP) // Enable this in multiplayer.
// Restrict to commands from our owning player.
if ((m_fScreenFlags & VGUI_SCREEN_ONLY_USABLE_BY_OWNER) && pClient != m_hPlayerOwner.Get())
return false;
#endif
// Give the owning entity a chance to handle the command.
if (GetOwnerEntity() && GetOwnerEntity()->HandleEntityCommand(pClient, pKeyValues))
return true;
// See if we have an output for this command.
const int i = m_PanelOutputs.Find(pKeyValues->GetString());
if (m_PanelOutputs.IsValidIndex(i))
{
variant_t Val;
Val.Set(FIELD_VOID, NULL);
m_PanelOutputs[i]->FireOutput(Val, pClient, this);
return true;
}
return false;
}
CBaseEntityOutput* CVGuiScreen::FindNamedOutput(const char* pszOutput)
{
if (pszOutput && pszOutput[0] == '~' && pszOutput[1])
{
const int i = m_PanelOutputs.Find(pszOutput + 1);
if (m_PanelOutputs.IsValidIndex(i))
return m_PanelOutputs[i];
return NULL;
}
return BaseClass::FindNamedOutput(pszOutput);
}
#endif // MAPBASE
void CVGuiScreen::SetAttachmentIndex( int nIndex ) void CVGuiScreen::SetAttachmentIndex( int nIndex )
{ {
m_nAttachmentIndex = nIndex; m_nAttachmentIndex = nIndex;

View File

@ -32,6 +32,15 @@ public:
virtual void Activate(); virtual void Activate();
virtual void OnRestore(); virtual void OnRestore();
#ifdef MAPBASE
~CVGuiScreen();
virtual int Save(ISave& save);
virtual int Restore(IRestore& restore);
virtual bool HandleEntityCommand(CBasePlayer* pClient, KeyValues* pKeyValues);
virtual CBaseEntityOutput* FindNamedOutput(const char* pszOutput);
#endif // MAPBASE
const char *GetPanelName() const; const char *GetPanelName() const;
// Sets the screen size + resolution // Sets the screen size + resolution
@ -75,6 +84,10 @@ private:
CNetworkVar( int, m_fScreenFlags ); CNetworkVar( int, m_fScreenFlags );
CNetworkVar( EHANDLE, m_hPlayerOwner ); CNetworkVar( EHANDLE, m_hPlayerOwner );
#ifdef MAPBASE
CUtlDict<CBaseEntityOutput*> m_PanelOutputs;
#endif // MAPBASE
friend CVGuiScreen *CreateVGuiScreen( const char *pScreenClassname, const char *pScreenType, CBaseEntity *pAttachedTo, CBaseEntity *pOwner, int nAttachmentIndex ); friend CVGuiScreen *CreateVGuiScreen( const char *pScreenClassname, const char *pScreenType, CBaseEntity *pAttachedTo, CBaseEntity *pOwner, int nAttachmentIndex );
}; };

View File

@ -963,3 +963,28 @@ CTacticalMissionManager *CGameRules::TacticalMissionManagerFactory( void )
} }
#endif #endif
#ifdef MAPBASE
void CGameRules::ClientCommandKeyValues(edict_t* pEntity, KeyValues* pKeyValues)
{
#ifndef CLIENT_DLL
static int s_nEntityCommandSymbol = KeyValues::CallGetSymbolForString("EntityCommand");
static int s_nEntIndexSymbol = KeyValues::CallGetSymbolForString("entindex");
static int s_nCommandDataSymbol = KeyValues::CallGetSymbolForString("command_data");
CBasePlayer* pPlayer = (CBasePlayer*)GetContainingEntity(pEntity);
if (!pPlayer)
return;
if (pKeyValues->GetNameSymbol() == s_nEntityCommandSymbol)
{
CBaseEntity* pEntity = CBaseEntity::Instance(pKeyValues->GetInt(s_nEntIndexSymbol));
KeyValues* pkvCommand = pKeyValues->FindKey(s_nCommandDataSymbol);
if (pEntity && pkvCommand)
{
pEntity->HandleEntityCommand(pPlayer, pkvCommand);
}
}
#endif // GAME_DLL
}
#endif // MAPBASE

View File

@ -178,7 +178,12 @@ public:
//Allow thirdperson camera. //Allow thirdperson camera.
virtual bool AllowThirdPersonCamera( void ) { return false; } virtual bool AllowThirdPersonCamera( void ) { return false; }
#ifdef MAPBASE
virtual void ClientCommandKeyValues(edict_t* pEntity, KeyValues* pKeyValues);
#else
virtual void ClientCommandKeyValues(edict_t* pEntity, KeyValues* pKeyValues) {} virtual void ClientCommandKeyValues(edict_t* pEntity, KeyValues* pKeyValues) {}
#endif // MAPBASE
// IsConnectedUserInfoChangeAllowed allows the clients to change // IsConnectedUserInfoChangeAllowed allows the clients to change
// cvars with the FCVAR_NOT_CONNECTED rule if it returns true // cvars with the FCVAR_NOT_CONNECTED rule if it returns true

View File

@ -43,6 +43,10 @@
#define IN_GRENADE2 (1 << 24) // grenade 2 #define IN_GRENADE2 (1 << 24) // grenade 2
#define IN_ATTACK3 (1 << 25) #define IN_ATTACK3 (1 << 25)
#ifdef MAPBASE
#define IN_VGUIMODE (1 << 26)
#endif // MAPBASE
#ifdef VGUI_SCREEN_FIX #ifdef VGUI_SCREEN_FIX
#define IN_VALIDVGUIINPUT (1 << 23) //bitflag for vgui fix #define IN_VALIDVGUIINPUT (1 << 23) //bitflag for vgui fix
#endif #endif