Mapbase v5.0
- Added keyvalue to hl2_gamerules which allows respawning in singleplayer
- Added the game instructor system (including env_instructor_hint) from later Valve games using a VDC tutorial which adjusts the version from the Alien Swarm SDK to FPS rules and a Source 2013 environment; Also added new KV and icons for further control from mappers (tutorial mentioned by Maestra Fenix)
- Added L4D/TF2 glows + point_glow entity as an all-purpose SDK-based off-shoot of tf_glow
- Fixed weapon pickup sound not playing (reported by Sl0th and later Cvoxulary)
- Fixed env_projectedtextures not updating on save/load
- Added func_fake_worldportal, a spatial point_camera inspired by linked_portal_door based on SDK code alone (WIP, may be changed a lot in future updates)
- Added option for point_camera and func_reflective_glass to use different render targets, therefore allowing multiple cameras and mirrors to be active at the same time
- Added additional RT camera textures to choose from with a default of 3, but also controllable through a -numcameratextures command line param
- Added adjustable convars for main view NearZ and skybox NearZ (suggested by someone recently, also suggested by Klems over a year ago)
- Fixed map-specific localization files, cleaned up map-specific file code
- Added a new block to gameinfo.txt which allows mods to automatically append their own command line parameters
- Fixed math_lightpattern corruption when setting pattern/style while active
- Fixed the "Touch" input crashing when given no entity
- Added a way to add EFlags via keyvalue (suggested by Niker107)
- Fixed ai_script_conditions not working without a NPC actor (reported by MetroHam)
- Fixed point_radiation_source causing huge problems when intensity is 0, even though it was already advised against (reported by beefbacon)
- Added "Mapbase" header to Mapbase-specific code files
- Fixed an issue with updating sky_camera not obtaining area correctly, causing some entities to not draw in the skybox
- Added "CopyFogController" and "CopyFogControllerWithScale" inputs to sky_camera, which copy fog parameters directly from a fog controller
- Added "SetScale" input to sky_camera for live scale changing
- Added convar to control player crouch speed multiplier (suggested by ArtyIF)
- Added a ton of fixes for people running the Debug configuration of the codebase (partial credit to stepa2)
- Added support for pre-defined enums and constants in VScript, starting with various values from the SDK code (damage types, trace masks, etc.)
- Added limited support for Valve's Quaternion class in VScript
- Added new instance helper capabilities, destructible game instances, and other misc. changes to VScript library
- Replaced most of the VScript "accessor" classes with direct references to the original classes, as they were getting complicated fast and adding new VScript-only functions to the original classes might not be as bad as previously thought
- Added base NPC hooks for AI sensing in VScript (allows control over sight and hearing), also exposed CSound for it
- Added various functions and hooks for VPhysics integration in VScript
- Added VScript-based custom suit devices
- Expanded trace info exposed to VScript to allow plane and surface access (suggested by krassell)
- Added ability to insert localization strings through VScript
- Added various misc. VScript functions with various purposes, including reading/writing EFlags, movetypes, collision groups, etc.
- Fixed VBSP not being able to correctly parse parallax corrected cubemaps in maps with instances
2020-08-14 21:21:25 +00:00
//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============//
2019-08-31 19:28:20 +00:00
//
// Purpose: A ballsier version of point_entity_finder.
// Originally called logic_entityfinder because a lot of this was written
// before I knew about point_entity_finder in the first place.
//
//=============================================================================
# include "cbase.h"
# include "eventqueue.h"
# include "filters.h"
# include "saverestore_utlvector.h"
// Uses a CUtlVector instead of an array.
# define ENTITYFINDER_UTLVECTOR 1
// Delays outputs directly instead of relying on an input.
# define ENTITYFINDER_OUTPUT_DELAY 1
# if !ENTITYFINDER_STATIC_ARRAY
# define ENTITYFINDER_MAX_STORED_ENTITIES 64
# endif
//-----------------------------------------------------------------------------
// Purpose: Entity finder that uses filters and other criteria to search the level for a specific entity.
//-----------------------------------------------------------------------------
class CPointAdvancedFinder : public CLogicalEntity
{
DECLARE_CLASS ( CPointAdvancedFinder , CLogicalEntity ) ;
private :
// Inputs
void InputSearch ( inputdata_t & inputdata ) ;
void InputSetSearchFilter ( inputdata_t & inputdata ) ;
void InputSetSearchPoint ( inputdata_t & inputdata ) ;
void InputSetRadius ( inputdata_t & inputdata ) { m_flRadius = inputdata . value . Float ( ) ; }
void InputSetMaxResults ( inputdata_t & inputdata ) { m_iNumSearches = inputdata . value . Int ( ) ; }
void InputSetOutputDelay ( inputdata_t & inputdata ) { m_flOutputDelay = inputdata . value . Float ( ) ; }
void InputSetFiringMethod ( inputdata_t & inputdata ) { m_iFiringMethod = inputdata . value . Int ( ) ; }
# ifndef ENTITYFINDER_OUTPUT_DELAY
void InputFoundEntity ( inputdata_t & inputdata ) ;
# endif
void Spawn ( ) ;
Vector GetSearchOrigin ( ) ;
bool SearchForEntities ( inputdata_t & inputdata ) ;
void FoundEntity ( CBaseEntity * pEntity , inputdata_t & inputdata ) ;
string_t m_iszSearchFilter ;
CHandle < CBaseFilter > m_hSearchFilter ;
string_t m_iszSearchPoint ;
EHANDLE m_hSearchPoint ;
float m_flRadius ;
int m_iNumSearches ;
int m_iFiringMethod ;
enum
{
FIRINGMETHOD_NONE = - 1 , // -1 for point_entity_finder compatibility
FIRINGMETHOD_NEAREST ,
FIRINGMETHOD_FARTHEST ,
FIRINGMETHOD_RANDOM ,
} ;
float m_flOutputDelay ;
float m_flLastOutputDelay = 0.0f ;
# if ENTITYFINDER_UTLVECTOR
CUtlVector < CBaseEntity * > m_StoredEntities ;
# else
CBaseEntity * m_StoredEntities [ ENTITYFINDER_MAX_STORED_ENTITIES ] ;
# endif
// Outputs
COutputEHANDLE m_OnFoundEntity ;
COutputEvent m_OnSearchFailed ;
DECLARE_DATADESC ( ) ;
} ;
LINK_ENTITY_TO_CLASS ( point_advanced_finder , CPointAdvancedFinder ) ;
BEGIN_DATADESC ( CPointAdvancedFinder )
// Keys
DEFINE_KEYFIELD ( m_iszSearchFilter , FIELD_STRING , " SearchFilter " ) ,
DEFINE_FIELD ( m_hSearchFilter , FIELD_EHANDLE ) ,
DEFINE_KEYFIELD ( m_iszSearchPoint , FIELD_STRING , " SearchPoint " ) ,
DEFINE_FIELD ( m_hSearchPoint , FIELD_EHANDLE ) ,
DEFINE_KEYFIELD ( m_flRadius , FIELD_FLOAT , " radius " ) ,
DEFINE_KEYFIELD ( m_iNumSearches , FIELD_INTEGER , " NumberOfEntities " ) ,
DEFINE_KEYFIELD ( m_flOutputDelay , FIELD_FLOAT , " OutputDelay " ) ,
DEFINE_KEYFIELD ( m_iFiringMethod , FIELD_INTEGER , " Method " ) ,
# if ENTITYFINDER_UTLVECTOR
DEFINE_UTLVECTOR ( m_StoredEntities , FIELD_CLASSPTR ) ,
# else
DEFINE_ARRAY ( m_StoredEntities , FIELD_CLASSPTR , ENTITYFINDER_MAX_STORED_ENTITIES ) ,
# endif
DEFINE_FIELD ( m_flLastOutputDelay , FIELD_FLOAT ) ,
// Inputs
DEFINE_INPUTFUNC ( FIELD_VOID , " BeginSearch " , InputSearch ) ,
DEFINE_INPUTFUNC ( FIELD_STRING , " SetSearchFilter " , InputSetSearchFilter ) ,
DEFINE_INPUTFUNC ( FIELD_STRING , " SetSearchPoint " , InputSetSearchPoint ) ,
DEFINE_INPUTFUNC ( FIELD_FLOAT , " SetRadius " , InputSetRadius ) ,
DEFINE_INPUTFUNC ( FIELD_INTEGER , " SetMaxResults " , InputSetMaxResults ) ,
DEFINE_INPUTFUNC ( FIELD_FLOAT , " SetOutputDelay " , InputSetOutputDelay ) ,
DEFINE_INPUTFUNC ( FIELD_INTEGER , " SetFiringMethod " , InputSetFiringMethod ) ,
# ifndef ENTITYFINDER_OUTPUT_DELAY
DEFINE_INPUTFUNC ( FIELD_EHANDLE , " FoundEntity " , InputFoundEntity ) ,
# endif
// Outputs
DEFINE_OUTPUT ( m_OnFoundEntity , " OnFoundEntity " ) ,
DEFINE_OUTPUT ( m_OnSearchFailed , " OnSearchFailed " ) ,
END_DATADESC ( )
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CPointAdvancedFinder : : Spawn ( )
{
if ( m_iszSearchFilter = = NULL_STRING )
{
Warning ( " %s (%s) has no search filter! \n " , GetClassname ( ) , GetDebugName ( ) ) ;
UTIL_Remove ( this ) ;
return ;
}
m_hSearchFilter = dynamic_cast < CBaseFilter * > ( gEntList . FindEntityByName ( NULL , m_iszSearchFilter , this ) ) ;
m_hSearchPoint = gEntList . FindEntityByName ( NULL , m_iszSearchPoint , this ) ;
BaseClass : : Spawn ( ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CPointAdvancedFinder : : InputSearch ( inputdata_t & inputdata )
{
SearchForEntities ( inputdata ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CPointAdvancedFinder : : InputSetSearchFilter ( inputdata_t & inputdata )
{
m_iszSearchFilter = inputdata . value . StringID ( ) ;
m_hSearchFilter = dynamic_cast < CBaseFilter * > ( gEntList . FindEntityByName ( NULL , m_iszSearchFilter , this , inputdata . pActivator , inputdata . pCaller ) ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CPointAdvancedFinder : : InputSetSearchPoint ( inputdata_t & inputdata )
{
m_iszSearchPoint = inputdata . value . StringID ( ) ;
m_hSearchPoint = gEntList . FindEntityByName ( NULL , m_iszSearchPoint , this , inputdata . pActivator , inputdata . pCaller ) ;
}
# ifndef ENTITYFINDER_OUTPUT_DELAY
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CPointAdvancedFinder : : InputFoundEntity ( inputdata_t & inputdata )
{
CBaseEntity * pEntity = inputdata . value . Entity ( ) ;
if ( ! pEntity )
return ;
m_OnFoundEntity . Set ( pEntity , pEntity , inputdata . pCaller ) ;
}
# endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
inline Vector CPointAdvancedFinder : : GetSearchOrigin ( )
{
if ( m_hSearchPoint = = NULL )
m_hSearchPoint = this ;
return m_hSearchPoint - > GetAbsOrigin ( ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CPointAdvancedFinder : : SearchForEntities ( inputdata_t & inputdata )
{
if ( ! m_hSearchFilter )
return false ;
m_flLastOutputDelay = 0.0f ;
int iNumResults = 0 ;
float flRadius = m_flRadius * m_flRadius ;
bool bShouldStoreEntities = ( m_iFiringMethod > FIRINGMETHOD_NONE | | m_flOutputDelay > 0 ) ;
# if !ENTITYFINDER_UTLVECTOR
if ( bShouldStoreEntities )
{
if ( m_iNumSearches > ENTITYFINDER_MAX_STORED_ENTITIES )
{
Warning ( " %s (%s) needs to store entities, but we're asked to look for more than the maximum, %i, with %i! Reducing to max... \n " , GetClassname ( ) , GetDebugName ( ) , ENTITYFINDER_MAX_STORED_ENTITIES , m_iNumSearches ) ;
m_iNumSearches = ENTITYFINDER_MAX_STORED_ENTITIES ;
}
else if ( m_iNumSearches = = 0 )
{
m_iNumSearches = ENTITYFINDER_MAX_STORED_ENTITIES ;
}
}
else
# endif
if ( m_iNumSearches = = 0 )
{
m_iNumSearches = MAX_EDICTS ;
}
const CEntInfo * pInfo = gEntList . FirstEntInfo ( ) ;
for ( ; pInfo ; pInfo = pInfo - > m_pNext )
{
CBaseEntity * ent = ( CBaseEntity * ) pInfo - > m_pEntity ;
if ( ! ent )
{
DevWarning ( " NULL entity in global entity list! \n " ) ;
continue ;
}
if ( iNumResults > = m_iNumSearches )
break ;
if ( m_hSearchFilter & & ! m_hSearchFilter - > PassesFilter ( this , ent ) )
continue ;
if ( flRadius > 0 & & ( ent - > GetAbsOrigin ( ) - GetSearchOrigin ( ) ) . LengthSqr ( ) > flRadius )
continue ;
if ( bShouldStoreEntities )
{
// Fire it later
# if ENTITYFINDER_UTLVECTOR
m_StoredEntities . AddToTail ( ent ) ;
# else
m_StoredEntities [ iNumResults ] = ent ;
# endif
}
else
{
// Fire it now
FoundEntity ( ent , inputdata ) ;
}
iNumResults + + ;
}
if ( iNumResults > 0 )
{
if ( bShouldStoreEntities )
{
if ( m_iFiringMethod = = FIRINGMETHOD_NEAREST | | m_iFiringMethod = = FIRINGMETHOD_FARTHEST )
{
bool bNotFarthest = m_iFiringMethod ! = FIRINGMETHOD_FARTHEST ;
float flMaxDist = m_flRadius ;
float flMinDist = 0 ;
if ( flMaxDist = = 0 )
flMaxDist = MAX_TRACE_LENGTH ;
for ( int iCur = 0 ; iCur < iNumResults ; iCur + + )
{
float flClosest = bNotFarthest ? flMaxDist : 0 ;
float flDistance = 0 ;
CBaseEntity * pClosest = NULL ;
for ( int i = 0 ; i < iNumResults ; i + + )
{
if ( ! m_StoredEntities [ i ] )
continue ;
flDistance = ( m_StoredEntities [ i ] - > GetAbsOrigin ( ) - GetSearchOrigin ( ) ) . Length ( ) ;
if ( flDistance < flMaxDist & & flDistance > flMinDist )
{
if ( bNotFarthest ? ( flDistance < flClosest ) : ( flDistance > flClosest ) )
{
pClosest = m_StoredEntities [ i ] ;
flClosest = flDistance ;
}
}
}
if ( pClosest )
{
bNotFarthest ? flMinDist = flClosest : flMaxDist = flClosest ;
FoundEntity ( pClosest , inputdata ) ;
}
else
{
DevWarning ( " %s (%s): NO CLOSEST!!! \n " , GetClassname ( ) , GetDebugName ( ) ) ;
}
}
}
else if ( m_iFiringMethod = = FIRINGMETHOD_RANDOM )
{
// This could probaly be better...
CUtlVector < int > iResultIndices ;
for ( int i = 0 ; i < iNumResults ; i + + )
iResultIndices . AddToTail ( i ) ;
while ( iResultIndices . Count ( ) > 0 )
{
int index = iResultIndices [ RandomInt ( 0 , iResultIndices . Count ( ) - 1 ) ] ;
if ( m_StoredEntities [ index ] )
{
FoundEntity ( m_StoredEntities [ index ] , inputdata ) ;
}
else
{
DevWarning ( " %s (%s): Found entity is null: %i \n " , GetClassname ( ) , GetDebugName ( ) , index ) ;
}
iResultIndices . FindAndRemove ( index ) ;
}
}
else if ( m_iFiringMethod = = FIRINGMETHOD_NONE )
{
for ( int i = 0 ; i < iNumResults ; i + + )
{
if ( m_StoredEntities [ i ] )
{
FoundEntity ( m_StoredEntities [ i ] , inputdata ) ;
}
else
{
DevWarning ( " %s (%s): Found entity is null: %i \n " , GetClassname ( ) , GetDebugName ( ) , i ) ;
}
}
}
m_StoredEntities . RemoveAll ( ) ;
}
return true ;
}
else
{
m_OnSearchFailed . FireOutput ( inputdata . pActivator , inputdata . pCaller ) ;
return false ;
}
return false ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CPointAdvancedFinder : : FoundEntity ( CBaseEntity * pEntity , inputdata_t & inputdata )
{
# ifdef ENTITYFINDER_OUTPUT_DELAY
variant_t variant ;
variant . SetEntity ( pEntity ) ;
DevMsg ( " %s (%s): Firing entity output in %f, added from %f \n " , GetClassname ( ) , GetDebugName ( ) , m_flLastOutputDelay , m_flOutputDelay ) ;
m_OnFoundEntity . FireOutput ( variant , pEntity , this , m_flLastOutputDelay ) ;
# else
if ( m_flOutputDelay = = 0 )
{
// Just fire it now
m_OnFoundEntity . Set ( pEntity , pEntity , inputdata . pCaller ) ;
DevMsg ( " %s (%s): Delay 0, firing now \n " , GetClassname ( ) , GetDebugName ( ) ) ;
return ;
}
//if (m_flLastOutputDelay == 0)
//m_flLastOutputDelay = gpGlobals->curtime;
variant_t variant ;
variant . SetEntity ( pEntity ) ;
DevMsg ( " %s (%s): Firing entity output in %f, added from %f \n " , GetClassname ( ) , GetDebugName ( ) , m_flLastOutputDelay , m_flOutputDelay ) ;
g_EventQueue . AddEvent ( this , " FoundEntity " , variant , m_flLastOutputDelay , inputdata . pActivator , inputdata . pCaller ) ;
# endif
m_flLastOutputDelay + = m_flOutputDelay ;
}