mirror of
https://github.com/mapbase-source/source-sdk-2013.git
synced 2024-12-26 06:45:31 +03:00
Merge branch 'develop' into feature/newer-toolsets
This commit is contained in:
commit
2dbd04e3d6
@ -784,6 +784,10 @@ C_BaseAnimating::C_BaseAnimating() :
|
||||
m_nPrevSequence = -1;
|
||||
m_nRestoreSequence = -1;
|
||||
m_pRagdoll = NULL;
|
||||
m_pClientsideRagdoll = NULL;
|
||||
#ifdef MAPBASE
|
||||
m_pServerRagdoll = NULL;
|
||||
#endif
|
||||
m_builtRagdoll = false;
|
||||
m_hitboxBoneCacheHandle = 0;
|
||||
int i;
|
||||
@ -1986,6 +1990,10 @@ CollideType_t C_BaseAnimating::GetCollideType( void )
|
||||
return BaseClass::GetCollideType();
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
ConVar ai_death_pose_enabled( "ai_death_pose_enabled", "1", FCVAR_NONE, "Toggles the death pose fix code, which cancels sequence transitions while a NPC is ragdolling." );
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: if the active sequence changes, keep track of the previous ones and decay them based on their decay rate
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -2002,6 +2010,14 @@ void C_BaseAnimating::MaintainSequenceTransitions( IBoneSetup &boneSetup, float
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( IsAboutToRagdoll() && ai_death_pose_enabled.GetBool() )
|
||||
{
|
||||
m_nPrevNewSequenceParity = m_nNewSequenceParity;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
m_SequenceTransitioner.CheckForSequenceChange(
|
||||
boneSetup.GetStudioHdr(),
|
||||
GetSequence(),
|
||||
@ -2781,14 +2797,29 @@ void C_BaseAnimating::CalculateIKLocks( float currentTime )
|
||||
|
||||
// debugoverlay->AddBoxOverlay( origin, Vector( -1, -1, -1 ), Vector( 1, 1, 1 ), QAngle( 0, 0, 0 ), 255, 0, 0, 0, 0 );
|
||||
|
||||
float d = (pTarget->est.pos - origin).Length();
|
||||
Vector vecDelta = (origin - pTarget->est.pos);
|
||||
float d = vecDelta.Length();
|
||||
|
||||
if ( d >= flDist)
|
||||
continue;
|
||||
|
||||
flDist = d;
|
||||
pTarget->SetPos( origin );
|
||||
pTarget->SetAngles( angles );
|
||||
#ifdef MAPBASE
|
||||
// For blending purposes, IK attachments should obey weight
|
||||
if ( pTarget->est.flWeight < 1.0f )
|
||||
{
|
||||
Quaternion qTarget;
|
||||
AngleQuaternion( angles, qTarget );
|
||||
|
||||
QuaternionSlerp( pTarget->est.q, qTarget, pTarget->est.flWeight, pTarget->est.q );
|
||||
pTarget->SetPos( pTarget->est.pos + (vecDelta * pTarget->est.flWeight) );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
pTarget->SetPos( origin );
|
||||
pTarget->SetAngles( angles );
|
||||
}
|
||||
// debugoverlay->AddBoxOverlay( pTarget->est.pos, Vector( -pTarget->est.radius, -pTarget->est.radius, -pTarget->est.radius ), Vector( pTarget->est.radius, pTarget->est.radius, pTarget->est.radius), QAngle( 0, 0, 0 ), 0, 255, 0, 0, 0 );
|
||||
}
|
||||
|
||||
@ -4948,26 +4979,26 @@ C_BaseAnimating *C_BaseAnimating::BecomeRagdollOnClient()
|
||||
{
|
||||
MoveToLastReceivedPosition( true );
|
||||
GetAbsOrigin();
|
||||
C_BaseAnimating *pRagdoll = CreateRagdollCopy();
|
||||
m_pClientsideRagdoll = CreateRagdollCopy();
|
||||
|
||||
matrix3x4_t boneDelta0[MAXSTUDIOBONES];
|
||||
matrix3x4_t boneDelta1[MAXSTUDIOBONES];
|
||||
matrix3x4_t currentBones[MAXSTUDIOBONES];
|
||||
const float boneDt = 0.1f;
|
||||
GetRagdollInitBoneArrays( boneDelta0, boneDelta1, currentBones, boneDt );
|
||||
pRagdoll->InitAsClientRagdoll( boneDelta0, boneDelta1, currentBones, boneDt );
|
||||
m_pClientsideRagdoll->InitAsClientRagdoll( boneDelta0, boneDelta1, currentBones, boneDt );
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
// Hook for ragdolling
|
||||
if (m_ScriptScope.IsInitialized() && g_Hook_OnClientRagdoll.CanRunInScope( m_ScriptScope ))
|
||||
{
|
||||
// ragdoll
|
||||
ScriptVariant_t args[] = { ScriptVariant_t( pRagdoll->GetScriptInstance() ) };
|
||||
ScriptVariant_t args[] = { ScriptVariant_t( m_pClientsideRagdoll->GetScriptInstance() ) };
|
||||
g_Hook_OnClientRagdoll.Call( m_ScriptScope, NULL, args );
|
||||
}
|
||||
#endif
|
||||
|
||||
return pRagdoll;
|
||||
return m_pClientsideRagdoll;
|
||||
}
|
||||
|
||||
bool C_BaseAnimating::InitAsClientRagdoll( const matrix3x4_t *pDeltaBones0, const matrix3x4_t *pDeltaBones1, const matrix3x4_t *pCurrentBonePosition, float boneDt, bool bFixedConstraints )
|
||||
|
@ -531,6 +531,10 @@ private:
|
||||
|
||||
public:
|
||||
CRagdoll *m_pRagdoll;
|
||||
C_BaseAnimating *m_pClientsideRagdoll; // From Alien Swarm SDK
|
||||
#ifdef MAPBASE
|
||||
C_BaseAnimating *m_pServerRagdoll; // Not from Alien Swarm SDK (note that this can exist without the entity having died)
|
||||
#endif
|
||||
|
||||
// Texture group to use
|
||||
int m_nSkin;
|
||||
|
@ -429,7 +429,8 @@ BEGIN_RECV_TABLE_NOBASE( C_BaseEntity, DT_AnimTimeMustBeFirst )
|
||||
END_RECV_TABLE()
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
ScriptHook_t CBaseEntity::g_Hook_UpdateOnRemove;
|
||||
ScriptHook_t C_BaseEntity::g_Hook_UpdateOnRemove;
|
||||
ScriptHook_t C_BaseEntity::g_Hook_ModifyEmitSoundParams;
|
||||
#endif
|
||||
|
||||
BEGIN_ENT_SCRIPTDESC_ROOT( C_BaseEntity, "Root class of all client-side entities" )
|
||||
@ -555,7 +556,11 @@ BEGIN_ENT_SCRIPTDESC_ROOT( C_BaseEntity, "Root class of all client-side entities
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptSetContextThink, "SetContextThink", "Set a think function on this entity." )
|
||||
|
||||
|
||||
DEFINE_SIMPLE_SCRIPTHOOK( CBaseEntity::g_Hook_UpdateOnRemove, "UpdateOnRemove", FIELD_VOID, "Called when the entity is being removed." )
|
||||
DEFINE_SIMPLE_SCRIPTHOOK( C_BaseEntity::g_Hook_UpdateOnRemove, "UpdateOnRemove", FIELD_VOID, "Called when the entity is being removed." )
|
||||
|
||||
BEGIN_SCRIPTHOOK( C_BaseEntity::g_Hook_ModifyEmitSoundParams, "ModifyEmitSoundParams", FIELD_VOID, "Called every time a sound is emitted on this entity, allowing for its parameters to be modified." )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "params", FIELD_HSCRIPT )
|
||||
END_SCRIPTHOOK()
|
||||
|
||||
#endif // MAPBASE_VSCRIPT
|
||||
|
||||
|
@ -296,6 +296,7 @@ public:
|
||||
CScriptScope m_ScriptScope;
|
||||
|
||||
static ScriptHook_t g_Hook_UpdateOnRemove;
|
||||
static ScriptHook_t g_Hook_ModifyEmitSoundParams;
|
||||
#endif
|
||||
|
||||
// IClientUnknown overrides.
|
||||
|
@ -281,6 +281,7 @@ END_RECV_TABLE()
|
||||
RecvPropInt ( RECVINFO( m_spawnflags ), 0, RecvProxy_ShiftPlayerSpawnflags ),
|
||||
|
||||
RecvPropBool ( RECVINFO( m_bDrawPlayerModelExternally ) ),
|
||||
RecvPropBool ( RECVINFO( m_bInTriggerFall ) ),
|
||||
#endif
|
||||
|
||||
END_RECV_TABLE()
|
||||
@ -331,7 +332,10 @@ END_RECV_TABLE()
|
||||
|
||||
RecvPropString( RECVINFO(m_szLastPlaceName) ),
|
||||
|
||||
RecvPropEHandle(RECVINFO(m_hPostProcessCtrl)), // Send to everybody - for spectating
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
RecvPropEHandle( RECVINFO( m_hPostProcessCtrl ) ), // Send to everybody - for spectating
|
||||
RecvPropEHandle( RECVINFO( m_hColorCorrectionCtrl ) ), // Send to everybody - for spectating
|
||||
#endif
|
||||
|
||||
#if defined USES_ECON_ITEMS
|
||||
RecvPropUtlVector( RECVINFO_UTLVECTOR( m_hMyWearables ), MAX_WEARABLES_SENT_FROM_SERVER, RecvPropEHandle(NULL, 0, 0) ),
|
||||
@ -2917,6 +2921,7 @@ void C_BasePlayer::UpdateFogBlend( void )
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -2925,6 +2930,15 @@ C_PostProcessController* C_BasePlayer::GetActivePostProcessController() const
|
||||
return m_hPostProcessCtrl.Get();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
C_ColorCorrection* C_BasePlayer::GetActiveColorCorrection() const
|
||||
{
|
||||
return m_hColorCorrectionCtrl.Get();
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -23,7 +23,10 @@
|
||||
#include "hintsystem.h"
|
||||
#include "SoundEmitterSystem/isoundemittersystembase.h"
|
||||
#include "c_env_fog_controller.h"
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
#include "c_postprocesscontroller.h"
|
||||
#include "c_colorcorrection.h"
|
||||
#endif
|
||||
#include "igameevents.h"
|
||||
#include "GameEventListener.h"
|
||||
|
||||
@ -381,7 +384,10 @@ public:
|
||||
void UpdateFogController( void );
|
||||
void UpdateFogBlend( void );
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
C_PostProcessController* GetActivePostProcessController() const;
|
||||
C_ColorCorrection* GetActiveColorCorrection() const;
|
||||
#endif
|
||||
|
||||
float GetFOVTime( void ){ return m_flFOVTime; }
|
||||
|
||||
@ -458,6 +464,8 @@ public:
|
||||
|
||||
// Allows the player's model to draw on non-main views, like monitors or mirrors.
|
||||
bool m_bDrawPlayerModelExternally;
|
||||
|
||||
bool m_bInTriggerFall;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
@ -645,7 +653,10 @@ private:
|
||||
// One for left and one for right side of step
|
||||
StepSoundCache_t m_StepSoundCache[ 2 ];
|
||||
|
||||
CNetworkHandle(C_PostProcessController, m_hPostProcessCtrl); // active postprocessing controller
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
CNetworkHandle( C_PostProcessController, m_hPostProcessCtrl ); // active postprocessing controller
|
||||
CNetworkHandle( C_ColorCorrection, m_hColorCorrectionCtrl ); // active FXVolume color correction
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
//===========================================================================//
|
||||
#include "cbase.h"
|
||||
|
||||
#include "c_colorcorrection.h"
|
||||
#include "filesystem.h"
|
||||
#include "cdll_client_int.h"
|
||||
#include "colorcorrectionmgr.h"
|
||||
@ -17,45 +18,27 @@
|
||||
|
||||
static ConVar mat_colcorrection_disableentities( "mat_colcorrection_disableentities", "0", FCVAR_NONE, "Disable map color-correction entities" );
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose : Color correction entity with radial falloff
|
||||
//------------------------------------------------------------------------------
|
||||
class C_ColorCorrection : public C_BaseEntity
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_ColorCorrection, C_BaseEntity );
|
||||
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
C_ColorCorrection();
|
||||
virtual ~C_ColorCorrection();
|
||||
|
||||
void OnDataChanged(DataUpdateType_t updateType);
|
||||
bool ShouldDraw();
|
||||
|
||||
void ClientThink();
|
||||
|
||||
private:
|
||||
Vector m_vecOrigin;
|
||||
|
||||
float m_minFalloff;
|
||||
float m_maxFalloff;
|
||||
float m_flCurWeight;
|
||||
char m_netLookupFilename[MAX_PATH];
|
||||
|
||||
bool m_bEnabled;
|
||||
|
||||
ClientCCHandle_t m_CCHandle;
|
||||
};
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
static ConVar mat_colcorrection_forceentitiesclientside( "mat_colcorrection_forceentitiesclientside", "0", FCVAR_CHEAT, "Forces color correction entities to be updated on the client" );
|
||||
#endif
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT(C_ColorCorrection, DT_ColorCorrection, CColorCorrection)
|
||||
RecvPropVector( RECVINFO(m_vecOrigin) ),
|
||||
RecvPropFloat( RECVINFO(m_minFalloff) ),
|
||||
RecvPropFloat( RECVINFO(m_maxFalloff) ),
|
||||
RecvPropFloat( RECVINFO(m_flCurWeight) ),
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
RecvPropFloat( RECVINFO(m_flMaxWeight) ),
|
||||
RecvPropFloat( RECVINFO(m_flFadeInDuration) ),
|
||||
RecvPropFloat( RECVINFO(m_flFadeOutDuration) ),
|
||||
#endif
|
||||
RecvPropString( RECVINFO(m_netLookupFilename) ),
|
||||
RecvPropBool( RECVINFO(m_bEnabled) ),
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
RecvPropBool( RECVINFO(m_bMaster) ),
|
||||
RecvPropBool( RECVINFO(m_bClientSide) ),
|
||||
RecvPropBool( RECVINFO(m_bExclusive) )
|
||||
#endif
|
||||
|
||||
END_RECV_TABLE()
|
||||
|
||||
@ -65,14 +48,43 @@ END_RECV_TABLE()
|
||||
//------------------------------------------------------------------------------
|
||||
C_ColorCorrection::C_ColorCorrection()
|
||||
{
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
m_minFalloff = -1.0f;
|
||||
m_maxFalloff = -1.0f;
|
||||
m_flFadeInDuration = 0.0f;
|
||||
m_flFadeOutDuration = 0.0f;
|
||||
m_flCurWeight = 0.0f;
|
||||
m_flMaxWeight = 1.0f;
|
||||
m_netLookupFilename[0] = '\0';
|
||||
m_bEnabled = false;
|
||||
m_bMaster = false;
|
||||
m_bExclusive = false;
|
||||
#endif
|
||||
m_CCHandle = INVALID_CLIENT_CCHANDLE;
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
m_bFadingIn = false;
|
||||
m_flFadeStartWeight = 0.0f;
|
||||
m_flFadeStartTime = 0.0f;
|
||||
m_flFadeDuration = 0.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
C_ColorCorrection::~C_ColorCorrection()
|
||||
{
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
g_pColorCorrectionMgr->RemoveColorCorrectionEntity( this, m_CCHandle );
|
||||
#else
|
||||
g_pColorCorrectionMgr->RemoveColorCorrection( m_CCHandle );
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
bool C_ColorCorrection::IsClientSide() const
|
||||
{
|
||||
return m_bClientSide || mat_colcorrection_forceentitiesclientside.GetBool();
|
||||
}
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose :
|
||||
@ -87,11 +99,21 @@ void C_ColorCorrection::OnDataChanged(DataUpdateType_t updateType)
|
||||
{
|
||||
if ( m_CCHandle == INVALID_CLIENT_CCHANDLE )
|
||||
{
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
// forming a unique name without extension
|
||||
char cleanName[MAX_PATH];
|
||||
V_StripExtension( m_netLookupFilename, cleanName, sizeof( cleanName ) );
|
||||
char name[MAX_PATH];
|
||||
Q_snprintf( name, MAX_PATH, "%s_%d", cleanName, entindex() );
|
||||
|
||||
m_CCHandle = g_pColorCorrectionMgr->AddColorCorrectionEntity( this, name, m_netLookupFilename );
|
||||
#else
|
||||
char filename[MAX_PATH];
|
||||
Q_strncpy( filename, m_netLookupFilename, MAX_PATH );
|
||||
|
||||
m_CCHandle = g_pColorCorrectionMgr->AddColorCorrection( filename );
|
||||
SetNextClientThink( ( m_CCHandle != INVALID_CLIENT_CCHANDLE ) ? CLIENT_THINK_ALWAYS : CLIENT_THINK_NEVER );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -104,6 +126,129 @@ bool C_ColorCorrection::ShouldDraw()
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
void C_ColorCorrection::Update( C_BasePlayer *pPlayer, float ccScale )
|
||||
{
|
||||
Assert( m_CCHandle != INVALID_CLIENT_CCHANDLE );
|
||||
|
||||
if ( mat_colcorrection_disableentities.GetInt() )
|
||||
{
|
||||
// Allow the colorcorrectionui panel (or user) to turn off color-correction entities
|
||||
g_pColorCorrectionMgr->SetColorCorrectionWeight( m_CCHandle, 0.0f, m_bExclusive );
|
||||
return;
|
||||
}
|
||||
|
||||
// fade weight on client
|
||||
if ( IsClientSide() )
|
||||
{
|
||||
m_flCurWeight = Lerp( GetFadeRatio(), m_flFadeStartWeight, m_bFadingIn ? m_flMaxWeight : 0.0f );
|
||||
}
|
||||
|
||||
if( !m_bEnabled && m_flCurWeight == 0.0f )
|
||||
{
|
||||
g_pColorCorrectionMgr->SetColorCorrectionWeight( m_CCHandle, 0.0f, m_bExclusive );
|
||||
return;
|
||||
}
|
||||
|
||||
Vector playerOrigin = pPlayer->GetAbsOrigin();
|
||||
|
||||
float weight = 0;
|
||||
if ( ( m_minFalloff != -1 ) && ( m_maxFalloff != -1 ) && m_minFalloff != m_maxFalloff )
|
||||
{
|
||||
float dist = (playerOrigin - m_vecOrigin).Length();
|
||||
weight = (dist-m_minFalloff) / (m_maxFalloff-m_minFalloff);
|
||||
if ( weight<0.0f ) weight = 0.0f;
|
||||
if ( weight>1.0f ) weight = 1.0f;
|
||||
}
|
||||
|
||||
g_pColorCorrectionMgr->SetColorCorrectionWeight( m_CCHandle, m_flCurWeight * ( 1.0 - weight ) * ccScale, m_bExclusive );
|
||||
}
|
||||
|
||||
void C_ColorCorrection::EnableOnClient( bool bEnable, bool bSkipFade )
|
||||
{
|
||||
if ( !IsClientSide() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_bFadingIn = bEnable;
|
||||
|
||||
// initialize countdown timer
|
||||
m_flFadeStartWeight = m_flCurWeight;
|
||||
float flFadeTimeScale = 1.0f;
|
||||
if ( m_flMaxWeight != 0.0f )
|
||||
{
|
||||
flFadeTimeScale = m_flCurWeight / m_flMaxWeight;
|
||||
}
|
||||
|
||||
if ( m_bFadingIn )
|
||||
{
|
||||
flFadeTimeScale = 1.0f - flFadeTimeScale;
|
||||
}
|
||||
|
||||
if ( bSkipFade )
|
||||
{
|
||||
flFadeTimeScale = 0.0f;
|
||||
}
|
||||
|
||||
StartFade( flFadeTimeScale * ( m_bFadingIn ? m_flFadeInDuration : m_flFadeOutDuration ) );
|
||||
|
||||
// update the clientside weight once here, in case the fade duration is 0
|
||||
m_flCurWeight = Lerp( GetFadeRatio(), m_flFadeStartWeight, m_bFadingIn ? m_flMaxWeight : 0.0f );
|
||||
}
|
||||
|
||||
Vector C_ColorCorrection::GetOrigin()
|
||||
{
|
||||
return m_vecOrigin;
|
||||
}
|
||||
|
||||
float C_ColorCorrection::GetMinFalloff()
|
||||
{
|
||||
return m_minFalloff;
|
||||
}
|
||||
|
||||
float C_ColorCorrection::GetMaxFalloff()
|
||||
{
|
||||
return m_maxFalloff;
|
||||
}
|
||||
|
||||
void C_ColorCorrection::SetWeight( float fWeight )
|
||||
{
|
||||
g_pColorCorrectionMgr->SetColorCorrectionWeight( m_CCHandle, fWeight, false );
|
||||
}
|
||||
|
||||
void C_ColorCorrection::StartFade( float flDuration )
|
||||
{
|
||||
m_flFadeStartTime = gpGlobals->curtime;
|
||||
m_flFadeDuration = MAX( flDuration, 0.0f );
|
||||
}
|
||||
|
||||
float C_ColorCorrection::GetFadeRatio() const
|
||||
{
|
||||
float flRatio = 1.0f;
|
||||
|
||||
if ( m_flFadeDuration != 0.0f )
|
||||
{
|
||||
flRatio = ( gpGlobals->curtime - m_flFadeStartTime ) / m_flFadeDuration;
|
||||
flRatio = clamp( flRatio, 0.0f, 1.0f );
|
||||
}
|
||||
return flRatio;
|
||||
}
|
||||
|
||||
bool C_ColorCorrection::IsFadeTimeElapsed() const
|
||||
{
|
||||
return ( ( gpGlobals->curtime - m_flFadeStartTime ) > m_flFadeDuration ) ||
|
||||
( ( gpGlobals->curtime - m_flFadeStartTime ) < 0.0f );
|
||||
}
|
||||
|
||||
void UpdateColorCorrectionEntities( C_BasePlayer *pPlayer, float ccScale, C_ColorCorrection **pList, int listCount )
|
||||
{
|
||||
for ( int i = 0; i < listCount; i++ )
|
||||
{
|
||||
pList[i]->Update(pPlayer, ccScale);
|
||||
}
|
||||
}
|
||||
#else
|
||||
void C_ColorCorrection::ClientThink()
|
||||
{
|
||||
if ( m_CCHandle == INVALID_CLIENT_CCHANDLE )
|
||||
@ -141,6 +286,7 @@ void C_ColorCorrection::ClientThink()
|
||||
|
||||
BaseClass::ClientThink();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
88
sp/src/game/client/c_colorcorrection.h
Normal file
88
sp/src/game/client/c_colorcorrection.h
Normal file
@ -0,0 +1,88 @@
|
||||
//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============//
|
||||
//
|
||||
// Note that this header exists in the Alien Swarm SDK, but not in stock Source SDK 2013.
|
||||
// Although technically a new Mapbase file, it only serves to move otherwise identical code,
|
||||
// so most code and repo conventions will pretend it was always there.
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// Purpose: Color correction entity with simple radial falloff
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef C_COLORCORRECTION_H
|
||||
#define C_COLORCORRECTION_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "colorcorrectionmgr.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose : Color correction entity with radial falloff
|
||||
//------------------------------------------------------------------------------
|
||||
class C_ColorCorrection : public C_BaseEntity
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_ColorCorrection, C_BaseEntity );
|
||||
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
C_ColorCorrection();
|
||||
virtual ~C_ColorCorrection();
|
||||
|
||||
void OnDataChanged(DataUpdateType_t updateType);
|
||||
bool ShouldDraw();
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
virtual void Update(C_BasePlayer *pPlayer, float ccScale);
|
||||
|
||||
bool IsMaster() const { return m_bMaster; }
|
||||
bool IsClientSide() const;
|
||||
bool IsExclusive() const { return m_bExclusive; }
|
||||
|
||||
void EnableOnClient( bool bEnable, bool bSkipFade = false );
|
||||
|
||||
Vector GetOrigin();
|
||||
float GetMinFalloff();
|
||||
float GetMaxFalloff();
|
||||
|
||||
void SetWeight( float fWeight );
|
||||
|
||||
protected:
|
||||
void StartFade( float flDuration );
|
||||
float GetFadeRatio() const;
|
||||
bool IsFadeTimeElapsed() const;
|
||||
#else
|
||||
void ClientThink();
|
||||
|
||||
private:
|
||||
#endif
|
||||
Vector m_vecOrigin;
|
||||
|
||||
float m_minFalloff;
|
||||
float m_maxFalloff;
|
||||
float m_flCurWeight;
|
||||
char m_netLookupFilename[MAX_PATH];
|
||||
|
||||
bool m_bEnabled;
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
float m_flFadeInDuration;
|
||||
float m_flFadeOutDuration;
|
||||
float m_flMaxWeight;
|
||||
|
||||
bool m_bMaster;
|
||||
bool m_bClientSide;
|
||||
bool m_bExclusive;
|
||||
|
||||
bool m_bFadingIn;
|
||||
float m_flFadeStartWeight;
|
||||
float m_flFadeStartTime;
|
||||
float m_flFadeDuration;
|
||||
#endif
|
||||
|
||||
ClientCCHandle_t m_CCHandle;
|
||||
};
|
||||
|
||||
#endif
|
@ -36,9 +36,26 @@ public:
|
||||
void OnDataChanged(DataUpdateType_t updateType);
|
||||
bool ShouldDraw();
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
void Update( C_BasePlayer *pPlayer, float ccScale );
|
||||
|
||||
void StartTouch( C_BaseEntity *pOther );
|
||||
void EndTouch( C_BaseEntity *pOther );
|
||||
#else
|
||||
void ClientThink();
|
||||
#endif
|
||||
|
||||
private:
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
float m_LastEnterWeight;
|
||||
float m_LastEnterTime;
|
||||
|
||||
float m_LastExitWeight;
|
||||
float m_LastExitTime;
|
||||
bool m_bEnabled;
|
||||
float m_MaxWeight;
|
||||
float m_FadeDuration;
|
||||
#endif
|
||||
float m_Weight;
|
||||
char m_lookupFilename[MAX_PATH];
|
||||
|
||||
@ -46,6 +63,11 @@ private:
|
||||
};
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT(C_ColorCorrectionVolume, DT_ColorCorrectionVolume, CColorCorrectionVolume)
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
RecvPropBool( RECVINFO( m_bEnabled ) ),
|
||||
RecvPropFloat( RECVINFO( m_MaxWeight ) ),
|
||||
RecvPropFloat( RECVINFO( m_FadeDuration ) ),
|
||||
#endif
|
||||
RecvPropFloat( RECVINFO(m_Weight) ),
|
||||
RecvPropString( RECVINFO(m_lookupFilename) ),
|
||||
END_RECV_TABLE()
|
||||
@ -82,11 +104,21 @@ void C_ColorCorrectionVolume::OnDataChanged(DataUpdateType_t updateType)
|
||||
{
|
||||
if ( m_CCHandle == INVALID_CLIENT_CCHANDLE )
|
||||
{
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
// forming a unique name without extension
|
||||
char cleanName[MAX_PATH];
|
||||
V_StripExtension( m_lookupFilename, cleanName, sizeof( cleanName ) );
|
||||
char name[MAX_PATH];
|
||||
Q_snprintf( name, MAX_PATH, "%s_%d", cleanName, entindex() );
|
||||
|
||||
m_CCHandle = g_pColorCorrectionMgr->AddColorCorrectionVolume( this, name, m_lookupFilename );
|
||||
#else
|
||||
char filename[MAX_PATH];
|
||||
Q_strncpy( filename, m_lookupFilename, MAX_PATH );
|
||||
|
||||
m_CCHandle = g_pColorCorrectionMgr->AddColorCorrection( filename );
|
||||
SetNextClientThink( ( m_CCHandle != INVALID_CLIENT_CCHANDLE ) ? CLIENT_THINK_ALWAYS : CLIENT_THINK_NEVER );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -99,11 +131,95 @@ bool C_ColorCorrectionVolume::ShouldDraw()
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
void C_ColorCorrectionVolume::StartTouch( CBaseEntity *pEntity )
|
||||
{
|
||||
m_LastEnterTime = gpGlobals->curtime;
|
||||
m_LastEnterWeight = m_Weight;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
void C_ColorCorrectionVolume::EndTouch( CBaseEntity *pEntity )
|
||||
{
|
||||
m_LastExitTime = gpGlobals->curtime;
|
||||
m_LastExitWeight = m_Weight;
|
||||
}
|
||||
|
||||
|
||||
void C_ColorCorrectionVolume::Update( C_BasePlayer *pPlayer, float ccScale )
|
||||
{
|
||||
if ( pPlayer )
|
||||
{
|
||||
bool isTouching = CollisionProp()->IsPointInBounds( pPlayer->EyePosition() );
|
||||
bool wasTouching = m_LastEnterTime > m_LastExitTime;
|
||||
|
||||
if ( isTouching && !wasTouching )
|
||||
{
|
||||
StartTouch( pPlayer );
|
||||
}
|
||||
else if ( !isTouching && wasTouching )
|
||||
{
|
||||
EndTouch( pPlayer );
|
||||
}
|
||||
}
|
||||
|
||||
if( !m_bEnabled )
|
||||
{
|
||||
m_Weight = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( m_LastEnterTime > m_LastExitTime )
|
||||
{
|
||||
// we most recently entered the volume
|
||||
|
||||
if( m_Weight < 1.0f )
|
||||
{
|
||||
float dt = gpGlobals->curtime - m_LastEnterTime;
|
||||
float weight = m_LastEnterWeight + dt / ((1.0f-m_LastEnterWeight)*m_FadeDuration);
|
||||
if( weight>1.0f )
|
||||
weight = 1.0f;
|
||||
|
||||
m_Weight = weight;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// we most recently exitted the volume
|
||||
|
||||
if( m_Weight > 0.0f )
|
||||
{
|
||||
float dt = gpGlobals->curtime - m_LastExitTime;
|
||||
float weight = (1.0f-m_LastExitWeight) + dt / (m_LastExitWeight*m_FadeDuration);
|
||||
if( weight>1.0f )
|
||||
weight = 1.0f;
|
||||
|
||||
m_Weight = 1.0f - weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Vector entityPosition = GetAbsOrigin();
|
||||
g_pColorCorrectionMgr->SetColorCorrectionWeight( m_CCHandle, m_Weight * ccScale );
|
||||
}
|
||||
|
||||
|
||||
void UpdateColorCorrectionVolumes( C_BasePlayer *pPlayer, float ccScale, C_ColorCorrectionVolume **pList, int listCount )
|
||||
{
|
||||
for ( int i = 0; i < listCount; i++ )
|
||||
{
|
||||
pList[i]->Update(pPlayer, ccScale);
|
||||
}
|
||||
}
|
||||
#else
|
||||
void C_ColorCorrectionVolume::ClientThink()
|
||||
{
|
||||
Vector entityPosition = GetAbsOrigin();
|
||||
g_pColorCorrectionMgr->SetColorCorrectionWeight( m_CCHandle, m_Weight );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
@ -40,7 +40,10 @@ ConVar r_RainSplashPercentage( "r_RainSplashPercentage", "20", FCVAR_CHEAT ); //
|
||||
ConVar r_RainParticleDensity( "r_RainParticleDensity", "1", FCVAR_NONE, "Density of Particle Rain 0-1" );
|
||||
|
||||
#ifdef MAPBASE
|
||||
ConVar r_RainParticleClampOffset( "r_RainParticleClampOffset", "112", FCVAR_NONE, "How far inward or outward to extrude clamped precipitation particle systems" );
|
||||
ConVar r_RainParticleClampOffset_Rain( "r_RainParticleClampOffset_Rain", "120", FCVAR_NONE, "How far inward or outward to extrude clamped precipitation particle systems using the 'Particle Rain' type." );
|
||||
ConVar r_RainParticleClampOffset_Ash( "r_RainParticleClampOffset_Ash", "300", FCVAR_NONE, "How far inward or outward to extrude clamped precipitation particle systems using the 'Particle Ash' type." );
|
||||
ConVar r_RainParticleClampOffset_RainStorm( "r_RainParticleClampOffset_RainStorm", "112", FCVAR_NONE, "How far inward or outward to extrude clamped precipitation particle systems using the 'Particle Rain Storm' type." );
|
||||
ConVar r_RainParticleClampOffset_Snow( "r_RainParticleClampOffset_Snow", "300", FCVAR_NONE, "How far inward or outward to extrude clamped precipitation particle systems using the 'Particle Snow' type." );
|
||||
ConVar r_RainParticleClampDebug( "r_RainParticleClampDebug", "0", FCVAR_NONE, "Enables debug code for precipitation particle system clamping" );
|
||||
#endif
|
||||
|
||||
@ -951,6 +954,70 @@ void CClient_Precipitation::CreateParticlePrecip( void )
|
||||
UpdateParticlePrecip( pPlayer );
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
void CClient_Precipitation::ClampParticlePosition( Vector &vPlayerPos, Vector &vOffsetPos, Vector &vOffsetPosNear, Vector &vOffsetPosFar )
|
||||
{
|
||||
Vector mins, maxs;
|
||||
modelinfo->GetModelBounds( GetModel(), mins, maxs );
|
||||
|
||||
// Account for precipitation height
|
||||
maxs.z += 180;
|
||||
|
||||
Vector vecOrigin; //= WorldSpaceCenter();
|
||||
VectorLerp( mins, maxs, 0.5f, vecOrigin );
|
||||
|
||||
maxs -= vecOrigin;
|
||||
mins -= vecOrigin;
|
||||
|
||||
//float flMax = r_RainParticleClampOffset.GetFloat();
|
||||
float flMax = 0;
|
||||
switch (m_nPrecipType)
|
||||
{
|
||||
case PRECIPITATION_TYPE_PARTICLERAIN:
|
||||
flMax = r_RainParticleClampOffset_Rain.GetFloat();
|
||||
break;
|
||||
|
||||
case PRECIPITATION_TYPE_PARTICLEASH:
|
||||
flMax = r_RainParticleClampOffset_Ash.GetFloat();
|
||||
break;
|
||||
|
||||
case PRECIPITATION_TYPE_PARTICLERAINSTORM:
|
||||
flMax = r_RainParticleClampOffset_RainStorm.GetFloat();
|
||||
break;
|
||||
|
||||
case PRECIPITATION_TYPE_PARTICLESNOW:
|
||||
flMax = r_RainParticleClampOffset_Snow.GetFloat();
|
||||
break;
|
||||
}
|
||||
|
||||
Vector addend( flMax, flMax, 0 );
|
||||
mins += addend;
|
||||
maxs -= addend;
|
||||
|
||||
if (flMax > 0)
|
||||
{
|
||||
// Unless this is extruding outwards, make sure the offset isn't inverting the bounds.
|
||||
// This means precipitation triggers with bounds less than offset*2 will turn into a thin line
|
||||
// and the involved precipitation will pretty much be spatial at all times, which is okay.
|
||||
mins.x = clamp( mins.x, -FLT_MAX, -1 );
|
||||
mins.y = clamp( mins.y, -FLT_MAX, -1 );
|
||||
maxs.x = clamp( maxs.x, 1, FLT_MAX );
|
||||
maxs.y = clamp( maxs.y, 1, FLT_MAX );
|
||||
}
|
||||
|
||||
if (r_RainParticleClampDebug.GetBool())
|
||||
debugoverlay->AddBoxOverlay( vecOrigin, mins, maxs, vec3_angle, 255, 0, 0, 128, 0.15f );
|
||||
|
||||
maxs += vecOrigin;
|
||||
mins += vecOrigin;
|
||||
|
||||
CalcClosestPointOnAABB( mins, maxs, vPlayerPos, vPlayerPos );
|
||||
CalcClosestPointOnAABB( mins, maxs, vOffsetPos, vOffsetPos );
|
||||
CalcClosestPointOnAABB( mins, maxs, vOffsetPosNear, vOffsetPosNear );
|
||||
CalcClosestPointOnAABB( mins, maxs, vOffsetPosFar, vOffsetPosFar );
|
||||
}
|
||||
#endif
|
||||
|
||||
void CClient_Precipitation::UpdateParticlePrecip( C_BasePlayer *pPlayer )
|
||||
{
|
||||
if ( !pPlayer )
|
||||
@ -980,44 +1047,7 @@ void CClient_Precipitation::UpdateParticlePrecip( C_BasePlayer *pPlayer )
|
||||
#ifdef MAPBASE
|
||||
if (m_spawnflags & SF_PRECIP_PARTICLE_CLAMP)
|
||||
{
|
||||
Vector mins, maxs;
|
||||
modelinfo->GetModelBounds( GetModel(), mins, maxs );
|
||||
|
||||
// Account for precipitation height
|
||||
maxs.z += 180;
|
||||
|
||||
Vector vecOrigin; //= WorldSpaceCenter();
|
||||
VectorLerp( mins, maxs, 0.5f, vecOrigin );
|
||||
|
||||
maxs -= vecOrigin;
|
||||
mins -= vecOrigin;
|
||||
|
||||
float flMax = r_RainParticleClampOffset.GetFloat();
|
||||
Vector addend( flMax, flMax, 0 );
|
||||
mins += addend;
|
||||
maxs -= addend;
|
||||
|
||||
if (flMax > 0)
|
||||
{
|
||||
// Unless this is extruding outwards, make sure the offset isn't inverting the bounds.
|
||||
// This means precipitation triggers with bounds less than offset*2 will turn into a thin line
|
||||
// and the involved precipitation will pretty much be spatial at all times, which is okay.
|
||||
mins.x = clamp( mins.x, -FLT_MAX, -1 );
|
||||
mins.y = clamp( mins.y, -FLT_MAX, -1 );
|
||||
maxs.x = clamp( maxs.x, 1, FLT_MAX );
|
||||
maxs.y = clamp( maxs.y, 1, FLT_MAX );
|
||||
}
|
||||
|
||||
if (r_RainParticleClampDebug.GetBool())
|
||||
debugoverlay->AddBoxOverlay( vecOrigin, mins, maxs, vec3_angle, 255, 0, 0, 128, 0.15f );
|
||||
|
||||
maxs += vecOrigin;
|
||||
mins += vecOrigin;
|
||||
|
||||
CalcClosestPointOnAABB( mins, maxs, vPlayerPos, vPlayerPos );
|
||||
CalcClosestPointOnAABB( mins, maxs, vOffsetPos, vOffsetPos );
|
||||
CalcClosestPointOnAABB( mins, maxs, vOffsetPosNear, vOffsetPosNear );
|
||||
CalcClosestPointOnAABB( mins, maxs, vOffsetPosFar, vOffsetPosFar );
|
||||
ClampParticlePosition( vPlayerPos, vOffsetPos, vOffsetPosNear, vOffsetPosFar );
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1236,6 +1266,13 @@ void CClient_Precipitation::DispatchInnerParticlePrecip( C_BasePlayer *pPlayer,
|
||||
Vector vOffsetPosFar = vPlayerPos + Vector ( 0, 0, 180 ) + ( vForward * m_flParticleInnerDist ); // 100.0
|
||||
Vector vDensity = Vector( r_RainParticleDensity.GetFloat(), 0, 0 ) * m_flDensity;
|
||||
|
||||
#ifdef MAPBASE
|
||||
if (m_spawnflags & SF_PRECIP_PARTICLE_CLAMP)
|
||||
{
|
||||
ClampParticlePosition( vPlayerPos, vOffsetPos, vOffsetPosNear, vOffsetPosFar );
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MAPBASE
|
||||
if (!(m_spawnflags & SF_PRECIP_PARTICLE_NO_OUTER))
|
||||
#endif
|
||||
|
@ -130,6 +130,10 @@ private:
|
||||
void CreateAshParticle( void );
|
||||
void CreateRainOrSnowParticle( Vector vSpawnPosition, Vector vVelocity );
|
||||
|
||||
#ifdef MAPBASE
|
||||
void ClampParticlePosition( Vector &vPlayerPos, Vector &vOffsetPos, Vector &vOffsetPosNear, Vector &vOffsetPosFar );
|
||||
#endif
|
||||
|
||||
// Information helpful in creating and rendering particles
|
||||
IMaterial *m_MatHandle; // material used
|
||||
|
||||
|
@ -48,6 +48,9 @@ protected:
|
||||
int m_iCachedDesiredOverlay;
|
||||
int m_iCurrentOverlay;
|
||||
float m_flCurrentOverlayTime;
|
||||
#ifdef MAPBASE
|
||||
int m_iOverlayIndex;
|
||||
#endif
|
||||
};
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_EnvScreenOverlay, DT_EnvScreenOverlay, CEnvScreenOverlay )
|
||||
@ -56,6 +59,9 @@ IMPLEMENT_CLIENTCLASS_DT( C_EnvScreenOverlay, DT_EnvScreenOverlay, CEnvScreenOve
|
||||
RecvPropFloat( RECVINFO( m_flStartTime ) ),
|
||||
RecvPropInt( RECVINFO( m_iDesiredOverlay ) ),
|
||||
RecvPropBool( RECVINFO( m_bIsActive ) ),
|
||||
#ifdef MAPBASE
|
||||
RecvPropInt( RECVINFO( m_iOverlayIndex ) ),
|
||||
#endif
|
||||
END_RECV_TABLE()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -77,7 +83,11 @@ void C_EnvScreenOverlay::PostDataUpdate( DataUpdateType_t updateType )
|
||||
BaseClass::PostDataUpdate( updateType );
|
||||
|
||||
// If we have a start time now, start the overlays going
|
||||
#ifdef MAPBASE
|
||||
if ( m_bIsActive && m_flStartTime > 0 && (view->GetScreenOverlayMaterial() == NULL || (m_iOverlayIndex != -1 && view->GetIndexedScreenOverlayMaterial(m_iOverlayIndex) == NULL)) )
|
||||
#else
|
||||
if ( m_bIsActive && m_flStartTime > 0 && view->GetScreenOverlayMaterial() == NULL )
|
||||
#endif
|
||||
{
|
||||
StartOverlays();
|
||||
}
|
||||
@ -111,7 +121,16 @@ void C_EnvScreenOverlay::StopOverlays( void )
|
||||
|
||||
if ( m_bWasActive && !m_bIsActive )
|
||||
{
|
||||
view->SetScreenOverlayMaterial( NULL );
|
||||
#ifdef MAPBASE
|
||||
if (m_iOverlayIndex != -1)
|
||||
{
|
||||
view->SetIndexedScreenOverlayMaterial( m_iOverlayIndex, NULL );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
view->SetScreenOverlayMaterial( NULL );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -163,7 +182,16 @@ void C_EnvScreenOverlay::StartCurrentOverlay( void )
|
||||
IMaterial *pMaterial = materials->FindMaterial( m_iszOverlayNames[m_iCurrentOverlay], TEXTURE_GROUP_CLIENT_EFFECTS, false );
|
||||
if ( !IsErrorMaterial( pMaterial ) )
|
||||
{
|
||||
view->SetScreenOverlayMaterial( pMaterial );
|
||||
#ifdef MAPBASE
|
||||
if (m_iOverlayIndex != -1)
|
||||
{
|
||||
view->SetIndexedScreenOverlayMaterial( m_iOverlayIndex, pMaterial );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
view->SetScreenOverlayMaterial( pMaterial );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -112,6 +112,15 @@ public:
|
||||
C_BasePlayer *GetPlayerOwner( void );
|
||||
bool IsInputOnlyToOwner( void );
|
||||
|
||||
#ifdef MAPBASE
|
||||
void GetSize( float &width, float &height ) const { width = m_flWidth; height = m_flHeight; }
|
||||
void GetPixelSize( int &width, int &height ) const { width = m_nPixelWidth; height = m_nPixelHeight; }
|
||||
void SetWidth( float flWidth ) { m_flWidth = flWidth; }
|
||||
void SetHeight( float flHeight ) { m_flHeight = flHeight; }
|
||||
void SetPixelWidth( int nWidth ) { m_nPixelWidth = nWidth; }
|
||||
void SetPixelHeight( int nHeight ) { m_nPixelHeight = nHeight; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
// Vgui screen management
|
||||
void CreateVguiScreen( const char *pTypeName );
|
||||
|
@ -292,8 +292,11 @@ ClientModeShared::ClientModeShared()
|
||||
m_pWeaponSelection = NULL;
|
||||
m_nRootSize[ 0 ] = m_nRootSize[ 1 ] = -1;
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
m_pCurrentPostProcessController = NULL;
|
||||
m_PostProcessLerpTimer.Invalidate();
|
||||
m_pCurrentColorCorrection = NULL;
|
||||
#endif
|
||||
|
||||
#if defined( REPLAY_ENABLED )
|
||||
m_pReplayReminderPanel = NULL;
|
||||
@ -635,6 +638,43 @@ void ClientModeShared::Update()
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void ClientModeShared::OnColorCorrectionWeightsReset( void )
|
||||
{
|
||||
C_ColorCorrection *pNewColorCorrection = NULL;
|
||||
C_ColorCorrection *pOldColorCorrection = m_pCurrentColorCorrection;
|
||||
C_BasePlayer* pPlayer = C_BasePlayer::GetLocalPlayer();
|
||||
if ( pPlayer )
|
||||
{
|
||||
pNewColorCorrection = pPlayer->GetActiveColorCorrection();
|
||||
}
|
||||
|
||||
if ( pNewColorCorrection != pOldColorCorrection )
|
||||
{
|
||||
if ( pOldColorCorrection )
|
||||
{
|
||||
pOldColorCorrection->EnableOnClient( false );
|
||||
}
|
||||
if ( pNewColorCorrection )
|
||||
{
|
||||
pNewColorCorrection->EnableOnClient( true, pOldColorCorrection == NULL );
|
||||
}
|
||||
m_pCurrentColorCorrection = pNewColorCorrection;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
float ClientModeShared::GetColorCorrectionScale( void ) const
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// This processes all input before SV Move messages are sent
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -91,6 +91,11 @@ public:
|
||||
virtual void ProcessInput(bool bActive);
|
||||
virtual bool CreateMove( float flInputSampleTime, CUserCmd *cmd );
|
||||
virtual void Update();
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
virtual void OnColorCorrectionWeightsReset( void );
|
||||
virtual float GetColorCorrectionScale( void ) const;
|
||||
virtual void ClearCurrentColorCorrection() { m_pCurrentColorCorrection = NULL; }
|
||||
#endif
|
||||
|
||||
// Input
|
||||
virtual int KeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding );
|
||||
@ -165,12 +170,16 @@ private:
|
||||
CBaseHudWeaponSelection *m_pWeaponSelection;
|
||||
int m_nRootSize[2];
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
void UpdatePostProcessingEffects();
|
||||
|
||||
const C_PostProcessController* m_pCurrentPostProcessController;
|
||||
PostProcessParameters_t m_CurrentPostProcessParameters;
|
||||
PostProcessParameters_t m_LerpStartPostProcessParameters, m_LerpEndPostProcessParameters;
|
||||
CountdownTimer m_PostProcessLerpTimer;
|
||||
|
||||
CHandle<C_ColorCorrection> m_pCurrentColorCorrection;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // CLIENTMODE_NORMAL_H
|
||||
|
@ -8,6 +8,12 @@
|
||||
#include "cbase.h"
|
||||
#include "tier0/vprof.h"
|
||||
#include "colorcorrectionmgr.h"
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
#include "clientmode_shared.h" //"clientmode.h"
|
||||
|
||||
// NOTE: This has to be the last file included!
|
||||
#include "tier0/memdbgon.h"
|
||||
#endif
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -16,6 +22,13 @@
|
||||
static CColorCorrectionMgr s_ColorCorrectionMgr;
|
||||
CColorCorrectionMgr *g_pColorCorrectionMgr = &s_ColorCorrectionMgr;
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
static ConVar mat_colcorrection_editor( "mat_colcorrection_editor", "0" );
|
||||
|
||||
static CUtlVector<C_ColorCorrection *> g_ColorCorrectionList;
|
||||
static CUtlVector<C_ColorCorrectionVolume *> g_ColorCorrectionVolumeList;
|
||||
#endif
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Constructor
|
||||
@ -62,10 +75,89 @@ void CColorCorrectionMgr::RemoveColorCorrection( ClientCCHandle_t h )
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
ClientCCHandle_t CColorCorrectionMgr::AddColorCorrectionEntity( C_ColorCorrection *pEntity, const char *pName, const char *pFileName )
|
||||
{
|
||||
ClientCCHandle_t h = AddColorCorrection(pName, pFileName);
|
||||
if ( h != INVALID_CLIENT_CCHANDLE )
|
||||
{
|
||||
Assert(g_ColorCorrectionList.Find(pEntity) == -1);
|
||||
g_ColorCorrectionList.AddToTail(pEntity);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
void CColorCorrectionMgr::RemoveColorCorrectionEntity( C_ColorCorrection *pEntity, ClientCCHandle_t h)
|
||||
{
|
||||
RemoveColorCorrection(h);
|
||||
g_ColorCorrectionList.FindAndFastRemove(pEntity);
|
||||
}
|
||||
|
||||
ClientCCHandle_t CColorCorrectionMgr::AddColorCorrectionVolume( C_ColorCorrectionVolume *pVolume, const char *pName, const char *pFileName )
|
||||
{
|
||||
ClientCCHandle_t h = AddColorCorrection(pName, pFileName);
|
||||
if ( h != INVALID_CLIENT_CCHANDLE )
|
||||
{
|
||||
Assert(g_ColorCorrectionVolumeList.Find(pVolume) == -1);
|
||||
g_ColorCorrectionVolumeList.AddToTail(pVolume);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
void CColorCorrectionMgr::RemoveColorCorrectionVolume( C_ColorCorrectionVolume *pVolume, ClientCCHandle_t h)
|
||||
{
|
||||
RemoveColorCorrection(h);
|
||||
g_ColorCorrectionVolumeList.FindAndFastRemove(pVolume);
|
||||
}
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Modify color correction weights
|
||||
//------------------------------------------------------------------------------
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
void CColorCorrectionMgr::SetColorCorrectionWeight( ClientCCHandle_t h, float flWeight, bool bExclusive )
|
||||
{
|
||||
if ( h != INVALID_CLIENT_CCHANDLE )
|
||||
{
|
||||
SetWeightParams_t params = { h, flWeight, bExclusive };
|
||||
m_colorCorrectionWeights.AddToTail( params );
|
||||
if( bExclusive && m_bHaveExclusiveWeight && ( flWeight != 0.0f ) )
|
||||
{
|
||||
DevWarning( "Found multiple active color_correction entities with exclusive setting enabled. This is invalid.\n" );
|
||||
}
|
||||
if ( bExclusive )
|
||||
{
|
||||
m_bHaveExclusiveWeight = true;
|
||||
m_flExclusiveWeight = flWeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CColorCorrectionMgr::CommitColorCorrectionWeights()
|
||||
{
|
||||
CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
|
||||
|
||||
for ( int i = 0; i < m_colorCorrectionWeights.Count(); i++ )
|
||||
{
|
||||
ColorCorrectionHandle_t ccHandle = reinterpret_cast<ColorCorrectionHandle_t>( m_colorCorrectionWeights[i].handle );
|
||||
float flWeight = m_colorCorrectionWeights[i].flWeight;
|
||||
if ( !m_colorCorrectionWeights[i].bExclusive )
|
||||
{
|
||||
flWeight = (1.0f - m_flExclusiveWeight ) * m_colorCorrectionWeights[i].flWeight;
|
||||
}
|
||||
pRenderContext->SetLookupWeight( ccHandle, flWeight );
|
||||
|
||||
// FIXME: NOTE! This doesn't work if the same handle has
|
||||
// its weight set twice with no intervening calls to ResetColorCorrectionWeights
|
||||
// which, at the moment, is true
|
||||
if ( flWeight != 0.0f )
|
||||
{
|
||||
++m_nActiveWeightCount;
|
||||
}
|
||||
}
|
||||
m_colorCorrectionWeights.RemoveAll();
|
||||
}
|
||||
#else
|
||||
void CColorCorrectionMgr::SetColorCorrectionWeight( ClientCCHandle_t h, float flWeight )
|
||||
{
|
||||
if ( h != INVALID_CLIENT_CCHANDLE )
|
||||
@ -83,6 +175,7 @@ void CColorCorrectionMgr::SetColorCorrectionWeight( ClientCCHandle_t h, float fl
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void CColorCorrectionMgr::ResetColorCorrectionWeights()
|
||||
{
|
||||
@ -93,6 +186,11 @@ void CColorCorrectionMgr::ResetColorCorrectionWeights()
|
||||
CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
|
||||
pRenderContext->ResetLookupWeights();
|
||||
m_nActiveWeightCount = 0;
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
m_bHaveExclusiveWeight = false;
|
||||
m_flExclusiveWeight = 0.0f;
|
||||
m_colorCorrectionWeights.RemoveAll();
|
||||
#endif
|
||||
}
|
||||
|
||||
void CColorCorrectionMgr::SetResetable( ClientCCHandle_t h, bool bResetable )
|
||||
@ -113,7 +211,34 @@ void CColorCorrectionMgr::SetResetable( ClientCCHandle_t h, bool bResetable )
|
||||
//------------------------------------------------------------------------------
|
||||
// Is color correction active?
|
||||
//------------------------------------------------------------------------------
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
bool CColorCorrectionMgr::HasNonZeroColorCorrectionWeights() const
|
||||
{
|
||||
return ( m_nActiveWeightCount != 0 ) || mat_colcorrection_editor.GetBool();
|
||||
}
|
||||
|
||||
void CColorCorrectionMgr::UpdateColorCorrection()
|
||||
{
|
||||
ResetColorCorrectionWeights();
|
||||
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
|
||||
IClientMode *pClientMode = GetClientModeNormal(); //GetClientMode();
|
||||
|
||||
Assert( pClientMode );
|
||||
if ( !pPlayer || !pClientMode )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pClientMode->OnColorCorrectionWeightsReset();
|
||||
float ccScale = pClientMode->GetColorCorrectionScale();
|
||||
|
||||
UpdateColorCorrectionEntities( pPlayer, ccScale, g_ColorCorrectionList.Base(), g_ColorCorrectionList.Count() );
|
||||
UpdateColorCorrectionVolumes( pPlayer, ccScale, g_ColorCorrectionVolumeList.Base(), g_ColorCorrectionVolumeList.Count() );
|
||||
CommitColorCorrectionWeights();
|
||||
}
|
||||
#else
|
||||
bool CColorCorrectionMgr::HasNonZeroColorCorrectionWeights() const
|
||||
{
|
||||
return ( m_nActiveWeightCount != 0 );
|
||||
}
|
||||
#endif
|
||||
|
@ -14,6 +14,10 @@
|
||||
|
||||
#include "igamesystem.h"
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
class C_ColorCorrection;
|
||||
class C_ColorCorrectionVolume;
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose : Singleton manager for color correction on the client
|
||||
@ -35,8 +39,21 @@ public:
|
||||
ClientCCHandle_t AddColorCorrection( const char *pName, const char *pFileName = NULL );
|
||||
void RemoveColorCorrection( ClientCCHandle_t );
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
ClientCCHandle_t AddColorCorrectionEntity( C_ColorCorrection *pEntity, const char *pName, const char *pFileName = NULL );
|
||||
void RemoveColorCorrectionEntity( C_ColorCorrection *pEntity, ClientCCHandle_t );
|
||||
|
||||
ClientCCHandle_t AddColorCorrectionVolume( C_ColorCorrectionVolume *pVolume, const char *pName, const char *pFileName = NULL );
|
||||
void RemoveColorCorrectionVolume( C_ColorCorrectionVolume *pVolume, ClientCCHandle_t );
|
||||
#endif
|
||||
|
||||
// Modify color correction weights
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
void SetColorCorrectionWeight( ClientCCHandle_t h, float flWeight, bool bExclusive = false );
|
||||
void UpdateColorCorrection();
|
||||
#else
|
||||
void SetColorCorrectionWeight( ClientCCHandle_t h, float flWeight );
|
||||
#endif
|
||||
void ResetColorCorrectionWeights();
|
||||
void SetResetable( ClientCCHandle_t h, bool bResetable );
|
||||
|
||||
@ -45,8 +62,27 @@ public:
|
||||
|
||||
private:
|
||||
int m_nActiveWeightCount;
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
bool m_bHaveExclusiveWeight;
|
||||
float m_flExclusiveWeight;
|
||||
|
||||
struct SetWeightParams_t
|
||||
{
|
||||
ClientCCHandle_t handle;
|
||||
float flWeight;
|
||||
bool bExclusive;
|
||||
};
|
||||
|
||||
CUtlVector< SetWeightParams_t > m_colorCorrectionWeights;
|
||||
|
||||
void CommitColorCorrectionWeights();
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
void UpdateColorCorrectionEntities( C_BasePlayer *pPlayer, float ccScale, C_ColorCorrection **pList, int listCount );
|
||||
void UpdateColorCorrectionVolumes( C_BasePlayer *pPlayer, float ccScale, C_ColorCorrectionVolume **pList, int listCount );
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Singleton access
|
||||
|
@ -25,6 +25,13 @@ extern ConVar r_drawmodeldecals;
|
||||
|
||||
ImpactSoundRouteFn g_pImpactSoundRouteFn = NULL;
|
||||
|
||||
#ifdef MAPBASE
|
||||
ConVar g_ragdoll_steal_impacts_client( "g_ragdoll_steal_impacts_client", "1", FCVAR_NONE, "Allows clientside death ragdolls to \"steal\" impacts from their source entities. This fixes issues with NPCs dying before decals are applied." );
|
||||
ConVar g_ragdoll_steal_impacts_server( "g_ragdoll_steal_impacts_server", "1", FCVAR_NONE, "Allows serverside death ragdolls to \"steal\" impacts from their source entities. This fixes issues with NPCs dying before decals are applied." );
|
||||
|
||||
ConVar g_ragdoll_client_impact_decals( "g_ragdoll_client_impact_decals", "1", FCVAR_NONE, "Applies decals to clientside ragdolls when they are hit." );
|
||||
#endif
|
||||
|
||||
//==========================================================================================================================
|
||||
// RAGDOLL ENUMERATOR
|
||||
//==========================================================================================================================
|
||||
@ -32,7 +39,11 @@ CRagdollEnumerator::CRagdollEnumerator( Ray_t& shot, int iDamageType )
|
||||
{
|
||||
m_rayShot = shot;
|
||||
m_iDamageType = iDamageType;
|
||||
#ifdef MAPBASE
|
||||
m_pHitEnt = NULL;
|
||||
#else
|
||||
m_bHit = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
IterationRetval_t CRagdollEnumerator::EnumElement( IHandleEntity *pHandleEntity )
|
||||
@ -57,7 +68,11 @@ IterationRetval_t CRagdollEnumerator::EnumElement( IHandleEntity *pHandleEntity
|
||||
if ( tr.fraction < 1.0 )
|
||||
{
|
||||
pModel->ImpactTrace( &tr, m_iDamageType, NULL );
|
||||
#ifdef MAPBASE
|
||||
m_pHitEnt = pModel;
|
||||
#else
|
||||
m_bHit = true;
|
||||
#endif
|
||||
|
||||
//FIXME: Yes? No?
|
||||
return ITERATION_STOP;
|
||||
@ -84,6 +99,22 @@ bool FX_AffectRagdolls( Vector vecOrigin, Vector vecStart, int iDamageType )
|
||||
return ragdollEnum.Hit();
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
C_BaseAnimating *FX_AffectRagdolls_GetHit( Vector vecOrigin, Vector vecStart, int iDamageType )
|
||||
{
|
||||
// don't do this when lots of ragdolls are simulating
|
||||
if ( s_RagdollLRU.CountRagdolls(true) > 1 )
|
||||
return false;
|
||||
Ray_t shotRay;
|
||||
shotRay.Init( vecStart, vecOrigin );
|
||||
|
||||
CRagdollEnumerator ragdollEnum( shotRay, iDamageType );
|
||||
partition->EnumerateElementsAlongRay( PARTITION_CLIENT_RESPONSIVE_EDICTS, shotRay, false, &ragdollEnum );
|
||||
|
||||
return ragdollEnum.GetHit();
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : &data -
|
||||
@ -104,6 +135,22 @@ bool Impact( Vector &vecOrigin, Vector &vecStart, int iMaterial, int iDamageType
|
||||
|
||||
Assert ( pEntity );
|
||||
|
||||
#ifdef MAPBASE
|
||||
// If the entity already has a ragdoll that was created on the current tick, use that ragdoll instead.
|
||||
// This allows the killing damage's decals to show up on the ragdoll.
|
||||
if (C_BaseAnimating *pAnimating = pEntity->GetBaseAnimating())
|
||||
{
|
||||
if (pAnimating->m_pClientsideRagdoll && WasRagdollCreatedOnCurrentTick( pAnimating->m_pClientsideRagdoll ) && g_ragdoll_steal_impacts_client.GetBool())
|
||||
{
|
||||
pEntity = pAnimating->m_pClientsideRagdoll;
|
||||
}
|
||||
else if (pAnimating->m_pServerRagdoll && WasRagdollCreatedOnCurrentTick( pAnimating->m_pServerRagdoll ) && g_ragdoll_steal_impacts_server.GetBool())
|
||||
{
|
||||
pEntity = pAnimating->m_pServerRagdoll;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Clear out the trace
|
||||
memset( &tr, 0, sizeof(trace_t));
|
||||
tr.fraction = 1.0f;
|
||||
@ -115,13 +162,52 @@ bool Impact( Vector &vecOrigin, Vector &vecStart, int iMaterial, int iDamageType
|
||||
VectorMA( vecStart, flLength + 8.0f, shotDir, traceExt );
|
||||
|
||||
// Attempt to hit ragdolls
|
||||
|
||||
|
||||
bool bHitRagdoll = false;
|
||||
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( !pEntity->IsClientCreated() )
|
||||
{
|
||||
C_BaseAnimating *pRagdoll = FX_AffectRagdolls_GetHit( vecOrigin, vecStart, iDamageType );
|
||||
if (pRagdoll)
|
||||
{
|
||||
bHitRagdoll = true;
|
||||
|
||||
if (g_ragdoll_client_impact_decals.GetBool())
|
||||
{
|
||||
pEntity = pRagdoll;
|
||||
|
||||
// HACKHACK: Get the ragdoll's nearest bone for its material
|
||||
int iNearestMaterial = 0;
|
||||
float flNearestDistSqr = FLT_MAX;
|
||||
|
||||
IPhysicsObject *pList[VPHYSICS_MAX_OBJECT_LIST_COUNT];
|
||||
int count = pEntity->VPhysicsGetObjectList( pList, ARRAYSIZE(pList) );
|
||||
for ( int i = 0; i < count; i++ )
|
||||
{
|
||||
Vector vecPosition;
|
||||
QAngle angAngles;
|
||||
pList[i]->GetPosition( &vecPosition, &angAngles );
|
||||
float flDistSqr = (vecStart - vecPosition).LengthSqr();
|
||||
if (flDistSqr < flNearestDistSqr)
|
||||
{
|
||||
iNearestMaterial = pList[i]->GetMaterialIndex();
|
||||
flNearestDistSqr = flDistSqr;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the material from the surfaceprop
|
||||
surfacedata_t *psurfaceData = physprops->GetSurfaceData( iNearestMaterial );
|
||||
iMaterial = psurfaceData->game.material;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
if ( !pEntity->IsClientCreated() )
|
||||
{
|
||||
bHitRagdoll = FX_AffectRagdolls( vecOrigin, vecStart, iDamageType );
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( (nFlags & IMPACT_NODECAL) == 0 )
|
||||
{
|
||||
|
@ -58,12 +58,21 @@ public:
|
||||
// Actual work code
|
||||
virtual IterationRetval_t EnumElement( IHandleEntity *pHandleEntity );
|
||||
|
||||
#ifdef MAPBASE
|
||||
bool Hit( void ) const { return m_pHitEnt != NULL; }
|
||||
C_BaseAnimating *GetHit( void ) { return m_pHitEnt; }
|
||||
#else
|
||||
bool Hit( void ) const { return m_bHit; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
Ray_t m_rayShot;
|
||||
int m_iDamageType;
|
||||
#ifdef MAPBASE
|
||||
C_BaseAnimating *m_pHitEnt;
|
||||
#else
|
||||
bool m_bHit;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // FX_IMPACT_H
|
||||
|
@ -146,6 +146,32 @@ bool CBaseViewport::LoadHudAnimations( void )
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Reloads HUD animations after loading a map-specific HUD animations file.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseViewport::ReloadHudAnimations( void )
|
||||
{
|
||||
// Force a reload
|
||||
if ( LoadHudAnimations() == false )
|
||||
{
|
||||
// Fall back to just the main
|
||||
if ( m_pAnimController->SetScriptFile( GetVPanel(), "scripts/HudAnimations.txt", true ) == false )
|
||||
{
|
||||
Assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Loads a map-specific HUD animations file.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBaseViewport::LoadCustomHudAnimations( const char *pszFile )
|
||||
{
|
||||
return m_pAnimController->SetScriptFile( GetVPanel(), pszFile, true );
|
||||
}
|
||||
#endif
|
||||
|
||||
//================================================================
|
||||
CBaseViewport::CBaseViewport() : vgui::EditablePanel( NULL, "CBaseViewport")
|
||||
{
|
||||
|
@ -73,6 +73,10 @@ public:
|
||||
public: // IGameEventListener:
|
||||
virtual void FireGameEvent( IGameEvent * event);
|
||||
|
||||
#ifdef MAPBASE
|
||||
bool LoadCustomHudAnimations( const char *pszFile );
|
||||
void ReloadHudAnimations( void );
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -32,6 +32,16 @@ struct creditname_t
|
||||
float flTimeAdd;
|
||||
float flTimeStart;
|
||||
int iSlot;
|
||||
|
||||
#ifdef MAPBASE
|
||||
// New credits stuff
|
||||
|
||||
Color cColorOverride;
|
||||
|
||||
// Images
|
||||
int iImageID = -1;
|
||||
float flImageScale = 1.0f;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define CREDITS_FILE "scripts/credits.txt"
|
||||
@ -93,6 +103,10 @@ private:
|
||||
void DrawOutroCreditsName( void );
|
||||
void DrawIntroCreditsName( void );
|
||||
void DrawLogo( void );
|
||||
#ifdef MAPBASE
|
||||
void DrawOutroCreditFont( const char *pCreditName, float flYPos, vgui::HFont hTFont, const Color &cColor, int iScreenWidth, int iDivisor = 2 );
|
||||
void DrawOutroCreditTexture( int iImageID, float flYPos, float flImageScale, const Color &cColor, int iScreenWidth, int iDivisor = 2 );
|
||||
#endif
|
||||
|
||||
void PrepareLogo( float flTime );
|
||||
void PrepareOutroCredits( void );
|
||||
@ -102,6 +116,10 @@ private:
|
||||
|
||||
void PrepareLine( vgui::HFont hFont, char const *pchLine );
|
||||
|
||||
#ifdef MAPBASE
|
||||
int GetOrAllocateImageID( const char *szFileName );
|
||||
#endif
|
||||
|
||||
CPanelAnimationVar( vgui::HFont, m_hTextFont, "TextFont", "Default" );
|
||||
CPanelAnimationVar( Color, m_TextColor, "TextColor", "FgColor" );
|
||||
|
||||
@ -110,7 +128,10 @@ private:
|
||||
float m_flScrollTime;
|
||||
float m_flSeparation;
|
||||
#ifdef MAPBASE
|
||||
int m_iEndLines;
|
||||
int m_iEndLines;
|
||||
float m_flEndLinesFadeHoldTime;
|
||||
bool m_bAllowColumns;
|
||||
CUtlDict<int, int> m_ImageDict;
|
||||
#endif
|
||||
float m_flFadeTime;
|
||||
bool m_bLastOneInPlace;
|
||||
@ -202,6 +223,20 @@ void CHudCredits::Clear( void )
|
||||
m_bLastOneInPlace = false;
|
||||
m_Alpha = m_TextColor[3];
|
||||
m_iLogoState = LOGO_FADEOFF;
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( surface() )
|
||||
{
|
||||
for (int i = m_ImageDict.Count()-1; i >= 0; i--)
|
||||
{
|
||||
if (m_ImageDict[i] != -1)
|
||||
{
|
||||
surface()->DestroyTextureID( m_ImageDict[i] );
|
||||
m_ImageDict.RemoveAt( i );
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -229,7 +264,11 @@ void CHudCredits::ReadNames( KeyValues *pKeyValue )
|
||||
{
|
||||
creditname_t Credits;
|
||||
V_strcpy_safe( Credits.szCreditName, pKVNames->GetName() );
|
||||
#ifdef MAPBASE
|
||||
V_strcpy_safe( Credits.szFontName, pKVNames->GetString( (const char *)NULL, "Default" ) );
|
||||
#else
|
||||
V_strcpy_safe( Credits.szFontName, pKeyValue->GetString( Credits.szCreditName, "Default" ) );
|
||||
#endif
|
||||
|
||||
m_CreditsList.AddToTail( Credits );
|
||||
pKVNames = pKVNames->GetNextKey();
|
||||
@ -248,6 +287,8 @@ void CHudCredits::ReadParams( KeyValues *pKeyValue )
|
||||
m_flSeparation = pKeyValue->GetFloat( "separation", 5 );
|
||||
#ifdef MAPBASE
|
||||
m_iEndLines = pKeyValue->GetInt( "endlines", 1 );
|
||||
m_flEndLinesFadeHoldTime = pKeyValue->GetFloat( "endlines_fadeholdtime", ( IsConsole() ? 2.0f : 10.0f ) ); // "360 certification requires that we not hold a static image too long."
|
||||
m_bAllowColumns = pKeyValue->GetBool( "allow_columns", false );
|
||||
#endif
|
||||
|
||||
m_flFadeInTime = pKeyValue->GetFloat( "fadeintime", 1 );
|
||||
@ -300,10 +341,46 @@ void CHudCredits::DrawOutroCreditsName( void )
|
||||
if ( pCredit == NULL )
|
||||
continue;
|
||||
|
||||
#ifdef MAPBASE
|
||||
vgui::HScheme scheme = GetScheme();
|
||||
#else
|
||||
vgui::HScheme scheme = vgui::scheme()->GetScheme( "ClientScheme" );
|
||||
vgui::HFont m_hTFont = vgui::scheme()->GetIScheme(scheme)->GetFont( pCredit->szFontName, true );
|
||||
#endif
|
||||
vgui::HFont m_hTFont = INVALID_FONT;
|
||||
|
||||
int iFontTall = surface()->GetFontTall ( m_hTFont );
|
||||
int iFontTall = 1;
|
||||
|
||||
#ifdef MAPBASE
|
||||
if (pCredit->iImageID != -1)
|
||||
{
|
||||
// Get the size of the tallest image if there's multiple
|
||||
int iFontWide;
|
||||
if (m_bAllowColumns && V_strstr( pCredit->szCreditName, "\t" ))
|
||||
{
|
||||
CUtlStringList outStrings;
|
||||
V_SplitString( pCredit->szCreditName, "\t", outStrings );
|
||||
FOR_EACH_VEC( outStrings, i )
|
||||
{
|
||||
int iTempTall;
|
||||
surface()->DrawGetTextureSize( GetOrAllocateImageID( outStrings[i] ), iFontWide, iTempTall );
|
||||
if (iTempTall > iFontTall)
|
||||
iFontTall = iTempTall;
|
||||
}
|
||||
outStrings.PurgeAndDeleteElements();
|
||||
}
|
||||
else
|
||||
{
|
||||
surface()->DrawGetTextureSize( GetOrAllocateImageID( pCredit->szCreditName ), iFontWide, iFontTall );
|
||||
}
|
||||
|
||||
iFontTall = ((float)iFontTall * pCredit->flImageScale);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
m_hTFont = vgui::scheme()->GetIScheme( scheme )->GetFont( pCredit->szFontName, true );
|
||||
iFontTall = surface()->GetFontTall( m_hTFont );
|
||||
}
|
||||
|
||||
if ( pCredit->flYPos < -iFontTall || pCredit->flYPos > iTall )
|
||||
{
|
||||
@ -317,6 +394,9 @@ void CHudCredits::DrawOutroCreditsName( void )
|
||||
Color cColor = m_TextColor;
|
||||
|
||||
#ifdef MAPBASE
|
||||
if (pCredit->cColorOverride.a() > 0)
|
||||
cColor = pCredit->cColorOverride;
|
||||
|
||||
// Some lines should stick around and fade out
|
||||
if ( i >= m_CreditsList.Count()-m_iEndLines )
|
||||
#else
|
||||
@ -333,8 +413,12 @@ void CHudCredits::DrawOutroCreditsName( void )
|
||||
{
|
||||
m_bLastOneInPlace = true;
|
||||
|
||||
#ifdef MAPBASE
|
||||
m_flFadeTime = gpGlobals->curtime + m_flEndLinesFadeHoldTime;
|
||||
#else
|
||||
// 360 certification requires that we not hold a static image too long.
|
||||
m_flFadeTime = gpGlobals->curtime + ( IsConsole() ? 2.0f : 10.0f );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -364,6 +448,50 @@ void CHudCredits::DrawOutroCreditsName( void )
|
||||
if ( pCredit->bActive == false )
|
||||
continue;
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Credits separated by tabs should appear divided
|
||||
if (m_bAllowColumns && V_strstr( pCredit->szCreditName, "\t" ))
|
||||
{
|
||||
CUtlStringList outStrings;
|
||||
V_SplitString( pCredit->szCreditName, "\t", outStrings );
|
||||
int iDivisor = 1 + outStrings.Count();
|
||||
if (pCredit->iImageID != -1)
|
||||
{
|
||||
FOR_EACH_VEC( outStrings, i )
|
||||
{
|
||||
int iImageID = GetOrAllocateImageID( outStrings[i] );
|
||||
|
||||
// Center the image if needed
|
||||
int iImageWide, iImageTall = 1;
|
||||
surface()->DrawGetTextureSize( iImageID, iImageWide, iImageTall );
|
||||
if (iImageTall < iFontTall)
|
||||
{
|
||||
DrawOutroCreditTexture( iImageID, pCredit->flYPos + ((iFontTall * 0.5f) - (iImageTall * 0.5f)), pCredit->flImageScale, cColor, iWidth*(i + 1), iDivisor );
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawOutroCreditTexture( iImageID, pCredit->flYPos, pCredit->flImageScale, cColor, iWidth*(i + 1), iDivisor );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FOR_EACH_VEC( outStrings, i )
|
||||
{
|
||||
DrawOutroCreditFont( outStrings[i], pCredit->flYPos, m_hTFont, cColor, iWidth*(i + 1), iDivisor );
|
||||
}
|
||||
}
|
||||
outStrings.PurgeAndDeleteElements();
|
||||
}
|
||||
else if (pCredit->iImageID != -1)
|
||||
{
|
||||
DrawOutroCreditTexture( pCredit->iImageID, pCredit->flYPos, pCredit->flImageScale, cColor, iWidth, 2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawOutroCreditFont( pCredit->szCreditName, pCredit->flYPos, m_hTFont, cColor, iWidth, 2 );
|
||||
}
|
||||
#else
|
||||
surface()->DrawSetTextFont( m_hTFont );
|
||||
surface()->DrawSetTextColor( cColor[0], cColor[1], cColor[2], cColor[3] );
|
||||
|
||||
@ -382,9 +510,56 @@ void CHudCredits::DrawOutroCreditsName( void )
|
||||
|
||||
surface()->DrawSetTextPos( ( iWidth / 2 ) - ( iStringWidth / 2 ), pCredit->flYPos );
|
||||
surface()->DrawUnicodeString( unicode );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
void CHudCredits::DrawOutroCreditFont( const char *pCreditName, float flYPos, vgui::HFont hTFont, const Color &cColor, int iScreenWidth, int iDivisor )
|
||||
{
|
||||
surface()->DrawSetTextFont( hTFont );
|
||||
surface()->DrawSetTextColor( cColor[0], cColor[1], cColor[2], cColor[3] );
|
||||
|
||||
wchar_t unicode[256];
|
||||
|
||||
if ( pCreditName[0] == '#' )
|
||||
{
|
||||
g_pVGuiLocalize->ConstructString( unicode, sizeof(unicode), g_pVGuiLocalize->Find(pCreditName), 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
g_pVGuiLocalize->ConvertANSIToUnicode( pCreditName, unicode, sizeof( unicode ) );
|
||||
}
|
||||
|
||||
int iStringWidth = GetStringPixelWidth( unicode, hTFont );
|
||||
|
||||
// ((iScreenWidth*iMultiplier) / iDivisor)
|
||||
// When needed, just multiply iScreenWidth before sending to the function
|
||||
surface()->DrawSetTextPos( (iScreenWidth / iDivisor) - (iStringWidth / 2), flYPos );
|
||||
surface()->DrawUnicodeString( unicode );
|
||||
}
|
||||
|
||||
void CHudCredits::DrawOutroCreditTexture( int iImageID, float flYPos, float flImageScale, const Color &cColor, int iScreenWidth, int iDivisor )
|
||||
{
|
||||
int iImageWide, iImageTall;
|
||||
surface()->DrawGetTextureSize( iImageID, iImageWide, iImageTall );
|
||||
|
||||
// Scale for resolution
|
||||
flImageScale *= ((float)GetTall() / 900.0f);
|
||||
|
||||
iImageWide = ((float)(iImageWide) * flImageScale);
|
||||
iImageTall = ((float)(iImageTall) * flImageScale);
|
||||
|
||||
iImageWide /= 2;
|
||||
//iImageTall /= 2;
|
||||
iScreenWidth /= iDivisor;
|
||||
|
||||
surface()->DrawSetColor( cColor );
|
||||
surface()->DrawSetTexture( iImageID );
|
||||
surface()->DrawTexturedRect( iScreenWidth - iImageWide, flYPos, iScreenWidth + iImageWide, flYPos + iImageTall );
|
||||
}
|
||||
#endif
|
||||
|
||||
void CHudCredits::DrawLogo( void )
|
||||
{
|
||||
if( m_iLogoState == LOGO_FADEOFF )
|
||||
@ -464,7 +639,11 @@ void CHudCredits::DrawLogo( void )
|
||||
Q_snprintf( szLogoFont, sizeof( szLogoFont ), "WeaponIcons" );
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
vgui::HScheme scheme = GetScheme();
|
||||
#else
|
||||
vgui::HScheme scheme = vgui::scheme()->GetScheme( "ClientScheme" );
|
||||
#endif
|
||||
vgui::HFont m_hTFont = vgui::scheme()->GetIScheme(scheme)->GetFont( szLogoFont );
|
||||
|
||||
int iFontTall = surface()->GetFontTall ( m_hTFont );
|
||||
@ -544,14 +723,26 @@ void CHudCredits::DrawIntroCreditsName( void )
|
||||
|
||||
if ( pCredit->bActive == false )
|
||||
continue;
|
||||
|
||||
|
||||
#ifdef MAPBASE
|
||||
vgui::HScheme scheme = GetScheme();
|
||||
#else
|
||||
vgui::HScheme scheme = vgui::scheme()->GetScheme( "ClientScheme" );
|
||||
#endif
|
||||
vgui::HFont m_hTFont = vgui::scheme()->GetIScheme(scheme)->GetFont( pCredit->szFontName );
|
||||
|
||||
float localTime = gpGlobals->curtime - pCredit->flTimeStart;
|
||||
|
||||
surface()->DrawSetTextFont( m_hTFont );
|
||||
#ifdef MAPBASE
|
||||
Color cColor = m_cColor;
|
||||
if (pCredit->cColorOverride.a() > 0)
|
||||
cColor = pCredit->cColorOverride;
|
||||
|
||||
surface()->DrawSetTextColor( cColor[0], cColor[1], cColor[2], FadeBlend( m_flFadeInTime, m_flFadeOutTime, m_flFadeHoldTime + pCredit->flTimeAdd, localTime ) * cColor[3] );
|
||||
#else
|
||||
surface()->DrawSetTextColor( m_cColor[0], m_cColor[1], m_cColor[2], FadeBlend( m_flFadeInTime, m_flFadeOutTime, m_flFadeHoldTime + pCredit->flTimeAdd, localTime ) * m_cColor[3] );
|
||||
#endif
|
||||
|
||||
wchar_t unicode[256];
|
||||
g_pVGuiLocalize->ConvertANSIToUnicode( pCredit->szCreditName, unicode, sizeof( unicode ) );
|
||||
@ -692,17 +883,119 @@ void CHudCredits::PrepareOutroCredits( void )
|
||||
if ( pCredit == NULL )
|
||||
continue;
|
||||
|
||||
#ifdef MAPBASE
|
||||
vgui::HScheme scheme = GetScheme();
|
||||
#else
|
||||
vgui::HScheme scheme = vgui::scheme()->GetScheme( "ClientScheme" );
|
||||
vgui::HFont m_hTFont = vgui::scheme()->GetIScheme(scheme)->GetFont( pCredit->szFontName, true );
|
||||
#endif
|
||||
|
||||
pCredit->flYPos = iHeight;
|
||||
pCredit->bActive = false;
|
||||
#ifdef MAPBASE
|
||||
if (pCredit->szFontName[0] == '$')
|
||||
{
|
||||
if (V_strncmp( pCredit->szFontName + 1, "Image", 5 ) == 0)
|
||||
{
|
||||
if (pCredit->szFontName[6] == ';')
|
||||
{
|
||||
CUtlStringList outStrings;
|
||||
V_SplitString( pCredit->szFontName, ";", outStrings );
|
||||
FOR_EACH_VEC( outStrings, i )
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
// Get scale
|
||||
case 1:
|
||||
pCredit->flImageScale = atof( outStrings[i] );
|
||||
break;
|
||||
|
||||
iHeight += surface()->GetFontTall ( m_hTFont ) + m_flSeparation;
|
||||
// Get color
|
||||
case 2:
|
||||
int tmp[4];
|
||||
UTIL_StringToIntArray( tmp, 4, outStrings[i] );
|
||||
pCredit->cColorOverride = Color( tmp[0], tmp[1], tmp[2], tmp[3] );
|
||||
break;
|
||||
}
|
||||
}
|
||||
outStrings.PurgeAndDeleteElements();
|
||||
}
|
||||
|
||||
PrepareLine( m_hTFont, pCredit->szCreditName );
|
||||
// Get the size of the tallest image if there's multiple
|
||||
int iFontWide, iFontTall = 1;
|
||||
if (m_bAllowColumns && V_strstr( pCredit->szCreditName, "\t" ))
|
||||
{
|
||||
CUtlStringList outStrings;
|
||||
V_SplitString( pCredit->szCreditName, "\t", outStrings );
|
||||
FOR_EACH_VEC( outStrings, i )
|
||||
{
|
||||
pCredit->iImageID = GetOrAllocateImageID( outStrings[i] );
|
||||
|
||||
int iTempTall;
|
||||
surface()->DrawGetTextureSize( pCredit->iImageID, iFontWide, iTempTall );
|
||||
if (iTempTall > iFontTall)
|
||||
iFontTall = iTempTall;
|
||||
}
|
||||
outStrings.PurgeAndDeleteElements();
|
||||
}
|
||||
else
|
||||
{
|
||||
pCredit->iImageID = GetOrAllocateImageID( pCredit->szCreditName );
|
||||
surface()->DrawGetTextureSize( pCredit->iImageID, iFontWide, iFontTall );
|
||||
}
|
||||
|
||||
pCredit->flYPos = iHeight;
|
||||
pCredit->bActive = false;
|
||||
|
||||
iHeight += ((float)iFontTall * pCredit->flImageScale * ((float)GetTall() / 900.0f)) + m_flSeparation;
|
||||
|
||||
Msg( "'%s' is image type (image scale is %f)\n", pCredit->szCreditName, pCredit->flImageScale );
|
||||
}
|
||||
else
|
||||
{
|
||||
//Msg( "'%s' is not an image type\n", pCredit->szFontName + 1 );
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
if (V_strstr( pCredit->szFontName, ";" ))
|
||||
{
|
||||
CUtlStringList outStrings;
|
||||
V_SplitString( pCredit->szFontName, ";", outStrings );
|
||||
FOR_EACH_VEC( outStrings, i )
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
// Get color
|
||||
case 1:
|
||||
int tmp[4];
|
||||
UTIL_StringToIntArray( tmp, 4, outStrings[i] );
|
||||
pCredit->cColorOverride = Color( tmp[0], tmp[1], tmp[2], tmp[3] );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Q_strncpy( pCredit->szFontName, outStrings[0], sizeof( pCredit->szFontName ) );
|
||||
outStrings.PurgeAndDeleteElements();
|
||||
}
|
||||
#endif
|
||||
|
||||
vgui::HFont m_hTFont = vgui::scheme()->GetIScheme( scheme )->GetFont( pCredit->szFontName, true );
|
||||
|
||||
pCredit->flYPos = iHeight;
|
||||
pCredit->bActive = false;
|
||||
|
||||
iHeight += surface()->GetFontTall ( m_hTFont ) + m_flSeparation;
|
||||
|
||||
PrepareLine( m_hTFont, pCredit->szCreditName );
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Check if the last line has a color override. If it does, use that as the alpha for the fadeout
|
||||
if (m_CreditsList.Tail().cColorOverride.a() != 0)
|
||||
m_Alpha = m_CreditsList.Tail().cColorOverride.a();
|
||||
#endif
|
||||
|
||||
SetActive( true );
|
||||
|
||||
g_iCreditsPixelHeight = iHeight;
|
||||
@ -721,7 +1014,34 @@ void CHudCredits::PrepareIntroCredits( void )
|
||||
if ( pCredit == NULL )
|
||||
continue;
|
||||
|
||||
#ifdef MAPBASE
|
||||
if (V_strstr( pCredit->szFontName, ";" ))
|
||||
{
|
||||
CUtlStringList outStrings;
|
||||
V_SplitString( pCredit->szFontName, ";", outStrings );
|
||||
FOR_EACH_VEC( outStrings, i )
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
// Get color
|
||||
case 1:
|
||||
int tmp[4];
|
||||
UTIL_StringToIntArray( tmp, 4, outStrings[i] );
|
||||
pCredit->cColorOverride = Color( tmp[0], tmp[1], tmp[2], tmp[3] );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Q_strncpy( pCredit->szFontName, outStrings[0], sizeof( pCredit->szFontName ) );
|
||||
outStrings.PurgeAndDeleteElements();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MAPBASE
|
||||
vgui::HScheme scheme = GetScheme();
|
||||
#else
|
||||
vgui::HScheme scheme = vgui::scheme()->GetScheme( "ClientScheme" );
|
||||
#endif
|
||||
vgui::HFont m_hTFont = vgui::scheme()->GetIScheme(scheme)->GetFont( pCredit->szFontName );
|
||||
|
||||
pCredit->flYPos = m_flY + ( iSlot * surface()->GetFontTall ( m_hTFont ) );
|
||||
@ -749,6 +1069,21 @@ void CHudCredits::PrepareIntroCredits( void )
|
||||
SetActive( true );
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
int CHudCredits::GetOrAllocateImageID( const char *szFileName )
|
||||
{
|
||||
int iIndex = m_ImageDict.Find( szFileName );
|
||||
if (iIndex == m_ImageDict.InvalidIndex())
|
||||
{
|
||||
iIndex = surface()->CreateNewTextureID();
|
||||
m_ImageDict.Insert( szFileName, iIndex );
|
||||
surface()->DrawSetTextureFile( iIndex, szFileName, true, false );
|
||||
return iIndex;
|
||||
}
|
||||
return m_ImageDict[iIndex];
|
||||
}
|
||||
#endif
|
||||
|
||||
void CHudCredits::MsgFunc_CreditsMsg( bf_read &msg )
|
||||
{
|
||||
m_iCreditsType = msg.ReadByte();
|
||||
|
@ -1612,6 +1612,9 @@ struct WorkUnitParams
|
||||
clr = Color( 255, 255, 255, 255 );
|
||||
newline = false;
|
||||
font = 0;
|
||||
#ifdef MAPBASE
|
||||
customFont = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
~WorkUnitParams()
|
||||
@ -1657,6 +1660,9 @@ struct WorkUnitParams
|
||||
Color clr;
|
||||
bool newline;
|
||||
vgui::HFont font;
|
||||
#ifdef MAPBASE
|
||||
bool customFont;
|
||||
#endif
|
||||
};
|
||||
|
||||
void CHudCloseCaption::AddWorkUnit( CCloseCaptionItem *item,
|
||||
@ -1771,27 +1777,58 @@ void CHudCloseCaption::ComputeStreamWork( int available_width, CCloseCaptionItem
|
||||
{
|
||||
AddWorkUnit( item, params );
|
||||
params.italic = !params.italic;
|
||||
#ifdef MAPBASE
|
||||
params.customFont = false;
|
||||
#endif
|
||||
}
|
||||
else if ( !wcscmp( cmd, L"B" ) )
|
||||
{
|
||||
AddWorkUnit( item, params );
|
||||
params.bold = !params.bold;
|
||||
#ifdef MAPBASE
|
||||
params.customFont = false;
|
||||
#endif
|
||||
}
|
||||
#ifdef MAPBASE
|
||||
else if ( !wcscmp( cmd, L"font" ) )
|
||||
{
|
||||
AddWorkUnit( item, params );
|
||||
vgui::IScheme *pScheme = vgui::scheme()->GetIScheme( GetScheme() );
|
||||
|
||||
if ( args[0] != 0 )
|
||||
{
|
||||
char font[64];
|
||||
g_pVGuiLocalize->ConvertUnicodeToANSI( args, font, sizeof( font ) );
|
||||
params.font = pScheme->GetFont( font );
|
||||
params.customFont = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
params.customFont = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
int font;
|
||||
if ( IsPC() )
|
||||
vgui::HFont useF = params.font;
|
||||
#ifdef MAPBASE
|
||||
if (params.customFont == false)
|
||||
#endif
|
||||
{
|
||||
font = params.GetFontNumber();
|
||||
int font;
|
||||
if ( IsPC() )
|
||||
{
|
||||
font = params.GetFontNumber();
|
||||
}
|
||||
else
|
||||
{
|
||||
font = streamlen >= cc_smallfontlength.GetInt() ? CCFONT_SMALL : CCFONT_NORMAL;
|
||||
}
|
||||
useF = m_hFonts[font];
|
||||
params.font = useF;
|
||||
}
|
||||
else
|
||||
{
|
||||
font = streamlen >= cc_smallfontlength.GetInt() ? CCFONT_SMALL : CCFONT_NORMAL;
|
||||
}
|
||||
vgui::HFont useF = m_hFonts[font];
|
||||
params.font = useF;
|
||||
|
||||
int w, h;
|
||||
|
||||
@ -2630,6 +2667,124 @@ void CHudCloseCaption::InitCaptionDictionary( const char *dbfile )
|
||||
g_AsyncCaptionResourceManager.SetDbInfo( m_AsyncCaptions );
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
void CHudCloseCaption::AddAdditionalCaptionDictionary( const char *dbfile, CUtlVector<CUtlSymbol> &outPathSymbols )
|
||||
{
|
||||
CGMsg( 1, CON_GROUP_MAPBASE_MISC, "Adding additional caption dictionary \"%s\"\n", dbfile );
|
||||
|
||||
g_AsyncCaptionResourceManager.Clear();
|
||||
|
||||
char searchPaths[4096];
|
||||
filesystem->GetSearchPath( "MOD", true, searchPaths, sizeof( searchPaths ) );
|
||||
|
||||
for ( char *path = strtok( searchPaths, ";" ); path; path = strtok( NULL, ";" ) )
|
||||
{
|
||||
if ( IsX360() && ( filesystem->GetDVDMode() == DVDMODE_STRICT ) && !V_stristr( path, ".zip" ) )
|
||||
{
|
||||
// only want zip paths
|
||||
continue;
|
||||
}
|
||||
|
||||
char fullpath[MAX_PATH];
|
||||
Q_snprintf( fullpath, sizeof( fullpath ), "%s%s", path, dbfile );
|
||||
Q_FixSlashes( fullpath );
|
||||
|
||||
if ( IsX360() )
|
||||
{
|
||||
char fullpath360[MAX_PATH];
|
||||
UpdateOrCreateCaptionFile( fullpath, fullpath360, sizeof( fullpath360 ) );
|
||||
Q_strncpy( fullpath, fullpath360, sizeof( fullpath ) );
|
||||
}
|
||||
|
||||
// Seach for this dictionary. If it already exists, remove it.
|
||||
for (int i = 0; i < m_AsyncCaptions.Count(); ++i)
|
||||
{
|
||||
if (FStrEq( m_AsyncCaptions[i].m_DataBaseFile.String(), fullpath ))
|
||||
{
|
||||
m_AsyncCaptions.Remove( i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FileHandle_t fh = filesystem->Open( fullpath, "rb" );
|
||||
if ( FILESYSTEM_INVALID_HANDLE != fh )
|
||||
{
|
||||
MEM_ALLOC_CREDIT();
|
||||
|
||||
CUtlBuffer dirbuffer;
|
||||
|
||||
AsyncCaption_t& entry = m_AsyncCaptions[ m_AsyncCaptions.AddToTail() ];
|
||||
|
||||
// Read the header
|
||||
filesystem->Read( &entry.m_Header, sizeof( entry.m_Header ), fh );
|
||||
if ( entry.m_Header.magic != COMPILED_CAPTION_FILEID )
|
||||
Error( "Invalid file id for %s\n", fullpath );
|
||||
if ( entry.m_Header.version != COMPILED_CAPTION_VERSION )
|
||||
Error( "Invalid file version for %s\n", fullpath );
|
||||
if ( entry.m_Header.directorysize < 0 || entry.m_Header.directorysize > 64 * 1024 )
|
||||
Error( "Invalid directory size %d for %s\n", entry.m_Header.directorysize, fullpath );
|
||||
//if ( entry.m_Header.blocksize != MAX_BLOCK_SIZE )
|
||||
// Error( "Invalid block size %d, expecting %d for %s\n", entry.m_Header.blocksize, MAX_BLOCK_SIZE, fullpath );
|
||||
|
||||
int directoryBytes = entry.m_Header.directorysize * sizeof( CaptionLookup_t );
|
||||
entry.m_CaptionDirectory.EnsureCapacity( entry.m_Header.directorysize );
|
||||
dirbuffer.EnsureCapacity( directoryBytes );
|
||||
|
||||
filesystem->Read( dirbuffer.Base(), directoryBytes, fh );
|
||||
filesystem->Close( fh );
|
||||
|
||||
entry.m_CaptionDirectory.CopyArray( (const CaptionLookup_t *)dirbuffer.PeekGet(), entry.m_Header.directorysize );
|
||||
entry.m_CaptionDirectory.RedoSort( true );
|
||||
|
||||
entry.m_DataBaseFile = fullpath;
|
||||
outPathSymbols.AddToTail( entry.m_DataBaseFile );
|
||||
}
|
||||
}
|
||||
|
||||
g_AsyncCaptionResourceManager.SetDbInfo( m_AsyncCaptions );
|
||||
}
|
||||
|
||||
void CHudCloseCaption::AddCustomCaptionFile( char const *file, CUtlVector<CUtlSymbol> &outPathSymbols )
|
||||
{
|
||||
//
|
||||
// 'file' should be something like "maps/mapbase_demo01_closecaption_%language%"
|
||||
//
|
||||
|
||||
CGMsg( 1, CON_GROUP_MAPBASE_MISC, "Adding custom caption file \"%s\"\n", file );
|
||||
|
||||
if (!IsX360())
|
||||
{
|
||||
g_pVGuiLocalize->AddFile( file, "MOD", true );
|
||||
}
|
||||
|
||||
char uilanguage[64];
|
||||
engine->GetUILanguage( uilanguage, sizeof( uilanguage ) );
|
||||
|
||||
char dbfile[512];
|
||||
V_StrSubst( file, "%language%", uilanguage, dbfile, sizeof( dbfile ) );
|
||||
V_SetExtension( dbfile, ".dat", sizeof( dbfile ) );
|
||||
AddAdditionalCaptionDictionary( dbfile, outPathSymbols );
|
||||
}
|
||||
|
||||
void CHudCloseCaption::RemoveCaptionDictionary( const CUtlSymbol &dbFileSymbol )
|
||||
{
|
||||
//
|
||||
// 'file' should be something like "maps/mapbase_demo01_closecaption_%language%"
|
||||
//
|
||||
|
||||
CGMsg( 1, CON_GROUP_MAPBASE_MISC, "Removing custom caption file \"%s\"\n", dbFileSymbol.String() );
|
||||
|
||||
for (int i = 0; i < m_AsyncCaptions.Count(); ++i)
|
||||
{
|
||||
if ( m_AsyncCaptions[i].m_DataBaseFile == dbFileSymbol )
|
||||
{
|
||||
m_AsyncCaptions.Remove( i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void CHudCloseCaption::OnFinishAsyncLoad( int nFileIndex, int nBlockNum, AsyncCaptionData_t *pData )
|
||||
{
|
||||
// Fill in data for all users of pData->m_nBlockNum
|
||||
|
@ -111,6 +111,11 @@ public:
|
||||
void PlayRandomCaption();
|
||||
|
||||
void InitCaptionDictionary( char const *dbfile );
|
||||
#ifdef MAPBASE
|
||||
void AddAdditionalCaptionDictionary( char const *dbfile, CUtlVector<CUtlSymbol> &outPathSymbols );
|
||||
void AddCustomCaptionFile( char const *file, CUtlVector<CUtlSymbol> &outPathSymbols );
|
||||
void RemoveCaptionDictionary( const CUtlSymbol &dbFileSymbol );
|
||||
#endif
|
||||
void OnFinishAsyncLoad( int nFileIndex, int nBlockNum, AsyncCaptionData_t *pData );
|
||||
|
||||
void Flush();
|
||||
@ -133,6 +138,11 @@ public:
|
||||
|
||||
void FindSound( char const *pchANSI );
|
||||
|
||||
#ifdef MAPBASE
|
||||
inline bool IsUsingCommentaryDimensions() const { return m_bUsingCommentaryDimensions; }
|
||||
inline void SetUsingCommentaryDimensions( bool bToggle ) { m_bUsingCommentaryDimensions = bToggle; }
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
struct CaptionRepeat
|
||||
@ -212,6 +222,10 @@ private:
|
||||
bool m_bVisibleDueToDirect;
|
||||
bool m_bPaintDebugInfo;
|
||||
CUtlSymbol m_CurrentLanguage;
|
||||
|
||||
#ifdef MAPBASE
|
||||
bool m_bUsingCommentaryDimensions;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // HUD_CLOSECAPTION_H
|
||||
|
@ -112,6 +112,11 @@ public:
|
||||
|
||||
virtual bool CanRecordDemo( char *errorMsg, int length ) const = 0;
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
virtual void OnColorCorrectionWeightsReset( void ) = 0;
|
||||
virtual float GetColorCorrectionScale( void ) const = 0;
|
||||
#endif
|
||||
|
||||
virtual void ComputeVguiResConditions( KeyValues *pkvConditions ) = 0;
|
||||
|
||||
//=============================================================================
|
||||
|
@ -115,6 +115,13 @@ public:
|
||||
virtual void SetScreenOverlayMaterial( IMaterial *pMaterial ) = 0;
|
||||
virtual IMaterial *GetScreenOverlayMaterial( ) = 0;
|
||||
|
||||
#ifdef MAPBASE
|
||||
virtual void SetIndexedScreenOverlayMaterial( int i, IMaterial *pMaterial ) = 0;
|
||||
virtual IMaterial *GetIndexedScreenOverlayMaterial( int i ) = 0;
|
||||
virtual void ResetIndexedScreenOverlays() = 0;
|
||||
virtual int GetMaxIndexedScreenOverlays() const = 0;
|
||||
#endif
|
||||
|
||||
virtual void WriteSaveGameScreenshot( const char *pFilename ) = 0;
|
||||
virtual void WriteSaveGameScreenshotOfSize( const char *pFilename, int width, int height, bool bCreatePowerOf2Padded = false, bool bWriteVTF = false ) = 0;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============//
|
||||
//
|
||||
// Purpose: Recreates Portal 2 linked_portal_door functionality using SDK code only.
|
||||
// Purpose: Recreates Portal 2 linked_portal_door visual functionality using SDK code only.
|
||||
// (basically a combination of point_camera and func_reflective_glass)
|
||||
//
|
||||
// $NoKeywords: $
|
||||
@ -120,8 +120,8 @@ C_FuncFakeWorldPortal *IsFakeWorldPortalInView( const CViewSetup& view, cplane_t
|
||||
//-----------------------------------------------------------------------------
|
||||
// Iterates through fake world portals instead of just picking one
|
||||
//-----------------------------------------------------------------------------
|
||||
C_FuncFakeWorldPortal *NextFakeWorldPortal( C_FuncFakeWorldPortal *pStart, const CViewSetup& view, cplane_t &plane,
|
||||
const Frustum_t &frustum )
|
||||
C_FuncFakeWorldPortal *NextFakeWorldPortal( C_FuncFakeWorldPortal *pStart, const CViewSetup& view,
|
||||
cplane_t &plane, Vector &vecPlaneOrigin, const Frustum_t &frustum )
|
||||
{
|
||||
// Early out if no cameras
|
||||
C_FuncFakeWorldPortal *pReflectiveGlass = NULL;
|
||||
@ -167,6 +167,7 @@ C_FuncFakeWorldPortal *NextFakeWorldPortal( C_FuncFakeWorldPortal *pStart, const
|
||||
if ( !pReflectiveGlass->m_hTargetPlane )
|
||||
continue;
|
||||
|
||||
vecPlaneOrigin = vecOrigin;
|
||||
return pReflectiveGlass;
|
||||
}
|
||||
}
|
||||
|
@ -55,8 +55,8 @@ public:
|
||||
//-----------------------------------------------------------------------------
|
||||
C_FuncFakeWorldPortal *IsFakeWorldPortalInView( const CViewSetup& view, cplane_t &plane );
|
||||
|
||||
C_FuncFakeWorldPortal *NextFakeWorldPortal( C_FuncFakeWorldPortal *pStart, const CViewSetup& view, cplane_t &plane,
|
||||
const Frustum_t &frustum );
|
||||
C_FuncFakeWorldPortal *NextFakeWorldPortal( C_FuncFakeWorldPortal *pStart, const CViewSetup& view,
|
||||
cplane_t &plane, Vector &vecPlaneOrigin, const Frustum_t &frustum );
|
||||
|
||||
|
||||
#endif // C_FUNC_FAKE_WORLDPORTAL
|
||||
|
@ -157,11 +157,34 @@ void C_TextDisplayPanel::UpdateText()
|
||||
m_pDisplayTextLabel->SetText( m_hScreenEntity->GetDisplayText() );
|
||||
|
||||
//SetSize( m_hScreenEntity->GetTextSize(), m_hScreenEntity->GetTextSize() );
|
||||
SetSize( m_hScreenEntity->GetResolution(), m_hScreenEntity->GetResolution() );
|
||||
m_pDisplayTextLabel->SetSize( m_hScreenEntity->GetResolution(), m_hScreenEntity->GetResolution() );
|
||||
//m_pDisplayTextLabel->SetSize( m_hScreenEntity->GetTextSize(), m_hScreenEntity->GetTextSize() );
|
||||
|
||||
Label::Alignment iAlignment = m_hScreenEntity->GetContentAlignment();
|
||||
|
||||
switch (iAlignment)
|
||||
{
|
||||
// Use a special scaling method when using a south alignment
|
||||
case Label::Alignment::a_southwest:
|
||||
case Label::Alignment::a_south:
|
||||
case Label::Alignment::a_southeast:
|
||||
int lW, lT;
|
||||
m_pDisplayTextLabel->GetContentSize( lW, lT );
|
||||
SetSize( m_hScreenEntity->GetResolution(), lT );
|
||||
m_pDisplayTextLabel->SetSize( m_hScreenEntity->GetResolution(), lT );
|
||||
|
||||
float sW, sT;
|
||||
m_hVGUIScreen->GetSize( sW, sT );
|
||||
//Msg( "Screen width: %f, new height: %f\n", sW, sW * (lT / m_hScreenEntity->GetResolution()) );
|
||||
m_hVGUIScreen->SetHeight( sW * ((float)lT / (float)m_hScreenEntity->GetResolution()) );
|
||||
m_hVGUIScreen->SetPixelHeight( lT );
|
||||
break;
|
||||
|
||||
default:
|
||||
SetSize( m_hScreenEntity->GetResolution(), m_hScreenEntity->GetResolution() );
|
||||
m_pDisplayTextLabel->SetSize( m_hScreenEntity->GetResolution(), m_hScreenEntity->GetResolution() );
|
||||
break;
|
||||
}
|
||||
|
||||
m_pDisplayTextLabel->SetContentAlignment( iAlignment );
|
||||
|
||||
bool bWrap = true;
|
||||
|
@ -487,6 +487,9 @@ int C_ServerRagdoll::InternalDrawModel( int flags )
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
static ConVar g_ragdoll_server_snatch_instance( "g_ragdoll_server_snatch_instance", "1", FCVAR_NONE, "Allows serverside ragdolls to snatch their source entities' model instances in the same way clientside ragdolls do, thereby retaining decals." );
|
||||
#endif
|
||||
|
||||
CStudioHdr *C_ServerRagdoll::OnNewModel( void )
|
||||
{
|
||||
@ -509,6 +512,26 @@ CStudioHdr *C_ServerRagdoll::OnNewModel( void )
|
||||
m_iv_ragAngles.SetMaxCount( m_elementCount );
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( GetOwnerEntity() )
|
||||
{
|
||||
if (GetOwnerEntity()->GetModelName() == GetModelName())
|
||||
{
|
||||
// TODO: Is there a better place for this?
|
||||
if (GetOwnerEntity()->GetBaseAnimating())
|
||||
GetOwnerEntity()->GetBaseAnimating()->m_pServerRagdoll = this;
|
||||
|
||||
if (g_ragdoll_server_snatch_instance.GetBool())
|
||||
{
|
||||
GetOwnerEntity()->SnatchModelInstance( this );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add server ragdolls to the creation tick list
|
||||
NoteRagdollCreationTick( this );
|
||||
#endif
|
||||
|
||||
return hdr;
|
||||
}
|
||||
|
||||
|
@ -107,7 +107,7 @@ extern ConVar cl_forwardspeed;
|
||||
static ConVar v_centermove( "v_centermove", "0.15");
|
||||
static ConVar v_centerspeed( "v_centerspeed","500" );
|
||||
|
||||
#ifdef TF_CLIENT_DLL
|
||||
#if defined(TF_CLIENT_DLL) || defined(MAPBASE)
|
||||
// 54 degrees approximates a 35mm camera - we determined that this makes the viewmodels
|
||||
// and motions look the most natural.
|
||||
ConVar v_viewmodel_fov( "viewmodel_fov", "54", FCVAR_ARCHIVE );
|
||||
|
@ -29,6 +29,9 @@ static ConVar mat_wateroverlaysize( "mat_wateroverlaysize", "256" );
|
||||
static ConVar mat_showframebuffertexture( "mat_showframebuffertexture", "0", FCVAR_CHEAT );
|
||||
static ConVar mat_framebuffercopyoverlaysize( "mat_framebuffercopyoverlaysize", "256" );
|
||||
static ConVar mat_showcamerarendertarget( "mat_showcamerarendertarget", "0", FCVAR_CHEAT );
|
||||
#ifdef MAPBASE
|
||||
static ConVar mat_showcamerarendertarget_all( "mat_showcamerarendertarget_all", "0", FCVAR_CHEAT );
|
||||
#endif
|
||||
static ConVar mat_camerarendertargetoverlaysize( "mat_camerarendertargetoverlaysize", "256", FCVAR_CHEAT );
|
||||
static ConVar mat_hsv( "mat_hsv", "0", FCVAR_CHEAT );
|
||||
static ConVar mat_yuv( "mat_yuv", "0", FCVAR_CHEAT );
|
||||
@ -178,6 +181,11 @@ void OverlayCameraRenderTarget( const char *pszMaterialName, float flX, float fl
|
||||
pMaterial = materials->FindMaterial( pszMaterialName, TEXTURE_GROUP_OTHER, true );
|
||||
if( !IsErrorMaterial( pMaterial ) )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
// HACKHACK
|
||||
pMaterial->IncrementReferenceCount();
|
||||
#endif
|
||||
|
||||
CMatRenderContextPtr pRenderContext( materials );
|
||||
pRenderContext->Bind( pMaterial );
|
||||
IMesh* pMesh = pRenderContext->GetDynamicMesh( true );
|
||||
@ -203,6 +211,11 @@ void OverlayCameraRenderTarget( const char *pszMaterialName, float flX, float fl
|
||||
|
||||
meshBuilder.End();
|
||||
pMesh->Draw();
|
||||
|
||||
#ifdef MAPBASE
|
||||
// HACKHACK
|
||||
pMaterial->DecrementReferenceCount();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -214,7 +227,11 @@ static void OverlayFrameBufferTexture( int nFrameBufferIndex )
|
||||
IMaterial *pMaterial;
|
||||
char buf[MAX_PATH];
|
||||
Q_snprintf( buf, MAX_PATH, "debug/debugfbtexture%d", nFrameBufferIndex );
|
||||
#ifdef MAPBASE
|
||||
pMaterial = materials->FindMaterial( buf, NULL, true );
|
||||
#else
|
||||
pMaterial = materials->FindMaterial( buf, TEXTURE_GROUP_OTHER, true );
|
||||
#endif
|
||||
if( !IsErrorMaterial( pMaterial ) )
|
||||
{
|
||||
CMatRenderContextPtr pRenderContext( materials );
|
||||
@ -586,12 +603,52 @@ void CDebugViewRender::Draw2DDebuggingInfo( const CViewSetup &view )
|
||||
|
||||
if ( mat_showcamerarendertarget.GetBool() )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
float w = mat_camerarendertargetoverlaysize.GetFloat();
|
||||
float h = mat_camerarendertargetoverlaysize.GetFloat();
|
||||
#else
|
||||
float w = mat_wateroverlaysize.GetFloat();
|
||||
float h = mat_wateroverlaysize.GetFloat();
|
||||
#endif
|
||||
#ifdef PORTAL
|
||||
g_pPortalRender->OverlayPortalRenderTargets( w, h );
|
||||
#else
|
||||
|
||||
#ifdef MAPBASE
|
||||
int iCameraNum = mat_showcamerarendertarget.GetInt();
|
||||
|
||||
if (iCameraNum == 1) // Display the default camera
|
||||
{
|
||||
OverlayCameraRenderTarget( "debug/debugcamerarendertarget", 0, 0, w, h );
|
||||
}
|
||||
else if (mat_showcamerarendertarget_all.GetBool()) // Display all cameras
|
||||
{
|
||||
OverlayCameraRenderTarget( "debug/debugcamerarendertarget", 0, 0, w, h );
|
||||
|
||||
// Already showed one camera
|
||||
iCameraNum--;
|
||||
|
||||
// Show Mapbase's cameras
|
||||
char szTextureName[48];
|
||||
for (int i = 0; i < iCameraNum; i++)
|
||||
{
|
||||
V_snprintf( szTextureName, sizeof( szTextureName ), "debug/debugcamerarendertarget_camera%i", i );
|
||||
|
||||
// Show them vertically if the cvar is set to 2
|
||||
if (mat_showcamerarendertarget_all.GetInt() == 2)
|
||||
OverlayCameraRenderTarget( szTextureName, 0, h * (i + 1), w, h );
|
||||
else
|
||||
OverlayCameraRenderTarget( szTextureName, w * (i + 1), 0, w, h );
|
||||
}
|
||||
}
|
||||
else // Display one of the new cameras
|
||||
{
|
||||
OverlayCameraRenderTarget( VarArgs( "debug/debugcamerarendertarget_camera%i", iCameraNum-2 ), 0, 0, w, h );
|
||||
}
|
||||
#else
|
||||
OverlayCameraRenderTarget( "debug/debugcamerarendertarget", 0, 0, w, h );
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -655,6 +712,57 @@ CON_COMMAND_F( r_screenoverlay, "Draw specified material as an overlay", FCVAR_C
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
// The same as above, but using the new indexed overlays
|
||||
//-----------------------------------------------------------------------------
|
||||
CON_COMMAND_F( r_screenoverlay_indexed, "Draw specified material as an overlay in the specified index", FCVAR_CHEAT|FCVAR_SERVER_CAN_EXECUTE )
|
||||
{
|
||||
if( args.ArgC() == 3 )
|
||||
{
|
||||
int index = atoi( args[1] );
|
||||
if (index < 0 || index >= MAX_SCREEN_OVERLAYS)
|
||||
{
|
||||
Warning( "r_screenoverlay_indexed: '%i' is out of range (should be 0-9)\n", index );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !Q_stricmp( "off", args[2] ) )
|
||||
{
|
||||
view->SetIndexedScreenOverlayMaterial( index, NULL );
|
||||
}
|
||||
else
|
||||
{
|
||||
IMaterial *pMaterial = materials->FindMaterial( args[2], TEXTURE_GROUP_OTHER, false );
|
||||
if ( !IsErrorMaterial( pMaterial ) )
|
||||
{
|
||||
view->SetIndexedScreenOverlayMaterial( index, pMaterial );
|
||||
}
|
||||
else
|
||||
{
|
||||
view->SetIndexedScreenOverlayMaterial( index, NULL );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( args.ArgC() == 2 )
|
||||
{
|
||||
int index = atoi( args[1] );
|
||||
if (index < 0 || index >= MAX_SCREEN_OVERLAYS)
|
||||
{
|
||||
Warning( "r_screenoverlay_indexed: '%i' is out of range (should be 0-9)\n", index );
|
||||
return;
|
||||
}
|
||||
|
||||
IMaterial *pMaterial = view->GetIndexedScreenOverlayMaterial( index );
|
||||
Warning( "r_screenoverlay_indexed %i: %s\n", index, pMaterial ? pMaterial->GetName() : "off" );
|
||||
}
|
||||
else
|
||||
{
|
||||
Warning( "Format: r_screenoverlay_indexed <index> <material> %s\n" );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Used to verify frame syncing.
|
||||
void CDebugViewRender::GenerateOverdrawForTesting()
|
||||
{
|
||||
|
@ -76,6 +76,7 @@
|
||||
|
||||
#ifdef MAPBASE
|
||||
#include "mapbase/c_func_fake_worldportal.h"
|
||||
#include "colorcorrectionmgr.h"
|
||||
#endif
|
||||
|
||||
// Projective textures
|
||||
@ -1218,6 +1219,73 @@ IMaterial *CViewRender::GetScreenOverlayMaterial( )
|
||||
}
|
||||
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Sets the screen space effect material (can't be done during rendering)
|
||||
//-----------------------------------------------------------------------------
|
||||
void CViewRender::SetIndexedScreenOverlayMaterial( int i, IMaterial *pMaterial )
|
||||
{
|
||||
if (i < 0 || i >= MAX_SCREEN_OVERLAYS)
|
||||
return;
|
||||
|
||||
m_IndexedScreenOverlayMaterials[i].Init( pMaterial );
|
||||
|
||||
if (pMaterial == NULL)
|
||||
{
|
||||
// Check if we should set to false
|
||||
int i;
|
||||
for (i = 0; i < MAX_SCREEN_OVERLAYS; i++)
|
||||
{
|
||||
if (m_IndexedScreenOverlayMaterials[i] != NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == MAX_SCREEN_OVERLAYS)
|
||||
m_bUsingIndexedScreenOverlays = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bUsingIndexedScreenOverlays = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
IMaterial *CViewRender::GetIndexedScreenOverlayMaterial( int i )
|
||||
{
|
||||
if (i < 0 || i >= MAX_SCREEN_OVERLAYS)
|
||||
return NULL;
|
||||
|
||||
return m_IndexedScreenOverlayMaterials[i];
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
void CViewRender::ResetIndexedScreenOverlays()
|
||||
{
|
||||
for (int i = 0; i < MAX_SCREEN_OVERLAYS; i++)
|
||||
{
|
||||
m_IndexedScreenOverlayMaterials[i].Init( NULL );
|
||||
}
|
||||
|
||||
m_bUsingIndexedScreenOverlays = false;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
int CViewRender::GetMaxIndexedScreenOverlays( ) const
|
||||
{
|
||||
return MAX_SCREEN_OVERLAYS;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Performs screen space effects, if any
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1254,6 +1322,44 @@ void CViewRender::PerformScreenOverlay( int x, int y, int w, int h )
|
||||
render->ViewDrawFade( color, m_ScreenOverlayMaterial );
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
if (m_bUsingIndexedScreenOverlays)
|
||||
{
|
||||
for (int i = 0; i < MAX_SCREEN_OVERLAYS; i++)
|
||||
{
|
||||
if (!m_IndexedScreenOverlayMaterials[i])
|
||||
continue;
|
||||
|
||||
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
|
||||
|
||||
if ( m_IndexedScreenOverlayMaterials[i]->NeedsFullFrameBufferTexture() )
|
||||
{
|
||||
// FIXME: check with multi/sub-rect renders. Should this be 0,0,w,h instead?
|
||||
DrawScreenEffectMaterial( m_IndexedScreenOverlayMaterials[i], x, y, w, h );
|
||||
}
|
||||
else if ( m_IndexedScreenOverlayMaterials[i]->NeedsPowerOfTwoFrameBufferTexture() )
|
||||
{
|
||||
// First copy the FB off to the offscreen texture
|
||||
UpdateRefractTexture( x, y, w, h, true );
|
||||
|
||||
// Now draw the entire screen using the material...
|
||||
CMatRenderContextPtr pRenderContext( materials );
|
||||
ITexture *pTexture = GetPowerOfTwoFrameBufferTexture( );
|
||||
int sw = pTexture->GetActualWidth();
|
||||
int sh = pTexture->GetActualHeight();
|
||||
// Note - don't offset by x,y - already done by the viewport.
|
||||
pRenderContext->DrawScreenSpaceRectangle( m_IndexedScreenOverlayMaterials[i], 0, 0, w, h,
|
||||
0, 0, sw-1, sh-1, sw, sh );
|
||||
}
|
||||
else
|
||||
{
|
||||
byte color[4] = { 255, 255, 255, 255 };
|
||||
render->ViewDrawFade( color, m_IndexedScreenOverlayMaterials[i] );
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void CViewRender::DrawUnderwaterOverlay( void )
|
||||
@ -2005,18 +2111,19 @@ void CViewRender::RenderView( const CViewSetup &view, int nClearFlags, int whatT
|
||||
GeneratePerspectiveFrustum( view.origin, view.angles, view.zNear, view.zFar, view.fov, view.m_flAspectRatio, frustum );
|
||||
|
||||
cplane_t portalPlane;
|
||||
Vector vecPlaneOrigin;
|
||||
//C_FuncFakeWorldPortal *pPortalEnt = IsFakeWorldPortalInView( view, portalPlane );
|
||||
//if ( pPortalEnt )
|
||||
C_FuncFakeWorldPortal *pPortalEnt = NextFakeWorldPortal( NULL, view, portalPlane, frustum );
|
||||
C_FuncFakeWorldPortal *pPortalEnt = NextFakeWorldPortal( NULL, view, portalPlane, vecPlaneOrigin, frustum );
|
||||
while ( pPortalEnt != NULL )
|
||||
{
|
||||
ITexture *pCameraTarget = pPortalEnt->RenderTarget();
|
||||
int width = pCameraTarget->GetActualWidth();
|
||||
int height = pCameraTarget->GetActualHeight();
|
||||
|
||||
DrawFakeWorldPortal( pCameraTarget, pPortalEnt, viewMiddle, C_BasePlayer::GetLocalPlayer(), 0, 0, width, height, view, portalPlane );
|
||||
DrawFakeWorldPortal( pCameraTarget, pPortalEnt, viewMiddle, C_BasePlayer::GetLocalPlayer(), 0, 0, width, height, view, portalPlane, vecPlaneOrigin );
|
||||
|
||||
pPortalEnt = NextFakeWorldPortal( pPortalEnt, view, portalPlane, frustum );
|
||||
pPortalEnt = NextFakeWorldPortal( pPortalEnt, view, portalPlane, vecPlaneOrigin, frustum );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -2027,6 +2134,10 @@ void CViewRender::RenderView( const CViewSetup &view, int nClearFlags, int whatT
|
||||
// Must be first
|
||||
render->SceneBegin();
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
g_pColorCorrectionMgr->UpdateColorCorrection();
|
||||
#endif
|
||||
|
||||
pRenderContext.GetFrom( materials );
|
||||
pRenderContext->TurnOnToneMapping();
|
||||
pRenderContext.SafeRelease();
|
||||
@ -3434,8 +3545,7 @@ ConVar r_fakeworldportal_debug("r_fakeworldportal_debug", "0");
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Sets up scene and renders WIP fake world portal view.
|
||||
// Based on code from monitors, mirrors, and 3D skyboxes.
|
||||
// It's also terrible right now.
|
||||
// Based on code from monitors, mirrors, and logic_measure_movement.
|
||||
//
|
||||
// Input : cameraNum -
|
||||
// &cameraView
|
||||
@ -3449,7 +3559,7 @@ ConVar r_fakeworldportal_debug("r_fakeworldportal_debug", "0");
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CViewRender::DrawFakeWorldPortal( ITexture *pRenderTarget, C_FuncFakeWorldPortal *pCameraEnt, const CViewSetup &cameraView, C_BasePlayer *localPlayer,
|
||||
int x, int y, int width, int height,
|
||||
const CViewSetup &mainView, cplane_t &ourPlane )
|
||||
const CViewSetup &mainView, cplane_t &ourPlane, const Vector &vecPlaneOrigin )
|
||||
{
|
||||
#ifdef USE_MONITORS
|
||||
VPROF_INCREMENT_COUNTER( "cameras rendered", 1 );
|
||||
@ -3488,97 +3598,89 @@ bool CViewRender::DrawFakeWorldPortal( ITexture *pRenderTarget, C_FuncFakeWorldP
|
||||
monitorView.origin = mainView.origin;
|
||||
monitorView.angles = mainView.angles;
|
||||
|
||||
// Temporary debug stuff
|
||||
// Debug stuff
|
||||
static float flLastDebugTime = 0.0f;
|
||||
bool bDebug = r_fakeworldportal_debug.GetBool() && gpGlobals->curtime > flLastDebugTime;
|
||||
|
||||
QAngle angTargetAngles = pCameraEnt->m_hTargetPlane->GetAbsAngles() + pCameraEnt->m_PlaneAngles;
|
||||
|
||||
// RED - First origin
|
||||
if (bDebug)
|
||||
debugoverlay->AddBoxOverlay( monitorView.origin, Vector(-32,-32,-32), Vector(32,32,32), monitorView.angles, 255, 0, 0, 128, 10.0f );
|
||||
|
||||
// Make sure the origin and angles are relative to the target plane
|
||||
monitorView.origin -= pCameraEnt->GetAbsOrigin();
|
||||
|
||||
// scale origin by sky scale
|
||||
if ( pCameraEnt->m_flScale > 0 )
|
||||
{
|
||||
float scale = 1.0f / pCameraEnt->m_flScale;
|
||||
VectorScale( monitorView.origin, scale, monitorView.origin );
|
||||
}
|
||||
|
||||
// YELLOW - Main origin
|
||||
if (bDebug)
|
||||
debugoverlay->AddBoxOverlay( pCameraEnt->GetAbsOrigin(), Vector(-32,-32,-32), Vector(32,32,32), monitorView.angles, 255, 224, 0, 128, 10.0f );
|
||||
|
||||
// Make sure our angles are relative to the main plane, just like the origin
|
||||
QAngle angOurAngles;
|
||||
VectorAngles( ourPlane.normal * -1, angOurAngles );
|
||||
//angles -= angOurAngles;
|
||||
|
||||
// First, create a matrix for the sky's angles.
|
||||
matrix3x4_t matSkyAngles;
|
||||
AngleMatrix( angTargetAngles - angOurAngles, matSkyAngles );
|
||||
|
||||
Vector vecSkyForward, vecSkyRight, vecSkyUp;
|
||||
//
|
||||
// Calculate the angles for the fake portal plane
|
||||
//
|
||||
QAngle angTargetAngles = pCameraEnt->m_hTargetPlane->GetAbsAngles() - pCameraEnt->m_PlaneAngles;
|
||||
QAngle angFakePortalAngles;
|
||||
|
||||
// Get vectors from our original angles.
|
||||
Vector vPlayerForward, vPlayerRight, vPlayerUp;
|
||||
AngleVectors( monitorView.angles, &vPlayerForward, &vPlayerRight, &vPlayerUp );
|
||||
|
||||
VectorTransform( vPlayerForward, matSkyAngles, vecSkyForward );
|
||||
VectorTransform( vPlayerRight, matSkyAngles, vecSkyRight );
|
||||
VectorTransform( vPlayerUp, matSkyAngles, vecSkyUp );
|
||||
|
||||
// Normalize them.
|
||||
VectorNormalize( vecSkyForward );
|
||||
VectorNormalize( vecSkyRight );
|
||||
VectorNormalize( vecSkyUp );
|
||||
Vector vOurForward, vOurRight, vOurUp;
|
||||
AngleVectors( pCameraEnt->GetAbsAngles(), &vOurForward, &vOurRight, &vOurUp );
|
||||
|
||||
Quaternion quat;
|
||||
BasisToQuaternion( vecSkyForward, vecSkyRight, vecSkyUp, quat );
|
||||
QuaternionAngles( quat, monitorView.angles );
|
||||
BasisToQuaternion( ourPlane.normal, vOurRight, vOurUp, quat );
|
||||
QuaternionAngles( quat, angFakePortalAngles );
|
||||
|
||||
// End of code mostly lifted from projected texture screenspace stuff
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
// Now just rotate our origin with that matrix.
|
||||
// We create a copy of the origin since VectorRotate doesn't want in1 to be the same variable as the destination.
|
||||
VectorRotate(Vector(monitorView.origin), matSkyAngles, monitorView.origin);
|
||||
|
||||
// BLUE - Target origin
|
||||
if (bDebug)
|
||||
debugoverlay->AddBoxOverlay( pCameraEnt->m_hTargetPlane->GetAbsOrigin(), Vector(-32,-32,-32), Vector(32,32,32), monitorView.angles, 0, 0, 255, 128, 10.0f );
|
||||
|
||||
monitorView.origin += pCameraEnt->m_hTargetPlane->GetAbsOrigin();
|
||||
|
||||
// GREEN - Final origin
|
||||
if (bDebug)
|
||||
{
|
||||
// RED - Initial player origin
|
||||
debugoverlay->AddBoxOverlay( monitorView.origin, Vector(-32,-32,-32), Vector(32,32,32), monitorView.angles, 255, 0, 0, 128, 10.0f );
|
||||
|
||||
// YELLOW - Portal origin
|
||||
debugoverlay->AddBoxOverlay( pCameraEnt->GetAbsOrigin(), Vector(-32,-32,-32), Vector(32,32,32), angFakePortalAngles, 255, 224, 0, 128, 10.0f );
|
||||
}
|
||||
|
||||
//
|
||||
// Translate the actual portal view position to be relative to the target
|
||||
//
|
||||
matrix3x4_t matPlayer, matPortal, matPlayerToPortal;
|
||||
AngleIMatrix( monitorView.angles, monitorView.origin, matPlayer );
|
||||
AngleMatrix( angFakePortalAngles, pCameraEnt->GetAbsOrigin(), matPortal );
|
||||
ConcatTransforms( matPlayer, matPortal, matPlayerToPortal );
|
||||
|
||||
// Apply the scale factor
|
||||
if ( pCameraEnt->m_flScale > 0 )
|
||||
{
|
||||
Vector vecTranslation;
|
||||
MatrixGetColumn( matPlayerToPortal, 3, vecTranslation );
|
||||
vecTranslation /= pCameraEnt->m_flScale;
|
||||
MatrixSetColumn( vecTranslation, 3, matPlayerToPortal );
|
||||
}
|
||||
|
||||
matrix3x4_t matTarget;
|
||||
AngleMatrix( angTargetAngles, pCameraEnt->m_hTargetPlane->GetAbsOrigin(), matTarget );
|
||||
|
||||
// Now apply the new matrix to the new reference point
|
||||
matrix3x4_t matPortalToPlayer, matNewPlayerPosition;
|
||||
MatrixInvert( matPlayerToPortal, matPortalToPlayer );
|
||||
|
||||
ConcatTransforms( matTarget, matPortalToPlayer, matNewPlayerPosition );
|
||||
|
||||
MatrixAngles( matNewPlayerPosition, monitorView.angles, monitorView.origin );
|
||||
|
||||
if (bDebug)
|
||||
{
|
||||
// BLUE - Target origin
|
||||
debugoverlay->AddBoxOverlay( pCameraEnt->m_hTargetPlane->GetAbsOrigin(), Vector(-32,-32,-32), Vector(32,32,32), angTargetAngles, 0, 0, 255, 128, 10.0f );
|
||||
|
||||
// GREEN - Final origin
|
||||
debugoverlay->AddBoxOverlay( monitorView.origin, Vector(-32,-32,-32), Vector(32,32,32), monitorView.angles, 0, 255, 0, 128, 10.0f );
|
||||
|
||||
flLastDebugTime = gpGlobals->curtime + 5.0f;
|
||||
}
|
||||
|
||||
|
||||
monitorView.fov = mainView.fov;
|
||||
monitorView.m_bOrtho = false;
|
||||
monitorView.m_flAspectRatio = 0.0f;
|
||||
monitorView.m_bOrtho = mainView.m_bOrtho;
|
||||
monitorView.m_flAspectRatio = mainView.m_flAspectRatio;
|
||||
monitorView.m_bViewToProjectionOverride = false;
|
||||
|
||||
// @MULTICORE (toml 8/11/2006): this should be a renderer....
|
||||
int nClearFlags = (VIEW_CLEAR_DEPTH | VIEW_CLEAR_COLOR | VIEW_CLEAR_OBEY_STENCIL);
|
||||
bool bDrew3dSkybox = false;
|
||||
SkyboxVisibility_t nSkyMode = pCameraEnt->SkyMode();
|
||||
|
||||
Frustum frustum;
|
||||
render->Push3DView( monitorView, nClearFlags, pRenderTarget, (VPlane *)frustum );
|
||||
|
||||
//
|
||||
// Monitor sky handling
|
||||
// Sky handling
|
||||
//
|
||||
if ( pCameraEnt->SkyMode() == SKYBOX_3DSKYBOX_VISIBLE )
|
||||
SkyboxVisibility_t nSkyMode = pCameraEnt->SkyMode();
|
||||
if ( nSkyMode == SKYBOX_3DSKYBOX_VISIBLE )
|
||||
{
|
||||
// if the 3d skybox world is drawn, then don't draw the normal skybox
|
||||
CSkyboxView *pSkyView = new CSkyboxView( this );
|
||||
@ -3589,16 +3691,21 @@ bool CViewRender::DrawFakeWorldPortal( ITexture *pRenderTarget, C_FuncFakeWorldP
|
||||
SafeRelease( pSkyView );
|
||||
}
|
||||
|
||||
//
|
||||
// Make a clipping plane for the target view
|
||||
//
|
||||
Vector4D plane;
|
||||
|
||||
// Combine the target angles and the plane angles
|
||||
Vector vecAnglesNormal( angTargetAngles.x, angTargetAngles.y, angTargetAngles.z );
|
||||
Vector vecAnglesNormal;
|
||||
AngleVectors( angTargetAngles, &vecAnglesNormal );
|
||||
VectorNormalize( vecAnglesNormal );
|
||||
VectorCopy( vecAnglesNormal, plane.AsVector3D() );
|
||||
VectorCopy( -vecAnglesNormal, plane.AsVector3D() );
|
||||
|
||||
// TODO: How do we get a good value for this!?!?
|
||||
//plane.w = m_OurPlane.dist + 0.1f;
|
||||
plane.w = -32.0f + 0.1f;
|
||||
// The portal plane's distance from the actual brush's origin
|
||||
float flPlaneDist = vecPlaneOrigin.Length();
|
||||
|
||||
// The target's distance from world origin
|
||||
plane.w = -((pCameraEnt->m_hTargetPlane->GetAbsOrigin() * vecAnglesNormal).Length() + flPlaneDist) + 0.1f;
|
||||
|
||||
CMatRenderContextPtr pRenderContext( materials );
|
||||
pRenderContext->PushCustomClipPlane( plane.Base() );
|
||||
|
@ -454,7 +454,7 @@ private:
|
||||
#ifdef MAPBASE
|
||||
bool DrawFakeWorldPortal( ITexture *pRenderTarget, C_FuncFakeWorldPortal *pCameraEnt, const CViewSetup &cameraView, C_BasePlayer *localPlayer,
|
||||
int x, int y, int width, int height,
|
||||
const CViewSetup &mainView, cplane_t &ourPlane );
|
||||
const CViewSetup &mainView, cplane_t &ourPlane, const Vector &vecPlaneOrigin );
|
||||
#endif
|
||||
|
||||
// Drawing primitives
|
||||
@ -468,6 +468,13 @@ private:
|
||||
IMaterial *GetScreenOverlayMaterial( );
|
||||
void PerformScreenOverlay( int x, int y, int w, int h );
|
||||
|
||||
#ifdef MAPBASE
|
||||
void SetIndexedScreenOverlayMaterial( int i, IMaterial *pMaterial );
|
||||
IMaterial *GetIndexedScreenOverlayMaterial( int i );
|
||||
void ResetIndexedScreenOverlays();
|
||||
int GetMaxIndexedScreenOverlays() const;
|
||||
#endif
|
||||
|
||||
void DrawUnderwaterOverlay( void );
|
||||
|
||||
// Water-related methods
|
||||
@ -511,6 +518,10 @@ private:
|
||||
CMaterialReference m_TranslucentSingleColor;
|
||||
CMaterialReference m_ModulateSingleColor;
|
||||
CMaterialReference m_ScreenOverlayMaterial;
|
||||
#ifdef MAPBASE
|
||||
CMaterialReference m_IndexedScreenOverlayMaterials[MAX_SCREEN_OVERLAYS];
|
||||
bool m_bUsingIndexedScreenOverlays;
|
||||
#endif
|
||||
CMaterialReference m_UnderWaterOverlayMaterial;
|
||||
|
||||
Vector m_vecLastFacing;
|
||||
|
@ -41,10 +41,13 @@ extern ScriptClassDesc_t * GetScriptDesc( CBaseEntity * );
|
||||
#endif // VMPROFILE
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
static ScriptHook_t g_Hook_OnEntityCreated;
|
||||
static ScriptHook_t g_Hook_OnEntityDeleted;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: A clientside variant of CScriptEntityIterator.
|
||||
//-----------------------------------------------------------------------------
|
||||
class CScriptClientEntityIterator
|
||||
class CScriptClientEntityIterator : public IClientEntityListener
|
||||
{
|
||||
public:
|
||||
HSCRIPT GetLocalPlayer()
|
||||
@ -96,6 +99,38 @@ public:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void EnableEntityListening()
|
||||
{
|
||||
// Start getting entity updates!
|
||||
ClientEntityList().AddListenerEntity( this );
|
||||
}
|
||||
|
||||
void DisableEntityListening()
|
||||
{
|
||||
// Stop getting entity updates!
|
||||
ClientEntityList().RemoveListenerEntity( this );
|
||||
}
|
||||
|
||||
void OnEntityCreated( CBaseEntity *pEntity )
|
||||
{
|
||||
if ( g_pScriptVM )
|
||||
{
|
||||
// entity
|
||||
ScriptVariant_t args[] = { ScriptVariant_t( pEntity->GetScriptInstance() ) };
|
||||
g_Hook_OnEntityCreated.Call( NULL, NULL, args );
|
||||
}
|
||||
};
|
||||
|
||||
void OnEntityDeleted( CBaseEntity *pEntity )
|
||||
{
|
||||
if ( g_pScriptVM )
|
||||
{
|
||||
// entity
|
||||
ScriptVariant_t args[] = { ScriptVariant_t( pEntity->GetScriptInstance() ) };
|
||||
g_Hook_OnEntityDeleted.Call( NULL, NULL, args );
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
} g_ScriptEntityIterator;
|
||||
|
||||
@ -106,6 +141,17 @@ BEGIN_SCRIPTDESC_ROOT_NAMED( CScriptClientEntityIterator, "CEntities", SCRIPT_SI
|
||||
DEFINE_SCRIPTFUNC( CreateByClassname, "Creates an entity by classname" )
|
||||
DEFINE_SCRIPTFUNC( FindByClassname, "Find entities by class name. Pass 'null' to start an iteration, or reference to a previously found entity to continue a search" )
|
||||
DEFINE_SCRIPTFUNC( FindByName, "Find entities by name. Pass 'null' to start an iteration, or reference to a previously found entity to continue a search" )
|
||||
|
||||
DEFINE_SCRIPTFUNC( EnableEntityListening, "Enables the 'OnEntity' hooks. This function must be called before using them." )
|
||||
DEFINE_SCRIPTFUNC( DisableEntityListening, "Disables the 'OnEntity' hooks." )
|
||||
|
||||
BEGIN_SCRIPTHOOK( g_Hook_OnEntityCreated, "OnEntityCreated", FIELD_VOID, "Called when an entity is created. Requires EnableEntityListening() to be fired beforehand." )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "entity", FIELD_HSCRIPT )
|
||||
END_SCRIPTHOOK()
|
||||
|
||||
BEGIN_SCRIPTHOOK( g_Hook_OnEntityDeleted, "OnEntityDeleted", FIELD_VOID, "Called when an entity is deleted. Requires EnableEntityListening() to be fired beforehand." )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "entity", FIELD_HSCRIPT )
|
||||
END_SCRIPTHOOK()
|
||||
END_SCRIPTDESC();
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -57,6 +57,45 @@ BEGIN_DATADESC( CBaseAnimatingOverlay )
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
BEGIN_ENT_SCRIPTDESC( CBaseAnimatingOverlay, CBaseAnimating, "Animating models which support dynamic animation layers/overlays." )
|
||||
|
||||
DEFINE_SCRIPTFUNC( GetNumAnimOverlays, "Gets the current number of animation layers." )
|
||||
DEFINE_SCRIPTFUNC( RemoveAllGestures, "Removes all animation layers." )
|
||||
|
||||
DEFINE_SCRIPTFUNC( IsValidLayer, "Returns true if the specified layer index is valid." )
|
||||
DEFINE_SCRIPTFUNC( HasActiveLayer, "Returns true if there is currently an active layer." )
|
||||
DEFINE_SCRIPTFUNC( RemoveLayer, "Removes the specified layer index with the specified kill rate and delay." )
|
||||
DEFINE_SCRIPTFUNC( FastRemoveLayer, "Removes the specified layer index immediately." )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptAddGesture, "AddGesture", "Adds a new animation layer using the specified activity name." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptAddGestureID, "AddGestureID", "Adds a new animation layer using the specified activity index." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptAddGestureSequence, "AddGestureSequence", "Adds a new animation layer using the specified activity name." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptAddGestureSequenceID, "AddGestureSequenceID", "Adds a new animation layer using the specified sequence index." )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptFindGestureLayer, "FindGestureLayer", "Finds and returns the first active animation layer which uses the specified activity name." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptFindGestureLayerByID, "FindGestureLayerByID", "Finds and returns the first active animation layer which uses the specified activity index." )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetLayerActivity, "GetLayerActivity", "Gets the activity name of the specified layer index." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetLayerActivityID, "GetLayerActivityID", "Gets the activity index of the specified layer index." )
|
||||
DEFINE_SCRIPTFUNC( GetLayerSequence, "Gets the sequence index of the specified layer index." )
|
||||
DEFINE_SCRIPTFUNC( SetLayerDuration, "Sets the duration of the specified layer index." )
|
||||
DEFINE_SCRIPTFUNC( GetLayerDuration, "Gets the duration of the specified layer index." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptSetLayerCycle, "SetLayerCycle", "Sets the cycle of the specified layer index." )
|
||||
DEFINE_SCRIPTFUNC( GetLayerCycle, "Gets the cycle of the specified layer index." )
|
||||
DEFINE_SCRIPTFUNC( SetLayerPlaybackRate, "Sets the playback rate of the specified layer index." )
|
||||
DEFINE_SCRIPTFUNC( SetLayerWeight, "Sets the weight of the specified layer index." )
|
||||
DEFINE_SCRIPTFUNC( GetLayerWeight, "Gets the weight of the specified layer index." )
|
||||
DEFINE_SCRIPTFUNC( SetLayerBlendIn, "Sets the fade-in of the specified layer index, with the fade being a 0-1 fraction of the cycle." )
|
||||
DEFINE_SCRIPTFUNC( SetLayerBlendOut, "Sets the fade-out of the specified layer index, with the fade being a 0-1 fraction of the cycle." )
|
||||
DEFINE_SCRIPTFUNC( SetLayerAutokill, "Sets whether or not the specified layer index should remove itself when it's finished playing." )
|
||||
DEFINE_SCRIPTFUNC( SetLayerLooping, "Sets whether or not the specified layer index should loop." )
|
||||
DEFINE_SCRIPTFUNC( SetLayerNoRestore, "Sets whether or not the specified layer index should restore after a save is loaded." )
|
||||
DEFINE_SCRIPTFUNC( SetLayerNoEvents, "Sets whether or not the specified layer index should fire animation events." )
|
||||
|
||||
END_SCRIPTDESC();
|
||||
#endif
|
||||
|
||||
|
||||
#define ORDER_BITS 4
|
||||
#define WEIGHT_BITS 8
|
||||
@ -354,7 +393,11 @@ void CBaseAnimatingOverlay::DispatchAnimEvents ( CBaseAnimating *eventHandler )
|
||||
|
||||
for ( int i = 0; i < m_AnimOverlay.Count(); i++ )
|
||||
{
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
if (m_AnimOverlay[ i ].IsActive() && !m_AnimOverlay[ i ].NoEvents())
|
||||
#else
|
||||
if (m_AnimOverlay[ i ].IsActive())
|
||||
#endif
|
||||
{
|
||||
m_AnimOverlay[ i ].DispatchAnimEvents( eventHandler, this );
|
||||
}
|
||||
@ -1052,6 +1095,38 @@ void CBaseAnimatingOverlay::SetLayerNoRestore( int iLayer, bool bNoRestore )
|
||||
}
|
||||
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
// From Alien Swarm SDK
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseAnimatingOverlay::SetLayerNoEvents( int iLayer, bool bNoEvents )
|
||||
{
|
||||
if (!IsValidLayer( iLayer ))
|
||||
return;
|
||||
|
||||
if (bNoEvents)
|
||||
{
|
||||
m_AnimOverlay[iLayer].m_fFlags |= ANIM_LAYER_NOEVENTS;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_AnimOverlay[iLayer].m_fFlags &= ~ANIM_LAYER_NOEVENTS;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBaseAnimatingOverlay::IsLayerFinished( int iLayer )
|
||||
{
|
||||
if (!IsValidLayer( iLayer ))
|
||||
return true;
|
||||
|
||||
return m_AnimOverlay[iLayer].m_bSequenceFinished;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1149,4 +1224,36 @@ bool CBaseAnimatingOverlay::HasActiveLayer( void )
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
int CBaseAnimatingOverlay::ScriptAddGesture( const char *pszActivity, bool autokill )
|
||||
{
|
||||
return AddGesture( (Activity)CAI_BaseNPC::GetActivityID( pszActivity ), autokill );
|
||||
}
|
||||
|
||||
int CBaseAnimatingOverlay::ScriptAddGestureID( int iActivity, bool autokill )
|
||||
{
|
||||
return AddGesture( (Activity)iActivity, autokill );
|
||||
}
|
||||
|
||||
int CBaseAnimatingOverlay::ScriptFindGestureLayer( const char *pszActivity )
|
||||
{
|
||||
return FindGestureLayer( (Activity)CAI_BaseNPC::GetActivityID( pszActivity ) );
|
||||
}
|
||||
|
||||
int CBaseAnimatingOverlay::ScriptFindGestureLayerByID( int iActivity )
|
||||
{
|
||||
return FindGestureLayer( (Activity)iActivity );
|
||||
}
|
||||
|
||||
const char *CBaseAnimatingOverlay::ScriptGetLayerActivity( int iLayer )
|
||||
{
|
||||
return CAI_BaseNPC::GetActivityName( GetLayerActivity( iLayer ) );
|
||||
}
|
||||
|
||||
int CBaseAnimatingOverlay::ScriptGetLayerActivityID( int iLayer )
|
||||
{
|
||||
return GetLayerActivity( iLayer );
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -43,6 +43,9 @@ public:
|
||||
#define ANIM_LAYER_DONTRESTORE 0x0008
|
||||
#define ANIM_LAYER_CHECKACCESS 0x0010
|
||||
#define ANIM_LAYER_DYING 0x0020
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
#define ANIM_LAYER_NOEVENTS 0x0040
|
||||
#endif
|
||||
|
||||
int m_fFlags;
|
||||
|
||||
@ -80,6 +83,9 @@ public:
|
||||
void Dying( void ) { m_fFlags |= ANIM_LAYER_DYING; }
|
||||
bool IsDying( void ) { return ((m_fFlags & ANIM_LAYER_DYING) != 0); }
|
||||
void Dead( void ) { m_fFlags &= ~ANIM_LAYER_DYING; }
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
bool NoEvents( void ) { return ((m_fFlags & ANIM_LAYER_NOEVENTS) != 0); }
|
||||
#endif
|
||||
|
||||
bool IsAbandoned( void );
|
||||
void MarkActive( void );
|
||||
@ -175,6 +181,11 @@ public:
|
||||
void SetLayerAutokill( int iLayer, bool bAutokill );
|
||||
void SetLayerLooping( int iLayer, bool bLooping );
|
||||
void SetLayerNoRestore( int iLayer, bool bNoRestore );
|
||||
#ifdef MAPBASE
|
||||
void SetLayerNoEvents( int iLayer, bool bNoEvents ); // From Alien Swarm SDK
|
||||
|
||||
bool IsLayerFinished( int iLayer );
|
||||
#endif
|
||||
|
||||
Activity GetLayerActivity( int iLayer );
|
||||
int GetLayerSequence( int iLayer );
|
||||
@ -195,9 +206,26 @@ public:
|
||||
private:
|
||||
int AllocateLayer( int iPriority = 0 ); // lower priorities are processed first
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
int ScriptAddGesture( const char *pszActivity, bool autokill );
|
||||
int ScriptAddGestureID( int iActivity, bool autokill );
|
||||
int ScriptAddGestureSequence( const char *pszSequence, bool autokill ) { return AddGestureSequence( LookupSequence( pszSequence ), autokill ); }
|
||||
int ScriptAddGestureSequenceID( int iSequence, bool autokill ) { return AddGestureSequence( iSequence, autokill ); }
|
||||
|
||||
int ScriptFindGestureLayer( const char *pszActivity );
|
||||
int ScriptFindGestureLayerByID( int iActivity );
|
||||
const char *ScriptGetLayerActivity( int iLayer );
|
||||
int ScriptGetLayerActivityID( int iLayer );
|
||||
|
||||
void ScriptSetLayerCycle( int iLayer, float flCycle ) { SetLayerCycle( iLayer, flCycle ); }
|
||||
#endif
|
||||
|
||||
DECLARE_SERVERCLASS();
|
||||
DECLARE_DATADESC();
|
||||
DECLARE_PREDICTABLE();
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
DECLARE_ENT_SCRIPTDESC();
|
||||
#endif
|
||||
};
|
||||
|
||||
EXTERN_SEND_TABLE(DT_BaseAnimatingOverlay);
|
||||
|
@ -103,6 +103,12 @@ protected:
|
||||
|
||||
inline CBaseEntity *GetActivator();
|
||||
|
||||
#ifdef MAPBASE
|
||||
inline float GetNPCOpenDistance() { return m_flNPCOpenDistance; }
|
||||
inline Activity GetNPCOpenFrontActivity() { return m_eNPCOpenFrontActivity; }
|
||||
inline Activity GetNPCOpenBackActivity() { return m_eNPCOpenBackActivity; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
// Implement these in your leaf class.
|
||||
@ -196,6 +202,12 @@ private:
|
||||
string_t m_SoundOpen;
|
||||
string_t m_SoundClose;
|
||||
|
||||
#ifdef MAPBASE
|
||||
float m_flNPCOpenDistance;
|
||||
Activity m_eNPCOpenFrontActivity;
|
||||
Activity m_eNPCOpenBackActivity;
|
||||
#endif
|
||||
|
||||
// dvs: FIXME: can we remove m_flSpeed from CBaseEntity?
|
||||
//float m_flSpeed; // Rotation speed when opening or closing in degrees per second.
|
||||
|
||||
|
@ -72,8 +72,23 @@ class CPointCommentaryNode : public CBaseAnimating
|
||||
DECLARE_CLASS( CPointCommentaryNode, CBaseAnimating );
|
||||
public:
|
||||
DECLARE_DATADESC();
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
DECLARE_ENT_SCRIPTDESC();
|
||||
#endif
|
||||
DECLARE_SERVERCLASS();
|
||||
|
||||
CPointCommentaryNode()
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
m_flViewTargetSpeedScale = 1.0f;
|
||||
m_flViewPositionSpeedScale = 1.0f;
|
||||
m_flReturnSpeedScale = 0.0f;
|
||||
m_flPanelScale = 1.0f;
|
||||
m_flPanelX = -1.0f;
|
||||
m_flPanelY = -1.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Spawn( void );
|
||||
void Precache( void );
|
||||
void Activate( void );
|
||||
@ -102,11 +117,37 @@ public:
|
||||
void TeleportTo( CBasePlayer *pPlayer );
|
||||
bool CanTeleportTo( void );
|
||||
|
||||
#ifdef MAPBASE
|
||||
bool IsActive() { return m_bActive; }
|
||||
bool IsDisabled() { return m_bDisabled; }
|
||||
|
||||
int GetCommentaryType() { return m_iCommentaryType; }
|
||||
void SetCommentaryType( int iType ) { m_iCommentaryType = iType; }
|
||||
|
||||
const char *GetCommentaryFile() { return STRING( m_iszCommentaryFile.Get() ); }
|
||||
void SetCommentaryFile( const char *pszNewFile ) { m_iszCommentaryFile.Set( AllocPooledString( pszNewFile ) ); }
|
||||
const char *GetSpeakers() { return STRING( m_iszSpeakers.Get() ); }
|
||||
void SetSpeakers( const char *pszSpeakers ) { m_iszSpeakers.Set( AllocPooledString( pszSpeakers ) ); }
|
||||
const char *GetPrintName() { return STRING( m_iszPrintName.Get() ); }
|
||||
void SetPrintName( const char *pszPrintName ) { m_iszPrintName.Set( AllocPooledString( pszPrintName ) ); }
|
||||
#endif
|
||||
|
||||
// Inputs
|
||||
void InputStartCommentary( inputdata_t &inputdata );
|
||||
void InputStartUnstoppableCommentary( inputdata_t &inputdata );
|
||||
void InputEnable( inputdata_t &inputdata );
|
||||
void InputDisable( inputdata_t &inputdata );
|
||||
#ifdef MAPBASE
|
||||
void InputSetViewTarget( inputdata_t &inputdata );
|
||||
void InputSetViewPosition( inputdata_t &inputdata );
|
||||
void InputSetViewTargetSpeed( inputdata_t &inputdata );
|
||||
void InputSetViewPositionSpeed( inputdata_t &inputdata );
|
||||
void InputSetReturnSpeed( inputdata_t &inputdata );
|
||||
#endif
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
static ScriptHook_t g_Hook_PreStartCommentary;
|
||||
#endif
|
||||
|
||||
private:
|
||||
string_t m_iszPreCommands;
|
||||
@ -119,6 +160,13 @@ private:
|
||||
string_t m_iszViewPosition;
|
||||
CNetworkVar( EHANDLE, m_hViewPosition );
|
||||
EHANDLE m_hViewPositionMover; // Entity used to blend the view to the viewposition entity
|
||||
#ifdef MAPBASE
|
||||
float m_flViewTargetSpeedScale;
|
||||
float m_flViewPositionSpeedScale;
|
||||
float m_flReturnSpeedScale;
|
||||
CNetworkVar( string_t, m_iszPrintName );
|
||||
float m_flViewPositionChangedTime; // View position now blends relative to this value. Mainly needed for when SetViewPosition is used
|
||||
#endif
|
||||
bool m_bPreventMovement;
|
||||
bool m_bUnderCrosshair;
|
||||
bool m_bUnstoppable;
|
||||
@ -138,6 +186,13 @@ private:
|
||||
CNetworkVar( string_t, m_iszSpeakers );
|
||||
CNetworkVar( int, m_iNodeNumber );
|
||||
CNetworkVar( int, m_iNodeNumberMax );
|
||||
|
||||
#ifdef MAPBASE
|
||||
CNetworkVar( int, m_iCommentaryType );
|
||||
CNetworkVar( float, m_flPanelScale );
|
||||
CNetworkVar( float, m_flPanelX );
|
||||
CNetworkVar( float, m_flPanelY );
|
||||
#endif
|
||||
};
|
||||
|
||||
BEGIN_DATADESC( CPointCommentaryNode )
|
||||
@ -166,6 +221,17 @@ BEGIN_DATADESC( CPointCommentaryNode )
|
||||
DEFINE_FIELD( m_bPreventChangesWhileMoving, FIELD_BOOLEAN ),
|
||||
DEFINE_KEYFIELD( m_bDisabled, FIELD_BOOLEAN, "start_disabled" ),
|
||||
DEFINE_KEYFIELD( m_vecTeleportOrigin, FIELD_VECTOR, "teleport_origin" ),
|
||||
#ifdef MAPBASE
|
||||
DEFINE_KEYFIELD( m_flViewTargetSpeedScale, FIELD_FLOAT, "viewtarget_speed" ),
|
||||
DEFINE_KEYFIELD( m_flViewPositionSpeedScale, FIELD_FLOAT, "viewposition_speed" ),
|
||||
DEFINE_KEYFIELD( m_flReturnSpeedScale, FIELD_FLOAT, "return_speed" ),
|
||||
DEFINE_KEYFIELD( m_iszPrintName, FIELD_STRING, "printname" ),
|
||||
DEFINE_FIELD( m_flViewPositionChangedTime, FIELD_TIME ),
|
||||
DEFINE_KEYFIELD( m_iCommentaryType, FIELD_INTEGER, "type" ),
|
||||
DEFINE_KEYFIELD( m_flPanelScale, FIELD_FLOAT, "panelscale" ),
|
||||
DEFINE_KEYFIELD( m_flPanelX, FIELD_FLOAT, "x" ),
|
||||
DEFINE_KEYFIELD( m_flPanelY, FIELD_FLOAT, "y" ),
|
||||
#endif
|
||||
|
||||
// Outputs
|
||||
DEFINE_OUTPUT( m_pOnCommentaryStarted, "OnCommentaryStarted" ),
|
||||
@ -176,6 +242,13 @@ BEGIN_DATADESC( CPointCommentaryNode )
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "StartUnstoppableCommentary", InputStartUnstoppableCommentary ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
|
||||
#ifdef MAPBASE
|
||||
DEFINE_INPUTFUNC( FIELD_EHANDLE, "SetViewTarget", InputSetViewTarget ),
|
||||
DEFINE_INPUTFUNC( FIELD_EHANDLE, "SetViewPosition", InputSetViewPosition ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetViewTargetSpeed", InputSetViewTargetSpeed ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetViewPositionSpeed", InputSetViewPositionSpeed ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetReturnSpeed", InputSetReturnSpeed ),
|
||||
#endif
|
||||
|
||||
// Functions
|
||||
DEFINE_THINKFUNC( SpinThink ),
|
||||
@ -183,6 +256,35 @@ BEGIN_DATADESC( CPointCommentaryNode )
|
||||
DEFINE_THINKFUNC( UpdateViewPostThink ),
|
||||
END_DATADESC()
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
|
||||
ScriptHook_t CPointCommentaryNode::g_Hook_PreStartCommentary;
|
||||
|
||||
BEGIN_ENT_SCRIPTDESC( CPointCommentaryNode, CBaseAnimating, "Commentary nodes which play commentary in commentary mode." )
|
||||
DEFINE_SCRIPTFUNC( IsDisabled, "" )
|
||||
DEFINE_SCRIPTFUNC( SetDisabled, "" )
|
||||
|
||||
DEFINE_SCRIPTFUNC( IsActive, "" )
|
||||
DEFINE_SCRIPTFUNC( GetCommentaryFile, "" )
|
||||
DEFINE_SCRIPTFUNC( SetCommentaryFile, "" )
|
||||
DEFINE_SCRIPTFUNC( GetSpeakers, "" )
|
||||
DEFINE_SCRIPTFUNC( SetSpeakers, "" )
|
||||
DEFINE_SCRIPTFUNC( GetPrintName, "" )
|
||||
DEFINE_SCRIPTFUNC( SetPrintName, "" )
|
||||
DEFINE_SCRIPTFUNC( GetCommentaryType, "" )
|
||||
DEFINE_SCRIPTFUNC( SetCommentaryType, "" )
|
||||
|
||||
DEFINE_SCRIPTFUNC( HasViewTarget, "" )
|
||||
DEFINE_SCRIPTFUNC( PreventsMovement, "" )
|
||||
DEFINE_SCRIPTFUNC( CannotBeStopped, "" )
|
||||
|
||||
DEFINE_SCRIPTFUNC( AbortPlaying, "Stops playing the node and snaps out of its camera control immediately. The game uses this function to shut down commentary while in the middle of playing a node, as it can't smoothly blend out (since the commentary entities need to be removed)." )
|
||||
|
||||
DEFINE_SIMPLE_SCRIPTHOOK( CPointCommentaryNode::g_Hook_PreStartCommentary, "PreStartCommentary", FIELD_BOOLEAN, "Called just before commentary begins. Use this to modify variables or commentary behavior before it begins. Returning false will prevent the commentary from starting." )
|
||||
END_SCRIPTDESC();
|
||||
|
||||
#endif // MAPBASE_VSCRIPT
|
||||
|
||||
IMPLEMENT_SERVERCLASS_ST( CPointCommentaryNode, DT_PointCommentaryNode )
|
||||
SendPropBool( SENDINFO(m_bActive) ),
|
||||
SendPropStringT( SENDINFO(m_iszCommentaryFile) ),
|
||||
@ -192,6 +294,13 @@ IMPLEMENT_SERVERCLASS_ST( CPointCommentaryNode, DT_PointCommentaryNode )
|
||||
SendPropInt( SENDINFO(m_iNodeNumber), 8, SPROP_UNSIGNED ),
|
||||
SendPropInt( SENDINFO(m_iNodeNumberMax), 8, SPROP_UNSIGNED ),
|
||||
SendPropEHandle( SENDINFO(m_hViewPosition) ),
|
||||
#ifdef MAPBASE
|
||||
SendPropStringT( SENDINFO( m_iszPrintName ) ),
|
||||
SendPropInt( SENDINFO( m_iCommentaryType ), 2, SPROP_UNSIGNED ),
|
||||
SendPropFloat( SENDINFO( m_flPanelScale ) ),
|
||||
SendPropFloat( SENDINFO( m_flPanelX ) ),
|
||||
SendPropFloat( SENDINFO( m_flPanelY ) ),
|
||||
#endif
|
||||
END_SEND_TABLE()
|
||||
|
||||
LINK_ENTITY_TO_CLASS( point_commentary_node, CPointCommentaryNode );
|
||||
@ -895,7 +1004,29 @@ void CPointCommentaryNode::Spawn( void )
|
||||
const char *szModel = STRING( GetModelName() );
|
||||
if (!szModel || !*szModel)
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
switch (m_iCommentaryType)
|
||||
{
|
||||
case COMMENTARY_TYPE_TEXT:
|
||||
szModel = "models/extras/info_text.mdl";
|
||||
break;
|
||||
|
||||
case COMMENTARY_TYPE_IMAGE:
|
||||
szModel = "models/extras/info_image.mdl";
|
||||
break;
|
||||
|
||||
case COMMENTARY_TYPE_SCENE:
|
||||
szModel = "models/extras/info_scene.mdl";
|
||||
break;
|
||||
|
||||
default:
|
||||
case COMMENTARY_TYPE_AUDIO:
|
||||
szModel = "models/extras/info_speech.mdl";
|
||||
break;
|
||||
}
|
||||
#else
|
||||
szModel = "models/extras/info_speech.mdl";
|
||||
#endif
|
||||
SetModelName( AllocPooledString(szModel) );
|
||||
}
|
||||
|
||||
@ -906,6 +1037,12 @@ void CPointCommentaryNode::Spawn( void )
|
||||
AddSolidFlags( FSOLID_CUSTOMRAYTEST | FSOLID_CUSTOMBOXTEST );
|
||||
AddEffects( EF_NOSHADOW );
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Default to view position speed scale (which in turn defaults to 1.0)
|
||||
if (m_flReturnSpeedScale == 0.0f)
|
||||
m_flReturnSpeedScale = m_flViewPositionSpeedScale;
|
||||
#endif
|
||||
|
||||
// Setup for animation
|
||||
ResetSequence( LookupSequence("idle") );
|
||||
SetThink( &CPointCommentaryNode::SpinThink );
|
||||
@ -1119,6 +1256,19 @@ void CPointCommentaryNode::StartCommentary( void )
|
||||
if ( !pPlayer )
|
||||
return;
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if (m_ScriptScope.IsInitialized() && g_Hook_PreStartCommentary.CanRunInScope( m_ScriptScope ))
|
||||
{
|
||||
ScriptVariant_t functionReturn;
|
||||
if ( g_Hook_PreStartCommentary.Call( m_ScriptScope, &functionReturn, NULL ) && functionReturn.m_type == FIELD_BOOLEAN )
|
||||
{
|
||||
// Don't play the commentary if it returned false
|
||||
if (functionReturn.m_bool == false)
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
m_bActive = true;
|
||||
|
||||
m_flAnimTime = gpGlobals->curtime;
|
||||
@ -1140,6 +1290,21 @@ void CPointCommentaryNode::StartCommentary( void )
|
||||
// Start the commentary
|
||||
m_flStartTime = gpGlobals->curtime;
|
||||
|
||||
#ifdef MAPBASE
|
||||
if (m_hViewPosition.Get())
|
||||
{
|
||||
m_flViewPositionChangedTime = gpGlobals->curtime;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_flViewPositionChangedTime = -1.0f;
|
||||
}
|
||||
|
||||
// This is now used in certain places to denote the "last blend to" origin
|
||||
m_vecFinishOrigin = pPlayer->EyePosition();
|
||||
m_vecFinishAngles = pPlayer->EyeAngles();
|
||||
#endif
|
||||
|
||||
// If we have a view target, start blending towards it
|
||||
if ( m_hViewTarget || m_hViewPosition.Get() )
|
||||
{
|
||||
@ -1214,6 +1379,10 @@ void CPointCommentaryNode::UpdateViewThink( void )
|
||||
float dx = AngleDiff( angGoal.x, angCurrent.x );
|
||||
float dy = AngleDiff( angGoal.y, angCurrent.y );
|
||||
float mod = 1.0 - ExponentialDecay( 0.5, 0.3, gpGlobals->frametime );
|
||||
#ifdef MAPBASE
|
||||
if (m_flViewTargetSpeedScale != 1.0f)
|
||||
mod *= m_flViewTargetSpeedScale;
|
||||
#endif
|
||||
float dxmod = dx * mod;
|
||||
float dymod = dy * mod;
|
||||
|
||||
@ -1254,16 +1423,85 @@ void CPointCommentaryNode::UpdateViewThink( void )
|
||||
}
|
||||
|
||||
// Blend to the target position over time.
|
||||
float flCurTime = (gpGlobals->curtime - m_flStartTime);
|
||||
#ifdef MAPBASE
|
||||
float flCurTime = (gpGlobals->curtime - m_flViewPositionChangedTime);
|
||||
if (m_flViewPositionSpeedScale != 1.0f)
|
||||
flCurTime *= m_flViewPositionSpeedScale;
|
||||
#else
|
||||
float flCurTime = (gpGlobals->curtime - m_flStartTime);
|
||||
#endif
|
||||
float flBlendPerc = clamp( flCurTime * 0.5f, 0.f, 1.f );
|
||||
|
||||
// Figure out the current view position
|
||||
Vector vecCurEye;
|
||||
#ifdef MAPBASE
|
||||
VectorLerp( m_vecFinishOrigin, m_hViewPosition.Get()->GetAbsOrigin(), flBlendPerc, vecCurEye );
|
||||
#else
|
||||
VectorLerp( pPlayer->EyePosition(), m_hViewPosition.Get()->GetAbsOrigin(), flBlendPerc, vecCurEye );
|
||||
#endif
|
||||
m_hViewPositionMover->SetAbsOrigin( vecCurEye );
|
||||
|
||||
SetNextThink( gpGlobals->curtime, s_pCommentaryUpdateViewThink );
|
||||
}
|
||||
#ifdef MAPBASE
|
||||
else if ( m_flViewPositionChangedTime != -1.0f && m_hViewPositionMover )
|
||||
{
|
||||
// Blend back to the player's position over time.
|
||||
float flCurTime = (gpGlobals->curtime - m_flViewPositionChangedTime);
|
||||
if (m_flViewPositionSpeedScale != 1.0f)
|
||||
flCurTime *= m_flViewPositionSpeedScale;
|
||||
|
||||
//float flTimeToBlend = MIN( 2.0, m_flViewPositionChangedTime - m_flStartTime );
|
||||
//float flBlendPerc = 1.0f - clamp( flCurTime / flTimeToBlend, 0.f, 1.f );
|
||||
float flBlendPerc = 1.0f - clamp( flCurTime * 0.5f, 0.f, 1.f );
|
||||
|
||||
//Msg("OUT: CurTime %.2f, BlendTime: %.2f, Blend: %.3f\n", flCurTime, flTimeToBlend, flBlendPerc );
|
||||
|
||||
// Only do this while we're still moving
|
||||
if ( flBlendPerc > 0 )
|
||||
{
|
||||
// Figure out the current view position
|
||||
Vector vecPlayerPos = pPlayer->EyePosition();
|
||||
Vector vecToPosition = (m_vecFinishOrigin - vecPlayerPos);
|
||||
Vector vecCurEye = pPlayer->EyePosition() + (vecToPosition * flBlendPerc);
|
||||
m_hViewPositionMover->SetAbsOrigin( vecCurEye );
|
||||
|
||||
if ( m_hViewTarget )
|
||||
{
|
||||
Quaternion quatFinish;
|
||||
Quaternion quatOriginal;
|
||||
Quaternion quatCurrent;
|
||||
AngleQuaternion( m_vecOriginalAngles, quatOriginal );
|
||||
AngleQuaternion( m_vecFinishAngles, quatFinish );
|
||||
QuaternionSlerp( quatFinish, quatOriginal, 1.0 - flBlendPerc, quatCurrent );
|
||||
QAngle angCurrent;
|
||||
QuaternionAngles( quatCurrent, angCurrent );
|
||||
m_hViewPositionMover->SetAbsAngles( angCurrent );
|
||||
}
|
||||
|
||||
SetNextThink( gpGlobals->curtime, s_pCommentaryUpdateViewThink );
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
pPlayer->SnapEyeAngles( m_hViewPositionMover->GetAbsAngles() );
|
||||
|
||||
// Try to clean up the view position stuff without ending the commentary
|
||||
if ( !m_hViewTargetAngles && pPlayer->GetActiveWeapon() )
|
||||
{
|
||||
pPlayer->GetActiveWeapon()->Deploy();
|
||||
}
|
||||
|
||||
if (pPlayer->GetViewEntity() == m_hViewPositionMover)
|
||||
{
|
||||
pPlayer->SetViewEntity( NULL );
|
||||
}
|
||||
UTIL_Remove( m_hViewPositionMover );
|
||||
|
||||
m_flViewPositionChangedTime = -1.0f;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1279,6 +1517,10 @@ void CPointCommentaryNode::UpdateViewPostThink( void )
|
||||
{
|
||||
// Blend back to the player's position over time.
|
||||
float flCurTime = (gpGlobals->curtime - m_flFinishedTime);
|
||||
#ifdef MAPBASE
|
||||
if (m_flReturnSpeedScale != 1.0f)
|
||||
flCurTime *= m_flReturnSpeedScale;
|
||||
#endif
|
||||
float flTimeToBlend = MIN( 2.0, m_flFinishedTime - m_flStartTime );
|
||||
float flBlendPerc = 1.0f - clamp( flCurTime / flTimeToBlend, 0.f, 1.f );
|
||||
|
||||
@ -1440,6 +1682,79 @@ void CPointCommentaryNode::InputDisable( inputdata_t &inputdata )
|
||||
SetDisabled( true );
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPointCommentaryNode::InputSetViewTarget( inputdata_t &inputdata )
|
||||
{
|
||||
m_hViewTarget = inputdata.value.Entity();
|
||||
|
||||
// Do not let Activate() reassign this
|
||||
m_iszViewTarget = NULL_STRING;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPointCommentaryNode::InputSetViewPosition( inputdata_t &inputdata )
|
||||
{
|
||||
if (m_hViewPosition.Get() && m_hViewPositionMover)
|
||||
{
|
||||
// In case the view position is being cleared, assign the "finish" vectors
|
||||
m_vecFinishOrigin = m_hViewPositionMover->GetAbsOrigin();
|
||||
m_vecFinishAngles = m_hViewPositionMover->GetAbsAngles();
|
||||
}
|
||||
else
|
||||
{
|
||||
CBasePlayer *pPlayer = GetCommentaryPlayer();
|
||||
if (pPlayer)
|
||||
{
|
||||
// And in case it's a new view position coming from the player, assign the "finish" vectors to the player
|
||||
m_vecFinishOrigin = pPlayer->EyePosition();
|
||||
m_vecFinishAngles = m_vecOriginalAngles = pPlayer->EyeAngles();
|
||||
}
|
||||
}
|
||||
|
||||
m_hViewPosition = inputdata.value.Entity();
|
||||
|
||||
// Do not let Activate() reassign this
|
||||
m_iszViewPosition = NULL_STRING;
|
||||
|
||||
m_flViewPositionChangedTime = gpGlobals->curtime;
|
||||
|
||||
// If we have a view target, start blending towards it
|
||||
if ( m_hViewPosition.Get() )
|
||||
{
|
||||
SetContextThink( &CPointCommentaryNode::UpdateViewThink, gpGlobals->curtime, s_pCommentaryUpdateViewThink );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPointCommentaryNode::InputSetViewTargetSpeed( inputdata_t &inputdata )
|
||||
{
|
||||
m_flViewTargetSpeedScale = inputdata.value.Float();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPointCommentaryNode::InputSetViewPositionSpeed( inputdata_t &inputdata )
|
||||
{
|
||||
m_flViewPositionSpeedScale = inputdata.value.Float();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPointCommentaryNode::InputSetReturnSpeed( inputdata_t &inputdata )
|
||||
{
|
||||
m_flReturnSpeedScale = inputdata.value.Float();
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1501,7 +1816,11 @@ void CPointCommentaryNode::SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways
|
||||
bool CPointCommentaryNode::PreventsMovement( void )
|
||||
{
|
||||
// If we're moving the player's view at all, prevent movement
|
||||
#ifdef MAPBASE
|
||||
if ( m_hViewPosition.Get() || m_flViewPositionChangedTime != -1.0f )
|
||||
#else
|
||||
if ( m_hViewPosition.Get() )
|
||||
#endif
|
||||
return true;
|
||||
|
||||
return m_bPreventMovement;
|
||||
|
@ -2180,15 +2180,22 @@ void CAI_BaseNPC::InitDefaultActivitySR(void)
|
||||
ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_AR2 );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_RELOAD_AR2 );
|
||||
//ADD_ACTIVITY_TO_SR( ACT_RELOAD_AR2_LOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RELOAD_AR2_LOW );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_GESTURE_RELOAD_AR2 );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_COVER_AR2_LOW );
|
||||
#endif
|
||||
|
||||
#ifdef SHARED_COMBINE_ACTIVITIES
|
||||
ADD_ACTIVITY_TO_SR( ACT_COMBINE_THROW_GRENADE );
|
||||
ADD_ACTIVITY_TO_SR( ACT_COMBINE_AR2_ALTFIRE );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_GESTURE_COMBINE_THROW_GRENADE );
|
||||
ADD_ACTIVITY_TO_SR( ACT_GESTURE_COMBINE_AR2_ALTFIRE );
|
||||
ADD_ACTIVITY_TO_SR( ACT_GESTURE_SPECIAL_ATTACK1 );
|
||||
ADD_ACTIVITY_TO_SR( ACT_GESTURE_SPECIAL_ATTACK2 );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_GESTURE_SIGNAL_ADVANCE );
|
||||
ADD_ACTIVITY_TO_SR( ACT_GESTURE_SIGNAL_FORWARD );
|
||||
ADD_ACTIVITY_TO_SR( ACT_GESTURE_SIGNAL_GROUP );
|
||||
@ -2198,8 +2205,249 @@ void CAI_BaseNPC::InitDefaultActivitySR(void)
|
||||
ADD_ACTIVITY_TO_SR( ACT_GESTURE_SIGNAL_TAKECOVER );
|
||||
#endif
|
||||
|
||||
#ifdef COMPANION_HOLSTER_WORKAROUND
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
ADD_ACTIVITY_TO_SR( ACT_IDLE_REVOLVER );
|
||||
ADD_ACTIVITY_TO_SR( ACT_IDLE_ANGRY_REVOLVER );
|
||||
ADD_ACTIVITY_TO_SR( ACT_WALK_REVOLVER );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RUN_REVOLVER );
|
||||
ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_REVOLVER );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_REVOLVER );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_REVOLVER );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RELOAD_REVOLVER );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_REVOLVER_LOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RELOAD_REVOLVER_LOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_COVER_REVOLVER_LOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_REVOLVER_LOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_GESTURE_RANGE_ATTACK_REVOLVER );
|
||||
ADD_ACTIVITY_TO_SR( ACT_GESTURE_RELOAD_REVOLVER );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_IDLE_CROSSBOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_IDLE_ANGRY_CROSSBOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_WALK_CROSSBOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RUN_CROSSBOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_CROSSBOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_CROSSBOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_CROSSBOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RELOAD_CROSSBOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_CROSSBOW_LOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RELOAD_CROSSBOW_LOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_COVER_CROSSBOW_LOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_CROSSBOW_LOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_GESTURE_RANGE_ATTACK_CROSSBOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_GESTURE_RELOAD_CROSSBOW );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_IDLE_PISTOL_RELAXED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_IDLE_PISTOL_STIMULATED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_WALK_PISTOL_RELAXED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_WALK_PISTOL_STIMULATED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RUN_PISTOL_RELAXED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RUN_PISTOL_STIMULATED );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_IDLE_AIM_PISTOL_STIMULATED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_PISTOL_STIMULATED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_PISTOL_STIMULATED );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_WALK_CROUCH_PISTOL );
|
||||
ADD_ACTIVITY_TO_SR( ACT_WALK_CROUCH_AIM_PISTOL );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RUN_CROUCH_PISTOL );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RUN_CROUCH_AIM_PISTOL );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_IDLE_SHOTGUN );
|
||||
ADD_ACTIVITY_TO_SR( ACT_WALK_SHOTGUN );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RUN_SHOTGUN );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_COVER_SHOTGUN_LOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_SHOTGUN_LOW );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_WALK_SHOTGUN_RELAXED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_WALK_SHOTGUN_STIMULATED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RUN_SHOTGUN_RELAXED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RUN_SHOTGUN_STIMULATED );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_IDLE_AIM_SHOTGUN_STIMULATED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_SHOTGUN_STIMULATED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_SHOTGUN_STIMULATED );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_RPG_LOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_RPG_LOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_GESTURE_RANGE_ATTACK_RPG );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_WALK_MELEE );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RUN_MELEE );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_RUN_PACKAGE );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RUN_SUITCASE );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_ARM_RIFLE );
|
||||
ADD_ACTIVITY_TO_SR( ACT_ARM_SHOTGUN );
|
||||
ADD_ACTIVITY_TO_SR( ACT_ARM_RPG );
|
||||
ADD_ACTIVITY_TO_SR( ACT_ARM_MELEE );
|
||||
ADD_ACTIVITY_TO_SR( ACT_DISARM_RIFLE );
|
||||
ADD_ACTIVITY_TO_SR( ACT_DISARM_SHOTGUN );
|
||||
ADD_ACTIVITY_TO_SR( ACT_DISARM_RPG );
|
||||
ADD_ACTIVITY_TO_SR( ACT_DISARM_MELEE );
|
||||
#endif
|
||||
|
||||
#ifdef EXPANDED_NAVIGATION_ACTIVITIES
|
||||
ADD_ACTIVITY_TO_SR( ACT_CLIMB_ALL );
|
||||
ADD_ACTIVITY_TO_SR( ACT_CLIMB_IDLE );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_CLIMB_MOUNT_TOP );
|
||||
ADD_ACTIVITY_TO_SR( ACT_CLIMB_MOUNT_BOTTOM );
|
||||
ADD_ACTIVITY_TO_SR( ACT_CLIMB_DISMOUNT_BOTTOM );
|
||||
#endif
|
||||
|
||||
#ifdef EXPANDED_HL2_COVER_ACTIVITIES
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK1_MED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK2_MED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_MED );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_AR2_MED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_SMG1_MED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_SHOTGUN_MED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_PISTOL_MED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_RPG_MED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_REVOLVER_MED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_CROSSBOW_MED );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_AR2_MED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_SMG1_MED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_SHOTGUN_MED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_PISTOL_MED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_RPG_MED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_REVOLVER_MED );
|
||||
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_CROSSBOW_MED );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_R );
|
||||
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_L );
|
||||
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_LOW_R );
|
||||
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_LOW_L );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_R_RIFLE );
|
||||
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_L_RIFLE );
|
||||
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_LOW_R_RIFLE );
|
||||
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_LOW_L_RIFLE );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_R_PISTOL );
|
||||
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_L_PISTOL );
|
||||
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_LOW_R_PISTOL );
|
||||
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_LOW_L_PISTOL );
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: This is a multi-purpose table which links NPC activities to their gesture variants.
|
||||
//-----------------------------------------------------------------------------
|
||||
CAI_BaseNPC::actlink_t CAI_BaseNPC::gm_ActivityGestureLinks[] =
|
||||
{
|
||||
{ ACT_RANGE_ATTACK1, ACT_GESTURE_RANGE_ATTACK1 },
|
||||
{ ACT_RANGE_ATTACK2, ACT_GESTURE_RANGE_ATTACK2 },
|
||||
{ ACT_MELEE_ATTACK1, ACT_GESTURE_MELEE_ATTACK1 },
|
||||
{ ACT_MELEE_ATTACK2, ACT_GESTURE_MELEE_ATTACK2 },
|
||||
{ ACT_RELOAD, ACT_GESTURE_RELOAD },
|
||||
|
||||
{ ACT_RANGE_ATTACK1_LOW, ACT_GESTURE_RANGE_ATTACK1 }, // NOTE: ACT_GESTURE_RANGE_ATTACK1_LOW exists, but isn't used
|
||||
{ ACT_RANGE_ATTACK2_LOW, ACT_GESTURE_RANGE_ATTACK2 }, // NOTE: ACT_GESTURE_RANGE_ATTACK2_LOW exists, but isn't used
|
||||
{ ACT_RELOAD_LOW, ACT_GESTURE_RELOAD },
|
||||
|
||||
{ ACT_MELEE_ATTACK_SWING, ACT_GESTURE_MELEE_ATTACK_SWING },
|
||||
|
||||
// -----------------------------------------------------------
|
||||
|
||||
{ ACT_RANGE_ATTACK_AR2, ACT_GESTURE_RANGE_ATTACK_AR2 },
|
||||
{ ACT_RANGE_ATTACK_AR2_LOW, ACT_GESTURE_RANGE_ATTACK_AR2 },
|
||||
{ ACT_RANGE_ATTACK_SMG1, ACT_GESTURE_RANGE_ATTACK_SMG1 },
|
||||
{ ACT_RANGE_ATTACK_SMG1_LOW, ACT_GESTURE_RANGE_ATTACK_SMG1 },
|
||||
{ ACT_RANGE_ATTACK_SHOTGUN, ACT_GESTURE_RANGE_ATTACK_SHOTGUN },
|
||||
{ ACT_RANGE_ATTACK_SHOTGUN_LOW, ACT_GESTURE_RANGE_ATTACK_SHOTGUN },
|
||||
{ ACT_RANGE_ATTACK_PISTOL, ACT_GESTURE_RANGE_ATTACK_PISTOL },
|
||||
{ ACT_RANGE_ATTACK_PISTOL_LOW, ACT_GESTURE_RANGE_ATTACK_PISTOL },
|
||||
|
||||
// -----------------------------------------------------------
|
||||
|
||||
{ ACT_SMALL_FLINCH, ACT_GESTURE_SMALL_FLINCH },
|
||||
{ ACT_BIG_FLINCH, ACT_GESTURE_BIG_FLINCH },
|
||||
{ ACT_FLINCH_HEAD, ACT_GESTURE_FLINCH_HEAD },
|
||||
{ ACT_FLINCH_CHEST, ACT_GESTURE_FLINCH_CHEST },
|
||||
{ ACT_FLINCH_STOMACH, ACT_GESTURE_FLINCH_STOMACH },
|
||||
{ ACT_FLINCH_LEFTARM, ACT_GESTURE_FLINCH_LEFTARM },
|
||||
{ ACT_FLINCH_RIGHTARM, ACT_GESTURE_FLINCH_RIGHTARM },
|
||||
{ ACT_FLINCH_LEFTLEG, ACT_GESTURE_FLINCH_LEFTLEG },
|
||||
{ ACT_FLINCH_RIGHTLEG, ACT_GESTURE_FLINCH_RIGHTLEG },
|
||||
|
||||
// -----------------------------------------------------------
|
||||
|
||||
#if AR2_ACTIVITY_FIX == 1
|
||||
{ ACT_RELOAD_AR2, ACT_GESTURE_RELOAD_AR2 },
|
||||
{ ACT_RELOAD_AR2_LOW, ACT_GESTURE_RELOAD_AR2 },
|
||||
#endif
|
||||
{ ACT_RELOAD_SMG1, ACT_GESTURE_RELOAD_SMG1 },
|
||||
{ ACT_RELOAD_SMG1_LOW, ACT_GESTURE_RELOAD_SMG1 },
|
||||
{ ACT_RELOAD_SHOTGUN, ACT_GESTURE_RELOAD_SHOTGUN },
|
||||
{ ACT_RELOAD_SHOTGUN_LOW, ACT_GESTURE_RELOAD_SHOTGUN },
|
||||
{ ACT_RELOAD_PISTOL, ACT_GESTURE_RELOAD_PISTOL },
|
||||
{ ACT_RELOAD_PISTOL_LOW, ACT_GESTURE_RELOAD_PISTOL },
|
||||
|
||||
#ifdef SHARED_COMBINE_ACTIVITIES
|
||||
{ ACT_SPECIAL_ATTACK1, ACT_GESTURE_SPECIAL_ATTACK1 },
|
||||
{ ACT_SPECIAL_ATTACK2, ACT_GESTURE_SPECIAL_ATTACK2 },
|
||||
{ ACT_COMBINE_THROW_GRENADE, ACT_GESTURE_COMBINE_THROW_GRENADE },
|
||||
{ ACT_COMBINE_AR2_ALTFIRE, ACT_GESTURE_COMBINE_AR2_ALTFIRE },
|
||||
|
||||
{ ACT_SIGNAL_ADVANCE, ACT_GESTURE_SIGNAL_ADVANCE },
|
||||
{ ACT_SIGNAL_FORWARD, ACT_GESTURE_SIGNAL_FORWARD },
|
||||
{ ACT_SIGNAL_GROUP, ACT_GESTURE_SIGNAL_GROUP },
|
||||
{ ACT_SIGNAL_HALT, ACT_GESTURE_SIGNAL_HALT },
|
||||
{ ACT_SIGNAL_LEFT, ACT_GESTURE_SIGNAL_LEFT },
|
||||
{ ACT_SIGNAL_RIGHT, ACT_GESTURE_SIGNAL_RIGHT },
|
||||
{ ACT_SIGNAL_TAKECOVER, ACT_GESTURE_SIGNAL_TAKECOVER },
|
||||
#endif
|
||||
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
{ ACT_RANGE_ATTACK_REVOLVER, ACT_GESTURE_RANGE_ATTACK_REVOLVER },
|
||||
{ ACT_RANGE_ATTACK_REVOLVER_LOW, ACT_GESTURE_RANGE_ATTACK_REVOLVER },
|
||||
{ ACT_RANGE_ATTACK_CROSSBOW, ACT_GESTURE_RANGE_ATTACK_CROSSBOW },
|
||||
{ ACT_RANGE_ATTACK_CROSSBOW_LOW, ACT_GESTURE_RANGE_ATTACK_CROSSBOW },
|
||||
{ ACT_RANGE_ATTACK_RPG, ACT_GESTURE_RANGE_ATTACK_RPG },
|
||||
{ ACT_RANGE_ATTACK_RPG_LOW, ACT_GESTURE_RANGE_ATTACK_RPG },
|
||||
|
||||
{ ACT_RELOAD_REVOLVER, ACT_GESTURE_RELOAD_REVOLVER },
|
||||
{ ACT_RELOAD_REVOLVER_LOW, ACT_GESTURE_RELOAD_REVOLVER },
|
||||
{ ACT_RELOAD_CROSSBOW, ACT_GESTURE_RELOAD_CROSSBOW },
|
||||
{ ACT_RELOAD_CROSSBOW_LOW, ACT_GESTURE_RELOAD_CROSSBOW },
|
||||
#endif
|
||||
};
|
||||
|
||||
Activity CAI_BaseNPC::GetGestureVersionOfActivity( Activity inActivity )
|
||||
{
|
||||
actlink_t *pTable = gm_ActivityGestureLinks;
|
||||
int actCount = ARRAYSIZE( gm_ActivityGestureLinks );
|
||||
|
||||
for ( int i = 0; i < actCount; i++, pTable++ )
|
||||
{
|
||||
if ( inActivity == pTable->sequence )
|
||||
{
|
||||
return pTable->gesture;
|
||||
}
|
||||
}
|
||||
|
||||
return ACT_INVALID;
|
||||
}
|
||||
|
||||
Activity CAI_BaseNPC::GetSequenceVersionOfGesture( Activity inActivity )
|
||||
{
|
||||
actlink_t *pTable = gm_ActivityGestureLinks;
|
||||
int actCount = ARRAYSIZE( gm_ActivityGestureLinks );
|
||||
|
||||
for (int i = 0; i < actCount; i++, pTable++)
|
||||
{
|
||||
if (inActivity == pTable->gesture)
|
||||
{
|
||||
return pTable->sequence;
|
||||
}
|
||||
}
|
||||
|
||||
return ACT_INVALID;
|
||||
}
|
||||
#endif
|
||||
|
@ -101,8 +101,8 @@ END_DATADESC()
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
BEGIN_ENT_SCRIPTDESC( CAI_BaseActor, CAI_BaseNPC, "The base class for NPCs which act in complex choreo scenes." )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptAddLookTarget, "AddLookTarget", "Add a potential look target for this actor." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptAddLookTargetPos, "AddLookTargetPos", "Add a potential look target position for this actor." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptAddLookTarget, "AddLookTarget", "Add a potential look target for this actor with the specified importance, duration, and ramp." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptAddLookTargetPos, "AddLookTargetPos", "Add a potential look target position for this actor with the specified importance, duration, and ramp." )
|
||||
|
||||
END_SCRIPTDESC();
|
||||
#endif
|
||||
@ -835,7 +835,11 @@ void CAI_BaseActor::UpdateLatchedValues( )
|
||||
// set head latch
|
||||
m_fLatchedPositions |= HUMANOID_LATCHED_HEAD;
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
if ( CanSkipAnimation() || !GetAttachment( "eyes", m_latchedEyeOrigin, &m_latchedHeadDirection ))
|
||||
#else
|
||||
if (!HasCondition( COND_IN_PVS ) || !GetAttachment( "eyes", m_latchedEyeOrigin, &m_latchedHeadDirection ))
|
||||
#endif
|
||||
{
|
||||
m_latchedEyeOrigin = BaseClass::EyePosition( );
|
||||
AngleVectors( GetLocalAngles(), &m_latchedHeadDirection );
|
||||
@ -1626,7 +1630,11 @@ void CAI_BaseActor::MaintainLookTargets( float flInterval )
|
||||
}
|
||||
|
||||
// don't bother with any of the rest if the player can't see you
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
if ( CanSkipAnimation() )
|
||||
#else
|
||||
if (!HasCondition( COND_IN_PVS ))
|
||||
#endif
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -100,6 +100,10 @@
|
||||
#include "items.h"
|
||||
#endif
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
#include "mapbase/vscript_funcs_shared.h"
|
||||
#endif
|
||||
|
||||
#include "env_debughistory.h"
|
||||
#include "collisionutils.h"
|
||||
|
||||
@ -165,6 +169,8 @@ extern ConVar ai_vehicle_avoidance;
|
||||
extern ISoundEmitterSystemBase *soundemitterbase;
|
||||
|
||||
ConVar ai_dynint_always_enabled( "ai_dynint_always_enabled", "0", FCVAR_NONE, "Makes the \"Don't Care\" setting equivalent to \"Yes\"." );
|
||||
|
||||
ConVar ai_debug_fake_sequence_gestures_always_play( "ai_debug_fake_sequence_gestures_always_play", "0", FCVAR_NONE, "Always plays fake sequence gestures." );
|
||||
#endif
|
||||
|
||||
#ifndef _RETAIL
|
||||
@ -309,6 +315,8 @@ ScriptHook_t CAI_BaseNPC::g_Hook_QuerySeeEntity;
|
||||
ScriptHook_t CAI_BaseNPC::g_Hook_TranslateActivity;
|
||||
ScriptHook_t CAI_BaseNPC::g_Hook_TranslateSchedule;
|
||||
ScriptHook_t CAI_BaseNPC::g_Hook_GetActualShootPosition;
|
||||
ScriptHook_t CAI_BaseNPC::g_Hook_OverrideMove;
|
||||
ScriptHook_t CAI_BaseNPC::g_Hook_ShouldPlayFakeSequenceGesture;
|
||||
#endif
|
||||
|
||||
//
|
||||
@ -664,7 +672,7 @@ void CAI_BaseNPC::Ignite( float flFlameLifetime, bool bNPCOnly, float flSize, bo
|
||||
|
||||
#ifdef HL2_EPISODIC
|
||||
CBasePlayer *pPlayer = AI_GetSinglePlayer();
|
||||
if ( pPlayer->IRelationType( this ) != D_LI )
|
||||
if ( pPlayer && pPlayer->IRelationType( this ) != D_LI )
|
||||
{
|
||||
CNPC_Alyx *alyx = CNPC_Alyx::GetAlyx();
|
||||
|
||||
@ -729,7 +737,7 @@ HSCRIPT CAI_BaseNPC::VScriptFindEnemyMemory( HSCRIPT pEnemy )
|
||||
AI_EnemyInfo_t *info = GetEnemies()->Find( ToEnt(pEnemy) );
|
||||
if (info)
|
||||
{
|
||||
hScript = g_pScriptVM->RegisterInstance( info );
|
||||
hScript = g_pScriptVM->RegisterInstance( reinterpret_cast<Script_AI_EnemyInfo_t*>(info) );
|
||||
}
|
||||
|
||||
return hScript;
|
||||
@ -989,29 +997,27 @@ int CAI_BaseNPC::OnTakeDamage_Alive( const CTakeDamageInfo &info )
|
||||
// only fire once per frame
|
||||
m_OnDamaged.FireOutput( info.GetAttacker(), this);
|
||||
|
||||
if( info.GetAttacker()->IsPlayer() )
|
||||
if ( info.GetAttacker() )
|
||||
{
|
||||
m_OnDamagedByPlayer.FireOutput( info.GetAttacker(), this );
|
||||
|
||||
// This also counts as being harmed by player's squad.
|
||||
m_OnDamagedByPlayerSquad.FireOutput( info.GetAttacker(), this );
|
||||
}
|
||||
else
|
||||
{
|
||||
// See if the person that injured me is an NPC.
|
||||
#ifdef MAPBASE
|
||||
// Sometimes I find these things and I can't just sit idly by.
|
||||
CAI_BaseNPC *pAttacker = info.GetAttacker()->MyNPCPointer();
|
||||
#else
|
||||
CAI_BaseNPC *pAttacker = dynamic_cast<CAI_BaseNPC *>( info.GetAttacker() );
|
||||
#endif
|
||||
CBasePlayer *pPlayer = AI_GetSinglePlayer();
|
||||
|
||||
if( pAttacker && pAttacker->IsAlive() && pPlayer )
|
||||
if( info.GetAttacker()->IsPlayer() )
|
||||
{
|
||||
if( pAttacker->GetSquad() != NULL && pAttacker->IsInPlayerSquad() )
|
||||
m_OnDamagedByPlayer.FireOutput( info.GetAttacker(), this );
|
||||
|
||||
// This also counts as being harmed by player's squad.
|
||||
m_OnDamagedByPlayerSquad.FireOutput( info.GetAttacker(), this );
|
||||
}
|
||||
else
|
||||
{
|
||||
// See if the person that injured me is an NPC.
|
||||
CAI_BaseNPC *pAttacker = info.GetAttacker()->MyNPCPointer();
|
||||
CBasePlayer *pPlayer = AI_GetSinglePlayer();
|
||||
|
||||
if( pAttacker && pAttacker->IsAlive() && pPlayer )
|
||||
{
|
||||
m_OnDamagedByPlayerSquad.FireOutput( info.GetAttacker(), this );
|
||||
if( pAttacker->GetSquad() != NULL && pAttacker->IsInPlayerSquad() )
|
||||
{
|
||||
m_OnDamagedByPlayerSquad.FireOutput( info.GetAttacker(), this );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2592,7 +2598,11 @@ bool CAI_BaseNPC::FValidateHintType ( CAI_Hint *pHint )
|
||||
Activity CAI_BaseNPC::GetHintActivity( short sHintType, Activity HintsActivity )
|
||||
{
|
||||
if ( HintsActivity != ACT_INVALID )
|
||||
#ifdef MAPBASE
|
||||
return TranslateActivity( HintsActivity ); // Always translate the activity
|
||||
#else
|
||||
return HintsActivity;
|
||||
#endif
|
||||
|
||||
return ACT_IDLE;
|
||||
}
|
||||
@ -6507,7 +6517,7 @@ CAI_BaseNPC *CAI_BaseNPC::CreateCustomTarget( const Vector &vecOrigin, float dur
|
||||
//-----------------------------------------------------------------------------
|
||||
Activity CAI_BaseNPC::TranslateCrouchActivity( Activity eNewActivity )
|
||||
{
|
||||
if (CapabilitiesGet() & bits_CAP_DUCK)
|
||||
if (CapabilitiesGet() & bits_CAP_DUCK && CanTranslateCrouchActivity())
|
||||
{
|
||||
// ========================================================================
|
||||
// The main issue with cover hint nodes is that crouch activities are not translated at the right time
|
||||
@ -6539,10 +6549,18 @@ Activity CAI_BaseNPC::TranslateCrouchActivity( Activity eNewActivity )
|
||||
CAI_Hint *pHint = GetHintNode();
|
||||
if (pHint)
|
||||
{
|
||||
if (pHint->HintType() == HINT_TACTICAL_COVER_LOW || pHint->HintType() == HINT_TACTICAL_COVER_MED)
|
||||
if (pHint->HintType() == HINT_TACTICAL_COVER_LOW)
|
||||
{
|
||||
nCoverActivity = ACT_RANGE_ATTACK1_LOW;
|
||||
}
|
||||
else if (pHint->HintType() == HINT_TACTICAL_COVER_MED)
|
||||
{
|
||||
#ifdef EXPANDED_HL2_COVER_ACTIVITIES
|
||||
nCoverActivity = ACT_RANGE_ATTACK1_MED;
|
||||
#else
|
||||
nCoverActivity = ACT_RANGE_ATTACK1_LOW;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6584,15 +6602,30 @@ Activity CAI_BaseNPC::NPC_BackupActivity( Activity eNewActivity )
|
||||
//if (eNewActivity == ACT_DROP_WEAPON)
|
||||
// return TranslateActivity(ACT_IDLE);
|
||||
|
||||
// ---------------------------------------------
|
||||
|
||||
// Accounts for certain act busy activities that aren't on all NPCs.
|
||||
if (eNewActivity == ACT_BUSY_QUEUE || eNewActivity == ACT_BUSY_STAND)
|
||||
return TranslateActivity(ACT_IDLE);
|
||||
|
||||
// ---------------------------------------------
|
||||
|
||||
if (eNewActivity == ACT_WALK_ANGRY)
|
||||
return TranslateActivity(ACT_WALK);
|
||||
|
||||
// GetCoverActivity() should have this covered.
|
||||
// ---------------------------------------------
|
||||
|
||||
// If one climbing animation isn't available, use the other
|
||||
if (eNewActivity == ACT_CLIMB_DOWN)
|
||||
return ACT_CLIMB_UP;
|
||||
else if (eNewActivity == ACT_CLIMB_UP)
|
||||
return ACT_CLIMB_DOWN;
|
||||
|
||||
// ---------------------------------------------
|
||||
|
||||
if (eNewActivity == ACT_COVER_MED)
|
||||
eNewActivity = ACT_COVER_LOW;
|
||||
|
||||
//if (eNewActivity == ACT_COVER)
|
||||
// return TranslateActivity(ACT_IDLE);
|
||||
|
||||
@ -6607,6 +6640,14 @@ Activity CAI_BaseNPC::NPC_BackupActivity( Activity eNewActivity )
|
||||
//-----------------------------------------------------------------------------
|
||||
Activity CAI_BaseNPC::NPC_TranslateActivity( Activity eNewActivity )
|
||||
{
|
||||
#ifdef EXPANDED_NAVIGATION_ACTIVITIES
|
||||
if ( GetNavType() == NAV_CLIMB && eNewActivity == ACT_IDLE )
|
||||
{
|
||||
// Schedules which break into idle activities should try to maintain the climbing animation.
|
||||
return ACT_CLIMB_IDLE;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MAPBASE
|
||||
Assert( eNewActivity != ACT_INVALID );
|
||||
|
||||
@ -6616,15 +6657,7 @@ Activity CAI_BaseNPC::NPC_TranslateActivity( Activity eNewActivity )
|
||||
{
|
||||
case ACT_RANGE_ATTACK1: eNewActivity = ACT_RANGE_ATTACK1_LOW; break;
|
||||
case ACT_RELOAD: eNewActivity = ACT_RELOAD_LOW; break;
|
||||
case ACT_IDLE: eNewActivity = ACT_CROUCHIDLE; break;
|
||||
|
||||
// ====
|
||||
// HACK : LEIPZIG 06 - The underlying problem is that the AR2 and SMG1 cannot map IDLE_ANGRY to a crouched equivalent automatically
|
||||
// which causes the character to pop up and down in their idle state of firing while crouched. -- jdw
|
||||
case ACT_IDLE_ANGRY_SMG1:
|
||||
case ACT_IDLE_ANGRY_AR2:
|
||||
eNewActivity = ACT_RANGE_AIM_LOW;
|
||||
break;
|
||||
case ACT_IDLE: eNewActivity = ACT_RANGE_AIM_LOW; break; // ACT_CROUCHIDLE is more-or-less deprecated and not friendly to weapon translation
|
||||
}
|
||||
}
|
||||
|
||||
@ -6837,7 +6870,12 @@ void CAI_BaseNPC::ResolveActivityToSequence(Activity NewActivity, int &iSequence
|
||||
|
||||
translatedActivity = TranslateActivity( NewActivity, &weaponActivity );
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Cover cases where TranslateActivity() returns a sequence by using ACT_SCRIPT_CUSTOM_MOVE
|
||||
if ( NewActivity == ACT_SCRIPT_CUSTOM_MOVE || translatedActivity == ACT_SCRIPT_CUSTOM_MOVE )
|
||||
#else
|
||||
if ( NewActivity == ACT_SCRIPT_CUSTOM_MOVE )
|
||||
#endif
|
||||
{
|
||||
iSequence = GetScriptCustomMoveSequence();
|
||||
}
|
||||
@ -7023,6 +7061,23 @@ void CAI_BaseNPC::SetIdealActivity( Activity NewActivity )
|
||||
// Perform translation in case we need to change sequences within a single activity,
|
||||
// such as between a standing idle and a crouching idle.
|
||||
ResolveActivityToSequence(m_IdealActivity, m_nIdealSequence, m_IdealTranslatedActivity, m_IdealWeaponActivity);
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Check if we need a gesture to imitate this sequence
|
||||
if ( ShouldPlayFakeSequenceGesture( m_IdealActivity, m_IdealTranslatedActivity ) )
|
||||
{
|
||||
Activity nGesture = SelectFakeSequenceGesture( m_IdealActivity, m_IdealTranslatedActivity );
|
||||
if (nGesture != -1)
|
||||
{
|
||||
PlayFakeSequenceGesture( nGesture, m_IdealActivity, m_IdealTranslatedActivity );
|
||||
}
|
||||
}
|
||||
else if (GetFakeSequenceGesture() != -1)
|
||||
{
|
||||
// Reset the current gesture sequence if there is one
|
||||
ResetFakeSequenceGesture();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -7071,6 +7126,14 @@ void CAI_BaseNPC::AdvanceToIdealActivity(void)
|
||||
//DevMsg("%s: Unable to get from sequence %s to %s!\n", GetClassname(), GetSequenceName(GetSequence()), GetSequenceName(m_nIdealSequence));
|
||||
SetActivity(m_IdealActivity);
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
// If there was a gesture imitating a sequence, get rid of it
|
||||
if ( GetFakeSequenceGesture() != -1 )
|
||||
{
|
||||
ResetFakeSequenceGesture();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -7128,6 +7191,12 @@ void CAI_BaseNPC::MaintainActivity(void)
|
||||
}
|
||||
// Else a transition sequence is in progress, do nothing.
|
||||
}
|
||||
#ifdef MAPBASE
|
||||
else if (GetFakeSequenceGesture() != -1)
|
||||
{
|
||||
// Don't advance even if the sequence gesture is finished, as advancing would just play the original activity afterwards
|
||||
}
|
||||
#endif
|
||||
// Else get a specific sequence for the activity and try to transition to that.
|
||||
else
|
||||
{
|
||||
@ -7146,11 +7215,103 @@ void CAI_BaseNPC::MaintainActivity(void)
|
||||
}
|
||||
|
||||
|
||||
#ifdef MAPBASE
|
||||
bool CAI_BaseNPC::ShouldPlayFakeSequenceGesture( Activity nActivity, Activity nTranslatedActivity )
|
||||
{
|
||||
// Don't do anything if we're resetting our activity
|
||||
if (GetActivity() == ACT_RESET)
|
||||
return false;
|
||||
|
||||
// No need to do this while we're moving
|
||||
if (IsCurTaskContinuousMove())
|
||||
return false;
|
||||
|
||||
if (ai_debug_fake_sequence_gestures_always_play.GetBool())
|
||||
return true;
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if (m_ScriptScope.IsInitialized() && g_Hook_ShouldPlayFakeSequenceGesture.CanRunInScope(m_ScriptScope))
|
||||
{
|
||||
// activity, translatedActivity
|
||||
ScriptVariant_t functionReturn;
|
||||
ScriptVariant_t args[] = { GetActivityName( nActivity ), GetActivityName( nTranslatedActivity ) };
|
||||
if (g_Hook_ShouldPlayFakeSequenceGesture.Call( m_ScriptScope, &functionReturn, args ))
|
||||
{
|
||||
if (functionReturn.m_type == FIELD_BOOLEAN)
|
||||
return functionReturn.m_bool;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (GetHintNode() && GetHintNode()->HintActivityName() != NULL_STRING)
|
||||
{
|
||||
switch (GetHintNode()->HintType())
|
||||
{
|
||||
// Cover nodes with custom activities should allow NPCs to do things like reload while in cover.
|
||||
case HINT_TACTICAL_COVER_LOW:
|
||||
case HINT_TACTICAL_COVER_MED:
|
||||
case HINT_TACTICAL_COVER_CUSTOM:
|
||||
if (HasMemory( bits_MEMORY_INCOVER ))
|
||||
{
|
||||
// Don't attack while using a custom animation in cover
|
||||
if (nActivity != ACT_RANGE_ATTACK1 && nActivity != ACT_RANGE_ATTACK1_LOW)
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Activity CAI_BaseNPC::SelectFakeSequenceGesture( Activity nActivity, Activity nTranslatedActivity )
|
||||
{
|
||||
return GetGestureVersionOfActivity( nTranslatedActivity );
|
||||
}
|
||||
|
||||
inline void CAI_BaseNPC::PlayFakeSequenceGesture( Activity nActivity, Activity nSequence, Activity nTranslatedSequence )
|
||||
{
|
||||
RestartGesture( nActivity, true, true );
|
||||
m_FakeSequenceGestureLayer = FindGestureLayer( nActivity );
|
||||
|
||||
switch ( nSequence )
|
||||
{
|
||||
case ACT_RANGE_ATTACK1:
|
||||
//case ACT_RANGE_ATTACK2:
|
||||
{
|
||||
OnRangeAttack1();
|
||||
|
||||
// FIXME: this seems a bit wacked
|
||||
Weapon_SetActivity( Weapon_TranslateActivity( nSequence ), 0 );
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
inline int CAI_BaseNPC::GetFakeSequenceGesture()
|
||||
{
|
||||
return m_FakeSequenceGestureLayer;
|
||||
}
|
||||
|
||||
void CAI_BaseNPC::ResetFakeSequenceGesture()
|
||||
{
|
||||
SetLayerCycle( m_FakeSequenceGestureLayer, 1.0f );
|
||||
m_FakeSequenceGestureLayer = -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Returns true if our ideal activity has finished playing.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CAI_BaseNPC::IsActivityFinished( void )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
if (GetFakeSequenceGesture() != -1)
|
||||
{
|
||||
return IsLayerFinished( GetFakeSequenceGesture() );
|
||||
}
|
||||
#endif
|
||||
|
||||
return (IsSequenceFinished() && (GetSequence() == m_nIdealSequence));
|
||||
}
|
||||
|
||||
@ -7186,6 +7347,15 @@ void CAI_BaseNPC::OnChangeActivity( Activity eNewActivity )
|
||||
eNewActivity == ACT_WALK )
|
||||
{
|
||||
Stand();
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Unlock custom cover nodes
|
||||
if (GetHintNode() && GetHintNode()->HintType() == HINT_TACTICAL_COVER_CUSTOM && HasMemory(bits_MEMORY_INCOVER))
|
||||
{
|
||||
GetHintNode()->Unlock( GetHintDelay( GetHintNode()->HintType() ) );
|
||||
SetHintNode( NULL );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -7462,7 +7632,11 @@ void CAI_BaseNPC::SetHullSizeNormal( bool force )
|
||||
if ( m_fIsUsingSmallHull || force )
|
||||
{
|
||||
// Find out what the height difference will be between the versions and adjust our bbox accordingly to keep us level
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
const float flScale = MIN( 1.0f, GetModelScale() ); // NOTE: Cannot scale NPC bounding box up, as pathfinding will fail (hull needs to match the traces used for the node network)
|
||||
#else
|
||||
const float flScale = GetModelScale();
|
||||
#endif
|
||||
Vector vecMins = ( GetHullMins() * flScale );
|
||||
Vector vecMaxs = ( GetHullMaxs() * flScale );
|
||||
|
||||
@ -7770,7 +7944,7 @@ int CAI_BaseNPC::HolsterWeapon( void )
|
||||
if ( IsWeaponHolstered() )
|
||||
return -1;
|
||||
|
||||
#ifdef COMPANION_HOLSTER_WORKAROUND
|
||||
#ifdef MAPBASE
|
||||
Activity activity = TranslateActivity( ACT_DISARM );
|
||||
int iHolsterGesture = FindGestureLayer( activity );
|
||||
if ( iHolsterGesture != -1 )
|
||||
@ -7826,7 +8000,7 @@ int CAI_BaseNPC::UnholsterWeapon( void )
|
||||
if ( !IsWeaponHolstered() )
|
||||
return -1;
|
||||
|
||||
#ifdef COMPANION_HOLSTER_WORKAROUND
|
||||
#ifdef MAPBASE
|
||||
Activity activity = TranslateActivity( ACT_ARM );
|
||||
int iHolsterGesture = FindGestureLayer( activity );
|
||||
#else
|
||||
@ -7855,13 +8029,12 @@ int CAI_BaseNPC::UnholsterWeapon( void )
|
||||
{
|
||||
SetActiveWeapon( GetWeapon(i) );
|
||||
|
||||
#ifdef COMPANION_HOLSTER_WORKAROUND
|
||||
int iLayer = AddGesture( activity, true );
|
||||
//iLayer = AddGesture( ACT_GESTURE_ARM, true );
|
||||
#ifdef MAPBASE
|
||||
int iLayer = AddGesture( TranslateActivity( ACT_ARM ), true );
|
||||
#else
|
||||
int iLayer = AddGesture( ACT_ARM, true );
|
||||
//iLayer = AddGesture( ACT_GESTURE_ARM, true );
|
||||
#endif
|
||||
//iLayer = AddGesture( ACT_GESTURE_ARM, true );
|
||||
|
||||
if (iLayer != -1)
|
||||
{
|
||||
@ -8040,6 +8213,26 @@ bool CAI_BaseNPC::DoUnholster( void )
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Returns true if the NPC should be unholstering their weapon
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CAI_BaseNPC::ShouldUnholsterWeapon( void )
|
||||
{
|
||||
return GetState() == NPC_STATE_COMBAT;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Returns true if the NPC can unholster their weapon
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CAI_BaseNPC::CanUnholsterWeapon( void )
|
||||
{
|
||||
// Don't unholster during special navigation
|
||||
if ( GetNavType() == NAV_JUMP || GetNavType() == NAV_CLIMB )
|
||||
return false;
|
||||
|
||||
return IsWeaponHolstered();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose: Give the NPC in question the weapon specified
|
||||
//------------------------------------------------------------------------------
|
||||
@ -9106,27 +9299,45 @@ Activity CAI_BaseNPC::GetCoverActivity( CAI_Hint *pHint )
|
||||
switch (pHint->HintType())
|
||||
{
|
||||
case HINT_TACTICAL_COVER_MED:
|
||||
#ifndef MAPBASE // I know what you're thinking, but ACT_COVER_MED is pretty much deprecated at this point anyway.
|
||||
{
|
||||
nCoverActivity = ACT_COVER_MED;
|
||||
#ifdef MAPBASE
|
||||
// Some NPCs lack ACT_COVER_MED, but could easily use ACT_COVER_LOW.
|
||||
if (SelectWeightedSequence(nCoverActivity) == ACTIVITY_NOT_AVAILABLE)
|
||||
nCoverActivity = ACT_COVER_LOW;
|
||||
#endif
|
||||
// NPCs which lack ACT_COVER_MED should fall through to HINT_TACTICAL_COVER_LOW
|
||||
if (SelectWeightedSequence( ACT_COVER_MED ) != ACTIVITY_NOT_AVAILABLE)
|
||||
{
|
||||
nCoverActivity = ACT_COVER_MED;
|
||||
}
|
||||
#else
|
||||
nCoverActivity = ACT_COVER_MED;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
case HINT_TACTICAL_COVER_LOW:
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
if (pHint->HintActivityName() != NULL_STRING)
|
||||
nCoverActivity = (Activity)CAI_BaseNPC::GetActivityID( STRING(pHint->HintActivityName()) );
|
||||
else
|
||||
#endif
|
||||
// Make sure nCoverActivity wasn't already assigned above, then fall through to HINT_TACTICAL_COVER_CUSTOM
|
||||
if (nCoverActivity == ACT_INVALID)
|
||||
nCoverActivity = ACT_COVER_LOW;
|
||||
#else
|
||||
nCoverActivity = ACT_COVER_LOW;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
case HINT_TACTICAL_COVER_CUSTOM:
|
||||
{
|
||||
if (pHint->HintActivityName() != NULL_STRING)
|
||||
{
|
||||
nCoverActivity = (Activity)CAI_BaseNPC::GetActivityID( STRING(pHint->HintActivityName()) );
|
||||
if (nCoverActivity == ACT_INVALID)
|
||||
{
|
||||
m_iszSceneCustomMoveSeq = pHint->HintActivityName();
|
||||
nCoverActivity = ACT_SCRIPT_CUSTOM_MOVE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -9164,6 +9375,13 @@ float CAI_BaseNPC::CalcIdealYaw( const Vector &vecTarget )
|
||||
|
||||
return UTIL_VecToYaw( vecProjection - GetLocalOrigin() );
|
||||
}
|
||||
#ifdef MAPBASE
|
||||
// Allow hint nodes to override the yaw without needing to control AI
|
||||
else if (GetHintNode() && GetHintNode()->OverridesNPCYaw( this ))
|
||||
{
|
||||
return GetHintNode()->Yaw();
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return UTIL_VecToYaw ( vecTarget - GetLocalOrigin() );
|
||||
@ -9504,7 +9722,7 @@ void CAI_BaseNPC::HandleAnimEvent( animevent_t *pEvent )
|
||||
if ( GetActiveWeapon() )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
GetActiveWeapon()->Reload_NPC();
|
||||
GetActiveWeapon()->Reload_NPC( true );
|
||||
#else
|
||||
GetActiveWeapon()->WeaponSound( RELOAD_NPC );
|
||||
GetActiveWeapon()->m_iClip1 = GetActiveWeapon()->GetMaxClip1();
|
||||
@ -9528,8 +9746,12 @@ void CAI_BaseNPC::HandleAnimEvent( animevent_t *pEvent )
|
||||
case EVENT_WEAPON_RELOAD_FILL_CLIP:
|
||||
{
|
||||
if ( GetActiveWeapon() )
|
||||
{
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
GetActiveWeapon()->Reload_NPC( false );
|
||||
#else
|
||||
GetActiveWeapon()->m_iClip1 = GetActiveWeapon()->GetMaxClip1();
|
||||
#endif
|
||||
ClearCondition(COND_LOW_PRIMARY_AMMO);
|
||||
ClearCondition(COND_NO_PRIMARY_AMMO);
|
||||
ClearCondition(COND_NO_SECONDARY_AMMO);
|
||||
@ -9544,7 +9766,11 @@ void CAI_BaseNPC::HandleAnimEvent( animevent_t *pEvent )
|
||||
|
||||
case NPC_EVENT_OPEN_DOOR:
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
CBasePropDoor *pDoor = m_hOpeningDoor;
|
||||
#else
|
||||
CBasePropDoor *pDoor = (CBasePropDoor *)(CBaseEntity *)GetNavigator()->GetPath()->GetCurWaypoint()->GetEHandleData();
|
||||
#endif
|
||||
if (pDoor != NULL)
|
||||
{
|
||||
OpenPropDoorNow( pDoor );
|
||||
@ -10692,6 +10918,7 @@ Vector CAI_BaseNPC::GetActualShootPosition( const Vector &shootOrigin )
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if (m_ScriptScope.IsInitialized() && g_Hook_GetActualShootPosition.CanRunInScope(m_ScriptScope))
|
||||
{
|
||||
// shootOrigin, target
|
||||
ScriptVariant_t functionReturn;
|
||||
ScriptVariant_t args[] = { shootOrigin, ToHScript( GetEnemy() ) };
|
||||
if (g_Hook_GetActualShootPosition.Call( m_ScriptScope, &functionReturn, args ))
|
||||
@ -11491,6 +11718,14 @@ bool CAI_BaseNPC::ChooseEnemy( void )
|
||||
//=========================================================
|
||||
void CAI_BaseNPC::PickupWeapon( CBaseCombatWeapon *pWeapon )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
if ( pWeapon->VPhysicsGetObject() && pWeapon->VPhysicsGetObject()->GetGameFlags() & FVPHYSICS_PLAYER_HELD )
|
||||
{
|
||||
CBasePlayer *pPlayer = UTIL_GetLocalPlayer();
|
||||
pPlayer->ForceDropOfCarriedPhysObjects( pWeapon );
|
||||
}
|
||||
#endif
|
||||
|
||||
pWeapon->OnPickedUp( this );
|
||||
Weapon_Equip( pWeapon );
|
||||
m_iszPendingWeapon = NULL_STRING;
|
||||
@ -11572,6 +11807,10 @@ CBaseEntity *CAI_BaseNPC::DropItem ( const char *pszItemName, Vector vecPos, QAn
|
||||
pItem->ApplyLocalAngularVelocityImpulse( AngularImpulse( 0, random->RandomFloat( 0, 100 ), 0 ) );
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
m_OnItemDrop.Set( pItem, pItem, this );
|
||||
#endif
|
||||
|
||||
return pItem;
|
||||
}
|
||||
else
|
||||
@ -11894,6 +12133,7 @@ BEGIN_DATADESC( CAI_BaseNPC )
|
||||
DEFINE_KEYFIELD( m_FriendlyFireOverride, FIELD_INTEGER, "FriendlyFireOverride" ),
|
||||
|
||||
DEFINE_KEYFIELD( m_flSpeedModifier, FIELD_FLOAT, "BaseSpeedModifier" ),
|
||||
DEFINE_FIELD( m_FakeSequenceGestureLayer, FIELD_INTEGER ),
|
||||
#endif
|
||||
|
||||
// Satisfy classcheck
|
||||
@ -11939,6 +12179,7 @@ BEGIN_DATADESC( CAI_BaseNPC )
|
||||
DEFINE_OUTPUT( m_OnForcedInteractionFinished, "OnForcedInteractionFinished" ),
|
||||
#ifdef MAPBASE
|
||||
DEFINE_OUTPUT( m_OnItemPickup, "OnItemPickup" ),
|
||||
DEFINE_OUTPUT( m_OnItemDrop, "OnItemDrop" ),
|
||||
#endif
|
||||
|
||||
// Inputs
|
||||
@ -12050,6 +12291,11 @@ BEGIN_ENT_SCRIPTDESC( CAI_BaseNPC, CBaseCombatCharacter, "The base class all NPC
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptSetActivityID, "SetActivityID", "Set the NPC's current activity ID." )
|
||||
DEFINE_SCRIPTFUNC( ResetActivity, "Reset the NPC's current activity." )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetGestureVersionOfActivity, "GetGestureVersionOfActivity", "Get the gesture activity counterpart of the specified sequence activity, if one exists." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetGestureVersionOfActivityID, "GetGestureVersionOfActivityID", "Get the gesture activity ID counterpart of the specified sequence activity ID, if one exists." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetSequenceVersionOfGesture, "GetSequenceVersionOfGesture", "Get the sequence activity counterpart of the specified gesture activity, if one exists." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetSequenceVersionOfGestureID, "GetSequenceVersionOfGestureID", "Get the sequence activity ID counterpart of the specified gesture activity ID, if one exists." )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetSchedule, "GetSchedule", "Get the NPC's current schedule." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetScheduleID, "GetScheduleID", "Get the NPC's current schedule ID." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptSetSchedule, "SetSchedule", "Set the NPC's current schedule." )
|
||||
@ -12096,10 +12342,17 @@ BEGIN_ENT_SCRIPTDESC( CAI_BaseNPC, CBaseCombatCharacter, "The base class all NPC
|
||||
DEFINE_SCRIPTHOOK_PARAM( "schedule", FIELD_CSTRING )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "schedule_id", FIELD_INTEGER )
|
||||
END_SCRIPTHOOK()
|
||||
BEGIN_SCRIPTHOOK( CAI_BaseNPC::g_Hook_GetActualShootPosition, "GetActualShootPosition", FIELD_VOID, "Called when the NPC is getting their actual shoot position, using the default shoot position as the parameter. (NOTE: NPCs which override this themselves might not always use this hook!)" )
|
||||
BEGIN_SCRIPTHOOK( CAI_BaseNPC::g_Hook_GetActualShootPosition, "GetActualShootPosition", FIELD_VECTOR, "Called when the NPC is getting their actual shoot position, using the default shoot position as the parameter. (NOTE: NPCs which override this themselves might not always use this hook!)" )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "shootOrigin", FIELD_VECTOR )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "target", FIELD_HSCRIPT )
|
||||
END_SCRIPTHOOK()
|
||||
BEGIN_SCRIPTHOOK( CAI_BaseNPC::g_Hook_OverrideMove, "OverrideMove", FIELD_VOID, "Called when the NPC runs movement code, allowing the NPC's movement to be overridden by some other method. (NOTE: NPCs which override this themselves might not always use this hook!)" )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "interval", FIELD_FLOAT )
|
||||
END_SCRIPTHOOK()
|
||||
BEGIN_SCRIPTHOOK( CAI_BaseNPC::g_Hook_ShouldPlayFakeSequenceGesture, "ShouldPlayFakeSequenceGesture", FIELD_BOOLEAN, "Called when an activity is set on a NPC. Returning true will make the NPC convert the activity into a gesture (if a gesture is available) and continue their current activity instead." )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "activity", FIELD_CSTRING )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "translatedActivity", FIELD_CSTRING )
|
||||
END_SCRIPTHOOK()
|
||||
|
||||
END_SCRIPTDESC();
|
||||
#endif
|
||||
@ -12750,6 +13003,8 @@ CAI_BaseNPC::CAI_BaseNPC(void)
|
||||
#ifdef MAPBASE
|
||||
m_iDynamicInteractionsAllowed = TRS_NONE;
|
||||
m_flSpeedModifier = 1.0f;
|
||||
|
||||
m_FakeSequenceGestureLayer = -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -13406,6 +13661,10 @@ void CAI_BaseNPC::Teleport( const Vector *newPosition, const QAngle *newAngles,
|
||||
CleanupScriptsOnTeleport( false );
|
||||
|
||||
BaseClass::Teleport( newPosition, newAngles, newVelocity );
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
CheckPVSCondition();
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -13529,6 +13788,20 @@ bool CAI_BaseNPC::OverrideMoveFacing( const AILocalMoveGoal_t &move, float flInt
|
||||
|
||||
bool CAI_BaseNPC::OverrideMove( float flInterval )
|
||||
{
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if (m_ScriptScope.IsInitialized() && g_Hook_OverrideMove.CanRunInScope(m_ScriptScope))
|
||||
{
|
||||
// interval
|
||||
ScriptVariant_t functionReturn;
|
||||
ScriptVariant_t args[] = { flInterval };
|
||||
if (g_Hook_OverrideMove.Call( m_ScriptScope, &functionReturn, args ))
|
||||
{
|
||||
if (functionReturn.m_type == FIELD_BOOLEAN)
|
||||
return functionReturn.m_bool;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -13700,6 +13973,10 @@ bool CAI_BaseNPC::OnUpcomingPropDoor( AILocalMoveGoal_t *pMoveGoal,
|
||||
|
||||
GetNavigator()->GetPath()->PrependWaypoints( pOpenDoorRoute );
|
||||
|
||||
#ifdef MAPBASE
|
||||
GetNavigator()->SetArrivalDirection( opendata.vecFaceDir );
|
||||
#endif
|
||||
|
||||
m_hOpeningDoor = pDoor;
|
||||
pMoveGoal->maxDist = distClear;
|
||||
*pResult = AIMR_CHANGE_TYPE;
|
||||
@ -13720,6 +13997,21 @@ bool CAI_BaseNPC::OnUpcomingPropDoor( AILocalMoveGoal_t *pMoveGoal,
|
||||
//-----------------------------------------------------------------------------
|
||||
void CAI_BaseNPC::OpenPropDoorBegin( CBasePropDoor *pDoor )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
opendata_t opendata;
|
||||
pDoor->GetNPCOpenData(this, opendata);
|
||||
|
||||
if (HaveSequenceForActivity( opendata.eActivity ))
|
||||
{
|
||||
int iLayer = AddGesture( opendata.eActivity );
|
||||
float flDuration = GetLayerDuration( iLayer );
|
||||
|
||||
// Face the door and wait for the activity to finish before trying to move through the doorway.
|
||||
m_flMoveWaitFinished = gpGlobals->curtime + flDuration + pDoor->GetOpenInterval();
|
||||
AddFacingTarget( opendata.vecFaceDir, 1.0, flDuration );
|
||||
}
|
||||
else
|
||||
#else
|
||||
// dvs: not quite working, disabled for now.
|
||||
//opendata_t opendata;
|
||||
//pDoor->GetNPCOpenData(this, opendata);
|
||||
@ -13729,6 +14021,7 @@ void CAI_BaseNPC::OpenPropDoorBegin( CBasePropDoor *pDoor )
|
||||
// SetIdealActivity(opendata.eActivity);
|
||||
//}
|
||||
//else
|
||||
#endif
|
||||
{
|
||||
// We don't have an appropriate sequence, just open the door magically.
|
||||
OpenPropDoorNow( pDoor );
|
||||
@ -13748,6 +14041,15 @@ void CAI_BaseNPC::OpenPropDoorNow( CBasePropDoor *pDoor )
|
||||
|
||||
// Wait for the door to finish opening before trying to move through the doorway.
|
||||
m_flMoveWaitFinished = gpGlobals->curtime + pDoor->GetOpenInterval();
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Remove the door from our waypoint
|
||||
if (GetNavigator()->GetPath() && GetNavigator()->GetCurWaypointFlags() & bits_WP_TO_DOOR)
|
||||
{
|
||||
GetNavigator()->GetPath()->GetCurWaypoint()->ModifyFlags( bits_WP_TO_DOOR, false );
|
||||
GetNavigator()->GetPath()->GetCurWaypoint()->m_hData = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -15937,6 +16239,26 @@ bool CAI_BaseNPC::CouldShootIfCrouching( CBaseEntity *pTarget )
|
||||
return bResult;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Check if this position will block our line of sight if aiming low.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CAI_BaseNPC::CouldShootIfCrouchingAt( const Vector &vecPosition, const Vector &vecForward, const Vector &vecRight, float flDist )
|
||||
{
|
||||
Vector vGunPos = vecPosition;
|
||||
vGunPos += (GetCrouchGunOffset() + vecRight * 8);
|
||||
|
||||
trace_t tr;
|
||||
AI_TraceLOS( vGunPos, vGunPos + (vecForward * flDist), this, &tr );
|
||||
if (tr.fraction != 1.0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -15952,9 +16274,16 @@ bool CAI_BaseNPC::IsCrouchedActivity( Activity activity )
|
||||
case ACT_COVER_SMG1_LOW:
|
||||
case ACT_RELOAD_SMG1_LOW:
|
||||
#ifdef MAPBASE
|
||||
//case ACT_RELOAD_AR2_LOW:
|
||||
#if AR2_ACTIVITY_FIX == 1
|
||||
case ACT_COVER_AR2_LOW:
|
||||
case ACT_RELOAD_AR2_LOW:
|
||||
#endif
|
||||
case ACT_RELOAD_PISTOL_LOW:
|
||||
case ACT_RELOAD_SHOTGUN_LOW:
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
case ACT_RELOAD_REVOLVER_LOW:
|
||||
case ACT_RELOAD_CROSSBOW_LOW:
|
||||
#endif
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
@ -998,6 +998,7 @@ public:
|
||||
Activity NPC_TranslateActivity( Activity eNewActivity );
|
||||
#ifdef MAPBASE
|
||||
Activity TranslateCrouchActivity( Activity baseAct );
|
||||
virtual bool CanTranslateCrouchActivity( void ) { return true; }
|
||||
virtual Activity NPC_BackupActivity( Activity eNewActivity );
|
||||
#endif
|
||||
Activity GetActivity( void ) { return m_Activity; }
|
||||
@ -1020,6 +1021,25 @@ public:
|
||||
|
||||
void SetActivityAndSequence(Activity NewActivity, int iSequence, Activity translatedActivity, Activity weaponActivity);
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------
|
||||
|
||||
// Returns the gesture variant of an activity (i.e. "ACT_GESTURE_RANGE_ATTACK1")
|
||||
static Activity GetGestureVersionOfActivity( Activity inActivity );
|
||||
|
||||
// Returns the sequence variant of a gesture activity
|
||||
static Activity GetSequenceVersionOfGesture( Activity inActivity );
|
||||
|
||||
//-----------------------------------------------------
|
||||
|
||||
virtual bool ShouldPlayFakeSequenceGesture( Activity nActivity, Activity nTranslatedActivity );
|
||||
virtual Activity SelectFakeSequenceGesture( Activity nActivity, Activity nTranslatedActivity );
|
||||
void PlayFakeSequenceGesture( Activity nActivity, Activity nSequence, Activity nTranslatedSequence );
|
||||
|
||||
int GetFakeSequenceGesture();
|
||||
void ResetFakeSequenceGesture();
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
void AdvanceToIdealActivity(void);
|
||||
@ -1033,6 +1053,10 @@ private:
|
||||
Activity m_IdealTranslatedActivity; // Desired actual translated animation state
|
||||
Activity m_IdealWeaponActivity; // Desired weapon animation state
|
||||
|
||||
#ifdef MAPBASE
|
||||
int m_FakeSequenceGestureLayer; // The gesture layer impersonating a sequence (-1 if invalid)
|
||||
#endif
|
||||
|
||||
CNetworkVar(int, m_iDeathPose );
|
||||
CNetworkVar(int, m_iDeathFrame );
|
||||
|
||||
@ -1217,6 +1241,8 @@ public:
|
||||
#endif
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
private:
|
||||
|
||||
// VScript stuff uses "VScript" instead of just "Script" to avoid
|
||||
// confusion with NPC_STATE_SCRIPT or StartScripting
|
||||
HSCRIPT VScriptGetEnemy();
|
||||
@ -1243,6 +1269,11 @@ public:
|
||||
int ScriptTranslateActivity( const char *szActivity ) { return TranslateActivity( (Activity)GetActivityID( szActivity ) ); }
|
||||
int ScriptTranslateActivityID( int iActivity ) { return TranslateActivity( (Activity)iActivity ); }
|
||||
|
||||
const char* VScriptGetGestureVersionOfActivity( const char *pszActivity ) { return GetActivityName( GetGestureVersionOfActivity( (Activity)GetActivityID( pszActivity ) ) ); }
|
||||
int VScriptGetGestureVersionOfActivityID( int iActivity ) { return GetGestureVersionOfActivity( (Activity)iActivity ); }
|
||||
const char* VScriptGetSequenceVersionOfGesture( const char *pszActivity ) { return GetActivityName( GetSequenceVersionOfGesture( (Activity)GetActivityID( pszActivity ) ) ); }
|
||||
int VScriptGetSequenceVersionOfGestureID( int iActivity ) { return GetSequenceVersionOfGesture( (Activity)iActivity ); }
|
||||
|
||||
const char* VScriptGetSchedule();
|
||||
int VScriptGetScheduleID();
|
||||
void VScriptSetSchedule( const char *szSchedule );
|
||||
@ -1731,8 +1762,8 @@ public:
|
||||
virtual bool DoHolster(void);
|
||||
virtual bool DoUnholster(void);
|
||||
|
||||
virtual bool ShouldUnholsterWeapon() { return GetState() == NPC_STATE_COMBAT; }
|
||||
virtual bool CanUnholsterWeapon() { return IsWeaponHolstered(); }
|
||||
virtual bool ShouldUnholsterWeapon();
|
||||
virtual bool CanUnholsterWeapon();
|
||||
|
||||
void InputGiveWeaponHolstered( inputdata_t &inputdata );
|
||||
void InputChangeWeapon( inputdata_t &inputdata );
|
||||
@ -2119,6 +2150,7 @@ public:
|
||||
COutputEHANDLE m_OnUnholsterWeapon;
|
||||
|
||||
COutputEHANDLE m_OnItemPickup;
|
||||
COutputEHANDLE m_OnItemDrop;
|
||||
|
||||
COutputInt m_OnStateChange;
|
||||
#endif
|
||||
@ -2206,6 +2238,10 @@ public:
|
||||
inline void ForceCrouch( void );
|
||||
inline void ClearForceCrouch( void );
|
||||
|
||||
#ifdef MAPBASE
|
||||
bool CouldShootIfCrouchingAt( const Vector &vecPosition, const Vector &vecForward, const Vector &vecRight, float flDist = 48.0f );
|
||||
#endif
|
||||
|
||||
protected:
|
||||
virtual bool Crouch( void );
|
||||
virtual bool Stand( void );
|
||||
@ -2265,6 +2301,16 @@ private:
|
||||
static CAI_GlobalScheduleNamespace gm_SchedulingSymbols;
|
||||
static CAI_ClassScheduleIdSpace gm_ClassScheduleIdSpace;
|
||||
|
||||
#ifdef MAPBASE
|
||||
typedef struct
|
||||
{
|
||||
Activity sequence;
|
||||
Activity gesture;
|
||||
} actlink_t;
|
||||
|
||||
static actlink_t gm_ActivityGestureLinks[];
|
||||
#endif
|
||||
|
||||
public:
|
||||
//----------------------------------------------------
|
||||
// Debugging tools
|
||||
@ -2316,6 +2362,7 @@ public:
|
||||
static ScriptHook_t g_Hook_TranslateSchedule;
|
||||
static ScriptHook_t g_Hook_GetActualShootPosition;
|
||||
static ScriptHook_t g_Hook_OverrideMove;
|
||||
static ScriptHook_t g_Hook_ShouldPlayFakeSequenceGesture;
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
@ -980,11 +980,12 @@ bool CAI_BaseNPC::FindCoverFromEnemy( bool bNodesOnly, float flMinDistance, floa
|
||||
// FIXME: add to goal
|
||||
if (GetHintNode())
|
||||
{
|
||||
GetNavigator()->SetArrivalActivity( GetCoverActivity( GetHintNode() ) );
|
||||
#ifdef MAPBASE
|
||||
if (GetHintNode()->GetIgnoreFacing() != HIF_NO)
|
||||
#endif
|
||||
GetHintNode()->NPCHandleStartNav( this, true );
|
||||
#else
|
||||
GetNavigator()->SetArrivalActivity( GetCoverActivity( GetHintNode() ) );
|
||||
GetNavigator()->SetArrivalDirection( GetHintNode()->GetDirection() );
|
||||
#endif
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -1363,6 +1364,14 @@ void CAI_BaseNPC::StartTask( const Task_t *pTask )
|
||||
break;
|
||||
|
||||
case TASK_STOP_MOVING:
|
||||
#ifdef MAPBASE
|
||||
if ( GetNavType() == NAV_CLIMB )
|
||||
{
|
||||
// Don't clear the goal so that the climb can finish
|
||||
DbgNavMsg( this, "Start TASK_STOP_MOVING with climb workaround\n" );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if ( ( GetNavigator()->IsGoalSet() && GetNavigator()->IsGoalActive() ) || GetNavType() == NAV_JUMP )
|
||||
{
|
||||
DbgNavMsg( this, "Start TASK_STOP_MOVING\n" );
|
||||
@ -3015,7 +3024,16 @@ void CAI_BaseNPC::StartTask( const Task_t *pTask )
|
||||
|
||||
case TASK_ITEM_PICKUP:
|
||||
{
|
||||
SetIdealActivity( ACT_PICKUP_GROUND );
|
||||
#ifdef MAPBASE
|
||||
if (GetTarget() && fabs( GetTarget()->WorldSpaceCenter().z - GetAbsOrigin().z ) >= 12.0f)
|
||||
{
|
||||
SetIdealActivity( ACT_PICKUP_RACK );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
SetIdealActivity( ACT_PICKUP_GROUND );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -3339,8 +3357,40 @@ void CAI_BaseNPC::RunTask( const Task_t *pTask )
|
||||
// a navigation while in the middle of a climb
|
||||
if (GetNavType() == NAV_CLIMB)
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
if (GetActivity() != ACT_CLIMB_DISMOUNT)
|
||||
{
|
||||
// Try to just pause the climb, but dismount if we're in SCHED_FAIL
|
||||
if (IsCurSchedule( SCHED_FAIL, false ))
|
||||
{
|
||||
GetMotor()->MoveClimbStop();
|
||||
}
|
||||
else
|
||||
{
|
||||
GetMotor()->MoveClimbPause();
|
||||
}
|
||||
|
||||
TaskComplete();
|
||||
}
|
||||
else if (IsActivityFinished())
|
||||
{
|
||||
// Dismount complete.
|
||||
GetMotor()->MoveClimbStop();
|
||||
|
||||
// Fix up our position if we have to
|
||||
Vector vecTeleportOrigin;
|
||||
if (GetMotor()->MoveClimbShouldTeleportToSequenceEnd( vecTeleportOrigin ))
|
||||
{
|
||||
SetLocalOrigin( vecTeleportOrigin );
|
||||
}
|
||||
|
||||
TaskComplete();
|
||||
}
|
||||
break;
|
||||
#else
|
||||
// wait until you reach the end
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
DbgNavMsg( this, "TASK_STOP_MOVING Complete\n" );
|
||||
@ -3385,6 +3435,17 @@ void CAI_BaseNPC::RunTask( const Task_t *pTask )
|
||||
// If the yaw is locked, this function will not act correctly
|
||||
Assert( GetMotor()->IsYawLocked() == false );
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( GetHintNode() && GetHintNode()->OverridesNPCYaw( this ) )
|
||||
{
|
||||
// If the yaw is supposed to use that of a hint node, chain to TASK_FACE_HINTNODE
|
||||
GetMotor()->SetIdealYaw( GetHintNode()->Yaw() );
|
||||
GetMotor()->SetIdealYaw( CalcReasonableFacing( true ) ); // CalcReasonableFacing() is based on previously set ideal yaw
|
||||
ChainRunTask( TASK_FACE_HINTNODE, pTask->flTaskData );
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
Vector vecEnemyLKP = GetEnemyLKP();
|
||||
if (!FInAimCone( vecEnemyLKP ))
|
||||
{
|
||||
@ -4271,6 +4332,15 @@ void CAI_BaseNPC::SetTurnActivity ( void )
|
||||
float flYD;
|
||||
flYD = GetMotor()->DeltaIdealYaw();
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Allow AddTurnGesture() to decide this
|
||||
if (GetMotor()->AddTurnGesture( flYD ))
|
||||
{
|
||||
SetIdealActivity( ACT_IDLE );
|
||||
Remember( bits_MEMORY_TURNING );
|
||||
return;
|
||||
}
|
||||
#else
|
||||
// FIXME: unknown case, update yaw should catch these
|
||||
/*
|
||||
if (GetMotor()->AddTurnGesture( flYD ))
|
||||
@ -4280,6 +4350,7 @@ void CAI_BaseNPC::SetTurnActivity ( void )
|
||||
return;
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
|
||||
if( flYD <= -80 && flYD >= -100 && SelectWeightedSequence( ACT_90_RIGHT ) != ACTIVITY_NOT_AVAILABLE )
|
||||
{
|
||||
|
@ -420,6 +420,24 @@ bool CAI_BehaviorBase::CanUnholsterWeapon( void )
|
||||
|
||||
return m_pBackBridge->BackBridge_CanUnholsterWeapon();
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
bool CAI_BehaviorBase::ShouldPickADeathPose( void )
|
||||
{
|
||||
Assert( m_pBackBridge != NULL );
|
||||
|
||||
return m_pBackBridge->BackBridge_ShouldPickADeathPose();
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
bool CAI_BehaviorBase::CanTranslateCrouchActivity( void )
|
||||
{
|
||||
Assert( m_pBackBridge != NULL );
|
||||
|
||||
return m_pBackBridge->BackBridge_CanTranslateCrouchActivity();
|
||||
}
|
||||
#endif
|
||||
|
||||
//-------------------------------------
|
||||
|
@ -132,6 +132,8 @@ public:
|
||||
void BridgeHandleAnimEvent( animevent_t *pEvent );
|
||||
#ifdef MAPBASE
|
||||
bool BridgeCanUnholsterWeapon( void );
|
||||
bool BridgeShouldPickADeathPose( void );
|
||||
bool BridgeCanTranslateCrouchActivity( void );
|
||||
#endif
|
||||
|
||||
virtual void GatherConditions();
|
||||
@ -220,6 +222,8 @@ protected:
|
||||
virtual void HandleAnimEvent( animevent_t *pEvent );
|
||||
#ifdef MAPBASE
|
||||
virtual bool CanUnholsterWeapon( void );
|
||||
virtual bool ShouldPickADeathPose( void );
|
||||
virtual bool CanTranslateCrouchActivity( void );
|
||||
#endif
|
||||
|
||||
virtual bool ShouldAlwaysThink();
|
||||
@ -370,6 +374,9 @@ public:
|
||||
#ifdef MAPBASE
|
||||
// For func_tank behavior
|
||||
virtual bool BackBridge_CanUnholsterWeapon( void ) = 0;
|
||||
|
||||
virtual bool BackBridge_ShouldPickADeathPose( void ) = 0;
|
||||
virtual bool BackBridge_CanTranslateCrouchActivity( void ) = 0;
|
||||
#endif
|
||||
|
||||
//-------------------------------------
|
||||
@ -470,6 +477,8 @@ public:
|
||||
void HandleAnimEvent( animevent_t *pEvent );
|
||||
#ifdef MAPBASE
|
||||
bool CanUnholsterWeapon( void );
|
||||
bool ShouldPickADeathPose( void );
|
||||
bool CanTranslateCrouchActivity( void );
|
||||
#endif
|
||||
|
||||
bool ShouldAlwaysThink();
|
||||
@ -534,6 +543,9 @@ private:
|
||||
#ifdef MAPBASE
|
||||
// For func_tank behavior
|
||||
bool BackBridge_CanUnholsterWeapon( void );
|
||||
|
||||
bool BackBridge_ShouldPickADeathPose( void );
|
||||
bool BackBridge_CanTranslateCrouchActivity( void );
|
||||
#endif
|
||||
|
||||
CAI_BehaviorBase **AccessBehaviors();
|
||||
@ -913,6 +925,20 @@ inline bool CAI_BehaviorBase::BridgeCanUnholsterWeapon( void )
|
||||
{
|
||||
return CanUnholsterWeapon();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline bool CAI_BehaviorBase::BridgeShouldPickADeathPose( void )
|
||||
{
|
||||
return ShouldPickADeathPose();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline bool CAI_BehaviorBase::BridgeCanTranslateCrouchActivity( void )
|
||||
{
|
||||
return CanTranslateCrouchActivity();
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1498,6 +1524,22 @@ inline bool CAI_BehaviorHost<BASE_NPC>::BackBridge_CanUnholsterWeapon( void )
|
||||
{
|
||||
return BaseClass::CanUnholsterWeapon();
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
template <class BASE_NPC>
|
||||
inline bool CAI_BehaviorHost<BASE_NPC>::BackBridge_ShouldPickADeathPose( void )
|
||||
{
|
||||
return BaseClass::ShouldPickADeathPose();
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
template <class BASE_NPC>
|
||||
inline bool CAI_BehaviorHost<BASE_NPC>::BackBridge_CanTranslateCrouchActivity( void )
|
||||
{
|
||||
return BaseClass::CanTranslateCrouchActivity();
|
||||
}
|
||||
#endif
|
||||
|
||||
//-------------------------------------
|
||||
@ -1914,6 +1956,28 @@ inline bool CAI_BehaviorHost<BASE_NPC>::CanUnholsterWeapon( void )
|
||||
|
||||
return BaseClass::CanUnholsterWeapon();
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
template <class BASE_NPC>
|
||||
inline bool CAI_BehaviorHost<BASE_NPC>::ShouldPickADeathPose( void )
|
||||
{
|
||||
if (m_pCurBehavior)
|
||||
return m_pCurBehavior->BridgeShouldPickADeathPose();
|
||||
|
||||
return BaseClass::ShouldPickADeathPose();
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
template <class BASE_NPC>
|
||||
inline bool CAI_BehaviorHost<BASE_NPC>::CanTranslateCrouchActivity( void )
|
||||
{
|
||||
if (m_pCurBehavior)
|
||||
return m_pCurBehavior->BridgeCanTranslateCrouchActivity();
|
||||
|
||||
return BaseClass::CanTranslateCrouchActivity();
|
||||
}
|
||||
#endif
|
||||
|
||||
//-------------------------------------
|
||||
|
@ -408,10 +408,11 @@ bool CAI_FollowBehavior::SetFollowGoal( CAI_FollowGoal *pGoal, bool fFinishCurSc
|
||||
SetFollowTarget( pGoal->GetGoalEntity() );
|
||||
#ifdef MAPBASE
|
||||
Assert( pGoal->m_iFormation < AIF_NUM_FORMATIONS );
|
||||
SetParameters( AI_FollowParams_t( (AI_Formations_t)pGoal->m_iFormation, pGoal->m_bNormalMemoryDiscard ) );
|
||||
#else
|
||||
Assert( pGoal->m_iFormation == AIF_SIMPLE || pGoal->m_iFormation == AIF_WIDE || pGoal->m_iFormation == AIF_MEDIUM || pGoal->m_iFormation == AIF_SIDEKICK || pGoal->m_iFormation == AIF_VORTIGAUNT );
|
||||
#endif
|
||||
SetParameters( AI_FollowParams_t( (AI_Formations_t)pGoal->m_iFormation ) );
|
||||
#endif
|
||||
m_hFollowGoalEnt = pGoal;
|
||||
m_flTimeUpdatedFollowPosition = 0;
|
||||
return true;
|
||||
@ -2138,6 +2139,9 @@ bool CAI_FollowBehavior::ShouldAlwaysThink()
|
||||
|
||||
BEGIN_DATADESC( CAI_FollowGoal )
|
||||
DEFINE_KEYFIELD( m_iFormation, FIELD_INTEGER, "Formation" ),
|
||||
#ifdef MAPBASE
|
||||
DEFINE_KEYFIELD( m_bNormalMemoryDiscard, FIELD_BOOLEAN, "NormalMemoryDiscard" ),
|
||||
#endif
|
||||
|
||||
#ifdef HL2_EPISODIC
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "OutsideTransition", InputOutsideTransition ),
|
||||
|
@ -71,6 +71,10 @@ public:
|
||||
|
||||
int m_iFormation;
|
||||
|
||||
#ifdef MAPBASE
|
||||
bool m_bNormalMemoryDiscard = false;
|
||||
#endif
|
||||
|
||||
DECLARE_DATADESC();
|
||||
};
|
||||
|
||||
|
@ -240,6 +240,23 @@ void CAI_StandoffBehavior::SetActive( bool fActive )
|
||||
{
|
||||
if ( fActive != m_fActive )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
// These sentences are only spoken if the standoff behavior is active, so they have to be arranged separately
|
||||
if ( fActive )
|
||||
{
|
||||
m_fActive = fActive;
|
||||
NotifyChangeBehaviorStatus();
|
||||
|
||||
GetOuter()->SpeakSentence( STANDOFF_SENTENCE_BEGIN_STANDOFF );
|
||||
}
|
||||
else
|
||||
{
|
||||
GetOuter()->SpeakSentence( STANDOFF_SENTENCE_END_STANDOFF );
|
||||
|
||||
m_fActive = fActive;
|
||||
NotifyChangeBehaviorStatus();
|
||||
}
|
||||
#else
|
||||
if ( fActive )
|
||||
{
|
||||
GetOuter()->SpeakSentence( STANDOFF_SENTENCE_BEGIN_STANDOFF );
|
||||
@ -251,6 +268,7 @@ void CAI_StandoffBehavior::SetActive( bool fActive )
|
||||
|
||||
m_fActive = fActive;
|
||||
NotifyChangeBehaviorStatus();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -517,10 +535,11 @@ int CAI_StandoffBehavior::SelectScheduleCheckCover( void )
|
||||
{
|
||||
StandoffMsg( "Regulated to not shoot\n" );
|
||||
#ifdef MAPBASE
|
||||
if ( GetHintType() == HINT_TACTICAL_COVER_LOW || GetHintType() == HINT_TACTICAL_COVER_MED )
|
||||
#else
|
||||
if ( GetHintType() == HINT_TACTICAL_COVER_LOW )
|
||||
if ( GetHintType() == HINT_TACTICAL_COVER_MED || GetCoverActivity() == ACT_COVER_MED )
|
||||
SetPosture( AIP_CROUCHING_MED );
|
||||
else
|
||||
#endif
|
||||
if ( GetHintType() == HINT_TACTICAL_COVER_LOW )
|
||||
SetPosture( AIP_CROUCHING );
|
||||
else
|
||||
SetPosture( AIP_STANDING );
|
||||
@ -539,7 +558,11 @@ int CAI_StandoffBehavior::SelectScheduleEstablishAim( void )
|
||||
{
|
||||
if ( HasCondition( COND_ENEMY_OCCLUDED ) )
|
||||
{
|
||||
#ifdef EXPANDED_HL2_COVER_ACTIVITIES
|
||||
if ( GetPosture() == AIP_CROUCHING || GetPosture() == AIP_CROUCHING_MED )
|
||||
#else
|
||||
if ( GetPosture() == AIP_CROUCHING )
|
||||
#endif
|
||||
{
|
||||
// force a stand up, just in case
|
||||
GetOuter()->SpeakSentence( STANDOFF_SENTENCE_STAND_CHECK_TARGET );
|
||||
@ -650,6 +673,15 @@ Activity CAI_MappedActivityBehavior_Temporary::GetMappedActivity( AI_Posture_t p
|
||||
{
|
||||
if ( posture != AIP_STANDING )
|
||||
{
|
||||
#ifdef EXPANDED_HL2_COVER_ACTIVITIES
|
||||
// See UpdateTranslateActivityMap() for more information on what this is for
|
||||
if ( posture == AIP_CROUCHING_MED )
|
||||
{
|
||||
if (activity != ACT_RANGE_ATTACK1)
|
||||
posture = AIP_CROUCHING;
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned short iActivityTranslation = m_ActivityMap.Find( MAKE_ACTMAP_KEY( posture, activity ) );
|
||||
if ( iActivityTranslation != m_ActivityMap.InvalidIndex() )
|
||||
{
|
||||
@ -667,10 +699,28 @@ Activity CAI_StandoffBehavior::NPC_TranslateActivity( Activity activity )
|
||||
Activity coverActivity = GetCoverActivity();
|
||||
if ( coverActivity != ACT_INVALID )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
if ( GetPosture() == AIP_STANDING )
|
||||
{
|
||||
if ( coverActivity == ACT_COVER_LOW )
|
||||
SetPosture( AIP_CROUCHING );
|
||||
else if ( coverActivity == ACT_COVER_MED )
|
||||
{
|
||||
SetPosture( AIP_CROUCHING_MED );
|
||||
coverActivity = ACT_COVER_LOW;
|
||||
}
|
||||
}
|
||||
else if (coverActivity == ACT_COVER_MED)
|
||||
coverActivity = ACT_COVER_LOW;
|
||||
|
||||
if ( activity == ACT_IDLE )
|
||||
activity = coverActivity;
|
||||
#else
|
||||
if (activity == ACT_IDLE)
|
||||
activity = coverActivity;
|
||||
if ( GetPosture() == AIP_STANDING && coverActivity == ACT_COVER_LOW )
|
||||
SetPosture( AIP_CROUCHING );
|
||||
#endif
|
||||
}
|
||||
|
||||
Activity result = GetMappedActivity( GetPosture(), activity );
|
||||
@ -1071,12 +1121,25 @@ void CAI_StandoffBehavior::UnlockHintNode()
|
||||
|
||||
Activity CAI_StandoffBehavior::GetCoverActivity()
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
// This does two things:
|
||||
// A. Allows medium cover nodes to be used, kind of.
|
||||
// B. GetCoverActivity() already checks everything we checked here.
|
||||
Activity coveract = GetOuter()->GetCoverActivity( GetHintNode() );
|
||||
return coveract == ACT_IDLE ? ACT_INVALID : coveract;
|
||||
#ifdef EXPANDED_HL2_COVER_ACTIVITIES
|
||||
// GetCoverActivity() already checks everything we checked here.
|
||||
Activity coverActivity = GetOuter()->GetCoverActivity( GetHintNode() );
|
||||
|
||||
if (coverActivity == ACT_COVER_LOW)
|
||||
{
|
||||
// Check if this node will block our line of sight if aiming low.
|
||||
Vector vHintPos, vHintForward, vHintRight;
|
||||
GetHintNode()->GetPosition( GetHullType(), &vHintPos );
|
||||
vHintForward = GetHintNode()->GetDirection();
|
||||
|
||||
GetHintNode()->GetVectors( NULL, &vHintRight, NULL );
|
||||
if (GetOuter()->CouldShootIfCrouchingAt( vHintPos, vHintForward, vHintRight ))
|
||||
{
|
||||
coverActivity = ACT_COVER_MED;
|
||||
}
|
||||
}
|
||||
|
||||
return coverActivity == ACT_IDLE ? ACT_INVALID : coverActivity;
|
||||
#else
|
||||
CAI_Hint *pHintNode = GetHintNode();
|
||||
if ( pHintNode && pHintNode->HintType() == HINT_TACTICAL_COVER_LOW )
|
||||
@ -1094,6 +1157,14 @@ struct AI_ActivityMapping_t
|
||||
Activity activity;
|
||||
const char * pszWeapon;
|
||||
Activity translation;
|
||||
#ifdef MAPBASE
|
||||
Activity backup;
|
||||
|
||||
AI_ActivityMapping_t( AI_Posture_t _p, Activity _a, const char *_w, Activity _t, Activity _b = ACT_INVALID )
|
||||
{
|
||||
posture = _p; activity = _a; pszWeapon = _w; translation = _t; backup = _b;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
void CAI_MappedActivityBehavior_Temporary::UpdateTranslateActivityMap()
|
||||
@ -1107,15 +1178,60 @@ void CAI_MappedActivityBehavior_Temporary::UpdateTranslateActivityMap()
|
||||
{ AIP_CROUCHING, ACT_WALK_AIM, NULL, ACT_WALK_CROUCH_AIM, },
|
||||
{ AIP_CROUCHING, ACT_RUN_AIM, NULL, ACT_RUN_CROUCH_AIM, },
|
||||
{ AIP_CROUCHING, ACT_RELOAD, NULL, ACT_RELOAD_LOW, },
|
||||
#ifdef MAPBASE
|
||||
{ AIP_CROUCHING, ACT_RANGE_ATTACK1, NULL, ACT_RANGE_ATTACK1_LOW, },
|
||||
{ AIP_CROUCHING, ACT_COVER_MED, NULL, ACT_COVER_LOW, },
|
||||
#else
|
||||
{ AIP_CROUCHING, ACT_RANGE_ATTACK_SMG1, NULL, ACT_RANGE_ATTACK_SMG1_LOW, },
|
||||
{ AIP_CROUCHING, ACT_RANGE_ATTACK_AR2, NULL, ACT_RANGE_ATTACK_AR2_LOW, },
|
||||
#endif
|
||||
|
||||
#ifdef EXPANDED_HL2_COVER_ACTIVITIES
|
||||
//
|
||||
// ============ Really long explanation that should be in a wiki/documentation article somewhere ~ Blixibon, 10/27/2021 ============
|
||||
//
|
||||
// Standoff behavior assumes low attack animations allow NPCs to see over barricades, with ACT_COVER_LOW being their "safely in cover" animation.
|
||||
// This is why AIP_CROUCHING translates ACT_RANGE_ATTACK1 to its low animation, but translates ACT_IDLE_ANGRY to ACT_COVER_LOW instead of ACT_RANGE_AIM_LOW,
|
||||
// as this would ideally allow NPCs to pop in and out of cover to shoot.
|
||||
// This is also why AIP_PEEKING translates ACT_COVER_LOW to ACT_RANGE_AIM_LOW, as it's supposed to force the NPC to peek over their cover.
|
||||
//
|
||||
// However, this assumption mainly just applies to metrocops. Citizens' low attacking animations crouch low to the ground (which isn't effective for
|
||||
// shooting over most barricades) and, while they do have a distinct ACT_COVER_LOW animation with transitions, they are close enough together that popping
|
||||
// in and out of cover is redundant in most cases. Meanwhile, Combine soldiers have identical ACT_COVER_LOW and ACT_RANGE_AIM_LOW animations, which means
|
||||
// they do not pop in and out of cover and AIP_PEEKING does nothing. This may be the reason why Combine soldiers occasionally get stuck in cover after a fight.
|
||||
//
|
||||
// -------------------------------------------------------------
|
||||
//
|
||||
// As part of Mapbase v7.0's NPC activity overhaul, a new "medium cover" activity set has been added. Metrocops' previous "low cover" animation set (which, as
|
||||
// mentioned before, is different from that of other NPCs) has been retroactively changed to use "medium cover". This was done for a few reasons unrelated to
|
||||
// standoff behavior, but the important point is that these activities indicate a new cover height. This means we can use them to give standoff behavior more leeway
|
||||
// for judging which animations to use in various levels of cover.
|
||||
//
|
||||
// Standoff behavior can use "medium cover" animations in cover which is too high for the "low" animations, and when the medium cover animations are not available,
|
||||
// it simply falls back to the "standing" animations, thus resolving the issue with other NPCs not peeking in and out of cover without requiring new medium cover
|
||||
// animations.
|
||||
//
|
||||
// In Mapbase, this is done by changing AIP_PEEKING to use the medium cover animations and adding a new alternate crouching posture posture called "AIP_CROUCHING_MED",
|
||||
// which only uses the medium cover attack activity and otherwise automatically falls back to AIP_CROUCHING. AIP_CROUCHING_MED is automatically set if the NPC cannot
|
||||
// get LOS from a regular crouching position.
|
||||
//
|
||||
{ AIP_CROUCHING_MED, ACT_RANGE_ATTACK1, NULL, ACT_RANGE_ATTACK1_MED, },
|
||||
|
||||
//----
|
||||
{ AIP_PEEKING, ACT_IDLE, NULL, ACT_RANGE_AIM_MED, },
|
||||
{ AIP_PEEKING, ACT_IDLE_ANGRY, NULL, ACT_RANGE_AIM_MED, },
|
||||
{ AIP_PEEKING, ACT_COVER_LOW, NULL, ACT_RANGE_AIM_MED, ACT_IDLE_ANGRY },
|
||||
{ AIP_PEEKING, ACT_COVER_MED, NULL, ACT_RANGE_AIM_MED, ACT_IDLE_ANGRY },
|
||||
{ AIP_PEEKING, ACT_RANGE_ATTACK1, NULL, ACT_RANGE_ATTACK1_MED, },
|
||||
{ AIP_PEEKING, ACT_RELOAD, NULL, ACT_RELOAD_LOW, },
|
||||
#else
|
||||
//----
|
||||
{ AIP_PEEKING, ACT_IDLE, NULL, ACT_RANGE_AIM_LOW, },
|
||||
{ AIP_PEEKING, ACT_IDLE_ANGRY, NULL, ACT_RANGE_AIM_LOW, },
|
||||
{ AIP_PEEKING, ACT_COVER_LOW, NULL, ACT_RANGE_AIM_LOW, },
|
||||
{ AIP_PEEKING, ACT_RANGE_ATTACK1, NULL, ACT_RANGE_ATTACK1_LOW, },
|
||||
{ AIP_PEEKING, ACT_RELOAD, NULL, ACT_RELOAD_LOW, },
|
||||
#endif
|
||||
};
|
||||
|
||||
m_ActivityMap.RemoveAll();
|
||||
@ -1127,7 +1243,7 @@ void CAI_MappedActivityBehavior_Temporary::UpdateTranslateActivityMap()
|
||||
if ( !mappings[i].pszWeapon || stricmp( mappings[i].pszWeapon, pszWeaponClass ) == 0 )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
// Check backup activity
|
||||
// Check NPC backup activity
|
||||
if ( HaveSequenceForActivity( mappings[i].translation ) || HaveSequenceForActivity( GetOuter()->Weapon_TranslateActivity( mappings[i].translation ) ) || HaveSequenceForActivity( GetOuter()->Weapon_BackupActivity( mappings[i].translation ) ) )
|
||||
#else
|
||||
if ( HaveSequenceForActivity( mappings[i].translation ) || HaveSequenceForActivity( GetOuter()->Weapon_TranslateActivity( mappings[i].translation ) ) )
|
||||
@ -1136,6 +1252,14 @@ void CAI_MappedActivityBehavior_Temporary::UpdateTranslateActivityMap()
|
||||
Assert( m_ActivityMap.Find( MAKE_ACTMAP_KEY( mappings[i].posture, mappings[i].activity ) ) == m_ActivityMap.InvalidIndex() );
|
||||
m_ActivityMap.Insert( MAKE_ACTMAP_KEY( mappings[i].posture, mappings[i].activity ), mappings[i].translation );
|
||||
}
|
||||
#ifdef MAPBASE
|
||||
// Check activity map backup activity
|
||||
else if ( mappings[i].backup != ACT_INVALID && HaveSequenceForActivity( mappings[i].backup ) )
|
||||
{
|
||||
Assert( m_ActivityMap.Find( MAKE_ACTMAP_KEY( mappings[i].posture, mappings[i].activity ) ) == m_ActivityMap.InvalidIndex() );
|
||||
m_ActivityMap.Insert( MAKE_ACTMAP_KEY( mappings[i].posture, mappings[i].activity ), mappings[i].backup );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -51,6 +51,9 @@ enum AI_Posture_t
|
||||
AIP_INDIFFERENT,
|
||||
AIP_STANDING,
|
||||
AIP_CROUCHING,
|
||||
#ifdef EXPANDED_HL2_COVER_ACTIVITIES
|
||||
AIP_CROUCHING_MED, // See UpdateTranslateActivityMap() for more information on what this is for
|
||||
#endif
|
||||
AIP_PEEKING,
|
||||
};
|
||||
|
||||
@ -149,6 +152,14 @@ protected:
|
||||
|
||||
// Standoff overrides base AI crouch handling
|
||||
bool IsCrouching( void ) { return false; }
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Standoff overrides base cover activity translation
|
||||
bool CanTranslateCrouchActivity( void ) { return false; }
|
||||
|
||||
// Don't do death poses while crouching
|
||||
bool ShouldPickADeathPose( void ) { return (GetPosture() != AIP_CROUCHING && GetPosture() != AIP_PEEKING) && BaseClass::ShouldPickADeathPose(); }
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
|
@ -1640,10 +1640,17 @@ void CAI_BlendedMotor::MaintainTurnActivity( void )
|
||||
|
||||
ConVar scene_flatturn( "scene_flatturn", "1" );
|
||||
|
||||
#ifdef MAPBASE
|
||||
ConVar ai_turning_enabled( "ai_turning_enabled", "1", FCVAR_NONE, "Enables NPC turning, which was previously disabled by Valve at some point after 2004 due to a now-unknown major issue." );
|
||||
#endif
|
||||
|
||||
bool CAI_BlendedMotor::AddTurnGesture( float flYD )
|
||||
{
|
||||
|
||||
// some funky bug with human turn gestures, disable for now
|
||||
#ifdef MAPBASE
|
||||
if (!ai_turning_enabled.GetBool())
|
||||
#endif
|
||||
return false;
|
||||
|
||||
// try using a turn gesture
|
||||
|
@ -35,6 +35,10 @@ CHintCriteria::CHintCriteria( void )
|
||||
m_strGroup = NULL_STRING;
|
||||
m_iFlags = 0;
|
||||
m_HintTypes.Purge();
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
m_pfnFilter = NULL;
|
||||
m_pFilterContext = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1117,10 +1121,10 @@ void CAI_Hint::NPCHandleStartNav( CAI_BaseNPC *pNPC, bool bDefaultFacing )
|
||||
|
||||
HintIgnoreFacing_t facing = GetIgnoreFacing();
|
||||
if (facing == HIF_DEFAULT)
|
||||
facing = bDefaultFacing ? HIF_YES : HIF_NO;
|
||||
facing = bDefaultFacing ? HIF_NO : HIF_YES;
|
||||
|
||||
if (facing == HIF_YES)
|
||||
pNPC->GetNavigator()->SetArrivalDirection(GetDirection());
|
||||
if (facing == HIF_NO)
|
||||
pNPC->GetNavigator()->SetArrivalDirection( GetDirection() );
|
||||
|
||||
if (HintActivityName() != NULL_STRING)
|
||||
{
|
||||
@ -1139,6 +1143,51 @@ void CAI_Hint::NPCHandleStartNav( CAI_BaseNPC *pNPC, bool bDefaultFacing )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Returns true if this hint should override a NPC's yaw even during regular AI.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CAI_Hint::OverridesNPCYaw( CAI_BaseNPC *pNPC )
|
||||
{
|
||||
switch (HintType())
|
||||
{
|
||||
case HINT_TACTICAL_COVER_CUSTOM:
|
||||
case HINT_TACTICAL_COVER_MED:
|
||||
case HINT_TACTICAL_COVER_LOW:
|
||||
{
|
||||
if (pNPC->HasMemory( bits_MEMORY_INCOVER ))
|
||||
{
|
||||
// By default, don't override yaw on cover nodes unless they use custom activities.
|
||||
HintIgnoreFacing_t facing = GetIgnoreFacing();
|
||||
if (facing == HIF_DEFAULT)
|
||||
return ( HintActivityName() != NULL_STRING );
|
||||
|
||||
return facing == HIF_NO;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case HINT_PLAYER_ALLY_MOVE_AWAY_DEST:
|
||||
{
|
||||
Vector vHintPos;
|
||||
GetPosition( pNPC, &vHintPos );
|
||||
if (VectorsAreEqual( vHintPos, pNPC->GetAbsOrigin(), 0.1f ))
|
||||
{
|
||||
// By default, don't override yaw on move away destinations unless they use custom activities.
|
||||
HintIgnoreFacing_t facing = GetIgnoreFacing();
|
||||
if (facing == HIF_DEFAULT)
|
||||
return ( HintActivityName() != NULL_STRING );
|
||||
|
||||
return facing == HIF_NO;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1258,6 +1307,30 @@ bool CAI_Hint::HintMatchesCriteria( CAI_BaseNPC *pNPC, const CHintCriteria &hint
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Test against generic filter
|
||||
// (From Alien Swarm SDK)
|
||||
if ( !hintCriteria.PassesFilter( this ) )
|
||||
{
|
||||
REPORTFAILURE( "Failed filter test" );
|
||||
return false;
|
||||
}
|
||||
|
||||
// (From Alien Swarm SDK)
|
||||
int nRadius = GetRadius();
|
||||
if ( nRadius != 0 )
|
||||
{
|
||||
// Calculate our distance
|
||||
float distance = (GetAbsOrigin() - position).LengthSqr();
|
||||
|
||||
if ( distance > nRadius * nRadius )
|
||||
{
|
||||
REPORTFAILURE( "NPC is not within the node's radius." );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( hintCriteria.HasFlag(bits_HINT_NPC_IN_NODE_FOV) )
|
||||
{
|
||||
if ( pNPC == NULL )
|
||||
@ -1377,10 +1450,18 @@ bool CAI_Hint::HintMatchesCriteria( CAI_BaseNPC *pNPC, const CHintCriteria &hint
|
||||
{
|
||||
trace_t tr;
|
||||
// Can my bounding box fit there?
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
Vector vStep( 0, 0, pNPC->StepHeight() );
|
||||
AI_TraceHull ( GetAbsOrigin() + vStep, GetAbsOrigin(), pNPC->WorldAlignMins(), pNPC->WorldAlignMaxs() - vStep,
|
||||
MASK_SOLID, pNPC, COLLISION_GROUP_NONE, &tr );
|
||||
|
||||
if ( tr.fraction < 0.95 )
|
||||
#else
|
||||
AI_TraceHull ( GetAbsOrigin(), GetAbsOrigin(), pNPC->WorldAlignMins(), pNPC->WorldAlignMaxs(),
|
||||
MASK_SOLID, pNPC, COLLISION_GROUP_NONE, &tr );
|
||||
|
||||
if ( tr.fraction != 1.0 )
|
||||
#endif
|
||||
{
|
||||
REPORTFAILURE( "Node isn't clear." );
|
||||
return false;
|
||||
@ -1396,6 +1477,15 @@ bool CAI_Hint::HintMatchesCriteria( CAI_BaseNPC *pNPC, const CHintCriteria &hint
|
||||
// Calculate our distance
|
||||
float distance = (GetAbsOrigin() - position).Length();
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Divide by hint weight
|
||||
float flWeight = GetHintWeight();
|
||||
if ( flWeight != 1.0f )
|
||||
{
|
||||
distance *= GetHintWeightInverse();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Must be closer than the current best
|
||||
if ( distance > *flNearestDistance )
|
||||
{
|
||||
@ -1576,6 +1666,14 @@ void CAI_Hint::OnRestore()
|
||||
m_NodeData.nNodeID = g_pAINetworkManager->GetEditOps()->GetNodeIdFromWCId( m_NodeData.nWCNodeID );
|
||||
FixupTargetNode();
|
||||
|
||||
#ifdef MAPBASE
|
||||
if (m_NodeData.flWeight != 0.0f && m_NodeData.flWeight != 1.0f)
|
||||
{
|
||||
// Re-invert the weight
|
||||
m_NodeData.flWeightInverse = 1.0f / m_NodeData.flWeight;
|
||||
}
|
||||
#endif
|
||||
|
||||
CAI_Node *pNode = GetNode();
|
||||
|
||||
if ( !pNode )
|
||||
@ -1751,6 +1849,11 @@ void CC_ai_drop_hint( const CCommand &args )
|
||||
nodeData.fIgnoreFacing = HIF_DEFAULT;
|
||||
nodeData.minState = NPC_STATE_IDLE;
|
||||
nodeData.maxState = NPC_STATE_COMBAT;
|
||||
#ifdef MAPBASE
|
||||
nodeData.nRadius = 0; // From Alien Swarm SDK
|
||||
nodeData.flWeight = 1.0f;
|
||||
nodeData.flWeightInverse = 1.0f;
|
||||
#endif
|
||||
CAI_Hint *pHint = CAI_HintManager::CreateHint( &nodeData, NULL );
|
||||
if ( pHint )
|
||||
{
|
||||
|
@ -112,6 +112,13 @@ enum Hint_e
|
||||
|
||||
// CS port hints
|
||||
HINT_CSTRIKE_HOSTAGE_ESCAPE = 1100,
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Mapbase hints
|
||||
// (these start at a high number to avoid potential conflicts with mod hints)
|
||||
|
||||
HINT_TACTICAL_COVER_CUSTOM = 10000, // Cover node with a custom hint activity (NPCs can take cover and reload here while playing said activity)
|
||||
#endif
|
||||
};
|
||||
const char *GetHintTypeDescription( Hint_e iHintType );
|
||||
const char *GetHintTypeDescription( CAI_Hint *pHint );
|
||||
@ -120,6 +127,10 @@ const char *GetHintTypeDescription( CAI_Hint *pHint );
|
||||
// CHintCriteria
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
typedef bool (*HintSearchFilterFunc_t)( void *pContext, CAI_Hint *pCandidate );
|
||||
#endif
|
||||
|
||||
class CHintCriteria
|
||||
{
|
||||
public:
|
||||
@ -134,6 +145,11 @@ public:
|
||||
void SetGroup( string_t group );
|
||||
string_t GetGroup( void ) const { return m_strGroup; }
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
void SetFilterFunc( HintSearchFilterFunc_t pfnFilter, void *pContext = NULL ) { m_pfnFilter = pfnFilter; m_pFilterContext = pContext; }
|
||||
bool PassesFilter( CAI_Hint *pCandidate ) const { return (m_pfnFilter) ? (*m_pfnFilter)(m_pFilterContext, pCandidate) : true; }
|
||||
#endif
|
||||
|
||||
int GetFirstHintType( void ) const { return m_iFirstHintType; }
|
||||
int GetLastHintType( void ) const { return m_iLastHintType; }
|
||||
bool MatchesHintType( int hintType ) const;
|
||||
@ -176,6 +192,11 @@ private:
|
||||
|
||||
zoneList_t m_zoneInclude;
|
||||
zoneList_t m_zoneExclude;
|
||||
|
||||
#ifdef MAPBASE
|
||||
HintSearchFilterFunc_t m_pfnFilter;
|
||||
void * m_pFilterContext;
|
||||
#endif
|
||||
};
|
||||
|
||||
class CAI_Node;
|
||||
@ -310,11 +331,21 @@ public:
|
||||
int GetNodeId() { return m_NodeData.nNodeID; }
|
||||
int GetWCId() { return m_NodeData.nWCNodeID; }
|
||||
|
||||
#ifdef MAPBASE
|
||||
int GetRadius() const { return m_NodeData.nRadius; } // From Alien Swarm SDK
|
||||
|
||||
float GetHintWeight() const { return m_NodeData.flWeight; }
|
||||
float GetHintWeightInverse() const { return m_NodeData.flWeightInverse; } // Used to multiply distances
|
||||
#endif
|
||||
|
||||
bool HintMatchesCriteria( CAI_BaseNPC *pNPC, const CHintCriteria &hintCriteria, const Vector &position, float *flNearestDistance, bool bIgnoreLock = false, bool bIgnoreHintType = false );
|
||||
bool IsInNodeFOV( CBaseEntity *pOther );
|
||||
|
||||
#ifdef MAPBASE
|
||||
void NPCHandleStartNav( CAI_BaseNPC *pNPC, bool bDefaultFacing );
|
||||
|
||||
// Returns true if this hint should override a NPC's yaw even during regular AI.
|
||||
bool OverridesNPCYaw( CAI_BaseNPC *pNPC );
|
||||
#endif
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
|
@ -173,6 +173,10 @@ BEGIN_SIMPLE_DATADESC( HintNodeData )
|
||||
DEFINE_KEYFIELD( fIgnoreFacing, FIELD_INTEGER, "IgnoreFacing" ),
|
||||
DEFINE_KEYFIELD( minState, FIELD_INTEGER, "MinimumState" ),
|
||||
DEFINE_KEYFIELD( maxState, FIELD_INTEGER, "MaximumState" ),
|
||||
#ifdef MAPBASE
|
||||
DEFINE_KEYFIELD( nRadius, FIELD_INTEGER, "radius" ), // From Alien Swarm SDK
|
||||
DEFINE_KEYFIELD( flWeight, FIELD_FLOAT, "hintweight" ),
|
||||
#endif
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
@ -205,6 +209,17 @@ int CNodeEnt::Spawn( const char *pMapData )
|
||||
m_NodeData.minState = NPC_STATE_IDLE;
|
||||
if ( m_NodeData.maxState == NPC_STATE_NONE )
|
||||
m_NodeData.maxState = NPC_STATE_COMBAT;
|
||||
#ifdef MAPBASE
|
||||
if (m_NodeData.flWeight == 0.0f)
|
||||
{
|
||||
m_NodeData.flWeight = 1.0f;
|
||||
}
|
||||
else if (m_NodeData.flWeight != 1.0f)
|
||||
{
|
||||
// Invert the weight so that it could be used as a direct multiplier for distances, etc.
|
||||
m_NodeData.flWeightInverse = 1.0f / m_NodeData.flWeight;
|
||||
}
|
||||
#endif
|
||||
// ---------------------------------------------------------------------------------
|
||||
// If just a hint node (not used for navigation) just create a hint and bail
|
||||
// ---------------------------------------------------------------------------------
|
||||
|
@ -42,6 +42,11 @@ struct HintNodeData
|
||||
HintIgnoreFacing_t fIgnoreFacing;
|
||||
NPC_STATE minState;
|
||||
NPC_STATE maxState;
|
||||
#ifdef MAPBASE
|
||||
int nRadius; // From Alien Swarm SDK
|
||||
float flWeight;
|
||||
float flWeightInverse; // Not saved
|
||||
#endif
|
||||
|
||||
int nWCNodeID; // Node ID assigned by worldcraft (not same as engine!)
|
||||
|
||||
|
@ -146,29 +146,6 @@ BEGIN_SIMPLE_DATADESC( AI_EnemyInfo_t )
|
||||
// NOT SAVED nextEMemory
|
||||
END_DATADESC()
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
#define DEFINE_ENEMY_INFO_SCRIPTFUNCS(name, desc) \
|
||||
DEFINE_SCRIPTFUNC_NAMED( Get##name, #name, "Get " desc ) \
|
||||
DEFINE_SCRIPTFUNC( Set##name, "Set " desc )
|
||||
|
||||
BEGIN_SCRIPTDESC_ROOT( AI_EnemyInfo_t, "Accessor for information about an enemy." )
|
||||
DEFINE_SCRIPTFUNC( Enemy, "Get the enemy." )
|
||||
DEFINE_SCRIPTFUNC( SetEnemy, "Set the enemy." )
|
||||
DEFINE_ENEMY_INFO_SCRIPTFUNCS( LastKnownLocation, "the enemy's last known location." )
|
||||
DEFINE_ENEMY_INFO_SCRIPTFUNCS( LastSeenLocation, "the enemy's last seen location." )
|
||||
DEFINE_ENEMY_INFO_SCRIPTFUNCS( TimeLastSeen, "the last time the enemy was seen." )
|
||||
DEFINE_ENEMY_INFO_SCRIPTFUNCS( TimeFirstSeen, "the first time the enemy was seen." )
|
||||
DEFINE_ENEMY_INFO_SCRIPTFUNCS( TimeLastReacquired, "the last time the enemy was reaquired." )
|
||||
DEFINE_ENEMY_INFO_SCRIPTFUNCS( TimeValidEnemy, "the time at which the enemy can be selected (reaction delay)." )
|
||||
DEFINE_ENEMY_INFO_SCRIPTFUNCS( TimeLastReceivedDamageFrom, "the last time damage was received from this enemy." )
|
||||
DEFINE_ENEMY_INFO_SCRIPTFUNCS( TimeAtFirstHand, "the time at which the enemy was seen firsthand." )
|
||||
DEFINE_ENEMY_INFO_SCRIPTFUNCS( DangerMemory, "the memory of danger position w/o enemy pointer." )
|
||||
DEFINE_ENEMY_INFO_SCRIPTFUNCS( EludedMe, "whether the enemy is not at the last known location." )
|
||||
DEFINE_ENEMY_INFO_SCRIPTFUNCS( Unforgettable, "whether the enemy is unforgettable." )
|
||||
DEFINE_ENEMY_INFO_SCRIPTFUNCS( MobbedMe, "whether the enemy was part of a mob at some point." )
|
||||
END_SCRIPTDESC();
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
CAI_Enemies::CAI_Enemies(void)
|
||||
|
@ -45,29 +45,6 @@ struct AI_EnemyInfo_t
|
||||
bool bUnforgettable;
|
||||
bool bMobbedMe; // True if enemy was part of a mob at some point
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
// Script functions.
|
||||
#define ENEMY_INFO_SCRIPT_FUNCS(type, name, var) \
|
||||
type Get##name() { return var; } \
|
||||
void Set##name( type v ) { var = v; }
|
||||
|
||||
HSCRIPT Enemy() { return ToHScript(hEnemy); }
|
||||
void SetEnemy( HSCRIPT ent ) { hEnemy = ToEnt(ent); }
|
||||
|
||||
ENEMY_INFO_SCRIPT_FUNCS( Vector, LastKnownLocation, vLastKnownLocation );
|
||||
ENEMY_INFO_SCRIPT_FUNCS( Vector, LastSeenLocation, vLastSeenLocation );
|
||||
ENEMY_INFO_SCRIPT_FUNCS( float, TimeLastSeen, timeLastSeen );
|
||||
ENEMY_INFO_SCRIPT_FUNCS( float, TimeFirstSeen, timeFirstSeen );
|
||||
ENEMY_INFO_SCRIPT_FUNCS( float, TimeLastReacquired, timeLastReacquired );
|
||||
ENEMY_INFO_SCRIPT_FUNCS( float, TimeValidEnemy, timeValidEnemy );
|
||||
ENEMY_INFO_SCRIPT_FUNCS( float, TimeLastReceivedDamageFrom, timeLastReceivedDamageFrom );
|
||||
ENEMY_INFO_SCRIPT_FUNCS( float, TimeAtFirstHand, timeAtFirstHand );
|
||||
ENEMY_INFO_SCRIPT_FUNCS( bool, DangerMemory, bDangerMemory );
|
||||
ENEMY_INFO_SCRIPT_FUNCS( bool, EludedMe, bEludedMe );
|
||||
ENEMY_INFO_SCRIPT_FUNCS( bool, Unforgettable, bUnforgettable );
|
||||
ENEMY_INFO_SCRIPT_FUNCS( bool, MobbedMe, bMobbedMe );
|
||||
#endif
|
||||
|
||||
DECLARE_SIMPLE_DATADESC();
|
||||
};
|
||||
|
||||
|
@ -14,6 +14,9 @@
|
||||
#include "ai_basenpc.h"
|
||||
#include "ai_localnavigator.h"
|
||||
#include "ai_moveprobe.h"
|
||||
#ifdef MAPBASE
|
||||
#include "ai_hint.h"
|
||||
#endif
|
||||
#include "saverestore_utlvector.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
@ -235,18 +238,47 @@ void CAI_Motor::MoveClimbStart( const Vector &climbDest, const Vector &climbDir
|
||||
// > code are not reciprocal for all state, and furthermore, stomp
|
||||
// > other state?
|
||||
|
||||
bool bGoingUp = (climbDir.z > 0.01);
|
||||
#ifdef EXPANDED_NAVIGATION_ACTIVITIES
|
||||
if ( bGoingUp && GetOuter()->HaveSequenceForActivity( ACT_CLIMB_MOUNT_BOTTOM ) )
|
||||
{
|
||||
SetActivity( ACT_CLIMB_MOUNT_BOTTOM );
|
||||
|
||||
// Steal m_vecDismount for this
|
||||
GetOuter()->GetSequenceLinearMotion( GetSequence(), &m_vecDismount );
|
||||
GetOuter()->SetCycle( GetOuter()->GetMovementFrame( m_vecDismount.z - climbDist ) );
|
||||
}
|
||||
else if ( !bGoingUp && GetOuter()->HaveSequenceForActivity( ACT_CLIMB_MOUNT_TOP ) )
|
||||
{
|
||||
SetActivity( ACT_CLIMB_MOUNT_TOP );
|
||||
|
||||
// Steal m_vecDismount for this
|
||||
GetOuter()->GetSequenceLinearMotion( GetSequence(), &m_vecDismount );
|
||||
GetOuter()->SetCycle( GetOuter()->GetMovementFrame( m_vecDismount.z - climbDist ) );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if ( fabsf( climbDir.z ) < .1 )
|
||||
{
|
||||
SetActivity( GetNavigator()->GetMovementActivity() );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetActivity( (climbDir.z > -0.01 ) ? ACT_CLIMB_UP : ACT_CLIMB_DOWN );
|
||||
SetActivity( bGoingUp ? ACT_CLIMB_UP : ACT_CLIMB_DOWN );
|
||||
}
|
||||
|
||||
m_nDismountSequence = SelectWeightedSequence( ACT_CLIMB_DISMOUNT );
|
||||
if (m_nDismountSequence != ACT_INVALID)
|
||||
{
|
||||
#ifdef EXPANDED_NAVIGATION_ACTIVITIES
|
||||
if ( !bGoingUp )
|
||||
{
|
||||
int nBottomDismount = SelectWeightedSequence( ACT_CLIMB_DISMOUNT_BOTTOM );
|
||||
if (nBottomDismount != ACTIVITY_NOT_AVAILABLE)
|
||||
m_nDismountSequence = nBottomDismount;
|
||||
}
|
||||
#endif
|
||||
|
||||
GetOuter()->GetSequenceLinearMotion( m_nDismountSequence, &m_vecDismount );
|
||||
}
|
||||
else
|
||||
@ -262,6 +294,76 @@ void CAI_Motor::MoveClimbStart( const Vector &climbDest, const Vector &climbDir
|
||||
|
||||
AIMoveResult_t CAI_Motor::MoveClimbExecute( const Vector &climbDest, const Vector &climbDir, float climbDist, float yaw, int climbNodesLeft )
|
||||
{
|
||||
#ifdef EXPANDED_NAVIGATION_ACTIVITIES
|
||||
if ( (GetActivity() == ACT_CLIMB_MOUNT_TOP || GetActivity() == ACT_CLIMB_MOUNT_BOTTOM) )
|
||||
{
|
||||
if (!GetOuter()->IsActivityFinished())
|
||||
{
|
||||
// Wait for the mounting to finish
|
||||
SetGroundEntity( NULL );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fix up our position if we have to
|
||||
Vector vecTeleportOrigin;
|
||||
if (MoveClimbShouldTeleportToSequenceEnd( vecTeleportOrigin ))
|
||||
{
|
||||
SetLocalOrigin( vecTeleportOrigin );
|
||||
}
|
||||
|
||||
// Reset activity and start from the beginning
|
||||
GetOuter()->ResetActivity();
|
||||
return MoveClimbExecute( climbDest, climbDir, climbDist, yaw, climbNodesLeft );
|
||||
}
|
||||
}
|
||||
else if ( fabsf( climbDir.z ) > .1 && (GetActivity() != ACT_CLIMB_DISMOUNT && GetActivity() != ACT_CLIMB_DISMOUNT_BOTTOM) )
|
||||
{
|
||||
bool bGoingUp = (climbDir.z > -0.01);
|
||||
if ( GetOuter()->HaveSequenceForActivity( ACT_CLIMB_ALL ) )
|
||||
{
|
||||
SetActivity( ACT_CLIMB_ALL );
|
||||
|
||||
// TODO: Use UTIL_VecToPitch() instead if move_yaw becomes a true climb yaw and not just an up-down scalar
|
||||
SetPoseParameter( GetOuter()->LookupPoseMoveYaw(), climbDir.z < 0 ? 180.0 : -180.0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
Activity desiredActivity = bGoingUp ? ACT_CLIMB_UP : ACT_CLIMB_DOWN;
|
||||
if ( GetActivity() != desiredActivity )
|
||||
{
|
||||
SetActivity( desiredActivity );
|
||||
}
|
||||
}
|
||||
|
||||
if (m_nDismountSequence != ACT_INVALID)
|
||||
{
|
||||
if (climbNodesLeft <= 2 && climbDist < fabs( m_vecDismount.z ))
|
||||
{
|
||||
if (bGoingUp)
|
||||
{
|
||||
// fixme: No other way to force m_nIdealSequence?
|
||||
GetOuter()->SetActivity( ACT_CLIMB_DISMOUNT );
|
||||
GetOuter()->SetCycle( GetOuter()->GetMovementFrame( m_vecDismount.z - climbDist ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GetSequence() != m_nDismountSequence && GetOuter()->GetSequenceActivity( m_nDismountSequence ) == ACT_CLIMB_DISMOUNT_BOTTOM)
|
||||
{
|
||||
SetActivity( ACT_CLIMB_DISMOUNT_BOTTOM );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( climbDir.Length() == 0 && GetOuter()->GetInstantaneousVelocity() <= 0.01 )
|
||||
{
|
||||
// The NPC is somehow stuck climbing with no direction or movement.
|
||||
// This can be caused by NPCs getting stuck in each other and/or being moved away from the ladder.
|
||||
// In these cases, the NPC has to be made unstuck, or else they may remain in an immobile climbing state forever.
|
||||
Warning( "%s had to abort climbing due to no direction or movement\n", GetOuter()->GetDebugName() );
|
||||
return AIMR_ILLEGAL;
|
||||
}
|
||||
#else
|
||||
if ( fabsf( climbDir.z ) > .1 )
|
||||
{
|
||||
if ( GetActivity() != ACT_CLIMB_DISMOUNT )
|
||||
@ -292,13 +394,34 @@ AIMoveResult_t CAI_Motor::MoveClimbExecute( const Vector &climbDest, const Vecto
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
float climbSpeed = GetOuter()->GetInstantaneousVelocity();
|
||||
|
||||
if (m_nDismountSequence != ACT_INVALID)
|
||||
{
|
||||
// catch situations where the climb mount/dismount finished before reaching goal
|
||||
#ifdef EXPANDED_NAVIGATION_ACTIVITIES
|
||||
if ((GetActivity() == ACT_CLIMB_DISMOUNT || GetActivity() == ACT_CLIMB_DISMOUNT_BOTTOM))
|
||||
{
|
||||
SetGroundEntity( NULL );
|
||||
|
||||
if (GetOuter()->IsActivityFinished())
|
||||
{
|
||||
// Fix up our position if we have to
|
||||
Vector vecTeleportOrigin;
|
||||
if (MoveClimbShouldTeleportToSequenceEnd( vecTeleportOrigin ))
|
||||
{
|
||||
// Just force it to complete
|
||||
climbDist = 0.0f;
|
||||
}
|
||||
|
||||
climbSpeed = 200.0f;
|
||||
}
|
||||
}
|
||||
#else
|
||||
climbSpeed = MAX( climbSpeed, 30.0 );
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -314,7 +437,7 @@ AIMoveResult_t CAI_Motor::MoveClimbExecute( const Vector &climbDest, const Vecto
|
||||
climbDist = 0;
|
||||
|
||||
const float climbTime = climbDist / climbSpeed;
|
||||
|
||||
|
||||
SetMoveInterval( GetMoveInterval() - climbTime );
|
||||
SetLocalOrigin( climbDest );
|
||||
|
||||
@ -330,6 +453,20 @@ AIMoveResult_t CAI_Motor::MoveClimbExecute( const Vector &climbDest, const Vecto
|
||||
// --------------------------------------------
|
||||
SetIdealYawAndUpdate( yaw );
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Lock the yaw if we're in position
|
||||
if ( UTIL_AngleMod( yaw ) == UTIL_AngleMod( GetLocalAngles().y ) )
|
||||
{
|
||||
SetYawLocked( true );
|
||||
}
|
||||
else if ( IsYawLocked() )
|
||||
{
|
||||
// We're in a different position now. Unlock the yaw and update it
|
||||
SetYawLocked( false );
|
||||
UpdateYaw( -1 );
|
||||
}
|
||||
#endif
|
||||
|
||||
return AIMR_OK;
|
||||
}
|
||||
|
||||
@ -340,11 +477,62 @@ void CAI_Motor::MoveClimbStop()
|
||||
else
|
||||
SetActivity( ACT_IDLE );
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Unlock desired weapon state so NPCs can unholster their weapons again.
|
||||
GetOuter()->SetDesiredWeaponState( DESIREDWEAPONSTATE_IGNORE );
|
||||
|
||||
// Unlock yaw
|
||||
SetYawLocked( false );
|
||||
#endif
|
||||
|
||||
GetOuter()->RemoveFlag( FL_FLY );
|
||||
SetSmoothedVelocity( vec3_origin );
|
||||
SetGravity( 1.0 );
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
void CAI_Motor::MoveClimbPause()
|
||||
{
|
||||
if (GetActivity() != ACT_CLIMB_DISMOUNT
|
||||
#ifdef EXPANDED_NAVIGATION_ACTIVITIES
|
||||
&& GetActivity() != ACT_CLIMB_MOUNT_TOP && GetActivity() != ACT_CLIMB_MOUNT_BOTTOM
|
||||
#endif
|
||||
)
|
||||
{
|
||||
if ( GetActivity() == ACT_CLIMB_ALL )
|
||||
{
|
||||
SetPoseParameter( GetOuter()->LookupPoseMoveYaw(), 0.0f );
|
||||
}
|
||||
|
||||
SetSmoothedVelocity( vec3_origin );
|
||||
}
|
||||
else
|
||||
{
|
||||
// If already dismounting, do nothing
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: This is part of a hack needed in cases where ladder mount/dismount animations collide with the world and don't move properly.
|
||||
// It's based off of the same code as scripted_sequence's teleportation fixup, although this function only resolves the bone origin and
|
||||
// returns whether or not teleportation is necessary, as the teleportation is achieved in different ways for different uses of this code.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CAI_Motor::MoveClimbShouldTeleportToSequenceEnd( Vector &teleportOrigin )
|
||||
{
|
||||
QAngle new_angle;
|
||||
GetOuter()->GetBonePosition( 0, teleportOrigin, new_angle );
|
||||
|
||||
// Ensure that there is actually a distance needed to teleport there
|
||||
if ((GetLocalOrigin() - teleportOrigin).Length2DSqr() > Square( 8.0 ))
|
||||
{
|
||||
teleportOrigin.z = GetLocalOrigin().z;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Motion for jumping
|
||||
// Input :
|
||||
@ -651,9 +839,20 @@ void CAI_Motor::MoveFacing( const AILocalMoveGoal_t &move )
|
||||
{
|
||||
// FIXME: move this up to navigator so that path goals can ignore these overrides.
|
||||
Vector dir;
|
||||
float flInfluence = GetFacingDirection( dir );
|
||||
dir = move.facing * (1 - flInfluence) + dir * flInfluence;
|
||||
VectorNormalize( dir );
|
||||
|
||||
#ifdef MAPBASE
|
||||
if (IsDeceleratingToGoal() && (GetOuter()->GetHintNode() /*|| GetOuter()->m_hOpeningDoor*/))
|
||||
{
|
||||
// Don't let the facing queue interfere with arrival direction in important cases
|
||||
dir = move.facing;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
float flInfluence = GetFacingDirection( dir );
|
||||
dir = move.facing * (1 - flInfluence) + dir * flInfluence;
|
||||
VectorNormalize( dir );
|
||||
}
|
||||
|
||||
// ideal facing direction
|
||||
float idealYaw = UTIL_AngleMod( UTIL_VecToYaw( dir ) );
|
||||
|
@ -62,6 +62,10 @@ public:
|
||||
virtual void MoveClimbStart( const Vector &climbDest, const Vector &climbDir, float climbDist, float yaw );
|
||||
virtual AIMoveResult_t MoveClimbExecute( const Vector &climbDest, const Vector &climbDir, float climbDist, float yaw, int climbNodesLeft );
|
||||
virtual void MoveClimbStop();
|
||||
#ifdef MAPBASE
|
||||
virtual void MoveClimbPause();
|
||||
virtual bool MoveClimbShouldTeleportToSequenceEnd( Vector &teleportOrigin );
|
||||
#endif
|
||||
|
||||
//---------------------------------
|
||||
|
||||
@ -83,6 +87,9 @@ public:
|
||||
const Vector & GetCurVel() const { return m_vecVelocity; }
|
||||
|
||||
virtual float OverrideMaxYawSpeed( Activity activity ) { return -1; }
|
||||
#ifdef MAPBASE
|
||||
virtual
|
||||
#endif
|
||||
bool IsDeceleratingToGoal() const { return false; }
|
||||
|
||||
//---------------------------------
|
||||
|
@ -999,12 +999,23 @@ int CAI_Navigator::GetArrivalSequence( int curSequence )
|
||||
activity = ACT_IDLE;
|
||||
}
|
||||
|
||||
sequence = GetOuter()->SelectWeightedSequence( GetOuter()->TranslateActivity( activity ), curSequence );
|
||||
Activity translatedActivity = GetOuter()->TranslateActivity( activity );
|
||||
sequence = GetOuter()->SelectWeightedSequence( translatedActivity, curSequence );
|
||||
|
||||
if ( sequence == ACT_INVALID )
|
||||
{
|
||||
DevMsg( GetOuter(), "No appropriate sequence for arrival activity %s (%d)\n", GetOuter()->GetActivityName( GetPath()->GetArrivalActivity() ), GetPath()->GetArrivalActivity() );
|
||||
sequence = GetOuter()->SelectWeightedSequence( GetOuter()->TranslateActivity( ACT_IDLE ), curSequence );
|
||||
#ifdef MAPBASE
|
||||
if ( translatedActivity == ACT_SCRIPT_CUSTOM_MOVE )
|
||||
{
|
||||
// ACT_SCRIPT_CUSTOM_MOVE allows activity translation to resolve into specific sequences
|
||||
sequence = GetOuter()->GetScriptCustomMoveSequence();
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
DevMsg( GetOuter(), "No appropriate sequence for arrival activity %s (%d)\n", GetOuter()->GetActivityName( GetPath()->GetArrivalActivity() ), GetPath()->GetArrivalActivity() );
|
||||
sequence = GetOuter()->SelectWeightedSequence( GetOuter()->TranslateActivity( ACT_IDLE ), curSequence );
|
||||
}
|
||||
}
|
||||
Assert( sequence != ACT_INVALID );
|
||||
GetPath()->SetArrivalSequence( sequence );
|
||||
@ -1642,6 +1653,15 @@ void CAI_Navigator::MoveCalcBaseGoal( AILocalMoveGoal_t *pMoveGoal )
|
||||
AI_Waypoint_t *pCurWaypoint = GetPath()->GetCurWaypoint();
|
||||
if ( pCurWaypoint->GetNext() && pCurWaypoint->GetNext()->NavType() != pCurWaypoint->NavType() )
|
||||
pMoveGoal->flags |= AILMG_TARGET_IS_TRANSITION;
|
||||
|
||||
#ifdef MAPBASE
|
||||
// TODO: Better place for this code?
|
||||
if (pMoveGoal->flags & AILMG_TARGET_IS_TRANSITION && pCurWaypoint->GetNext()->NavType() == NAV_CLIMB)
|
||||
{
|
||||
// NPCs need to holster their weapons before climbing.
|
||||
GetOuter()->SetDesiredWeaponState( DESIREDWEAPONSTATE_HOLSTERED );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
const Task_t *pCurTask = GetOuter()->GetTask();
|
||||
@ -2164,11 +2184,26 @@ bool CAI_Navigator::OnMoveBlocked( AIMoveResult_t *pResult )
|
||||
if (pDoor != NULL)
|
||||
{
|
||||
GetOuter()->OpenPropDoorBegin( pDoor );
|
||||
#ifdef MAPBASE
|
||||
// Tell the navigation to stop running until we're done.
|
||||
OnNewGoal();
|
||||
#endif
|
||||
*pResult = AIMR_OK;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( GetOuter()->m_hOpeningDoor )
|
||||
{
|
||||
// In the process of opening a door
|
||||
// Because navigation is now supposed to terminate when a NPC begins opening a door, this code should not be reached.
|
||||
DbgNavMsg( GetOuter(), "CAI_Navigator::OnMoveBlocked had to check for m_hOpeningDoor\n" );
|
||||
*pResult = AIMR_OK;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Allow the NPC to override this behavior
|
||||
if ( GetOuter()->OnMoveBlocked( pResult ))
|
||||
@ -2591,8 +2626,12 @@ bool CAI_Navigator::Move( float flInterval )
|
||||
|
||||
if ( GetNavType() == NAV_CLIMB )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
GetMotor()->MoveClimbPause();
|
||||
#else
|
||||
GetMotor()->MoveClimbStop();
|
||||
SetNavType( NAV_GROUND );
|
||||
#endif
|
||||
}
|
||||
GetMotor()->MoveStop();
|
||||
AssertMsg( TaskIsRunning() || TaskIsComplete(), ("Schedule stalled!!\n") );
|
||||
@ -2695,6 +2734,11 @@ void CAI_Navigator::AdvancePath()
|
||||
if (pDoor != NULL)
|
||||
{
|
||||
GetOuter()->OpenPropDoorBegin(pDoor);
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Tell the navigation to stop running until we're done.
|
||||
OnNewGoal();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -3880,7 +3924,12 @@ bool CAI_Navigator::GetStoppingPath( CAI_WaypointList * pClippedWaypoints )
|
||||
AI_Waypoint_t *pCurWaypoint = GetPath()->GetCurWaypoint();
|
||||
if ( pCurWaypoint )
|
||||
{
|
||||
#ifdef EXPANDED_NAVIGATION_ACTIVITIES
|
||||
// Since regular climb nav can interrupt itself now, only do this when dismounting
|
||||
bool bMustCompleteCurrent = ( (pCurWaypoint->NavType() == NAV_CLIMB && (GetActivity() == ACT_CLIMB_DISMOUNT || GetActivity() == ACT_CLIMB_MOUNT_TOP)) || pCurWaypoint->NavType() == NAV_JUMP );
|
||||
#else
|
||||
bool bMustCompleteCurrent = ( pCurWaypoint->NavType() == NAV_CLIMB || pCurWaypoint->NavType() == NAV_JUMP );
|
||||
#endif
|
||||
float distRemaining = GetMotor()->MinStoppingDist( 0 );
|
||||
|
||||
if ( bMustCompleteCurrent )
|
||||
|
@ -144,6 +144,31 @@ public:
|
||||
int m_capabilities; // cache this
|
||||
};
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-------------------------------------
|
||||
// Purpose: A version of CNodeFilter which allows hints to influence the result.
|
||||
//-------------------------------------
|
||||
class CNodeHintFilter : public CNodeFilter
|
||||
{
|
||||
public:
|
||||
CNodeHintFilter( CAI_BaseNPC *pNPC, const Vector &pos ) : CNodeFilter( pNPC, pos ) {}
|
||||
CNodeHintFilter( const Vector &pos ) : CNodeFilter( pos ) {}
|
||||
|
||||
virtual float NodeDistanceSqr( CAI_Node &node )
|
||||
{
|
||||
// Heavier hints are considered closer
|
||||
if ( node.GetHint() && node.GetHint()->GetHintWeight() != 1.0f && (node.GetHint()->GetGroup() == NULL_STRING || node.GetHint()->GetGroup() == m_pNPC->GetHintGroup()) )
|
||||
{
|
||||
return CNodeFilter::NodeDistanceSqr( node ) * node.GetHint()->GetHintWeightInverse();
|
||||
}
|
||||
else
|
||||
{
|
||||
return CNodeFilter::NodeDistanceSqr( node );
|
||||
}
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CAI_Network
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -351,7 +376,12 @@ int CAI_Network::NearestNodeToPoint( CAI_BaseNPC *pNPC, const Vector &vecOrigin,
|
||||
// First get nodes distances and eliminate those that are beyond
|
||||
// the maximum allowed distance for local movements
|
||||
// ---------------------------------------------------------------
|
||||
#ifdef MAPBASE
|
||||
// Allow hint weight to influence supposed distance
|
||||
CNodeHintFilter filter( pNPC, vecOrigin );
|
||||
#else
|
||||
CNodeFilter filter( pNPC, vecOrigin );
|
||||
#endif
|
||||
|
||||
#ifdef AI_PERF_MON
|
||||
m_nPerfStatNN++;
|
||||
@ -605,8 +635,13 @@ CAI_Node *CAI_Network::AddNode( const Vector &origin, float yaw )
|
||||
|
||||
CAI_Link *CAI_Network::CreateLink( int srcID, int destID, CAI_DynamicLink *pDynamicLink )
|
||||
{
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
CAI_Node *pSrcNode = GetNode( srcID );
|
||||
CAI_Node *pDestNode = GetNode( destID );
|
||||
#else
|
||||
CAI_Node *pSrcNode = g_pBigAINet->GetNode( srcID );
|
||||
CAI_Node *pDestNode = g_pBigAINet->GetNode( destID );
|
||||
#endif
|
||||
|
||||
Assert( pSrcNode && pDestNode && pSrcNode != pDestNode );
|
||||
|
||||
|
@ -71,6 +71,8 @@ CON_COMMAND( ai_debug_node_connect, "Debug the attempted connection between two
|
||||
ConVar g_ai_norebuildgraph( "ai_norebuildgraph", "0" );
|
||||
#ifdef MAPBASE
|
||||
ConVar g_ai_norebuildgraphmessage( "ai_norebuildgraphmessage", "0", FCVAR_ARCHIVE, "Stops the \"Node graph out of date\" message from appearing when rebuilding node graph" );
|
||||
|
||||
ConVar g_ai_ignore_graph_timestamps( "g_ai_ignore_graph_timestamps", "1", FCVAR_NONE, "Ignores file timestamps when rebuilding nodegraphs, only relying on internal map version differences" );
|
||||
#endif
|
||||
|
||||
|
||||
@ -986,6 +988,11 @@ bool CAI_NetworkManager::IsAIFileCurrent ( const char *szMapName )
|
||||
// dvd build process validates and guarantees correctness, timestamps are allowed to be wrong
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
if (g_ai_ignore_graph_timestamps.GetBool())
|
||||
return true;
|
||||
#endif
|
||||
|
||||
{
|
||||
const char *pGameDir = CommandLine()->ParmValue( "-game", "hl2" );
|
||||
|
@ -411,7 +411,12 @@ int CAI_TacticalServices::FindCoverNode(const Vector &vNearPos, const Vector &vT
|
||||
// --------------------------------------------------------
|
||||
pNode->Lock( 1.0 );
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( pNode->GetHint() && ( pNode->GetHint()->HintType() == HINT_TACTICAL_COVER_MED || pNode->GetHint()->HintType() == HINT_TACTICAL_COVER_LOW
|
||||
|| pNode->GetHint()->HintType() == HINT_TACTICAL_COVER_CUSTOM ) )
|
||||
#else
|
||||
if ( pNode->GetHint() && ( pNode->GetHint()->HintType() == HINT_TACTICAL_COVER_MED || pNode->GetHint()->HintType() == HINT_TACTICAL_COVER_LOW ) )
|
||||
#endif
|
||||
{
|
||||
if ( GetOuter()->GetHintNode() )
|
||||
{
|
||||
|
@ -32,6 +32,9 @@
|
||||
#include "gib.h"
|
||||
#include "CRagdollMagnet.h"
|
||||
#endif
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
#include "mapbase/vscript_funcs_shared.h"
|
||||
#endif
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
@ -1296,7 +1299,7 @@ bool CBaseAnimating::ScriptHookHandleAnimEvent( animevent_t *pEvent )
|
||||
{
|
||||
if (m_ScriptScope.IsInitialized() && g_Hook_HandleAnimEvent.CanRunInScope(m_ScriptScope))
|
||||
{
|
||||
HSCRIPT hEvent = g_pScriptVM->RegisterInstance( pEvent );
|
||||
HSCRIPT hEvent = g_pScriptVM->RegisterInstance( reinterpret_cast<scriptanimevent_t*>(pEvent) );
|
||||
|
||||
// event
|
||||
ScriptVariant_t args[] = { hEvent };
|
||||
|
@ -388,6 +388,8 @@ private:
|
||||
|
||||
void InputSetCycle( inputdata_t &inputdata );
|
||||
void InputSetPlaybackRate( inputdata_t &inputdata );
|
||||
|
||||
public: // From Alien Swarm SDK
|
||||
#endif
|
||||
|
||||
bool CanSkipAnimation( void );
|
||||
|
@ -61,11 +61,6 @@
|
||||
extern int g_interactionBarnacleVictimReleased;
|
||||
#endif //HL2_DLL
|
||||
|
||||
#ifdef MAPBASE
|
||||
extern acttable_t *GetSMG1Acttable();
|
||||
extern int GetSMG1ActtableCount();
|
||||
#endif
|
||||
|
||||
extern ConVar weapon_showproficiency;
|
||||
|
||||
ConVar ai_show_hull_attacks( "ai_show_hull_attacks", "0" );
|
||||
@ -1788,7 +1783,14 @@ void CBaseCombatCharacter::Event_Killed( const CTakeDamageInfo &info )
|
||||
// if flagged to drop a health kit
|
||||
if (HasSpawnFlags(SF_NPC_DROP_HEALTHKIT))
|
||||
{
|
||||
CBaseEntity::Create( "item_healthvial", GetAbsOrigin(), GetAbsAngles() );
|
||||
CBaseEntity *pItem = CBaseEntity::Create( "item_healthvial", GetAbsOrigin(), GetAbsAngles() );
|
||||
if (pItem)
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
if (MyNPCPointer())
|
||||
MyNPCPointer()->m_OnItemDrop.Set( pItem, pItem, this );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
// clear the deceased's sound channels.(may have been firing or reloading when killed)
|
||||
EmitSound( "BaseCombatCharacter.StopWeaponSounds" );
|
||||
@ -2744,19 +2746,22 @@ Activity CBaseCombatCharacter::Weapon_BackupActivity( Activity activity, bool we
|
||||
return activity;
|
||||
}
|
||||
|
||||
acttable_t *pTable = GetSMG1Acttable();
|
||||
int actCount = GetSMG1ActtableCount();
|
||||
for ( int i = 0; i < actCount; i++, pTable++ )
|
||||
acttable_t *pTable = pWeapon->GetBackupActivityList();
|
||||
if (pTable)
|
||||
{
|
||||
if ( activity == pTable->baseAct )
|
||||
int actCount = pWeapon->GetBackupActivityListCount();
|
||||
for ( int i = 0; i < actCount; i++, pTable++ )
|
||||
{
|
||||
// Don't pick SMG animations we don't actually have an animation for.
|
||||
if (GetModelPtr() ? !GetModelPtr()->HaveSequenceForActivity(pTable->weaponAct) : false)
|
||||
if ( activity == pTable->baseAct )
|
||||
{
|
||||
return activity;
|
||||
}
|
||||
// Don't pick SMG animations we don't actually have an animation for.
|
||||
if (GetModelPtr() ? !GetModelPtr()->HaveSequenceForActivity(pTable->weaponAct) : false)
|
||||
{
|
||||
return activity;
|
||||
}
|
||||
|
||||
return (Activity)pTable->weaponAct;
|
||||
return (Activity)pTable->weaponAct;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -373,7 +373,12 @@ bool CBaseCombatWeapon::WeaponLOSCondition( const Vector &ownerPos, const Vector
|
||||
//-----------------------------------------------------------------------------
|
||||
int CBaseCombatWeapon::WeaponRangeAttack1Condition( float flDot, float flDist )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
// HACKHACK: HasPrimaryAmmo() checks the NPC's reserve ammo counts, which should not be evaluated here if we use clips
|
||||
if ( UsesPrimaryAmmo() && (UsesClipsForAmmo1() ? !m_iClip1 : !HasPrimaryAmmo()) )
|
||||
#else
|
||||
if ( UsesPrimaryAmmo() && !HasPrimaryAmmo() )
|
||||
#endif
|
||||
{
|
||||
return COND_NO_PRIMARY_AMMO;
|
||||
}
|
||||
|
@ -106,6 +106,10 @@ ConVar sv_netvisdist( "sv_netvisdist", "10000", FCVAR_CHEAT | FCVAR_DEVELOPMENTO
|
||||
|
||||
ConVar sv_script_think_interval("sv_script_think_interval", "0.1");
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
ConVar ent_text_allow_script( "ent_text_allow_script", "1" );
|
||||
#endif
|
||||
|
||||
|
||||
// This table encodes edict data.
|
||||
void SendProxy_AnimTime( const SendProp *pProp, const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID )
|
||||
@ -454,6 +458,17 @@ extern bool g_bDisableEhandleAccess;
|
||||
//-----------------------------------------------------------------------------
|
||||
CBaseEntity::~CBaseEntity( )
|
||||
{
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
// HACKHACK: This is needed to fix a crash when an entity removes itself with Destroy() during its own think function.
|
||||
// (see https://github.com/mapbase-source/source-sdk-2013/issues/138)
|
||||
FOR_EACH_VEC( m_ScriptThinkFuncs, i )
|
||||
{
|
||||
HSCRIPT h = m_ScriptThinkFuncs[i]->m_hfnThink;
|
||||
if ( h ) g_pScriptVM->ReleaseScript( h );
|
||||
}
|
||||
m_ScriptThinkFuncs.PurgeAndDeleteElements();
|
||||
#endif // MAPBASE_VSCRIPT
|
||||
|
||||
// FIXME: This can't be called from UpdateOnRemove! There's at least one
|
||||
// case where friction sounds are added between the call to UpdateOnRemove + ~CBaseEntity
|
||||
PhysCleanupFrictionSounds( this );
|
||||
@ -1060,6 +1075,28 @@ int CBaseEntity::DrawDebugTextOverlays(void)
|
||||
offset++;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
// 'OnEntText' hook inspired by later source games
|
||||
if (m_ScriptScope.IsInitialized() && g_Hook_OnEntText.CanRunInScope( m_ScriptScope ))
|
||||
{
|
||||
if (ent_text_allow_script.GetBool())
|
||||
{
|
||||
ScriptVariant_t functionReturn;
|
||||
if ( g_Hook_OnEntText.Call( m_ScriptScope, &functionReturn, NULL ) && functionReturn.m_type == FIELD_CSTRING )
|
||||
{
|
||||
CUtlStringList outStrings;
|
||||
V_SplitString( functionReturn.m_pszString, "\n", outStrings );
|
||||
|
||||
FOR_EACH_VEC( outStrings, i )
|
||||
{
|
||||
EntityText( offset, outStrings[i], 0, 224, 240, 255 );
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (m_debugOverlays & OVERLAY_VIEWOFFSET)
|
||||
@ -1349,10 +1386,10 @@ float CBaseEntity::GetMaxOutputDelay( const char *pszOutput )
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CBaseEntity::CancelEventsByInput( const char *szInput )
|
||||
{
|
||||
g_EventQueue.CancelEventsByInput( this, szInput );
|
||||
}
|
||||
//void CBaseEntity::CancelEventsByInput( const char *szInput )
|
||||
//{
|
||||
// g_EventQueue.CancelEventsByInput( this, szInput );
|
||||
//}
|
||||
#endif // MAPBASE_VSCRIPT
|
||||
|
||||
CBaseEntityOutput *CBaseEntity::FindNamedOutput( const char *pszOutput )
|
||||
@ -2209,11 +2246,15 @@ END_DATADESC()
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
ScriptHook_t CBaseEntity::g_Hook_UpdateOnRemove;
|
||||
ScriptHook_t CBaseEntity::g_Hook_OnEntText;
|
||||
|
||||
ScriptHook_t CBaseEntity::g_Hook_VPhysicsCollision;
|
||||
ScriptHook_t CBaseEntity::g_Hook_FireBullets;
|
||||
ScriptHook_t CBaseEntity::g_Hook_OnDeath;
|
||||
ScriptHook_t CBaseEntity::g_Hook_OnKilledOther;
|
||||
ScriptHook_t CBaseEntity::g_Hook_HandleInteraction;
|
||||
ScriptHook_t CBaseEntity::g_Hook_ModifyEmitSoundParams;
|
||||
ScriptHook_t CBaseEntity::g_Hook_ModifySentenceParams;
|
||||
#endif
|
||||
|
||||
BEGIN_ENT_SCRIPTDESC_ROOT( CBaseEntity, "Root class of all server-side entities" )
|
||||
@ -2348,7 +2389,7 @@ BEGIN_ENT_SCRIPTDESC_ROOT( CBaseEntity, "Root class of all server-side entities"
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptAcceptInput, "AcceptInput", "" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptFireOutput, "FireOutput", "Fire an entity output" )
|
||||
DEFINE_SCRIPTFUNC( GetMaxOutputDelay, "Get the longest delay for all events attached to an output" )
|
||||
DEFINE_SCRIPTFUNC( CancelEventsByInput, "Cancel all I/O events for this entity, match input" )
|
||||
//DEFINE_SCRIPTFUNC( CancelEventsByInput, "Cancel all I/O events for this entity, match input" ) // Commented out due to unpredictability and unknown risks
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptAddOutput, "AddOutput", "Add an output" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetKeyValue, "GetKeyValue", "Get a keyvalue" )
|
||||
@ -2460,6 +2501,7 @@ BEGIN_ENT_SCRIPTDESC_ROOT( CBaseEntity, "Root class of all server-side entities"
|
||||
// Hooks
|
||||
//
|
||||
DEFINE_SIMPLE_SCRIPTHOOK( CBaseEntity::g_Hook_UpdateOnRemove, "UpdateOnRemove", FIELD_VOID, "Called when the entity is being removed." )
|
||||
DEFINE_SIMPLE_SCRIPTHOOK( CBaseEntity::g_Hook_OnEntText, "OnEntText", FIELD_CSTRING, "Called every frame when ent_text is enabled on the entity. Return a string to be added to the ent_text printout." )
|
||||
|
||||
BEGIN_SCRIPTHOOK( CBaseEntity::g_Hook_VPhysicsCollision, "VPhysicsCollision", FIELD_VOID, "Called for every single VPhysics-related collision experienced by this entity." )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "entity", FIELD_HSCRIPT )
|
||||
@ -2489,6 +2531,14 @@ BEGIN_ENT_SCRIPTDESC_ROOT( CBaseEntity, "Root class of all server-side entities"
|
||||
//DEFINE_SCRIPTHOOK_PARAM( "data", FIELD_VARIANT )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "sourceEnt", FIELD_HSCRIPT )
|
||||
END_SCRIPTHOOK()
|
||||
|
||||
BEGIN_SCRIPTHOOK( CBaseEntity::g_Hook_ModifyEmitSoundParams, "ModifyEmitSoundParams", FIELD_VOID, "Called every time a sound is emitted on this entity, allowing for its parameters to be modified." )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "params", FIELD_HSCRIPT )
|
||||
END_SCRIPTHOOK()
|
||||
|
||||
BEGIN_SCRIPTHOOK( CBaseEntity::g_Hook_ModifySentenceParams, "ModifySentenceParams", FIELD_VOID, "Called every time a sentence is emitted on this entity, allowing for its parameters to be modified." )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "params", FIELD_HSCRIPT )
|
||||
END_SCRIPTHOOK()
|
||||
#endif
|
||||
END_SCRIPTDESC();
|
||||
|
||||
@ -2604,15 +2654,6 @@ void CBaseEntity::UpdateOnRemove( void )
|
||||
|
||||
g_pScriptVM->RemoveInstance( m_hScriptInstance );
|
||||
m_hScriptInstance = NULL;
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
FOR_EACH_VEC( m_ScriptThinkFuncs, i )
|
||||
{
|
||||
HSCRIPT h = m_ScriptThinkFuncs[i]->m_hfnThink;
|
||||
if ( h ) g_pScriptVM->ReleaseScript( h );
|
||||
}
|
||||
m_ScriptThinkFuncs.PurgeAndDeleteElements();
|
||||
#endif // MAPBASE_VSCRIPT
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -610,7 +610,7 @@ public:
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
void ScriptFireOutput( const char *pszOutput, HSCRIPT hActivator, HSCRIPT hCaller, const char *szValue, float flDelay );
|
||||
float GetMaxOutputDelay( const char *pszOutput );
|
||||
void CancelEventsByInput( const char *szInput );
|
||||
//void CancelEventsByInput( const char *szInput );
|
||||
#endif
|
||||
|
||||
|
||||
@ -1537,6 +1537,12 @@ public:
|
||||
void GenderExpandString( char const *in, char *out, int maxlen );
|
||||
|
||||
virtual void ModifyEmitSoundParams( EmitSound_t ¶ms );
|
||||
#ifdef MAPBASE
|
||||
// Same as above, but for sentences
|
||||
// (which don't actually have EmitSound_t params)
|
||||
virtual void ModifySentenceParams( int &iSentenceIndex, int &iChannel, float &flVolume, soundlevel_t &iSoundlevel, int &iFlags, int &iPitch,
|
||||
const Vector **pOrigin, const Vector **pDirection, bool &bUpdatePositions, float &soundtime, int &iSpecialDSP, int &iSpeakerIndex );
|
||||
#endif
|
||||
|
||||
static float GetSoundDuration( const char *soundname, char const *actormodel );
|
||||
|
||||
@ -2148,11 +2154,15 @@ public:
|
||||
void ScriptSetTakeDamage( int val ) { m_takedamage = val; }
|
||||
|
||||
static ScriptHook_t g_Hook_UpdateOnRemove;
|
||||
static ScriptHook_t g_Hook_OnEntText;
|
||||
|
||||
static ScriptHook_t g_Hook_VPhysicsCollision;
|
||||
static ScriptHook_t g_Hook_FireBullets;
|
||||
static ScriptHook_t g_Hook_OnDeath;
|
||||
static ScriptHook_t g_Hook_OnKilledOther;
|
||||
static ScriptHook_t g_Hook_HandleInteraction;
|
||||
static ScriptHook_t g_Hook_ModifyEmitSoundParams;
|
||||
static ScriptHook_t g_Hook_ModifySentenceParams;
|
||||
#endif
|
||||
|
||||
string_t m_iszVScripts;
|
||||
|
@ -95,7 +95,11 @@ BEGIN_DATADESC( CBaseFlex )
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
BEGIN_ENT_SCRIPTDESC( CBaseFlex, CBaseAnimatingOverlay, "Animated characters who have vertex flex capability." )
|
||||
#else
|
||||
BEGIN_ENT_SCRIPTDESC( CBaseFlex, CBaseAnimating, "Animated characters who have vertex flex capability." )
|
||||
#endif
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetOldestScene, "GetCurrentScene", "Returns the instance of the oldest active scene entity (if any)." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetSceneByIndex, "GetSceneByIndex", "Returns the instance of the scene entity at the specified index." )
|
||||
END_SCRIPTDESC();
|
||||
|
@ -5,9 +5,8 @@
|
||||
// $NoKeywords: $
|
||||
//===========================================================================//
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "cbase.h"
|
||||
#include "colorcorrection.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
@ -16,64 +15,6 @@
|
||||
|
||||
static const char *s_pFadeInContextThink = "ColorCorrectionFadeInThink";
|
||||
static const char *s_pFadeOutContextThink = "ColorCorrectionFadeOutThink";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// FIXME: This really should inherit from something more lightweight
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose : Shadow control entity
|
||||
//------------------------------------------------------------------------------
|
||||
class CColorCorrection : public CBaseEntity
|
||||
{
|
||||
DECLARE_CLASS( CColorCorrection, CBaseEntity );
|
||||
public:
|
||||
DECLARE_SERVERCLASS();
|
||||
DECLARE_DATADESC();
|
||||
|
||||
CColorCorrection();
|
||||
|
||||
void Spawn( void );
|
||||
int UpdateTransmitState();
|
||||
void Activate( void );
|
||||
|
||||
virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; }
|
||||
|
||||
// Inputs
|
||||
void InputEnable( inputdata_t &inputdata );
|
||||
void InputDisable( inputdata_t &inputdata );
|
||||
void InputSetFadeInDuration ( inputdata_t &inputdata );
|
||||
void InputSetFadeOutDuration ( inputdata_t &inputdata );
|
||||
|
||||
private:
|
||||
void FadeIn ( void );
|
||||
void FadeOut ( void );
|
||||
|
||||
void FadeInThink( void ); // Fades lookup weight from Cur->MaxWeight
|
||||
void FadeOutThink( void ); // Fades lookup weight from CurWeight->0.0
|
||||
|
||||
|
||||
|
||||
float m_flFadeInDuration; // Duration for a full 0->MaxWeight transition
|
||||
float m_flFadeOutDuration; // Duration for a full Max->0 transition
|
||||
float m_flStartFadeInWeight;
|
||||
float m_flStartFadeOutWeight;
|
||||
float m_flTimeStartFadeIn;
|
||||
float m_flTimeStartFadeOut;
|
||||
|
||||
float m_flMaxWeight;
|
||||
|
||||
bool m_bStartDisabled;
|
||||
CNetworkVar( bool, m_bEnabled );
|
||||
|
||||
CNetworkVar( float, m_MinFalloff );
|
||||
CNetworkVar( float, m_MaxFalloff );
|
||||
CNetworkVar( float, m_flCurWeight );
|
||||
CNetworkString( m_netlookupFilename, MAX_PATH );
|
||||
|
||||
string_t m_lookupFilename;
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS(color_correction, CColorCorrection);
|
||||
|
||||
@ -97,12 +38,19 @@ BEGIN_DATADESC( CColorCorrection )
|
||||
|
||||
DEFINE_KEYFIELD( m_bEnabled, FIELD_BOOLEAN, "enabled" ),
|
||||
DEFINE_KEYFIELD( m_bStartDisabled, FIELD_BOOLEAN, "StartDisabled" ),
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
DEFINE_KEYFIELD( m_bExclusive, FIELD_BOOLEAN, "exclusive" ),
|
||||
#endif
|
||||
// DEFINE_ARRAY( m_netlookupFilename, FIELD_CHARACTER, MAX_PATH ),
|
||||
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetFadeInDuration", InputSetFadeInDuration ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetFadeOutDuration", InputSetFadeOutDuration ),
|
||||
#ifdef MAPBASE
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetMinFalloff", InputSetMinFalloff ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetMaxFalloff", InputSetMaxFalloff ),
|
||||
#endif
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
@ -112,8 +60,18 @@ IMPLEMENT_SERVERCLASS_ST_NOBASE(CColorCorrection, DT_ColorCorrection)
|
||||
SendPropFloat( SENDINFO(m_MinFalloff) ),
|
||||
SendPropFloat( SENDINFO(m_MaxFalloff) ),
|
||||
SendPropFloat( SENDINFO(m_flCurWeight) ),
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
SendPropFloat( SENDINFO(m_flMaxWeight) ),
|
||||
SendPropFloat( SENDINFO(m_flFadeInDuration) ),
|
||||
SendPropFloat( SENDINFO(m_flFadeOutDuration) ),
|
||||
#endif
|
||||
SendPropString( SENDINFO(m_netlookupFilename) ),
|
||||
SendPropBool( SENDINFO(m_bEnabled) ),
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
SendPropBool( SENDINFO(m_bMaster) ),
|
||||
SendPropBool( SENDINFO(m_bClientSide) ),
|
||||
SendPropBool( SENDINFO(m_bExclusive) ),
|
||||
#endif
|
||||
END_SEND_TABLE()
|
||||
|
||||
|
||||
@ -132,6 +90,11 @@ CColorCorrection::CColorCorrection() : BaseClass()
|
||||
m_flTimeStartFadeOut = 0.0f;
|
||||
m_netlookupFilename.GetForModify()[0] = 0;
|
||||
m_lookupFilename = NULL_STRING;
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
m_bMaster = false;
|
||||
m_bClientSide = false;
|
||||
m_bExclusive = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -175,6 +138,11 @@ void CColorCorrection::Activate( void )
|
||||
{
|
||||
BaseClass::Activate();
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK (moved to Activate() for save/restore support)
|
||||
m_bMaster = IsMaster();
|
||||
m_bClientSide = IsClientSide();
|
||||
#endif
|
||||
|
||||
Q_strncpy( m_netlookupFilename.GetForModify(), STRING( m_lookupFilename ), MAX_PATH );
|
||||
}
|
||||
|
||||
@ -183,6 +151,11 @@ void CColorCorrection::Activate( void )
|
||||
//-----------------------------------------------------------------------------
|
||||
void CColorCorrection::FadeIn ( void )
|
||||
{
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
if ( m_bClientSide || ( m_bEnabled && m_flCurWeight >= m_flMaxWeight ) )
|
||||
return;
|
||||
#endif
|
||||
|
||||
m_bEnabled = true;
|
||||
m_flTimeStartFadeIn = gpGlobals->curtime;
|
||||
m_flStartFadeInWeight = m_flCurWeight;
|
||||
@ -194,6 +167,11 @@ void CColorCorrection::FadeIn ( void )
|
||||
//-----------------------------------------------------------------------------
|
||||
void CColorCorrection::FadeOut ( void )
|
||||
{
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
if ( m_bClientSide || ( !m_bEnabled && m_flCurWeight <= 0.0f ) )
|
||||
return;
|
||||
#endif
|
||||
|
||||
m_bEnabled = false;
|
||||
m_flTimeStartFadeOut = gpGlobals->curtime;
|
||||
m_flStartFadeOutWeight = m_flCurWeight;
|
||||
@ -230,7 +208,11 @@ void CColorCorrection::FadeInThink( void )
|
||||
flFadeRatio = clamp ( flFadeRatio, 0.0f, 1.0f );
|
||||
m_flStartFadeInWeight = clamp ( m_flStartFadeInWeight, 0.0f, 1.0f );
|
||||
|
||||
#ifdef MAPBASE
|
||||
m_flCurWeight = Lerp( flFadeRatio, m_flStartFadeInWeight, m_flMaxWeight.Get() );
|
||||
#else
|
||||
m_flCurWeight = Lerp( flFadeRatio, m_flStartFadeInWeight, m_flMaxWeight );
|
||||
#endif
|
||||
|
||||
SetNextThink( gpGlobals->curtime + COLOR_CORRECTION_ENT_THINK_RATE, s_pFadeInContextThink );
|
||||
}
|
||||
@ -312,3 +294,94 @@ void CColorCorrection::InputSetFadeOutDuration( inputdata_t& inputdata )
|
||||
{
|
||||
m_flFadeOutDuration = inputdata.value.Float();
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
void CColorCorrection::InputSetMinFalloff( inputdata_t& inputdata )
|
||||
{
|
||||
m_MinFalloff = inputdata.value.Float();
|
||||
}
|
||||
|
||||
void CColorCorrection::InputSetMaxFalloff( inputdata_t& inputdata )
|
||||
{
|
||||
m_MaxFalloff = inputdata.value.Float();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
CColorCorrectionSystem s_ColorCorrectionSystem( "ColorCorrectionSystem" );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CColorCorrectionSystem *ColorCorrectionSystem( void )
|
||||
{
|
||||
return &s_ColorCorrectionSystem;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Clear out the fog controller.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CColorCorrectionSystem::LevelInitPreEntity( void )
|
||||
{
|
||||
m_hMasterController = NULL;
|
||||
ListenForGameEvent( "round_start" );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Find the master controller. If no controller is
|
||||
// set as Master, use the first controller found.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CColorCorrectionSystem::InitMasterController( void )
|
||||
{
|
||||
CColorCorrection *pColorCorrection = NULL;
|
||||
do
|
||||
{
|
||||
pColorCorrection = static_cast<CColorCorrection*>( gEntList.FindEntityByClassname( pColorCorrection, "color_correction" ) );
|
||||
if ( pColorCorrection )
|
||||
{
|
||||
if ( m_hMasterController.Get() == NULL )
|
||||
{
|
||||
m_hMasterController = pColorCorrection;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( pColorCorrection->IsMaster() )
|
||||
{
|
||||
m_hMasterController = pColorCorrection;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while ( pColorCorrection );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: On a multiplayer map restart, re-find the master controller.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CColorCorrectionSystem::FireGameEvent( IGameEvent *pEvent )
|
||||
{
|
||||
InitMasterController();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: On level load find the master fog controller. If no controller is
|
||||
// set as Master, use the first fog controller found.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CColorCorrectionSystem::LevelInitPostEntity( void )
|
||||
{
|
||||
InitMasterController();
|
||||
|
||||
// HACK: Singleplayer games don't get a call to CBasePlayer::Spawn on level transitions.
|
||||
// CBasePlayer::Activate is called before this is called so that's too soon to set up the fog controller.
|
||||
// We don't have a hook similar to Activate that happens after LevelInitPostEntity
|
||||
// is called, or we could just do this in the player itself.
|
||||
if ( gpGlobals->maxClients == 1 )
|
||||
{
|
||||
CBasePlayer *pPlayer = UTIL_GetLocalPlayer();
|
||||
if ( pPlayer && ( pPlayer->m_hColorCorrectionCtrl.Get() == NULL ) )
|
||||
{
|
||||
pPlayer->InitColorCorrectionController();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
147
sp/src/game/server/colorcorrection.h
Normal file
147
sp/src/game/server/colorcorrection.h
Normal file
@ -0,0 +1,147 @@
|
||||
//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============//
|
||||
//
|
||||
// Note that this header exists in the Alien Swarm SDK, but not in stock Source SDK 2013.
|
||||
// Although technically a new Mapbase file, it only serves to move otherwise identical code,
|
||||
// so most code and repo conventions will pretend it was always there.
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// Purpose: Color correction entity.
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef COLOR_CORRECTION_H
|
||||
#define COLOR_CORRECTION_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include "cbase.h"
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
#include "GameEventListener.h"
|
||||
|
||||
// Spawn Flags
|
||||
#define SF_COLORCORRECTION_MASTER 0x0001
|
||||
#define SF_COLORCORRECTION_CLIENTSIDE 0x0002
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// FIXME: This really should inherit from something more lightweight
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose : Shadow control entity
|
||||
//------------------------------------------------------------------------------
|
||||
class CColorCorrection : public CBaseEntity
|
||||
{
|
||||
DECLARE_CLASS( CColorCorrection, CBaseEntity );
|
||||
public:
|
||||
DECLARE_SERVERCLASS();
|
||||
DECLARE_DATADESC();
|
||||
|
||||
CColorCorrection();
|
||||
|
||||
void Spawn( void );
|
||||
int UpdateTransmitState();
|
||||
void Activate( void );
|
||||
|
||||
virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; }
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
bool IsMaster( void ) const { return HasSpawnFlags( SF_COLORCORRECTION_MASTER ); }
|
||||
|
||||
bool IsClientSide( void ) const { return HasSpawnFlags( SF_COLORCORRECTION_CLIENTSIDE ); }
|
||||
|
||||
bool IsExclusive( void ) const { return m_bExclusive; }
|
||||
#endif
|
||||
|
||||
// Inputs
|
||||
void InputEnable( inputdata_t &inputdata );
|
||||
void InputDisable( inputdata_t &inputdata );
|
||||
void InputSetFadeInDuration ( inputdata_t &inputdata );
|
||||
void InputSetFadeOutDuration ( inputdata_t &inputdata );
|
||||
#ifdef MAPBASE
|
||||
void InputSetMinFalloff( inputdata_t &inputdata );
|
||||
void InputSetMaxFalloff( inputdata_t &inputdata );
|
||||
#endif
|
||||
|
||||
private:
|
||||
void FadeIn ( void );
|
||||
void FadeOut ( void );
|
||||
|
||||
void FadeInThink( void ); // Fades lookup weight from Cur->MaxWeight
|
||||
void FadeOutThink( void ); // Fades lookup weight from CurWeight->0.0
|
||||
|
||||
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
CNetworkVar( float, m_flFadeInDuration ); // Duration for a full 0->MaxWeight transition
|
||||
CNetworkVar( float, m_flFadeOutDuration ); // Duration for a full Max->0 transition
|
||||
#else
|
||||
float m_flFadeInDuration; // Duration for a full 0->MaxWeight transition
|
||||
float m_flFadeOutDuration; // Duration for a full Max->0 transition
|
||||
#endif
|
||||
float m_flStartFadeInWeight;
|
||||
float m_flStartFadeOutWeight;
|
||||
float m_flTimeStartFadeIn;
|
||||
float m_flTimeStartFadeOut;
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
CNetworkVar( float, m_flMaxWeight );
|
||||
#else
|
||||
float m_flMaxWeight;
|
||||
#endif
|
||||
|
||||
bool m_bStartDisabled;
|
||||
CNetworkVar( bool, m_bEnabled );
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
CNetworkVar( bool, m_bMaster );
|
||||
CNetworkVar( bool, m_bClientSide );
|
||||
CNetworkVar( bool, m_bExclusive );
|
||||
#endif
|
||||
|
||||
CNetworkVar( float, m_MinFalloff );
|
||||
CNetworkVar( float, m_MaxFalloff );
|
||||
CNetworkVar( float, m_flCurWeight );
|
||||
CNetworkString( m_netlookupFilename, MAX_PATH );
|
||||
|
||||
string_t m_lookupFilename;
|
||||
};
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
//=============================================================================
|
||||
//
|
||||
// ColorCorrection Controller System. Just a place to store a master controller
|
||||
//
|
||||
class CColorCorrectionSystem : public CAutoGameSystem, public CGameEventListener
|
||||
{
|
||||
public:
|
||||
|
||||
// Creation/Init.
|
||||
CColorCorrectionSystem( char const *name ) : CAutoGameSystem( name )
|
||||
{
|
||||
m_hMasterController = NULL;
|
||||
}
|
||||
|
||||
~CColorCorrectionSystem()
|
||||
{
|
||||
m_hMasterController = NULL;
|
||||
}
|
||||
|
||||
virtual void LevelInitPreEntity();
|
||||
virtual void LevelInitPostEntity();
|
||||
virtual void FireGameEvent( IGameEvent *pEvent );
|
||||
CColorCorrection *GetMasterColorCorrection( void ) { return m_hMasterController; }
|
||||
|
||||
private:
|
||||
|
||||
void InitMasterController( void );
|
||||
CHandle< CColorCorrection > m_hMasterController;
|
||||
};
|
||||
|
||||
CColorCorrectionSystem *ColorCorrectionSystem( void );
|
||||
#endif
|
||||
|
||||
#endif // COLOR_CORRECTION_H
|
@ -48,7 +48,11 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
CNetworkVar( bool, m_bEnabled );
|
||||
#else
|
||||
bool m_bEnabled;
|
||||
#endif
|
||||
bool m_bStartDisabled;
|
||||
|
||||
CNetworkVar( float, m_Weight );
|
||||
@ -61,7 +65,11 @@ private:
|
||||
float m_LastExitWeight;
|
||||
float m_LastExitTime;
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
CNetworkVar( float, m_FadeDuration );
|
||||
#else
|
||||
float m_FadeDuration;
|
||||
#endif
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS(color_correction_volume, CColorCorrectionVolume);
|
||||
@ -90,6 +98,11 @@ END_DATADESC()
|
||||
|
||||
|
||||
IMPLEMENT_SERVERCLASS_ST_NOBASE(CColorCorrectionVolume, DT_ColorCorrectionVolume)
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
SendPropBool( SENDINFO(m_bEnabled) ),
|
||||
SendPropFloat( SENDINFO(m_MaxWeight) ),
|
||||
SendPropFloat( SENDINFO(m_FadeDuration) ),
|
||||
#endif
|
||||
SendPropFloat( SENDINFO(m_Weight) ),
|
||||
SendPropString( SENDINFO(m_lookupFilename) ),
|
||||
END_SEND_TABLE()
|
||||
|
@ -39,6 +39,9 @@ protected:
|
||||
CNetworkVar( float, m_flStartTime );
|
||||
CNetworkVar( int, m_iDesiredOverlay );
|
||||
CNetworkVar( bool, m_bIsActive );
|
||||
#ifdef MAPBASE
|
||||
CNetworkVar( int, m_iOverlayIndex );
|
||||
#endif
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( env_screenoverlay, CEnvScreenOverlay );
|
||||
@ -74,6 +77,9 @@ BEGIN_DATADESC( CEnvScreenOverlay )
|
||||
DEFINE_FIELD( m_iDesiredOverlay, FIELD_INTEGER ),
|
||||
DEFINE_FIELD( m_flStartTime, FIELD_TIME ),
|
||||
DEFINE_FIELD( m_bIsActive, FIELD_BOOLEAN ),
|
||||
#ifdef MAPBASE
|
||||
DEFINE_KEYFIELD( m_iOverlayIndex, FIELD_INTEGER, "OverlayIndex" ),
|
||||
#endif
|
||||
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "StartOverlays", InputStartOverlay ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "StopOverlays", InputStopOverlay ),
|
||||
@ -93,6 +99,9 @@ IMPLEMENT_SERVERCLASS_ST( CEnvScreenOverlay, DT_EnvScreenOverlay )
|
||||
SendPropFloat( SENDINFO( m_flStartTime ), 32, SPROP_NOSCALE ),
|
||||
SendPropInt( SENDINFO( m_iDesiredOverlay ), 5 ),
|
||||
SendPropBool( SENDINFO( m_bIsActive ) ),
|
||||
#ifdef MAPBASE
|
||||
SendPropInt( SENDINFO( m_iOverlayIndex ), 5 ),
|
||||
#endif
|
||||
END_SEND_TABLE()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -103,6 +112,9 @@ CEnvScreenOverlay::CEnvScreenOverlay( void )
|
||||
m_flStartTime = 0;
|
||||
m_iDesiredOverlay = 0;
|
||||
m_bIsActive = false;
|
||||
#ifdef MAPBASE
|
||||
m_iOverlayIndex = -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -5,6 +5,7 @@
|
||||
//=============================================================================
|
||||
|
||||
#include "cbase.h"
|
||||
#include "env_tonemap_controller.h"
|
||||
#include "baseentity.h"
|
||||
#include "entityoutput.h"
|
||||
#include "convar.h"
|
||||
@ -16,50 +17,6 @@
|
||||
|
||||
ConVar mat_hdr_tonemapscale( "mat_hdr_tonemapscale", "1.0", FCVAR_CHEAT, "The HDR tonemap scale. 1 = Use autoexposure, 0 = eyes fully closed, 16 = eyes wide open." );
|
||||
|
||||
// 0 - eyes fully closed / fully black
|
||||
// 1 - nominal
|
||||
// 16 - eyes wide open / fully white
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Entity that controls player's tonemap
|
||||
//-----------------------------------------------------------------------------
|
||||
class CEnvTonemapController : public CPointEntity
|
||||
{
|
||||
DECLARE_CLASS( CEnvTonemapController, CPointEntity );
|
||||
public:
|
||||
DECLARE_DATADESC();
|
||||
DECLARE_SERVERCLASS();
|
||||
|
||||
void Spawn( void );
|
||||
int UpdateTransmitState( void );
|
||||
void UpdateTonemapScaleBlend( void );
|
||||
|
||||
// Inputs
|
||||
void InputSetTonemapScale( inputdata_t &inputdata );
|
||||
void InputBlendTonemapScale( inputdata_t &inputdata );
|
||||
void InputSetTonemapRate( inputdata_t &inputdata );
|
||||
void InputSetAutoExposureMin( inputdata_t &inputdata );
|
||||
void InputSetAutoExposureMax( inputdata_t &inputdata );
|
||||
void InputUseDefaultAutoExposure( inputdata_t &inputdata );
|
||||
void InputSetBloomScale( inputdata_t &inputdata );
|
||||
void InputUseDefaultBloomScale( inputdata_t &inputdata );
|
||||
void InputSetBloomScaleRange( inputdata_t &inputdata );
|
||||
|
||||
private:
|
||||
float m_flBlendTonemapStart; // HDR Tonemap at the start of the blend
|
||||
float m_flBlendTonemapEnd; // Target HDR Tonemap at the end of the blend
|
||||
float m_flBlendEndTime; // Time at which the blend ends
|
||||
float m_flBlendStartTime; // Time at which the blend started
|
||||
|
||||
CNetworkVar( bool, m_bUseCustomAutoExposureMin );
|
||||
CNetworkVar( bool, m_bUseCustomAutoExposureMax );
|
||||
CNetworkVar( bool, m_bUseCustomBloomScale );
|
||||
CNetworkVar( float, m_flCustomAutoExposureMin );
|
||||
CNetworkVar( float, m_flCustomAutoExposureMax );
|
||||
CNetworkVar( float, m_flCustomBloomScale);
|
||||
CNetworkVar( float, m_flCustomBloomScaleMinimum);
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( env_tonemap_controller, CEnvTonemapController );
|
||||
|
||||
BEGIN_DATADESC( CEnvTonemapController )
|
||||
@ -120,27 +77,72 @@ int CEnvTonemapController::UpdateTransmitState()
|
||||
return SetTransmitState( FL_EDICT_ALWAYS );
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CEnvTonemapController::KeyValue( const char *szKeyName, const char *szValue )
|
||||
{
|
||||
if ( FStrEq( szKeyName, "TonemapScale" ) )
|
||||
{
|
||||
float flTonemapScale = atof( szValue );
|
||||
if (flTonemapScale != -1.0f)
|
||||
{
|
||||
mat_hdr_tonemapscale.SetValue( flTonemapScale );
|
||||
}
|
||||
}
|
||||
else if (FStrEq( szKeyName, "TonemapRate" ))
|
||||
{
|
||||
float flTonemapRate = atof( szValue );
|
||||
if (flTonemapRate != -1.0f)
|
||||
{
|
||||
ConVarRef mat_hdr_manual_tonemap_rate( "mat_hdr_manual_tonemap_rate" );
|
||||
if ( mat_hdr_manual_tonemap_rate.IsValid() )
|
||||
{
|
||||
mat_hdr_manual_tonemap_rate.SetValue( flTonemapRate );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (FStrEq( szKeyName, "AutoExposureMin" ))
|
||||
{
|
||||
float flAutoExposureMin = atof( szValue );
|
||||
if (flAutoExposureMin != 1.0f)
|
||||
{
|
||||
m_flCustomAutoExposureMin = flAutoExposureMin;
|
||||
m_bUseCustomAutoExposureMin = true;
|
||||
}
|
||||
}
|
||||
else if (FStrEq( szKeyName, "AutoExposureMax" ))
|
||||
{
|
||||
float flAutoExposureMax = atof( szValue );
|
||||
if (flAutoExposureMax != 1.0f)
|
||||
{
|
||||
m_flCustomAutoExposureMax = flAutoExposureMax;
|
||||
m_bUseCustomAutoExposureMax = true;
|
||||
}
|
||||
}
|
||||
else if (FStrEq( szKeyName, "BloomScale" ))
|
||||
{
|
||||
float flBloomScale = atof( szValue );
|
||||
if (flBloomScale != 1.0f)
|
||||
{
|
||||
m_flCustomBloomScale = flBloomScale;
|
||||
m_flCustomBloomScaleMinimum = flBloomScale;
|
||||
m_bUseCustomBloomScale = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
return BaseClass::KeyValue( szKeyName, szValue );
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Set the tonemap scale to the specified value
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvTonemapController::InputSetTonemapScale( inputdata_t &inputdata )
|
||||
{
|
||||
//Tony; in multiplayer, we check to see if the activator is a player, if they are, we trigger an input on them, and then get out.
|
||||
//if there is no activator, or the activator is not a player; ie: LogicAuto, we set the 'global' values.
|
||||
if ( ( gpGlobals->maxClients > 1 ) )
|
||||
{
|
||||
if ( inputdata.pActivator != NULL && inputdata.pActivator->IsPlayer() )
|
||||
{
|
||||
// DevMsg("activator is a player: InputSetTonemapScale\n");
|
||||
CBasePlayer *pPlayer = ToBasePlayer(inputdata.pActivator);
|
||||
if (pPlayer)
|
||||
{
|
||||
pPlayer->InputSetTonemapScale( inputdata );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float flRemapped = inputdata.value.Float();
|
||||
mat_hdr_tonemapscale.SetValue( flRemapped );
|
||||
}
|
||||
@ -150,10 +152,6 @@ void CEnvTonemapController::InputSetTonemapScale( inputdata_t &inputdata )
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvTonemapController::InputBlendTonemapScale( inputdata_t &inputdata )
|
||||
{
|
||||
//Tony; TODO!!! -- tonemap scale blending does _not_ work properly in multiplayer..
|
||||
if ( ( gpGlobals->maxClients > 1 ) )
|
||||
return;
|
||||
|
||||
char parseString[255];
|
||||
Q_strncpy(parseString, inputdata.value.String(), sizeof(parseString));
|
||||
|
||||
@ -207,22 +205,6 @@ void CEnvTonemapController::InputSetBloomScaleRange( inputdata_t &inputdata )
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvTonemapController::InputSetTonemapRate( inputdata_t &inputdata )
|
||||
{
|
||||
//Tony; in multiplayer, we check to see if the activator is a player, if they are, we trigger an input on them, and then get out.
|
||||
//if there is no activator, or the activator is not a player; ie: LogicAuto, we set the 'global' values.
|
||||
if ( ( gpGlobals->maxClients > 1 ) )
|
||||
{
|
||||
if ( inputdata.pActivator != NULL && inputdata.pActivator->IsPlayer() )
|
||||
{
|
||||
// DevMsg("activator is a player: InputSetTonemapRate\n");
|
||||
CBasePlayer *pPlayer = ToBasePlayer(inputdata.pActivator);
|
||||
if (pPlayer)
|
||||
{
|
||||
pPlayer->InputSetTonemapRate( inputdata );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: There should be a better way to do this.
|
||||
ConVarRef mat_hdr_manual_tonemap_rate( "mat_hdr_manual_tonemap_rate" );
|
||||
if ( mat_hdr_manual_tonemap_rate.IsValid() )
|
||||
@ -254,22 +236,6 @@ void CEnvTonemapController::UpdateTonemapScaleBlend( void )
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvTonemapController::InputSetAutoExposureMin( inputdata_t &inputdata )
|
||||
{
|
||||
//Tony; in multiplayer, we check to see if the activator is a player, if they are, we trigger an input on them, and then get out.
|
||||
//if there is no activator, or the activator is not a player; ie: LogicAuto, we set the 'global' values.
|
||||
if ( ( gpGlobals->maxClients > 1 ) )
|
||||
{
|
||||
if ( inputdata.pActivator != NULL && inputdata.pActivator->IsPlayer() )
|
||||
{
|
||||
// DevMsg("activator is a player: InputSetAutoExposureMin\n");
|
||||
CBasePlayer *pPlayer = ToBasePlayer(inputdata.pActivator);
|
||||
if (pPlayer)
|
||||
{
|
||||
pPlayer->InputSetAutoExposureMin( inputdata );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_flCustomAutoExposureMin = inputdata.value.Float();
|
||||
m_bUseCustomAutoExposureMin = true;
|
||||
}
|
||||
@ -279,22 +245,6 @@ void CEnvTonemapController::InputSetAutoExposureMin( inputdata_t &inputdata )
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvTonemapController::InputSetAutoExposureMax( inputdata_t &inputdata )
|
||||
{
|
||||
//Tony; in multiplayer, we check to see if the activator is a player, if they are, we trigger an input on them, and then get out.
|
||||
//if there is no activator, or the activator is not a player; ie: LogicAuto, we set the 'global' values.
|
||||
if ( ( gpGlobals->maxClients > 1 ) )
|
||||
{
|
||||
if ( inputdata.pActivator != NULL && inputdata.pActivator->IsPlayer() )
|
||||
{
|
||||
// DevMsg("activator is a player: InputSetAutoExposureMax\n");
|
||||
CBasePlayer *pPlayer = ToBasePlayer(inputdata.pActivator);
|
||||
if (pPlayer)
|
||||
{
|
||||
pPlayer->InputSetAutoExposureMax( inputdata );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_flCustomAutoExposureMax = inputdata.value.Float();
|
||||
m_bUseCustomAutoExposureMax = true;
|
||||
}
|
||||
@ -304,22 +254,6 @@ void CEnvTonemapController::InputSetAutoExposureMax( inputdata_t &inputdata )
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvTonemapController::InputUseDefaultAutoExposure( inputdata_t &inputdata )
|
||||
{
|
||||
//Tony; in multiplayer, we check to see if the activator is a player, if they are, we trigger an input on them, and then get out.
|
||||
//if there is no activator, or the activator is not a player; ie: LogicAuto, we set the 'global' values.
|
||||
if ( ( gpGlobals->maxClients > 1 ) )
|
||||
{
|
||||
if ( inputdata.pActivator != NULL && inputdata.pActivator->IsPlayer() )
|
||||
{
|
||||
// DevMsg("activator is a player: InputUseDefaultAutoExposure\n");
|
||||
CBasePlayer *pPlayer = ToBasePlayer(inputdata.pActivator);
|
||||
if (pPlayer)
|
||||
{
|
||||
pPlayer->InputUseDefaultAutoExposure( inputdata );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_bUseCustomAutoExposureMin = false;
|
||||
m_bUseCustomAutoExposureMax = false;
|
||||
}
|
||||
@ -329,22 +263,6 @@ void CEnvTonemapController::InputUseDefaultAutoExposure( inputdata_t &inputdata
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvTonemapController::InputSetBloomScale( inputdata_t &inputdata )
|
||||
{
|
||||
//Tony; in multiplayer, we check to see if the activator is a player, if they are, we trigger an input on them, and then get out.
|
||||
//if there is no activator, or the activator is not a player; ie: LogicAuto, we set the 'global' values.
|
||||
if ( ( gpGlobals->maxClients > 1 ) )
|
||||
{
|
||||
if ( inputdata.pActivator != NULL && inputdata.pActivator->IsPlayer() )
|
||||
{
|
||||
// DevMsg("activator is a player: InputSetBloomScale\n");
|
||||
CBasePlayer *pPlayer = ToBasePlayer(inputdata.pActivator);
|
||||
if (pPlayer)
|
||||
{
|
||||
pPlayer->InputSetBloomScale( inputdata );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_flCustomBloomScale = inputdata.value.Float();
|
||||
m_flCustomBloomScaleMinimum = m_flCustomBloomScale;
|
||||
m_bUseCustomBloomScale = true;
|
||||
@ -355,21 +273,111 @@ void CEnvTonemapController::InputSetBloomScale( inputdata_t &inputdata )
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvTonemapController::InputUseDefaultBloomScale( inputdata_t &inputdata )
|
||||
{
|
||||
//Tony; in multiplayer, we check to see if the activator is a player, if they are, we trigger an input on them, and then get out.
|
||||
//if there is no activator, or the activator is not a player; ie: LogicAuto, we set the 'global' values.
|
||||
if ( ( gpGlobals->maxClients > 1 ) )
|
||||
{
|
||||
if ( inputdata.pActivator != NULL && inputdata.pActivator->IsPlayer() )
|
||||
{
|
||||
// DevMsg("activator is a player: InputUseDefaultBloomScale\n");
|
||||
CBasePlayer *pPlayer = ToBasePlayer(inputdata.pActivator);
|
||||
if (pPlayer)
|
||||
{
|
||||
pPlayer->InputUseDefaultBloomScale( inputdata );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_bUseCustomBloomScale = false;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
LINK_ENTITY_TO_CLASS( trigger_tonemap, CTonemapTrigger );
|
||||
|
||||
BEGIN_DATADESC( CTonemapTrigger )
|
||||
DEFINE_KEYFIELD( m_tonemapControllerName, FIELD_STRING, "TonemapName" ),
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
void CTonemapTrigger::Spawn( void )
|
||||
{
|
||||
AddSpawnFlags( SF_TRIGGER_ALLOW_CLIENTS );
|
||||
|
||||
BaseClass::Spawn();
|
||||
InitTrigger();
|
||||
|
||||
m_hTonemapController = gEntList.FindEntityByName( NULL, m_tonemapControllerName );
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
void CTonemapTrigger::StartTouch( CBaseEntity *other )
|
||||
{
|
||||
if ( !PassesTriggerFilters( other ) )
|
||||
return;
|
||||
|
||||
BaseClass::StartTouch( other );
|
||||
|
||||
CBasePlayer *player = ToBasePlayer( other );
|
||||
if ( !player )
|
||||
return;
|
||||
|
||||
player->OnTonemapTriggerStartTouch( this );
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
void CTonemapTrigger::EndTouch( CBaseEntity *other )
|
||||
{
|
||||
if ( !PassesTriggerFilters( other ) )
|
||||
return;
|
||||
|
||||
BaseClass::EndTouch( other );
|
||||
|
||||
CBasePlayer *player = ToBasePlayer( other );
|
||||
if ( !player )
|
||||
return;
|
||||
|
||||
player->OnTonemapTriggerEndTouch( this );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Clear out the tonemap controller.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTonemapSystem::LevelInitPreEntity( void )
|
||||
{
|
||||
m_hMasterController = NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: On level load find the master fog controller. If no controller is
|
||||
// set as Master, use the first fog controller found.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTonemapSystem::LevelInitPostEntity( void )
|
||||
{
|
||||
// Overall master controller
|
||||
CEnvTonemapController *pTonemapController = NULL;
|
||||
do
|
||||
{
|
||||
pTonemapController = static_cast<CEnvTonemapController*>( gEntList.FindEntityByClassname( pTonemapController, "env_tonemap_controller" ) );
|
||||
if ( pTonemapController )
|
||||
{
|
||||
if ( m_hMasterController == NULL )
|
||||
{
|
||||
m_hMasterController = pTonemapController;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( pTonemapController->IsMaster() )
|
||||
{
|
||||
m_hMasterController = pTonemapController;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while ( pTonemapController );
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
CTonemapSystem s_TonemapSystem( "TonemapSystem" );
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
CTonemapSystem *TheTonemapSystem( void )
|
||||
{
|
||||
return &s_TonemapSystem;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
#endif
|
||||
|
140
sp/src/game/server/env_tonemap_controller.h
Normal file
140
sp/src/game/server/env_tonemap_controller.h
Normal file
@ -0,0 +1,140 @@
|
||||
//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============//
|
||||
//
|
||||
// Note that this header exists in the Alien Swarm SDK, but not in stock Source SDK 2013.
|
||||
// Although technically a new Mapbase file, it only serves to move otherwise identical code,
|
||||
// so most code and repo conventions will pretend it was always there.
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef ENV_TONEMAP_CONTROLLER_H
|
||||
#define ENV_TONEMAP_CONTROLLER_H
|
||||
|
||||
#include "triggers.h"
|
||||
|
||||
// 0 - eyes fully closed / fully black
|
||||
// 1 - nominal
|
||||
// 16 - eyes wide open / fully white
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
// Spawn Flags
|
||||
#define SF_TONEMAP_MASTER 0x0001
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Entity that controls player's tonemap
|
||||
//-----------------------------------------------------------------------------
|
||||
class CEnvTonemapController : public CPointEntity
|
||||
{
|
||||
DECLARE_CLASS( CEnvTonemapController, CPointEntity );
|
||||
public:
|
||||
DECLARE_DATADESC();
|
||||
DECLARE_SERVERCLASS();
|
||||
|
||||
void Spawn( void );
|
||||
int UpdateTransmitState( void );
|
||||
void UpdateTonemapScaleBlend( void );
|
||||
|
||||
#ifdef MAPBASE
|
||||
bool IsMaster( void ) const { return HasSpawnFlags( SF_TONEMAP_MASTER ); } // From Alien Swarm SDK
|
||||
|
||||
bool KeyValue( const char *szKeyName, const char *szValue );
|
||||
#endif
|
||||
|
||||
// Inputs
|
||||
void InputSetTonemapScale( inputdata_t &inputdata );
|
||||
void InputBlendTonemapScale( inputdata_t &inputdata );
|
||||
void InputSetTonemapRate( inputdata_t &inputdata );
|
||||
void InputSetAutoExposureMin( inputdata_t &inputdata );
|
||||
void InputSetAutoExposureMax( inputdata_t &inputdata );
|
||||
void InputUseDefaultAutoExposure( inputdata_t &inputdata );
|
||||
void InputSetBloomScale( inputdata_t &inputdata );
|
||||
void InputUseDefaultBloomScale( inputdata_t &inputdata );
|
||||
void InputSetBloomScaleRange( inputdata_t &inputdata );
|
||||
|
||||
private:
|
||||
float m_flBlendTonemapStart; // HDR Tonemap at the start of the blend
|
||||
float m_flBlendTonemapEnd; // Target HDR Tonemap at the end of the blend
|
||||
float m_flBlendEndTime; // Time at which the blend ends
|
||||
float m_flBlendStartTime; // Time at which the blend started
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
public:
|
||||
#endif
|
||||
CNetworkVar( bool, m_bUseCustomAutoExposureMin );
|
||||
CNetworkVar( bool, m_bUseCustomAutoExposureMax );
|
||||
CNetworkVar( bool, m_bUseCustomBloomScale );
|
||||
CNetworkVar( float, m_flCustomAutoExposureMin );
|
||||
CNetworkVar( float, m_flCustomAutoExposureMax );
|
||||
CNetworkVar( float, m_flCustomBloomScale);
|
||||
CNetworkVar( float, m_flCustomBloomScaleMinimum);
|
||||
};
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
class CTonemapTrigger : public CBaseTrigger
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CTonemapTrigger, CBaseTrigger );
|
||||
DECLARE_DATADESC();
|
||||
|
||||
virtual void Spawn( void );
|
||||
virtual void StartTouch( CBaseEntity *other );
|
||||
virtual void EndTouch( CBaseEntity *other );
|
||||
|
||||
CBaseEntity *GetTonemapController( void ) const;
|
||||
|
||||
private:
|
||||
string_t m_tonemapControllerName;
|
||||
EHANDLE m_hTonemapController;
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
inline CBaseEntity *CTonemapTrigger::GetTonemapController( void ) const
|
||||
{
|
||||
return m_hTonemapController.Get();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
// Tonemap Controller System.
|
||||
class CTonemapSystem : public CAutoGameSystem
|
||||
{
|
||||
public:
|
||||
|
||||
// Creation/Init.
|
||||
CTonemapSystem( char const *name ) : CAutoGameSystem( name )
|
||||
{
|
||||
m_hMasterController = NULL;
|
||||
}
|
||||
|
||||
~CTonemapSystem()
|
||||
{
|
||||
m_hMasterController = NULL;
|
||||
}
|
||||
|
||||
virtual void LevelInitPreEntity();
|
||||
virtual void LevelInitPostEntity();
|
||||
CBaseEntity *GetMasterTonemapController( void ) const;
|
||||
|
||||
private:
|
||||
|
||||
EHANDLE m_hMasterController;
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
inline CBaseEntity *CTonemapSystem::GetMasterTonemapController( void ) const
|
||||
{
|
||||
return m_hMasterController.Get();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
CTonemapSystem *TheTonemapSystem( void );
|
||||
#endif
|
||||
|
||||
#endif //ENV_TONEMAP_CONTROLLER_H
|
153
sp/src/game/server/fogvolume.cpp
Normal file
153
sp/src/game/server/fogvolume.cpp
Normal file
@ -0,0 +1,153 @@
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
// Copyright (c) 2007 Turtle Rock Studios, Inc. - All Rights Reserved
|
||||
|
||||
#include "cbase.h"
|
||||
#include "fogvolume.h"
|
||||
#include "collisionutils.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
|
||||
CUtlVector< CFogVolume * > TheFogVolumes;
|
||||
|
||||
ConVar fog_volume_debug( "fog_volume_debug", "0", 0, "If enabled, prints diagnostic information about the current fog volume" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
LINK_ENTITY_TO_CLASS(fog_volume, CFogVolume);
|
||||
|
||||
BEGIN_DATADESC( CFogVolume )
|
||||
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
|
||||
|
||||
DEFINE_KEYFIELD( m_fogName, FIELD_STRING, "FogName" ),
|
||||
DEFINE_KEYFIELD( m_postProcessName, FIELD_STRING, "PostProcessName" ),
|
||||
DEFINE_KEYFIELD( m_colorCorrectionName, FIELD_STRING, "ColorCorrectionName" ),
|
||||
DEFINE_KEYFIELD( m_bDisabled, FIELD_BOOLEAN, "StartDisabled" ),
|
||||
|
||||
DEFINE_FIELD( m_hFogController, FIELD_EHANDLE ),
|
||||
DEFINE_FIELD( m_hPostProcessController, FIELD_EHANDLE ),
|
||||
DEFINE_FIELD( m_hColorCorrectionController, FIELD_EHANDLE ),
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
CFogVolume *CFogVolume::FindFogVolumeForPosition( const Vector &position )
|
||||
{
|
||||
CFogVolume *fogVolume = NULL;
|
||||
for ( int i=0; i<TheFogVolumes.Count(); ++i )
|
||||
{
|
||||
fogVolume = TheFogVolumes[i];
|
||||
|
||||
Vector vecRelativeCenter;
|
||||
fogVolume->CollisionProp()->WorldToCollisionSpace( position, &vecRelativeCenter );
|
||||
if ( IsBoxIntersectingSphere( fogVolume->CollisionProp()->OBBMins(), fogVolume->CollisionProp()->OBBMaxs(), vecRelativeCenter, 1.0f ) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
fogVolume = NULL;
|
||||
}
|
||||
|
||||
// This doesn't work well if there are multiple players or multiple fog volume queries per frame; might want to relocate this if that's the case
|
||||
if ( fog_volume_debug.GetBool() )
|
||||
{
|
||||
if ( fogVolume )
|
||||
{
|
||||
char fogVolumeName[256];
|
||||
fogVolume->GetKeyValue( "targetname", fogVolumeName, 256 );
|
||||
engine->Con_NPrintf( 0, "Fog Volume ""%s"" found at position (%f %f %f)", fogVolumeName, position.x, position.y, position.z );
|
||||
engine->Con_NPrintf( 1, "Fog: %s, post process: %s, color correct: %s", fogVolume->m_fogName, fogVolume->m_postProcessName, fogVolume->m_colorCorrectionName );
|
||||
}
|
||||
else
|
||||
{
|
||||
engine->Con_NPrintf( 0, "No Fog Volume found at given position (%f %f %f)", position.x, position.y, position.z );
|
||||
}
|
||||
}
|
||||
|
||||
return fogVolume;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
CFogVolume::CFogVolume() :
|
||||
BaseClass(),
|
||||
m_bDisabled( false ),
|
||||
m_bInFogVolumesList( false )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
CFogVolume::~CFogVolume()
|
||||
{
|
||||
RemoveFromGlobalList();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
void CFogVolume::Spawn( void )
|
||||
{
|
||||
BaseClass::Spawn();
|
||||
|
||||
SetSolid( SOLID_BSP );
|
||||
SetSolidFlags( FSOLID_NOT_SOLID );
|
||||
SetModel( STRING( GetModelName() ) );
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
void CFogVolume::AddToGlobalList()
|
||||
{
|
||||
if ( !m_bInFogVolumesList )
|
||||
{
|
||||
TheFogVolumes.AddToTail( this );
|
||||
m_bInFogVolumesList = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
void CFogVolume::RemoveFromGlobalList()
|
||||
{
|
||||
if ( m_bInFogVolumesList )
|
||||
{
|
||||
TheFogVolumes.FindAndRemove( this );
|
||||
m_bInFogVolumesList = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void CFogVolume::InputEnable( inputdata_t &data )
|
||||
{
|
||||
m_bDisabled = false;
|
||||
AddToGlobalList();
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void CFogVolume::InputDisable( inputdata_t &data )
|
||||
{
|
||||
m_bDisabled = true;
|
||||
RemoveFromGlobalList();
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Called when the level loads or is restored
|
||||
//----------------------------------------------------------------------------
|
||||
void CFogVolume::Activate()
|
||||
{
|
||||
BaseClass::Activate();
|
||||
|
||||
m_hFogController = dynamic_cast< CFogController* >( gEntList.FindEntityByName( NULL, m_fogName ) );
|
||||
m_hPostProcessController = dynamic_cast< CPostProcessController* >( gEntList.FindEntityByName( NULL, m_postProcessName ) );
|
||||
m_hColorCorrectionController = dynamic_cast< CColorCorrection* >( gEntList.FindEntityByName( NULL, m_colorCorrectionName ) );
|
||||
|
||||
if ( !m_bDisabled )
|
||||
{
|
||||
AddToGlobalList();
|
||||
}
|
||||
}
|
74
sp/src/game/server/fogvolume.h
Normal file
74
sp/src/game/server/fogvolume.h
Normal file
@ -0,0 +1,74 @@
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
// Copyright (c) 2007 Turtle Rock Studios, Inc. - All Rights Reserved
|
||||
|
||||
#ifndef FOG_VOLUME_H
|
||||
#define FOG_VOLUME_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
class CFogController;
|
||||
class CPostProcessController;
|
||||
class CColorCorrection;
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
// Fog volume entity
|
||||
class CFogVolume : public CServerOnlyEntity
|
||||
{
|
||||
DECLARE_CLASS( CFogVolume, CServerOnlyEntity );
|
||||
DECLARE_DATADESC();
|
||||
|
||||
public:
|
||||
CFogVolume();
|
||||
virtual ~CFogVolume();
|
||||
virtual void Spawn( void );
|
||||
virtual void Activate();
|
||||
|
||||
static CFogVolume *FindFogVolumeForPosition( const Vector &position );
|
||||
|
||||
const char *GetFogControllerName() const
|
||||
{
|
||||
return STRING( m_fogName );
|
||||
}
|
||||
|
||||
CFogController* GetFogController( ) const
|
||||
{
|
||||
return m_hFogController.Get();
|
||||
}
|
||||
|
||||
CPostProcessController* GetPostProcessController( ) const
|
||||
{
|
||||
return m_hPostProcessController.Get();
|
||||
}
|
||||
|
||||
CColorCorrection* GetColorCorrectionController( ) const
|
||||
{
|
||||
return m_hColorCorrectionController.Get();
|
||||
}
|
||||
|
||||
void InputEnable( inputdata_t &data );
|
||||
void InputDisable( inputdata_t &data );
|
||||
|
||||
private:
|
||||
string_t m_fogName;
|
||||
string_t m_postProcessName;
|
||||
string_t m_colorCorrectionName;
|
||||
|
||||
CHandle< CFogController > m_hFogController;
|
||||
CHandle< CPostProcessController > m_hPostProcessController;
|
||||
CHandle< CColorCorrection > m_hColorCorrectionController;
|
||||
|
||||
bool m_bDisabled;
|
||||
bool m_bInFogVolumesList;
|
||||
|
||||
void AddToGlobalList();
|
||||
void RemoveFromGlobalList();
|
||||
};
|
||||
|
||||
extern CUtlVector< CFogVolume * > TheFogVolumes;
|
||||
|
||||
|
||||
#endif // FOG_VOLUME_H
|
@ -221,6 +221,10 @@ bool CBreakable::KeyValue( const char *szKeyName, const char *szValue )
|
||||
if ( object > 0 && object < ARRAYSIZE(pSpawnObjects) )
|
||||
m_iszSpawnObject = MAKE_STRING( pSpawnObjects[object] );
|
||||
#ifdef MAPBASE
|
||||
// "0" is the default value of a "choices" field in Hammer, representing nothing selected
|
||||
// atoi() returning 0 may also indicate a failed conversion, so check szValue directly
|
||||
else if ( FStrEq( szValue, "0" ) )
|
||||
m_iszSpawnObject = NULL_STRING;
|
||||
else
|
||||
m_iszSpawnObject = AllocPooledString(szValue);
|
||||
#endif
|
||||
|
@ -110,6 +110,28 @@ bool CAI_FuncTankBehavior::IsInterruptable( void )
|
||||
|
||||
return BaseClass::IsInterruptable();
|
||||
}
|
||||
|
||||
ConVar ai_tank_allow_expanded_npcs( "ai_tank_allow_expanded_npcs", "1", FCVAR_NONE, "Allows Father Grigori, Barney, and vortigaunts to automatically man func_tanks." );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CAI_FuncTankBehavior::CanManTank( CFuncTank *pTank, bool bForced )
|
||||
{
|
||||
if (!bForced)
|
||||
{
|
||||
// In order to prevent potential problems in existing maps, Father Grigori, Barney, and vortigaunts can be set to not automatically man func_tanks by default.
|
||||
if (ai_tank_allow_expanded_npcs.GetBool() == false)
|
||||
{
|
||||
const char *pszClass = GetOuter()->GetClassname();
|
||||
if ( FStrEq( pszClass, "npc_monk" ) || FStrEq( pszClass, "npc_barney" ) || FStrEq( pszClass, "npc_vortigaunt" ) )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -51,6 +51,8 @@ public:
|
||||
void PrescheduleThink();
|
||||
#ifdef MAPBASE
|
||||
bool IsInterruptable( void );
|
||||
|
||||
bool CanManTank( CFuncTank *pTank, bool bForced );
|
||||
#endif
|
||||
|
||||
Activity NPC_TranslateActivity( Activity activity );
|
||||
|
@ -267,6 +267,10 @@ private:
|
||||
typedef CHandle<CAvoidSphere> AvoidSphereHandle_t;
|
||||
|
||||
float m_flRadius;
|
||||
#ifdef MAPBASE
|
||||
string_t m_iszAvoidFilter;
|
||||
EHANDLE m_hAvoidFilter;
|
||||
#endif
|
||||
|
||||
static CUtlVector< AvoidSphereHandle_t > s_AvoidSpheres;
|
||||
};
|
||||
|
@ -402,7 +402,11 @@ void CFuncTank::InputFindNPCToManTank( inputdata_t &inputdata )
|
||||
{
|
||||
// Verify the npc has the func_tank controller behavior.
|
||||
CAI_FuncTankBehavior *pBehavior;
|
||||
#ifdef MAPBASE
|
||||
if ( pNPC->GetBehavior( &pBehavior ) && pBehavior->CanManTank( this, true ) )
|
||||
#else
|
||||
if ( pNPC->GetBehavior( &pBehavior ) )
|
||||
#endif
|
||||
{
|
||||
m_hController = pNPC;
|
||||
pBehavior->SetFuncTank( this );
|
||||
@ -439,7 +443,7 @@ void CFuncTank::InputTeleportNPCToManTank( inputdata_t &inputdata )
|
||||
{
|
||||
// Verify the npc has the func_tank controller behavior.
|
||||
CAI_FuncTankBehavior *pBehavior;
|
||||
if ( pNPC->GetBehavior( &pBehavior ) )
|
||||
if ( pNPC->GetBehavior( &pBehavior ) && pBehavior->CanManTank( this, true ) )
|
||||
{
|
||||
Vector vecVec;
|
||||
QAngle angAng;
|
||||
@ -512,7 +516,7 @@ void CFuncTank::InputForceNPCToManTank( inputdata_t &inputdata )
|
||||
{
|
||||
// Verify the npc has the func_tank controller behavior.
|
||||
CAI_FuncTankBehavior *pBehavior;
|
||||
if ( pNPC->GetBehavior( &pBehavior ) )
|
||||
if ( pNPC->GetBehavior( &pBehavior ) && pBehavior->CanManTank( this, true ) )
|
||||
{
|
||||
// Set the forced condition
|
||||
pBehavior->SetCondition( CAI_FuncTankBehavior::COND_FUNCTANK_FORCED );
|
||||
@ -627,7 +631,11 @@ void CFuncTank::NPC_FindController( void )
|
||||
continue;
|
||||
|
||||
CAI_FuncTankBehavior *pBehavior;
|
||||
#ifdef MAPBASE
|
||||
if ( pNPC->GetBehavior( &pBehavior ) && pBehavior->CanManTank( this, false ) )
|
||||
#else
|
||||
if ( pNPC->GetBehavior( &pBehavior ) )
|
||||
#endif
|
||||
{
|
||||
// Don't mount the func_tank if your "enemy" is within X feet or it or the npc.
|
||||
CBaseEntity *pEnemy = pNPC->GetEnemy();
|
||||
|
@ -142,7 +142,7 @@ void respawn( CBaseEntity *pEdict, bool fCopyCorpse )
|
||||
{
|
||||
// In SP respawns, only create corpse if drawing externally
|
||||
CBasePlayer *pPlayer = (CBasePlayer*)pEdict;
|
||||
if ( fCopyCorpse && pPlayer->m_bDrawPlayerModelExternally )
|
||||
if ( fCopyCorpse && pPlayer->GetDrawPlayerModelExternally() )
|
||||
{
|
||||
// make a copy of the dead body for appearances sake
|
||||
pPlayer->CreateCorpse();
|
||||
|
@ -259,6 +259,7 @@ public:
|
||||
|
||||
void InputSetHandModel( inputdata_t &inputdata );
|
||||
void InputSetHandModelSkin( inputdata_t &inputdata );
|
||||
void InputSetHandModelBodyGroup( inputdata_t &inputdata );
|
||||
|
||||
void InputSetPlayerModel( inputdata_t &inputdata );
|
||||
void InputSetPlayerDrawExternally( inputdata_t &inputdata );
|
||||
@ -4617,6 +4618,7 @@ BEGIN_DATADESC( CLogicPlayerProxy )
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "GetAmmoOnWeapon", InputGetAmmoOnWeapon ),
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "SetHandModel", InputSetHandModel ),
|
||||
DEFINE_INPUTFUNC( FIELD_INTEGER, "SetHandModelSkin", InputSetHandModelSkin ),
|
||||
DEFINE_INPUTFUNC( FIELD_INTEGER, "SetHandModelBodyGroup", InputSetHandModelBodyGroup ),
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "SetPlayerModel", InputSetPlayerModel ),
|
||||
DEFINE_INPUTFUNC( FIELD_BOOLEAN, "SetPlayerDrawExternally", InputSetPlayerDrawExternally ),
|
||||
DEFINE_INPUT( m_MaxArmor, FIELD_INTEGER, "SetMaxInputArmor" ),
|
||||
@ -4659,6 +4661,8 @@ bool CLogicPlayerProxy::KeyValue( const char *szKeyName, const char *szValue )
|
||||
vm->SetModel(szValue);
|
||||
else if (FStrEq(szKeyName, "Skin")) // HandsVMSkin
|
||||
vm->m_nSkin = atoi(szValue);
|
||||
else if (FStrEq(szKeyName, "Body")) // HandsVMBody
|
||||
vm->m_nBody = atoi(szValue);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -5062,6 +5066,17 @@ void CLogicPlayerProxy::InputSetHandModelSkin( inputdata_t &inputdata )
|
||||
vm->m_nSkin = inputdata.value.Int();
|
||||
}
|
||||
|
||||
void CLogicPlayerProxy::InputSetHandModelBodyGroup( inputdata_t &inputdata )
|
||||
{
|
||||
if (!m_hPlayer)
|
||||
return;
|
||||
|
||||
CBasePlayer *pPlayer = static_cast<CBasePlayer*>( m_hPlayer.Get() );
|
||||
CBaseViewModel *vm = pPlayer->GetViewModel(1);
|
||||
if (vm)
|
||||
vm->m_nBody = inputdata.value.Int();
|
||||
}
|
||||
|
||||
void CLogicPlayerProxy::InputSetPlayerModel( inputdata_t &inputdata )
|
||||
{
|
||||
if (!m_hPlayer)
|
||||
@ -5089,6 +5104,6 @@ void CLogicPlayerProxy::InputSetPlayerDrawExternally( inputdata_t &inputdata )
|
||||
return;
|
||||
|
||||
CBasePlayer *pPlayer = static_cast<CBasePlayer*>(m_hPlayer.Get());
|
||||
pPlayer->m_bDrawPlayerModelExternally = inputdata.value.Bool();
|
||||
pPlayer->SetDrawPlayerModelExternally( inputdata.value.Bool() );
|
||||
}
|
||||
#endif
|
||||
|
@ -156,6 +156,8 @@ ConVar npc_alyx_crouch( "npc_alyx_crouch", "1" );
|
||||
#ifdef MAPBASE
|
||||
ConVar npc_alyx_interact_manhacks( "npc_alyx_interact_manhacks", "1" );
|
||||
ConVar npc_alyx_interact_turrets( "npc_alyx_interact_turrets", "0" );
|
||||
|
||||
ConVar npc_alyx_allow_fly( "npc_alyx_allow_fly", "0", FCVAR_NONE, "Allows Alyx to use FL_FLY outside of scripted sequences, actbusy, or navigation." );
|
||||
#endif
|
||||
|
||||
// global pointer to Alyx for fast lookups
|
||||
@ -319,7 +321,9 @@ CNPC_Alyx *CNPC_Alyx::GetAlyx( void )
|
||||
//=========================================================
|
||||
bool CNPC_Alyx::CreateBehaviors()
|
||||
{
|
||||
#ifndef MAPBASE // Moved to CNPC_PlayerCompanion
|
||||
AddBehavior( &m_FuncTankBehavior );
|
||||
#endif
|
||||
bool result = BaseClass::CreateBehaviors();
|
||||
|
||||
return result;
|
||||
@ -885,7 +889,11 @@ void CNPC_Alyx::GatherConditions()
|
||||
|
||||
// ROBIN: This was here to solve a problem in a playtest. We've since found what we think was the cause.
|
||||
// It's a useful piece of debug to have lying there, so I've left it in.
|
||||
if ( (GetFlags() & FL_FLY) && m_NPCState != NPC_STATE_SCRIPT && !m_ActBusyBehavior.IsActive() && !m_PassengerBehavior.IsEnabled() )
|
||||
if ( (GetFlags() & FL_FLY) && m_NPCState != NPC_STATE_SCRIPT && !m_ActBusyBehavior.IsActive() && !m_PassengerBehavior.IsEnabled()
|
||||
#ifdef MAPBASE
|
||||
&& GetNavType() != NAV_CLIMB && !npc_alyx_allow_fly.GetBool()
|
||||
#endif
|
||||
)
|
||||
{
|
||||
Warning( "Removed FL_FLY from Alyx, who wasn't running a script or actbusy. Time %.2f, map %s.\n", gpGlobals->curtime, STRING(gpGlobals->mapname) );
|
||||
RemoveFlag( FL_FLY );
|
||||
@ -1687,9 +1695,88 @@ Activity CNPC_Alyx::NPC_TranslateActivity( Activity activity )
|
||||
case ACT_DROP_WEAPON: if ( HasShotgun() ) return (Activity)ACT_DROP_WEAPON_SHOTGUN;
|
||||
}
|
||||
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
// Alyx has her own pistol readiness animations which use the default activities
|
||||
switch (activity)
|
||||
{
|
||||
case ACT_IDLE_PISTOL_RELAXED:
|
||||
return ACT_IDLE_RELAXED;
|
||||
case ACT_IDLE_PISTOL_STIMULATED:
|
||||
return ACT_IDLE_STIMULATED;
|
||||
case ACT_WALK_PISTOL_RELAXED:
|
||||
return ACT_WALK;
|
||||
case ACT_WALK_PISTOL_STIMULATED:
|
||||
return ACT_WALK_PISTOL;
|
||||
case ACT_RUN_PISTOL_RELAXED:
|
||||
return ACT_RUN;
|
||||
case ACT_RUN_PISTOL_STIMULATED:
|
||||
return ACT_RUN_PISTOL;
|
||||
}
|
||||
#endif
|
||||
|
||||
return activity;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
Activity CNPC_Alyx::Weapon_TranslateActivity( Activity activity, bool *pRequired )
|
||||
{
|
||||
activity = BaseClass::Weapon_TranslateActivity( activity, pRequired );
|
||||
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
// Alyx has her own pistol readiness animations which use the default activities
|
||||
switch (activity)
|
||||
{
|
||||
case ACT_IDLE_PISTOL_RELAXED:
|
||||
return ACT_IDLE_RELAXED;
|
||||
case ACT_IDLE_PISTOL_STIMULATED:
|
||||
return ACT_IDLE_STIMULATED;
|
||||
case ACT_WALK_PISTOL_RELAXED:
|
||||
return ACT_WALK;
|
||||
case ACT_WALK_PISTOL_STIMULATED:
|
||||
return ACT_WALK_PISTOL;
|
||||
case ACT_RUN_PISTOL_RELAXED:
|
||||
return ACT_RUN;
|
||||
case ACT_RUN_PISTOL_STIMULATED:
|
||||
return ACT_RUN_PISTOL;
|
||||
}
|
||||
#endif
|
||||
|
||||
return activity;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
Activity CNPC_Alyx::Weapon_BackupActivity( Activity activity, bool weaponTranslationWasRequired, CBaseCombatWeapon *pSpecificWeapon )
|
||||
{
|
||||
activity = BaseClass::Weapon_BackupActivity( activity, weaponTranslationWasRequired, pSpecificWeapon );
|
||||
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
// Alyx has her own pistol readiness animations which use the default activities
|
||||
switch (activity)
|
||||
{
|
||||
case ACT_IDLE_PISTOL_RELAXED:
|
||||
return ACT_IDLE_RELAXED;
|
||||
case ACT_IDLE_PISTOL_STIMULATED:
|
||||
return ACT_IDLE_STIMULATED;
|
||||
case ACT_WALK_PISTOL_RELAXED:
|
||||
return ACT_WALK;
|
||||
case ACT_WALK_PISTOL_STIMULATED:
|
||||
return ACT_WALK_PISTOL;
|
||||
case ACT_RUN_PISTOL_RELAXED:
|
||||
return ACT_RUN;
|
||||
case ACT_RUN_PISTOL_STIMULATED:
|
||||
return ACT_RUN_PISTOL;
|
||||
}
|
||||
#endif
|
||||
|
||||
return activity;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool CNPC_Alyx::ShouldDeferToFollowBehavior()
|
||||
{
|
||||
return BaseClass::ShouldDeferToFollowBehavior();
|
||||
|
@ -91,6 +91,10 @@ public:
|
||||
bool CanSeeEntityInDarkness( CBaseEntity *pEntity );
|
||||
bool IsCoverPosition( const Vector &vecThreat, const Vector &vecPosition );
|
||||
Activity NPC_TranslateActivity ( Activity activity );
|
||||
#ifdef MAPBASE
|
||||
Activity Weapon_TranslateActivity( Activity baseAct, bool *pRequired = NULL );
|
||||
Activity Weapon_BackupActivity( Activity activity, bool weaponTranslationWasRequired = false, CBaseCombatWeapon *pSpecificWeapon = NULL );
|
||||
#endif
|
||||
bool ShouldDeferToFollowBehavior();
|
||||
void BuildScheduleTestBits();
|
||||
bool ShouldBehaviorSelectSchedule( CAI_BehaviorBase *pBehavior );
|
||||
@ -231,7 +235,9 @@ private:
|
||||
|
||||
bool m_bShouldHaveEMP;
|
||||
|
||||
#ifndef MAPBASE // Moved to CNPC_PlayerCompanion
|
||||
CAI_FuncTankBehavior m_FuncTankBehavior;
|
||||
#endif
|
||||
|
||||
COutputEvent m_OnFinishInteractWithObject;
|
||||
COutputEvent m_OnPlayerUse;
|
||||
|
@ -42,6 +42,10 @@
|
||||
#include "physics_bone_follower.h"
|
||||
#endif // HL2_EPISODIC
|
||||
|
||||
#ifdef MAPBASE
|
||||
#include "filters.h"
|
||||
#endif
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
@ -5680,6 +5684,9 @@ LINK_ENTITY_TO_CLASS( npc_heli_avoidsphere, CAvoidSphere );
|
||||
BEGIN_DATADESC( CAvoidSphere )
|
||||
|
||||
DEFINE_KEYFIELD( m_flRadius, FIELD_FLOAT, "radius" ),
|
||||
#ifdef MAPBASE
|
||||
DEFINE_KEYFIELD( m_iszAvoidFilter, FIELD_STRING, "AvoidFilter" ),
|
||||
#endif
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
@ -5720,6 +5727,18 @@ void CAvoidSphere::Activate( )
|
||||
{
|
||||
BaseClass::Activate();
|
||||
s_AvoidSpheres.AddToTail( this );
|
||||
|
||||
#ifdef MAPBASE
|
||||
m_hAvoidFilter = gEntList.FindEntityByName( NULL, m_iszAvoidFilter, this );
|
||||
if (m_hAvoidFilter)
|
||||
{
|
||||
if (dynamic_cast<CBaseFilter*>(m_hAvoidFilter.Get()) == NULL)
|
||||
{
|
||||
Warning( "%s: \"%s\" is not a valid filter", GetDebugName(), m_hAvoidFilter->GetDebugName() );
|
||||
m_hAvoidFilter = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void CAvoidSphere::UpdateOnRemove( )
|
||||
@ -5746,6 +5765,12 @@ void CAvoidSphere::ComputeAvoidanceForces( CBaseEntity *pEntity, float flEntityR
|
||||
CAvoidSphere *pSphere = s_AvoidSpheres[i].Get();
|
||||
const Vector &vecAvoidCenter = pSphere->WorldSpaceCenter();
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Continue if not passing the avoid sphere filter
|
||||
if ( pSphere->m_hAvoidFilter && !(static_cast<CBaseFilter*>( pSphere->m_hAvoidFilter.Get())->PassesFilter(pSphere, pEntity )) )
|
||||
continue;
|
||||
#endif
|
||||
|
||||
// NOTE: This test can be thought of sweeping a sphere through space
|
||||
// and seeing if it intersects the avoidance sphere
|
||||
float flTotalRadius = flEntityRadius + pSphere->m_flRadius;
|
||||
|
@ -689,6 +689,12 @@ bool CNPC_Barnacle::CanPickup( CBaseCombatCharacter *pBCC )
|
||||
if( FClassnameIs( pBCC, "npc_turret_floor" ) )
|
||||
return false;
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Don't pickup rollermines
|
||||
if( FClassnameIs( pBCC, "npc_rollermine" ) )
|
||||
return false;
|
||||
#endif
|
||||
|
||||
// Don't pick up a dead player or NPC
|
||||
if( !pBCC->IsAlive() )
|
||||
return false;
|
||||
|
@ -51,8 +51,10 @@ public:
|
||||
|
||||
virtual void Precache()
|
||||
{
|
||||
#ifndef MAPBASE // This is now done in CNPC_PlayerCompanion::Precache()
|
||||
// Prevents a warning
|
||||
SelectModel( );
|
||||
#endif
|
||||
BaseClass::Precache();
|
||||
|
||||
PrecacheScriptSound( "NPC_Barney.FootstepLeft" );
|
||||
|
@ -1278,6 +1278,14 @@ void CNPC_BaseScanner::MoveToTarget( float flInterval, const Vector &vecMoveTarg
|
||||
myZAccel = flDist / flInterval;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
if (m_flSpeedModifier != 1.0f)
|
||||
{
|
||||
myAccel *= m_flSpeedModifier;
|
||||
//myZAccel *= m_flSpeedModifier;
|
||||
}
|
||||
#endif
|
||||
|
||||
MoveInDirection( flInterval, targetDir, myAccel, myZAccel, myDecay );
|
||||
|
||||
// calc relative banking targets
|
||||
|
@ -407,6 +407,27 @@ BEGIN_DATADESC( CNPC_Citizen )
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
ScriptHook_t CNPC_Citizen::g_Hook_SelectModel;
|
||||
|
||||
BEGIN_ENT_SCRIPTDESC( CNPC_Citizen, CAI_BaseActor, "npc_citizen from Half-Life 2" )
|
||||
|
||||
DEFINE_SCRIPTFUNC( IsMedic, "Returns true if this citizen is a medic." )
|
||||
DEFINE_SCRIPTFUNC( IsAmmoResupplier, "Returns true if this citizen is an ammo resupplier." )
|
||||
DEFINE_SCRIPTFUNC( CanHeal, "Returns true if this citizen is a medic or ammo resupplier currently able to heal/give ammo." )
|
||||
|
||||
DEFINE_SCRIPTFUNC( GetCitizenType, "Gets the citizen's type. 1 = Downtrodden, 2 = Refugee, 3 = Rebel, 4 = Unique" )
|
||||
DEFINE_SCRIPTFUNC( SetCitizenType, "Sets the citizen's type. 1 = Downtrodden, 2 = Refugee, 3 = Rebel, 4 = Unique" )
|
||||
|
||||
BEGIN_SCRIPTHOOK( CNPC_Citizen::g_Hook_SelectModel, "SelectModel", FIELD_CSTRING, "Called when a citizen is selecting a random model. 'model_path' is the directory of the selected model and 'model_head' is the name. The 'gender' parameter uses the 'GENDER_' constants and is based only on the citizen's random head spawnflags. If a full model path string is returned, it will be used as the model instead." )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "model_path", FIELD_CSTRING )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "model_head", FIELD_CSTRING )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "gender", FIELD_INTEGER )
|
||||
END_SCRIPTHOOK()
|
||||
|
||||
END_SCRIPTDESC();
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@ -418,10 +439,11 @@ CSimpleSimTimer CNPC_Citizen::gm_PlayerSquadEvaluateTimer;
|
||||
bool CNPC_Citizen::CreateBehaviors()
|
||||
{
|
||||
BaseClass::CreateBehaviors();
|
||||
AddBehavior( &m_FuncTankBehavior );
|
||||
#ifdef MAPBASE
|
||||
AddBehavior( &m_RappelBehavior );
|
||||
AddBehavior( &m_PolicingBehavior );
|
||||
#else // Moved to CNPC_PlayerCompanion
|
||||
AddBehavior( &m_FuncTankBehavior );
|
||||
#endif
|
||||
|
||||
return true;
|
||||
@ -431,7 +453,12 @@ bool CNPC_Citizen::CreateBehaviors()
|
||||
//-----------------------------------------------------------------------------
|
||||
void CNPC_Citizen::Precache()
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
// CNPC_PlayerCompanion::Precache() is responsible for calling this now
|
||||
BaseClass::Precache();
|
||||
#else
|
||||
SelectModel();
|
||||
#endif
|
||||
SelectExpressionType();
|
||||
|
||||
if ( !npc_citizen_dont_precache_all.GetBool() )
|
||||
@ -468,7 +495,9 @@ void CNPC_Citizen::Precache()
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef MAPBASE // See above
|
||||
BaseClass::Precache();
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -769,6 +798,54 @@ void CNPC_Citizen::SelectModel()
|
||||
pszModelName = g_ppszRandomHeads[m_iHead];
|
||||
SetModelName(NULL_STRING);
|
||||
}
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if (m_ScriptScope.IsInitialized() && g_Hook_SelectModel.CanRunInScope( m_ScriptScope ))
|
||||
{
|
||||
gender_t scriptGender;
|
||||
switch (gender)
|
||||
{
|
||||
case 'm':
|
||||
scriptGender = GENDER_MALE;
|
||||
break;
|
||||
case 'f':
|
||||
scriptGender = GENDER_FEMALE;
|
||||
break;
|
||||
default:
|
||||
scriptGender = GENDER_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
const char *pszModelPath = CFmtStr( "models/Humans/%s/", (const char *)(CFmtStr( g_ppszModelLocs[m_Type], (IsMedic()) ? "m" : "" )) );
|
||||
|
||||
// model_path, model_head, gender
|
||||
ScriptVariant_t args[] = { pszModelPath, pszModelName, (int)scriptGender };
|
||||
ScriptVariant_t returnValue = NULL;
|
||||
g_Hook_SelectModel.Call( m_ScriptScope, &returnValue, args );
|
||||
|
||||
if (returnValue.m_type == FIELD_CSTRING && returnValue.m_pszString[0] != '\0')
|
||||
{
|
||||
// Refresh the head if it's different
|
||||
const char *pszNewHead = strrchr( returnValue.m_pszString, '/' );
|
||||
if ( pszNewHead && Q_stricmp(pszNewHead+1, pszModelName) != 0 )
|
||||
{
|
||||
pszNewHead++;
|
||||
for ( int i = 0; i < ARRAYSIZE(g_ppszRandomHeads); i++ )
|
||||
{
|
||||
if ( Q_stricmp( g_ppszRandomHeads[i], pszModelName ) == 0 )
|
||||
{
|
||||
m_iHead = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Just set the model right here
|
||||
SetModelName( AllocPooledString( returnValue.m_pszString ) );
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Assert( pszModelName || GetModelName() != NULL_STRING );
|
||||
@ -1466,7 +1543,11 @@ int CNPC_Citizen::SelectScheduleRetrieveItem()
|
||||
// Been kicked out of the player squad since the time I located the health.
|
||||
ClearCondition( COND_HEALTH_ITEM_AVAILABLE );
|
||||
}
|
||||
#ifdef MAPBASE
|
||||
else if ( m_FollowBehavior.GetFollowTarget() )
|
||||
#else
|
||||
else
|
||||
#endif
|
||||
{
|
||||
CBaseEntity *pBase = FindHealthItem(m_FollowBehavior.GetFollowTarget()->GetAbsOrigin(), Vector( 120, 120, 120 ) );
|
||||
CItem *pItem = dynamic_cast<CItem *>(pBase);
|
||||
@ -1932,12 +2013,7 @@ void CNPC_Citizen::RunTask( const Task_t *pTask )
|
||||
return;
|
||||
}
|
||||
// Add imprecision to avoid obvious robotic perfection stationary targets
|
||||
#ifdef MAPBASE
|
||||
// More imprecision with low-accuracy citizens
|
||||
float imprecision = 18*sin(gpGlobals->curtime) + cosh(GetCurrentWeaponProficiency() - 4);
|
||||
#else
|
||||
float imprecision = 18*sin(gpGlobals->curtime);
|
||||
#endif
|
||||
vecLaserPos.x += imprecision;
|
||||
vecLaserPos.y += imprecision;
|
||||
vecLaserPos.z += imprecision;
|
||||
@ -2014,6 +2090,13 @@ Activity CNPC_Citizen::NPC_TranslateActivity( Activity activity )
|
||||
return ACT_RUN_AIM_AR2_STIMULATED;
|
||||
if (activity == ACT_WALK_AIM_AR2)
|
||||
return ACT_WALK_AIM_AR2_STIMULATED;
|
||||
|
||||
#ifdef EXPANDED_HL2_WEAPON_ACTIVITIES
|
||||
if (activity == ACT_RUN_AIM_PISTOL)
|
||||
return ACT_RUN_AIM_PISTOL_STIMULATED;
|
||||
if (activity == ACT_WALK_AIM_PISTOL)
|
||||
return ACT_WALK_AIM_PISTOL_STIMULATED;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -2278,25 +2361,21 @@ bool CNPC_Citizen::IsManhackMeleeCombatant()
|
||||
//-----------------------------------------------------------------------------
|
||||
Vector CNPC_Citizen::GetActualShootPosition( const Vector &shootOrigin )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
// The code below is probably broken. If not, it definitely isn't very effective.
|
||||
return BaseClass::GetActualShootPosition( shootOrigin );
|
||||
#else
|
||||
Vector vecTarget = BaseClass::GetActualShootPosition( shootOrigin );
|
||||
|
||||
#ifdef MAPBASE
|
||||
// If we're firing an RPG at a gunship, aim off to it's side, because we'll auger towards it.
|
||||
// The gunship RPG code does not appear to be funcitonal, so only set the laser position.
|
||||
if ( GetActiveWeapon() && EntIsClass(GetActiveWeapon(), gm_isz_class_RPG) && GetEnemy() )
|
||||
{
|
||||
CWeaponRPG *pRPG = static_cast<CWeaponRPG*>(GetActiveWeapon());
|
||||
if ( EntIsClass( GetEnemy(), gm_isz_class_Gunship ) )
|
||||
pRPG->SetNPCLaserPosition( vecTarget );
|
||||
}
|
||||
#else
|
||||
CWeaponRPG *pRPG = dynamic_cast<CWeaponRPG*>(GetActiveWeapon());
|
||||
// If we're firing an RPG at a gunship, aim off to it's side, because we'll auger towards it.
|
||||
if ( pRPG && GetEnemy() )
|
||||
{
|
||||
if ( FClassnameIs( GetEnemy(), "npc_combinegunship" ) )
|
||||
#endif
|
||||
{
|
||||
Vector vecRight;
|
||||
GetVectors( NULL, &vecRight, NULL );
|
||||
@ -2331,11 +2410,10 @@ Vector CNPC_Citizen::GetActualShootPosition( const Vector &shootOrigin )
|
||||
{
|
||||
pRPG->SetNPCLaserPosition( vecTarget );
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
return vecTarget;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -277,6 +277,11 @@ public:
|
||||
|
||||
virtual void OnChangeRunningBehavior( CAI_BehaviorBase *pOldBehavior, CAI_BehaviorBase *pNewBehavior );
|
||||
|
||||
#ifdef MAPBASE
|
||||
int GetCitizenType() { return (int)m_Type; }
|
||||
void SetCitizenType( int iType ) { m_Type = (CitizenType_t)iType; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
//-----------------------------------------------------
|
||||
// Conditions, Schedules, Tasks
|
||||
@ -365,7 +370,6 @@ private:
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------
|
||||
CAI_FuncTankBehavior m_FuncTankBehavior;
|
||||
#ifdef MAPBASE
|
||||
CAI_RappelBehavior m_RappelBehavior;
|
||||
CAI_PolicingBehavior m_PolicingBehavior;
|
||||
@ -373,6 +377,8 @@ private:
|
||||
// Rappel
|
||||
virtual bool IsWaitingToRappel( void ) { return m_RappelBehavior.IsWaitingToRappel(); }
|
||||
void BeginRappel() { m_RappelBehavior.BeginRappel(); }
|
||||
#else // Moved to CNPC_PlayerCompanion
|
||||
CAI_FuncTankBehavior m_FuncTankBehavior;
|
||||
#endif
|
||||
|
||||
CHandle<CAI_FollowGoal> m_hSavedFollowGoalEnt;
|
||||
@ -382,6 +388,10 @@ private:
|
||||
|
||||
//-----------------------------------------------------
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
static ScriptHook_t g_Hook_SelectModel;
|
||||
DECLARE_ENT_SCRIPTDESC();
|
||||
#endif
|
||||
DECLARE_DATADESC();
|
||||
#ifdef _XBOX
|
||||
protected:
|
||||
|
@ -43,6 +43,7 @@ int g_fCombineQuestion; // true if an idle grunt asked a question. Cleared wh
|
||||
#ifdef MAPBASE
|
||||
ConVar npc_combine_idle_walk_easy( "npc_combine_idle_walk_easy", "1", FCVAR_NONE, "Mapbase: Allows Combine soldiers to use ACT_WALK_EASY as a walking animation when idle." );
|
||||
ConVar npc_combine_unarmed_anims( "npc_combine_unarmed_anims", "1", FCVAR_NONE, "Mapbase: Allows Combine soldiers to use unarmed idle/walk animations when they have no weapon." );
|
||||
ConVar npc_combine_protected_run( "npc_combine_protected_run", "0", FCVAR_NONE, "Mapbase: Allows Combine soldiers to use \"protected run\" animations." );
|
||||
ConVar npc_combine_altfire_not_allies_only( "npc_combine_altfire_not_allies_only", "1", FCVAR_NONE, "Mapbase: Elites are normally only allowed to fire their alt-fire attack at the player and the player's allies; This allows elites to alt-fire at other enemies too." );
|
||||
|
||||
ConVar npc_combine_new_cover_behavior( "npc_combine_new_cover_behavior", "1", FCVAR_NONE, "Mapbase: Toggles small patches for parts of npc_combine AI related to soldiers failing to take cover. These patches are minimal and only change cases where npc_combine would otherwise look at an enemy without shooting or run up to the player to melee attack when they don't have to. Consult the Mapbase wiki for more information." );
|
||||
@ -127,8 +128,9 @@ Activity ACT_COMBINE_AR2_ALTFIRE;
|
||||
Activity ACT_WALK_EASY;
|
||||
Activity ACT_WALK_MARCH;
|
||||
#ifdef MAPBASE
|
||||
Activity ACT_IDLE_UNARMED;
|
||||
Activity ACT_WALK_UNARMED;
|
||||
Activity ACT_TURRET_CARRY_IDLE;
|
||||
Activity ACT_TURRET_CARRY_WALK;
|
||||
Activity ACT_TURRET_CARRY_RUN;
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------
|
||||
@ -230,7 +232,9 @@ DEFINE_INPUTFUNC( FIELD_STRING, "SetPoliceGoal", InputSetPoliceGoal ),
|
||||
DEFINE_AIGRENADE_DATADESC()
|
||||
#endif
|
||||
|
||||
#ifndef MAPBASE
|
||||
DEFINE_FIELD( m_iLastAnimEventHandled, FIELD_INTEGER ),
|
||||
#endif
|
||||
DEFINE_FIELD( m_fIsElite, FIELD_BOOLEAN ),
|
||||
#ifndef MAPBASE
|
||||
DEFINE_FIELD( m_vecAltFireTarget, FIELD_VECTOR ),
|
||||
@ -542,7 +546,12 @@ void CNPC_Combine::GatherConditions()
|
||||
|
||||
if( GetState() == NPC_STATE_COMBAT )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
// Don't override the standoff
|
||||
if( IsCurSchedule( SCHED_COMBINE_WAIT_IN_COVER, false ) && !m_StandoffBehavior.IsActive() )
|
||||
#else
|
||||
if( IsCurSchedule( SCHED_COMBINE_WAIT_IN_COVER, false ) )
|
||||
#endif
|
||||
{
|
||||
// Soldiers that are standing around doing nothing poll for attack slots so
|
||||
// that they can respond quickly when one comes available. If they can
|
||||
@ -746,7 +755,8 @@ Class_T CNPC_Combine::Classify ( void )
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CNPC_Combine::IsAltFireCapable( void )
|
||||
{
|
||||
return IsElite() || m_bAlternateCapable;
|
||||
// The base class tells us if we're carrying an alt-fire-able weapon.
|
||||
return (IsElite() || m_bAlternateCapable) && BaseClass::IsAltFireCapable();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1538,11 +1548,6 @@ void CNPC_Combine::BuildScheduleTestBits( void )
|
||||
//-----------------------------------------------------------------------------
|
||||
Activity CNPC_Combine::Weapon_TranslateActivity( Activity eNewActivity, bool *pRequired )
|
||||
{
|
||||
// We have differing low animations and ACT_CROUCHIDLE is not friendly to weapon translation.
|
||||
// ACT_CROUCHIDLE is pretty much deprecated at this point anyway.
|
||||
if (eNewActivity == ACT_CROUCHIDLE)
|
||||
eNewActivity = ACT_RANGE_AIM_LOW;
|
||||
|
||||
return BaseClass::Weapon_TranslateActivity(eNewActivity, pRequired);
|
||||
}
|
||||
|
||||
@ -1551,12 +1556,6 @@ Activity CNPC_Combine::Weapon_TranslateActivity( Activity eNewActivity, bool *pR
|
||||
//-----------------------------------------------------------------------------
|
||||
Activity CNPC_Combine::NPC_BackupActivity( Activity eNewActivity )
|
||||
{
|
||||
// Otherwise we move around, T-posing.
|
||||
if (eNewActivity == ACT_WALK)
|
||||
return ACT_WALK_UNARMED;
|
||||
else if (eNewActivity == ACT_RUN)
|
||||
return ACT_RUN_RIFLE;
|
||||
|
||||
// Some models might not contain ACT_COMBINE_BUGBAIT, which the soldier model uses instead of ACT_IDLE_ON_FIRE.
|
||||
// Contrariwise, soldiers may be called to use ACT_IDLE_ON_FIRE in other parts of the AI and need to translate to ACT_COMBINE_BUGBAIT.
|
||||
if (eNewActivity == ACT_COMBINE_BUGBAIT)
|
||||
@ -1628,16 +1627,32 @@ Activity CNPC_Combine::NPC_TranslateActivity( Activity eNewActivity )
|
||||
}
|
||||
}
|
||||
#ifdef MAPBASE
|
||||
else if (!GetActiveWeapon() && npc_combine_unarmed_anims.GetBool() && HaveSequenceForActivity(ACT_IDLE_UNARMED))
|
||||
else if (!GetActiveWeapon() && !npc_combine_unarmed_anims.GetBool())
|
||||
{
|
||||
if (eNewActivity == ACT_IDLE || eNewActivity == ACT_IDLE_ANGRY)
|
||||
eNewActivity = ACT_IDLE_UNARMED;
|
||||
eNewActivity = ACT_IDLE_SMG1;
|
||||
else if (eNewActivity == ACT_WALK)
|
||||
eNewActivity = ACT_WALK_UNARMED;
|
||||
eNewActivity = ACT_WALK_RIFLE;
|
||||
else if (eNewActivity == ACT_RUN)
|
||||
eNewActivity = ACT_RUN_RIFLE;
|
||||
}
|
||||
else if (eNewActivity == ACT_WALK && m_NPCState == NPC_STATE_IDLE && npc_combine_idle_walk_easy.GetBool() && HaveSequenceForActivity(ACT_WALK_EASY))
|
||||
else if (m_NPCState == NPC_STATE_IDLE && eNewActivity == ACT_WALK)
|
||||
{
|
||||
eNewActivity = ACT_WALK_EASY;
|
||||
if (npc_combine_idle_walk_easy.GetBool())
|
||||
{
|
||||
// ACT_WALK_EASY has been replaced with ACT_WALK_RELAXED for weapon translation purposes
|
||||
eNewActivity = ACT_WALK_RELAXED;
|
||||
}
|
||||
else if (GetActiveWeapon())
|
||||
{
|
||||
eNewActivity = ACT_WALK_RIFLE;
|
||||
}
|
||||
}
|
||||
|
||||
if ( eNewActivity == ACT_RUN && ( IsCurSchedule( SCHED_TAKE_COVER_FROM_BEST_SOUND ) || IsCurSchedule( SCHED_FLEE_FROM_BEST_SOUND ) ) )
|
||||
{
|
||||
if ( random->RandomInt( 0, 1 ) && npc_combine_protected_run.GetBool() && HaveSequenceForActivity( ACT_RUN_PROTECTED ) )
|
||||
eNewActivity = ACT_RUN_PROTECTED;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -2022,7 +2037,7 @@ int CNPC_Combine::SelectSchedule( void )
|
||||
Vector vecTarget = m_hForcedGrenadeTarget->WorldSpaceCenter();
|
||||
|
||||
#ifdef MAPBASE
|
||||
// I switched this to IsAltFireCapable() before, but m_bAlternateCapable makes it necessary to use IsElite() again.
|
||||
// This was switched to IsAltFireCapable() before, but m_bAlternateCapable makes it necessary to use IsElite() again.
|
||||
#endif
|
||||
if ( IsElite() )
|
||||
{
|
||||
@ -2604,7 +2619,6 @@ int CNPC_Combine::TranslateSchedule( int scheduleType )
|
||||
#ifdef MAPBASE
|
||||
// SCHED_COMBINE_WAIT_IN_COVER uses INCOVER, but only gets out of it when the soldier moves.
|
||||
// That seems to mess up shooting, so this Forget() attempts to fix that.
|
||||
// I don't know if there's a better workaround.
|
||||
Forget( bits_MEMORY_INCOVER );
|
||||
#endif
|
||||
|
||||
@ -3687,7 +3701,9 @@ void CNPC_Combine::SetActivity( Activity NewActivity )
|
||||
{
|
||||
BaseClass::SetActivity( NewActivity );
|
||||
|
||||
#ifndef MAPBASE // CAI_GrenadeUser
|
||||
m_iLastAnimEventHandled = -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -3787,6 +3803,13 @@ WeaponProficiency_t CNPC_Combine::CalcWeaponProficiency( CBaseCombatWeapon *pWea
|
||||
{
|
||||
return WEAPON_PROFICIENCY_GOOD;
|
||||
}
|
||||
#ifdef MAPBASE
|
||||
else if ( pWeapon->ClassMatches( gm_isz_class_Pistol ) )
|
||||
{
|
||||
// Mods which need a lower soldier pistol accuracy can either change this value or use proficiency override in Hammer.
|
||||
return WEAPON_PROFICIENCY_VERY_GOOD;
|
||||
}
|
||||
#endif
|
||||
|
||||
return BaseClass::CalcWeaponProficiency( pWeapon );
|
||||
}
|
||||
@ -3902,7 +3925,12 @@ bool CNPC_Combine::IsRunningApproachEnemySchedule()
|
||||
|
||||
bool CNPC_Combine::ShouldPickADeathPose( void )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
// Check base class as well
|
||||
return !IsCrouching() && BaseClass::ShouldPickADeathPose();
|
||||
#else
|
||||
return !IsCrouching();
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -3936,8 +3964,9 @@ DECLARE_ACTIVITY( ACT_COMBINE_AR2_ALTFIRE )
|
||||
DECLARE_ACTIVITY( ACT_WALK_EASY )
|
||||
DECLARE_ACTIVITY( ACT_WALK_MARCH )
|
||||
#ifdef MAPBASE
|
||||
DECLARE_ACTIVITY( ACT_IDLE_UNARMED )
|
||||
DECLARE_ACTIVITY( ACT_WALK_UNARMED )
|
||||
DECLARE_ACTIVITY( ACT_TURRET_CARRY_IDLE )
|
||||
DECLARE_ACTIVITY( ACT_TURRET_CARRY_WALK )
|
||||
DECLARE_ACTIVITY( ACT_TURRET_CARRY_RUN )
|
||||
#endif
|
||||
|
||||
DECLARE_ANIMEVENT( COMBINE_AE_BEGIN_ALTFIRE )
|
||||
|
@ -59,7 +59,7 @@ public:
|
||||
// Create components
|
||||
virtual bool CreateComponents();
|
||||
|
||||
#ifndef MAPBASE
|
||||
#ifndef MAPBASE // CAI_GrenadeUser
|
||||
bool CanThrowGrenade( const Vector &vecTarget );
|
||||
bool CheckCanThrowGrenade( const Vector &vecTarget );
|
||||
#endif
|
||||
@ -118,7 +118,7 @@ public:
|
||||
const char* GetGrenadeAttachment() { return "lefthand"; }
|
||||
#else
|
||||
#endif
|
||||
#ifndef MAPBASE
|
||||
#ifndef MAPBASE // CAI_GrenadeUser
|
||||
void DelayAltFireAttack( float flDelay );
|
||||
void DelaySquadAltFireAttack( float flDelay );
|
||||
#endif
|
||||
@ -131,7 +131,7 @@ public:
|
||||
Vector EyeOffset( Activity nActivity );
|
||||
Vector EyePosition( void );
|
||||
Vector BodyTarget( const Vector &posSrc, bool bNoisy = true );
|
||||
#ifndef MAPBASE
|
||||
#ifndef MAPBASE // CAI_GrenadeUser
|
||||
Vector GetAltFireTarget();
|
||||
#endif
|
||||
|
||||
@ -320,7 +320,7 @@ private:
|
||||
|
||||
private:
|
||||
int m_nKickDamage;
|
||||
#ifndef MAPBASE
|
||||
#ifndef MAPBASE // CAI_GrenadeUser
|
||||
Vector m_vecTossVelocity;
|
||||
EHANDLE m_hForcedGrenadeTarget;
|
||||
#else
|
||||
@ -334,12 +334,12 @@ private:
|
||||
// Time Variables
|
||||
float m_flNextPainSoundTime;
|
||||
float m_flNextAlertSoundTime;
|
||||
#ifndef MAPBASE
|
||||
#ifndef MAPBASE // CAI_GrenadeUser
|
||||
float m_flNextGrenadeCheck;
|
||||
#endif
|
||||
float m_flNextLostSoundTime;
|
||||
float m_flAlertPatrolTime; // When to stop doing alert patrol
|
||||
#ifndef MAPBASE
|
||||
#ifndef MAPBASE // CAI_GrenadeUser
|
||||
float m_flNextAltFireTime; // Elites only. Next time to begin considering alt-fire attack.
|
||||
#endif
|
||||
|
||||
@ -351,7 +351,7 @@ private:
|
||||
CAI_Sentence< CNPC_Combine > m_Sentences;
|
||||
#endif
|
||||
|
||||
#ifndef MAPBASE
|
||||
#ifndef MAPBASE // CAI_GrenadeUser
|
||||
int m_iNumGrenades;
|
||||
#endif
|
||||
CAI_AssaultBehavior m_AssaultBehavior;
|
||||
@ -365,9 +365,11 @@ private:
|
||||
#endif
|
||||
|
||||
public:
|
||||
#ifndef MAPBASE // CAI_GrenadeUser
|
||||
int m_iLastAnimEventHandled;
|
||||
#endif
|
||||
bool m_fIsElite;
|
||||
#ifndef MAPBASE
|
||||
#ifndef MAPBASE // CAI_GrenadeUser
|
||||
Vector m_vecAltFireTarget;
|
||||
#endif
|
||||
|
||||
|
@ -1296,7 +1296,11 @@ void CFastZombie::StartTask( const Task_t *pTask )
|
||||
CBaseEntity *pEnemy = GetEnemy();
|
||||
Vector vecJumpDir;
|
||||
|
||||
if ( GetActivity() == ACT_CLIMB_UP || GetActivity() == ACT_CLIMB_DOWN )
|
||||
if ( GetActivity() == ACT_CLIMB_UP || GetActivity() == ACT_CLIMB_DOWN
|
||||
#ifdef EXPANDED_NAVIGATION_ACTIVITIES
|
||||
|| GetActivity() == ACT_CLIMB_ALL
|
||||
#endif
|
||||
)
|
||||
{
|
||||
// Jump off the pipe backwards!
|
||||
Vector forward;
|
||||
@ -1449,7 +1453,11 @@ int CFastZombie::TranslateSchedule( int scheduleType )
|
||||
break;
|
||||
|
||||
case SCHED_FASTZOMBIE_UNSTICK_JUMP:
|
||||
if ( GetActivity() == ACT_CLIMB_UP || GetActivity() == ACT_CLIMB_DOWN || GetActivity() == ACT_CLIMB_DISMOUNT )
|
||||
if ( GetActivity() == ACT_CLIMB_UP || GetActivity() == ACT_CLIMB_DOWN || GetActivity() == ACT_CLIMB_DISMOUNT
|
||||
#ifdef EXPANDED_NAVIGATION_ACTIVITIES
|
||||
|| (GetActivity() >= ACT_CLIMB_ALL && GetActivity() <= ACT_CLIMB_DISMOUNT_BOTTOM)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
return SCHED_FASTZOMBIE_CLIMBING_UNSTICK_JUMP;
|
||||
}
|
||||
@ -1477,8 +1485,10 @@ int CFastZombie::TranslateSchedule( int scheduleType )
|
||||
//---------------------------------------------------------
|
||||
Activity CFastZombie::NPC_TranslateActivity( Activity baseAct )
|
||||
{
|
||||
#ifndef MAPBASE // Now covered by CAI_BaseNPC::NPC_BackupActivity
|
||||
if ( baseAct == ACT_CLIMB_DOWN )
|
||||
return ACT_CLIMB_UP;
|
||||
#endif
|
||||
|
||||
return BaseClass::NPC_TranslateActivity( baseAct );
|
||||
}
|
||||
|
@ -64,8 +64,10 @@ public:
|
||||
|
||||
virtual void Precache()
|
||||
{
|
||||
#ifndef MAPBASE // This is now done in CNPC_PlayerCompanion::Precache()
|
||||
// Prevents a warning
|
||||
SelectModel( );
|
||||
SelectModel();
|
||||
#endif
|
||||
BaseClass::Precache();
|
||||
|
||||
PrecacheScriptSound( "NPC_Fisherman.FootstepLeft" );
|
||||
|
@ -261,6 +261,7 @@ BEGIN_DATADESC( CNPC_MetroPolice )
|
||||
#ifdef MAPBASE
|
||||
DEFINE_AIGRENADE_DATADESC()
|
||||
DEFINE_INPUT( m_iGrenadeCapabilities, FIELD_INTEGER, "SetGrenadeCapabilities" ),
|
||||
DEFINE_INPUT( m_iGrenadeDropCapabilities, FIELD_INTEGER, "SetGrenadeDropCapabilities" ),
|
||||
#endif
|
||||
|
||||
END_DATADESC()
|
||||
@ -517,6 +518,11 @@ CNPC_MetroPolice::CNPC_MetroPolice()
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
m_iGrenadeCapabilities = GRENCAP_GRENADE;
|
||||
|
||||
if (ai_grenade_always_drop.GetBool())
|
||||
{
|
||||
m_iGrenadeDropCapabilities = (eGrenadeDropCapabilities)(GRENDROPCAP_GRENADE | GRENDROPCAP_ALTFIRE | GRENDROPCAP_INTERRUPTED);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -882,7 +888,7 @@ void CNPC_MetroPolice::SpeakStandoffSentence( int nSentenceType )
|
||||
break;
|
||||
|
||||
case STANDOFF_SENTENCE_FORCED_TAKE_COVER:
|
||||
SpeakIfAllowed( TLK_COP_SO_END );
|
||||
SpeakIfAllowed( TLK_COP_SO_FORCE_COVER );
|
||||
break;
|
||||
|
||||
case STANDOFF_SENTENCE_STAND_CHECK_TARGET:
|
||||
@ -1008,7 +1014,12 @@ void CNPC_MetroPolice::SpeakSentence( int nSentenceType )
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Fixed issues with standoff sentences not playing when they should
|
||||
if ( m_StandoffBehavior.IsActive() )
|
||||
#else
|
||||
if ( GetRunningBehavior() == &m_StandoffBehavior )
|
||||
#endif
|
||||
{
|
||||
SpeakStandoffSentence( nSentenceType );
|
||||
return;
|
||||
@ -1526,7 +1537,12 @@ void CNPC_MetroPolice::OnUpdateShotRegulator( )
|
||||
BaseClass::OnUpdateShotRegulator();
|
||||
|
||||
// FIXME: This code (except the burst interval) could be used for all weapon types
|
||||
#ifdef MAPBASE
|
||||
// Only if we actually have the pistol out
|
||||
if ( EntIsClass( GetActiveWeapon(), gm_isz_class_Pistol ) )
|
||||
#else
|
||||
if( Weapon_OwnsThisType( "weapon_pistol" ) )
|
||||
#endif
|
||||
{
|
||||
if ( m_nBurstMode == BURST_NOT_ACTIVE )
|
||||
{
|
||||
@ -3676,6 +3692,11 @@ void CNPC_MetroPolice::Event_Killed( const CTakeDamageInfo &info )
|
||||
DropItem( "item_healthvial", WorldSpaceCenter()+RandomVector(-4,4), RandomAngle(0,360) );
|
||||
pHL2GameRules->NPC_DroppedHealth();
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Drop grenades if we should
|
||||
DropGrenadeItemsOnDeath( info, pPlayer );
|
||||
#endif
|
||||
}
|
||||
|
||||
BaseClass::Event_Killed( info );
|
||||
@ -3883,6 +3904,15 @@ int CNPC_MetroPolice::SelectScheduleNoDirectEnemy()
|
||||
return SCHED_METROPOLICE_SMASH_PROP;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
// If you see your enemy and you're still arming yourself, wait and don't just charge in
|
||||
// (if your weapon is holstered, you're probably about to arm yourself)
|
||||
if ( HasCondition( COND_SEE_ENEMY ) && GetWeapon(0) && (IsWeaponHolstered() || FindGestureLayer( TranslateActivity( ACT_ARM ) ) != -1) )
|
||||
{
|
||||
return SCHED_COMBAT_FACE;
|
||||
}
|
||||
#endif
|
||||
|
||||
return SCHED_METROPOLICE_CHASE_ENEMY;
|
||||
}
|
||||
|
||||
@ -4506,34 +4536,7 @@ int CNPC_MetroPolice::SelectBehaviorOverrideSchedule()
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CNPC_MetroPolice::IsCrouchedActivity( Activity activity )
|
||||
{
|
||||
Activity realActivity = TranslateActivity(activity);
|
||||
|
||||
switch ( realActivity )
|
||||
{
|
||||
case ACT_RELOAD_LOW:
|
||||
case ACT_COVER_LOW:
|
||||
case ACT_COVER_PISTOL_LOW:
|
||||
case ACT_COVER_SMG1_LOW:
|
||||
case ACT_RELOAD_SMG1_LOW:
|
||||
//case ACT_RELOAD_AR2_LOW:
|
||||
case ACT_RELOAD_PISTOL_LOW:
|
||||
case ACT_RELOAD_SHOTGUN_LOW:
|
||||
|
||||
// These animations aren't actually "low" on metrocops
|
||||
//case ACT_RANGE_AIM_LOW:
|
||||
//case ACT_RANGE_AIM_AR2_LOW:
|
||||
//case ACT_RANGE_AIM_SMG1_LOW:
|
||||
//case ACT_RANGE_AIM_PISTOL_LOW:
|
||||
|
||||
//case ACT_RANGE_ATTACK1_LOW:
|
||||
//case ACT_RANGE_ATTACK_AR2_LOW:
|
||||
//case ACT_RANGE_ATTACK_SMG1_LOW:
|
||||
//case ACT_RANGE_ATTACK_PISTOL_LOW:
|
||||
//case ACT_RANGE_ATTACK2_LOW:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return BaseClass::IsCrouchedActivity( activity );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -4929,7 +4932,12 @@ int CNPC_MetroPolice::SelectSchedule( void )
|
||||
// This will cause the cops to run backwards + shoot at the same time
|
||||
if ( !bHighHealth && !HasBaton() )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
// Don't do this with the 357 or any weapons which don't use clips
|
||||
if ( GetActiveWeapon() && GetActiveWeapon()->UsesClipsForAmmo1() && GetActiveWeapon()->m_iClassname != gm_isz_class_357 && (GetActiveWeapon()->m_iClip1 <= 5) )
|
||||
#else
|
||||
if ( GetActiveWeapon() && (GetActiveWeapon()->m_iClip1 <= 5) )
|
||||
#endif
|
||||
{
|
||||
#ifdef METROPOLICE_USES_RESPONSE_SYSTEM
|
||||
SpeakIfAllowed( TLK_COP_LOWAMMO );
|
||||
|
@ -67,8 +67,12 @@ public:
|
||||
|
||||
const char* GetGrenadeAttachment() { return "LHand"; }
|
||||
|
||||
virtual bool IsAltFireCapable() { return (m_iGrenadeCapabilities & GRENCAP_ALTFIRE) != 0; }
|
||||
virtual bool IsAltFireCapable() { return (m_iGrenadeCapabilities & GRENCAP_ALTFIRE) != 0 && BaseClass::IsAltFireCapable(); }
|
||||
virtual bool IsGrenadeCapable() { return (m_iGrenadeCapabilities & GRENCAP_GRENADE) != 0; }
|
||||
|
||||
virtual bool ShouldDropGrenades() { return (m_iGrenadeDropCapabilities & GRENDROPCAP_GRENADE) != 0 && BaseClass::ShouldDropGrenades(); }
|
||||
virtual bool ShouldDropInterruptedGrenades() { return (m_iGrenadeDropCapabilities & GRENDROPCAP_INTERRUPTED) != 0 && BaseClass::ShouldDropInterruptedGrenades(); }
|
||||
virtual bool ShouldDropAltFire() { return (m_iGrenadeDropCapabilities & GRENDROPCAP_ALTFIRE) != 0 && BaseClass::ShouldDropAltFire(); }
|
||||
#endif
|
||||
|
||||
Vector EyeDirection3D( void ) { return CAI_BaseHumanoid::EyeDirection3D(); } // cops don't have eyes
|
||||
@ -520,6 +524,7 @@ private:
|
||||
|
||||
// Determines whether this NPC is allowed to use grenades or alt-fire stuff.
|
||||
eGrenadeCapabilities m_iGrenadeCapabilities;
|
||||
eGrenadeDropCapabilities m_iGrenadeDropCapabilities;
|
||||
#endif
|
||||
|
||||
AIHANDLE m_hManhack;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user