mirror of
https://github.com/mapbase-source/source-sdk-2013.git
synced 2025-01-10 05:56:45 +03:00
c448f194ae
- 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
394 lines
12 KiB
C++
394 lines
12 KiB
C++
//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============//
|
|
//
|
|
// 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;
|
|
}
|