From b95c72eb3fb8db4efeb0c0d47f57bad68ec5c1ed Mon Sep 17 00:00:00 2001 From: Alexander 'z33ky' Hirsch <1zeeky@gmail.com> Date: Thu, 29 Apr 2021 18:06:36 +0200 Subject: [PATCH 1/5] Fix viewmodel flip on zoom The fabs() was incorrectly applied only to the viewmodel's FOV instead of the result of that subtracted by the FOV offset. Further it doesn't seem to make sense to use the absolute value of that subtraction; Yes, it does prevent flipping, but it will zoom out again as the FOV decreases. Instead just limit the result of the subtraction to non-negative numbers. --- sp/src/game/client/view.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sp/src/game/client/view.cpp b/sp/src/game/client/view.cpp index 21294735..c78c76fd 100644 --- a/sp/src/game/client/view.cpp +++ b/sp/src/game/client/view.cpp @@ -745,7 +745,7 @@ void CViewRender::SetUpViews() //Adjust the viewmodel's FOV to move with any FOV offsets on the viewer's end #ifdef MAPBASE - view.fovViewmodel = fabs(g_pClientMode->GetViewModelFOV()) - flFOVOffset; + view.fovViewmodel = max(0.001f, g_pClientMode->GetViewModelFOV() - flFOVOffset); #else view.fovViewmodel = g_pClientMode->GetViewModelFOV() - flFOVOffset; #endif From 06c7f7040d1219adea59a66eb0bf086d52a48bf5 Mon Sep 17 00:00:00 2001 From: Alexander 'z33ky' Hirsch <1zeeky@gmail.com> Date: Thu, 29 Apr 2021 18:41:50 +0200 Subject: [PATCH 2/5] Fix env_instructor_hint from disappearing after savegame load It is a bit unfortunate that the initial animation plays again after load. This is likely not fixable with SDK code without reimplementing the HUD bits, which are part of the external engine code. Also adds a destructor override, since we are dealing with a polymorphic class. --- sp/src/game/server/env_instructor_hint.cpp | 92 +++++++++++++++++++++- 1 file changed, 89 insertions(+), 3 deletions(-) diff --git a/sp/src/game/server/env_instructor_hint.cpp b/sp/src/game/server/env_instructor_hint.cpp index 32b75041..20b2379c 100644 --- a/sp/src/game/server/env_instructor_hint.cpp +++ b/sp/src/game/server/env_instructor_hint.cpp @@ -26,6 +26,15 @@ public: DECLARE_CLASS( CEnvInstructorHint, CPointEntity ); DECLARE_DATADESC(); +#ifdef MAPBASE + CEnvInstructorHint( void ); +#endif + virtual ~CEnvInstructorHint( void ) {} + +#ifdef MAPBASE + virtual void OnRestore( void ); +#endif + private: void InputShowHint( inputdata_t &inputdata ); void InputEndHint( inputdata_t &inputdata ); @@ -56,6 +65,10 @@ private: #ifdef MAPBASE string_t m_iszStartSound; int m_iHintTargetPos; + float m_flActiveUntil; + CHandle m_hActivator; + EHANDLE m_hTarget; + bool m_bFilterByActivator; #endif }; @@ -85,8 +98,13 @@ BEGIN_DATADESC( CEnvInstructorHint ) #ifdef MAPBASE DEFINE_KEYFIELD( m_iszStartSound, FIELD_STRING, "hint_start_sound" ), DEFINE_KEYFIELD( m_iHintTargetPos, FIELD_INTEGER, "hint_target_pos" ), + + DEFINE_FIELD( m_flActiveUntil, FIELD_TIME ), + DEFINE_FIELD( m_hActivator, FIELD_EHANDLE ), + DEFINE_FIELD( m_hTarget, FIELD_EHANDLE ), + DEFINE_FIELD( m_bFilterByActivator, FIELD_BOOLEAN ), #endif - + DEFINE_INPUTFUNC( FIELD_STRING, "ShowHint", InputShowHint ), DEFINE_INPUTFUNC( FIELD_VOID, "EndHint", InputEndHint ), @@ -102,6 +120,43 @@ END_DATADESC() #define LOCATOR_ICON_FX_SHAKE_NARROW 0x00000040 #define LOCATOR_ICON_FX_STATIC 0x00000100 // This icon draws at a fixed location on the HUD. +#ifdef MAPBASE +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +CEnvInstructorHint::CEnvInstructorHint( void ) +{ + m_hActivator = NULL; + m_hTarget = NULL; + m_bFilterByActivator = false; + m_flActiveUntil = -1.0f; +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void CEnvInstructorHint::OnRestore( void ) +{ + int iTimeLeft = 0; + if ( m_flActiveUntil < 0.0f ) + { + return; + } + if ( m_iTimeout != 0 ) + { + iTimeLeft = static_cast( m_flActiveUntil - gpGlobals->curtime ); + if ( iTimeLeft <= 0 ) + { + return; + } + } + + int iOriginalTimeout = m_iTimeout; + m_iTimeout = iTimeLeft; + inputdata_t inputdata; + InputShowHint( inputdata ); + m_iTimeout = iOriginalTimeout; +} +#endif + //----------------------------------------------------------------------------- // Purpose: Input handler for showing the message and/or playing the sound. //----------------------------------------------------------------------------- @@ -110,7 +165,15 @@ void CEnvInstructorHint::InputShowHint( inputdata_t &inputdata ) IGameEvent * event = gameeventmanager->CreateEvent( "instructor_server_hint_create", false ); if ( event ) { - CBaseEntity *pTargetEntity = gEntList.FindEntityByName( NULL, m_iszHintTargetEntity ); + CBaseEntity *pTargetEntity = NULL; + +#ifdef MAPBASE + pTargetEntity = m_hTarget; + + if ( pTargetEntity == NULL ) +#endif + pTargetEntity = gEntList.FindEntityByName( NULL, m_iszHintTargetEntity ); + if( pTargetEntity == NULL && !m_bStatic ) pTargetEntity = inputdata.pActivator; @@ -137,6 +200,15 @@ void CEnvInstructorHint::InputShowHint( inputdata_t &inputdata ) pActivator = pMarine->GetCommander(); } #else +#ifdef MAPBASE + if ( m_hActivator ) + { + pActivator = m_hActivator; + bFilterByActivator = m_bFilterByActivator; + } + else +#endif + if ( inputdata.value.StringID() != NULL_STRING ) { CBaseEntity *pTarget = gEntList.FindEntityByName( NULL, inputdata.value.String() ); @@ -150,7 +222,7 @@ void CEnvInstructorHint::InputShowHint( inputdata_t &inputdata ) { if ( GameRules()->IsMultiplayer() == false ) { - pActivator = UTIL_GetLocalPlayer(); + pActivator = UTIL_GetLocalPlayer(); } else { @@ -190,6 +262,13 @@ void CEnvInstructorHint::InputShowHint( inputdata_t &inputdata ) #endif gameeventmanager->FireEvent( event ); + +#ifdef MAPBASE + m_flActiveUntil = gpGlobals->curtime + m_iTimeout; + m_hTarget = pTargetEntity; + m_hActivator = pActivator; + m_bFilterByActivator = bFilterByActivator; +#endif } } @@ -203,6 +282,13 @@ void CEnvInstructorHint::InputEndHint( inputdata_t &inputdata ) event->SetString( "hint_name", GetEntityName().ToCStr() ); gameeventmanager->FireEvent( event ); + +#ifdef MAPBASE + m_flActiveUntil = -1.0f; + m_hActivator = NULL; + m_hTarget = NULL; + m_bFilterByActivator = false; +#endif } } From f6a750e4b326fe3069f3ca41d7eba483a4b97d9c Mon Sep 17 00:00:00 2001 From: Alexander 'z33ky' Hirsch <1zeeky@gmail.com> Date: Sun, 6 Jun 2021 15:52:35 +0200 Subject: [PATCH 3/5] Initialize all basis vectors for env_projectedtexture with target --- sp/src/game/client/c_env_projectedtexture.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sp/src/game/client/c_env_projectedtexture.cpp b/sp/src/game/client/c_env_projectedtexture.cpp index a74bb46e..7bd15a17 100644 --- a/sp/src/game/client/c_env_projectedtexture.cpp +++ b/sp/src/game/client/c_env_projectedtexture.cpp @@ -283,6 +283,8 @@ void C_EnvProjectedTexture::UpdateLight( void ) // VectorNormalize( vRight ); // VectorNormalize( vUp ); + + VectorVectors( vForward, vRight, vUp ); } } else From e989cf63c52a3dc8ee5e87e3a59dced180f47dea Mon Sep 17 00:00:00 2001 From: Alexander 'z33ky' Hirsch <1zeeky@gmail.com> Date: Sun, 6 Jun 2021 15:57:05 +0200 Subject: [PATCH 4/5] Fix ReadFileEx() arguments when loading scene files The parser expects NUL terminated data. --- sp/src/game/server/sceneentity.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sp/src/game/server/sceneentity.cpp b/sp/src/game/server/sceneentity.cpp index fc332249..67ca064a 100644 --- a/sp/src/game/server/sceneentity.cpp +++ b/sp/src/game/server/sceneentity.cpp @@ -4298,7 +4298,7 @@ const char *GetFirstSoundInScene(const char *pszScene) else { void *pBuffer = NULL; - if (filesystem->ReadFileEx( pszScene, "MOD", &pBuffer, false, true )) + if (filesystem->ReadFileEx( pszScene, "MOD", &pBuffer, true )) { g_TokenProcessor.SetBuffer((char*)pBuffer); CChoreoScene *pScene = ChoreoLoadScene( pszScene, NULL, &g_TokenProcessor, LocalScene_Printf ); @@ -5284,7 +5284,7 @@ int GetSceneSpeechCount( char const *pszScene ) else { void *pBuffer = NULL; - if (filesystem->ReadFileEx( pszScene, "MOD", &pBuffer, false, true )) + if (filesystem->ReadFileEx( pszScene, "MOD", &pBuffer, true )) { int iNumSounds = 0; @@ -5359,7 +5359,7 @@ void PrecacheInstancedScene( char const *pszScene ) // Attempt to precache manually void *pBuffer = NULL; - if (filesystem->ReadFileEx( loadfile, "MOD", &pBuffer, false, true )) + if (filesystem->ReadFileEx( loadfile, "MOD", &pBuffer, true )) { g_TokenProcessor.SetBuffer((char*)pBuffer); CChoreoScene *pScene = ChoreoLoadScene( loadfile, NULL, &g_TokenProcessor, LocalScene_Printf ); From b41d49c639d3a1a5042a24618169c0714e167df7 Mon Sep 17 00:00:00 2001 From: Alexander 'z33ky' Hirsch <1zeeky@gmail.com> Date: Sun, 6 Jun 2021 16:08:39 +0200 Subject: [PATCH 5/5] Fix scene file loading memory errors Fixes leaks. Also safeguards against deallocated pointers by doing g_TokenProcessor.SetBuffer(NULL) after parsing is done - an access at NULL should be easier to debug than at some random address, potentially just reading in garbage data. --- sp/src/game/server/sceneentity.cpp | 31 +++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/sp/src/game/server/sceneentity.cpp b/sp/src/game/server/sceneentity.cpp index 67ca064a..5cef9cc0 100644 --- a/sp/src/game/server/sceneentity.cpp +++ b/sp/src/game/server/sceneentity.cpp @@ -3735,7 +3735,7 @@ CChoreoScene *CSceneEntity::LoadScene( const char *filename, IChoreoEventCallbac Q_FixSlashes( loadfile ); // binary compiled vcd - void *pBuffer; + void *pBuffer = NULL; #ifdef MAPBASE // // Raw scene file support @@ -3760,12 +3760,13 @@ CChoreoScene *CSceneEntity::LoadScene( const char *filename, IChoreoEventCallbac { g_TokenProcessor.SetBuffer((char*)pBuffer); pScene = ChoreoLoadScene( loadfile, NULL, &g_TokenProcessor, LocalScene_Printf ); + g_TokenProcessor.SetBuffer(NULL); } // Okay, it's definitely missing. else { MissingSceneWarning( loadfile ); - return NULL; + pScene = NULL; } if (pScene) @@ -4283,6 +4284,7 @@ CBaseEntity *CSceneEntity::FindNamedEntity( const char *name, CBaseEntity *pActo #ifdef MAPBASE const char *GetFirstSoundInScene(const char *pszScene) { + const char *soundName; SceneCachedData_t sceneData; if ( scenefilecache->GetSceneCachedData( pszScene, &sceneData ) ) { @@ -4292,7 +4294,7 @@ const char *GetFirstSoundInScene(const char *pszScene) short stringId = scenefilecache->GetSceneCachedSound( sceneData.sceneId, 0 ); // Trust that it's been precached - return scenefilecache->GetSceneString( stringId ); + soundName = scenefilecache->GetSceneString( stringId ); } } else @@ -4302,6 +4304,7 @@ const char *GetFirstSoundInScene(const char *pszScene) { g_TokenProcessor.SetBuffer((char*)pBuffer); CChoreoScene *pScene = ChoreoLoadScene( pszScene, NULL, &g_TokenProcessor, LocalScene_Printf ); + g_TokenProcessor.SetBuffer(NULL); if (pScene) { for (int i = 0; i < pScene->GetNumEvents(); i++) @@ -4309,13 +4312,17 @@ const char *GetFirstSoundInScene(const char *pszScene) CChoreoEvent *pEvent = pScene->GetEvent(i); if (pEvent->GetType() == CChoreoEvent::SPEAK) - return pEvent->GetParameters(); + { + soundName = pEvent->GetParameters(); + break; + } } } } + FreeSceneFileMemory( pBuffer ); } - return NULL; + return soundName; } const char *GetFirstSoundInScene(CChoreoScene *scene) @@ -4483,6 +4490,8 @@ bool CSceneEntity::ScriptLoadSceneFromString(const char* pszFilename, const char PrecacheScene(pScene); } + g_TokenProcessor.SetBuffer(NULL); + if (pScene != NULL) { // release prior scene if present @@ -5284,12 +5293,12 @@ int GetSceneSpeechCount( char const *pszScene ) else { void *pBuffer = NULL; + int iNumSounds = 0; if (filesystem->ReadFileEx( pszScene, "MOD", &pBuffer, true )) { - int iNumSounds = 0; - g_TokenProcessor.SetBuffer((char*)pBuffer); CChoreoScene *pScene = ChoreoLoadScene( pszScene, NULL, &g_TokenProcessor, LocalScene_Printf ); + g_TokenProcessor.SetBuffer(NULL); if (pScene) { for (int i = 0; i < pScene->GetNumEvents(); i++) @@ -5300,9 +5309,11 @@ int GetSceneSpeechCount( char const *pszScene ) iNumSounds++; } } - - return iNumSounds; } + + FreeSceneFileMemory( pBuffer ); + + return iNumSounds; } #endif return 0; @@ -5367,7 +5378,9 @@ void PrecacheInstancedScene( char const *pszScene ) { PrecacheChoreoScene(pScene); } + g_TokenProcessor.SetBuffer(NULL); } + FreeSceneFileMemory( pBuffer ); #else // Scenes are sloppy and don't always exist. // A scene that is not in the pre-built cache image, but on disk, is a true error.